Backed out changeset a097b61f5810 (bug 1247729) for timeouts in browser_layout_update-after-reload.js a=backout
authorWes Kocher <wkocher@mozilla.com>
Wed, 13 Jul 2016 14:26:06 -0700
changeset 347018 34a128489d8895e2f1ef58f43e2b4d196be6e544
parent 347017 0ec4b1228536dabe17e78060f4413fc91b162d58
child 347019 c492812c7932a78769ae2ddad321b725e09fd9ea
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1247729
milestone50.0a1
backs outa097b61f58102776941bd3fa0023092ac3f27a3f
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset a097b61f5810 (bug 1247729) for timeouts in browser_layout_update-after-reload.js a=backout
devtools/client/inspector/computed/computed.js
devtools/client/inspector/computed/test/browser_computed_cycle_color.js
devtools/client/inspector/computed/test/browser_computed_keybindings_01.js
devtools/client/inspector/computed/test/browser_computed_matched-selectors-toggle.js
devtools/client/inspector/computed/test/head.js
devtools/client/inspector/inspector-panel.js
devtools/client/inspector/inspector.xul
devtools/client/inspector/layout/layout.js
devtools/client/inspector/layout/test/head.js
devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-color_01.js
devtools/client/inspector/shared/test/browser_styleinspector_refresh_when_active.js
devtools/client/inspector/test/head.js
devtools/client/responsivedesign/test/head.js
devtools/client/shared/telemetry.js
devtools/client/shared/test/browser_telemetry_sidebar.js
devtools/client/themes/computed.css
devtools/client/themes/layout.css
devtools/client/themes/rules.css
devtools/client/themes/toolbars.css
toolkit/components/telemetry/Histograms.json
--- a/devtools/client/inspector/computed/computed.js
+++ b/devtools/client/inspector/computed/computed.js
@@ -24,18 +24,16 @@ const {XPCOMUtils} = require("resource:/
 const {getCssProperties} = require("devtools/shared/fronts/css-properties");
 
 loader.lazyRequireGetter(this, "overlays",
   "devtools/client/inspector/shared/style-inspector-overlays");
 loader.lazyRequireGetter(this, "StyleInspectorMenu",
   "devtools/client/inspector/shared/style-inspector-menu");
 loader.lazyRequireGetter(this, "KeyShortcuts",
   "devtools/client/shared/key-shortcuts", true);
-loader.lazyRequireGetter(this, "LayoutView",
-  "devtools/client/inspector/layout/layout", true);
 
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
                                   "resource://gre/modules/PluralForm.jsm");
 
 XPCOMUtils.defineLazyGetter(CssComputedView, "_strings", function () {
   return Services.strings.createBundle(
     "chrome://devtools-shared/locale/styleinspector.properties");
 });
@@ -166,16 +164,17 @@ function CssComputedView(inspector, docu
   this._onCopy = this._onCopy.bind(this);
   this._onFilterStyles = this._onFilterStyles.bind(this);
   this._onClearSearch = this._onClearSearch.bind(this);
   this._onIncludeBrowserStyles = this._onIncludeBrowserStyles.bind(this);
   this._onFilterTextboxContextMenu =
     this._onFilterTextboxContextMenu.bind(this);
 
   let doc = this.styleDocument;
+  this.root = doc.getElementById("root");
   this.element = doc.getElementById("propertyContainer");
   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);
@@ -773,16 +772,17 @@ CssComputedView.prototype = {
     this.searchField.removeEventListener("input", this._onFilterStyles);
     this.searchField.removeEventListener("contextmenu",
                                          this._onFilterTextboxContextMenu);
     this.searchClearButton.removeEventListener("click", this._onClearSearch);
     this.includeBrowserStylesCheckbox.removeEventListener("command",
       this.includeBrowserStylesChanged);
 
     // Nodes used in templating
+    this.root = null;
     this.element = null;
     this.panel = null;
     this.searchField = null;
     this.searchClearButton = null;
     this.includeBrowserStylesCheckbox = null;
 
     // Property views
     for (let propView of this.propertyViews) {
@@ -1402,86 +1402,85 @@ SelectorView.prototype = {
     });
   }
 };
 
 function ComputedViewTool(inspector, window) {
   this.inspector = inspector;
   this.document = window.document;
 
-  this.computedView = new CssComputedView(this.inspector, this.document,
+  this.view = new CssComputedView(this.inspector, this.document,
     this.inspector.pageStyle);
-  this.layoutView = new LayoutView(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", this.onSelected);
   this.inspector.selection.on("new-node-front", this.onSelected);
   this.inspector.selection.on("pseudoclass", this.refresh);
   this.inspector.sidebar.on("computedview-selected", this.onPanelSelected);
   this.inspector.pageStyle.on("stylesheet-updated", this.refresh);
   this.inspector.walker.on("mutations", this.onMutations);
   this.inspector.walker.on("resize", this.onResized);
 
-  this.computedView.selectElement(null);
+  this.view.selectElement(null);
 
   this.onSelected();
 }
 
 ComputedViewTool.prototype = {
   isSidebarActive: function () {
-    if (!this.computedView) {
+    if (!this.view) {
       return false;
     }
     return this.inspector.sidebar.getCurrentTabID() == "computedview";
   },
 
   onSelected: function (event) {
     // Ignore the event if the view has been destroyed, or if it's inactive.
     // But only if the current selection isn't null. If it's been set to null,
     // let the update go through as this is needed to empty the view on
     // navigation.
-    if (!this.computedView) {
+    if (!this.view) {
       return;
     }
 
     let isInactive = !this.isSidebarActive() &&
                      this.inspector.selection.nodeFront;
     if (isInactive) {
       return;
     }
 
-    this.computedView.setPageStyle(this.inspector.pageStyle);
+    this.view.setPageStyle(this.inspector.pageStyle);
 
     if (!this.inspector.selection.isConnected() ||
         !this.inspector.selection.isElementNode()) {
-      this.computedView.selectElement(null);
+      this.view.selectElement(null);
       return;
     }
 
     if (!event || event == "new-node-front") {
       let done = this.inspector.updating("computed-view");
-      this.computedView.selectElement(this.inspector.selection.nodeFront).then(() => {
+      this.view.selectElement(this.inspector.selection.nodeFront).then(() => {
         done();
       });
     }
   },
 
   refresh: function () {
     if (this.isSidebarActive()) {
-      this.computedView.refreshPanel();
+      this.view.refreshPanel();
     }
   },
 
   onPanelSelected: function () {
-    if (this.inspector.selection.nodeFront === this.computedView._viewedElement) {
+    if (this.inspector.selection.nodeFront === this.view._viewedElement) {
       this.refresh();
     } else {
       this.onSelected();
     }
   },
 
   /**
    * When markup mutations occur, if an attribute of the selected node changes,
@@ -1512,18 +1511,17 @@ ComputedViewTool.prototype = {
     this.inspector.selection.off("pseudoclass", this.refresh);
     this.inspector.selection.off("new-node-front", this.onSelected);
     this.inspector.selection.off("detached", 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.layoutView.destroy();
+    this.view.destroy();
 
-    this.computedView = this.layoutView = this.document = this.inspector = null;
+    this.view = this.document = this.inspector = null;
   }
 };
 
 exports.CssComputedView = CssComputedView;
 exports.ComputedViewTool = ComputedViewTool;
 exports.PropertyView = PropertyView;
--- a/devtools/client/inspector/computed/test/browser_computed_cycle_color.js
+++ b/devtools/client/inspector/computed/test/browser_computed_cycle_color.js
@@ -54,17 +54,16 @@ function* checkColorCycling(container, v
   for (let test of tests) {
     yield checkSwatchShiftClick(container, win, test.value, test.comment);
   }
 }
 
 function* checkSwatchShiftClick(container, win, expectedValue, comment) {
   let swatch = container.querySelector(".computedview-colorswatch");
   let valueNode = container.querySelector(".computedview-color");
-  swatch.scrollIntoView();
 
   let onUnitChange = swatch.once("unit-change");
   EventUtils.synthesizeMouseAtCenter(swatch, {
     type: "mousedown",
     shiftKey: true
   }, win);
   yield onUnitChange;
   is(valueNode.textContent, expectedValue, comment);
--- a/devtools/client/inspector/computed/test/browser_computed_keybindings_01.js
+++ b/devtools/client/inspector/computed/test/browser_computed_keybindings_01.js
@@ -20,17 +20,16 @@ add_task(function* () {
   let {inspector, view} = yield openComputedView();
   yield selectNode(".matches", inspector);
 
   let propView = getFirstVisiblePropertyView(view);
   let rulesTable = propView.matchedSelectorsContainer;
   let matchedExpander = propView.element;
 
   info("Focusing the property");
-  matchedExpander.scrollIntoView();
   let onMatchedExpanderFocus = once(matchedExpander, "focus", true);
   EventUtils.synthesizeMouseAtCenter(matchedExpander, {}, view.styleWindow);
   yield onMatchedExpanderFocus;
 
   yield checkToggleKeyBinding(view.styleWindow, "VK_SPACE", rulesTable,
                               inspector);
   yield checkToggleKeyBinding(view.styleWindow, "VK_RETURN", rulesTable,
                               inspector);
--- a/devtools/client/inspector/computed/test/browser_computed_matched-selectors-toggle.js
+++ b/devtools/client/inspector/computed/test/browser_computed_matched-selectors-toggle.js
@@ -25,17 +25,17 @@ add_task(function* () {
   yield testExpandOnDblClick(view, inspector);
   yield testCollapseOnDblClick(view, inspector);
 });
 
 function* testExpandOnTwistyClick({styleDocument, styleWindow}, inspector) {
   info("Testing that a property expands on twisty click");
 
   info("Getting twisty element");
-  let twisty = styleDocument.querySelector("#propertyContainer .expandable");
+  let twisty = styleDocument.querySelector(".expandable");
   ok(twisty, "Twisty found");
 
   let onExpand = inspector.once("computed-view-property-expanded");
   info("Clicking on the twisty element");
   twisty.click();
 
   yield onExpand;
 
@@ -44,17 +44,17 @@ function* testExpandOnTwistyClick({style
   ok(div.childNodes.length > 0,
     "Matched selectors are expanded on twisty click");
 }
 
 function* testCollapseOnTwistyClick({styleDocument, styleWindow}, inspector) {
   info("Testing that a property collapses on twisty click");
 
   info("Getting twisty element");
-  let twisty = styleDocument.querySelector("#propertyContainer .expandable");
+  let twisty = styleDocument.querySelector(".expandable");
   ok(twisty, "Twisty found");
 
   let onCollapse = inspector.once("computed-view-property-collapsed");
   info("Clicking on the twisty element");
   twisty.click();
 
   yield onCollapse;
 
@@ -66,18 +66,16 @@ function* testCollapseOnTwistyClick({sty
 
 function* testExpandOnDblClick({styleDocument, styleWindow}, inspector) {
   info("Testing that a property expands on container dbl-click");
 
   info("Getting computed property container");
   let container = styleDocument.querySelector(".property-view");
   ok(container, "Container found");
 
-  container.scrollIntoView();
-
   let onExpand = inspector.once("computed-view-property-expanded");
   info("Dbl-clicking on the container");
   EventUtils.synthesizeMouseAtCenter(container, {clickCount: 2}, styleWindow);
 
   yield onExpand;
 
   // Expanded means the matchedselectors div is not empty
   let div = styleDocument.querySelector(".property-content .matchedselectors");
--- a/devtools/client/inspector/computed/test/head.js
+++ b/devtools/client/inspector/computed/test/head.js
@@ -127,17 +127,17 @@ function getComputedViewPropertyValue(vi
  *        The instance of the computed view panel
  * @param {Number} index
  *        The index of the property to be expanded
  * @return a promise that resolves when the property has been expanded, or
  * rejects if the property was not found
  */
 function expandComputedViewPropertyByIndex(view, index) {
   info("Expanding property " + index + " in the computed view");
-  let expandos = view.styleDocument.querySelectorAll("#propertyContainer .expandable");
+  let expandos = view.styleDocument.querySelectorAll(".expandable");
   if (!expandos.length || !expandos[index]) {
     return promise.reject();
   }
 
   let onExpand = view.inspector.once("computed-view-property-expanded");
   expandos[index].click();
   return onExpand;
 }
--- a/devtools/client/inspector/inspector-panel.js
+++ b/devtools/client/inspector/inspector-panel.js
@@ -26,16 +26,17 @@ const MenuItem = require("devtools/clien
 
 loader.lazyRequireGetter(this, "CSS", "CSS");
 
 loader.lazyRequireGetter(this, "CommandUtils", "devtools/client/shared/developer-toolbar", true);
 loader.lazyRequireGetter(this, "ComputedViewTool", "devtools/client/inspector/computed/computed", true);
 loader.lazyRequireGetter(this, "FontInspector", "devtools/client/inspector/fonts/fonts", true);
 loader.lazyRequireGetter(this, "HTMLBreadcrumbs", "devtools/client/inspector/breadcrumbs", true);
 loader.lazyRequireGetter(this, "InspectorSearch", "devtools/client/inspector/inspector-search", true);
+loader.lazyRequireGetter(this, "LayoutView", "devtools/client/inspector/layout/layout", true);
 loader.lazyRequireGetter(this, "MarkupView", "devtools/client/inspector/markup/markup", true);
 loader.lazyRequireGetter(this, "RuleViewTool", "devtools/client/inspector/rules/rules", true);
 loader.lazyRequireGetter(this, "ToolSidebar", "devtools/client/framework/sidebar", true);
 loader.lazyRequireGetter(this, "ViewHelpers", "devtools/client/shared/widgets/view-helpers", true);
 
 loader.lazyGetter(this, "strings", () => {
   return Services.strings.createBundle("chrome://devtools/locale/inspector.properties");
 });
@@ -414,16 +415,17 @@ InspectorPanel.prototype = {
     this._setDefaultSidebar = (event, toolId) => {
       Services.prefs.setCharPref("devtools.inspector.activeSidebar", toolId);
     };
 
     this.sidebar.on("select", this._setDefaultSidebar);
 
     this.ruleview = new RuleViewTool(this, this.panelWin);
     this.computedview = new ComputedViewTool(this, this.panelWin);
+    this.layoutview = new LayoutView(this, this.panelWin);
 
     if (this.target.form.animationsActor) {
       this.sidebar.addTab("animationinspector",
                           "chrome://devtools/content/animationinspector/animation-inspector.xhtml",
                           {selected: defaultTab == "animationinspector",
                            insertBefore: "fontinspector"});
     }
 
@@ -687,16 +689,20 @@ InspectorPanel.prototype = {
     if (this.computedview) {
       this.computedview.destroy();
     }
 
     if (this.fontInspector) {
       this.fontInspector.destroy();
     }
 
+    if (this.layoutview) {
+      this.layoutview.destroy();
+    }
+
     let cssPropertiesDestroyer = this._cssPropertiesLoaded.then(({front}) => {
       if (front) {
         front.destroy();
       }
     });
 
     this.sidebar.off("select", this._setDefaultSidebar);
     let sidebarDestroyer = this.sidebar.destroy();
--- a/devtools/client/inspector/inspector.xul
+++ b/devtools/client/inspector/inspector.xul
@@ -53,16 +53,19 @@
     <tabbox id="inspector-sidebar" handleCtrlTab="false" class="devtools-sidebar-tabs" hidden="true">
       <tabs>
         <tab id="sidebar-tab-ruleview"
              label="&ruleViewTitle;"
              crop="end"/>
         <tab id="sidebar-tab-computedview"
              label="&computedViewTitle;"
              crop="end"/>
+        <tab id="sidebar-tab-layoutview"
+             label="&layoutViewTitle;"
+             crop="end"/>
         <tab id="sidebar-tab-fontinspector"
              label="&fontInspectorTitle;"
              crop="end"
              hidden="true"/>
       </tabs>
       <tabpanels flex="1">
         <tabpanel id="sidebar-panel-ruleview" class="devtools-monospace theme-sidebar inspector-tabpanel">
           <html:div id="ruleview-toolbar-container" class="devtools-toolbar">
@@ -100,74 +103,69 @@
               <html:button id="computedview-searchinput-clear" class="devtools-searchinput-clear"></html:button>
             </html:div>
             <checkbox id="browser-style-checkbox"
                       class="includebrowserstyles"
                       checked="false"
                       label="&browserStylesLabel;"/>
           </html:div>
 
-          <html:div id="computedview-container">
-            <html:div id="layout-wrapper" class="theme-separator" tabindex="0">
-              <html:div id="layout-header">
-                <html:div id="layout-expander" class="expander theme-twisty expandable" open=""></html:div>
-                <html:span>&layoutViewTitle;</html:span>
-                <html:button class="devtools-button" id="layout-geometry-editor" title="&geometry.button.tooltip;"></html:button>
-              </html:div>
+          <html:div id="propertyContainer">
+          </html:div>
+
+          <html:div id="computedview-no-results" hidden="">
+            &noPropertiesFound;
+          </html:div>
+        </tabpanel>
 
-              <html:div id="layout-container">
-                <html:div id="layout-main">
-                  <html:span class="layout-legend" data-box="margin" title="&margin.tooltip;">&margin.tooltip;</html:span>
-                  <html:div id="layout-margins" data-box="margin" title="&margin.tooltip;">
-                    <html:span class="layout-legend" data-box="border" title="&border.tooltip;">&border.tooltip;</html:span>
-                    <html:div id="layout-borders" data-box="border" title="&border.tooltip;">
-                      <html:span class="layout-legend" data-box="padding" title="&padding.tooltip;">&padding.tooltip;</html:span>
-                      <html:div id="layout-padding" data-box="padding" title="&padding.tooltip;">
-                        <html:div id="layout-content" data-box="content" title="&content.tooltip;">
-                        </html:div>
+        <tabpanel id="sidebar-panel-layoutview" class="devtools-monospace theme-sidebar inspector-tabpanel">
+          <html:div id="layout-wrapper">
+            <html:div id="layout-container">
+              <html:p id="layout-header">
+                <html:span id="layout-element-size"></html:span>
+                <html:section id="layout-position-group">
+                  <html:button class="devtools-button" id="layout-geometry-editor" title="&geometry.button.tooltip;"></html:button>
+                  <html:span id="layout-element-position"></html:span>
+                </html:section>
+              </html:p>
+
+              <html:div id="layout-main">
+                <html:span class="layout-legend" data-box="margin" title="&margin.tooltip;">&margin.tooltip;</html:span>
+                <html:div id="layout-margins" data-box="margin" title="&margin.tooltip;">
+                  <html:span class="layout-legend" data-box="border" title="&border.tooltip;">&border.tooltip;</html:span>
+                  <html:div id="layout-borders" data-box="border" title="&border.tooltip;">
+                    <html:span class="layout-legend" data-box="padding" title="&padding.tooltip;">&padding.tooltip;</html:span>
+                    <html:div id="layout-padding" data-box="padding" title="&padding.tooltip;">
+                      <html:div id="layout-content" data-box="content" title="&content.tooltip;">
                       </html:div>
                     </html:div>
                   </html:div>
-
-                  <html:p class="layout-margin layout-top"><html:span data-box="margin" class="layout-editable" title="margin-top"></html:span></html:p>
-                  <html:p class="layout-margin layout-right"><html:span data-box="margin" class="layout-editable" title="margin-right"></html:span></html:p>
-                  <html:p class="layout-margin layout-bottom"><html:span data-box="margin" class="layout-editable" title="margin-bottom"></html:span></html:p>
-                  <html:p class="layout-margin layout-left"><html:span data-box="margin" class="layout-editable" title="margin-left"></html:span></html:p>
-
-                  <html:p class="layout-border layout-top"><html:span data-box="border" class="layout-editable" title="border-top"></html:span></html:p>
-                  <html:p class="layout-border layout-right"><html:span data-box="border" class="layout-editable" title="border-right"></html:span></html:p>
-                  <html:p class="layout-border layout-bottom"><html:span data-box="border" class="layout-editable" title="border-bottom"></html:span></html:p>
-                  <html:p class="layout-border layout-left"><html:span data-box="border" class="layout-editable" title="border-left"></html:span></html:p>
-
-                  <html:p class="layout-padding layout-top"><html:span data-box="padding" class="layout-editable" title="padding-top"></html:span></html:p>
-                  <html:p class="layout-padding layout-right"><html:span data-box="padding" class="layout-editable" title="padding-right"></html:span></html:p>
-                  <html:p class="layout-padding layout-bottom"><html:span data-box="padding" class="layout-editable" title="padding-bottom"></html:span></html:p>
-                  <html:p class="layout-padding layout-left"><html:span data-box="padding" class="layout-editable" title="padding-left"></html:span></html:p>
-
-                  <html:p class="layout-size"><html:span data-box="content" title="&content.tooltip;"></html:span></html:p>
                 </html:div>
 
-                <html:div id="layout-info">
-                  <html:span id="layout-element-size"></html:span>
-                  <html:section id="layout-position-group">
-                    <html:span id="layout-element-position"></html:span>
-                  </html:section>
-                </html:div>
+                <html:p class="layout-border layout-top"><html:span data-box="border" class="layout-editable" title="border-top"></html:span></html:p>
+                <html:p class="layout-border layout-right"><html:span data-box="border" class="layout-editable" title="border-right"></html:span></html:p>
+                <html:p class="layout-border layout-bottom"><html:span data-box="border" class="layout-editable" title="border-bottom"></html:span></html:p>
+                <html:p class="layout-border layout-left"><html:span data-box="border" class="layout-editable" title="border-left"></html:span></html:p>
+
+                <html:p class="layout-margin layout-top"><html:span data-box="margin" class="layout-editable" title="margin-top"></html:span></html:p>
+                <html:p class="layout-margin layout-right"><html:span data-box="margin" class="layout-editable" title="margin-right"></html:span></html:p>
+                <html:p class="layout-margin layout-bottom"><html:span data-box="margin" class="layout-editable" title="margin-bottom"></html:span></html:p>
+                <html:p class="layout-margin layout-left"><html:span data-box="margin" class="layout-editable" title="margin-left"></html:span></html:p>
 
-                <html:div style="display: none">
-                  <html:p id="layout-dummy"></html:p>
-                </html:div>
-              </html:div>
-            </html:div>
+                <html:p class="layout-padding layout-top"><html:span data-box="padding" class="layout-editable" title="padding-top"></html:span></html:p>
+                <html:p class="layout-padding layout-right"><html:span data-box="padding" class="layout-editable" title="padding-right"></html:span></html:p>
+                <html:p class="layout-padding layout-bottom"><html:span data-box="padding" class="layout-editable" title="padding-bottom"></html:span></html:p>
+                <html:p class="layout-padding layout-left"><html:span data-box="padding" class="layout-editable" title="padding-left"></html:span></html:p>
 
-            <html:div id="propertyContainer" class="theme-separator" tabindex="0">
-            </html:div>
+                <html:p class="layout-size"><html:span data-box="content" title="&content.tooltip;"></html:span></html:p>
+              </html:div>
 
-            <html:div id="computedview-no-results" hidden="">
-              &noPropertiesFound;
+              <html:div style="display: none">
+                <html:p id="layout-dummy"></html:p>
+              </html:div>
             </html:div>
           </html:div>
         </tabpanel>
 
         <tabpanel id="sidebar-panel-fontinspector" class="devtools-monospace theme-sidebar inspector-tabpanel">
           <html:div class="devtools-toolbar">
             <html:div class="devtools-searchbox">
               <html:input id="font-preview-text-input"
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -63,17 +63,17 @@ EditingSession.prototype = {
    * no style rules affect the property.
    *
    * @param property  The name of the property as a string
    */
   getProperty: function (property) {
     // Create a hidden element for getPropertyFromRule to use
     let div = this._doc.createElement("div");
     div.setAttribute("style", "display: none");
-    this._doc.getElementById("sidebar-panel-computedview").appendChild(div);
+    this._doc.getElementById("sidebar-panel-layoutview").appendChild(div);
     this._element = this._doc.createElement("p");
     div.appendChild(this._element);
 
     // As the rules are in order of priority we can just iterate until we find
     // the first that defines a value for the property and return that.
     for (let rule of this._rules) {
       let value = this.getPropertyFromRule(rule, property);
       if (value !== "") {
@@ -178,52 +178,43 @@ EditingSession.prototype = {
     this._doc = null;
     this._rules = null;
     this._modifications.clear();
   }
 };
 
 /**
  * The layout-view panel
- * @param {InspectorPanel} inspector
- *        An instance of the inspector-panel currently loaded in the toolbox
- * @param {Document} document
- *        The document that will contain the layout view.
+ * @param {InspectorPanel} inspector An instance of the inspector-panel
+ * currently loaded in the toolbox
+ * @param {Window} win The window containing the panel
  */
-function LayoutView(inspector, document) {
+function LayoutView(inspector, win) {
   this.inspector = inspector;
-  this.doc = document;
-  this.wrapper = this.doc.getElementById("layout-wrapper");
-  this.container = this.doc.getElementById("layout-container");
-  this.expander = this.doc.getElementById("layout-expander");
+  this.doc = win.document;
   this.sizeLabel = this.doc.querySelector(".layout-size > span");
   this.sizeHeadingLabel = this.doc.getElementById("layout-element-size");
   this._geometryEditorHighlighter = null;
 
   this.init();
 }
 
 LayoutView.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.inspector.sidebar.on("layoutview-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("layout-header");
-    header.addEventListener("dblclick", this.onToggleExpander);
-
     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.initBoxModelHighlighter();
 
     // Store for the different dimensions of the node.
@@ -317,16 +308,17 @@ LayoutView.prototype = {
     // Mark document as RTL or LTR:
     let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
                     .getService(Ci.nsIXULChromeRegistry);
     let dir = chromeReg.isLocaleRTL("global");
     let container = this.doc.getElementById("layout-container");
     container.setAttribute("dir", dir ? "rtl" : "ltr");
 
     let nodeGeometry = this.doc.getElementById("layout-geometry-editor");
+
     this.onGeometryButtonClick = this.onGeometryButtonClick.bind(this);
     nodeGeometry.addEventListener("click", this.onGeometryButtonClick);
   },
 
   initBoxModelHighlighter: function () {
     let highlightElts = this.doc.querySelectorAll("#layout-container *[title]");
     this.onHighlightMouseOver = this.onHighlightMouseOver.bind(this);
     this.onHighlightMouseOut = this.onHighlightMouseOut.bind(this);
@@ -418,17 +410,17 @@ LayoutView.prototype = {
   },
 
   /**
    * Is the layoutview visible in the sidebar.
    * @return {Boolean}
    */
   isViewVisible: function () {
     return this.inspector &&
-           this.inspector.sidebar.getCurrentTabID() == "computedview";
+           this.inspector.sidebar.getCurrentTabID() == "layoutview";
   },
 
   /**
    * Is the layoutview visible in the sidebar and is the current node valid to
    * be displayed in the view.
    * @return {Boolean}
    */
   isViewVisibleAndNodeValid: function () {
@@ -443,62 +435,55 @@ LayoutView.prototype = {
   destroy: function () {
     let highlightElts = this.doc.querySelectorAll("#layout-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("layout-header");
-    header.removeEventListener("dblclick", this.onToggleExpander);
-
     let nodeGeometry = this.doc.getElementById("layout-geometry-editor");
     nodeGeometry.removeEventListener("click", this.onGeometryButtonClick);
 
     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 LayoutView
     // 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.sidebar.off("layoutview-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.sizeHeadingLabel = null;
+    this.sizeLabel = null;
     this.inspector = null;
     this.doc = null;
-    this.wrapper = null;
-    this.container = null;
-    this.expander = null;
-    this.sizeLabel = null;
-    this.sizeHeadingLabel = null;
 
     if (this.reflowFront) {
       this.untrackReflows();
       this.reflowFront.destroy();
       this.reflowFront = null;
     }
   },
 
   onSidebarSelect: function (e, sidebar) {
-    this.setActive(sidebar === "computedview");
+    this.setActive(sidebar === "layoutview");
   },
 
   /**
    * Selection 'new-node-front' event handler.
    */
   onNewSelection: function () {
-    let done = this.inspector.updating("computed-view");
+    let done = this.inspector.updating("layoutview");
     this.onNewNode()
       .then(() => this.hideGeometryEditor())
       .then(done, (err) => {
         console.error(err);
         done();
       }).catch(console.error);
   },
 
@@ -536,28 +521,16 @@ LayoutView.prototype = {
       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);
   },
 
@@ -572,33 +545,34 @@ LayoutView.prototype = {
    * @param {Boolean} isActive
    */
   setActive: function (isActive) {
     if (isActive === this.isActive) {
       return;
     }
     this.isActive = isActive;
 
+    let panel = this.doc.getElementById("sidebar-panel-layoutview");
+    panel.classList.toggle("inactive", !isActive);
+
     if (isActive) {
       this.trackReflows();
     } else {
       this.untrackReflows();
     }
   },
 
   /**
    * Compute the dimensions of the node and update the values in
-   * the inspector.xul document.
+   * the layoutview/view.xhtml 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("layoutview-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, {});
@@ -614,16 +588,22 @@ LayoutView.prototype = {
       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;
       }
 
+      // If the view isn't active, no need to do anything more.
+      if (!this.isActive) {
+        this.inspector.emit("layoutview-updated");
+        return null;
+      }
+
       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]);
@@ -671,20 +651,18 @@ LayoutView.prototype = {
 
       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("layoutview-updated");
-      return null;
+      return undefined;
     }).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
--- a/devtools/client/inspector/layout/test/head.js
+++ b/devtools/client/inspector/layout/test/head.js
@@ -50,33 +50,33 @@ function selectAndHighlightNode(nodeOrSe
 
 /**
  * Open the toolbox, with the inspector tool visible, and the layout-view
  * sidebar tab selected.
  * @return a promise that resolves when the inspector is ready and the layout
  * view is visible and ready
  */
 function openLayoutView() {
-  return openInspectorSidebarTab("computedview").then(data => {
+  return openInspectorSidebarTab("layoutview").then(data => {
     // The actual highligher show/hide methods are mocked in layoutview tests.
     // The highlighter is tested in devtools/inspector/test.
     function mockHighlighter({highlighter}) {
       highlighter.showBoxModel = function () {
         return promise.resolve();
       };
       highlighter.hideBoxModel = function () {
         return promise.resolve();
       };
     }
     mockHighlighter(data.toolbox);
 
     return {
       toolbox: data.toolbox,
       inspector: data.inspector,
-      view: data.inspector.computedview.layoutView,
+      view: data.inspector.layoutview,
       testActor: data.testActor
     };
   });
 }
 
 /**
  * Wait for the layoutview-updated event.
  * @return a promise
--- a/devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-color_01.js
+++ b/devtools/client/inspector/shared/test/browser_styleinspector_context-menu-copy-color_01.js
@@ -19,17 +19,17 @@ add_task(function* () {
   yield testView("ruleview", inspector);
   yield testView("computedview", inspector);
 });
 
 function* testView(viewId, inspector) {
   info("Testing " + viewId);
 
   yield inspector.sidebar.select(viewId);
-  let view = inspector[viewId].view || inspector[viewId].computedView;
+  let view = inspector[viewId].view;
   yield selectNode("div", inspector);
 
   testIsColorValueNode(view);
   testIsColorPopupOnAllNodes(view);
   yield clearCurrentNodeSelection(inspector);
 }
 
 /**
--- a/devtools/client/inspector/shared/test/browser_styleinspector_refresh_when_active.js
+++ b/devtools/client/inspector/shared/test/browser_styleinspector_refresh_when_active.js
@@ -15,17 +15,17 @@ add_task(function* () {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
 
   yield selectNode("#one", inspector);
 
   is(getRuleViewPropertyValue(view, "element", "color"), "red",
     "The rule-view shows the properties for test node one");
 
-  let cView = inspector.computedview.computedView;
+  let cView = inspector.computedview.view;
   let prop = getComputedViewProperty(cView, "color");
   ok(!prop, "The computed-view doesn't show the properties for test node one");
 
   info("Switching to the computed-view");
   let onComputedViewReady = inspector.once("computed-view-refreshed");
   selectComputedView(inspector);
   yield onComputedViewReady;
 
--- a/devtools/client/inspector/test/head.js
+++ b/devtools/client/inspector/test/head.js
@@ -292,17 +292,17 @@ function openRuleView() {
  * view is visible and ready
  */
 function openComputedView() {
   return openInspectorSidebarTab("computedview").then(data => {
     return {
       toolbox: data.toolbox,
       inspector: data.inspector,
       testActor: data.testActor,
-      view: data.inspector.computedview.computedView
+      view: data.inspector.computedview.view
     };
   });
 }
 
 /**
  * Select the rule view sidebar tab on an already opened inspector panel.
  *
  * @param {InspectorPanel} inspector
@@ -318,17 +318,17 @@ function selectRuleView(inspector) {
  * Select the computed view sidebar tab on an already opened inspector panel.
  *
  * @param {InspectorPanel} inspector
  *        The opened inspector panel
  * @return {CssComputedView} the computed view
  */
 function selectComputedView(inspector) {
   inspector.sidebar.select("computedview");
-  return inspector.computedview.computedView;
+  return inspector.computedview.view;
 }
 
 /**
  * Get the NodeFront for a node that matches a given css selector, via the
  * protocol.
  * @param {String|NodeFront} selector
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently
  * loaded in the toolbox
--- a/devtools/client/responsivedesign/test/head.js
+++ b/devtools/client/responsivedesign/test/head.js
@@ -142,17 +142,17 @@ var openInspectorSideBar = Task.async(fu
   let {toolbox, inspector} = yield openInspector();
 
   info("Selecting the " + id + " sidebar");
   inspector.sidebar.select(id);
 
   return {
     toolbox: toolbox,
     inspector: inspector,
-    view: inspector[id].view || inspector[id].computedView
+    view: inspector[id].view
   };
 });
 
 /**
  * Checks whether the inspector's sidebar corresponding to the given id already
  * exists
  * @param {InspectorPanel}
  * @param {String}
--- a/devtools/client/shared/telemetry.js
+++ b/devtools/client/shared/telemetry.js
@@ -92,16 +92,21 @@ Telemetry.prototype = {
       userHistogram: "DEVTOOLS_RULEVIEW_OPENED_PER_USER_FLAG",
       timerHistogram: "DEVTOOLS_RULEVIEW_TIME_ACTIVE_SECONDS"
     },
     computedview: {
       histogram: "DEVTOOLS_COMPUTEDVIEW_OPENED_COUNT",
       userHistogram: "DEVTOOLS_COMPUTEDVIEW_OPENED_PER_USER_FLAG",
       timerHistogram: "DEVTOOLS_COMPUTEDVIEW_TIME_ACTIVE_SECONDS"
     },
+    layoutview: {
+      histogram: "DEVTOOLS_LAYOUTVIEW_OPENED_COUNT",
+      userHistogram: "DEVTOOLS_LAYOUTVIEW_OPENED_PER_USER_FLAG",
+      timerHistogram: "DEVTOOLS_LAYOUTVIEW_TIME_ACTIVE_SECONDS"
+    },
     fontinspector: {
       histogram: "DEVTOOLS_FONTINSPECTOR_OPENED_COUNT",
       userHistogram: "DEVTOOLS_FONTINSPECTOR_OPENED_PER_USER_FLAG",
       timerHistogram: "DEVTOOLS_FONTINSPECTOR_TIME_ACTIVE_SECONDS"
     },
     animationinspector: {
       histogram: "DEVTOOLS_ANIMATIONINSPECTOR_OPENED_COUNT",
       userHistogram: "DEVTOOLS_ANIMATIONINSPECTOR_OPENED_PER_USER_FLAG",
--- a/devtools/client/shared/test/browser_telemetry_sidebar.js
+++ b/devtools/client/shared/test/browser_telemetry_sidebar.js
@@ -23,17 +23,17 @@ add_task(function* () {
   gBrowser.removeCurrentTab();
 });
 
 function* testSidebar(toolbox) {
   info("Testing sidebar");
 
   let inspector = toolbox.getCurrentPanel();
   let sidebarTools = ["ruleview", "computedview", "fontinspector",
-                      "animationinspector"];
+                      "layoutview", "animationinspector"];
 
   // Concatenate the array with itself so that we can open each tool twice.
   sidebarTools.push.apply(sidebarTools, sidebarTools);
 
   return new Promise(resolve => {
     // See TOOL_DELAY for why we need setTimeout here
     setTimeout(function selectSidebarTab() {
       let tool = sidebarTools.pop();
--- a/devtools/client/themes/computed.css
+++ b/devtools/client/themes/computed.css
@@ -19,25 +19,20 @@
 }
 
 #browser-style-checkbox {
   /* Bug 1200073 - extra space before the browser styles checkbox so
      they aren't squished together in a small window. */
   margin-inline-start: 5px;
 }
 
-#computedview-container {
-  overflow: auto;
-}
-
 #propertyContainer {
   -moz-user-select: text;
+  overflow: auto;
   flex: auto;
-  border-top-width: 1px;
-  border-top-style: dotted;
 }
 
 .row-striped {
   background: var(--theme-body-background);
 }
 
 .property-view-hidden,
 .property-content-hidden {
@@ -50,19 +45,17 @@
   flex-wrap: wrap;
 }
 
 .property-name-container {
   width: 202px;
 }
 
 .property-value-container {
-  display: flex;
-  flex: 1 1 168px;
-  overflow: hidden;
+  width: 168px;
 }
 
 .property-name-container > *,
 .property-value-container > * {
   display: inline-block;
   vertical-align: middle;
 }
 
--- a/devtools/client/themes/layout.css
+++ b/devtools/client/themes/layout.css
@@ -1,40 +1,71 @@
 /* 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/ */
 
+#sidebar-panel-layoutview {
+  display: block;
+  overflow: auto;
+}
+
+#layout-wrapper {
+  /* The sidebar-panel is not focusable, this wrapper will catch click events in
+     all the empty area around the layout-container */
+  height: 100%;
+}
+
 #layout-container {
   /* The view will grow bigger as the window gets resized, until 400px */
   max-width: 400px;
   margin: 0px auto;
   padding: 0;
+  /* "Contain" the absolutely positioned #layout-main element */
+  position: relative;
+}
+
+/* Header: contains the position and size of the element */
+
+#layout-header {
+  box-sizing: border-box;
+  width: 100%;
+  padding: 4px 14px;
+  display: -moz-box;
+  vertical-align: top;
+}
+
+#layout-header:dir(rtl) {
+  -moz-box-direction: reverse;
 }
 
-/* Header */
+#layout-header > span {
+  display: -moz-box;
+}
 
-#layout-header,
-#layout-info {
-  display: flex;
-  align-items: center;
-  padding: 4px 17px;
+#layout-element-size {
+  -moz-box-flex: 1;
 }
 
-#layout-geometry-editor {
-  visibility: hidden;
+#layout-element-size:dir(rtl) {
+  -moz-box-pack: end;
 }
 
-#layout-geometry-editor::before {
-  background: url(images/geometry-editor.svg) no-repeat center center / 16px 16px;
+@media (max-height: 250px) {
+  #layout-header {
+    padding-top: 0;
+    padding-bottom: 0;
+    margin-top: 10px;
+    margin-bottom: 8px;
+  }
 }
 
 /* Main: contains the box-model regions */
 
 #layout-main {
-  position: relative;
+  position: absolute;
   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 10px 14px;
   width: calc(100% - 2 * 14px);
@@ -279,17 +310,17 @@
     left: 16px;
   }
 
   .layout-border.layout-right {
     right: 17px;
   }
 }
 
-/* Legend: displayed inside regions */
+/* Legend, displayed inside regions */
 
 .layout-legend {
   position: absolute;
   margin: 5px 6px;
   z-index: 1;
 }
 
 .layout-legend[data-box="margin"] {
@@ -319,18 +350,28 @@
 }
 
 /* Make sure the content size doesn't appear as editable like the other sizes */
 
 .layout-size > span {
   cursor: default;
 }
 
-/* Layout info: contains the position and size of the element */
+/* Hide all values when the view is inactive */
 
-#layout-element-size {
-  flex: 1;
+#layout-container.inactive > #layout-header > #layout-element-position,
+#layout-container.inactive > #layout-header > #layout-element-size,
+#layout-container.inactive > #layout-main > p {
+   visibility: hidden;
 }
 
 #layout-position-group {
   display: flex;
   align-items: center;
 }
+
+#layout-geometry-editor {
+  visibility: hidden;
+}
+
+#layout-geometry-editor::before {
+  background: url(images/geometry-editor.svg) no-repeat center center / 16px 16px;
+}
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -43,16 +43,17 @@
 #ruleview-toolbar-container {
   display: flex;
   flex-direction: column;
   height: auto;
 }
 
 #ruleview-toolbar {
   display: flex;
+  height: 23px;
 }
 
 #ruleview-toolbar > .devtools-searchbox:first-child {
   padding-inline-start: 0px;
 }
 
 #ruleview-command-toolbar {
   display: flex;
--- a/devtools/client/themes/toolbars.css
+++ b/devtools/client/themes/toolbars.css
@@ -428,17 +428,16 @@
 .devtools-filterinput .textbox-input::-moz-placeholder {
   font-style: normal;
 }
 
 /* Searchbox is a div container element for a search input element */
 .devtools-searchbox {
   display: flex;
   flex: 1;
-  height: 23px;
   position: relative;
   padding: 0 3px;
 }
 
 /* The spacing is accomplished with a padding on the searchbox */
 .devtools-searchbox > .devtools-textinput,
 .devtools-searchbox > .devtools-searchinput,
 .devtools-searchbox > .devtools-filterinput {
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -6323,16 +6323,24 @@
   "DEVTOOLS_COMPUTEDVIEW_OPENED_COUNT": {
     "alert_emails": ["dev-developer-tools@lists.mozilla.org"],
     "expires_in_version": "never",
     "kind": "count",
     "bug_numbers": [1247985],
     "description": "Number of times the DevTools Computed View has been opened.",
     "releaseChannelCollection": "opt-out"
   },
+  "DEVTOOLS_LAYOUTVIEW_OPENED_COUNT": {
+    "alert_emails": ["dev-developer-tools@lists.mozilla.org"],
+    "expires_in_version": "never",
+    "kind": "count",
+    "bug_numbers": [1247985],
+    "description": "Number of times the DevTools Layout View has been opened.",
+    "releaseChannelCollection": "opt-out"
+  },
   "DEVTOOLS_FONTINSPECTOR_OPENED_COUNT": {
     "alert_emails": ["dev-developer-tools@lists.mozilla.org"],
     "expires_in_version": "never",
     "kind": "count",
     "bug_numbers": [1247985],
     "description": "Number of times the DevTools Font Inspector has been opened.",
     "releaseChannelCollection": "opt-out"
   },
@@ -6596,16 +6604,21 @@
     "kind": "flag",
     "description": "Number of users that have opened the DevTools Rule View."
   },
   "DEVTOOLS_COMPUTEDVIEW_OPENED_PER_USER_FLAG": {
     "expires_in_version": "never",
     "kind": "flag",
     "description": "Number of users that have opened the DevTools Computed View."
   },
+  "DEVTOOLS_LAYOUTVIEW_OPENED_PER_USER_FLAG": {
+    "expires_in_version": "never",
+    "kind": "flag",
+    "description": "Number of users that have opened the DevTools Layout View."
+  },
   "DEVTOOLS_FONTINSPECTOR_OPENED_PER_USER_FLAG": {
     "expires_in_version": "never",
     "kind": "flag",
     "description": "Number of users that have opened the DevTools Font Inspector."
   },
   "DEVTOOLS_ANIMATIONINSPECTOR_OPENED_PER_USER_FLAG": {
     "expires_in_version": "never",
     "kind": "flag",
@@ -6802,16 +6815,23 @@
   },
   "DEVTOOLS_COMPUTEDVIEW_TIME_ACTIVE_SECONDS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 10000000,
     "n_buckets": 100,
     "description": "How long has the computed view been active (seconds)"
   },
+  "DEVTOOLS_LAYOUTVIEW_TIME_ACTIVE_SECONDS": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 10000000,
+    "n_buckets": 100,
+    "description": "How long has the layout view been active (seconds)"
+  },
   "DEVTOOLS_FONTINSPECTOR_TIME_ACTIVE_SECONDS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 10000000,
     "n_buckets": 100,
     "description": "How long has the font inspector been active (seconds)"
   },
   "DEVTOOLS_ANIMATIONINSPECTOR_TIME_ACTIVE_SECONDS": {