Bug 1363419 - Unregister DevTools on Add-on disabling. r=jdescottes draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Tue, 09 May 2017 18:28:57 +0200
changeset 576399 df561479e3dc057ae610013212b3cc695c4a1a93
parent 576246 838652a84b76c273e084d0705f3f4f3be89520a8
child 628194 626a3f4b2e90fa63652c375d6c354095f44aa948
push id58358
push userbmo:poirot.alex@gmail.com
push dateThu, 11 May 2017 18:19:45 +0000
reviewersjdescottes
bugs1363419
milestone55.0a1
Bug 1363419 - Unregister DevTools on Add-on disabling. r=jdescottes MozReview-Commit-ID: 7ME0xBdjvle
devtools/bootstrap.js
--- a/devtools/bootstrap.js
+++ b/devtools/bootstrap.js
@@ -1,13 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* global content */
+/* global content, APP_SHUTDOWN */
 /* exported startup, shutdown, install, uninstall */
 
 "use strict";
 
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
 const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
@@ -135,16 +135,52 @@ let getTopLevelWindow = function (window
   return window.QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIWebNavigation)
                .QueryInterface(Ci.nsIDocShellTreeItem)
                .rootTreeItem
                .QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIDOMWindow);
 };
 
+function unload(reason) {
+  // This frame script is going to be executed in all processes:
+  // parent and child
+  Services.ppmm.loadProcessScript("data:,(" + function (scriptReason) {
+    /* Flush message manager cached frame scripts as well as chrome locales */
+    let obs = Components.classes["@mozilla.org/observer-service;1"]
+                        .getService(Components.interfaces.nsIObserverService);
+    obs.notifyObservers(null, "message-manager-flush-caches");
+
+    /* Also purge cached modules in child processes, we do it a few lines after
+       in the parent process */
+    if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
+      Services.obs.notifyObservers(null, "devtools-unload", scriptReason);
+    }
+  } + ")(\"" + reason.replace(/"/g, '\\"') + "\")", false);
+
+  // As we can't get a reference to existing Loader.jsm instances, we send them
+  // an observer service notification to unload them.
+  Services.obs.notifyObservers(null, "devtools-unload", reason);
+
+  // Then spawn a brand new Loader.jsm instance and start the main module
+  Cu.unload("resource://devtools/shared/Loader.jsm");
+  // Also unload all resources loaded as jsm, hopefully all of them are going
+  // to be converted into regular modules
+  Cu.unload("resource://devtools/client/shared/browser-loader.js");
+  Cu.unload("resource://devtools/client/framework/ToolboxProcess.jsm");
+  Cu.unload("resource://devtools/shared/apps/Devices.jsm");
+  Cu.unload("resource://devtools/client/scratchpad/scratchpad-manager.jsm");
+  Cu.unload("resource://devtools/shared/Parser.jsm");
+  Cu.unload("resource://devtools/client/shared/DOMHelpers.jsm");
+  Cu.unload("resource://devtools/client/shared/widgets/VariablesView.jsm");
+  Cu.unload("resource://devtools/client/responsivedesign/responsivedesign.jsm");
+  Cu.unload("resource://devtools/client/shared/widgets/AbstractTreeItem.jsm");
+  Cu.unload("resource://devtools/shared/deprecated-sync-thenables.js");
+}
+
 function reload(event) {
   // We automatically reload the toolbox if we are on a browser tab
   // with a toolbox already opened
   let reloadToolbox = false;
   if (event) {
     let top = getTopLevelWindow(event.view);
     let isBrowser = top.location.href.includes("/browser.xul");
     if (isBrowser && top.gBrowser) {
@@ -167,49 +203,17 @@ function reload(event) {
     reopenBrowserConsole = true;
   }
 
   dump("Reload DevTools.  (reload-toolbox:" + reloadToolbox + ")\n");
 
   // Invalidate xul cache in order to see changes made to chrome:// files
   Services.obs.notifyObservers(null, "startupcache-invalidate");
 
-  // This frame script is going to be executed in all processes:
-  // parent and child
-  Services.ppmm.loadProcessScript("data:,new " + function () {
-    /* Flush message manager cached frame scripts as well as chrome locales */
-    let obs = Components.classes["@mozilla.org/observer-service;1"]
-                        .getService(Components.interfaces.nsIObserverService);
-    obs.notifyObservers(null, "message-manager-flush-caches");
-
-    /* Also purge cached modules in child processes, we do it a few lines after
-       in the parent process */
-    if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
-      Services.obs.notifyObservers(null, "devtools-unload", "reload");
-    }
-  }, false);
-
-  // As we can't get a reference to existing Loader.jsm instances, we send them
-  // an observer service notification to unload them.
-  Services.obs.notifyObservers(null, "devtools-unload", "reload");
-
-  // Then spawn a brand new Loader.jsm instance and start the main module
-  Cu.unload("resource://devtools/shared/Loader.jsm");
-  // Also unload all resources loaded as jsm, hopefully all of them are going
-  // to be converted into regular modules
-  Cu.unload("resource://devtools/client/shared/browser-loader.js");
-  Cu.unload("resource://devtools/client/framework/ToolboxProcess.jsm");
-  Cu.unload("resource://devtools/shared/apps/Devices.jsm");
-  Cu.unload("resource://devtools/client/scratchpad/scratchpad-manager.jsm");
-  Cu.unload("resource://devtools/shared/Parser.jsm");
-  Cu.unload("resource://devtools/client/shared/DOMHelpers.jsm");
-  Cu.unload("resource://devtools/client/shared/widgets/VariablesView.jsm");
-  Cu.unload("resource://devtools/client/responsivedesign/responsivedesign.jsm");
-  Cu.unload("resource://devtools/client/shared/widgets/AbstractTreeItem.jsm");
-  Cu.unload("resource://devtools/shared/deprecated-sync-thenables.js");
+  unload("reload");
 
   // Update the preferences before starting new code
   setPrefs();
 
   const {devtools} = Cu.import("resource://devtools/shared/Loader.jsm", {});
   devtools.require("devtools/client/framework/devtools-browser");
 
   // Go over all top level windows to reload all devtools related things
@@ -288,28 +292,35 @@ function startup(data) {
     if (userValue != value) {
       Services.prefs.setBoolPref(name, value);
       originalPrefValues[name] = userValue;
     }
   }
 
   reload();
 }
-function shutdown() {
+function shutdown(data, reason) {
+  // On browser shutdown, do not try to cleanup anything
+  if (reason == APP_SHUTDOWN) {
+    return;
+  }
+
   listener.stop();
   listener = null;
 
   // Restore preferences that used to be before the addon was installed
   for (let name in originalPrefValues) {
     let userValue = Services.prefs.getBoolPref(name);
     // Only reset the pref if it hasn't changed
     if (userValue == prefs[name]) {
       Services.prefs.setBoolPref(name, originalPrefValues[name]);
     }
   }
+
+  unload("disable");
 }
 function install() {
   try {
     actionOccurred("reloadAddonInstalled");
   } catch (e) {
     // When installing on Firefox builds without devtools, telemetry doesn't
     // work yet and throws.
   }