Bug 1336198 - Part 7: Refactor box model logic into box-model.js. r=jdescottes
☠☠ backed out by dbf5e2d59850 ☠ ☠
authorGabriel Luong <gabriel.luong@gmail.com>
Sun, 19 Feb 2017 22:52:01 -0500
changeset 372861 29efd4e3acf025dec21a0ead931379f288e0849d
parent 372860 03b3126da4af5941dcef7c6abb1f5ecd5873c053
child 372862 b2d689c41408b6e59660552f9cd2eb3ee03ff558
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)
reviewersjdescottes
bugs1336198
milestone54.0a1
Bug 1336198 - Part 7: Refactor box model logic into box-model.js. r=jdescottes
devtools/client/inspector/boxmodel/box-model.js
devtools/client/inspector/boxmodel/moz.build
devtools/client/inspector/inspector.js
devtools/client/inspector/layout/components/App.js
devtools/client/inspector/layout/layout.js
devtools/client/shared/browser-loader.js
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/boxmodel/box-model.js
@@ -0,0 +1,285 @@
+/* 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/. */
+
+"use strict";
+
+const { Task } = require("devtools/shared/task");
+const { getCssProperties } = require("devtools/shared/fronts/css-properties");
+const { ReflowFront } = require("devtools/shared/fronts/reflow");
+
+const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
+
+const { updateLayout } = require("./actions/box-model");
+
+const EditingSession = require("./utils/editing-session");
+
+const NUMERIC = /^-?[\d\.]+$/;
+
+/**
+ * A singleton instance of the box model controllers.
+ *
+ * @param  {Inspector} inspector
+ *         An instance of the Inspector currently loaded in the toolbox.
+ * @param  {Window} window
+ *         The document window of the toolbox.
+ */
+function BoxModel(inspector, window) {
+  this.document = window.document;
+  this.inspector = inspector;
+  this.store = inspector.store;
+
+  this.updateBoxModel = this.updateBoxModel.bind(this);
+
+  this.onHideBoxModelHighlighter = this.onHideBoxModelHighlighter.bind(this);
+  this.onNewSelection = this.onNewSelection.bind(this);
+  this.onShowBoxModelEditor = this.onShowBoxModelEditor.bind(this);
+  this.onShowBoxModelHighlighter = this.onShowBoxModelHighlighter.bind(this);
+  this.onSidebarSelect = this.onSidebarSelect.bind(this);
+
+  this.inspector.selection.on("new-node-front", this.onNewSelection);
+  this.inspector.sidebar.on("select", this.onSidebarSelect);
+}
+
+BoxModel.prototype = {
+
+  /**
+   * Destruction function called when the inspector is destroyed. Removes event listeners
+   * and cleans up references.
+   */
+  destroy() {
+    this.inspector.selection.off("new-node-front", this.onNewSelection);
+    this.inspector.sidebar.off("select", this.onSidebarSelect);
+
+    if (this.reflowFront) {
+      this.untrackReflows();
+      this.reflowFront.destroy();
+      this.reflowFront = null;
+    }
+
+    this.document = null;
+    this.inspector = null;
+    this.walker = null;
+  },
+
+  /**
+   * Returns an object containing the box model's handler functions used in the box
+   * model's React component props.
+   */
+  getComponentProps() {
+    return {
+      onHideBoxModelHighlighter: this.onHideBoxModelHighlighter,
+      onShowBoxModelEditor: this.onShowBoxModelEditor,
+      onShowBoxModelHighlighter: this.onShowBoxModelHighlighter,
+    };
+  },
+
+  /**
+   * Returns true if the layout panel is visible, and false otherwise.
+   */
+  isPanelVisible() {
+    return this.inspector.toolbox.currentToolId === "inspector" &&
+           this.inspector.sidebar &&
+           this.inspector.sidebar.getCurrentTabID() === "layoutview";
+  },
+
+  /**
+   * Returns true if the layout panel is visible and the current node is valid to
+   * be displayed in the view.
+   */
+  isPanelVisibleAndNodeValid() {
+    return this.isPanelVisible() &&
+           this.inspector.selection.isConnected() &&
+           this.inspector.selection.isElementNode();
+  },
+
+  /**
+   * Starts listening to reflows in the current tab.
+   */
+  trackReflows() {
+    if (!this.reflowFront) {
+      let { target } = this.inspector;
+      if (target.form.reflowActor) {
+        this.reflowFront = ReflowFront(target.client,
+                                       target.form);
+      } else {
+        return;
+      }
+    }
+
+    this.reflowFront.on("reflows", this.updateBoxModel);
+    this.reflowFront.start();
+  },
+
+  /**
+   * Stops listening to reflows in the current tab.
+   */
+  untrackReflows() {
+    if (!this.reflowFront) {
+      return;
+    }
+
+    this.reflowFront.off("reflows", this.updateBoxModel);
+    this.reflowFront.stop();
+  },
+
+  /**
+   * Updates the box model panel by dispatching the new layout data.
+   */
+  updateBoxModel() {
+    let lastRequest = Task.spawn((function* () {
+      if (!(this.isPanelVisible() &&
+          this.inspector.selection.isConnected() &&
+          this.inspector.selection.isElementNode())) {
+        return null;
+      }
+
+      let node = this.inspector.selection.nodeFront;
+      let layout = yield this.inspector.pageStyle.getLayout(node, {
+        autoMargins: true,
+      });
+      let styleEntries = yield this.inspector.pageStyle.getApplied(node, {});
+      this.elementRules = styleEntries.map(e => e.rule);
+
+      // Update the redux store with the latest layout properties and update the box
+      // model view.
+      this.store.dispatch(updateLayout(layout));
+
+      // If a subsequent request has been made, wait for that one instead.
+      if (this._lastRequest != lastRequest) {
+        return this._lastRequest;
+      }
+
+      this._lastRequest = null;
+
+      this.inspector.emit("boxmodel-view-updated");
+      return null;
+    }).bind(this)).catch(console.error);
+
+    this._lastRequest = lastRequest;
+  },
+
+  /**
+   * Selection 'new-node-front' event handler.
+   */
+  onNewSelection: function () {
+    if (!this.isPanelVisibleAndNodeValid()) {
+      return;
+    }
+
+    this.updateBoxModel();
+  },
+
+  /**
+   * Hides the box-model highlighter on the currently selected element.
+   */
+  onHideBoxModelHighlighter() {
+    let toolbox = this.inspector.toolbox;
+    toolbox.highlighterUtils.unhighlight();
+  },
+
+  /**
+   * Shows the inplace editor when a box model editable value is clicked on the
+   * box model panel.
+   *
+   * @param  {DOMNode} element
+   *         The element that was clicked.
+   * @param  {Event} event
+   *         The event object.
+   * @param  {String} property
+   *         The name of the property.
+   */
+  onShowBoxModelEditor(element, event, property) {
+    let session = new EditingSession({
+      inspector: this.inspector,
+      doc: this.document,
+      elementRules: this.elementRules,
+    });
+    let initialValue = session.getProperty(property);
+
+    let editor = new InplaceEditor({
+      element: element,
+      initial: initialValue,
+      contentType: InplaceEditor.CONTENT_TYPES.CSS_VALUE,
+      property: {
+        name: property
+      },
+      start: self => {
+        self.elt.parentNode.classList.add("boxmodel-editing");
+      },
+      change: value => {
+        if (NUMERIC.test(value)) {
+          value += "px";
+        }
+
+        let properties = [
+          { name: property, value: value }
+        ];
+
+        if (property.substring(0, 7) == "border-") {
+          let bprop = property.substring(0, property.length - 5) + "style";
+          let style = session.getProperty(bprop);
+          if (!style || style == "none" || style == "hidden") {
+            properties.push({ name: bprop, value: "solid" });
+          }
+        }
+
+        session.setProperties(properties).catch(e => console.error(e));
+      },
+      done: (value, commit) => {
+        editor.elt.parentNode.classList.remove("boxmodel-editing");
+        if (!commit) {
+          session.revert().then(() => {
+            session.destroy();
+          }, e => console.error(e));
+          return;
+        }
+
+        let node = this.inspector.selection.nodeFront;
+        this.inspector.pageStyle.getLayout(node, {
+          autoMargins: true,
+        }).then(layout => {
+          this.store.dispatch(updateLayout(layout));
+        }, e => console.error(e));
+      },
+      contextMenu: this.inspector.onTextBoxContextMenu,
+      cssProperties: getCssProperties(this.inspector.toolbox)
+    }, event);
+  },
+
+  /**
+   * Shows the box-model highlighter on the currently selected element.
+   *
+   * @param  {Object} options
+   *         Options passed to the highlighter actor.
+   */
+  onShowBoxModelHighlighter(options = {}) {
+    let toolbox = this.inspector.toolbox;
+    let nodeFront = this.inspector.selection.nodeFront;
+
+    toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
+  },
+
+  /**
+   * Handler for the inspector sidebar select event. Starts listening for
+   * "grid-layout-changed" if the layout panel is visible. Otherwise, stop
+   * listening for grid layout changes. Finally, refresh the layout view if
+   * it is visible.
+   */
+  onSidebarSelect() {
+    if (!this.isPanelVisible()) {
+      this.untrackReflows();
+      return;
+    }
+
+    if (this.inspector.selection.isConnected() &&
+        this.inspector.selection.isElementNode()) {
+      this.trackReflows();
+    }
+
+    this.updateBoxModel();
+  },
+
+};
+
+module.exports = BoxModel;
--- a/devtools/client/inspector/boxmodel/moz.build
+++ b/devtools/client/inspector/boxmodel/moz.build
@@ -7,10 +7,11 @@
 DIRS += [
     'actions',
     'components',
     'reducers',
     'utils',
 ]
 
 DevToolsModules(
+    'box-model.js',
     'types.js',
 )
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -18,16 +18,17 @@ var {Task} = require("devtools/shared/ta
 const {initCssProperties} = require("devtools/shared/fronts/css-properties");
 const nodeConstants = require("devtools/shared/dom-node-constants");
 const Telemetry = require("devtools/client/shared/telemetry");
 
 const Menu = require("devtools/client/framework/menu");
 const MenuItem = require("devtools/client/framework/menu-item");
 
 const {HTMLBreadcrumbs} = require("devtools/client/inspector/breadcrumbs");
+const BoxModel = require("devtools/client/inspector/boxmodel/box-model");
 const {ComputedViewTool} = require("devtools/client/inspector/computed/computed");
 const {FontInspector} = require("devtools/client/inspector/fonts/fonts");
 const {InspectorSearch} = require("devtools/client/inspector/inspector-search");
 const {RuleViewTool} = require("devtools/client/inspector/rules/rules");
 const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay");
 const {ToolSidebar} = require("devtools/client/inspector/toolsidebar");
 const MarkupView = require("devtools/client/inspector/markup/markup");
 const {CommandUtils} = require("devtools/client/shared/developer-toolbar");
@@ -568,16 +569,17 @@ Inspector.prototype = {
 
     this.sidebar.addExistingTab(
       "computedview",
       INSPECTOR_L10N.getStr("inspector.sidebar.computedViewTitle"),
       defaultTab == "computedview");
 
     this.ruleview = new RuleViewTool(this, this.panelWin);
     this.computedview = new ComputedViewTool(this, this.panelWin);
+    this.boxmodel = new BoxModel(this, this.panelWin);
 
     if (Services.prefs.getBoolPref("devtools.layoutview.enabled")) {
       const LayoutView = this.browserRequire("devtools/client/inspector/layout/layout");
       this.layoutview = new LayoutView(this, this.panelWin);
     }
 
     if (this.target.form.animationsActor) {
       this.sidebar.addFrameTab(
--- a/devtools/client/inspector/layout/components/App.js
+++ b/devtools/client/inspector/layout/components/App.js
@@ -6,19 +6,20 @@
 
 const { addons, createClass, createFactory, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 const { connect } = require("devtools/client/shared/vendor/react-redux");
 
 const { LocalizationHelper } = require("devtools/shared/l10n");
 
 const Accordion = createFactory(require("./Accordion"));
-const BoxModel = createFactory(require("./BoxModel"));
 const Grid = createFactory(require("./Grid"));
 
+const BoxModel = createFactory(require("devtools/client/inspector/boxmodel/components/BoxModel"));
+
 const Types = require("../types");
 const { getStr } = require("../utils/l10n");
 
 const BOXMODEL_STRINGS_URI = "devtools/client/locales/boxmodel.properties";
 const BOXMODEL_L10N = new LocalizationHelper(BOXMODEL_STRINGS_URI);
 
 const App = createClass({
 
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -1,180 +1,87 @@
 /* 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/. */
 
 "use strict";
 
 const Services = require("Services");
 const { Task } = require("devtools/shared/task");
-const { getCssProperties } = require("devtools/shared/fronts/css-properties");
-const { ReflowFront } = require("devtools/shared/fronts/reflow");
 
-const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
 const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 
 const {
-  updateLayout,
-} = require("./actions/box-model");
-const {
   updateGridHighlighted,
   updateGrids,
 } = require("./actions/grids");
 const {
   updateShowGridLineNumbers,
   updateShowInfiniteLines,
 } = require("./actions/highlighter-settings");
 
 const App = createFactory(require("./components/App"));
 
-const EditingSession = require("./utils/editing-session");
-
 const { LocalizationHelper } = require("devtools/shared/l10n");
 const INSPECTOR_L10N =
   new LocalizationHelper("devtools/client/locales/inspector.properties");
 
-const NUMERIC = /^-?[\d\.]+$/;
 const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
 const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
 
 function LayoutView(inspector, window) {
   this.document = window.document;
   this.highlighters = inspector.highlighters;
   this.inspector = inspector;
   this.store = inspector.store;
   this.walker = this.inspector.walker;
 
-  this.updateBoxModel = this.updateBoxModel.bind(this);
-
   this.onGridLayoutChange = this.onGridLayoutChange.bind(this);
   this.onHighlighterChange = this.onHighlighterChange.bind(this);
-  this.onNewSelection = this.onNewSelection.bind(this);
   this.onSidebarSelect = this.onSidebarSelect.bind(this);
 
   this.init();
 
   this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange);
   this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange);
-  this.inspector.selection.on("new-node-front", this.onNewSelection);
   this.inspector.sidebar.on("select", this.onSidebarSelect);
 }
 
 LayoutView.prototype = {
 
   /**
    * Initializes the layout view by fetching the LayoutFront from the walker, creating
    * the redux store and adding the view into the inspector sidebar.
    */
   init: Task.async(function* () {
     if (!this.inspector) {
       return;
     }
 
+    let {
+      onHideBoxModelHighlighter,
+      onShowBoxModelEditor,
+      onShowBoxModelHighlighter,
+    } = this.inspector.boxmodel.getComponentProps();
+
     this.layoutInspector = yield this.inspector.walker.getLayoutInspector();
 
     this.loadHighlighterSettings();
 
     let app = App({
       /**
        * Shows the box model properties under the box model if true, otherwise, hidden by
        * default.
        */
       showBoxModelProperties: true,
 
-      /**
-       * Hides the box-model highlighter on the currently selected element.
-       */
-      onHideBoxModelHighlighter: () => {
-        let toolbox = this.inspector.toolbox;
-        toolbox.highlighterUtils.unhighlight();
-      },
-
-      /**
-       * Shows the inplace editor when a box model editable value is clicked on the
-       * box model panel.
-       *
-       * @param  {DOMNode} element
-       *         The element that was clicked.
-       * @param  {Event} event
-       *         The event object.
-       * @param  {String} property
-       *         The name of the property.
-       */
-      onShowBoxModelEditor: (element, event, property) => {
-        let session = new EditingSession({
-          inspector: this.inspector,
-          doc: this.document,
-          elementRules: this.elementRules,
-        });
-        let initialValue = session.getProperty(property);
-
-        let editor = new InplaceEditor({
-          element: element,
-          initial: initialValue,
-          contentType: InplaceEditor.CONTENT_TYPES.CSS_VALUE,
-          property: {
-            name: property
-          },
-          start: self => {
-            self.elt.parentNode.classList.add("boxmodel-editing");
-          },
-          change: value => {
-            if (NUMERIC.test(value)) {
-              value += "px";
-            }
-
-            let properties = [
-              { name: property, value: value }
-            ];
-
-            if (property.substring(0, 7) == "border-") {
-              let bprop = property.substring(0, property.length - 5) + "style";
-              let style = session.getProperty(bprop);
-              if (!style || style == "none" || style == "hidden") {
-                properties.push({ name: bprop, value: "solid" });
-              }
-            }
-
-            session.setProperties(properties).catch(e => console.error(e));
-          },
-          done: (value, commit) => {
-            editor.elt.parentNode.classList.remove("boxmodel-editing");
-            if (!commit) {
-              session.revert().then(() => {
-                session.destroy();
-              }, e => console.error(e));
-              return;
-            }
-
-            let node = this.inspector.selection.nodeFront;
-            this.inspector.pageStyle.getLayout(node, {
-              autoMargins: true,
-            }).then(layout => {
-              this.store.dispatch(updateLayout(layout));
-            }, e => console.error(e));
-          },
-          contextMenu: this.inspector.onTextBoxContextMenu,
-          cssProperties: getCssProperties(this.inspector.toolbox)
-        }, event);
-      },
-
-      /**
-       * Shows the box-model highlighter on the currently selected element.
-       *
-       * @param  {Object} options
-       *         Options passed to the highlighter actor.
-       */
-      onShowBoxModelHighlighter: (options = {}) => {
-        let toolbox = this.inspector.toolbox;
-        let nodeFront = this.inspector.selection.nodeFront;
-
-        toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
-      },
+      onHideBoxModelHighlighter,
+      onShowBoxModelEditor,
+      onShowBoxModelHighlighter,
 
       /**
        * Handler for a change in the input checkboxes in the GridList component.
        * Toggles on/off the grid highlighter for the provided grid container element.
        *
        * @param  {NodeFront} node
        *         The NodeFront of the grid container element for which the grid
        *         highlighter is toggled on/off for.
@@ -248,26 +155,19 @@ LayoutView.prototype = {
 
   /**
    * Destruction function called when the inspector is destroyed. Removes event listeners
    * and cleans up references.
    */
   destroy() {
     this.highlighters.off("grid-highlighter-hidden", this.onHighlighterChange);
     this.highlighters.off("grid-highlighter-shown", this.onHighlighterChange);
-    this.inspector.selection.off("new-node-front", this.onNewSelection);
     this.inspector.sidebar.off("select", this.onSidebarSelect);
     this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
 
-    if (this.reflowFront) {
-      this.untrackReflows();
-      this.reflowFront.destroy();
-      this.reflowFront = null;
-    }
-
     this.document = null;
     this.inspector = null;
     this.layoutInspector = null;
     this.store = null;
     this.walker = null;
   },
 
   /**
@@ -275,105 +175,29 @@ LayoutView.prototype = {
    */
   isPanelVisible() {
     return this.inspector.toolbox.currentToolId === "inspector" &&
            this.inspector.sidebar &&
            this.inspector.sidebar.getCurrentTabID() === "layoutview";
   },
 
   /**
-   * Returns true if the layout panel is visible and the current node is valid to
-   * be displayed in the view.
-   */
-  isPanelVisibleAndNodeValid() {
-    return this.isPanelVisible() &&
-           this.inspector.selection.isConnected() &&
-           this.inspector.selection.isElementNode();
-  },
-
-  /**
    * Load the grid highligher display settings into the store from the stored preferences.
    */
   loadHighlighterSettings() {
     let { dispatch } = this.store;
 
     let showGridLineNumbers = Services.prefs.getBoolPref(SHOW_GRID_LINE_NUMBERS);
     let showInfinteLines = Services.prefs.getBoolPref(SHOW_INFINITE_LINES_PREF);
 
     dispatch(updateShowGridLineNumbers(showGridLineNumbers));
     dispatch(updateShowInfiniteLines(showInfinteLines));
   },
 
   /**
-   * Starts listening to reflows in the current tab.
-   */
-  trackReflows() {
-    if (!this.reflowFront) {
-      let { target } = this.inspector;
-      if (target.form.reflowActor) {
-        this.reflowFront = ReflowFront(target.client,
-                                       target.form);
-      } else {
-        return;
-      }
-    }
-
-    this.reflowFront.on("reflows", this.updateBoxModel);
-    this.reflowFront.start();
-  },
-
-  /**
-   * Stops listening to reflows in the current tab.
-   */
-  untrackReflows() {
-    if (!this.reflowFront) {
-      return;
-    }
-
-    this.reflowFront.off("reflows", this.updateBoxModel);
-    this.reflowFront.stop();
-  },
-
-  /**
-   * Updates the box model panel by dispatching the new layout data.
-   */
-  updateBoxModel() {
-    let lastRequest = Task.spawn((function* () {
-      if (!(this.isPanelVisible() &&
-          this.inspector.selection.isConnected() &&
-          this.inspector.selection.isElementNode())) {
-        return null;
-      }
-
-      let node = this.inspector.selection.nodeFront;
-      let layout = yield this.inspector.pageStyle.getLayout(node, {
-        autoMargins: true,
-      });
-      let styleEntries = yield this.inspector.pageStyle.getApplied(node, {});
-      this.elementRules = styleEntries.map(e => e.rule);
-
-      // Update the redux store with the latest layout properties and update the box
-      // model view.
-      this.store.dispatch(updateLayout(layout));
-
-      // If a subsequent request has been made, wait for that one instead.
-      if (this._lastRequest != lastRequest) {
-        return this._lastRequest;
-      }
-
-      this._lastRequest = null;
-
-      this.inspector.emit("boxmodel-view-updated");
-      return null;
-    }).bind(this)).catch(console.error);
-
-    this._lastRequest = lastRequest;
-  },
-
-  /**
    * Updates the grid panel by dispatching the new grid data. This is called when the
    * layout view becomes visible or the view needs to be updated with new grid data.
    *
    * @param {Array|null} gridFronts
    *        Optional array of all GridFront in the current page.
    */
   updateGridPanel: Task.async(function* (gridFronts) {
     // Stop refreshing if the inspector or store is already destroyed.
@@ -425,44 +249,26 @@ LayoutView.prototype = {
    *         is shown for.
    */
   onHighlighterChange(event, nodeFront) {
     let highlighted = event === "grid-highlighter-shown";
     this.store.dispatch(updateGridHighlighted(nodeFront, highlighted));
   },
 
   /**
-   * Selection 'new-node-front' event handler.
-   */
-  onNewSelection: function () {
-    if (!this.isPanelVisibleAndNodeValid()) {
-      return;
-    }
-
-    this.updateBoxModel();
-  },
-
-  /**
    * Handler for the inspector sidebar select event. Starts listening for
    * "grid-layout-changed" if the layout panel is visible. Otherwise, stop
    * listening for grid layout changes. Finally, refresh the layout view if
    * it is visible.
    */
   onSidebarSelect() {
     if (!this.isPanelVisible()) {
       this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
-      this.untrackReflows();
       return;
     }
 
-    if (this.inspector.selection.isConnected() &&
-        this.inspector.selection.isElementNode()) {
-      this.trackReflows();
-    }
-
     this.layoutInspector.on("grid-layout-changed", this.onGridLayoutChange);
-    this.updateBoxModel();
     this.updateGridPanel();
   },
 
 };
 
 module.exports = LayoutView;
--- a/devtools/client/shared/browser-loader.js
+++ b/devtools/client/shared/browser-loader.js
@@ -7,16 +7,17 @@ var Cu = Components.utils;
 const loaders = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
 const { devtools } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const { joinURI } = devtools.require("devtools/shared/path");
 const { assert } = devtools.require("devtools/shared/DevToolsUtils");
 const Services = devtools.require("Services");
 const { AppConstants } = devtools.require("resource://gre/modules/AppConstants.jsm");
 
 const BROWSER_BASED_DIRS = [
+  "resource://devtools/client/inspector/boxmodel",
   "resource://devtools/client/inspector/layout",
   "resource://devtools/client/jsonview",
   "resource://devtools/client/shared/vendor",
   "resource://devtools/client/shared/redux",
 ];
 
 const COMMON_LIBRARY_DIRS = [
   "resource://devtools/client/shared/vendor",