mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-03 17:58:55 +02:00
Bug 1968779 - Wait for builtin-newtab.js to signal that it has finished onStartup before allowing ActivityStream to be instantiated. r=pdahiya
Differential Revision: https://phabricator.services.mozilla.com/D251397
This commit is contained in:
parent
4a3b6f3796
commit
0dd415b292
3 changed files with 70 additions and 62 deletions
|
|
@ -464,10 +464,16 @@ class BaseAboutNewTabRedirector {
|
||||||
export class AboutNewTabRedirectorParent extends BaseAboutNewTabRedirector {
|
export class AboutNewTabRedirectorParent extends BaseAboutNewTabRedirector {
|
||||||
#addonInitialized = false;
|
#addonInitialized = false;
|
||||||
#suspendedChannels = [];
|
#suspendedChannels = [];
|
||||||
|
#addonInitializedPromise = null;
|
||||||
|
#addonInitializedResolver = null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
let { promise, resolve } = Promise.withResolvers();
|
||||||
|
this.#addonInitializedPromise = promise;
|
||||||
|
this.#addonInitializedResolver = resolve;
|
||||||
|
|
||||||
ChromeUtils.registerWindowActor("AboutNewTab", {
|
ChromeUtils.registerWindowActor("AboutNewTab", {
|
||||||
parent: {
|
parent: {
|
||||||
esModuleURI: "resource:///actors/AboutNewTabParent.sys.mjs",
|
esModuleURI: "resource:///actors/AboutNewTabParent.sys.mjs",
|
||||||
|
|
@ -499,18 +505,30 @@ export class AboutNewTabRedirectorParent extends BaseAboutNewTabRedirector {
|
||||||
* Waits for the AddonManager to be fully initialized, and for the built-in
|
* Waits for the AddonManager to be fully initialized, and for the built-in
|
||||||
* addon to be ready. Once that's done, it tterates any suspended channels and
|
* addon to be ready. Once that's done, it tterates any suspended channels and
|
||||||
* resumes them, now that the built-in addon has been set up.
|
* resumes them, now that the built-in addon has been set up.
|
||||||
*
|
|
||||||
* @returns {Promise<undefined>}
|
|
||||||
* Resolves when the built-in addon has initialized and all suspended
|
|
||||||
* channels are resumed.
|
|
||||||
*/
|
*/
|
||||||
builtInAddonInitialized() {
|
notifyBuiltInAddonInitialized() {
|
||||||
this.#addonInitialized = true;
|
this.#addonInitialized = true;
|
||||||
|
|
||||||
for (let suspendedChannel of this.#suspendedChannels) {
|
for (let suspendedChannel of this.#suspendedChannels) {
|
||||||
suspendedChannel.resume();
|
suspendedChannel.resume();
|
||||||
}
|
}
|
||||||
this.#suspendedChannels = [];
|
this.#suspendedChannels = [];
|
||||||
|
this.#addonInitializedResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Promise that reoslves when the newtab built-in addon has notified
|
||||||
|
* that it has finished initializing. If this is somehow checked when
|
||||||
|
* BROWSER_NEWTAB_AS_ADDON is not true, then this always resolves.
|
||||||
|
*
|
||||||
|
* @type {Promise<undefined>}
|
||||||
|
*/
|
||||||
|
get promiseBuiltInAddonInitialized() {
|
||||||
|
if (!AppConstants.BROWSER_NEWTAB_AS_ADDON) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.#addonInitializedPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
newChannel(uri, loadInfo) {
|
newChannel(uri, loadInfo) {
|
||||||
|
|
|
||||||
|
|
@ -48,45 +48,51 @@ this.builtin_newtab = class extends ExtensionAPI {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { rootURI } = this.extension;
|
try {
|
||||||
|
const { rootURI } = this.extension;
|
||||||
|
|
||||||
resProto.setSubstitutionWithFlags(
|
resProto.setSubstitutionWithFlags(
|
||||||
ResourceSubstitution,
|
ResourceSubstitution,
|
||||||
rootURI,
|
rootURI,
|
||||||
Ci.nsISubstitutingProtocolHandler.ALLOW_CONTENT_ACCESS
|
Ci.nsISubstitutingProtocolHandler.ALLOW_CONTENT_ACCESS
|
||||||
);
|
|
||||||
|
|
||||||
let aomStartup = Cc[
|
|
||||||
"@mozilla.org/addons/addon-manager-startup;1"
|
|
||||||
].getService(Ci.amIAddonManagerStartup);
|
|
||||||
const manifestURI = Services.io.newURI(
|
|
||||||
"manifest.json",
|
|
||||||
null,
|
|
||||||
this.extension.rootURI
|
|
||||||
);
|
|
||||||
this.#chromeHandle = aomStartup.registerChrome(manifestURI, [
|
|
||||||
["content", "newtab", "data/content", "contentaccessible=yes"],
|
|
||||||
]);
|
|
||||||
|
|
||||||
let redirector = Cc[
|
|
||||||
"@mozilla.org/network/protocol/about;1?what=newtab"
|
|
||||||
].getService(Ci.nsIAboutModule).wrappedJSObject;
|
|
||||||
|
|
||||||
if (this.extension.rootURI.spec.endsWith("newtab@mozilla.org.xpi!/")) {
|
|
||||||
// We must be a train-hopped XPI running in this app. This means we
|
|
||||||
// may have Fluent files or Glean pings/metrics to register dynamically.
|
|
||||||
const newtabFileSource = new L10nFileSource(
|
|
||||||
"newtab",
|
|
||||||
"app",
|
|
||||||
SUPPORTED_LOCALES,
|
|
||||||
`resource://newtab/locales/{locale}/`
|
|
||||||
);
|
);
|
||||||
L10nRegistry.getInstance().registerSources([newtabFileSource]);
|
|
||||||
|
|
||||||
// Dynamically register any Glean pings/metrics here.
|
let aomStartup = Cc[
|
||||||
this.registerMetricsFromJson();
|
"@mozilla.org/addons/addon-manager-startup;1"
|
||||||
|
].getService(Ci.amIAddonManagerStartup);
|
||||||
|
const manifestURI = Services.io.newURI(
|
||||||
|
"manifest.json",
|
||||||
|
null,
|
||||||
|
this.extension.rootURI
|
||||||
|
);
|
||||||
|
this.#chromeHandle = aomStartup.registerChrome(manifestURI, [
|
||||||
|
["content", "newtab", "data/content", "contentaccessible=yes"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
let redirector = Cc[
|
||||||
|
"@mozilla.org/network/protocol/about;1?what=newtab"
|
||||||
|
].getService(Ci.nsIAboutModule).wrappedJSObject;
|
||||||
|
|
||||||
|
if (this.extension.rootURI.spec.endsWith("newtab@mozilla.org.xpi!/")) {
|
||||||
|
// We must be a train-hopped XPI running in this app. This means we
|
||||||
|
// may have Fluent files or Glean pings/metrics to register dynamically.
|
||||||
|
const newtabFileSource = new L10nFileSource(
|
||||||
|
"newtab",
|
||||||
|
"app",
|
||||||
|
SUPPORTED_LOCALES,
|
||||||
|
`resource://newtab/locales/{locale}/`
|
||||||
|
);
|
||||||
|
L10nRegistry.getInstance().registerSources([newtabFileSource]);
|
||||||
|
|
||||||
|
// Dynamically register any Glean pings/metrics here.
|
||||||
|
this.registerMetricsFromJson();
|
||||||
|
}
|
||||||
|
redirector.notifyBuiltInAddonInitialized();
|
||||||
|
Glean.newtab.addonReadySuccess.set(true);
|
||||||
|
} catch(e) {
|
||||||
|
Glean.newtab.addonReadySuccess.set(false);
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
redirector.builtInAddonInitialized();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onShutdown() {
|
onShutdown() {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ const lazy = {};
|
||||||
ChromeUtils.defineESModuleGetters(lazy, {
|
ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
ActivityStream: "resource://newtab/lib/ActivityStream.sys.mjs",
|
ActivityStream: "resource://newtab/lib/ActivityStream.sys.mjs",
|
||||||
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
|
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
|
||||||
AddonManagerPrivate: "resource://gre/modules/AddonManager.sys.mjs",
|
|
||||||
ObjectUtils: "resource://gre/modules/ObjectUtils.sys.mjs",
|
ObjectUtils: "resource://gre/modules/ObjectUtils.sys.mjs",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -160,28 +159,13 @@ export const AboutNewTab = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AppConstants.BROWSER_NEWTAB_AS_ADDON) {
|
if (AppConstants.BROWSER_NEWTAB_AS_ADDON) {
|
||||||
let addonPolicy = WebExtensionPolicy.getByID(BUILTIN_ADDON_ID);
|
// Wait until the built-in addon has reported that it has finished
|
||||||
if (!addonPolicy) {
|
// initializing.
|
||||||
// If this is the first time that the build flag was set to true, we
|
let redirector = Cc[
|
||||||
// might not yet have refreshed the addon database cache yet, in which
|
"@mozilla.org/network/protocol/about;1?what=newtab"
|
||||||
// case the addonPolicy will be null. In that case, we'll wait for the
|
].getService(Ci.nsIAboutModule).wrappedJSObject;
|
||||||
// database to be ready before proceeding.
|
|
||||||
//
|
|
||||||
// We don't always just wait for the databaseReady Promise to resolve
|
|
||||||
// in order to avoid regressing newtab render times by needlessly
|
|
||||||
// going back to the event loop.
|
|
||||||
await lazy.AddonManagerPrivate.databaseReady;
|
|
||||||
addonPolicy = WebExtensionPolicy.getByID(BUILTIN_ADDON_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!addonPolicy) {
|
await redirector.promiseBuiltInAddonInitialized;
|
||||||
// Something's gone very wrong here, and we should collect telemetry
|
|
||||||
// about it.
|
|
||||||
Glean.newtab.addonReadySuccess.set(false);
|
|
||||||
} else {
|
|
||||||
await addonPolicy.readyPromise;
|
|
||||||
Glean.newtab.addonReadySuccess.set(true);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// We may have had the built-in addon installed in the past. Since the
|
// We may have had the built-in addon installed in the past. Since the
|
||||||
// flag is false, let's go ahead and remove it. We don't need to await on
|
// flag is false, let's go ahead and remove it. We don't need to await on
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue