From ca581ef48237aa93ce58d4fc889bc4cfcb8899dd Mon Sep 17 00:00:00 2001 From: Ian Bicking Date: Wed, 15 Mar 2017 15:20:37 -0500 Subject: [PATCH] Fix #2332, fix #2333: toggle webextension on pref change Other changes: * Fix #2370, unset deviceId pref set by old addon. * Update Promise rejection / Error handling to match behavior documented in the addons-related Gecko code. --- addon/bootstrap.js | 94 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/addon/bootstrap.js b/addon/bootstrap.js index 5edd63e4a0..a148eb4d6a 100644 --- a/addon/bootstrap.js +++ b/addon/bootstrap.js @@ -1,34 +1,79 @@ -/* globals Components, AddonManager */ -/* eslint-disable no-unused-vars */ +/* globals AddonManager, Components, Services */ const OLD_ADDON_PREF_NAME = "extensions.jid1-NeEaf3sAHdKHPA@jetpack.deviceIdInfo"; const OLD_ADDON_ID = "jid1-NeEaf3sAHdKHPA@jetpack"; +const ADDON_ID = "pageshot@mozilla.org"; +const TELEMETRY_PREF = "toolkit.telemetry.enabled"; +const PREF_BRANCH = "extensions.pageshot."; +const USER_DISABLE_PREF = "disabled"; +const SYSTEM_DISABLE_PREF = "system-disabled"; -const prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefBranch); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); +const { interfaces: Ci, utils: Cu } = Components; +Cu.import("resource://gre/modules/AddonManager.jsm"); +Cu.import("resource://gre/modules/Console.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +const { EmbeddedExtensionManager } = Cu.import("resource://gre/modules/LegacyExtensionsUtils.jsm"); -function startup(data, reason) { - data.webExtension.startup().then((api) => { - const {browser} = api; - browser.runtime.onMessage.addListener(handleMessage); +const prefs = Services.prefs; + +function getBoolPref(pref) { + return prefs.getPrefType(pref) && prefs.getBoolPref(pref); +} + +function isDisabled() { + return getBoolPref(PREF_BRANCH + USER_DISABLE_PREF) || + getBoolPref(PREF_BRANCH + SYSTEM_DISABLE_PREF); +} + +function startup(data, reason) { // eslint-disable-line no-unused-vars + handleStartup(); +} + +function handleStartup() { + AddonManager.getAddonByID(ADDON_ID).then((addon) => { + if (addon === null) { + console.error('Unable to start WebExtension: wrapper addon not found'); + return; + } + const webExtension = EmbeddedExtensionManager.getEmbeddedExtensionFor({ + id: ADDON_ID, + resourceURI: addon.getResourceURI().QueryInterface(Ci.nsIFileURL) + }); + + if (!isDisabled() && !webExtension.started) { + webExtension.startup().then((api) => { + api.browser.runtime.onMessage.addListener(handleMessage); + }).catch((err) => { + // The startup() promise will be rejected if the webExtension was + // already started (a harmless error), or if initializing the + // WebExtension failed and threw (an important error). + console.error(err); + if (err.message !== "This embedded extension has already been started") { + // TODO: send to sentry? + } + }); + } else if (isDisabled()) { + webExtension.shutdown().then(() => { + EmbeddedExtensionManager.untrackEmbeddedExtension(webExtension); + }); + } }); } -function shutdown(data, reason) {} -function install(data, reason) {} -function uninstall(data, reason) {} +function shutdown(data, reason) {} // eslint-disable-line no-unused-vars +function install(data, reason) {} // eslint-disable-line no-unused-vars +function uninstall(data, reason) {} // eslint-disable-line no-unused-vars function handleMessage(msg, sender, sendReply) { if (msg && msg.funcName === "getTelemetryPref") { - let enableTelemetry = prefs.getPrefType('toolkit.telemetry.enabled') && prefs.getBoolPref("toolkit.telemetry.enabled"); + let enableTelemetry = getBoolPref(TELEMETRY_PREF); sendReply({type: "success", value: enableTelemetry}); } else if (msg && msg.funcName === "getOldDeviceInfo") { let oldDeviceInfo = prefs.prefHasUserValue(OLD_ADDON_PREF_NAME) && prefs.getCharPref(OLD_ADDON_PREF_NAME); sendReply({type: "success", value: oldDeviceInfo || null}); } else if (msg && msg.funcName === "removeOldAddon") { AddonManager.getAddonByID(OLD_ADDON_ID, (addon) => { - // FIXME: remove OLD_ADDON_PREF_NAME, see #2370 + prefs.clearUserPref(OLD_ADDON_PREF_NAME); if (addon) { addon.uninstall(); } @@ -36,3 +81,24 @@ function handleMessage(msg, sender, sendReply) { }); } } + +const pageshotPrefObserver = { + register: function() { + this.branch = prefs.getBranch(PREF_BRANCH); + this.branch.addObserver("", this, false); + }, + + unregister: function() { + this.branch.removeObserver("", this); + }, + + observe: function(aSubject, aTopic, aData) { + // aSubject is the nsIPrefBranch we're observing (after appropriate QI) + // aData is the name of the pref that's been changed (relative to aSubject) + if (aData == USER_DISABLE_PREF || aData == SYSTEM_DISABLE_PREF) { + handleStartup(); + } + } +}; + +pageshotPrefObserver.register();