Bug 1293287: Close extension popups on extension shutdown. r?aswan
MozReview-Commit-ID: 5lpIk6XrdOM
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -86,16 +86,24 @@ XPCOMUtils.defineLazyGetter(this, "stand
let styleSheetURI = NetUtil.newURI("chrome://browser/content/extension-win-panel.css");
let winStyleSheet = styleSheetService.preloadSheet(styleSheetURI,
styleSheetService.AGENT_SHEET);
stylesheets.push(winStyleSheet);
}
return stylesheets;
});
+/* eslint-disable mozilla/balanced-listeners */
+extensions.on("page-shutdown", (type, context) => {
+ if (context.type == "popup" && context.active) {
+ context.contentWindow.close();
+ }
+});
+/* eslint-enable mozilla/balanced-listeners */
+
class BasePopup {
constructor(extension, viewNode, popupURL, browserStyle, fixedWidth = false) {
this.extension = extension;
this.popupURL = popupURL;
this.viewNode = viewNode;
this.browserStyle = browserStyle;
this.window = viewNode.ownerGlobal;
this.destroyed = false;
@@ -124,18 +132,20 @@ class BasePopup {
this.browserLoadedDeferred.reject(new Error("Popup destroyed"));
return this.browserReady.then(() => {
this.destroyBrowser(this.browser);
this.browser.remove();
this.viewNode.removeEventListener(this.DESTROY_EVENT, this);
this.viewNode.style.maxHeight = "";
- this.panel.style.removeProperty("--panel-arrowcontent-background");
- this.panel.style.removeProperty("--panel-arrow-image-vertical");
+ if (this.panel) {
+ this.panel.style.removeProperty("--panel-arrowcontent-background");
+ this.panel.style.removeProperty("--panel-arrow-image-vertical");
+ }
this.browser = null;
this.viewNode = null;
});
}
destroyBrowser(browser) {
browser.removeEventListener("DOMWindowCreated", this, true);
@@ -149,17 +159,17 @@ class BasePopup {
// Returns the name of the event fired on `viewNode` when the popup is being
// destroyed. This must be implemented by every subclass.
get DESTROY_EVENT() {
throw new Error("Not implemented");
}
get panel() {
let panel = this.viewNode;
- while (panel.localName != "panel") {
+ while (panel && panel.localName != "panel") {
panel = panel.parentNode;
}
return panel;
}
handleEvent(event) {
switch (event.type) {
case this.DESTROY_EVENT:
--- a/browser/components/extensions/test/browser/browser.ini
+++ b/browser/components/extensions/test/browser/browser.ini
@@ -44,16 +44,17 @@ tags = webextensions
[browser_ext_pageAction_context.js]
[browser_ext_pageAction_popup.js]
[browser_ext_pageAction_popup_resize.js]
[browser_ext_pageAction_simple.js]
[browser_ext_pageAction_title.js]
[browser_ext_popup_api_injection.js]
[browser_ext_popup_background.js]
[browser_ext_popup_corners.js]
+[browser_ext_popup_shutdown.js]
[browser_ext_runtime_openOptionsPage.js]
[browser_ext_runtime_openOptionsPage_uninstall.js]
[browser_ext_runtime_setUninstallURL.js]
[browser_ext_simple.js]
[browser_ext_tab_runtimeConnect.js]
[browser_ext_tabs_audio.js]
[browser_ext_tabs_captureVisibleTab.js]
[browser_ext_tabs_create.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_popup_shutdown.js
@@ -0,0 +1,80 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+add_task(function* testPopupShutdown() {
+ let getExtension = () => {
+ return ExtensionTestUtils.loadExtension({
+ background() {
+ browser.tabs.query({active: true, currentWindow: true}, tabs => {
+ browser.pageAction.show(tabs[0].id);
+ });
+ },
+
+ manifest: {
+ "browser_action": {
+ "default_popup": "popup.html",
+ "browser_style": false,
+ },
+
+ "page_action": {
+ "default_popup": "popup.html",
+ "browser_style": false,
+ },
+ },
+
+ files: {
+ "popup.html": `<!DOCTYPE html>
+ <html><head><meta charset="utf-8"></head></html>`,
+ },
+ });
+ };
+
+ {
+ info("Test stand-alone browserAction popup");
+
+ let extension = getExtension();
+ yield extension.startup();
+
+ clickBrowserAction(extension);
+ let browser = yield awaitExtensionPanel(extension);
+ let panel = getPanelForNode(browser);
+
+ yield extension.unload();
+
+ is(panel.parentNode, null, "Panel should be removed from the document");
+ }
+
+ {
+ info("Test menu panel browserAction popup");
+
+ let extension = getExtension();
+ yield extension.startup();
+
+ let widget = getBrowserActionWidget(extension);
+ CustomizableUI.addWidgetToArea(widget.id, CustomizableUI.AREA_PANEL);
+
+ clickBrowserAction(extension);
+ let browser = yield awaitExtensionPanel(extension);
+ let panel = getPanelForNode(browser);
+
+ yield extension.unload();
+
+ is(panel.state, "closed", "Panel should be closed");
+ }
+
+ {
+ info("Test pageAction popup");
+
+ let extension = getExtension();
+ yield extension.startup();
+
+ clickPageAction(extension);
+ let browser = yield awaitExtensionPanel(extension);
+ let panel = getPanelForNode(browser);
+
+ yield extension.unload();
+
+ is(panel.parentNode, null, "Panel should be removed from the document");
+ }
+});