Backed out 8 changesets (bug 1336198) for devtool failures in browser_boxmodel.js
authorIris Hsiao <ihsiao@mozilla.com>
Mon, 20 Feb 2017 15:32:18 +0800
changeset 372872 dbf5e2d598506b33da4f66445622b7cf89b650b2
parent 372871 e96fb1e91da5facc18e89b3d04610aa0970dc975
child 372873 3f4226570a86d2ae7345245ecae8a722e56d3da0
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)
bugs1336198
milestone54.0a1
backs out148f39b53d9cdceaf32f1474b6bb7369f7cb1ea3
b2d689c41408b6e59660552f9cd2eb3ee03ff558
29efd4e3acf025dec21a0ead931379f288e0849d
03b3126da4af5941dcef7c6abb1f5ecd5873c053
c7101889b2ece5b7f5b67d27b31349258574dfd9
e00c4a1694c4736e5236a775e612b7c5595c872d
eca5d4226787156308d8767086a7a638637f1fee
9e507c03b6cd796b9543c3802d4c9c008b61716d
Backed out 8 changesets (bug 1336198) for devtool failures in browser_boxmodel.js Backed out changeset 148f39b53d9c (bug 1336198) Backed out changeset b2d689c41408 (bug 1336198) Backed out changeset 29efd4e3acf0 (bug 1336198) Backed out changeset 03b3126da4af (bug 1336198) Backed out changeset c7101889b2ec (bug 1336198) Backed out changeset e00c4a1694c4 (bug 1336198) Backed out changeset eca5d4226787 (bug 1336198) Backed out changeset 9e507c03b6cd (bug 1336198)
devtools/client/inspector/boxmodel/actions/box-model.js
devtools/client/inspector/boxmodel/actions/index.js
devtools/client/inspector/boxmodel/actions/moz.build
devtools/client/inspector/boxmodel/box-model.js
devtools/client/inspector/boxmodel/components/BoxModel.js
devtools/client/inspector/boxmodel/components/BoxModelApp.js
devtools/client/inspector/boxmodel/components/BoxModelEditable.js
devtools/client/inspector/boxmodel/components/BoxModelInfo.js
devtools/client/inspector/boxmodel/components/BoxModelMain.js
devtools/client/inspector/boxmodel/components/BoxModelProperties.js
devtools/client/inspector/boxmodel/components/ComputedProperty.js
devtools/client/inspector/boxmodel/components/moz.build
devtools/client/inspector/boxmodel/moz.build
devtools/client/inspector/boxmodel/reducers/box-model.js
devtools/client/inspector/boxmodel/reducers/moz.build
devtools/client/inspector/boxmodel/test/.eslintrc.js
devtools/client/inspector/boxmodel/test/browser.ini
devtools/client/inspector/boxmodel/test/browser_boxmodel.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_allproperties.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_bluronclick.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_border.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_stylerules.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_guides.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_navigation.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_rotate-labels-on-sides.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_sync.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_tooltips.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_update-after-navigation.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_update-after-reload.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_update-in-iframes.js
devtools/client/inspector/boxmodel/test/doc_boxmodel_iframe1.html
devtools/client/inspector/boxmodel/test/doc_boxmodel_iframe2.html
devtools/client/inspector/boxmodel/test/head.js
devtools/client/inspector/boxmodel/types.js
devtools/client/inspector/boxmodel/utils/editing-session.js
devtools/client/inspector/boxmodel/utils/moz.build
devtools/client/inspector/components/deprecated-box-model.js
devtools/client/inspector/components/moz.build
devtools/client/inspector/components/test/.eslintrc.js
devtools/client/inspector/components/test/browser.ini
devtools/client/inspector/components/test/browser_boxmodel.js
devtools/client/inspector/components/test/browser_boxmodel_editablemodel.js
devtools/client/inspector/components/test/browser_boxmodel_editablemodel_allproperties.js
devtools/client/inspector/components/test/browser_boxmodel_editablemodel_bluronclick.js
devtools/client/inspector/components/test/browser_boxmodel_editablemodel_border.js
devtools/client/inspector/components/test/browser_boxmodel_editablemodel_stylerules.js
devtools/client/inspector/components/test/browser_boxmodel_guides.js
devtools/client/inspector/components/test/browser_boxmodel_navigation.js
devtools/client/inspector/components/test/browser_boxmodel_rotate-labels-on-sides.js
devtools/client/inspector/components/test/browser_boxmodel_sync.js
devtools/client/inspector/components/test/browser_boxmodel_tooltips.js
devtools/client/inspector/components/test/browser_boxmodel_update-after-navigation.js
devtools/client/inspector/components/test/browser_boxmodel_update-after-reload.js
devtools/client/inspector/components/test/browser_boxmodel_update-in-iframes.js
devtools/client/inspector/components/test/doc_boxmodel_iframe1.html
devtools/client/inspector/components/test/doc_boxmodel_iframe2.html
devtools/client/inspector/components/test/head.js
devtools/client/inspector/computed/computed.js
devtools/client/inspector/computed/test/browser_computed_search-filter.js
devtools/client/inspector/computed/test/browser_computed_search-filter_clear.js
devtools/client/inspector/inspector.js
devtools/client/inspector/inspector.xhtml
devtools/client/inspector/layout/actions/box-model.js
devtools/client/inspector/layout/actions/index.js
devtools/client/inspector/layout/actions/moz.build
devtools/client/inspector/layout/components/App.js
devtools/client/inspector/layout/components/BoxModel.js
devtools/client/inspector/layout/components/BoxModelEditable.js
devtools/client/inspector/layout/components/BoxModelInfo.js
devtools/client/inspector/layout/components/BoxModelMain.js
devtools/client/inspector/layout/components/BoxModelProperties.js
devtools/client/inspector/layout/components/ComputedProperty.js
devtools/client/inspector/layout/components/moz.build
devtools/client/inspector/layout/layout.js
devtools/client/inspector/layout/reducers/box-model.js
devtools/client/inspector/layout/reducers/moz.build
devtools/client/inspector/layout/types.js
devtools/client/inspector/layout/utils/editing-session.js
devtools/client/inspector/layout/utils/moz.build
devtools/client/inspector/moz.build
devtools/client/inspector/reducers.js
devtools/client/inspector/test/browser_inspector_textbox-menu.js
devtools/client/jar.mn
devtools/client/shared/browser-loader.js
devtools/client/themes/deprecated-boxmodel.css
deleted file mode 100644
--- a/devtools/client/inspector/boxmodel/actions/index.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/* 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 { createEnum } = require("devtools/client/shared/enum");
-
-createEnum([
-
-  // Update the layout state with the latest layout properties.
-  "UPDATE_LAYOUT",
-
-], module.exports);
deleted file mode 100644
--- a/devtools/client/inspector/boxmodel/actions/moz.build
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-DevToolsModules(
-    'box-model.js',
-    'index.js',
-)
deleted file mode 100644
--- a/devtools/client/inspector/boxmodel/box-model.js
+++ /dev/null
@@ -1,291 +0,0 @@
-/* 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 computed or layout panel is visible, and false otherwise.
-   */
-  isPanelVisible() {
-    return this.inspector.toolbox.currentToolId === "inspector" &&
-           this.inspector.sidebar &&
-           (this.inspector.sidebar.getCurrentTabID() === "layoutview" ||
-            this.inspector.sidebar.getCurrentTabID() === "computedview");
-  },
-
-  /**
-   * 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;
-    }
-
-    if (this.inspector.selection.isConnected() &&
-        this.inspector.selection.isElementNode()) {
-      this.trackReflows();
-    }
-
-    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;
deleted file mode 100644
--- a/devtools/client/inspector/boxmodel/components/BoxModelApp.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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 { addons, createClass, createFactory, 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("devtools/client/inspector/layout/components/Accordion"));
-const BoxModel = createFactory(require("./BoxModel"));
-
-const Types = require("../types");
-
-const BOXMODEL_STRINGS_URI = "devtools/client/locales/boxmodel.properties";
-const BOXMODEL_L10N = new LocalizationHelper(BOXMODEL_STRINGS_URI);
-
-const BoxModelApp = createClass({
-
-  displayName: "BoxModelApp",
-
-  propTypes: {
-    boxModel: PropTypes.shape(Types.boxModel).isRequired,
-    showBoxModelProperties: PropTypes.bool.isRequired,
-    onHideBoxModelHighlighter: PropTypes.func.isRequired,
-    onShowBoxModelEditor: PropTypes.func.isRequired,
-    onShowBoxModelHighlighter: PropTypes.func.isRequired,
-  },
-
-  mixins: [ addons.PureRenderMixin ],
-
-  render() {
-    return Accordion({
-      items: [
-        {
-          header: BOXMODEL_L10N.getStr("boxmodel.title"),
-          component: BoxModel,
-          componentProps: this.props,
-          opened: true,
-        }
-      ]
-    });
-  },
-
-});
-
-module.exports = connect(state => state)(BoxModelApp);
deleted file mode 100644
--- a/devtools/client/inspector/boxmodel/components/moz.build
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-DevToolsModules(
-    'BoxModel.js',
-    'BoxModelApp.js',
-    'BoxModelEditable.js',
-    'BoxModelInfo.js',
-    'BoxModelMain.js',
-    'BoxModelProperties.js',
-    'ComputedProperty.js',
-)
deleted file mode 100644
--- a/devtools/client/inspector/boxmodel/moz.build
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-DIRS += [
-    'actions',
-    'components',
-    'reducers',
-    'utils',
-]
-
-DevToolsModules(
-    'box-model.js',
-    'types.js',
-)
-
-BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
deleted file mode 100644
--- a/devtools/client/inspector/boxmodel/reducers/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-DevToolsModules(
-    'box-model.js',
-)
deleted file mode 100644
--- a/devtools/client/inspector/boxmodel/types.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 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 { PropTypes } = require("devtools/client/shared/vendor/react");
-
-/**
- * The box model data for the current selected node.
- */
-exports.boxModel = {
-
-  // The layout information of the current selected node
-  layout: PropTypes.object,
-
-};
deleted file mode 100644
--- a/devtools/client/inspector/boxmodel/utils/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-DevToolsModules(
-    'editing-session.js',
-)
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/components/deprecated-box-model.js
@@ -0,0 +1,912 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/**
+ * THIS MODULE IS DEPRECATED.
+ *
+ * To continue any work related to the box model view, see the new react/redux
+ * implementation in devtools/client/inspector/layout/.
+ */
+
+"use strict";
+
+const {Task} = require("devtools/shared/task");
+const {InplaceEditor, editableItem} =
+      require("devtools/client/shared/inplace-editor");
+const {ReflowFront} = require("devtools/shared/fronts/reflow");
+const {LocalizationHelper} = require("devtools/shared/l10n");
+const {getCssProperties} = require("devtools/shared/fronts/css-properties");
+const {KeyCodes} = require("devtools/client/shared/keycodes");
+const EditingSession = require("devtools/client/inspector/layout/utils/editing-session");
+
+const STRINGS_URI = "devtools/client/locales/shared.properties";
+const STRINGS_INSPECTOR = "devtools/shared/locales/styleinspector.properties";
+const SHARED_L10N = new LocalizationHelper(STRINGS_URI);
+const INSPECTOR_L10N = new LocalizationHelper(STRINGS_INSPECTOR);
+const NUMERIC = /^-?[\d\.]+$/;
+const LONG_TEXT_ROTATE_LIMIT = 3;
+
+/**
+ * The box model view
+ * @param {InspectorPanel} inspector
+ *        An instance of the inspector-panel currently loaded in the toolbox
+ * @param {Document} document
+ *        The document that will contain the box model view.
+ */
+function BoxModelView(inspector, document) {
+  this.inspector = inspector;
+  this.doc = document;
+  this.wrapper = this.doc.getElementById("old-boxmodel-wrapper");
+  this.container = this.doc.getElementById("old-boxmodel-container");
+  this.expander = this.doc.getElementById("old-boxmodel-expander");
+  this.sizeLabel = this.doc.querySelector(".old-boxmodel-size > span");
+  this.sizeHeadingLabel = this.doc.getElementById("old-boxmodel-element-size");
+  this._geometryEditorHighlighter = null;
+  this._cssProperties = getCssProperties(inspector.toolbox);
+
+  this.init();
+}
+
+BoxModelView.prototype = {
+  init: function () {
+    this.update = this.update.bind(this);
+
+    this.onNewSelection = this.onNewSelection.bind(this);
+    this.inspector.selection.on("new-node-front", this.onNewSelection);
+
+    this.onNewNode = this.onNewNode.bind(this);
+    this.inspector.sidebar.on("computedview-selected", this.onNewNode);
+
+    this.onSidebarSelect = this.onSidebarSelect.bind(this);
+    this.inspector.sidebar.on("select", this.onSidebarSelect);
+
+    this.onToggleExpander = this.onToggleExpander.bind(this);
+    this.expander.addEventListener("click", this.onToggleExpander);
+    let header = this.doc.getElementById("old-boxmodel-header");
+    header.addEventListener("dblclick", this.onToggleExpander);
+
+    this.onFilterComputedView = this.onFilterComputedView.bind(this);
+    this.inspector.on("computed-view-filtered",
+      this.onFilterComputedView);
+
+    this.onPickerStarted = this.onPickerStarted.bind(this);
+    this.onMarkupViewLeave = this.onMarkupViewLeave.bind(this);
+    this.onMarkupViewNodeHover = this.onMarkupViewNodeHover.bind(this);
+    this.onWillNavigate = this.onWillNavigate.bind(this);
+    this.onKeyDown = this.onKeyDown.bind(this);
+    this.onLevelClick = this.onLevelClick.bind(this);
+    this.setAriaActive = this.setAriaActive.bind(this);
+    this.getEditBoxes = this.getEditBoxes.bind(this);
+    this.makeFocusable = this.makeFocusable.bind(this);
+    this.makeUnfocasable = this.makeUnfocasable.bind(this);
+    this.moveFocus = this.moveFocus.bind(this);
+    this.onFocus = this.onFocus.bind(this);
+
+    this.borderLayout = this.doc.getElementById("old-boxmodel-borders");
+    this.boxModel = this.doc.getElementById("old-boxmodel-wrapper");
+    this.marginLayout = this.doc.getElementById("old-boxmodel-margins");
+    this.paddingLayout = this.doc.getElementById("old-boxmodel-padding");
+
+    this.layouts = {
+      "margin": new Map([
+        [KeyCodes.DOM_VK_ESCAPE, this.marginLayout],
+        [KeyCodes.DOM_VK_DOWN, this.borderLayout],
+        [KeyCodes.DOM_VK_UP, null],
+        ["click", this.marginLayout]
+      ]),
+      "border": new Map([
+        [KeyCodes.DOM_VK_ESCAPE, this.borderLayout],
+        [KeyCodes.DOM_VK_DOWN, this.paddingLayout],
+        [KeyCodes.DOM_VK_UP, this.marginLayout],
+        ["click", this.borderLayout]
+      ]),
+      "padding": new Map([
+        [KeyCodes.DOM_VK_ESCAPE, this.paddingLayout],
+        [KeyCodes.DOM_VK_DOWN, null],
+        [KeyCodes.DOM_VK_UP, this.borderLayout],
+        ["click", this.paddingLayout]
+      ])
+    };
+
+    this.boxModel.addEventListener("click", this.onLevelClick, true);
+    this.boxModel.addEventListener("focus", this.onFocus, true);
+    this.boxModel.addEventListener("keydown", this.onKeyDown, true);
+
+    this.initBoxModelHighlighter();
+
+    // Store for the different dimensions of the node.
+    // 'selector' refers to the element that holds the value;
+    // 'property' is what we are measuring;
+    // 'value' is the computed dimension, computed in update().
+    this.map = {
+      position: {
+        selector: "#old-boxmodel-element-position",
+        property: "position",
+        value: undefined
+      },
+      marginTop: {
+        selector: ".old-boxmodel-margin.old-boxmodel-top > span",
+        property: "margin-top",
+        value: undefined
+      },
+      marginBottom: {
+        selector: ".old-boxmodel-margin.old-boxmodel-bottom > span",
+        property: "margin-bottom",
+        value: undefined
+      },
+      marginLeft: {
+        selector: ".old-boxmodel-margin.old-boxmodel-left > span",
+        property: "margin-left",
+        value: undefined
+      },
+      marginRight: {
+        selector: ".old-boxmodel-margin.old-boxmodel-right > span",
+        property: "margin-right",
+        value: undefined
+      },
+      paddingTop: {
+        selector: ".old-boxmodel-padding.old-boxmodel-top > span",
+        property: "padding-top",
+        value: undefined
+      },
+      paddingBottom: {
+        selector: ".old-boxmodel-padding.old-boxmodel-bottom > span",
+        property: "padding-bottom",
+        value: undefined
+      },
+      paddingLeft: {
+        selector: ".old-boxmodel-padding.old-boxmodel-left > span",
+        property: "padding-left",
+        value: undefined
+      },
+      paddingRight: {
+        selector: ".old-boxmodel-padding.old-boxmodel-right > span",
+        property: "padding-right",
+        value: undefined
+      },
+      borderTop: {
+        selector: ".old-boxmodel-border.old-boxmodel-top > span",
+        property: "border-top-width",
+        value: undefined
+      },
+      borderBottom: {
+        selector: ".old-boxmodel-border.old-boxmodel-bottom > span",
+        property: "border-bottom-width",
+        value: undefined
+      },
+      borderLeft: {
+        selector: ".old-boxmodel-border.old-boxmodel-left > span",
+        property: "border-left-width",
+        value: undefined
+      },
+      borderRight: {
+        selector: ".old-boxmodel-border.old-boxmodel-right > span",
+        property: "border-right-width",
+        value: undefined
+      }
+    };
+
+    // Make each element the dimensions editable
+    for (let i in this.map) {
+      if (i == "position") {
+        continue;
+      }
+
+      let dimension = this.map[i];
+      editableItem({
+        element: this.doc.querySelector(dimension.selector)
+      }, (element, event) => {
+        this.initEditor(element, event, dimension);
+      });
+    }
+
+    this.onNewNode();
+
+    let nodeGeometry = this.doc.getElementById("old-layout-geometry-editor");
+    this.onGeometryButtonClick = this.onGeometryButtonClick.bind(this);
+    nodeGeometry.addEventListener("click", this.onGeometryButtonClick);
+  },
+
+  initBoxModelHighlighter: function () {
+    let highlightElts = this.doc.querySelectorAll("#old-boxmodel-container *[title]");
+    this.onHighlightMouseOver = this.onHighlightMouseOver.bind(this);
+    this.onHighlightMouseOut = this.onHighlightMouseOut.bind(this);
+
+    for (let element of highlightElts) {
+      element.addEventListener("mouseover", this.onHighlightMouseOver, true);
+      element.addEventListener("mouseout", this.onHighlightMouseOut, true);
+    }
+  },
+
+  /**
+   * Start listening to reflows in the current tab.
+   */
+  trackReflows: function () {
+    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.update);
+    this.reflowFront.start();
+  },
+
+  /**
+   * Stop listening to reflows in the current tab.
+   */
+  untrackReflows: function () {
+    if (!this.reflowFront) {
+      return;
+    }
+
+    this.reflowFront.off("reflows", this.update);
+    this.reflowFront.stop();
+  },
+
+  /**
+   * Called when the user clicks on one of the editable values in the box model view
+   */
+  initEditor: function (element, event, dimension) {
+    let { property } = dimension;
+    let session = new EditingSession(this);
+    let initialValue = session.getProperty(property);
+
+    let editor = new InplaceEditor({
+      element: element,
+      initial: initialValue,
+      contentType: InplaceEditor.CONTENT_TYPES.CSS_VALUE,
+      property: {
+        name: dimension.property
+      },
+      start: self => {
+        self.elt.parentNode.classList.add("old-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("old-boxmodel-editing");
+        if (!commit) {
+          session.revert().then(() => {
+            session.destroy();
+          }, e => console.error(e));
+        }
+      },
+      contextMenu: this.inspector.onTextBoxContextMenu,
+      cssProperties: this._cssProperties
+    }, event);
+  },
+
+  /**
+   * Is the BoxModelView visible in the sidebar.
+   * @return {Boolean}
+   */
+  isViewVisible: function () {
+    return this.inspector &&
+           this.inspector.sidebar.getCurrentTabID() == "computedview";
+  },
+
+  /**
+   * Is the BoxModelView visible in the sidebar and is the current node valid to
+   * be displayed in the view.
+   * @return {Boolean}
+   */
+  isViewVisibleAndNodeValid: function () {
+    return this.isViewVisible() &&
+           this.inspector.selection.isConnected() &&
+           this.inspector.selection.isElementNode();
+  },
+
+  /**
+   * Destroy the nodes. Remove listeners.
+   */
+  destroy: function () {
+    let highlightElts = this.doc.querySelectorAll("#old-boxmodel-container *[title]");
+
+    for (let element of highlightElts) {
+      element.removeEventListener("mouseover", this.onHighlightMouseOver, true);
+      element.removeEventListener("mouseout", this.onHighlightMouseOut, true);
+    }
+
+    this.expander.removeEventListener("click", this.onToggleExpander);
+    let header = this.doc.getElementById("old-boxmodel-header");
+    header.removeEventListener("dblclick", this.onToggleExpander);
+
+    let nodeGeometry = this.doc.getElementById("old-layout-geometry-editor");
+    nodeGeometry.removeEventListener("click", this.onGeometryButtonClick);
+
+    this.boxModel.removeEventListener("click", this.onLevelClick, true);
+    this.boxModel.removeEventListener("focus", this.onFocus, true);
+    this.boxModel.removeEventListener("keydown", this.onKeyDown, true);
+
+    this.inspector.off("picker-started", this.onPickerStarted);
+
+    // Inspector Panel will destroy `markup` object on "will-navigate" event,
+    // therefore we have to check if it's still available in case BoxModelView
+    // is destroyed immediately after.
+    if (this.inspector.markup) {
+      this.inspector.markup.off("leave", this.onMarkupViewLeave);
+      this.inspector.markup.off("node-hover", this.onMarkupViewNodeHover);
+    }
+
+    this.inspector.sidebar.off("computedview-selected", this.onNewNode);
+    this.inspector.selection.off("new-node-front", this.onNewSelection);
+    this.inspector.sidebar.off("select", this.onSidebarSelect);
+    this.inspector.target.off("will-navigate", this.onWillNavigate);
+    this.inspector.off("computed-view-filtered", this.onFilterComputedView);
+
+    this.inspector = null;
+    this.doc = null;
+    this.wrapper = null;
+    this.container = null;
+    this.expander = null;
+    this.sizeLabel = null;
+    this.sizeHeadingLabel = null;
+
+    this.marginLayout = null;
+    this.borderLayout = null;
+    this.paddingLayout = null;
+    this.boxModel = null;
+    this.layouts = null;
+
+    if (this.reflowFront) {
+      this.untrackReflows();
+      this.reflowFront.destroy();
+      this.reflowFront = null;
+    }
+  },
+
+  /**
+   * Set initial box model focus to the margin layout.
+   */
+  onFocus: function () {
+    let activeDescendant = this.boxModel.getAttribute("aria-activedescendant");
+
+    if (!activeDescendant) {
+      let nextLayout = this.marginLayout;
+      this.setAriaActive(nextLayout);
+    }
+  },
+
+  /**
+   * Active aria-level set to current layout.
+   *
+   * @param {Element} nextLayout
+   *        Element of next layout that user has navigated to
+   * @param {Node} target
+   *        Node to be observed
+   */
+  setAriaActive: function (nextLayout, target) {
+    this.boxModel.setAttribute("aria-activedescendant", nextLayout.id);
+    if (target && target._editable) {
+      target.blur();
+    }
+
+    // Clear all
+    this.marginLayout.classList.remove("layout-active-elm");
+    this.borderLayout.classList.remove("layout-active-elm");
+    this.paddingLayout.classList.remove("layout-active-elm");
+
+    // Set the next level's border outline
+    nextLayout.classList.add("layout-active-elm");
+  },
+
+  /**
+   * Update aria-active on mouse click.
+   *
+   * @param {Event} event
+   *         The event triggered by a mouse click on the box model
+   */
+  onLevelClick: function (event) {
+    let {target} = event;
+    let nextLayout = this.layouts[target.getAttribute("data-box")].get("click");
+
+    this.setAriaActive(nextLayout, target);
+  },
+
+  /**
+   * Handle keyboard navigation and focus for box model layouts.
+   *
+   * Updates active layout on arrow key navigation
+   * Focuses next layout's editboxes on enter key
+   * Unfocuses current layout's editboxes when active layout changes
+   * Controls tabbing between editBoxes
+   *
+   * @param {Event} event
+   *         The event triggered by a keypress on the box model
+   */
+  onKeyDown: function (event) {
+    let {target, keyCode} = event;
+    // If focused on editable value or in editing mode
+    let isEditable = target._editable || target.editor;
+    let level = this.boxModel.getAttribute("aria-activedescendant");
+    let editingMode = target.tagName === "input";
+    let nextLayout;
+
+    switch (keyCode) {
+      case KeyCodes.DOM_VK_RETURN:
+        if (!isEditable) {
+          this.makeFocusable(level);
+        }
+        break;
+      case KeyCodes.DOM_VK_DOWN:
+      case KeyCodes.DOM_VK_UP:
+        if (!editingMode) {
+          event.preventDefault();
+          this.makeUnfocasable(level);
+          let datalevel = this.doc.getElementById(level).getAttribute("data-box");
+          nextLayout = this.layouts[datalevel].get(keyCode);
+          this.boxModel.focus();
+        }
+        break;
+      case KeyCodes.DOM_VK_TAB:
+        if (isEditable) {
+          event.preventDefault();
+          this.moveFocus(event, level);
+        }
+        break;
+      case KeyCodes.DOM_VK_ESCAPE:
+        if (isEditable && target._editable) {
+          event.preventDefault();
+          event.stopPropagation();
+          this.makeUnfocasable(level);
+          this.boxModel.focus();
+        }
+        break;
+      default:
+        break;
+    }
+
+    if (nextLayout) {
+      this.setAriaActive(nextLayout, target);
+    }
+  },
+
+  /**
+   * Make previous layout's elements unfocusable.
+   *
+   * @param {String} editLevel
+   *        The previous layout
+   */
+  makeUnfocasable: function (editLevel) {
+    let editBoxes = this.getEditBoxes(editLevel);
+    editBoxes.forEach(editBox => editBox.setAttribute("tabindex", "-1"));
+  },
+
+  /**
+   * Make current layout's elements focusable.
+   *
+   * @param {String} editLevel
+   *        The current layout
+   */
+  makeFocusable: function (editLevel) {
+    let editBoxes = this.getEditBoxes(editLevel);
+    editBoxes.forEach(editBox => editBox.setAttribute("tabindex", "0"));
+    editBoxes[0].focus();
+  },
+
+  /**
+   * Keyboard navigation of edit boxes wraps around on edge
+   * elements ([layout]-top, [layout]-left).
+   *
+   * @param {Node} target
+   *        Node to be observed
+   * @param {Boolean} shiftKey
+   *        Determines if shiftKey was pressed
+   * @param {String} level
+   *        Current active layout
+   */
+  moveFocus: function ({target, shiftKey}, level) {
+    let editBoxes = this.getEditBoxes(level);
+    let editingMode = target.tagName === "input";
+    // target.nextSibling is input field
+    let position = editingMode ? editBoxes.indexOf(target.nextSibling)
+                               : editBoxes.indexOf(target);
+
+    if (position === editBoxes.length - 1 && !shiftKey) {
+      position = 0;
+    } else if (position === 0 && shiftKey) {
+      position = editBoxes.length - 1;
+    } else {
+      shiftKey ? position-- : position++;
+    }
+
+    let editBox = editBoxes[position];
+    editBox.focus();
+
+    if (editingMode) {
+      editBox.click();
+    }
+  },
+
+  /**
+   * Retrieve edit boxes for current layout.
+   *
+   * @param {String} editLevel
+   *        Current active layout
+   * @return Layout's edit boxes
+   */
+  getEditBoxes: function (editLevel) {
+    let dataLevel = this.doc.getElementById(editLevel).getAttribute("data-box");
+    return [...this.doc.querySelectorAll(
+      `[data-box="${dataLevel}"].old-boxmodel-editable`)];
+  },
+
+  onSidebarSelect: function (e, sidebar) {
+    this.setActive(sidebar === "computedview");
+  },
+
+  /**
+   * Selection 'new-node-front' event handler.
+   */
+  onNewSelection: function () {
+    let done = this.inspector.updating("computed-view");
+    this.onNewNode()
+      .then(() => this.hideGeometryEditor())
+      .then(done, (err) => {
+        console.error(err);
+        done();
+      }).catch(console.error);
+  },
+
+  /**
+   * @return a promise that resolves when the view has been updated
+   */
+  onNewNode: function () {
+    this.setActive(this.isViewVisibleAndNodeValid());
+    return this.update();
+  },
+
+  onHighlightMouseOver: function (e) {
+    let region = e.target.getAttribute("data-box");
+    if (!region) {
+      return;
+    }
+
+    this.showBoxModel({
+      region,
+      showOnly: region,
+      onlyRegionArea: true
+    });
+  },
+
+  onHighlightMouseOut: function () {
+    this.hideBoxModel();
+  },
+
+  onGeometryButtonClick: function ({target}) {
+    if (target.hasAttribute("checked")) {
+      target.removeAttribute("checked");
+      this.hideGeometryEditor();
+    } else {
+      target.setAttribute("checked", "true");
+      this.showGeometryEditor();
+    }
+  },
+
+  onPickerStarted: function () {
+    this.hideGeometryEditor();
+  },
+
+  onToggleExpander: function () {
+    let isOpen = this.expander.hasAttribute("open");
+
+    if (isOpen) {
+      this.container.hidden = true;
+      this.expander.removeAttribute("open");
+    } else {
+      this.container.hidden = false;
+      this.expander.setAttribute("open", "");
+    }
+  },
+
+  onMarkupViewLeave: function () {
+    this.showGeometryEditor(true);
+  },
+
+  onMarkupViewNodeHover: function () {
+    this.hideGeometryEditor(false);
+  },
+
+  onWillNavigate: function () {
+    this._geometryEditorHighlighter.release().catch(console.error);
+    this._geometryEditorHighlighter = null;
+  },
+
+  /**
+   * Event handler that responds to the computed view being filtered
+   * @param {String} reason
+   * @param {Boolean} hidden
+   *        Whether or not to hide the box model wrapper
+   */
+  onFilterComputedView: function (reason, hidden) {
+    this.wrapper.hidden = hidden;
+  },
+
+  /**
+   * Stop tracking reflows and hide all values when no node is selected or the
+   * box model view is hidden, otherwise track reflows and show values.
+   * @param {Boolean} isActive
+   */
+  setActive: function (isActive) {
+    if (isActive === this.isActive) {
+      return;
+    }
+    this.isActive = isActive;
+
+    if (isActive) {
+      this.trackReflows();
+    } else {
+      this.untrackReflows();
+    }
+  },
+
+  /**
+   * Compute the dimensions of the node and update the values in
+   * the inspector.xul document.
+   * @return a promise that will be resolved when complete.
+   */
+  update: function () {
+    let lastRequest = Task.spawn((function* () {
+      if (!this.isViewVisibleAndNodeValid()) {
+        this.wrapper.hidden = true;
+        this.inspector.emit("boxmodel-view-updated");
+        return null;
+      }
+
+      let node = this.inspector.selection.nodeFront;
+      let layout = yield this.inspector.pageStyle.getLayout(node, {
+        autoMargins: this.isActive
+      });
+      let styleEntries = yield this.inspector.pageStyle.getApplied(node, {});
+
+      yield this.updateGeometryButton();
+
+      // If a subsequent request has been made, wait for that one instead.
+      if (this._lastRequest != lastRequest) {
+        return this._lastRequest;
+      }
+
+      this._lastRequest = null;
+      let width = layout.width;
+      let height = layout.height;
+      let newLabel = SHARED_L10N.getFormatStr("dimensions", width, height);
+
+      if (this.sizeHeadingLabel.textContent != newLabel) {
+        this.sizeHeadingLabel.textContent = newLabel;
+      }
+
+      for (let i in this.map) {
+        let property = this.map[i].property;
+        if (!(property in layout)) {
+          // Depending on the actor version, some properties
+          // might be missing.
+          continue;
+        }
+        let parsedValue = parseFloat(layout[property]);
+        if (Number.isNaN(parsedValue)) {
+          // Not a number. We use the raw string.
+          // Useful for "position" for example.
+          this.map[i].value = layout[property];
+        } else {
+          this.map[i].value = parsedValue;
+        }
+      }
+
+      let margins = layout.autoMargins;
+      if ("top" in margins) {
+        this.map.marginTop.value = "auto";
+      }
+      if ("right" in margins) {
+        this.map.marginRight.value = "auto";
+      }
+      if ("bottom" in margins) {
+        this.map.marginBottom.value = "auto";
+      }
+      if ("left" in margins) {
+        this.map.marginLeft.value = "auto";
+      }
+
+      for (let i in this.map) {
+        let selector = this.map[i].selector;
+        let span = this.doc.querySelector(selector);
+        this.updateSourceRuleTooltip(span, this.map[i].property, styleEntries);
+        if (span.textContent.length > 0 &&
+            span.textContent == this.map[i].value) {
+          continue;
+        }
+        span.textContent = this.map[i].value;
+        this.manageOverflowingText(span);
+      }
+
+      width -= this.map.borderLeft.value + this.map.borderRight.value +
+               this.map.paddingLeft.value + this.map.paddingRight.value;
+      width = parseFloat(width.toPrecision(6));
+      height -= this.map.borderTop.value + this.map.borderBottom.value +
+                this.map.paddingTop.value + this.map.paddingBottom.value;
+      height = parseFloat(height.toPrecision(6));
+
+      let newValue = width + "\u00D7" + height;
+      if (this.sizeLabel.textContent != newValue) {
+        this.sizeLabel.textContent = newValue;
+      }
+
+      this.elementRules = styleEntries.map(e => e.rule);
+
+      this.wrapper.hidden = false;
+
+      this.inspector.emit("boxmodel-view-updated");
+      return null;
+    }).bind(this)).catch(console.error);
+
+    this._lastRequest = lastRequest;
+    return this._lastRequest;
+  },
+
+  /**
+   * Update the text in the tooltip shown when hovering over a value to provide
+   * information about the source CSS rule that sets this value.
+   * @param {DOMNode} el The element that will receive the tooltip.
+   * @param {String} property The name of the CSS property for the tooltip.
+   * @param {Array} rules An array of applied rules retrieved by
+   * styleActor.getApplied.
+   */
+  updateSourceRuleTooltip: function (el, property, rules) {
+    // Dummy element used to parse the cssText of applied rules.
+    let dummyEl = this.doc.createElement("div");
+
+    // Rules are in order of priority so iterate until we find the first that
+    // defines a value for the property.
+    let sourceRule, value;
+    for (let {rule} of rules) {
+      dummyEl.style.cssText = rule.cssText;
+      value = dummyEl.style.getPropertyValue(property);
+      if (value !== "") {
+        sourceRule = rule;
+        break;
+      }
+    }
+
+    let title = property;
+    if (sourceRule && sourceRule.selectors) {
+      title += "\n" + sourceRule.selectors.join(", ");
+    }
+    if (sourceRule && sourceRule.parentStyleSheet) {
+      if (sourceRule.parentStyleSheet.href) {
+        title += "\n" + sourceRule.parentStyleSheet.href + ":" + sourceRule.line;
+      } else {
+        title += "\n" + INSPECTOR_L10N.getStr("rule.sourceInline") +
+          ":" + sourceRule.line;
+      }
+    }
+
+    el.setAttribute("title", title);
+  },
+
+  /**
+   * Show the box-model highlighter on the currently selected element
+   * @param {Object} options Options passed to the highlighter actor
+   */
+  showBoxModel: function (options = {}) {
+    let toolbox = this.inspector.toolbox;
+    let nodeFront = this.inspector.selection.nodeFront;
+
+    toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
+  },
+
+  /**
+   * Hide the box-model highlighter on the currently selected element
+   */
+  hideBoxModel: function () {
+    let toolbox = this.inspector.toolbox;
+
+    toolbox.highlighterUtils.unhighlight();
+  },
+
+  /**
+   * Show the geometry editor highlighter on the currently selected element
+   * @param {Boolean} [showOnlyIfActive=false]
+   *   Indicates if the Geometry Editor should be shown only if it's active but
+   *   hidden.
+   */
+  showGeometryEditor: function (showOnlyIfActive = false) {
+    let toolbox = this.inspector.toolbox;
+    let nodeFront = this.inspector.selection.nodeFront;
+    let nodeGeometry = this.doc.getElementById("old-layout-geometry-editor");
+    let isActive = nodeGeometry.hasAttribute("checked");
+
+    if (showOnlyIfActive && !isActive) {
+      return;
+    }
+
+    if (this._geometryEditorHighlighter) {
+      this._geometryEditorHighlighter.show(nodeFront).catch(console.error);
+      return;
+    }
+
+    // instantiate Geometry Editor highlighter
+    toolbox.highlighterUtils
+      .getHighlighterByType("GeometryEditorHighlighter").then(highlighter => {
+        highlighter.show(nodeFront).catch(console.error);
+        this._geometryEditorHighlighter = highlighter;
+
+        // Hide completely the geometry editor if the picker is clicked
+        toolbox.on("picker-started", this.onPickerStarted);
+
+        // Temporary hide the geometry editor
+        this.inspector.markup.on("leave", this.onMarkupViewLeave);
+        this.inspector.markup.on("node-hover", this.onMarkupViewNodeHover);
+
+        // Release the actor on will-navigate event
+        this.inspector.target.once("will-navigate", this.onWillNavigate);
+      });
+  },
+
+  /**
+   * Hide the geometry editor highlighter on the currently selected element
+   * @param {Boolean} [updateButton=true]
+   *   Indicates if the Geometry Editor's button needs to be unchecked too
+   */
+  hideGeometryEditor: function (updateButton = true) {
+    if (this._geometryEditorHighlighter) {
+      this._geometryEditorHighlighter.hide().catch(console.error);
+    }
+
+    if (updateButton) {
+      let nodeGeometry = this.doc.getElementById("old-layout-geometry-editor");
+      nodeGeometry.removeAttribute("checked");
+    }
+  },
+
+  /**
+   * Update the visibility and the state of the geometry editor button,
+   * based on the selected node.
+   */
+  updateGeometryButton: Task.async(function* () {
+    let node = this.inspector.selection.nodeFront;
+    let isEditable = false;
+
+    if (node) {
+      isEditable = yield this.inspector.pageStyle.isPositionEditable(node);
+    }
+
+    let nodeGeometry = this.doc.getElementById("old-layout-geometry-editor");
+    nodeGeometry.style.visibility = isEditable ? "visible" : "hidden";
+  }),
+
+  manageOverflowingText: function (span) {
+    let classList = span.parentNode.classList;
+
+    if (classList.contains("old-boxmodel-left") ||
+        classList.contains("old-boxmodel-right")) {
+      let force = span.textContent.length > LONG_TEXT_ROTATE_LIMIT;
+      classList.toggle("old-boxmodel-rotate", force);
+    }
+  }
+};
+
+module.exports = BoxModelView;
--- a/devtools/client/inspector/components/moz.build
+++ b/devtools/client/inspector/components/moz.build
@@ -1,10 +1,13 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
+    'deprecated-box-model.js',
     'inspector-tab-panel.css',
     'inspector-tab-panel.js',
 )
+
+BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
rename from devtools/client/inspector/boxmodel/test/.eslintrc.js
rename to devtools/client/inspector/components/test/.eslintrc.js
rename from devtools/client/inspector/boxmodel/test/browser.ini
rename to devtools/client/inspector/components/test/browser.ini
--- a/devtools/client/inspector/boxmodel/test/browser.ini
+++ b/devtools/client/inspector/components/test/browser.ini
@@ -8,35 +8,23 @@ support-files =
   !/devtools/client/commandline/test/helpers.js
   !/devtools/client/framework/test/shared-head.js
   !/devtools/client/inspector/test/head.js
   !/devtools/client/inspector/test/shared-head.js
   !/devtools/client/shared/test/test-actor.js
   !/devtools/client/shared/test/test-actor-registry.js
 
 [browser_boxmodel.js]
-skip-if = os == "linux" # Bug 1336198 Disabled for test timed out issues in linux
 [browser_boxmodel_editablemodel.js]
-skip-if = os == "linux" # Bug 1336198 Disabled for test timed out issues in linux
 # [browser_boxmodel_editablemodel_allproperties.js]
 # Disabled for too many intermittent failures (bug 1009322)
 [browser_boxmodel_editablemodel_bluronclick.js]
-skip-if = os == "linux" # Bug 1336198 Disabled for test timed out issues in linux
 [browser_boxmodel_editablemodel_border.js]
-skip-if = os == "linux" # Bug 1336198 Disabled for test timed out issues in linux
 [browser_boxmodel_editablemodel_stylerules.js]
-skip-if = os == "linux" # Bug 1336198 Disabled for test timed out issues in linux
 [browser_boxmodel_guides.js]
-skip-if = os == "linux" # Bug 1336198 Disabled for test timed out issues in linux
 [browser_boxmodel_navigation.js]
-skip-if = true # Bug 1336198
 [browser_boxmodel_rotate-labels-on-sides.js]
-skip-if = os == "linux" # Bug 1336198 Disabled for test timed out issues in linux
 [browser_boxmodel_sync.js]
-skip-if = os == "linux" # Bug 1336198 Disabled for test timed out issues in linux
 [browser_boxmodel_tooltips.js]
-skip-if = true # Bug 1336198
 [browser_boxmodel_update-after-navigation.js]
-skip-if = os == "linux" # Bug 1336198 Disabled for test timed out issues in linux
 [browser_boxmodel_update-after-reload.js]
-skip-if = os == "linux" # Bug 1336198 Disabled for test timed out issues in linux
 # [browser_boxmodel_update-in-iframes.js]
 # Bug 1020038 boxmodel-view updates for iframe elements changes
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel.js
rename to devtools/client/inspector/components/test/browser_boxmodel.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel.js
@@ -5,128 +5,128 @@
 "use strict";
 
 // Test that the box model displays the right values and that it updates when
 // the node's style is changed
 
 // Expected values:
 var res1 = [
   {
-    selector: ".boxmodel-element-size",
+    selector: "#old-boxmodel-element-size",
     value: "160" + "\u00D7" + "160.117"
   },
   {
-    selector: ".boxmodel-size > span",
+    selector: ".old-boxmodel-size > span",
     value: "100" + "\u00D7" + "100.117"
   },
   {
-    selector: ".boxmodel-margin.boxmodel-top > span",
+    selector: ".old-boxmodel-margin.old-boxmodel-top > span",
     value: 30
   },
   {
-    selector: ".boxmodel-margin.boxmodel-left > span",
+    selector: ".old-boxmodel-margin.old-boxmodel-left > span",
     value: "auto"
   },
   {
-    selector: ".boxmodel-margin.boxmodel-bottom > span",
+    selector: ".old-boxmodel-margin.old-boxmodel-bottom > span",
     value: 30
   },
   {
-    selector: ".boxmodel-margin.boxmodel-right > span",
+    selector: ".old-boxmodel-margin.old-boxmodel-right > span",
     value: "auto"
   },
   {
-    selector: ".boxmodel-padding.boxmodel-top > span",
+    selector: ".old-boxmodel-padding.old-boxmodel-top > span",
     value: 20
   },
   {
-    selector: ".boxmodel-padding.boxmodel-left > span",
+    selector: ".old-boxmodel-padding.old-boxmodel-left > span",
     value: 20
   },
   {
-    selector: ".boxmodel-padding.boxmodel-bottom > span",
+    selector: ".old-boxmodel-padding.old-boxmodel-bottom > span",
     value: 20
   },
   {
-    selector: ".boxmodel-padding.boxmodel-right > span",
+    selector: ".old-boxmodel-padding.old-boxmodel-right > span",
     value: 20
   },
   {
-    selector: ".boxmodel-border.boxmodel-top > span",
+    selector: ".old-boxmodel-border.old-boxmodel-top > span",
     value: 10
   },
   {
-    selector: ".boxmodel-border.boxmodel-left > span",
+    selector: ".old-boxmodel-border.old-boxmodel-left > span",
     value: 10
   },
   {
-    selector: ".boxmodel-border.boxmodel-bottom > span",
+    selector: ".old-boxmodel-border.old-boxmodel-bottom > span",
     value: 10
   },
   {
-    selector: ".boxmodel-border.boxmodel-right > span",
+    selector: ".old-boxmodel-border.old-boxmodel-right > span",
     value: 10
   },
 ];
 
 var res2 = [
   {
-    selector: ".boxmodel-element-size",
+    selector: "#old-boxmodel-element-size",
     value: "190" + "\u00D7" + "210"
   },
   {
-    selector: ".boxmodel-size > span",
+    selector: ".old-boxmodel-size > span",
     value: "100" + "\u00D7" + "150"
   },
   {
-    selector: ".boxmodel-margin.boxmodel-top > span",
+    selector: ".old-boxmodel-margin.old-boxmodel-top > span",
     value: 30
   },
   {
-    selector: ".boxmodel-margin.boxmodel-left > span",
+    selector: ".old-boxmodel-margin.old-boxmodel-left > span",
     value: "auto"
   },
   {
-    selector: ".boxmodel-margin.boxmodel-bottom > span",
+    selector: ".old-boxmodel-margin.old-boxmodel-bottom > span",
     value: 30
   },
   {
-    selector: ".boxmodel-margin.boxmodel-right > span",
+    selector: ".old-boxmodel-margin.old-boxmodel-right > span",
     value: "auto"
   },
   {
-    selector: ".boxmodel-padding.boxmodel-top > span",
+    selector: ".old-boxmodel-padding.old-boxmodel-top > span",
     value: 20
   },
   {
-    selector: ".boxmodel-padding.boxmodel-left > span",
+    selector: ".old-boxmodel-padding.old-boxmodel-left > span",
     value: 20
   },
   {
-    selector: ".boxmodel-padding.boxmodel-bottom > span",
+    selector: ".old-boxmodel-padding.old-boxmodel-bottom > span",
     value: 20
   },
   {
-    selector: ".boxmodel-padding.boxmodel-right > span",
+    selector: ".old-boxmodel-padding.old-boxmodel-right > span",
     value: 50
   },
   {
-    selector: ".boxmodel-border.boxmodel-top > span",
+    selector: ".old-boxmodel-border.old-boxmodel-top > span",
     value: 10
   },
   {
-    selector: ".boxmodel-border.boxmodel-left > span",
+    selector: ".old-boxmodel-border.old-boxmodel-left > span",
     value: 10
   },
   {
-    selector: ".boxmodel-border.boxmodel-bottom > span",
+    selector: ".old-boxmodel-border.old-boxmodel-bottom > span",
     value: 10
   },
   {
-    selector: ".boxmodel-border.boxmodel-right > span",
+    selector: ".old-boxmodel-border.old-boxmodel-right > span",
     value: 10
   },
 ];
 
 add_task(function* () {
   let style = "div { position: absolute; top: 42px; left: 42px; " +
               "height: 100.111px; width: 100px; border: 10px solid black; " +
               "padding: 20px; margin: 30px auto;}";
@@ -137,28 +137,28 @@ add_task(function* () {
   yield selectNode("div", inspector);
 
   yield testInitialValues(inspector, view);
   yield testChangingValues(inspector, view, testActor);
 });
 
 function* testInitialValues(inspector, view) {
   info("Test that the initial values of the box model are correct");
-  let viewdoc = view.document;
+  let viewdoc = view.doc;
 
   for (let i = 0; i < res1.length; i++) {
     let elt = viewdoc.querySelector(res1[i].selector);
     is(elt.textContent, res1[i].value,
        res1[i].selector + " has the right value.");
   }
 }
 
 function* testChangingValues(inspector, view, testActor) {
   info("Test that changing the document updates the box model");
-  let viewdoc = view.document;
+  let viewdoc = view.doc;
 
   let onUpdated = waitForUpdate(inspector);
   yield testActor.setAttribute("div", "style",
                                "height:150px;padding-right:50px;");
   yield onUpdated;
 
   for (let i = 0; i < res2.length; i++) {
     let elt = viewdoc.querySelector(res2[i].selector);
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel.js
rename to devtools/client/inspector/components/test/browser_boxmodel_editablemodel.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_editablemodel.js
@@ -31,164 +31,164 @@ add_task(function* () {
 function* testEditingMargins(inspector, view, testActor) {
   info("Test that editing margin dynamically updates the document, pressing " +
        "escape cancels the changes");
 
   is((yield getStyle(testActor, "#div1", "margin-top")), "",
      "Should be no margin-top on the element.");
   yield selectNode("#div1", inspector);
 
-  let span = view.document.querySelector(".boxmodel-margin.boxmodel-top > span");
+  let span = view.doc.querySelector(".old-boxmodel-margin.old-boxmodel-top > span");
   is(span.textContent, 5, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "5px", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("3", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("3", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is((yield getStyle(testActor, "#div1", "margin-top")), "3px",
      "Should have updated the margin.");
 
-  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is((yield getStyle(testActor, "#div1", "margin-top")), "",
      "Should be no margin-top on the element.");
   is(span.textContent, 5, "Should have the right value in the box model.");
 }
 
 function* testKeyBindings(inspector, view, testActor) {
   info("Test that arrow keys work correctly and pressing enter commits the " +
        "changes");
 
   is((yield getStyle(testActor, "#div1", "margin-left")), "",
      "Should be no margin-top on the element.");
   yield selectNode("#div1", inspector);
 
-  let span = view.document.querySelector(".boxmodel-margin.boxmodel-left > span");
+  let span = view.doc.querySelector(".old-boxmodel-margin.old-boxmodel-left > span");
   is(span.textContent, 10, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "10px", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("VK_UP", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_UP", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "11px", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "margin-left")), "11px",
      "Should have updated the margin.");
 
-  EventUtils.synthesizeKey("VK_DOWN", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_DOWN", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "10px", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "margin-left")), "10px",
      "Should have updated the margin.");
 
-  EventUtils.synthesizeKey("VK_UP", { shiftKey: true }, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_UP", { shiftKey: true }, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "20px", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "margin-left")), "20px",
      "Should have updated the margin.");
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
   is((yield getStyle(testActor, "#div1", "margin-left")), "20px",
      "Should be the right margin-top on the element.");
   is(span.textContent, 20, "Should have the right value in the box model.");
 }
 
 function* testEscapeToUndo(inspector, view, testActor) {
   info("Test that deleting the value removes the property but escape undoes " +
        "that");
 
   is((yield getStyle(testActor, "#div1", "margin-left")), "20px",
      "Should be the right margin-top on the element.");
   yield selectNode("#div1", inspector);
 
-  let span = view.document.querySelector(".boxmodel-margin.boxmodel-left > span");
+  let span = view.doc.querySelector(".old-boxmodel-margin.old-boxmodel-left > span");
   is(span.textContent, 20, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "20px", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("VK_DELETE", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_DELETE", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "margin-left")), "",
      "Should have updated the margin.");
 
-  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is((yield getStyle(testActor, "#div1", "margin-left")), "20px",
      "Should be the right margin-top on the element.");
   is(span.textContent, 20, "Should have the right value in the box model.");
 }
 
 function* testDeletingValue(inspector, view, testActor) {
   info("Test that deleting the value removes the property");
 
   yield setStyle(testActor, "#div1", "marginRight", "15px");
   yield waitForUpdate(inspector);
 
   yield selectNode("#div1", inspector);
 
-  let span = view.document.querySelector(".boxmodel-margin.boxmodel-right > span");
+  let span = view.doc.querySelector(".old-boxmodel-margin.old-boxmodel-right > span");
   is(span.textContent, 15, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "15px", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("VK_DELETE", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_DELETE", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "margin-right")), "",
      "Should have updated the margin.");
 
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
   is((yield getStyle(testActor, "#div1", "margin-right")), "",
      "Should be the right margin-top on the element.");
   is(span.textContent, 10, "Should have the right value in the box model.");
 }
 
 function* testRefocusingOnClick(inspector, view, testActor) {
   info("Test that clicking in the editor input does not remove focus");
 
   yield selectNode("#div4", inspector);
 
-  let span = view.document.querySelector(".boxmodel-margin.boxmodel-top > span");
+  let span = view.doc.querySelector(".old-boxmodel-margin.old-boxmodel-top > span");
   is(span.textContent, 1, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
 
   info("Click in the already opened editor input");
-  EventUtils.synthesizeMouseAtCenter(editor, {}, view.document.defaultView);
-  is(editor, view.document.activeElement,
+  EventUtils.synthesizeMouseAtCenter(editor, {}, view.doc.defaultView);
+  is(editor, view.doc.activeElement,
     "Inplace editor input should still have focus.");
 
   info("Check the input can still be used as expected");
-  EventUtils.synthesizeKey("VK_UP", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_UP", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "2px", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div4", "margin-top")), "2px",
      "Should have updated the margin.");
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
   is((yield getStyle(testActor, "#div4", "margin-top")), "2px",
      "Should be the right margin-top on the element.");
   is(span.textContent, 2, "Should have the right value in the box model.");
 }
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_allproperties.js
rename to devtools/client/inspector/components/test/browser_boxmodel_editablemodel_allproperties.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_allproperties.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_editablemodel_allproperties.js
@@ -27,120 +27,120 @@ add_task(function* () {
 function* testEditing(inspector, view, testActor) {
   info("When all properties are set on the node editing one should work");
 
   yield setStyle(testActor, "#div1", "padding", "5px");
   yield waitForUpdate(inspector);
 
   yield selectNode("#div1", inspector);
 
-  let span = view.document.querySelector(".boxmodel-padding.boxmodel-bottom > span");
+  let span = view.doc.querySelector(".old-boxmodel-padding.old-boxmodel-bottom > span");
   is(span.textContent, 5, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "5px", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("7", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("7", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "7", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "padding-bottom")), "7px",
      "Should have updated the padding");
 
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
   is((yield getStyle(testActor, "#div1", "padding-bottom")), "7px",
      "Should be the right padding.");
   is(span.textContent, 7, "Should have the right value in the box model.");
 }
 
 function* testEditingAndCanceling(inspector, view, testActor) {
   info("When all properties are set on the node editing one and then " +
        "cancelling with ESCAPE should work");
 
   yield setStyle(testActor, "#div1", "padding", "5px");
   yield waitForUpdate(inspector);
 
   yield selectNode("#div1", inspector);
 
-  let span = view.document.querySelector(".boxmodel-padding.boxmodel-left > span");
+  let span = view.doc.querySelector(".old-boxmodel-padding.old-boxmodel-left > span");
   is(span.textContent, 5, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "5px", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("8", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("8", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "8", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "padding-left")), "8px",
      "Should have updated the padding");
 
-  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is((yield getStyle(testActor, "#div1", "padding-left")), "5px",
      "Should be the right padding.");
   is(span.textContent, 5, "Should have the right value in the box model.");
 }
 
 function* testDeleting(inspector, view, testActor) {
   info("When all properties are set on the node deleting one should work");
 
   yield selectNode("#div1", inspector);
 
-  let span = view.document.querySelector(".boxmodel-padding.boxmodel-left > span");
+  let span = view.doc.querySelector(".old-boxmodel-padding.old-boxmodel-left > span");
   is(span.textContent, 5, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "5px", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("VK_DELETE", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_DELETE", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "padding-left")), "",
      "Should have updated the padding");
 
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
   is((yield getStyle(testActor, "#div1", "padding-left")), "",
      "Should be the right padding.");
   is(span.textContent, 3, "Should have the right value in the box model.");
 }
 
 function* testDeletingAndCanceling(inspector, view, testActor) {
   info("When all properties are set on the node deleting one then cancelling " +
        "should work");
 
   yield setStyle(testActor, "#div1", "padding", "5px");
   yield waitForUpdate(inspector);
 
   yield selectNode("#div1", inspector);
 
-  let span = view.document.querySelector(".boxmodel-padding.boxmodel-left > span");
+  let span = view.doc.querySelector(".old-boxmodel-padding.old-boxmodel-left > span");
   is(span.textContent, 5, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "5px", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("VK_DELETE", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_DELETE", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "padding-left")), "",
      "Should have updated the padding");
 
-  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is((yield getStyle(testActor, "#div1", "padding-left")), "5px",
      "Should be the right padding.");
   is(span.textContent, 5, "Should have the right value in the box model.");
 }
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_bluronclick.js
rename to devtools/client/inspector/components/test/browser_boxmodel_editablemodel_bluronclick.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_bluronclick.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_editablemodel_bluronclick.js
@@ -25,50 +25,50 @@ add_task(function* () {
 
   yield selectNode("#div1", inspector);
   yield testClickingOutsideEditor(view);
   yield testClickingBelowContainer(view);
 });
 
 function* testClickingOutsideEditor(view) {
   info("Test that clicking outside the editor blurs it");
-  let span = view.document.querySelector(".boxmodel-margin.boxmodel-top > span");
+  let span = view.doc.querySelector(".old-boxmodel-margin.old-boxmodel-top > span");
   is(span.textContent, 10, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
 
   info("Click next to the opened editor input.");
   let onBlur = once(editor, "blur");
   let rect = editor.getBoundingClientRect();
   EventUtils.synthesizeMouse(editor, rect.width + 10, rect.height / 2, {},
-    view.document.defaultView);
+    view.doc.defaultView);
   yield onBlur;
 
-  is(view.document.querySelector(".styleinspector-propertyeditor"), null,
+  is(view.doc.querySelector(".styleinspector-propertyeditor"), null,
     "Inplace editor has been removed.");
 }
 
 function* testClickingBelowContainer(view) {
   info("Test that clicking below the box-model container blurs it");
-  let span = view.document.querySelector(".boxmodel-margin.boxmodel-top > span");
+  let span = view.doc.querySelector(".old-boxmodel-margin.old-boxmodel-top > span");
   is(span.textContent, 10, "Should have the right value in the box model.");
 
-  info("Test that clicking below the boxmodel-container blurs the opened editor");
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  info("Test that clicking below the old-boxmodel-container blurs the opened editor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
 
   let onBlur = once(editor, "blur");
-  let container = view.document.querySelector(".boxmodel-container");
+  let container = view.doc.querySelector("#old-boxmodel-container");
   // Using getBoxQuads here because getBoundingClientRect (and therefore synthesizeMouse)
   // use an erroneous height of ~50px for the boxmodel-container.
   let bounds = container.getBoxQuads({relativeTo: view.doc})[0].bounds;
   EventUtils.synthesizeMouseAtPoint(
     bounds.left + 10,
     bounds.top + bounds.height + 10,
-    {}, view.document.defaultView);
+    {}, view.doc.defaultView);
   yield onBlur;
 
-  is(view.document.querySelector(".styleinspector-propertyeditor"), null,
+  is(view.doc.querySelector(".styleinspector-propertyeditor"), null,
     "Inplace editor has been removed.");
 }
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_border.js
rename to devtools/client/inspector/components/test/browser_boxmodel_editablemodel_border.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_border.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_editablemodel_border.js
@@ -19,34 +19,34 @@ add_task(function* () {
   let {inspector, view, testActor} = yield openBoxModelView();
 
   is((yield getStyle(testActor, "#div1", "border-top-width")), "",
      "Should have the right border");
   is((yield getStyle(testActor, "#div1", "border-top-style")), "",
      "Should have the right border");
   yield selectNode("#div1", inspector);
 
-  let span = view.document.querySelector(".boxmodel-border.boxmodel-top > span");
+  let span = view.doc.querySelector(".old-boxmodel-border.old-boxmodel-top > span");
   is(span.textContent, 0, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "0", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("1", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("1", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "1", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "border-top-width")), "1px",
      "Should have the right border");
   is((yield getStyle(testActor, "#div1", "border-top-style")), "solid",
      "Should have the right border");
 
-  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is((yield getStyle(testActor, "#div1", "border-top-width")), "",
      "Should be the right padding.");
   is((yield getStyle(testActor, "#div1", "border-top-style")), "",
      "Should have the right border");
   is(span.textContent, 0, "Should have the right value in the box model.");
 });
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_stylerules.js
rename to devtools/client/inspector/components/test/browser_boxmodel_editablemodel_stylerules.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_editablemodel_stylerules.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_editablemodel_stylerules.js
@@ -26,88 +26,88 @@ add_task(function* () {
 
 function* testUnits(inspector, view, testActor) {
   info("Test that entering units works");
 
   is((yield getStyle(testActor, "#div1", "padding-top")), "",
      "Should have the right padding");
   yield selectNode("#div1", inspector);
 
-  let span = view.document.querySelector(".boxmodel-padding.boxmodel-top > span");
+  let span = view.doc.querySelector(".old-boxmodel-padding.old-boxmodel-top > span");
   is(span.textContent, 3, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "3px", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("1", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("1", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
-  EventUtils.synthesizeKey("e", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("e", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is((yield getStyle(testActor, "#div1", "padding-top")), "",
      "An invalid value is handled cleanly");
 
-  EventUtils.synthesizeKey("m", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("m", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "1em", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div1", "padding-top")),
      "1em", "Should have updated the padding.");
 
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
   is((yield getStyle(testActor, "#div1", "padding-top")), "1em",
      "Should be the right padding.");
   is(span.textContent, 16, "Should have the right value in the box model.");
 }
 
 function* testValueComesFromStyleRule(inspector, view, testActor) {
   info("Test that we pick up the value from a higher style rule");
 
   is((yield getStyle(testActor, "#div2", "border-bottom-width")), "",
      "Should have the right border-bottom-width");
   yield selectNode("#div2", inspector);
 
-  let span = view.document.querySelector(".boxmodel-border.boxmodel-bottom > span");
+  let span = view.doc.querySelector(".old-boxmodel-border.old-boxmodel-bottom > span");
   is(span.textContent, 16, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "1em", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("0", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("0", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
 
   is(editor.value, "0", "Should have the right value in the editor.");
   is((yield getStyle(testActor, "#div2", "border-bottom-width")), "0px",
      "Should have updated the border.");
 
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
   is((yield getStyle(testActor, "#div2", "border-bottom-width")), "0px",
      "Should be the right border-bottom-width.");
   is(span.textContent, 0, "Should have the right value in the box model.");
 }
 
 function* testShorthandsAreParsed(inspector, view, testActor) {
   info("Test that shorthand properties are parsed correctly");
 
   is((yield getStyle(testActor, "#div3", "padding-right")), "",
      "Should have the right padding");
   yield selectNode("#div3", inspector);
 
-  let span = view.document.querySelector(".boxmodel-padding.boxmodel-right > span");
+  let span = view.doc.querySelector(".old-boxmodel-padding.old-boxmodel-right > span");
   is(span.textContent, 32, "Should have the right value in the box model.");
 
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
   ok(editor, "Should have opened the editor.");
   is(editor.value, "2em", "Should have the right value in the editor.");
 
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
   is((yield getStyle(testActor, "#div3", "padding-right")), "",
      "Should be the right padding.");
   is(span.textContent, 32, "Should have the right value in the box model.");
 }
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_guides.js
rename to devtools/client/inspector/components/test/browser_boxmodel_guides.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_guides.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_guides.js
@@ -23,26 +23,26 @@ add_task(function* () {
   yield selectNode("div", inspector);
 
   // Mock the highlighter by replacing the showBoxModel method.
   toolbox.highlighter.showBoxModel = function (nodeFront, options) {
     highlightedNodeFront = nodeFront;
     highlighterOptions = options;
   };
 
-  let elt = view.document.querySelector(".boxmodel-margins");
+  let elt = view.doc.getElementById("old-boxmodel-margins");
   yield testGuideOnLayoutHover(elt, "margin", inspector, view);
 
-  elt = view.document.querySelector(".boxmodel-borders");
+  elt = view.doc.getElementById("old-boxmodel-borders");
   yield testGuideOnLayoutHover(elt, "border", inspector, view);
 
-  elt = view.document.querySelector(".boxmodel-paddings");
+  elt = view.doc.getElementById("old-boxmodel-padding");
   yield testGuideOnLayoutHover(elt, "padding", inspector, view);
 
-  elt = view.document.querySelector(".boxmodel-content");
+  elt = view.doc.getElementById("old-boxmodel-content");
   yield testGuideOnLayoutHover(elt, "content", inspector, view);
 });
 
 function* testGuideOnLayoutHover(elt, expectedRegion, inspector) {
   info("Synthesizing mouseover on the boxmodel-view");
   EventUtils.synthesizeMouse(elt, 2, 2, {type: "mouseover"},
     elt.ownerDocument.defaultView);
 
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_navigation.js
rename to devtools/client/inspector/components/test/browser_boxmodel_navigation.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_navigation.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_navigation.js
@@ -24,80 +24,80 @@ add_task(function* () {
   yield testChangingLevels(inspector, view);
   yield testTabbingWrapAround(inspector, view);
   yield testChangingLevelsByClicking(inspector, view);
 });
 
 function* testInitialFocus(inspector, view) {
   info("Test that the focus is on margin layout.");
   let viewdoc = view.doc;
-  let boxmodel = viewdoc.getElementById("boxmodel-wrapper");
+  let boxmodel = viewdoc.getElementById("old-boxmodel-wrapper");
   boxmodel.focus();
   EventUtils.synthesizeKey("VK_RETURN", {});
 
-  is(boxmodel.getAttribute("aria-activedescendant"), "boxmodel-margins",
+  is(boxmodel.getAttribute("aria-activedescendant"), "old-boxmodel-margins",
     "Should be set to the margin layout.");
 }
 
 function* testChangingLevels(inspector, view) {
   info("Test that using arrow keys updates level.");
   let viewdoc = view.doc;
-  let boxmodel = viewdoc.getElementById("boxmodel-wrapper");
+  let boxmodel = viewdoc.getElementById("old-boxmodel-wrapper");
   boxmodel.focus();
   EventUtils.synthesizeKey("VK_RETURN", {});
   EventUtils.synthesizeKey("VK_ESCAPE", {});
 
   EventUtils.synthesizeKey("VK_DOWN", {});
-  is(boxmodel.getAttribute("aria-activedescendant"), "boxmodel-borders",
+  is(boxmodel.getAttribute("aria-activedescendant"), "old-boxmodel-borders",
     "Should be set to the border layout.");
 
   EventUtils.synthesizeKey("VK_DOWN", {});
-  is(boxmodel.getAttribute("aria-activedescendant"), "boxmodel-padding",
+  is(boxmodel.getAttribute("aria-activedescendant"), "old-boxmodel-padding",
     "Should be set to the padding layout.");
 
   EventUtils.synthesizeKey("VK_UP", {});
-  is(boxmodel.getAttribute("aria-activedescendant"), "boxmodel-borders",
+  is(boxmodel.getAttribute("aria-activedescendant"), "old-boxmodel-borders",
     "Should be set to the border layout.");
 
   EventUtils.synthesizeKey("VK_UP", {});
-  is(boxmodel.getAttribute("aria-activedescendant"), "boxmodel-margins",
+  is(boxmodel.getAttribute("aria-activedescendant"), "old-boxmodel-margins",
     "Should be set to the margin layout.");
 }
 
 function* testTabbingWrapAround(inspector, view) {
   info("Test that using arrow keys updates level.");
   let viewdoc = view.doc;
-  let boxmodel = viewdoc.getElementById("boxmodel-wrapper");
+  let boxmodel = viewdoc.getElementById("old-boxmodel-wrapper");
   boxmodel.focus();
   EventUtils.synthesizeKey("VK_RETURN", {});
 
   let editLevel = boxmodel.getAttribute("aria-activedescendant");
   let dataLevel = viewdoc.getElementById(editLevel).getAttribute("data-box");
   let editBoxes = [...viewdoc.querySelectorAll(
-    `[data-box="${dataLevel}"].boxmodel-editable`)];
+    `[data-box="${dataLevel}"].old-boxmodel-editable`)];
 
   EventUtils.synthesizeKey("VK_ESCAPE", {});
   editBoxes[3].focus();
   EventUtils.synthesizeKey("VK_TAB", {});
   is(editBoxes[0], viewdoc.activeElement, "Top edit box should have focus.");
 
   editBoxes[0].focus();
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true });
   is(editBoxes[3], viewdoc.activeElement, "Left edit box should have focus.");
 }
 
 function* testChangingLevelsByClicking(inspector, view) {
   info("Test that clicking on levels updates level.");
   let viewdoc = view.doc;
-  let boxmodel = viewdoc.getElementById("boxmodel-wrapper");
+  let boxmodel = viewdoc.getElementById("old-boxmodel-wrapper");
   boxmodel.focus();
 
-  let marginLayout = viewdoc.getElementById("boxmodel-margins");
-  let borderLayout = viewdoc.getElementById("boxmodel-borders");
-  let paddingLayout = viewdoc.getElementById("boxmodel-padding");
+  let marginLayout = viewdoc.getElementById("old-boxmodel-margins");
+  let borderLayout = viewdoc.getElementById("old-boxmodel-borders");
+  let paddingLayout = viewdoc.getElementById("old-boxmodel-padding");
   let layouts = [paddingLayout, borderLayout, marginLayout];
 
   layouts.forEach(layout => {
     layout.click();
     is(boxmodel.getAttribute("aria-activedescendant"), layout.id,
       "Should be set to" + layout.getAttribute("data-box") + "layout.");
   });
 }
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_rotate-labels-on-sides.js
rename to devtools/client/inspector/components/test/browser_boxmodel_rotate-labels-on-sides.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_rotate-labels-on-sides.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_rotate-labels-on-sides.js
@@ -2,28 +2,28 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test that longer values are rotated on the side
 
 const res1 = [
-  {selector: ".boxmodel-margin.boxmodel-top > span", value: 30},
-  {selector: ".boxmodel-margin.boxmodel-left > span", value: "auto"},
-  {selector: ".boxmodel-margin.boxmodel-bottom > span", value: 30},
-  {selector: ".boxmodel-margin.boxmodel-right > span", value: "auto"},
-  {selector: ".boxmodel-padding.boxmodel-top > span", value: 20},
-  {selector: ".boxmodel-padding.boxmodel-left > span", value: 2000000},
-  {selector: ".boxmodel-padding.boxmodel-bottom > span", value: 20},
-  {selector: ".boxmodel-padding.boxmodel-right > span", value: 20},
-  {selector: ".boxmodel-border.boxmodel-top > span", value: 10},
-  {selector: ".boxmodel-border.boxmodel-left > span", value: 10},
-  {selector: ".boxmodel-border.boxmodel-bottom > span", value: 10},
-  {selector: ".boxmodel-border.boxmodel-right > span", value: 10},
+  {selector: ".old-boxmodel-margin.old-boxmodel-top > span", value: 30},
+  {selector: ".old-boxmodel-margin.old-boxmodel-left > span", value: "auto"},
+  {selector: ".old-boxmodel-margin.old-boxmodel-bottom > span", value: 30},
+  {selector: ".old-boxmodel-margin.old-boxmodel-right > span", value: "auto"},
+  {selector: ".old-boxmodel-padding.old-boxmodel-top > span", value: 20},
+  {selector: ".old-boxmodel-padding.old-boxmodel-left > span", value: 2000000},
+  {selector: ".old-boxmodel-padding.old-boxmodel-bottom > span", value: 20},
+  {selector: ".old-boxmodel-padding.old-boxmodel-right > span", value: 20},
+  {selector: ".old-boxmodel-border.old-boxmodel-top > span", value: 10},
+  {selector: ".old-boxmodel-border.old-boxmodel-left > span", value: 10},
+  {selector: ".old-boxmodel-border.old-boxmodel-bottom > span", value: 10},
+  {selector: ".old-boxmodel-border.old-boxmodel-right > span", value: 10},
 ];
 
 const TEST_URI = encodeURIComponent([
   "<style>",
   "div { border:10px solid black; padding: 20px 20px 20px 2000000px; " +
   "margin: 30px auto; }",
   "</style>",
   "<div></div>"
@@ -31,19 +31,19 @@ const TEST_URI = encodeURIComponent([
 const LONG_TEXT_ROTATE_LIMIT = 3;
 
 add_task(function* () {
   yield addTab("data:text/html," + TEST_URI);
   let {inspector, view} = yield openBoxModelView();
   yield selectNode("div", inspector);
 
   for (let i = 0; i < res1.length; i++) {
-    let elt = view.document.querySelector(res1[i].selector);
+    let elt = view.doc.querySelector(res1[i].selector);
     let isLong = elt.textContent.length > LONG_TEXT_ROTATE_LIMIT;
     let classList = elt.parentNode.classList;
-    let canBeRotated = classList.contains("boxmodel-left") ||
-                       classList.contains("boxmodel-right");
-    let isRotated = classList.contains("boxmodel-rotate");
+    let canBeRotated = classList.contains("old-boxmodel-left") ||
+                       classList.contains("old-boxmodel-right");
+    let isRotated = classList.contains("old-boxmodel-rotate");
 
     is(canBeRotated && isLong,
       isRotated, res1[i].selector + " correctly rotated.");
   }
 });
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_sync.js
rename to devtools/client/inspector/components/test/browser_boxmodel_sync.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_sync.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_sync.js
@@ -12,24 +12,24 @@ add_task(function* () {
   yield addTab("data:text/html," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openBoxModelView();
 
   info("When a property is edited, it should sync in the rule view");
 
   yield selectNode("p", inspector);
 
   info("Modify padding-bottom in box model view");
-  let span = view.document.querySelector(".boxmodel-padding.boxmodel-bottom > span");
-  EventUtils.synthesizeMouseAtCenter(span, {}, view.document.defaultView);
-  let editor = view.document.querySelector(".styleinspector-propertyeditor");
+  let span = view.doc.querySelector(".old-boxmodel-padding.old-boxmodel-bottom > span");
+  EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
+  let editor = view.doc.querySelector(".styleinspector-propertyeditor");
 
-  EventUtils.synthesizeKey("7", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("7", {}, view.doc.defaultView);
   yield waitForUpdate(inspector);
   is(editor.value, "7", "Should have the right value in the editor.");
-  EventUtils.synthesizeKey("VK_RETURN", {}, view.document.defaultView);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
   let onRuleViewRefreshed = once(inspector, "rule-view-refreshed");
   let onRuleViewSelected = once(inspector.sidebar, "ruleview-selected");
   info("Select the rule view and check that the property was synced there");
   let ruleView = selectRuleView(inspector);
 
   info("Wait for the rule view to be selected");
   yield onRuleViewSelected;
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_tooltips.js
rename to devtools/client/inspector/components/test/browser_boxmodel_tooltips.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_tooltips.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_tooltips.js
@@ -71,49 +71,49 @@ const VALUES_TEST_DATA = [{
 }];
 
 add_task(function* () {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openBoxModelView();
 
   info("Checking the regions tooltips");
 
-  ok(view.document.querySelector(".boxmodel-margins").hasAttribute("title"),
+  ok(view.doc.querySelector("#old-boxmodel-margins").hasAttribute("title"),
     "The margin region has a tooltip");
-  is(view.document.querySelector(".boxmodel-margins").getAttribute("title"), "margin",
+  is(view.doc.querySelector("#old-boxmodel-margins").getAttribute("title"), "margin",
     "The margin region has the correct tooltip content");
 
-  ok(view.document.querySelector(".boxmodel-borders").hasAttribute("title"),
+  ok(view.doc.querySelector("#old-boxmodel-borders").hasAttribute("title"),
     "The border region has a tooltip");
-  is(view.document.querySelector(".boxmodel-borders").getAttribute("title"), "border",
+  is(view.doc.querySelector("#old-boxmodel-borders").getAttribute("title"), "border",
     "The border region has the correct tooltip content");
 
-  ok(view.document.querySelector(".boxmodel-paddings").hasAttribute("title"),
+  ok(view.doc.querySelector("#old-boxmodel-padding").hasAttribute("title"),
     "The padding region has a tooltip");
-  is(view.document.querySelector(".boxmodel-paddings").getAttribute("title"), "padding",
+  is(view.doc.querySelector("#old-boxmodel-padding").getAttribute("title"), "padding",
     "The padding region has the correct tooltip content");
 
-  ok(view.document.querySelector(".boxmodel-content").hasAttribute("title"),
+  ok(view.doc.querySelector("#old-boxmodel-content").hasAttribute("title"),
     "The content region has a tooltip");
-  is(view.document.querySelector(".boxmodel-content").getAttribute("title"), "content",
+  is(view.doc.querySelector("#old-boxmodel-content").getAttribute("title"), "content",
     "The content region has the correct tooltip content");
 
   for (let {selector, values} of VALUES_TEST_DATA) {
     info("Selecting " + selector + " and checking the values tooltips");
     yield selectNode(selector, inspector);
 
     info("Iterate over all values");
     for (let key in view.map) {
       if (key === "position") {
         continue;
       }
 
       let name = view.map[key].property;
       let expectedTooltipData = values.find(o => o.name === name);
-      let el = view.document.querySelector(view.map[key].selector);
+      let el = view.doc.querySelector(view.map[key].selector);
 
       ok(el.hasAttribute("title"), "The " + name + " value has a tooltip");
 
       if (expectedTooltipData) {
         info("The " + name + " value comes from a css rule");
         let expectedTooltip = name + "\n" + expectedTooltipData.ruleSelector +
                               "\n" + expectedTooltipData.styleSheetLocation;
         is(el.getAttribute("title"), expectedTooltip, "The tooltip is correct");
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_update-after-navigation.js
rename to devtools/client/inspector/components/test/browser_boxmodel_update-after-navigation.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_update-after-navigation.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_update-after-navigation.js
@@ -27,61 +27,64 @@ add_task(function* () {
   yield inspector.once("markuploaded");
 
   yield testBackToFirstPage(inspector, view, testActor);
 });
 
 function* testFirstPage(inspector, view, testActor) {
   info("Test that the box model view works on the first page");
 
+  info("Selecting the test node");
   yield selectNode("p", inspector);
 
   info("Checking that the box model view shows the right value");
-  let paddingElt = view.document.querySelector(
-    ".boxmodel-padding.boxmodel-top > span");
+  let paddingElt = view.doc.querySelector(
+    ".old-boxmodel-padding.old-boxmodel-top > span");
   is(paddingElt.textContent, "50");
 
   info("Listening for box model view changes and modifying the padding");
   let onUpdated = waitForUpdate(inspector);
   yield setStyle(testActor, "p", "padding", "20px");
   yield onUpdated;
   ok(true, "Box model view got updated");
 
   info("Checking that the box model view shows the right value after update");
   is(paddingElt.textContent, "20");
 }
 
 function* testSecondPage(inspector, view, testActor) {
   info("Test that the box model view works on the second page");
 
+  info("Selecting the test node");
   yield selectNode("p", inspector);
 
   info("Checking that the box model view shows the right value");
-  let sizeElt = view.document.querySelector(".boxmodel-size > span");
+  let sizeElt = view.doc.querySelector(".old-boxmodel-size > span");
   is(sizeElt.textContent, "100" + "\u00D7" + "100");
 
   info("Listening for box model view changes and modifying the size");
   let onUpdated = waitForUpdate(inspector);
   yield setStyle(testActor, "p", "width", "200px");
   yield onUpdated;
   ok(true, "Box model view got updated");
 
   info("Checking that the box model view shows the right value after update");
   is(sizeElt.textContent, "200" + "\u00D7" + "100");
 }
 
 function* testBackToFirstPage(inspector, view, testActor) {
   info("Test that the box model view works on the first page after going back");
 
+  info("Selecting the test node");
   yield selectNode("p", inspector);
 
   info("Checking that the box model view shows the right value, which is the" +
     "modified value from step one because of the bfcache");
-  let paddingElt = view.document.querySelector(
-    ".boxmodel-padding.boxmodel-top > span");
+  let paddingElt = view.doc.querySelector(
+    ".old-boxmodel-padding.old-boxmodel-top > span");
   is(paddingElt.textContent, "20");
 
   info("Listening for box model view changes and modifying the padding");
   let onUpdated = waitForUpdate(inspector);
   yield setStyle(testActor, "p", "padding", "100px");
   yield onUpdated;
   ok(true, "Box model view got updated");
 
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_update-after-reload.js
rename to devtools/client/inspector/components/test/browser_boxmodel_update-after-reload.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_update-after-reload.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_update-after-reload.js
@@ -17,21 +17,22 @@ add_task(function* () {
   yield testActor.reload();
   yield inspector.once("markuploaded");
 
   info("Test that the box model view works on the reloaded page");
   yield assertBoxModelView(inspector, view, testActor);
 });
 
 function* assertBoxModelView(inspector, view, testActor) {
+  info("Selecting the test node");
   yield selectNode("p", inspector);
 
   info("Checking that the box model view shows the right value");
-  let paddingElt = view.document.querySelector(
-    ".boxmodel-padding.boxmodel-top > span");
+  let paddingElt = view.doc.querySelector(
+    ".old-boxmodel-padding.old-boxmodel-top > span");
   is(paddingElt.textContent, "50");
 
   info("Listening for box model view changes and modifying the padding");
   let onUpdated = waitForUpdate(inspector);
   yield setStyle(testActor, "p", "padding", "20px");
   yield onUpdated;
   ok(true, "Box model view got updated");
 
rename from devtools/client/inspector/boxmodel/test/browser_boxmodel_update-in-iframes.js
rename to devtools/client/inspector/components/test/browser_boxmodel_update-in-iframes.js
--- a/devtools/client/inspector/boxmodel/test/browser_boxmodel_update-in-iframes.js
+++ b/devtools/client/inspector/components/test/browser_boxmodel_update-in-iframes.js
@@ -17,17 +17,17 @@ add_task(function* () {
 
 function* testResizingInIframe(inspector, view, testActor) {
   info("Test that resizing an element in an iframe updates its box model");
 
   info("Selecting the nested test node");
   yield selectNodeInIframe2("div", inspector);
 
   info("Checking that the box model view shows the right value");
-  let sizeElt = view.document.querySelector(".boxmodel-size > span");
+  let sizeElt = view.doc.querySelector(".old-boxmodel-size > span");
   is(sizeElt.textContent, "400\u00D7200");
 
   info("Listening for box model view changes and modifying its size");
   let onUpdated = waitForUpdate(inspector);
   yield setStyleInIframe2(testActor, "div", "width", "200px");
   yield onUpdated;
   ok(true, "Box model view got updated");
 
@@ -42,17 +42,17 @@ function* testReflowsAfterIframeDeletion
   info("Deleting the iframe2");
   yield removeIframe2(testActor);
   yield inspector.once("inspector-updated");
 
   info("Selecting the test node in iframe1");
   yield selectNodeInIframe1("p", inspector);
 
   info("Checking that the box model view shows the right value");
-  let sizeElt = view.document.querySelector(".boxmodel-size > span");
+  let sizeElt = view.doc.querySelector(".old-boxmodel-size > span");
   is(sizeElt.textContent, "100\u00D7100");
 
   info("Listening for box model view changes and modifying its size");
   let onUpdated = waitForUpdate(inspector);
   yield setStyleInIframe1(testActor, "p", "width", "200px");
   yield onUpdated;
   ok(true, "Box model view got updated");
 
rename from devtools/client/inspector/boxmodel/test/doc_boxmodel_iframe1.html
rename to devtools/client/inspector/components/test/doc_boxmodel_iframe1.html
rename from devtools/client/inspector/boxmodel/test/doc_boxmodel_iframe2.html
rename to devtools/client/inspector/components/test/doc_boxmodel_iframe2.html
rename from devtools/client/inspector/boxmodel/test/head.js
rename to devtools/client/inspector/components/test/head.js
--- a/devtools/client/inspector/boxmodel/test/head.js
+++ b/devtools/client/inspector/components/test/head.js
@@ -53,17 +53,17 @@ function openBoxModelView() {
         return promise.resolve();
       };
     }
     mockHighlighter(data.toolbox);
 
     return {
       toolbox: data.toolbox,
       inspector: data.inspector,
-      view: data.inspector.computedview,
+      view: data.inspector.computedview.boxModelView,
       testActor: data.testActor
     };
   });
 }
 
 /**
  * Wait for the boxmodel-view-updated event.
  * @return a promise
@@ -80,19 +80,8 @@ function getStyle(testActor, selector, p
 }
 
 function setStyle(testActor, selector, propertyName, value) {
   return testActor.eval(`
     content.document.querySelector("${selector}")
                     .style.${propertyName} = "${value}";
   `);
 }
-
-/**
- * The box model doesn't participate in the inspector's update mechanism, so simply
- * calling the default selectNode isn't enough to guarantee that the box model view has
- * finished updating. We also need to wait for the "boxmodel-view-updated" event.
- */
-var _selectNode = selectNode;
-selectNode = function* (node, inspector, reason) {
-  yield _selectNode(node, inspector, reason);
-  yield waitForUpdate(inspector);
-};
--- a/devtools/client/inspector/computed/computed.js
+++ b/devtools/client/inspector/computed/computed.js
@@ -21,24 +21,19 @@ const {
   VIEW_NODE_SELECTOR_TYPE,
   VIEW_NODE_PROPERTY_TYPE,
   VIEW_NODE_VALUE_TYPE,
   VIEW_NODE_IMAGE_URL_TYPE,
 } = require("devtools/client/inspector/shared/node-types");
 const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
 const TooltipsOverlay = require("devtools/client/inspector/shared/tooltips-overlay");
 const KeyShortcuts = require("devtools/client/shared/key-shortcuts");
+const BoxModelView = require("devtools/client/inspector/components/deprecated-box-model");
 const clipboardHelper = require("devtools/shared/platform/clipboard");
 
-const { createElement, createFactory } = require("devtools/client/shared/vendor/react");
-const ReactDOM = require("devtools/client/shared/vendor/react-dom");
-const { Provider } = require("devtools/client/shared/vendor/react-redux");
-
-const BoxModelApp = createFactory(require("devtools/client/inspector/boxmodel/components/BoxModelApp"));
-
 const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
 
 const PREF_ORIG_SOURCES = "devtools.styleeditor.source-maps-enabled";
 
 const FILTER_CHANGED_TIMEOUT = 150;
 const HTML_NS = "http://www.w3.org/1999/xhtml";
@@ -154,17 +149,16 @@ UpdateProcess.prototype = {
  *        The document that will contain the computed view.
  * @param {PageStyleFront} pageStyle
  *        Front for the page style actor that will be providing
  *        the style information.
  */
 function CssComputedView(inspector, document, pageStyle) {
   this.inspector = inspector;
   this.highlighters = inspector.highlighters;
-  this.store = inspector.store;
   this.styleDocument = document;
   this.styleWindow = this.styleDocument.defaultView;
   this.pageStyle = pageStyle;
 
   this.propertyViews = [];
 
   let cssProperties = getCssProperties(inspector.toolbox);
   this._outputParser = new OutputParser(document, cssProperties);
@@ -175,17 +169,16 @@ function CssComputedView(inspector, docu
   this._onClick = this._onClick.bind(this);
   this._onCopy = this._onCopy.bind(this);
   this._onFilterStyles = this._onFilterStyles.bind(this);
   this._onClearSearch = this._onClearSearch.bind(this);
   this._onIncludeBrowserStyles = this._onIncludeBrowserStyles.bind(this);
 
   let doc = this.styleDocument;
   this.element = doc.getElementById("propertyContainer");
-  this.boxModelWrapper = doc.getElementById("boxmodel-wrapper");
   this.searchField = doc.getElementById("computedview-searchbox");
   this.searchClearButton = doc.getElementById("computedview-searchinput-clear");
   this.includeBrowserStylesCheckbox =
     doc.getElementById("browser-style-checkbox");
 
   this.shortcuts = new KeyShortcuts({ window: this.styleWindow });
   this._onShortcut = this._onShortcut.bind(this);
   this.shortcuts.on("CmdOrCtrl+F", this._onShortcut);
@@ -211,17 +204,16 @@ function CssComputedView(inspector, docu
   this._onSourcePrefChanged = this._onSourcePrefChanged.bind(this);
   this._prefObserver = new PrefObserver("devtools.");
   this._prefObserver.on(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
   this._prefObserver.on("devtools.defaultColorUnit", this._handlePrefChange);
 
   // The element that we're inspecting, and the document that it comes from.
   this._viewedElement = null;
 
-  this.createBoxModelView();
   this.createStyleViews();
 
   this._contextmenu = new StyleInspectorMenu(this, { isRuleView: false });
 
   // Add the tooltips and highlightersoverlay
   this.tooltips = new TooltipsOverlay(this);
   this.tooltips.addToView();
 
@@ -555,20 +547,20 @@ CssComputedView.prototype = {
 
     let filterTimeout = (this.searchField.value.length > 0)
       ? FILTER_CHANGED_TIMEOUT : 0;
     this.searchClearButton.hidden = this.searchField.value.length === 0;
 
     this._filterChangedTimeout = setTimeout(() => {
       if (this.searchField.value.length > 0) {
         this.searchField.setAttribute("filled", true);
-        this.boxModelWrapper.hidden = true;
+        this.inspector.emit("computed-view-filtered", true);
       } else {
         this.searchField.removeAttribute("filled");
-        this.boxModelWrapper.hidden = false;
+        this.inspector.emit("computed-view-filtered", false);
       }
 
       this.refreshPanel();
       this._filterChangeTimeout = null;
     }, filterTimeout);
   },
 
   /**
@@ -609,39 +601,16 @@ CssComputedView.prototype = {
     this._handlePrefChange();
     for (let propView of this.propertyViews) {
       propView.updateSourceLinks();
     }
     this.inspector.emit("computed-view-sourcelinks-updated");
   },
 
   /**
-   * Render the box model view.
-   */
-  createBoxModelView: function () {
-    let {
-      onHideBoxModelHighlighter,
-      onShowBoxModelEditor,
-      onShowBoxModelHighlighter,
-    } = this.inspector.boxmodel.getComponentProps();
-
-    let provider = createElement(
-      Provider,
-      { store: this.store },
-      BoxModelApp({
-        showBoxModelProperties: false,
-        onHideBoxModelHighlighter,
-        onShowBoxModelEditor,
-        onShowBoxModelHighlighter,
-      })
-    );
-    ReactDOM.render(provider, this.boxModelWrapper);
-  },
-
-  /**
    * The CSS as displayed by the UI.
    */
   createStyleViews: function () {
     if (CssComputedView.propertyNames) {
       return;
     }
 
     CssComputedView.propertyNames = [];
@@ -809,30 +778,29 @@ CssComputedView.prototype = {
     this.searchField.removeEventListener("contextmenu",
       this.inspector.onTextBoxContextMenu);
     this.searchClearButton.removeEventListener("click", this._onClearSearch);
     this.includeBrowserStylesCheckbox.removeEventListener("input",
       this._onIncludeBrowserStyles);
 
     // Nodes used in templating
     this.element = null;
-    this.boxModelWrapper = null;
+    this.panel = null;
     this.searchField = null;
     this.searchClearButton = null;
     this.includeBrowserStylesCheckbox = null;
 
     // Property views
     for (let propView of this.propertyViews) {
       propView.destroy();
     }
     this.propertyViews = null;
 
     this.inspector = null;
     this.highlighters = null;
-    this.store = null;
     this.styleDocument = null;
     this.styleWindow = null;
 
     this._isDestroyed = true;
   }
 };
 
 function PropertyInfo(tree, name) {
@@ -1443,16 +1411,17 @@ SelectorView.prototype = {
 };
 
 function ComputedViewTool(inspector, window) {
   this.inspector = inspector;
   this.document = window.document;
 
   this.computedView = new CssComputedView(this.inspector, this.document,
     this.inspector.pageStyle);
+  this.boxModelView = new BoxModelView(this.inspector, this.document);
 
   this.onSelected = this.onSelected.bind(this);
   this.refresh = this.refresh.bind(this);
   this.onPanelSelected = this.onPanelSelected.bind(this);
   this.onMutations = this.onMutations.bind(this);
   this.onResized = this.onResized.bind(this);
 
   this.inspector.selection.on("detached-front", this.onSelected);
@@ -1551,16 +1520,17 @@ ComputedViewTool.prototype = {
     this.inspector.selection.off("new-node-front", this.onSelected);
     this.inspector.selection.off("detached-front", this.onSelected);
     this.inspector.sidebar.off("computedview-selected", this.onPanelSelected);
     if (this.inspector.pageStyle) {
       this.inspector.pageStyle.off("stylesheet-updated", this.refresh);
     }
 
     this.computedView.destroy();
+    this.boxModelView.destroy();
 
-    this.computedView = this.document = this.inspector = null;
+    this.computedView = this.boxModelView = this.document = this.inspector = null;
   }
 };
 
 exports.CssComputedView = CssComputedView;
 exports.ComputedViewTool = ComputedViewTool;
 exports.PropertyView = PropertyView;
--- a/devtools/client/inspector/computed/test/browser_computed_search-filter.js
+++ b/devtools/client/inspector/computed/test/browser_computed_search-filter.js
@@ -29,17 +29,17 @@ function* testToggleDefaultStyles(inspec
   let onRefreshed = inspector.once("computed-view-refreshed");
   checkbox.click();
   yield onRefreshed;
 }
 
 function* testAddTextInFilter(inspector, computedView) {
   info("setting filter text to \"color\"");
   let doc = computedView.styleDocument;
-  let boxModelWrapper = doc.getElementById("boxmodel-wrapper");
+  let boxModelWrapper = doc.querySelector("#old-boxmodel-wrapper");
   let searchField = computedView.searchField;
   let onRefreshed = inspector.once("computed-view-refreshed");
   let win = computedView.styleWindow;
 
   // First check to make sure that accel + F doesn't focus search if the
   // container isn't focused
   inspector.panelWin.focus();
   EventUtils.synthesizeKey("f", { accelKey: true });
--- a/devtools/client/inspector/computed/test/browser_computed_search-filter_clear.js
+++ b/devtools/client/inspector/computed/test/browser_computed_search-filter_clear.js
@@ -45,17 +45,17 @@ function* testAddTextInFilter(inspector,
   });
 }
 
 function* testClearSearchFilter(inspector, computedView) {
   info("Clearing the search filter");
 
   let win = computedView.styleWindow;
   let doc = computedView.styleDocument;
-  let boxModelWrapper = doc.getElementById("boxmodel-wrapper");
+  let boxModelWrapper = doc.querySelector("#old-boxmodel-wrapper");
   let propertyViews = computedView.propertyViews;
   let searchField = computedView.searchField;
   let searchClearButton = computedView.searchClearButton;
   let onRefreshed = inspector.once("computed-view-refreshed");
 
   EventUtils.synthesizeMouseAtCenter(searchClearButton, {}, win);
   yield onRefreshed;
 
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -18,17 +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");
 const {ViewHelpers} = require("devtools/client/shared/widgets/view-helpers");
@@ -73,16 +73,18 @@ const PORTRAIT_MODE_WIDTH = 700;
  *      Fired when the computed rules view updates to a new node
  * - computed-view-property-expanded
  *      Fired when a property is expanded in the computed rules view
  * - computed-view-property-collapsed
  *      Fired when a property is collapsed in the computed rules view
  * - computed-view-sourcelinks-updated
  *      Fired when the stylesheet source links have been updated (when switching
  *      to source-mapped files)
+ * - computed-view-filtered
+ *      Fired when the computed rules view is filtered
  * - rule-view-refreshed
  *      Fired when the rule view updates to a new node
  * - rule-view-sourcelinks-updated
  *      Fired when the stylesheet source links have been updated (when switching
  *      to source-mapped files)
  */
 function Inspector(toolbox) {
   this._toolbox = toolbox;
@@ -565,20 +567,16 @@ Inspector.prototype = {
       defaultTab == "ruleview");
 
     this.sidebar.addExistingTab(
       "computedview",
       INSPECTOR_L10N.getStr("inspector.sidebar.computedViewTitle"),
       defaultTab == "computedview");
 
     this.ruleview = new RuleViewTool(this, this.panelWin);
-    this.boxmodel = new BoxModel(this, this.panelWin);
-
-    const {ComputedViewTool} =
-      this.browserRequire("devtools/client/inspector/computed/computed");
     this.computedview = new ComputedViewTool(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) {
--- a/devtools/client/inspector/inspector.xhtml
+++ b/devtools/client/inspector/inspector.xhtml
@@ -9,16 +9,17 @@
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
 
   <link rel="stylesheet" href="chrome://devtools/skin/widgets.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/inspector.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/rules.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/computed.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/fonts.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/boxmodel.css"/>
+  <link rel="stylesheet" href="chrome://devtools/skin/deprecated-boxmodel.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/layout.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/animationinspector.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/sidebar-toggle.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/tabs.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/tabbar.css"/>
   <link rel="stylesheet" href="resource://devtools/client/inspector/components/inspector-tab-panel.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/splitter/split-box.css"/>
   <link rel="stylesheet" href="resource://devtools/client/inspector/layout/components/Accordion.css"/>
@@ -126,17 +127,70 @@
                       type="checkbox"
                       class="includebrowserstyles"/>
           <label id="browser-style-checkbox-label" for="browser-style-checkbox"
                         data-localization="content=inspector.browserStyles.label"></label>
         </div>
 
         <div id="computedview-container">
           <div id="computedview-container-focusable" tabindex="-1">
-            <div id="boxmodel-wrapper" tabindex="0">
+            <div id="old-boxmodel-wrapper" tabindex="0"
+              data-localization-bundle="devtools/client/locales/boxmodel.properties">
+              <div id="old-boxmodel-header">
+                <div id="old-boxmodel-expander" class="expander theme-twisty expandable" open=""></div>
+                <span data-localization="content=boxmodel.title"></span>
+              </div>
+
+              <div id="old-boxmodel-container">
+                <div id="old-boxmodel-main">
+                  <span class="old-boxmodel-legend" data-box="margin" data-localization="content=boxmodel.margin;title=boxmodel.margin"></span>
+                  <div id="old-boxmodel-margins" data-box="margin" data-localization="title=boxmodel.margin">
+                    <span class="old-boxmodel-legend" data-box="border" data-localization="content=boxmodel.border;title=boxmodel.border"></span>
+                    <div id="old-boxmodel-borders" data-box="border" data-localization="title=boxmodel.border">
+                      <span class="old-boxmodel-legend" data-box="padding" data-localization="content=boxmodel.padding;title=boxmodel.padding"></span>
+                      <div id="old-boxmodel-padding" data-box="padding" data-localization="title=boxmodel.padding">
+                        <div id="old-boxmodel-content" data-box="content" data-localization="title=boxmodel.content">
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+
+                  <p class="old-boxmodel-margin old-boxmodel-top"><span data-box="margin" class="old-boxmodel-editable" title="margin-top"></span></p>
+                  <p class="old-boxmodel-margin old-boxmodel-right"><span data-box="margin" class="old-boxmodel-editable" title="margin-right"></span></p>
+                  <p class="old-boxmodel-margin old-boxmodel-bottom"><span data-box="margin" class="old-boxmodel-editable" title="margin-bottom"></span></p>
+                  <p class="old-boxmodel-margin old-boxmodel-left"><span data-box="margin" class="old-boxmodel-editable" title="margin-left"></span></p>
+
+                  <p class="old-boxmodel-border old-boxmodel-top"><span data-box="border" class="old-boxmodel-editable" title="border-top"></span></p>
+                  <p class="old-boxmodel-border old-boxmodel-right"><span data-box="border" class="old-boxmodel-editable" title="border-right"></span></p>
+                  <p class="old-boxmodel-border old-boxmodel-bottom"><span data-box="border" class="old-boxmodel-editable" title="border-bottom"></span></p>
+                  <p class="old-boxmodel-border old-boxmodel-left"><span data-box="border" class="old-boxmodel-editable" title="border-left"></span></p>
+
+                  <p class="old-boxmodel-padding old-boxmodel-top"><span data-box="padding" class="old-boxmodel-editable" title="padding-top"></span></p>
+                  <p class="old-boxmodel-padding old-boxmodel-right"><span data-box="padding" class="old-boxmodel-editable" title="padding-right"></span></p>
+                  <p class="old-boxmodel-padding old-boxmodel-bottom"><span data-box="padding" class="old-boxmodel-editable" title="padding-bottom"></span></p>
+                  <p class="old-boxmodel-padding old-boxmodel-left"><span data-box="padding" class="old-boxmodel-editable" title="padding-left"></span></p>
+
+                  <p class="old-boxmodel-size">
+                    <span data-box="content" data-localization="title=boxmodel.content"></span>
+                  </p>
+                </div>
+
+                <div id="old-boxmodel-info">
+                  <span id="old-boxmodel-element-size"></span>
+                  <section id="old-boxmodel-position-group">
+                    <button class="devtools-button" id="old-layout-geometry-editor"
+                            data-localization="title=boxmodel.geometryButton.tooltip"></button>
+                    <span id="old-boxmodel-element-position"></span>
+                  </section>
+                </div>
+
+                <div style="display: none">
+                  <p id="old-boxmodel-dummy"></p>
+                </div>
+              </div>
             </div>
 
             <div id="propertyContainer" class="theme-separator" tabindex="0" dir="ltr">
             </div>
 
             <div id="computedview-no-results" hidden="" data-localization="content=inspector.noProperties"></div>
           </div>
         </div>
rename from devtools/client/inspector/boxmodel/actions/box-model.js
rename to devtools/client/inspector/layout/actions/box-model.js
--- a/devtools/client/inspector/layout/actions/index.js
+++ b/devtools/client/inspector/layout/actions/index.js
@@ -9,15 +9,18 @@ const { createEnum } = require("devtools
 createEnum([
 
   // Update the grid highlighted state.
   "UPDATE_GRID_HIGHLIGHTED",
 
   // Update the entire grids state with the new list of grids.
   "UPDATE_GRIDS",
 
+  // Update the layout state with the latest layout properties.
+  "UPDATE_LAYOUT",
+
   // Update the grid highlighter's show grid line numbers state.
   "UPDATE_SHOW_GRID_LINE_NUMBERS",
 
   // Update the grid highlighter's show infinite lines state.
   "UPDATE_SHOW_INFINITE_LINES",
 
 ], module.exports);
--- a/devtools/client/inspector/layout/actions/moz.build
+++ b/devtools/client/inspector/layout/actions/moz.build
@@ -1,11 +1,12 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
+    'box-model.js',
     'grids.js',
     'highlighter-settings.js',
     'index.js',
 )
--- a/devtools/client/inspector/layout/components/App.js
+++ b/devtools/client/inspector/layout/components/App.js
@@ -6,20 +6,19 @@
 
 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({
 
rename from devtools/client/inspector/boxmodel/components/BoxModel.js
rename to devtools/client/inspector/layout/components/BoxModel.js
rename from devtools/client/inspector/boxmodel/components/BoxModelEditable.js
rename to devtools/client/inspector/layout/components/BoxModelEditable.js
rename from devtools/client/inspector/boxmodel/components/BoxModelInfo.js
rename to devtools/client/inspector/layout/components/BoxModelInfo.js
rename from devtools/client/inspector/boxmodel/components/BoxModelMain.js
rename to devtools/client/inspector/layout/components/BoxModelMain.js
--- a/devtools/client/inspector/boxmodel/components/BoxModelMain.js
+++ b/devtools/client/inspector/layout/components/BoxModelMain.js
@@ -32,33 +32,17 @@ module.exports = createClass({
 
   mixins: [ addons.PureRenderMixin ],
 
   getBorderOrPaddingValue(property) {
     let { layout } = this.props.boxModel;
     return layout[property] ? parseFloat(layout[property]) : "-";
   },
 
-  getHeightValue(property) {
-    let { layout } = this.props.boxModel;
-
-    if (property == undefined) {
-      return "-";
-    }
-
-    property -= parseFloat(layout["border-top-width"]) +
-                parseFloat(layout["border-bottom-width"]) +
-                parseFloat(layout["padding-top"]) +
-                parseFloat(layout["padding-bottom"]);
-    property = parseFloat(property.toPrecision(6));
-
-    return property;
-  },
-
-  getWidthValue(property) {
+  getHeightOrWidthValue(property) {
     let { layout } = this.props.boxModel;
 
     if (property == undefined) {
       return "-";
     }
 
     property -= parseFloat(layout["border-left-width"]) +
                 parseFloat(layout["border-right-width"]) +
@@ -94,35 +78,35 @@ module.exports = createClass({
       showOnly: region,
       onlyRegionArea: true,
     });
   },
 
   render() {
     let { boxModel, onShowBoxModelEditor } = this.props;
     let { layout } = boxModel;
-    let { height, width } = layout;
+    let { width, height } = layout;
 
     let borderTop = this.getBorderOrPaddingValue("border-top-width");
     let borderRight = this.getBorderOrPaddingValue("border-right-width");
     let borderBottom = this.getBorderOrPaddingValue("border-bottom-width");
     let borderLeft = this.getBorderOrPaddingValue("border-left-width");
 
     let paddingTop = this.getBorderOrPaddingValue("padding-top");
     let paddingRight = this.getBorderOrPaddingValue("padding-right");
     let paddingBottom = this.getBorderOrPaddingValue("padding-bottom");
     let paddingLeft = this.getBorderOrPaddingValue("padding-left");
 
     let marginTop = this.getMarginValue("margin-top", "top");
     let marginRight = this.getMarginValue("margin-right", "right");
     let marginBottom = this.getMarginValue("margin-bottom", "bottom");
     let marginLeft = this.getMarginValue("margin-left", "left");
 
-    height = this.getHeightValue(height);
-    width = this.getWidthValue(width);
+    width = this.getHeightOrWidthValue(width);
+    height = this.getHeightOrWidthValue(height);
 
     return dom.div(
       {
         className: "boxmodel-main",
         onMouseOver: this.onHighlightMouseOver,
         onMouseOut: this.props.onHideBoxModelHighlighter,
       },
       dom.span(
rename from devtools/client/inspector/boxmodel/components/BoxModelProperties.js
rename to devtools/client/inspector/layout/components/BoxModelProperties.js
rename from devtools/client/inspector/boxmodel/components/ComputedProperty.js
rename to devtools/client/inspector/layout/components/ComputedProperty.js
--- a/devtools/client/inspector/layout/components/moz.build
+++ b/devtools/client/inspector/layout/components/moz.build
@@ -3,12 +3,18 @@
 # 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/.
 
 DevToolsModules(
     'Accordion.css',
     'Accordion.js',
     'App.js',
+    'BoxModel.js',
+    'BoxModelEditable.js',
+    'BoxModelInfo.js',
+    'BoxModelMain.js',
+    'BoxModelProperties.js',
+    'ComputedProperty.js',
     'Grid.js',
     'GridDisplaySettings.js',
     'GridList.js',
 )
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -1,87 +1,180 @@
 /* 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,
 
-      onHideBoxModelHighlighter,
-      onShowBoxModelEditor,
-      onShowBoxModelHighlighter,
+      /**
+       * 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 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.
@@ -155,19 +248,26 @@ 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;
   },
 
   /**
@@ -175,29 +275,105 @@ 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.
@@ -249,26 +425,44 @@ 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;
rename from devtools/client/inspector/boxmodel/reducers/box-model.js
rename to devtools/client/inspector/layout/reducers/box-model.js
--- a/devtools/client/inspector/layout/reducers/moz.build
+++ b/devtools/client/inspector/layout/reducers/moz.build
@@ -1,10 +1,11 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
+    'box-model.js',
     'grids.js',
     'highlighter-settings.js',
 )
--- a/devtools/client/inspector/layout/types.js
+++ b/devtools/client/inspector/layout/types.js
@@ -2,16 +2,26 @@
  * 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 { PropTypes } = require("devtools/client/shared/vendor/react");
 
 /**
+ * The box model data for the current selected node.
+ */
+exports.boxModel = {
+
+  // The layout information of the current selected node
+  layout: PropTypes.object,
+
+};
+
+/**
  * A single grid container in the document.
  */
 exports.grid = {
 
   // The id of the grid
   id: PropTypes.number,
 
   // The grid fragment object of the grid container
rename from devtools/client/inspector/boxmodel/utils/editing-session.js
rename to devtools/client/inspector/layout/utils/editing-session.js
--- a/devtools/client/inspector/layout/utils/moz.build
+++ b/devtools/client/inspector/layout/utils/moz.build
@@ -1,9 +1,10 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
+    'editing-session.js',
     'l10n.js',
 )
--- a/devtools/client/inspector/moz.build
+++ b/devtools/client/inspector/moz.build
@@ -1,14 +1,13 @@
 # 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/.
 
 DIRS += [
-    'boxmodel',
     'components',
     'computed',
     'fonts',
     'layout',
     'markup',
     'rules',
     'shared'
 ]
--- a/devtools/client/inspector/reducers.js
+++ b/devtools/client/inspector/reducers.js
@@ -2,11 +2,11 @@
  * 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";
 
 // This file exposes the Redux reducers of the box model, grid and grid highlighter
 // settings.
 
-exports.boxModel = require("devtools/client/inspector/boxmodel/reducers/box-model");
+exports.boxModel = require("devtools/client/inspector/layout/reducers/box-model");
 exports.grids = require("devtools/client/inspector/layout/reducers/grids");
 exports.highlighterSettings = require("devtools/client/inspector/layout/reducers/highlighter-settings");
--- a/devtools/client/inspector/test/browser_inspector_textbox-menu.js
+++ b/devtools/client/inspector/test/browser_inspector_textbox-menu.js
@@ -61,17 +61,17 @@ add_task(function* () {
 
   info("Switching to the computed-view");
   let onComputedViewReady = inspector.once("boxmodel-view-updated");
   selectComputedView(inspector);
   yield onComputedViewReady;
 
   info("Testing the box-model region");
   let margin = inspector.panelDoc.querySelector(
-    ".boxmodel-margin.boxmodel-top > span");
+    ".old-boxmodel-margin.old-boxmodel-top > span");
   EventUtils.synthesizeMouseAtCenter(margin, {}, inspector.panelWin);
   yield checkTextBox(inspector.panelDoc.activeElement, toolbox);
 });
 
 function* checkTextBox(textBox, {textBoxContextMenuPopup}) {
   is(textBoxContextMenuPopup.state, "closed", "The menu is closed");
 
   info("Simulating context click on the textbox and expecting the menu to open");
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -172,16 +172,17 @@ devtools.jar:
     skin/images/item-toggle.svg (themes/images/item-toggle.svg)
     skin/images/item-arrow-dark-rtl.svg (themes/images/item-arrow-dark-rtl.svg)
     skin/images/item-arrow-dark-ltr.svg (themes/images/item-arrow-dark-ltr.svg)
     skin/images/item-arrow-rtl.svg (themes/images/item-arrow-rtl.svg)
     skin/images/item-arrow-ltr.svg (themes/images/item-arrow-ltr.svg)
     skin/images/noise.png (themes/images/noise.png)
     skin/images/dropmarker.svg (themes/images/dropmarker.svg)
     skin/boxmodel.css (themes/boxmodel.css)
+    skin/deprecated-boxmodel.css (themes/deprecated-boxmodel.css)
     skin/images/geometry-editor.svg (themes/images/geometry-editor.svg)
     skin/images/pause.svg (themes/images/pause.svg)
     skin/images/play.svg (themes/images/play.svg)
     skin/images/fast-forward.svg (themes/images/fast-forward.svg)
     skin/images/rewind.svg (themes/images/rewind.svg)
     skin/images/debugger-step-in.svg (themes/images/debugger-step-in.svg)
     skin/images/debugger-step-out.svg (themes/images/debugger-step-out.svg)
     skin/images/debugger-step-over.svg (themes/images/debugger-step-over.svg)
--- a/devtools/client/shared/browser-loader.js
+++ b/devtools/client/shared/browser-loader.js
@@ -7,18 +7,16 @@ 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/computed",
   "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",
new file mode 100644
--- /dev/null
+++ b/devtools/client/themes/deprecated-boxmodel.css
@@ -0,0 +1,259 @@
+/* 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/ */
+
+/**
+ * THIS STYLESHEET IS FOR THE DEPRECATED BOX MODEL MODULE (deprecated-box-model.js) AND
+ * SHOULD NO LONGER BE MODIFIED.
+ */
+
+#old-boxmodel-wrapper {
+  border-bottom-style: solid;
+  border-bottom-width: 1px;
+  border-color: var(--theme-splitter-color);
+  -moz-user-select: none;
+}
+
+#old-boxmodel-container {
+  /* The view will grow bigger as the window gets resized, until 400px */
+  max-width: 400px;
+  margin: 0px auto;
+  padding: 0;
+}
+
+/* Header */
+
+#old-boxmodel-header,
+#old-boxmodel-info {
+  display: flex;
+  align-items: center;
+  padding: 4px 17px;
+}
+
+#old-layout-geometry-editor {
+  visibility: hidden;
+}
+
+#old-layout-geometry-editor::before {
+  background: url(images/geometry-editor.svg) no-repeat center center / 16px 16px;
+}
+
+/* Main: contains the box-model regions */
+
+#old-boxmodel-main {
+  position: relative;
+  box-sizing: border-box;
+  /* The regions are semi-transparent, so the white background is partly
+     visible */
+  background-color: white;
+  color: var(--theme-selection-color);
+  /* Make sure there is some space between the window's edges and the regions */
+  margin: 0 14px 4px 14px;
+  width: calc(100% - 2 * 14px);
+}
+
+.old-boxmodel-margin,
+.old-boxmodel-size {
+  color: var(--theme-highlight-blue);
+}
+
+/* Regions are 3 nested elements with wide borders and outlines */
+
+#old-boxmodel-content {
+  height: 18px;
+}
+
+#old-boxmodel-margins,
+#old-boxmodel-borders,
+#old-boxmodel-padding {
+  border-color: hsla(210,100%,85%,0.2);
+  border-width: 18px;
+  border-style: solid;
+  outline: dotted 1px hsl(210,100%,85%);
+}
+
+#old-boxmodel-margins {
+  /* This opacity applies to all of the regions, since they are nested */
+  opacity: .8;
+}
+
+/* Regions colors */
+
+#old-boxmodel-margins {
+  border-color: #edff64;
+}
+
+#old-boxmodel-borders {
+  border-color: #444444;
+}
+
+#old-boxmodel-padding {
+  border-color: #6a5acd;
+}
+
+#old-boxmodel-content {
+  background-color: #87ceeb;
+}
+
+.theme-firebug #old-boxmodel-main,
+.theme-firebug #old-boxmodel-borders,
+.theme-firebug #old-boxmodel-content {
+  border-style: solid;
+}
+
+.theme-firebug #old-boxmodel-main,
+.theme-firebug #old-boxmodel-header {
+  font-family: var(--proportional-font-family);
+}
+
+.theme-firebug #old-boxmodel-main {
+  color: var(--theme-body-color);
+  font-size: var(--theme-toolbar-font-size);
+}
+
+.theme-firebug #old-boxmodel-header {
+  font-size: var(--theme-toolbar-font-size);
+}
+
+/* Editable region sizes are contained in absolutely positioned <p> */
+
+#old-boxmodel-main > p {
+  position: absolute;
+  pointer-events: none;
+  margin: 0;
+  text-align: center;
+}
+
+#old-boxmodel-main > p > span,
+#old-boxmodel-main > p > input {
+  vertical-align: middle;
+  pointer-events: auto;
+}
+
+/* Coordinates for the region sizes */
+
+.old-boxmodel-top,
+.old-boxmodel-bottom {
+  width: calc(100% - 2px);
+  text-align: center;
+}
+
+.old-boxmodel-padding.old-boxmodel-top {
+  top: 37px;
+}
+
+.old-boxmodel-padding.old-boxmodel-bottom {
+  bottom: 38px;
+}
+
+.old-boxmodel-border.old-boxmodel-top {
+  top: 19px;
+}
+
+.old-boxmodel-border.old-boxmodel-bottom {
+  bottom: 20px;
+}
+
+.old-boxmodel-margin.old-boxmodel-top {
+  top: 1px;
+}
+
+.old-boxmodel-margin.old-boxmodel-bottom {
+  bottom: 2px;
+}
+
+.old-boxmodel-size,
+.old-boxmodel-margin.old-boxmodel-left,
+.old-boxmodel-margin.old-boxmodel-right,
+.old-boxmodel-border.old-boxmodel-left,
+.old-boxmodel-border.old-boxmodel-right,
+.old-boxmodel-padding.old-boxmodel-left,
+.old-boxmodel-padding.old-boxmodel-right {
+  top: 22px;
+  line-height: 80px;
+}
+
+.old-boxmodel-size {
+  width: calc(100% - 2px);
+}
+
+.old-boxmodel-margin.old-boxmodel-right,
+.old-boxmodel-margin.old-boxmodel-left,
+.old-boxmodel-border.old-boxmodel-left,
+.old-boxmodel-border.old-boxmodel-right,
+.old-boxmodel-padding.old-boxmodel-right,
+.old-boxmodel-padding.old-boxmodel-left {
+  width: 21px;
+}
+
+.old-boxmodel-padding.old-boxmodel-left {
+  left: 35px;
+}
+
+.old-boxmodel-padding.old-boxmodel-right {
+  right: 35px;
+}
+
+.old-boxmodel-border.old-boxmodel-left {
+  left: 16px;
+}
+
+.old-boxmodel-border.old-boxmodel-right {
+  right: 17px;
+}
+
+.old-boxmodel-margin.old-boxmodel-right {
+  right: 0;
+}
+
+.old-boxmodel-margin.old-boxmodel-left {
+  left: 0;
+}
+
+.old-boxmodel-rotate.old-boxmodel-left:not(.old-boxmodel-editing) {
+  transform: rotate(-90deg);
+}
+
+.old-boxmodel-rotate.old-boxmodel-right:not(.old-boxmodel-editing) {
+  transform: rotate(90deg);
+}
+
+/* Legend: displayed inside regions */
+
+.old-boxmodel-legend {
+  position: absolute;
+  margin: 2px 6px;
+  z-index: 1;
+}
+
+.old-boxmodel-legend[data-box="margin"] {
+  color: var(--theme-highlight-blue);
+}
+
+/* Editable fields */
+
+.old-boxmodel-editable {
+  border: 1px dashed transparent;
+  -moz-user-select: none;
+}
+
+.old-boxmodel-editable:hover {
+  border-bottom-color: hsl(0, 0%, 50%);
+}
+
+/* Make sure the content size doesn't appear as editable like the other sizes */
+
+.old-boxmodel-size > span {
+  cursor: default;
+}
+
+/* Box Model Info: contains the position and size of the element */
+
+#old-boxmodel-element-size {
+  flex: 1;
+}
+
+#old-boxmodel-position-group {
+  display: flex;
+  align-items: center;
+}