diff --git a/browser/components/extensions/test/browser/browser_ext_getViews.js b/browser/components/extensions/test/browser/browser_ext_getViews.js index efbda4f8bf4a..0143d3694cbd 100644 --- a/browser/components/extensions/test/browser/browser_ext_getViews.js +++ b/browser/components/extensions/test/browser/browser_ext_getViews.js @@ -20,6 +20,7 @@ function genericChecker() { "tab": 0, "popup": 0, }; + let background; for (let i = 0; i < views.length; i++) { let view = views[i]; browser.test.assertTrue(view.kind in counts, "view type is valid"); @@ -27,9 +28,17 @@ function genericChecker() { if (view.kind == "background") { browser.test.assertTrue(view === browser.extension.getBackgroundPage(), "background page is correct"); + background = view; } } - browser.test.sendMessage("counts", counts); + if (background) { + browser.runtime.getBackgroundPage().then(view => { + browser.test.assertEq(background, view, "runtime.getBackgroundPage() is correct"); + browser.test.sendMessage("counts", counts); + }); + } else { + browser.test.sendMessage("counts", counts); + } } else if (msg == kind + "-open-tab") { browser.tabs.create({windowId: args[0], url: browser.runtime.getURL("tab.html")}); } else if (msg == kind + "-close-tab") { diff --git a/toolkit/components/extensions/ExtensionUtils.jsm b/toolkit/components/extensions/ExtensionUtils.jsm index 067de45b0180..2374fdc297cd 100644 --- a/toolkit/components/extensions/ExtensionUtils.jsm +++ b/toolkit/components/extensions/ExtensionUtils.jsm @@ -212,30 +212,41 @@ class BaseContext { * callback. May resolve to a `SpreadArgs` instance, in which case * each element will be used as a separate argument. * + * Unless the promise object belongs to the cloneScope global, its + * resolution value is cloned into cloneScope prior to calling the + * `callback` function or resolving the wrapped promise. + * * @param {function} [callback] The callback function to wrap * * @returns {Promise|undefined} If callback is null, a promise object * belonging to the target scope. Otherwise, undefined. */ wrapPromise(promise, callback = null) { + // Note: `promise instanceof this.cloneScope.Promise` returns true + // here even for promises that do not belong to the content scope. + let runSafe = runSafeSync.bind(null, this); + if (promise.constructor === this.cloneScope.Promise) { + runSafe = runSafeSyncWithoutClone; + } + if (callback) { promise.then( args => { if (args instanceof SpreadArgs) { - runSafeSync(this, callback, ...args); + runSafe(callback, ...args); } else { - runSafeSync(this, callback, args); + runSafe(callback, args); } }, error => { this.withLastError(error, () => { - runSafeSync(this, callback); + runSafeSyncWithoutClone(callback); }); }); } else { return new this.cloneScope.Promise((resolve, reject) => { promise.then( - value => { runSafeSync(this, resolve, value); }, + value => { runSafe(resolve, value); }, value => { if (!(value instanceof this.cloneScope.Error)) { value = new this.cloneScope.Error(value.message); diff --git a/toolkit/components/extensions/ext-backgroundPage.js b/toolkit/components/extensions/ext-backgroundPage.js index a6b2c8a95d82..c3895a1c32bc 100644 --- a/toolkit/components/extensions/ext-backgroundPage.js +++ b/toolkit/components/extensions/ext-backgroundPage.js @@ -133,8 +133,8 @@ extensions.registerSchemaAPI("extension", null, (extension, context) => { }, runtime: { - getBackgroundPage: function(callback) { - runSafe(context, callback, backgroundPagesMap.get(extension).contentWindow); + getBackgroundPage() { + return context.cloneScope.Promise.resolve(backgroundPagesMap.get(extension).contentWindow); }, }, }; diff --git a/toolkit/components/extensions/schemas/runtime.json b/toolkit/components/extensions/schemas/runtime.json index 3bb4294c0270..0c8f3e1e9b7c 100644 --- a/toolkit/components/extensions/schemas/runtime.json +++ b/toolkit/components/extensions/schemas/runtime.json @@ -114,6 +114,7 @@ "name": "getBackgroundPage", "type": "function", "description": "Retrieves the JavaScript 'window' object for the background page running inside the current extension/app. If the background page is an event page, the system will ensure it is loaded before calling the callback. If there is no background page, an error is set.", + "async": "callback", "parameters": [ { "type": "function",