Bug 1404584 wip use update and uninstall events to clear old chrome_settings_overrides
This is a work in progress, it depends on the patches from
bug 1409245.
MozReview-Commit-ID: ArdO2LMaR9G
--- a/browser/components/extensions/ext-browser.json
+++ b/browser/components/extensions/ext-browser.json
@@ -22,16 +22,17 @@
"scopes": ["addon_parent"],
"paths": [
["browsingData"]
]
},
"chrome_settings_overrides": {
"url": "chrome://browser/content/ext-chrome-settings-overrides.js",
"scopes": [],
+ "events": ["update", "uninstall"],
"schema": "chrome://browser/content/schemas/chrome_settings_overrides.json",
"manifest": ["chrome_settings_overrides"]
},
"commands": {
"url": "chrome://browser/content/ext-commands.js",
"schema": "chrome://browser/content/schemas/commands.json",
"scopes": ["addon_parent"],
"manifest": ["commands"],
--- a/browser/components/extensions/ext-chrome-settings-overrides.js
+++ b/browser/components/extensions/ext-chrome-settings-overrides.js
@@ -29,76 +29,93 @@ const searchInitialized = () => {
Services.obs.removeObserver(observer, SEARCH_SERVICE_TOPIC);
resolve();
}, SEARCH_SERVICE_TOPIC);
});
};
this.chrome_settings_overrides = class extends ExtensionAPI {
- processDefaultSearchSetting(action) {
- let {extension} = this;
+ static processDefaultSearchSetting(action, id) {
let item = ExtensionSettingsStore.getSetting(DEFAULT_SEARCH_STORE_TYPE, DEFAULT_SEARCH_SETTING_NAME);
if (!item) {
return;
}
if (Services.search.currentEngine.name != item.value &&
Services.search.currentEngine.name != item.initialValue) {
// The current engine is not the same as the value that the ExtensionSettingsStore has.
// This means that the user changed the engine, so we shouldn't control it anymore.
// Do nothing and remove our entry from the ExtensionSettingsStore.
- ExtensionSettingsStore.removeSetting(extension.id, DEFAULT_SEARCH_STORE_TYPE, DEFAULT_SEARCH_SETTING_NAME);
+ ExtensionSettingsStore.removeSetting(id, DEFAULT_SEARCH_STORE_TYPE, DEFAULT_SEARCH_SETTING_NAME);
return;
}
- item = ExtensionSettingsStore[action](extension.id, DEFAULT_SEARCH_STORE_TYPE, DEFAULT_SEARCH_SETTING_NAME);
+ item = ExtensionSettingsStore[action](id, DEFAULT_SEARCH_STORE_TYPE, DEFAULT_SEARCH_SETTING_NAME);
if (item) {
try {
let engine = Services.search.getEngineByName(item.value || item.initialValue);
if (engine) {
Services.search.currentEngine = engine;
}
} catch (e) {
Components.utils.reportError(e);
}
}
}
+ static onUninstall(id) {
+ this.processDefaultSearchSetting("removeSetting", id);
+
+ // XXX move this somewhere shared
+ // We shouldn't need to wait for search initialized here
+ // because the search service should be ready to go.
+ let engines = Services.search.getEnginesByExtensionID(extension.id);
+ for (let engine of engines) {
+ try {
+ Services.search.removeEngine(engine);
+ } catch (e) {
+ Components.utils.reportError(e);
+ }
+ }
+ }
+
+ static onUpdate(id, manifest) {
+ let haveHomepage = manifest && manifest.chrome_settings_overrides &&
+ manifest.chrome_settings_overrides.homepage;
+ if (!haveHomepage) {
+ ExtensionPreferencesManager.removeSetting(id, "homepage_override");
+ }
+
+ // XXX something with search settings too
+ }
+
async onManifestEntry(entryName) {
let {extension} = this;
let {manifest} = extension;
await ExtensionSettingsStore.initialize();
if (manifest.chrome_settings_overrides.homepage) {
ExtensionPreferencesManager.setSetting(extension.id, "homepage_override",
manifest.chrome_settings_overrides.homepage);
}
if (manifest.chrome_settings_overrides.search_provider) {
await searchInitialized();
extension.callOnClose({
close: () => {
- if (extension.shutdownReason == "ADDON_DISABLE" ||
- extension.shutdownReason == "ADDON_UNINSTALL") {
- switch (extension.shutdownReason) {
- case "ADDON_DISABLE":
- this.processDefaultSearchSetting("disable");
- break;
+ if (extension.shutdownReason == "ADDON_DISABLE") {
+ chrome_settings_overrides.processDefaultSearchSetting("disable", extension.id);
+ }
- case "ADDON_UNINSTALL":
- this.processDefaultSearchSetting("removeSetting");
- break;
- }
- // We shouldn't need to wait for search initialized here
- // because the search service should be ready to go.
- let engines = Services.search.getEnginesByExtensionID(extension.id);
- for (let engine of engines) {
- try {
- Services.search.removeEngine(engine);
- } catch (e) {
- Components.utils.reportError(e);
- }
+ // We shouldn't need to wait for search initialized here
+ // because the search service should be ready to go.
+ let engines = Services.search.getEnginesByExtensionID(extension.id);
+ for (let engine of engines) {
+ try {
+ Services.search.removeEngine(engine);
+ } catch (e) {
+ Components.utils.reportError(e);
}
}
},
});
let searchProvider = manifest.chrome_settings_overrides.search_provider;
let engineName = searchProvider.name.trim();
if (searchProvider.is_default) {
@@ -140,31 +157,31 @@ this.chrome_settings_overrides = class e
}
// Needs to be called every time to handle reenabling, but
// only sets default for install or enable.
await this.setDefault(engineName);
} else if (ExtensionSettingsStore.hasSetting(
extension.id, DEFAULT_SEARCH_STORE_TYPE, DEFAULT_SEARCH_SETTING_NAME)) {
// is_default has been removed, but we still have a setting. Remove it.
// This won't cover the case where the entire search_provider is removed.
- this.processDefaultSearchSetting("removeSetting");
+ chrome_settings_overrides.processDefaultSearchSetting("removeSetting");
}
}
}
async setDefault(engineName) {
let {extension} = this;
if (extension.startupReason === "ADDON_INSTALL") {
let item = await ExtensionSettingsStore.addSetting(
extension.id, DEFAULT_SEARCH_STORE_TYPE, DEFAULT_SEARCH_SETTING_NAME, engineName, () => {
return Services.search.currentEngine.name;
});
Services.search.currentEngine = Services.search.getEngineByName(item.value);
} else if (extension.startupReason === "ADDON_ENABLE") {
- this.processDefaultSearchSetting("enable");
+ chrome_settings_overrides.processDefaultSearchSetting("enable");
}
}
addSearchEngine(searchProvider) {
let {extension} = this;
let isCurrent = false;
let index = -1;
if (extension.startupReason === "ADDON_UPGRADE") {
--- a/toolkit/components/extensions/ExtensionParent.jsm
+++ b/toolkit/components/extensions/ExtensionParent.jsm
@@ -72,28 +72,53 @@ let StartupCache;
const global = this;
// This object loads the ext-*.js scripts that define the extension API.
let apiManager = new class extends SchemaAPIManager {
constructor() {
super("main");
this.initialized = null;
- this.on("startup", (event, extension) => { // eslint-disable-line mozilla/balanced-listeners
+ // eslint-disable mozilla/balanced-listeners
+ this.on("startup", (e, extension) => { // eslint-disable-line mozilla/balanced-listeners
let promises = [];
for (let apiName of this.eventModules.get("startup")) {
promises.push(this.asyncGetAPI(apiName, extension).then(api => {
if (api) {
- api.onStartup(extension.startupReason);
+ api.onStartup();
}
}));
}
return Promise.all(promises);
});
+
+ this.on("update", (e, {id}) => {
+ let modules = this.eventModules.get("update");
+ if (modules.size == 0) {
+ return;
+ }
+
+ // XXX load manifest
+ let manifest = null;
+
+ return Promise.all(Array.from(modules).map(async apiName => {
+ let module = await this.asyncLoadModule(apiName);
+ module.onUpdate(id, manifest);
+ }));
+ });
+
+ this.on("uninstall", (e, {id}) => {
+ let modules = this.eventModules.get("uninstall");
+ return Promise.all(Array.from(modules).map(async apiName => {
+ let module = await this.asyncLoadModule(apiName);
+ module.onUninstall(id);
+ }));
+ });
+ // eslint-enable mozilla/balanced-listeners
}
getModuleJSONURLs() {
return Array.from(XPCOMUtils.enumerateCategoryEntries(CATEGORY_EXTENSION_MODULES),
([name, url]) => url);
}
// Loads all the ext-*.js scripts currently registered.
--- a/toolkit/components/extensions/ExtensionPreferencesManager.jsm
+++ b/toolkit/components/extensions/ExtensionPreferencesManager.jsm
@@ -31,46 +31,30 @@ XPCOMUtils.defineLazyModuleGetter(this,
"resource://gre/modules/ExtensionSettingsStore.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
XPCOMUtils.defineLazyGetter(this, "defaultPreferences", function() {
return new Preferences({defaultBranch: true});
});
-const ADDON_REPLACE_REASONS = new Set([
- "ADDON_DOWNGRADE",
- "ADDON_UPGRADE",
-]);
+/* eslint-disable mozilla/balanced-listeners */
+Management.on("uninstall", (type, {id}) => {
+ ExtensionPreferencesManager.removeAll(id);
+});
-/* eslint-disable mozilla/balanced-listeners */
Management.on("shutdown", (type, extension) => {
- switch (extension.shutdownReason) {
- case "ADDON_DISABLE":
- case "ADDON_DOWNGRADE":
- case "ADDON_UPGRADE":
- if (ADDON_REPLACE_REASONS.has(extension.shutdownReason)) {
- Services.obs.notifyObservers(null, "web-extension-preferences-replacing");
- }
- this.ExtensionPreferencesManager.disableAll(extension.id);
- break;
-
- case "ADDON_UNINSTALL":
- this.ExtensionPreferencesManager.removeAll(extension.id);
- break;
+ if (extension.shutdownReason == "ADDON_DISABLE") {
+ this.ExtensionPreferencesManager.disableAll(extension.id);
}
});
Management.on("startup", async (type, extension) => {
- if (["ADDON_ENABLE", "ADDON_UPGRADE", "ADDON_DOWNGRADE"].includes(extension.startupReason)) {
- const enablePromise = this.ExtensionPreferencesManager.enableAll(extension.id);
- if (ADDON_REPLACE_REASONS.has(extension.startupReason)) {
- await enablePromise;
- Services.obs.notifyObservers(null, "web-extension-preferences-replaced");
- }
+ if (extension.startupReason == "ADDON_ENABLE") {
+ this.ExtensionPreferencesManager.enableAll(extension.id);
}
});
/* eslint-enable mozilla/balanced-listeners */
const STORE_TYPE = "prefs";
// Definitions of settings, each of which correspond to a different API.
let settingsMap = new Map();