Bug 1340529 - Fix shown/hidden events for a devtools_panel toggled from toolbox preferences. r=kmag
authorLuca Greco <lgreco@mozilla.com>
Thu, 16 Feb 2017 04:07:49 +0100
changeset 374979 17658ab4c138f54540cce67cc2eb1a6258d10748
parent 374978 625d277367c3ace7d63658053db6106e8f254016
child 374980 2825d7b622e7268461e16e2d3cec6d0bef61b415
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag
bugs1340529
milestone54.0a1
Bug 1340529 - Fix shown/hidden events for a devtools_panel toggled from toolbox preferences. r=kmag MozReview-Commit-ID: H81qwCEoaf9
browser/components/extensions/ext-c-devtools-panels.js
browser/components/extensions/ext-devtools-panels.js
browser/components/extensions/test/browser/browser_ext_devtools_panel.js
--- a/browser/components/extensions/ext-c-devtools-panels.js
+++ b/browser/components/extensions/ext-c-devtools-panels.js
@@ -39,16 +39,23 @@ class ChildDevToolsPanel extends EventEm
     if (this._panelContext) {
       return this._panelContext;
     }
 
     for (let view of this.context.extension.devtoolsViews) {
       if (view.viewType === "devtools_panel" &&
           view.devtoolsToolboxInfo.toolboxPanelId === this.id) {
         this._panelContext = view;
+
+        // Reset the cached _panelContext property when the view is closed.
+        view.callOnClose({
+          close: () => {
+            this._panelContext = null;
+          },
+        });
         return view;
       }
     }
 
     return null;
   }
 
   receiveMessage({name, data}) {
--- a/browser/components/extensions/ext-devtools-panels.js
+++ b/browser/components/extensions/ext-devtools-panels.js
@@ -165,31 +165,36 @@ class ParentDevToolsPanel {
     //   its ParentDevToolsPanel instance is still valid, but the built devtools panel is removed from
     //   the toolbox (and re-built again if the user re-enable it from the toolbox preferences panel)
     // - when the creator context has been destroyed, the ParentDevToolsPanel close method is called,
     //   it remove the tool definition from the toolbox, which will call this destroy method.
     return () => {
       unwatchExtensionProxyContextLoad();
       browser.remove();
       toolbox.off("select", this.onToolboxPanelSelect);
+
+      // If the panel has been disabled from the toolbox preferences,
+      // we need to re-initialize the waitTopLevelContext Promise.
+      this.waitTopLevelContext = new Promise(resolve => {
+        this._resolveTopLevelContext = resolve;
+      });
     };
   }
 
   onToolboxReady() {
     if (!this.panelAdded) {
       this.panelAdded = true;
       this.addPanel();
     }
   }
 
   onToolboxPanelSelect(what, id) {
     if (!this.waitTopLevelContext || !this.panelAdded) {
       return;
     }
-
     if (!this.visible && id === this.id) {
       // Wait that the panel is fully loaded and emit show.
       this.waitTopLevelContext.then(() => {
         this.visible = true;
         this.context.parentMessageManager.sendAsyncMessage("Extension:DevToolsPanelShown", {
           toolboxPanelId: this.id,
         });
       });
@@ -213,16 +218,18 @@ class ParentDevToolsPanel {
     // Explicitly remove the panel if it is registered and the toolbox is not
     // closing itself.
     if (toolbox.isToolRegistered(this.id) && !toolbox._destroyer) {
       toolbox.removeAdditionalTool(this.id);
     }
 
     this.context = null;
     this.toolbox = null;
+    this.waitTopLevelContext = null;
+    this._resolveTopLevelContext = null;
   }
 }
 
 extensions.registerSchemaAPI("devtools.panels", "devtools_parent", context => {
   // An incremental "per context" id used in the generated devtools panel id.
   let nextPanelId = 0;
 
   return {
--- a/browser/components/extensions/test/browser/browser_ext_devtools_panel.js
+++ b/browser/components/extensions/test/browser/browser_ext_devtools_panel.js
@@ -130,16 +130,66 @@ add_task(function* test_devtools_page_pa
   yield gDevTools.showToolbox(target, "webconsole");
   const secondCycleResults = yield extension.awaitMessage("devtools_panel_hidden");
   info("Addon Devtools Panel hidden - second cycle");
 
   is(secondCycleResults.panelCreated, 1, "devtools.panel.create callback has been called once");
   is(secondCycleResults.panelShown, 2, "panel.onShown listener has been called twice");
   is(secondCycleResults.panelHidden, 2, "panel.onHidden listener has been called twice");
 
+  // Turn off the addon devtools panel using the visibilityswitch.
+  const waitToolVisibilityOff = new Promise(resolve => {
+    toolbox.once("tool-unregistered", resolve);
+  });
+
+  Services.prefs.setBoolPref(`devtools.webext-${panelId}.enabled`, false);
+  gDevTools.emit("tool-unregistered", panelId);
+
+  yield waitToolVisibilityOff;
+
+  ok(toolbox.hasAdditionalTool(panelId),
+     "The tool has not been removed on visibilityswitch set to false");
+
+  is(toolbox.visibleAdditionalTools.filter(tool => tool.id == panelId).length, 0,
+     "The tool is not visible on visibilityswitch set to false");
+
+  // Turn on the addon devtools panel using the visibilityswitch.
+  const waitToolVisibilityOn = new Promise(resolve => {
+    toolbox.once("tool-registered", resolve);
+  });
+
+  Services.prefs.setBoolPref(`devtools.webext-${panelId}.enabled`, true);
+  gDevTools.emit("tool-registered", panelId);
+
+  yield waitToolVisibilityOn;
+
+  ok(toolbox.hasAdditionalTool(panelId),
+     "The tool has been added on visibilityswitch set to true");
+  is(toolbox.visibleAdditionalTools.filter(toolId => toolId == panelId).length, 1,
+     "The tool is visible on visibilityswitch set to true");
+
+  // Test devtools panel is loaded correctly after being toggled and
+  // devtools panel events has been fired as expected.
+  yield gDevTools.showToolbox(target, panelId);
+  yield extension.awaitMessage("devtools_panel_shown");
+  info("Addon Devtools Panel shown - after visibilityswitch toggled");
+
+  info("Wait until the Addon Devtools Panel has been loaded - after visibilityswitch toggled");
+  const panelTabIdAfterToggle = yield extension.awaitMessage("devtools_panel_inspectedWindow_tabId");
+  is(panelTabIdAfterToggle, devtoolsPageTabId,
+     "Got the same devtools.inspectedWindow.tabId from devtools panel after visibility toggled");
+
+  yield gDevTools.showToolbox(target, "webconsole");
+  const toolToggledResults = yield extension.awaitMessage("devtools_panel_hidden");
+  info("Addon Devtools Panel hidden - after visibilityswitch toggled");
+
+  is(toolToggledResults.panelCreated, 1, "devtools.panel.create callback has been called once");
+  is(toolToggledResults.panelShown, 3, "panel.onShown listener has been called three times");
+  is(toolToggledResults.panelHidden, 3, "panel.onHidden listener has been called three times");
+
   yield gDevTools.closeToolbox(target);
 
   yield target.destroy();
 
   yield extension.unload();
 
   yield BrowserTestUtils.removeTab(tab);
 });