Bug 1382661 - Stop injecting DeveloperToolbar on top level windows. r=jdescottes draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Thu, 20 Jul 2017 13:52:57 +0200
changeset 612946 af33e7e01b508e01bd5f982e06feeaaa367512cb
parent 612140 e67c23c783ea77ba82e7376cfb0aab1c56952a3d
child 612952 558a85d502e19737d632afd779e23d5dcabd0740
push id69664
push userbmo:poirot.alex@gmail.com
push dateFri, 21 Jul 2017 09:09:56 +0000
reviewersjdescottes
bugs1382661
milestone56.0a1
Bug 1382661 - Stop injecting DeveloperToolbar on top level windows. r=jdescottes MozReview-Commit-ID: L6k7SPf8czd
devtools/client/commandline/test/helpers.js
devtools/client/framework/devtools-browser.js
devtools/client/menus.js
devtools/client/shared/developer-toolbar.js
devtools/client/shared/test/.eslintrc.js
devtools/client/shared/test/browser_toolbar_basic.js
devtools/client/shared/test/browser_toolbar_tooltip.js
devtools/client/shared/test/browser_toolbar_webconsole_errors_count.js
devtools/client/webconsole/hudservice.js
--- a/devtools/client/commandline/test/helpers.js
+++ b/devtools/client/commandline/test/helpers.js
@@ -19,16 +19,17 @@
 // A copy of this code exists in firefox mochitests. They should be kept
 // in sync. Hence the exports synonym for non AMD contexts.
 var { helpers, assert } = (function () {
 
   var helpers = {};
 
   var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
   var { TargetFactory } = require("devtools/client/framework/target");
+  var { gDevToolsBrowser } = require("devtools/client/framework/devtools-browser");
   var Services = require("Services");
 
   var assert = { ok: ok, is: is, log: info };
   var util = require("gcli/util/util");
   var cli = require("gcli/cli");
   var KeyEvent = require("gcli/util/util").KeyEvent;
 
   const { GcliFront } = require("devtools/shared/fronts/gcli");
@@ -206,18 +207,18 @@ var { helpers, assert } = (function () {
  * - requisition
  * @return A promise which resolves to the options object when the 'load' event
  * happens on the new tab
  */
   helpers.openToolbar = function (options) {
     options = options || {};
     options.chromeWindow = options.chromeWindow || window;
 
-    return options.chromeWindow.DeveloperToolbar.show(true).then(function () {
-      var toolbar = options.chromeWindow.DeveloperToolbar;
+    var toolbar = gDevToolsBrowser.getDeveloperToolbar(options.chromeWindow);
+    return toolbar.show(true).then(function () {
       options.automator = createDeveloperToolbarAutomator(toolbar);
       options.requisition = toolbar.requisition;
       return options;
     });
   };
 
 /**
  * Navigate the current tab to a URL
@@ -238,17 +239,18 @@ var { helpers, assert } = (function () {
   });
 
 /**
  * Undo the effects of |helpers.openToolbar|
  * @param options The options object passed to |helpers.openToolbar|
  * @return A promise resolved (with undefined) when the toolbar is closed
  */
   helpers.closeToolbar = function (options) {
-    return options.chromeWindow.DeveloperToolbar.hide().then(function () {
+    var toolbar = gDevToolsBrowser.getDeveloperToolbar(options.chromeWindow).hide();
+    return toolbar.then(function () {
       delete options.automator;
       delete options.requisition;
     });
   };
 
 /**
  * A helper to work with Task.spawn so you can do:
  *   return Task.spawn(realTestFunc).then(finish, helpers.handleError);
@@ -318,28 +320,28 @@ var { helpers, assert } = (function () {
  * As addTab, but that also opens the developer toolbar. In addition a new
  * 'automator' property is added to the options object which uses the
  * developer toolbar
  */
   helpers.addTabWithToolbar = function (url, callback, options) {
     return helpers.addTab(url, function (innerOptions) {
       var win = innerOptions.chromeWindow;
 
-      return win.DeveloperToolbar.show(true).then(function () {
-        var toolbar = win.DeveloperToolbar;
+      var toolbar = gDevToolsBrowser.getDeveloperToolbar(win);
+      return toolbar.show(true).then(function () {
         innerOptions.automator = createDeveloperToolbarAutomator(toolbar);
         innerOptions.requisition = toolbar.requisition;
 
         var reply = callback.call(null, innerOptions);
 
         return Promise.resolve(reply).catch(function (error) {
           ok(false, error);
           console.error(error);
         }).then(function () {
-          win.DeveloperToolbar.hide().then(function () {
+          toolbar.hide().then(function () {
             delete innerOptions.automator;
           });
         });
       });
     }, options);
   };
 
 /**
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -19,16 +19,17 @@ const {gDevTools} = require("./devtools"
 
 // Load target and toolbox lazily as they need gDevTools to be fully initialized
 loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/target", true);
 loader.lazyRequireGetter(this, "Toolbox", "devtools/client/framework/toolbox", true);
 loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
 loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/main", true);
 loader.lazyRequireGetter(this, "BrowserMenus", "devtools/client/framework/browser-menus");
 loader.lazyRequireGetter(this, "appendStyleSheet", "devtools/client/shared/stylesheet-utils", true);
+loader.lazyRequireGetter(this, "DeveloperToolbar", "devtools/client/shared/developer-toolbar", true);
 
 loader.lazyImporter(this, "CustomizableUI", "resource:///modules/CustomizableUI.jsm");
 loader.lazyImporter(this, "CustomizableWidgets", "resource:///modules/CustomizableWidgets.jsm");
 loader.lazyImporter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm");
 loader.lazyImporter(this, "LightweightThemeManager", "resource://gre/modules/LightweightThemeManager.jsm");
 
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
@@ -50,16 +51,21 @@ var gDevToolsBrowser = exports.gDevTools
   _trackedBrowserWindows: new Set(),
 
   /**
    * WeakMap keeping track of the devtools-browser stylesheets loaded in the various
    * tracked windows.
    */
   _browserStyleSheets: new WeakMap(),
 
+  /**
+   * WeakMap keeping track of DeveloperToolbar instances for each firefox window.
+   */
+  _toolbars: new WeakMap(),
+
   _tabStats: {
     peakOpen: 0,
     peakPinned: 0,
     histOpen: [],
     histPinned: []
   },
 
   /**
@@ -103,17 +109,17 @@ var gDevToolsBrowser = exports.gDevTools
     toggleMenuItem("menu_devToolbar", devToolbarEnabled);
     let focusEl = doc.getElementById("menu_devToolbar");
     if (devToolbarEnabled) {
       focusEl.removeAttribute("disabled");
     } else {
       focusEl.setAttribute("disabled", "true");
     }
     if (devToolbarEnabled && Services.prefs.getBoolPref("devtools.toolbar.visible")) {
-      win.DeveloperToolbar.show(false).catch(console.error);
+      this.getDeveloperToolbar(win).show(false).catch(console.error);
     }
 
     // Enable WebIDE?
     let webIDEEnabled = Services.prefs.getBoolPref("devtools.webide.enabled");
     toggleMenuItem("menu_webide", webIDEEnabled);
 
     if (webIDEEnabled) {
       gDevToolsBrowser.installWebIDEWidget();
@@ -494,36 +500,46 @@ var gDevToolsBrowser = exports.gDevTools
     gDevToolsBrowser._trackedBrowserWindows.add(win);
 
     BrowserMenus.addMenus(win.document);
 
     // Register the Developer widget in the Hamburger menu or navbar
     // only once menus are registered as it depends on it.
     gDevToolsBrowser.installDeveloperWidget();
 
-    // Inject lazily DeveloperToolbar on the chrome window
-    loader.lazyGetter(win, "DeveloperToolbar", function () {
-      let { DeveloperToolbar } = require("devtools/client/shared/developer-toolbar");
-      return new DeveloperToolbar(win);
-    });
-
     this.updateCommandAvailability(win);
     this.updateDevtoolsThemeAttribute(win);
     this.ensurePrefObserver();
     win.addEventListener("unload", this);
 
     let tabContainer = win.gBrowser.tabContainer;
     tabContainer.addEventListener("TabSelect", this);
     tabContainer.addEventListener("TabOpen", this);
     tabContainer.addEventListener("TabClose", this);
     tabContainer.addEventListener("TabPinned", this);
     tabContainer.addEventListener("TabUnpinned", this);
   },
 
   /**
+   * Create singleton instance of the developer toolbar for a given top level window.
+   *
+   * @param {Window} win
+   *        The window to which the toolbar should be created.
+   */
+  getDeveloperToolbar(win) {
+    let toolbar = this._toolbars.get(win);
+    if (toolbar) {
+      return toolbar;
+    }
+    toolbar = new DeveloperToolbar(win);
+    this._toolbars.set(win, toolbar);
+    return toolbar;
+  },
+
+  /**
    * Hook the JS debugger tool to the "Debug Script" button of the slow script
    * dialog.
    */
   setSlowScriptDebugHandler() {
     let debugService = Cc["@mozilla.org/dom/slow-script-debug;1"]
                          .getService(Ci.nsISlowScriptDebug);
     let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
 
@@ -722,21 +738,17 @@ var gDevToolsBrowser = exports.gDevTools
     }
 
     let styleSheet = this._browserStyleSheets.get(win);
     if (styleSheet) {
       styleSheet.remove();
       this._browserStyleSheets.delete(win);
     }
 
-    // Destroy the Developer toolbar if it has been accessed
-    let desc = Object.getOwnPropertyDescriptor(win, "DeveloperToolbar");
-    if (desc && !desc.get) {
-      win.DeveloperToolbar.destroy();
-    }
+    this._toolbars.delete(win);
 
     let tabContainer = win.gBrowser.tabContainer;
     tabContainer.removeEventListener("TabSelect", this);
     tabContainer.removeEventListener("TabOpen", this);
     tabContainer.removeEventListener("TabClose", this);
     tabContainer.removeEventListener("TabPinned", this);
     tabContainer.removeEventListener("TabUnpinned", this);
   },
--- a/devtools/client/menus.js
+++ b/devtools/client/menus.js
@@ -70,19 +70,19 @@ exports.menuitems = [
     l10nKey: "devToolbarMenu",
     disabled: true,
     oncommand(event) {
       let window = event.target.ownerDocument.defaultView;
       // Distinguish events when selecting a menuitem, where we either open
       // or close the toolbar and when hitting the key shortcut where we just
       // focus the toolbar if it doesn't already has it.
       if (event.target.tagName.toLowerCase() == "menuitem") {
-        window.DeveloperToolbar.toggle();
+        gDevToolsBrowser.getDeveloperToolbar(window).toggle();
       } else {
-        window.DeveloperToolbar.focusToggle();
+        gDevToolsBrowser.getDeveloperToolbar(window).focusToggle();
       }
     },
     key: {
       id: "devToolbar",
       modifiers: "shift"
     },
     checkbox: true
   },
--- a/devtools/client/shared/developer-toolbar.js
+++ b/devtools/client/shared/developer-toolbar.js
@@ -225,17 +225,19 @@ DeveloperToolbar.prototype.createToolbar
   }
   let toolbar = this._doc.createElement("toolbar");
   toolbar.setAttribute("id", "developer-toolbar");
   toolbar.setAttribute("hidden", "true");
 
   let close = this._doc.createElement("toolbarbutton");
   close.setAttribute("id", "developer-toolbar-closebutton");
   close.setAttribute("class", "close-icon");
-  close.setAttribute("oncommand", "DeveloperToolbar.hide();");
+  close.addEventListener("command", (event) => {
+    this.hide();
+  });
   let closeTooltip = L10N.getStr("toolbar.closeButton.tooltip");
   close.setAttribute("tooltiptext", closeTooltip);
 
   let stack = this._doc.createElement("stack");
   stack.setAttribute("flex", "1");
 
   let input = this._doc.createElement("textbox");
   input.setAttribute("class", "gclitoolbar-input-node");
--- a/devtools/client/shared/test/.eslintrc.js
+++ b/devtools/client/shared/test/.eslintrc.js
@@ -1,9 +1,6 @@
 "use strict";
 
 module.exports = {
   // Extend from the shared list of defined globals for mochitests.
   "extends": "../../../.eslintrc.mochitests.js",
-  "globals": {
-    "DeveloperToolbar": true
-  }
 };
--- a/devtools/client/shared/test/browser_toolbar_basic.js
+++ b/devtools/client/shared/test/browser_toolbar_basic.js
@@ -1,27 +1,30 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests that the developer toolbar works properly
 
+const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
+
 const TEST_URI = TEST_URI_ROOT + "doc_toolbar_basic.html";
 
 add_task(function* () {
   info("Starting browser_toolbar_basic.js");
   yield addTab(TEST_URI);
 
-  ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in to start");
+  let toolbar = gDevToolsBrowser.getDeveloperToolbar(window);
+  ok(!toolbar.visible, "DeveloperToolbar is not visible in to start");
 
-  let shown = oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.SHOW);
+  let shown = oneTimeObserve(toolbar.NOTIFICATIONS.SHOW);
   document.getElementById("menu_devToolbar").doCommand();
   yield shown;
-  ok(DeveloperToolbar.visible, "DeveloperToolbar is visible in checkOpen");
+  ok(toolbar.visible, "DeveloperToolbar is visible in checkOpen");
 
   let close = document.getElementById("developer-toolbar-closebutton");
   ok(close, "Close button exists");
 
   let toggleToolbox =
     document.getElementById("menu_devToolbox");
   ok(!isChecked(toggleToolbox), "toggle toolbox button is not checked");
 
@@ -31,30 +34,30 @@ add_task(function* () {
 
   yield addTab("about:blank");
   info("Opened a new tab");
 
   ok(!isChecked(toggleToolbox), "toggle toolbox button is not checked");
 
   gBrowser.removeCurrentTab();
 
-  let hidden = oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.HIDE);
+  let hidden = oneTimeObserve(toolbar.NOTIFICATIONS.HIDE);
   document.getElementById("menu_devToolbar").doCommand();
   yield hidden;
-  ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in hidden");
+  ok(!toolbar.visible, "DeveloperToolbar is not visible in hidden");
 
-  shown = oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.SHOW);
+  shown = oneTimeObserve(toolbar.NOTIFICATIONS.SHOW);
   document.getElementById("menu_devToolbar").doCommand();
   yield shown;
-  ok(DeveloperToolbar.visible, "DeveloperToolbar is visible in after open");
+  ok(toolbar.visible, "DeveloperToolbar is visible in after open");
 
   ok(isChecked(toggleToolbox), "toggle toolbox button is checked");
 
-  hidden = oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.HIDE);
+  hidden = oneTimeObserve(toolbar.NOTIFICATIONS.HIDE);
   document.getElementById("developer-toolbar-closebutton").doCommand();
   yield hidden;
 
-  ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible after re-close");
+  ok(!toolbar.visible, "DeveloperToolbar is not visible after re-close");
 });
 
 function isChecked(b) {
   return b.getAttribute("checked") == "true";
 }
--- a/devtools/client/shared/test/browser_toolbar_tooltip.js
+++ b/devtools/client/shared/test/browser_toolbar_tooltip.js
@@ -1,99 +1,103 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests that the developer toolbar works properly
 
+const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
+
 const TEST_URI = "data:text/html;charset=utf-8,<p>Tooltip Tests</p>";
 const PREF_DEVTOOLS_THEME = "devtools.theme";
 
 registerCleanupFunction(() => {
   // Set preferences back to their original values
   Services.prefs.clearUserPref(PREF_DEVTOOLS_THEME);
 });
 
+let toolbar = gDevToolsBrowser.getDeveloperToolbar(window);
+
 add_task(function* showToolbar() {
   yield addTab(TEST_URI);
 
   info("Starting browser_toolbar_tooltip.js");
 
-  ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in runTest");
+  ok(!toolbar.visible, "DeveloperToolbar is not visible in runTest");
 
-  let showPromise = observeOnce(DeveloperToolbar.NOTIFICATIONS.SHOW);
+  let showPromise = observeOnce(toolbar.NOTIFICATIONS.SHOW);
   document.getElementById("menu_devToolbar").doCommand();
   yield showPromise;
 });
 
 add_task(function* testDimensions() {
-  let tooltipPanel = DeveloperToolbar.tooltipPanel;
+  let tooltipPanel = toolbar.tooltipPanel;
 
-  DeveloperToolbar.focusManager.helpRequest();
-  yield DeveloperToolbar.inputter.setInput("help help");
+  toolbar.focusManager.helpRequest();
+  yield toolbar.inputter.setInput("help help");
 
-  DeveloperToolbar.inputter.setCursor({ start: "help help".length });
+  toolbar.inputter.setCursor({ start: "help help".length });
   is(tooltipPanel._dimensions.start, "help ".length,
           "search param start, when cursor at end");
   ok(getLeftMargin() > 30, "tooltip offset, when cursor at end");
 
-  DeveloperToolbar.inputter.setCursor({ start: "help".length });
+  toolbar.inputter.setCursor({ start: "help".length });
   is(tooltipPanel._dimensions.start, 0,
           "search param start, when cursor at end of command");
   ok(getLeftMargin() > 9, "tooltip offset, when cursor at end of command");
 
-  DeveloperToolbar.inputter.setCursor({ start: "help help".length - 1 });
+  toolbar.inputter.setCursor({ start: "help help".length - 1 });
   is(tooltipPanel._dimensions.start, "help ".length,
           "search param start, when cursor at penultimate position");
   ok(getLeftMargin() > 30, "tooltip offset, when cursor at penultimate position");
 
-  DeveloperToolbar.inputter.setCursor({ start: 0 });
+  toolbar.inputter.setCursor({ start: 0 });
   is(tooltipPanel._dimensions.start, 0,
           "search param start, when cursor at start");
   ok(getLeftMargin() > 9, "tooltip offset, when cursor at start");
 });
 
 add_task(function* testThemes() {
-  let tooltipPanel = DeveloperToolbar.tooltipPanel;
+  let tooltipPanel = toolbar.tooltipPanel;
   ok(tooltipPanel.document, "Tooltip panel is initialized");
 
   Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "dark");
 
-  yield DeveloperToolbar.inputter.setInput("");
-  yield DeveloperToolbar.inputter.setInput("help help");
+  yield toolbar.inputter.setInput("");
+  yield toolbar.inputter.setInput("help help");
   is(tooltipPanel.document.documentElement.getAttribute("devtoolstheme"),
      "dark", "Tooltip panel has correct theme");
 
   Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "light");
 
-  yield DeveloperToolbar.inputter.setInput("");
-  yield DeveloperToolbar.inputter.setInput("help help");
+  yield toolbar.inputter.setInput("");
+  yield toolbar.inputter.setInput("help help");
   is(tooltipPanel.document.documentElement.getAttribute("devtoolstheme"),
      "light", "Tooltip panel has correct theme");
 });
 
 add_task(function* hideToolbar() {
   info("Ending browser_toolbar_tooltip.js");
-  yield DeveloperToolbar.inputter.setInput("");
+  yield toolbar.inputter.setInput("");
 
-  ok(DeveloperToolbar.visible, "DeveloperToolbar is visible in hideToolbar");
+  ok(toolbar.visible, "DeveloperToolbar is visible in hideToolbar");
 
   info("Hide toolbar");
-  let hidePromise = observeOnce(DeveloperToolbar.NOTIFICATIONS.HIDE);
+  let hidePromise = observeOnce(toolbar.NOTIFICATIONS.HIDE);
   document.getElementById("menu_devToolbar").doCommand();
   yield hidePromise;
 
-  ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in hideToolbar");
+  ok(!toolbar.visible, "DeveloperToolbar is not visible in hideToolbar");
 
   info("Done test");
 });
 
 function getLeftMargin() {
-  let style = DeveloperToolbar.tooltipPanel._panel.style.marginLeft;
+  let style = toolbar.tooltipPanel._panel.style.marginLeft;
   return parseInt(style.slice(0, -2), 10);
 }
 
 function observeOnce(topic, ownsWeak = false) {
   return new Promise(function (resolve, reject) {
     let resolver = function (subject) {
       Services.obs.removeObserver(resolver, topic);
       resolve(subject);
--- a/devtools/client/shared/test/browser_toolbar_webconsole_errors_count.js
+++ b/devtools/client/shared/test/browser_toolbar_webconsole_errors_count.js
@@ -2,24 +2,28 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /* eslint-disable mozilla/no-cpows-in-tests */
 
 "use strict";
 
 // Tests that the developer toolbar errors count works properly.
 
+const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
+
 // Use the old webconsole since this is directly accessing old DOM, and
 // the error count isn't reset when pressing the clear button in new one
 // See Bug 1304794.
 Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
 registerCleanupFunction(function* () {
   Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
 });
 
+let toolbar = gDevToolsBrowser.getDeveloperToolbar(window);
+
 function test() {
   const TEST_URI = TEST_URI_ROOT + "doc_toolbar_webconsole_errors_count.html";
 
   let tab1, tab2, webconsole;
 
   Services.prefs.setBoolPref("javascript.options.strict", true);
 
   registerCleanupFunction(() => {
@@ -30,25 +34,25 @@ function test() {
   addTab(TEST_URI).then(openToolbar);
 
   function openToolbar(tab) {
     tab1 = tab;
     ignoreAllUncaughtExceptions(false);
 
     expectUncaughtException();
 
-    if (!DeveloperToolbar.visible) {
-      DeveloperToolbar.show(true).then(onOpenToolbar);
+    if (!toolbar.visible) {
+      toolbar.show(true).then(onOpenToolbar);
     } else {
       onOpenToolbar();
     }
   }
 
   function onOpenToolbar() {
-    ok(DeveloperToolbar.visible, "DeveloperToolbar is visible");
+    ok(toolbar.visible, "DeveloperToolbar is visible");
     webconsole = document.getElementById("developer-toolbar-toolbox-button");
 
     waitForButtonUpdate({
       name: "web console button shows page errors",
       errors: 3,
       warnings: 0,
       callback: addErrors,
     });
@@ -235,19 +239,19 @@ function test() {
         // Get out of the toolbar event execution loop.
         executeSoon(options.callback);
       }
       return result;
     }
 
     if (!check()) {
       info("wait for: " + options.name);
-      DeveloperToolbar.on("errors-counter-updated", function onUpdate(event) {
+      toolbar.on("errors-counter-updated", function onUpdate(event) {
         if (check()) {
-          DeveloperToolbar.off(event, onUpdate);
+          toolbar.off(event, onUpdate);
         }
       });
     }
   }
 
   function openWebConsole(tab, callback) {
     let target = TargetFactory.forTab(tab);
     gDevTools.showToolbox(target, "webconsole").then((toolbox) =>
--- a/devtools/client/webconsole/hudservice.js
+++ b/devtools/client/webconsole/hudservice.js
@@ -2,16 +2,17 @@
  * 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/. */
 
 "use strict";
 
 var WebConsoleUtils = require("devtools/client/webconsole/utils").Utils;
 const {extend} = require("devtools/shared/extend");
 var {TargetFactory} = require("devtools/client/framework/target");
+var {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
 var {Tools} = require("devtools/client/definitions");
 const { Task } = require("devtools/shared/task");
 var promise = require("promise");
 var Services = require("Services");
 
 loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
 loader.lazyRequireGetter(this, "WebConsoleFrame", "devtools/client/webconsole/webconsole", true);
 loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
@@ -391,17 +392,18 @@ WebConsole.prototype = {
 
   /**
    * The clear output button handler.
    * @private
    */
   _onClearButton: function WC__onClearButton()
   {
     if (this.target.isLocalTab) {
-      this.browserWindow.DeveloperToolbar.resetErrorsCount(this.target.tab);
+      gDevToolsBrowser.getDeveloperToolbar(this.browserWindow)
+        .resetErrorsCount(this.target.tab);
     }
   },
 
   /**
    * Alias for the WebConsoleFrame.setFilterState() method.
    * @see webconsole.js::WebConsoleFrame.setFilterState()
    */
   setFilterState: function WC_setFilterState()