Bug 1273251: Part 6 - Test that extension window wrappers are nuked on close. r?billm draft
authorKris Maglione <maglione.k@gmail.com>
Thu, 17 Nov 2016 12:44:30 -0800
changeset 440652 52073d2c6cf4d2d5c9845959a9deeac00d5f434f
parent 440651 fc8916a9983f427cfc45e39b4d54c34349846d4e
child 537427 5926deeeacb101de220ab0c99cd83810ac15281d
push id36285
push usermaglione.k@gmail.com
push dateThu, 17 Nov 2016 23:17:43 +0000
reviewersbillm
bugs1273251
milestone52.0a1
Bug 1273251: Part 6 - Test that extension window wrappers are nuked on close. r?billm MozReview-Commit-ID: 3sWNuLqZBzp
js/xpconnect/tests/unit/test_nuke_webextension_wrappers.js
js/xpconnect/tests/unit/xpcshell.ini
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/unit/test_nuke_webextension_wrappers.js
@@ -0,0 +1,81 @@
+/* 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/. */
+
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=1273251
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+Cu.import("resource://gre/modules/Timer.jsm");
+
+function promiseEvent(target, event) {
+  return new Promise(resolve => {
+    target.addEventListener(event, resolve, {capture: true, once: true});
+  });
+}
+
+add_task(function* setup() {
+  let aps = Cc["@mozilla.org/addons/policy-service;1"].getService(Ci.nsIAddonPolicyService).wrappedJSObject;
+
+  let oldAddonIdCallback = aps.setExtensionURIToAddonIdCallback(uri => uri.host);
+  do_register_cleanup(() => {
+    aps.setExtensionURIToAddonIdCallback(oldAddonIdCallback);
+  });
+});
+
+function getWindowlessBrowser(url) {
+  let ssm = Services.scriptSecurityManager;
+
+  let uri = NetUtil.newURI(url);
+  // TODO: Remove when addonId origin attribute is removed.
+  let attrs = {addonId: uri.host};
+
+  let principal = ssm.createCodebasePrincipal(uri, attrs);
+
+  let webnav = Services.appShell.createWindowlessBrowser(false);
+
+  let docShell = webnav.QueryInterface(Ci.nsIInterfaceRequestor)
+                       .getInterface(Ci.nsIDocShell);
+
+  docShell.createAboutBlankContentViewer(principal);
+
+  return webnav;
+}
+
+add_task(function*() {
+  let ssm = Services.scriptSecurityManager;
+
+  let webnavA = getWindowlessBrowser("moz-extension://foo/a.html");
+  let webnavB = getWindowlessBrowser("moz-extension://foo/b.html");
+
+  let winA = Cu.waiveXrays(webnavA.document.defaultView);
+  let winB = Cu.waiveXrays(webnavB.document.defaultView);
+
+  winB.winA = winA;
+  winB.eval(`winA.thing = {foo: "bar"};`);
+
+  let getThing = winA.eval(String(() => {
+    try {
+      return thing.foo;
+    } catch (e) {
+      return String(e);
+    }
+  }));
+
+  // Check that the object can be accessed normally before windowB is closed.
+  equal(getThing(), "bar");
+
+  webnavB.close();
+
+  // Wrappers are nuked asynchronously, so wait a tick.
+  yield new Promise(resolve => setTimeout(resolve, 0));
+
+  // Check that it can't be accessed after he window has been closed.
+  let result = getThing();
+  ok(/dead object/.test(result),
+     `Result should show a dead wrapper error: ${result}`);
+
+  webnavA.close();
+});
--- a/js/xpconnect/tests/unit/xpcshell.ini
+++ b/js/xpconnect/tests/unit/xpcshell.ini
@@ -96,16 +96,17 @@ fail-if = os == "android"
 fail-if = os == "android"
 [test_tearoffs.js]
 [test_want_components.js]
 [test_components.js]
 [test_allowedDomains.js]
 [test_allowedDomainsXHR.js]
 [test_nuke_sandbox.js]
 [test_nuke_sandbox_event_listeners.js]
+[test_nuke_webextension_wrappers.js]
 [test_sandbox_metadata.js]
 [test_exportFunction.js]
 [test_promise.js]
 [test_returncode.js]
 skip-if = os == "android" # native test components aren't available on Android
 [test_textDecoder.js]
 [test_url.js]
 [test_URLSearchParams.js]