Bug 1356334: Part 7 - Destroy content script sandboxes after slow script termination. r=mixedpuppy
☠☠ backed out by 399db8547abb ☠ ☠
authorKris Maglione <maglione.k@gmail.com>
Sun, 16 Apr 2017 14:03:33 -0700
changeset 375603 4f5bcd2b2dc695397c97f0c1391b66c6f8251939
parent 375602 d832803270ac831fd760356f36e16ef2a2d6d45b
child 375604 b0bdc6c0e7ef5fdb86e8fd3fb276b2c9cab364ad
push id32358
push userkwierso@gmail.com
push dateFri, 18 Aug 2017 22:53:28 +0000
treeherdermozilla-central@4f4487cc2d30 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmixedpuppy
bugs1356334
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1356334: Part 7 - Destroy content script sandboxes after slow script termination. r=mixedpuppy MozReview-Commit-ID: 6JSnW0G6qlY
toolkit/components/extensions/ExtensionContent.jsm
--- a/toolkit/components/extensions/ExtensionContent.jsm
+++ b/toolkit/components/extensions/ExtensionContent.jsm
@@ -431,16 +431,18 @@ class ContentScriptContextChild extends 
 
       Cu.evalInSandbox(`
         window.JSON = JSON;
         window.XMLHttpRequest = XMLHttpRequest;
         window.fetch = fetch;
       `, this.sandbox);
     }
 
+    DocumentManager.sandboxContexts.set(this.sandbox, this);
+
     Object.defineProperty(this, "principal", {
       value: Cu.getObjectPrincipal(this.sandbox),
       enumerable: true,
       configurable: true,
     });
 
     this.url = contentWindow.location.href;
 
@@ -475,16 +477,18 @@ class ContentScriptContextChild extends 
     if (script.requiresCleanup) {
       this.scripts.push(script);
     }
   }
 
   close() {
     super.unload();
 
+    DocumentManager.sandboxContexts.delete(this.sandbox);
+
     if (this.contentWindow) {
       for (let script of this.scripts) {
         script.cleanup(this.contentWindow);
       }
 
       // Overwrite the content script APIs with an empty object if the APIs objects are still
       // defined in the content window (bug 1214658).
       if (this.isExtensionPage) {
@@ -523,30 +527,34 @@ defineLazyGetter(ContentScriptContextChi
 });
 
 // Responsible for creating ExtensionContexts and injecting content
 // scripts into them when new documents are created.
 DocumentManager = {
   // Map[windowId -> Map[ExtensionChild -> ContentScriptContextChild]]
   contexts: new Map(),
 
+  sandboxContexts: new WeakMap(),
+
   initialized: false,
 
   lazyInit() {
     if (this.initialized) {
       return;
     }
     this.initialized = true;
 
     Services.obs.addObserver(this, "inner-window-destroyed");
+    Services.obs.addObserver(this, "kill-content-script-sandbox");
     Services.obs.addObserver(this, "memory-pressure");
   },
 
   uninit() {
     Services.obs.removeObserver(this, "inner-window-destroyed");
+    Services.obs.removeObserver(this, "kill-content-script-sandbox");
     Services.obs.removeObserver(this, "memory-pressure");
   },
 
   observers: {
     "inner-window-destroyed"(subject, topic, data) {
       let windowId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
 
       MessageChannel.abortResponses({innerWindowID: windowId});
@@ -556,16 +564,23 @@ DocumentManager = {
         let extensions = this.contexts.get(windowId);
         for (let context of extensions.values()) {
           context.close();
         }
 
         this.contexts.delete(windowId);
       }
     },
+    "kill-content-script-sandbox"(subject) {
+      let sandbox = subject.wrappedJSObject;
+      let context = this.sandboxContexts.get(sandbox);
+      if (context) {
+        context.close();
+      }
+    },
     "memory-pressure"(subject, topic, data) {
       let timeout = data === "heap-minimize" ? 0 : undefined;
 
       for (let cache of ChromeUtils.nondeterministicGetWeakSetKeys(scriptCaches)) {
         cache.clear(timeout);
       }
     },
   },