Bug 703031 - [highlighter] Refactor the highlighter code. Create highlighter.jsm - Patch D; r=rcampbell
authorPaul Rouget <paul@mozilla.com>
Tue, 06 Dec 2011 18:23:20 +0100
changeset 86008 3446a54199ab3f3e145bcaa1fbb9553d2b273512
parent 86007 a62e69926f832a2c4ff84eea30ab0f65aa75dbed
child 86009 5104705ee96a447a4d6fed2f74eb1b581171bd0a
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrcampbell
bugs703031
milestone12.0a1
Bug 703031 - [highlighter] Refactor the highlighter code. Create highlighter.jsm - Patch D; r=rcampbell
browser/devtools/highlighter/highlighter.jsm
browser/devtools/highlighter/test/Makefile.in
browser/devtools/highlighter/test/browser_inspector_breadcrumbs.js
browser/devtools/highlighter/test/browser_inspector_bug_665880.js
browser/devtools/highlighter/test/browser_inspector_bug_672902_keyboard_shortcuts.js
browser/devtools/highlighter/test/browser_inspector_bug_674871.js
browser/devtools/highlighter/test/browser_inspector_editor.js
browser/devtools/highlighter/test/browser_inspector_highlighter.js
browser/devtools/highlighter/test/browser_inspector_iframeTest.js
browser/devtools/highlighter/test/browser_inspector_initialization.js
browser/devtools/highlighter/test/browser_inspector_keybindings.js
browser/devtools/highlighter/test/browser_inspector_registertools.js
browser/devtools/highlighter/test/browser_inspector_scrolling.js
browser/devtools/highlighter/test/browser_inspector_treePanel_click.js
browser/devtools/highlighter/test/browser_inspector_treeSelection.js
browser/devtools/highlighter/test/head.js
browser/devtools/webconsole/test/browser_webconsole_bug_653531_highlighter_console_helper.js
--- a/browser/devtools/highlighter/highlighter.jsm
+++ b/browser/devtools/highlighter/highlighter.jsm
@@ -619,67 +619,16 @@ Highlighter.prototype = {
       this.nodeInfo.container.style.left = "0";
       this.nodeInfo.container.style.top = "0";
       this.nodeInfo.container.setAttribute("position", "top");
       this.nodeInfo.container.setAttribute("hide-arrow", "true");
     }
   },
 
   /**
-   * Return the midpoint of a line from pointA to pointB.
-   *
-   * @param object aPointA
-   *        An object with x and y properties.
-   * @param object aPointB
-   *        An object with x and y properties.
-   * @returns object
-   *          An object with x and y properties.
-   */
-  midPoint: function Highlighter_midPoint(aPointA, aPointB)
-  {
-    let pointC = { };
-    pointC.x = (aPointB.x - aPointA.x) / 2 + aPointA.x;
-    pointC.y = (aPointB.y - aPointA.y) / 2 + aPointA.y;
-    return pointC;
-  },
-
-  /**
-   * Return the node under the highlighter rectangle. Useful for testing.
-   * Calculation based on midpoint of diagonal from top left to bottom right
-   * of panel.
-   *
-   * @returns nsIDOMNode|null
-   *          Returns the node under the current highlighter rectangle. Null is
-   *          returned if there is no node highlighted.
-   */
-  get highlitNode()
-  {
-    // Not highlighting? Bail.
-    if (!this._highlighting || !this._contentRect) {
-      return null;
-    }
-
-    let a = {
-      x: this._contentRect.left,
-      y: this._contentRect.top
-    };
-
-    let b = {
-      x: a.x + this._contentRect.width,
-      y: a.y + this._contentRect.height
-    };
-
-    // Get midpoint of diagonal line.
-    let midpoint = this.midPoint(a, b);
-
-    return LayoutHelpers.getElementFromPoint(this.win.document, midpoint.x,
-      midpoint.y);
-  },
-
-  /**
    * Store page zoom factor.
    */
   computeZoomFactor: function Highlighter_computeZoomFactor() {
     this.zoom =
       this.win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
       .getInterface(Components.interfaces.nsIDOMWindowUtils)
       .screenPixelsPerCSSPixel;
   },
--- a/browser/devtools/highlighter/test/Makefile.in
+++ b/browser/devtools/highlighter/test/Makefile.in
@@ -61,18 +61,19 @@ include $(topsrcdir)/config/rules.mk
 		browser_inspector_bug_566084_location_changed.js \
 		browser_inspector_infobar.js \
 		browser_inspector_bug_690361.js \
 		browser_inspector_bug_672902_keyboard_shortcuts.js \
 		browser_inspector_keybindings.js \
 		browser_inspector_breadcrumbs.html \
 		browser_inspector_breadcrumbs.js \
 		browser_inspector_bug_699308_iframe_navigation.js \
-        browser_inspector_changes.js \
-        browser_inspector_ruleviewstore.js \
-        browser_inspector_duplicate_ruleview.js \
+		browser_inspector_changes.js \
+		browser_inspector_ruleviewstore.js \
+		browser_inspector_duplicate_ruleview.js \
+		head.js \
 		$(NULL)
 
 # Disabled due to constant failures
 # 		browser_inspector_treePanel_click.js \
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/devtools/highlighter/test/browser_inspector_breadcrumbs.js
+++ b/browser/devtools/highlighter/test/browser_inspector_breadcrumbs.js
@@ -43,32 +43,29 @@ function test()
 
   function runTests()
   {
     Services.obs.removeObserver(runTests,
       InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
 
     cursor = 0;
     executeSoon(function() {
-      Services.obs.addObserver(nodeSelected,
-        InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
-
+      InspectorUI.highlighter.addListener("nodeselected", nodeSelected);
       InspectorUI.inspectNode(nodes[0].node);
     });
   }
 
   function nodeSelected()
   {
     executeSoon(function() {
       performTest();
       cursor++;
       if (cursor >= nodes.length) {
 
-        Services.obs.removeObserver(nodeSelected,
-          InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+        InspectorUI.highlighter.removeListener("nodeselected", nodeSelected);
         Services.obs.addObserver(finishUp,
           InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
 
         executeSoon(function() {
           InspectorUI.closeInspectorUI();
         });
       } else {
         let node = nodes[cursor].node;
--- a/browser/devtools/highlighter/test/browser_inspector_bug_665880.js
+++ b/browser/devtools/highlighter/test/browser_inspector_bug_665880.js
@@ -29,27 +29,25 @@ function test()
   }
 
   function runObjectInspectionTest()
   {
     Services.obs.removeObserver(runObjectInspectionTest,
       InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
 
     executeSoon(function() {
-      Services.obs.addObserver(performTestComparison,
-        InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+      InspectorUI.highlighter.addListener("nodeselected", performTestComparison);
 
       InspectorUI.inspectNode(objectNode);
     });
   }
 
   function performTestComparison()
   {
-    Services.obs.removeObserver(performTestComparison,
-      InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+    InspectorUI.highlighter.removeListener("nodeselected", performTestComparison);
 
     is(InspectorUI.selection, objectNode, "selection matches node");
 
     Services.obs.addObserver(finishUp,
       InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
     InspectorUI.closeInspectorUI();
   }
 
--- a/browser/devtools/highlighter/test/browser_inspector_bug_672902_keyboard_shortcuts.js
+++ b/browser/devtools/highlighter/test/browser_inspector_bug_672902_keyboard_shortcuts.js
@@ -33,94 +33,79 @@ function test()
   }
 
   function findAndHighlightNode()
   {
     Services.obs.removeObserver(findAndHighlightNode,
                                 InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
 
     executeSoon(function() {
-      Services.obs.addObserver(highlightBodyNode,
-                               InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING,
-                               false);
+      InspectorUI.highlighter.addListener("nodeselected", highlightBodyNode);
       // Test that navigating around without a selected node gets us to the
       // body element.
       node = doc.querySelector("body");
       EventUtils.synthesizeKey("VK_RIGHT", { });
     });
   }
 
   function highlightBodyNode()
   {
-    Services.obs.removeObserver(highlightBodyNode,
-                                InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+    InspectorUI.highlighter.removeListener("nodeselected", highlightBodyNode);
     is(InspectorUI.selection, node, "selected body element");
 
     executeSoon(function() {
-      Services.obs.addObserver(highlightHeaderNode,
-                               InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING,
-                               false);
+      InspectorUI.highlighter.addListener("nodeselected", highlightHeaderNode);
       // Test that moving to the child works.
       node = doc.querySelector("h1");
       EventUtils.synthesizeKey("VK_RIGHT", { });
     });
   }
 
   function highlightHeaderNode()
   {
-    Services.obs.removeObserver(highlightHeaderNode,
-                                InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+    InspectorUI.highlighter.removeListener("nodeselected", highlightHeaderNode);
     is(InspectorUI.selection, node, "selected h1 element");
 
     executeSoon(function() {
-      Services.obs.addObserver(highlightParagraphNode,
-                               InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING,
-                               false);
+      InspectorUI.highlighter.addListener("nodeselected", highlightParagraphNode);
       // Test that moving to the next sibling works.
       node = doc.querySelector("p");
       EventUtils.synthesizeKey("VK_DOWN", { });
     });
   }
 
   function highlightParagraphNode()
   {
-    Services.obs.removeObserver(highlightParagraphNode,
-                                InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+    InspectorUI.highlighter.removeListener("nodeselected", highlightParagraphNode);
     is(InspectorUI.selection, node, "selected p element");
 
     executeSoon(function() {
-      Services.obs.addObserver(highlightHeaderNodeAgain,
-                               InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING,
-                               false);
+      InspectorUI.highlighter.addListener("nodeselected", highlightHeaderNodeAgain);
       // Test that moving to the previous sibling works.
       node = doc.querySelector("h1");
       EventUtils.synthesizeKey("VK_UP", { });
     });
   }
 
   function highlightHeaderNodeAgain()
   {
-    Services.obs.removeObserver(highlightHeaderNodeAgain,
-                                InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+    InspectorUI.highlighter.removeListener("nodeselected", highlightHeaderNodeAgain);
     is(InspectorUI.selection, node, "selected h1 element");
 
     executeSoon(function() {
-      Services.obs.addObserver(highlightParentNode,
-                               InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING,
-                               false);
+      InspectorUI.highlighter.addListener("nodeselected", highlightParentNode);
       // Test that moving to the parent works.
       node = doc.querySelector("body");
       EventUtils.synthesizeKey("VK_LEFT", { });
     });
   }
 
   function highlightParentNode()
   {
-    Services.obs.removeObserver(highlightParentNode,
-                                InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+    InspectorUI.highlighter.removeListener("nodeselected", highlightParentNode);
     is(InspectorUI.selection, node, "selected body element");
 
     // Test that locking works.
     EventUtils.synthesizeKey("VK_RETURN", { });
     executeSoon(isTheNodeLocked);
   }
 
   function isTheNodeLocked()
--- a/browser/devtools/highlighter/test/browser_inspector_bug_674871.js
+++ b/browser/devtools/highlighter/test/browser_inspector_bug_674871.js
@@ -52,45 +52,39 @@ function test()
   }
 
   function runTests()
   {
     Services.obs.removeObserver(runTests,
       InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
 
     executeSoon(function() {
-      Services.obs.addObserver(isTheIframeSelected,
-        InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+      InspectorUI.highlighter.addListener("nodeselected", isTheIframeSelected);
 
       moveMouseOver(iframeNode, 1, 1);
     });
   }
 
   function isTheIframeSelected()
   {
-    Services.obs.removeObserver(isTheIframeSelected,
-      InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+    InspectorUI.highlighter.removeListener("nodeselected", isTheIframeSelected);
 
     is(InspectorUI.selection, iframeNode, "selection matches node");
     iframeNode.style.marginBottom = doc.defaultView.innerHeight + "px";
     doc.defaultView.scrollBy(0, 40);
 
     executeSoon(function() {
-      Services.obs.addObserver(isTheIframeContentSelected,
-        InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
-
+      InspectorUI.highlighter.addListener("nodeselected", isTheIframeContentSelected);
       moveMouseOver(iframeNode, 40, 40);
     });
   }
 
   function isTheIframeContentSelected()
   {
-    Services.obs.removeObserver(isTheIframeContentSelected,
-      InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
-
+    InspectorUI.highlighter.removeListener("nodeselected", isTheIframeContentSelected);
     is(InspectorUI.selection, iframeBodyNode, "selection matches node");
     // 184 == 200 + 11(border) + 13(padding) - 40(scroll)
     is(InspectorUI.highlighter._highlightRect.height, 184,
       "highlighter height");
 
     Services.obs.addObserver(finishUp,
       InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
     InspectorUI.closeInspectorUI();
--- a/browser/devtools/highlighter/test/browser_inspector_editor.js
+++ b/browser/devtools/highlighter/test/browser_inspector_editor.js
@@ -53,17 +53,17 @@ function runEditorTests()
 
   // start the tests
   doNextStep();
 }
 
 function highlighterTrap()
 {
   // bug 696107
-  Services.obs.removeObserver(highlighterTrap, InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+  InspectorUI.highlighter.removeListener("nodeselected", highlighterTrap);
   ok(false, "Highlighter moved. Shouldn't be here!");
   finishUp();
 }
 
 function doEditorTestSteps()
 {
   let treePanel = InspectorUI.treePanel;
   let editor = treePanel.treeBrowserDocument.getElementById("attribute-editor");
@@ -110,32 +110,31 @@ function doEditorTestSteps()
 
   is(treePanel.editingContext.repObj, div, "editor session has correct reference to div");
   is(treePanel.editingContext.attrObj, attrValNode_id, "editor session has correct reference to `id` attribute-value node in HTML panel");
   is(treePanel.editingContext.attrName, "id", "editor session knows correct attribute-name");
 
   editorInput.value = "Hello World";
   editorInput.focus();
 
-  Services.obs.addObserver(highlighterTrap,
-      InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+  InspectorUI.highlighter.addListener("nodeselected", highlighterTrap);
 
   // hit <enter> to save the textbox value
   executeSoon(function() {
     // Extra key to test that keyboard handlers have been removed. bug 696107.
     EventUtils.synthesizeKey("VK_LEFT", {}, attrValNode_id.ownerDocument.defaultView);
     EventUtils.synthesizeKey("VK_RETURN", {}, attrValNode_id.ownerDocument.defaultView);
   });
 
   // two `yield` statements, to trap both the "SAVED" and "CLOSED" events that will be triggered
   yield;
   yield; // End of Step 2
 
   // remove this from previous step
-  Services.obs.removeObserver(highlighterTrap, InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+  InspectorUI.highlighter.removeListener("nodeselected", highlighterTrap);
 
   // Step 3: validate that the previous editing session saved correctly, then open editor on `class` attribute value
   ok(!treePanel.editingContext, "Step 3: editor session ended");
   editorVisible = editor.classList.contains("editing");
   ok(!editorVisible, "editor popup hidden");
   attrValNodeHighlighted = attrValNode_id.classList.contains("editingAttributeValue");
   ok(!attrValNodeHighlighted, "`id` attribute-value node is no longer editor-highlighted");
   is(div.getAttribute("id"), "Hello World", "`id` attribute-value successfully updated");
--- a/browser/devtools/highlighter/test/browser_inspector_highlighter.js
+++ b/browser/devtools/highlighter/test/browser_inspector_highlighter.js
@@ -98,47 +98,43 @@ function runSelectionTests(subject)
 {
   Services.obs.removeObserver(runSelectionTests,
     InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
 
   is(subject.wrappedJSObject, InspectorUI,
      "InspectorUI accessible in the observer");
 
   executeSoon(function() {
-    Services.obs.addObserver(performTestComparisons,
-      InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+    InspectorUI.highlighter.addListener("nodeselected", performTestComparisons);
     EventUtils.synthesizeMouse(h1, 2, 2, {type: "mousemove"}, content);
   });
 }
 
 function performTestComparisons(evt)
 {
-  Services.obs.removeObserver(performTestComparisons,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+  InspectorUI.highlighter.removeListener("nodeselected", performTestComparisons);
 
   InspectorUI.stopInspecting();
-  ok(InspectorUI.highlighter.isHighlighting, "highlighter is highlighting");
-  is(InspectorUI.highlighter.highlitNode, h1, "highlighter matches selection")
+  ok(isHighlighting(), "highlighter is highlighting");
+  is(getHighlitNode(), h1, "highlighter matches selection")
   is(InspectorUI.selection, h1, "selection matches node");
-  is(InspectorUI.selection, InspectorUI.highlighter.highlitNode, "selection matches highlighter");
+  is(InspectorUI.selection, getHighlitNode(), "selection matches highlighter");
 
 
   div = doc.querySelector("div#checkOutThisWickedSpread");
 
   executeSoon(function() {
-    Services.obs.addObserver(finishTestComparisons,
-        InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+    InspectorUI.highlighter.addListener("nodeselected", finishTestComparisons);
     InspectorUI.inspectNode(div);
   });
 }
 
 function finishTestComparisons()
 {
-  Services.obs.removeObserver(finishTestComparisons,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+  InspectorUI.highlighter.removeListener("nodeselected", finishTestComparisons);
 
   // get dimensions of div element
   let divDims = div.getBoundingClientRect();
   let divWidth = divDims.width;
   let divHeight = divDims.height;
 
   // get dimensions of transparent veil box over element
   let veilBoxDims = 
--- a/browser/devtools/highlighter/test/browser_inspector_iframeTest.js
+++ b/browser/devtools/highlighter/test/browser_inspector_iframeTest.js
@@ -90,44 +90,42 @@ function setupIframeTests()
   InspectorUI.openInspectorUI();
 }
 
 function runIframeTests()
 {
   Services.obs.removeObserver(runIframeTests,
     InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
 
-  Services.obs.addObserver(performTestComparisons1,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
 
-  executeSoon(moveMouseOver.bind(this, div1));
+  executeSoon(function() {
+    InspectorUI.highlighter.addListener("nodeselected", performTestComparisons1);
+    moveMouseOver(div1)
+  });
 }
 
 function performTestComparisons1()
 {
-  Services.obs.removeObserver(performTestComparisons1,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+  InspectorUI.highlighter.removeListener("nodeselected", performTestComparisons1);
 
   is(InspectorUI.selection, div1, "selection matches div1 node");
-  is(InspectorUI.highlighter.highlitNode, div1, "highlighter matches selection");
+  is(getHighlitNode(), div1, "highlighter matches selection");
 
   executeSoon(function() {
-    Services.obs.addObserver(performTestComparisons2,
-      InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+    InspectorUI.highlighter.addListener("nodeselected", performTestComparisons2);
     moveMouseOver(div2);
   });
 }
 
 function performTestComparisons2()
 {
-  Services.obs.removeObserver(performTestComparisons2,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+  InspectorUI.highlighter.removeListener("nodeselected", performTestComparisons2);
 
   is(InspectorUI.selection, div2, "selection matches div2 node");
-  is(InspectorUI.highlighter.highlitNode, div2, "highlighter matches selection");
+  is(getHighlitNode(), div2, "highlighter matches selection");
 
   finish();
 }
 
 function test() {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
--- a/browser/devtools/highlighter/test/browser_inspector_initialization.js
+++ b/browser/devtools/highlighter/test/browser_inspector_initialization.js
@@ -167,29 +167,29 @@ function openInspectorForContextTest()
     InspectorUI.openInspectorUI(salutation);
   });
 }
 
 function inspectNodesFromContextTestWhileOpen()
 {
   Services.obs.removeObserver(inspectNodesFromContextTestWhileOpen, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
   Services.obs.addObserver(inspectNodesFromContextTestTrap, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
-  Services.obs.addObserver(inspectNodesFromContextTestHighlight, InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+  InspectorUI.highlighter.addListener("nodeselected", inspectNodesFromContextTestHighlight);
   is(InspectorUI.selection, salutation, "Inspector is highlighting salutation");
   closing = doc.getElementById("closing");
   ok(closing, "we have the closing statement");
   executeSoon(function() {
     InspectorUI.openInspectorUI(closing);
   });
 }
 
 function inspectNodesFromContextTestHighlight()
 {
   winId = InspectorUI.winID;
-  Services.obs.removeObserver(inspectNodesFromContextTestHighlight, InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+  InspectorUI.highlighter.removeListener("nodeselected", inspectNodesFromContextTestHighlight);
   Services.obs.addObserver(finishInspectorTests, InspectorUI.INSPECTOR_NOTIFICATIONS.DESTROYED, false);
   is(InspectorUI.selection, closing, "InspectorUI.selection is header");
   executeSoon(function() {
     InspectorUI.closeInspectorUI();
   });
 }
 
 function inspectNodesFromContextTestTrap()
--- a/browser/devtools/highlighter/test/browser_inspector_keybindings.js
+++ b/browser/devtools/highlighter/test/browser_inspector_keybindings.js
@@ -27,28 +27,24 @@ function test()
   }
 
   function highlightNode()
   {
     Services.obs.removeObserver(highlightNode,
       InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
 
     executeSoon(function() {
-      Services.obs.addObserver(lockNode,
-        InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
-
+      InspectorUI.highlighter.addListener("nodeselected", lockNode);
       InspectorUI.inspectNode(node);
     });
   }
 
   function lockNode()
   {
-    Services.obs.removeObserver(lockNode,
-      InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
-
+    InspectorUI.highlighter.removeListener("nodeselected", lockNode);
     EventUtils.synthesizeKey("VK_RETURN", { });
 
     executeSoon(isTheNodeLocked);
   }
 
   function isTheNodeLocked()
   {
     is(InspectorUI.selection, node, "selection matches node");
--- a/browser/devtools/highlighter/test/browser_inspector_registertools.js
+++ b/browser/devtools/highlighter/test/browser_inspector_registertools.js
@@ -91,23 +91,23 @@ function setupHighlighterTests()
 
 function inspectorOpen()
 {
   info("we received the inspector-opened notification");
   Services.obs.removeObserver(inspectorOpen, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
   toolsLength = InspectorUI.tools.length;
   toolEvents = InspectorUI.toolEvents.length;
   info("tools registered");
-  Services.obs.addObserver(startToolTests, InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+  InspectorUI.highlighter.addListener("nodeselected", startToolTests);
   InspectorUI.inspectNode(h1);
 }
 
 function startToolTests(evt)
 {
-  Services.obs.removeObserver(startToolTests, InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+  InspectorUI.highlighter.removeListener("nodeselected", startToolTests);
   InspectorUI.stopInspecting();
   info("Getting InspectorUI.tools");
   let tools = InspectorUI.tools;
 
   tool1 = InspectorUI.tools["tool_1"];
   tool2 = InspectorUI.tools["tool_2"];
   tool3 = InspectorUI.tools["tool_3"];
 
--- a/browser/devtools/highlighter/test/browser_inspector_scrolling.js
+++ b/browser/devtools/highlighter/test/browser_inspector_scrolling.js
@@ -68,32 +68,33 @@ function toggleInspector()
   Services.obs.addObserver(inspectNode, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
   InspectorUI.toggleInspectorUI();
 }
 
 function inspectNode()
 {
   Services.obs.removeObserver(inspectNode,
     InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
-  Services.obs.addObserver(performScrollingTest,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+
+  InspectorUI.highlighter.addListener("nodeselected", performScrollingTest);
 
   executeSoon(function() {
     InspectorUI.inspectNode(div);
   });
 }
 
 function performScrollingTest()
 {
-  Services.obs.removeObserver(performScrollingTest,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+  InspectorUI.highlighter.removeListener("nodeselected", performScrollingTest);
 
-  EventUtils.synthesizeMouseScroll(div, 10, 10,
-    {axis:"vertical", delta:50, type:"MozMousePixelScroll"},
-    iframe.contentWindow);
+  executeSoon(function() {
+    EventUtils.synthesizeMouseScroll(div, 10, 10,
+      {axis:"vertical", delta:50, type:"MozMousePixelScroll"},
+      iframe.contentWindow);
+  });
 
   gBrowser.selectedBrowser.addEventListener("scroll", function() {
     gBrowser.selectedBrowser.removeEventListener("scroll", arguments.callee,
       false);
 
     is(iframe.contentDocument.body.scrollTop, 50, "inspected iframe scrolled");
 
     div = iframe = doc = null;
--- a/browser/devtools/highlighter/test/browser_inspector_treePanel_click.js
+++ b/browser/devtools/highlighter/test/browser_inspector_treePanel_click.js
@@ -29,34 +29,31 @@ function test() {
   function runTests() {
     Services.obs.removeObserver(runTests, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
     Services.obs.addObserver(testNode1, InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, false);
     InspectorUI.select(node1, true, true, true);
     InspectorUI.openTreePanel();
   }
 
   function testNode1() {
-    dump("testNode1\n");
     Services.obs.removeObserver(testNode1, InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY);
     is(InspectorUI.selection, node1, "selection matches node");
-    is(InspectorUI.highlighter.node, node1, "selection matches node");
+    is(getHighlitNode(), node1, "selection matches node");
     testNode2();
   }
 
   function testNode2() {
-    dump("testNode2\n")
-    Services.obs.addObserver(testHighlightingNode2, InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+    InspectorUI.highlighter.addListener("nodeselected", testHighlightingNode2);
     InspectorUI.treePanelSelect("node2");
   }
 
   function testHighlightingNode2() {
-    dump("testHighlightingNode2\n")
-    Services.obs.removeObserver(testHighlightingNode2, InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+    InspectorUI.highlighter.removeListener("nodeselected", testHighlightingNode2);
     is(InspectorUI.selection, node2, "selection matches node");
-    is(InspectorUI.highlighter.node, node2, "selection matches node");
+    is(getHighlitNode(), node2, "selection matches node");
     Services.obs.addObserver(finishUp, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
     InspectorUI.closeInspectorUI();
   }
 
   function finishUp() {
     Services.obs.removeObserver(finishUp, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED);
     doc = node1 = node2 = null;
     gBrowser.removeCurrentTab();
--- a/browser/devtools/highlighter/test/browser_inspector_treeSelection.js
+++ b/browser/devtools/highlighter/test/browser_inspector_treeSelection.js
@@ -71,31 +71,30 @@ function setupSelectionTests()
     InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
   InspectorUI.openInspectorUI();
 }
 
 function runSelectionTests()
 {
   Services.obs.removeObserver(runSelectionTests,
     InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
-  Services.obs.addObserver(performTestComparisons,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+
   executeSoon(function() {
+    InspectorUI.highlighter.addListener("nodeselected", performTestComparisons);
     InspectorUI.inspectNode(h1);
   });
 }
 
 function performTestComparisons(evt)
 {
-  Services.obs.removeObserver(performTestComparisons,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+  InspectorUI.highlighter.removeListener("nodeselected", performTestComparisons);
 
   is(h1, InspectorUI.selection, "selection matches node");
-  ok(InspectorUI.highlighter.isHighlighting, "highlighter is highlighting");
-  is(InspectorUI.highlighter.highlitNode, h1, "highlighter highlighting correct node");
+  ok(isHighlighting(), "highlighter is highlighting");
+  is(getHighlitNode(), h1, "highlighter highlighting correct node");
 
   finishUp();
 }
 
 function finishUp() {
   InspectorUI.closeInspectorUI();
   doc = h1 = null;
   gBrowser.removeCurrentTab();
new file mode 100644
--- /dev/null
+++ b/browser/devtools/highlighter/test/head.js
@@ -0,0 +1,78 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is DevTools test code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Paul Rouget <paul@mozilla.com> (Original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const Cu = Components.utils;
+Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
+
+function isHighlighting()
+{
+  let veil = InspectorUI.highlighter.veilTransparentBox;
+  return !(veil.style.visibility == "hidden");
+}
+
+function getHighlitNode()
+{
+  let h = InspectorUI.highlighter;
+  if (!isHighlighting() || !h._contentRect)
+    return null;
+
+  let a = {
+    x: h._contentRect.left,
+    y: h._contentRect.top
+  };
+
+  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,
+    midpoint.y);
+}
+
+
+function midPoint(aPointA, aPointB)
+{
+  let pointC = { };
+  pointC.x = (aPointB.x - aPointA.x) / 2 + aPointA.x;
+  pointC.y = (aPointB.y - aPointA.y) / 2 + aPointA.y;
+  return pointC;
+}
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_653531_highlighter_console_helper.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_653531_highlighter_console_helper.js
@@ -87,29 +87,27 @@ function setupHighlighterTests()
 }
 
 function runSelectionTests()
 {
   Services.obs.removeObserver(runSelectionTests,
     InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
 
   executeSoon(function() {
-    Services.obs.addObserver(performTestComparisons,
-      InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+    InspectorUI.highlighter.addListener("nodeselected", performTestComparisons);
     EventUtils.synthesizeMouse(h1, 2, 2, {type: "mousemove"}, content);
   });
 }
 
 function performTestComparisons(evt)
 {
-  Services.obs.removeObserver(performTestComparisons,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+  InspectorUI.highlighter.removeListener("nodeselected", performTestComparisons);
 
   InspectorUI.stopInspecting();
-  ok(InspectorUI.highlighter.isHighlighting, "highlighter is highlighting");
+  is(InspectorUI.highlighter.node, h1, "node selected");
   is(InspectorUI.selection, h1, "selection matches node");
 
   HUDService.activateHUDForContext(gBrowser.selectedTab);
   let hudId = HUDService.getHudIdByWindow(content);
   let hud = HUDService.hudReferences[hudId];
   let jsterm = hud.jsterm;
   outputNode = hud.outputNode;