Bug 897960 - walker should support mozbrowser iframes. r=dcamp
authorPaul Rouget <paul@mozilla.com>
Sun, 08 Sep 2013 11:01:00 +0200
changeset 146126 89a059433037889ef254dd7f587546be126ca3c9
parent 146125 fab07b9d6dee1b52ede6e8049e8c904369512c15
child 146127 bbb54cde82c33ad1aa657ff69c9a4557e2908ddf
push id25242
push useremorley@mozilla.com
push dateMon, 09 Sep 2013 12:13:52 +0000
treeherdermozilla-central@218d4334d29e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdcamp
bugs897960
milestone26.0a1
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
Bug 897960 - walker should support mozbrowser iframes. r=dcamp
browser/devtools/commandline/BuiltinCommands.jsm
browser/devtools/debugger/debugger-controller.js
browser/devtools/debugger/debugger-toolbar.js
browser/devtools/debugger/test/browser_dbg_pause-resume.js
browser/devtools/inspector/breadcrumbs.js
browser/devtools/inspector/highlighter.js
browser/devtools/inspector/test/browser_inspector_bug_817558_delete_node.js
browser/devtools/inspector/test/browser_inspector_destroyselection.js
browser/devtools/inspector/test/head.js
browser/devtools/layoutview/view.js
browser/devtools/markupview/markup-view.js
browser/devtools/scratchpad/scratchpad.js
browser/devtools/shared/test/browser_layoutHelpers.js
browser/devtools/tilt/test/browser_tilt_utils05.js
browser/devtools/tilt/test/browser_tilt_utils07.js
browser/devtools/tilt/tilt-utils.js
--- a/browser/devtools/commandline/BuiltinCommands.jsm
+++ b/browser/devtools/commandline/BuiltinCommands.jsm
@@ -1742,17 +1742,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 
       if (!fullpage) {
         if (!node) {
           left = window.scrollX;
           top = window.scrollY;
           width = window.innerWidth;
           height = window.innerHeight;
         } else {
-          let rect = LayoutHelpers.getRect(node, window);
+          let lh = new LayoutHelpers(window);
+          let rect = lh.getRect(node, window);
           top = rect.top;
           left = rect.left;
           width = rect.width;
           height = rect.height;
         }
       } else {
         width = window.innerWidth + window.scrollMaxX;
         height = window.innerHeight + window.scrollMaxY;
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -14,17 +14,16 @@ const FETCH_SOURCE_RESPONSE_DELAY = 50; 
 const FRAME_STEP_CLEAR_DELAY = 100; // ms
 const CALL_STACK_PAGE_SIZE = 25; // frames
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
 let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
 Cu.import("resource:///modules/source-editor.jsm");
-Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
 Cu.import("resource:///modules/devtools/BreadcrumbsWidget.jsm");
 Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
 Cu.import("resource:///modules/devtools/VariablesView.jsm");
 Cu.import("resource:///modules/devtools/VariablesViewController.jsm");
 Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Parser",
   "resource:///modules/devtools/Parser.jsm");
@@ -35,16 +34,23 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 Object.defineProperty(this, "NetworkHelper", {
   get: function() {
     return devtools.require("devtools/toolkit/webconsole/network-helper");
   },
   configurable: true,
   enumerable: true
 });
 
+Object.defineProperty(this, "DevtoolsHelpers", {
+  get: function() {
+    return devtools.require("devtools/shared/helpers");
+  },
+  configurable: true,
+  enumerable: true
+});
 
 /**
  * Object defining the debugger controller components.
  */
 let DebuggerController = {
   /**
    * Initializes the debugger controller.
    */
--- a/browser/devtools/debugger/debugger-toolbar.js
+++ b/browser/devtools/debugger/debugger-toolbar.js
@@ -33,20 +33,20 @@ ToolbarView.prototype = {
     this._instrumentsPaneToggleButton = document.getElementById("instruments-pane-toggle");
     this._resumeOrderPanel = document.getElementById("resumption-order-panel");
     this._resumeButton = document.getElementById("resume");
     this._stepOverButton = document.getElementById("step-over");
     this._stepInButton = document.getElementById("step-in");
     this._stepOutButton = document.getElementById("step-out");
     this._chromeGlobals = document.getElementById("chrome-globals");
 
-    let resumeKey = LayoutHelpers.prettyKey(document.getElementById("resumeKey"), true);
-    let stepOverKey = LayoutHelpers.prettyKey(document.getElementById("stepOverKey"), true);
-    let stepInKey = LayoutHelpers.prettyKey(document.getElementById("stepInKey"), true);
-    let stepOutKey = LayoutHelpers.prettyKey(document.getElementById("stepOutKey"), true);
+    let resumeKey = DevtoolsHelpers.prettyKey(document.getElementById("resumeKey"), true);
+    let stepOverKey = DevtoolsHelpers.prettyKey(document.getElementById("stepOverKey"), true);
+    let stepInKey = DevtoolsHelpers.prettyKey(document.getElementById("stepInKey"), true);
+    let stepOutKey = DevtoolsHelpers.prettyKey(document.getElementById("stepOutKey"), true);
     this._resumeTooltip = L10N.getFormatStr("resumeButtonTooltip", resumeKey);
     this._pauseTooltip = L10N.getFormatStr("pauseButtonTooltip", resumeKey);
     this._stepOverTooltip = L10N.getFormatStr("stepOverTooltip", stepOverKey);
     this._stepInTooltip = L10N.getFormatStr("stepInTooltip", stepInKey);
     this._stepOutTooltip = L10N.getFormatStr("stepOutTooltip", stepOutKey);
 
     this._instrumentsPaneToggleButton.addEventListener("mousedown", this._onTogglePanesPressed, false);
     this._resumeButton.addEventListener("mousedown", this._onResumePressed, false);
@@ -724,22 +724,22 @@ FilterView.prototype = {
     this._functionOperatorLabel = document.getElementById("function-operator-label");
     this._tokenOperatorButton = document.getElementById("token-operator-button");
     this._tokenOperatorLabel = document.getElementById("token-operator-label");
     this._lineOperatorButton = document.getElementById("line-operator-button");
     this._lineOperatorLabel = document.getElementById("line-operator-label");
     this._variableOperatorButton = document.getElementById("variable-operator-button");
     this._variableOperatorLabel = document.getElementById("variable-operator-label");
 
-    this._fileSearchKey = LayoutHelpers.prettyKey(document.getElementById("fileSearchKey"), true);
-    this._globalSearchKey = LayoutHelpers.prettyKey(document.getElementById("globalSearchKey"), true);
-    this._filteredFunctionsKey = LayoutHelpers.prettyKey(document.getElementById("functionSearchKey"), true);
-    this._tokenSearchKey = LayoutHelpers.prettyKey(document.getElementById("tokenSearchKey"), true);
-    this._lineSearchKey = LayoutHelpers.prettyKey(document.getElementById("lineSearchKey"), true);
-    this._variableSearchKey = LayoutHelpers.prettyKey(document.getElementById("variableSearchKey"), true);
+    this._fileSearchKey = DevtoolsHelpers.prettyKey(document.getElementById("fileSearchKey"), true);
+    this._globalSearchKey = DevtoolsHelpers.prettyKey(document.getElementById("globalSearchKey"), true);
+    this._filteredFunctionsKey = DevtoolsHelpers.prettyKey(document.getElementById("functionSearchKey"), true);
+    this._tokenSearchKey = DevtoolsHelpers.prettyKey(document.getElementById("tokenSearchKey"), true);
+    this._lineSearchKey = DevtoolsHelpers.prettyKey(document.getElementById("lineSearchKey"), true);
+    this._variableSearchKey = DevtoolsHelpers.prettyKey(document.getElementById("variableSearchKey"), true);
 
     this._searchbox.addEventListener("click", this._onClick, false);
     this._searchbox.addEventListener("select", this._onSearch, false);
     this._searchbox.addEventListener("input", this._onSearch, false);
     this._searchbox.addEventListener("keypress", this._onKeyPress, false);
     this._searchbox.addEventListener("blur", this._onBlur, false);
 
     this._globalOperatorButton.setAttribute("label", SEARCH_GLOBAL_FLAG);
--- a/browser/devtools/debugger/test/browser_dbg_pause-resume.js
+++ b/browser/devtools/debugger/test/browser_dbg_pause-resume.js
@@ -3,54 +3,54 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var gPane = null;
 var gTab = null;
 var gDebugger = null;
 var gView = null;
-var gLH = null;
+var gDH = null;
 var gL10N = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
     gDebugger = gPane.panelWin;
     gView = gDebugger.DebuggerView;
-    gLH = gDebugger.LayoutHelpers;
+    gDH = gDebugger.DevtoolsHelpers;
     gL10N = gDebugger.L10N;
 
     testPause();
   });
 }
 
 function testPause() {
   is(gDebugger.DebuggerController.activeThread.paused, false,
     "Should be running after debug_tab_pane.");
 
   let button = gDebugger.document.getElementById("resume");
   is(button.getAttribute("tooltiptext"),
      gL10N.getFormatStr("pauseButtonTooltip",
-      gLH.prettyKey(gDebugger.document.getElementById("resumeKey"))),
+      gDH.prettyKey(gDebugger.document.getElementById("resumeKey"))),
     "Button tooltip should be pause when running.");
 
   gDebugger.DebuggerController.activeThread.addOneTimeListener("paused", function() {
     Services.tm.currentThread.dispatch({ run: function() {
 
       let frames = gDebugger.DebuggerView.StackFrames.widget._list;
       let childNodes = frames.childNodes;
 
       is(gDebugger.DebuggerController.activeThread.paused, true,
         "Should be paused after an interrupt request.");
 
       is(button.getAttribute("tooltiptext"),
          gL10N.getFormatStr("resumeButtonTooltip",
-          gLH.prettyKey(gDebugger.document.getElementById("resumeKey"))),
+          gDH.prettyKey(gDebugger.document.getElementById("resumeKey"))),
         "Button tooltip should be resume when paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 0,
         "Should have no frames when paused in the main loop.");
 
       testResume();
     }}, 0);
   });
@@ -65,17 +65,17 @@ function testResume() {
     Services.tm.currentThread.dispatch({ run: function() {
 
       is(gDebugger.DebuggerController.activeThread.paused, false,
         "Should be paused after an interrupt request.");
 
       let button = gDebugger.document.getElementById("resume");
       is(button.getAttribute("tooltiptext"),
          gL10N.getFormatStr("pauseButtonTooltip",
-          gLH.prettyKey(gDebugger.document.getElementById("resumeKey"))),
+          gDH.prettyKey(gDebugger.document.getElementById("resumeKey"))),
         "Button tooltip should be pause when running.");
 
       closeDebuggerAndFinish();
     }}, 0);
   });
 
   EventUtils.sendMouseEvent({ type: "mousedown" },
     gDebugger.document.getElementById("resume"),
@@ -83,11 +83,11 @@ function testResume() {
 }
 
 registerCleanupFunction(function() {
   removeTab(gTab);
   gPane = null;
   gTab = null;
   gDebugger = null;
   gView = null;
-  gLH = null;
+  gDH = null;
   gL10N = null;
 });
--- a/browser/devtools/inspector/breadcrumbs.js
+++ b/browser/devtools/inspector/breadcrumbs.js
@@ -6,17 +6,16 @@
 
 const {Cc, Cu, Ci} = require("chrome");
 
 const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
 const ENSURE_SELECTION_VISIBLE_DELAY = 50; // ms
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
-Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 let promise = require("sdk/core/promise");
 
 const LOW_PRIORITY_ELEMENTS = {
   "HEAD": true,
   "BASE": true,
   "BASEFONT": true,
--- a/browser/devtools/inspector/highlighter.js
+++ b/browser/devtools/inspector/highlighter.js
@@ -88,16 +88,17 @@ function LocalHighlighter(aTarget, aInsp
 {
   this.target = aTarget;
   this.tab = aTarget.tab;
   this.toolbox = aToolbox;
   this.browser = this.tab.linkedBrowser;
   this.chromeDoc = this.tab.ownerDocument;
   this.chromeWin = this.chromeDoc.defaultView;
   this.inspector = aInspector
+  this.layoutHelpers = new LayoutHelpers(this.browser.contentWindow);
 
   EventEmitter.decorate(this);
 
   this._init();
 }
 
 LocalHighlighter.prototype = {
   get selection() {
@@ -220,17 +221,17 @@ LocalHighlighter.prototype = {
       if (this.selection.reason != "navigateaway") {
         this.disabled = false;
       }
       this.show();
       this.updateInfobar();
       this.invalidateSize();
       if (!this._highlighting &&
           this.selection.reason != "highlighter") {
-        LayoutHelpers.scrollIntoViewIfNeeded(this.selection.node);
+        this.layoutHelpers.scrollIntoViewIfNeeded(this.selection.node);
       }
     } else {
       this.disabled = true;
       this.hide();
     }
   },
 
   /**
@@ -250,17 +251,17 @@ LocalHighlighter.prototype = {
     // here, do the check manually.
     if (!this.selection.node ||
         !this.selection.node.ownerDocument ||
         !this.selection.node.ownerDocument.defaultView) {
       return;
     }
 
     let clientRect = this.selection.node.getBoundingClientRect();
-    let rect = LayoutHelpers.getDirtyRect(this.selection.node);
+    let rect = this.layoutHelpers.getDirtyRect(this.selection.node);
     this.highlightRectangle(rect);
 
     this.moveInfobar();
 
     if (this._highlighting) {
       this.showOutline();
       this.emit("highlighting");
     }
@@ -456,17 +457,17 @@ LocalHighlighter.prototype = {
     let texthbox = this.chromeDoc.createElement("hbox");
     texthbox.className = "highlighter-nodeinfobar-text";
     texthbox.setAttribute("align", "center");
     texthbox.setAttribute("flex", "1");
 
     texthbox.addEventListener("mousedown", function(aEvent) {
       // On click, show the node:
       if (this.selection.isElementNode()) {
-        LayoutHelpers.scrollIntoViewIfNeeded(this.selection.node);
+        this.layoutHelpers.scrollIntoViewIfNeeded(this.selection.node);
       }
     }.bind(this), true);
 
     texthbox.appendChild(tagNameLabel);
     texthbox.appendChild(idLabel);
     texthbox.appendChild(classesBox);
     texthbox.appendChild(pseudoClassesBox);
 
@@ -509,17 +510,17 @@ LocalHighlighter.prototype = {
 
     let oldRect = this._contentRect;
 
     if (oldRect && aRect.top == oldRect.top && aRect.left == oldRect.left &&
         aRect.width == oldRect.width && aRect.height == oldRect.height) {
       return; // same rectangle
     }
 
-    let aRectScaled = LayoutHelpers.getZoomedRect(this.win, aRect);
+    let aRectScaled = this.layoutHelpers.getZoomedRect(this.win, aRect);
 
     if (aRectScaled.left >= 0 && aRectScaled.top >= 0 &&
         aRectScaled.width > 0 && aRectScaled.height > 0) {
 
       this.showOutline();
 
       // The bottom div and the right div are flexibles (flex=1).
       // We don't need to resize them.
@@ -804,17 +805,17 @@ LocalHighlighter.prototype = {
    */
   handleMouseMove: function LocalHighlighter_handleMouseMove(aEvent)
   {
     let doc = aEvent.target.ownerDocument;
 
     // This should never happen, but just in case, we don't let the
     // highlighter highlight browser nodes.
     if (doc && doc != this.chromeDoc) {
-      let element = LayoutHelpers.getElementFromPoint(aEvent.target.ownerDocument,
+      let element = this.layoutHelpers.getElementFromPoint(aEvent.target.ownerDocument,
         aEvent.clientX, aEvent.clientY);
       if (element && element != this.selection.node) {
         this.selection.setNode(element, "highlighter");
       }
     }
   },
 };
 
--- a/browser/devtools/inspector/test/browser_inspector_bug_817558_delete_node.js
+++ b/browser/devtools/inspector/test/browser_inspector_bug_817558_delete_node.js
@@ -28,17 +28,18 @@ function test()
     inspector = aInspector;
     inspector.selection.setNode(node);
     inspector.once("inspector-updated", () => {
       let parentNode = node.parentNode;
       parentNode.removeChild(node);
 
       let tmp = {};
       Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tmp);
-      ok(!tmp.LayoutHelpers.isNodeConnected(node), "Node considered as disconnected.");
+      let lh = new tmp.LayoutHelpers(window.content);
+      ok(!lh.isNodeConnected(node), "Node considered as disconnected.");
 
       // Wait for the inspector to process the mutation
       inspector.once("inspector-updated", () => {
         is(inspector.selection.node, parentNode, "parent of selection got selected");
         finishUp();
       });
     });
   };
--- a/browser/devtools/inspector/test/browser_inspector_destroyselection.js
+++ b/browser/devtools/inspector/test/browser_inspector_destroyselection.js
@@ -28,17 +28,18 @@ function test()
     inspector = aInspector;
     inspector.selection.setNode(node);
 
     iframe.parentNode.removeChild(iframe);
     iframe = null;
 
     let tmp = {};
     Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tmp);
-    ok(!tmp.LayoutHelpers.isNodeConnected(node), "Node considered as disconnected.");
+    let lh = new tmp.LayoutHelpers(window.content);
+    ok(!lh.isNodeConnected(node), "Node considered as disconnected.");
     ok(!inspector.selection.isConnected(), "Selection considered as disconnected");
 
     finishUp();
   }
 
   function finishUp() {
     node = null;
     gBrowser.removeCurrentTab();
--- a/browser/devtools/inspector/test/head.js
+++ b/browser/devtools/inspector/test/head.js
@@ -72,17 +72,18 @@ function getHighlitNode()
   let b = {
     x: a.x + h._contentRect.width,
     y: a.y + h._contentRect.height
   };
 
   // Get midpoint of diagonal line.
   let midpoint = midPoint(a, b);
 
-  return LayoutHelpers.getElementFromPoint(h.win.document, midpoint.x,
+  let lh = new LayoutHelpers(window.content);
+  return lh.getElementFromPoint(h.win.document, midpoint.x,
     midpoint.y);
 }
 
 
 function midPoint(aPointA, aPointB)
 {
   let pointC = { };
   pointC.x = (aPointB.x - aPointA.x) / 2 + aPointA.x;
--- a/browser/devtools/layoutview/view.js
+++ b/browser/devtools/layoutview/view.js
@@ -3,17 +3,16 @@
 /* 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 Cu = Components.utils;
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
 Cu.import("resource://gre/modules/devtools/Loader.jsm");
 Cu.import("resource://gre/modules/devtools/Console.jsm");
 
 const promise = devtools.require("sdk/core/promise");
 
 function LayoutView(aInspector, aWindow)
 {
   this.inspector = aInspector;
--- a/browser/devtools/markupview/markup-view.js
+++ b/browser/devtools/markupview/markup-view.js
@@ -48,16 +48,18 @@ loader.lazyGetter(this, "AutocompletePop
 function MarkupView(aInspector, aFrame, aControllerWindow)
 {
   this._inspector = aInspector;
   this.walker = this._inspector.walker;
   this._frame = aFrame;
   this.doc = this._frame.contentDocument;
   this._elt = this.doc.querySelector("#root");
 
+  this.layoutHelpers = new LayoutHelpers(this.doc.defaultView);
+
   try {
     this.maxChildren = Services.prefs.getIntPref("devtools.markup.pagesize");
   } catch(ex) {
     this.maxChildren = DEFAULT_MAX_CHILDREN;
   }
 
   // Creating the popup to be used to show CSS suggestions.
   let options = {
@@ -401,17 +403,17 @@ MarkupView.prototype = {
       this.importNode(parent);
       this.expandNode(parent);
     }
 
     return this._waitForChildren().then(() => {
       return this._ensureVisible(aNode);
     }).then(() => {
       // Why is this not working?
-      LayoutHelpers.scrollIntoViewIfNeeded(this._containers.get(aNode).editor.elt, centered);
+      this.layoutHelpers.scrollIntoViewIfNeeded(this._containers.get(aNode).editor.elt, centered);
     });
   },
 
   /**
    * Expand the container's children.
    */
   _expandContainer: function MT__expandContainer(aContainer)
   {
@@ -1226,17 +1228,17 @@ ElementEditor.prototype = {
       attrName: aAttr.name,
     };
     this.template("attribute", data);
     var {attr, inner, name, val} = data;
 
     // Double quotes need to be handled specially to prevent DOMParser failing.
     // name="v"a"l"u"e" when editing -> name='v"a"l"u"e"'
     // name="v'a"l'u"e" when editing -> name="v'a&quot;l'u&quot;e"
-    let editValueDisplayed = aAttr.value;
+    let editValueDisplayed = aAttr.value || "";
     let hasDoubleQuote = editValueDisplayed.contains('"');
     let hasSingleQuote = editValueDisplayed.contains("'");
     let initial = aAttr.name + '="' + editValueDisplayed + '"';
 
     // Can't just wrap value with ' since the value contains both " and '.
     if (hasDoubleQuote && hasSingleQuote) {
         editValueDisplayed = editValueDisplayed.replace(/\"/g, "&quot;");
         initial = aAttr.name + '="' + editValueDisplayed + '"';
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -14,24 +14,24 @@
 
 "use strict";
 
 let require = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
 
 let { Cc, Ci, Cu } = require("chrome");
 let promise = require("sdk/core/promise");
 let Telemetry = require("devtools/shared/telemetry");
+let DevtoolsHelpers = require("devtools/shared/helpers");
 let TargetFactory = require("devtools/framework/target").TargetFactory;
 const escodegen = require("escodegen/escodegen");
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource:///modules/source-editor.jsm");
-Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
 Cu.import("resource:///modules/devtools/scratchpad-manager.jsm");
 Cu.import("resource://gre/modules/jsdebugger.jsm");
 Cu.import("resource:///modules/devtools/gDevTools.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
 Cu.import("resource://gre/modules/reflect.jsm");
 Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
 
@@ -1279,19 +1279,19 @@ var Scratchpad = {
       let chromeContextCommand = document.getElementById("sp-cmd-browserContext");
       environmentMenu.removeAttribute("hidden");
       chromeContextCommand.removeAttribute("disabled");
       errorConsoleCommand.removeAttribute("disabled");
     }
 
     let initialText = this.strings.formatStringFromName(
       "scratchpadIntro1",
-      [LayoutHelpers.prettyKey(document.getElementById("sp-key-run")),
-       LayoutHelpers.prettyKey(document.getElementById("sp-key-inspect")),
-       LayoutHelpers.prettyKey(document.getElementById("sp-key-display"))],
+      [DevtoolsHelpers.prettyKey(document.getElementById("sp-key-run")),
+       DevtoolsHelpers.prettyKey(document.getElementById("sp-key-inspect")),
+       DevtoolsHelpers.prettyKey(document.getElementById("sp-key-display"))],
       3);
 
     let args = window.arguments;
 
     if (args && args[0] instanceof Ci.nsIDialogParamBlock) {
       args = args[0];
     } else {
       // If this Scratchpad window doesn't have any arguments, horrible
--- a/browser/devtools/shared/test/browser_layoutHelpers.js
+++ b/browser/devtools/shared/test/browser_layoutHelpers.js
@@ -20,78 +20,80 @@ function test() {
     let doc = browser.contentDocument;
     runTest(doc.defaultView, doc.getElementById('some'));
     gBrowser.removeCurrentTab();
     finish();
   });
 }
 
 function runTest(win, some) {
+  let lh = new LayoutHelpers(win);
+
   some.style.top = win.innerHeight + 'px';
   some.style.left = win.innerWidth + 'px';
   // The tests start with a black 2x2 pixels square below bottom right.
   // Do not resize the window during the tests.
 
   win.scroll(win.innerWidth / 2, win.innerHeight + 2);  // Above the viewport.
-  LayoutHelpers.scrollIntoViewIfNeeded(some);
+  lh.scrollIntoViewIfNeeded(some);
   is(win.scrollY, Math.floor(win.innerHeight / 2) + 1,
      'Element completely hidden above should appear centered.');
 
   win.scroll(win.innerWidth / 2, win.innerHeight + 1);  // On the top edge.
-  LayoutHelpers.scrollIntoViewIfNeeded(some);
+  lh.scrollIntoViewIfNeeded(some);
   is(win.scrollY, win.innerHeight,
      'Element partially visible above should appear above.');
 
   win.scroll(win.innerWidth / 2, 0);  // Just below the viewport.
-  LayoutHelpers.scrollIntoViewIfNeeded(some);
+  lh.scrollIntoViewIfNeeded(some);
   is(win.scrollY, Math.floor(win.innerHeight / 2) + 1,
      'Element completely hidden below should appear centered.');
 
   win.scroll(win.innerWidth / 2, 1);  // On the bottom edge.
-  LayoutHelpers.scrollIntoViewIfNeeded(some);
+  lh.scrollIntoViewIfNeeded(some);
   is(win.scrollY, 2,
      'Element partially visible below should appear below.');
 
 
   win.scroll(win.innerWidth / 2, win.innerHeight + 2);  // Above the viewport.
-  LayoutHelpers.scrollIntoViewIfNeeded(some, false);
+  lh.scrollIntoViewIfNeeded(some, false);
   is(win.scrollY, win.innerHeight,
      'Element completely hidden above should appear above ' +
      'if parameter is false.');
 
   win.scroll(win.innerWidth / 2, win.innerHeight + 1);  // On the top edge.
-  LayoutHelpers.scrollIntoViewIfNeeded(some, false);
+  lh.scrollIntoViewIfNeeded(some, false);
   is(win.scrollY, win.innerHeight,
      'Element partially visible above should appear above ' +
      'if parameter is false.');
 
   win.scroll(win.innerWidth / 2, 0);  // Below the viewport.
-  LayoutHelpers.scrollIntoViewIfNeeded(some, false);
+  lh.scrollIntoViewIfNeeded(some, false);
   is(win.scrollY, 2,
      'Element completely hidden below should appear below ' +
      'if parameter is false.');
 
   win.scroll(win.innerWidth / 2, 1);  // On the bottom edge.
-  LayoutHelpers.scrollIntoViewIfNeeded(some, false);
+  lh.scrollIntoViewIfNeeded(some, false);
   is(win.scrollY, 2,
      'Element partially visible below should appear below ' +
      'if parameter is false.');
 
   // The case of iframes.
   win.scroll(0, 0);
 
   let frame = win.document.getElementById('frame');
   let fwin = frame.contentWindow;
 
   frame.style.top = win.innerHeight + 'px';
   frame.style.left = win.innerWidth + 'px';
 
   fwin.addEventListener('load', function frameLoad() {
     let some = fwin.document.getElementById('some');
-    LayoutHelpers.scrollIntoViewIfNeeded(some);
+    lh.scrollIntoViewIfNeeded(some);
     is(win.scrollX, Math.floor(win.innerWidth / 2) + 20,
        'Scrolling from an iframe should center the iframe vertically.');
     is(win.scrollY, Math.floor(win.innerHeight / 2) + 20,
        'Scrolling from an iframe should center the iframe horizontally.');
     is(fwin.scrollX, Math.floor(fwin.innerWidth / 2) + 1,
        'Scrolling from an iframe should center the element vertically.');
     is(fwin.scrollY, Math.floor(fwin.innerHeight / 2) + 1,
        'Scrolling from an iframe should center the element horizontally.');
--- a/browser/devtools/tilt/test/browser_tilt_utils05.js
+++ b/browser/devtools/tilt/test/browser_tilt_utils05.js
@@ -50,20 +50,21 @@ function test() {
 
     is(cwDimensions.width - iframe.contentWindow.scrollMaxX,
       iframe.contentWindow.innerWidth,
       "The content window width wasn't calculated correctly.");
     is(cwDimensions.height - iframe.contentWindow.scrollMaxY,
       iframe.contentWindow.innerHeight,
       "The content window height wasn't calculated correctly.");
 
-    let nodeCoordinates = LayoutHelpers.getRect(
+    let lh = new LayoutHelpers(gBrowser.contentWindow);
+    let nodeCoordinates = lh.getRect(
       iframe.contentDocument.getElementById("test-div"), iframe.contentWindow);
 
-    let frameOffset = LayoutHelpers.getIframeContentOffset(iframe);
+    let frameOffset = lh.getIframeContentOffset(iframe);
     let frameRect = iframe.getBoundingClientRect();
 
     is(nodeCoordinates.top, frameRect.top + frameOffset[0] + 98,
       "The node coordinates top value wasn't calculated correctly.");
     is(nodeCoordinates.left, frameRect.left + frameOffset[1] + 76,
       "The node coordinates left value wasn't calculated correctly.");
     is(nodeCoordinates.width, 123,
       "The node coordinates width value wasn't calculated correctly.");
--- a/browser/devtools/tilt/test/browser_tilt_utils07.js
+++ b/browser/devtools/tilt/test/browser_tilt_utils07.js
@@ -99,20 +99,21 @@ function test() {
 
     is(cwDimensions.width - iframe.contentWindow.scrollMaxX,
       iframe.contentWindow.innerWidth,
       "The content window width wasn't calculated correctly.");
     is(cwDimensions.height - iframe.contentWindow.scrollMaxY,
       iframe.contentWindow.innerHeight,
       "The content window height wasn't calculated correctly.");
 
-    let nodeCoordinates = LayoutHelpers.getRect(
+    let lh = new LayoutHelpers(gBrowser.contentWindow);
+    let nodeCoordinates = lh.getRect(
       iframe.contentDocument.getElementById("test-div"), iframe.contentWindow);
 
-    let frameOffset = LayoutHelpers.getIframeContentOffset(iframe);
+    let frameOffset = lh.getIframeContentOffset(iframe);
     let frameRect = iframe.getBoundingClientRect();
 
     is(nodeCoordinates.top, frameRect.top + frameOffset[0],
       "The node coordinates top value wasn't calculated correctly.");
     is(nodeCoordinates.left, frameRect.left + frameOffset[1],
       "The node coordinates left value wasn't calculated correctly.");
     is(nodeCoordinates.width, 123,
       "The node coordinates width value wasn't calculated correctly.");
--- a/browser/devtools/tilt/tilt-utils.js
+++ b/browser/devtools/tilt/tilt-utils.js
@@ -400,18 +400,19 @@ TiltUtils.DOM = {
    *                  width of the node
    *         {Number} height
    *                  height of the node
    *         {Number} thickness
    *                  thickness of the node
    */
   getNodePosition: function TUD_getNodePosition(aContentWindow, aNode,
                                                 aParentPosition) {
+    let lh = new LayoutHelpers(aContentWindow);
     // get the x, y, width and height coordinates of the node
-    let coord = LayoutHelpers.getRect(aNode, aContentWindow);
+    let coord = lh.getRect(aNode, aContentWindow);
     if (!coord) {
       return null;
     }
 
     coord.depth = aParentPosition ? (aParentPosition.depth + aParentPosition.thickness) : 0;
     coord.thickness = STACK_THICKNESS;
 
     return coord;