Bug 916481 - Use Finder.jsm in the Metro browser [r=mbrubeck]
authorCasper van Donderen <casper.vandonderen@gmail.com>
Thu, 09 Jan 2014 07:58:25 -0800
changeset 162802 faa87475ab44087f7a5e92ef3e365da57aa6ad6d
parent 162801 06bc8e68d4fcd9fbb4bf8170d94ee192045f8cb5
child 162803 18acca8fc68166f566149926a58fe6db951d1ec3
push id25971
push userkwierso@gmail.com
push dateFri, 10 Jan 2014 00:50:13 +0000
treeherdermozilla-central@37516445a0b5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs916481
milestone29.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 916481 - Use Finder.jsm in the Metro browser [r=mbrubeck]
browser/metro/base/content/bindings/browser.xml
browser/metro/base/content/browser.js
browser/metro/base/content/contenthandlers/FindHandler.js
browser/metro/base/content/helperui/FindHelperUI.js
browser/metro/base/jar.mn
--- a/browser/metro/base/content/bindings/browser.xml
+++ b/browser/metro/base/content/bindings/browser.xml
@@ -1284,13 +1284,24 @@
             this._active = val;
             let keepVisible = false;
             this.messageManager.sendAsyncMessage((val ? "Content:Activate" : "Content:Deactivate"), { keepviewport: keepVisible });
             if (val)
               this.getRootView()._updateCacheViewport();
          ]]></setter>
       </property>
 
+      <field name="_remoteFinder">null</field>
+      <property name="finder" readonly="true">
+        <getter><![CDATA[
+          if (!this._remoteFinder) {
+            let jsm = "resource://gre/modules/RemoteFinder.jsm";
+            let RemoteFinder = Cu.import(jsm, {}).RemoteFinder;
+            this._remoteFinder = new RemoteFinder(this);
+          }
+          return this._remoteFinder;
+        ]]></getter>
+      </property>
     </implementation>
 
   </binding>
 
 </bindings>
--- a/browser/metro/base/content/browser.js
+++ b/browser/metro/base/content/browser.js
@@ -58,17 +58,16 @@ var Browser = {
 
     try {
       messageManager.loadFrameScript("chrome://browser/content/Util.js", true);
       messageManager.loadFrameScript("chrome://browser/content/contenthandlers/Content.js", true);
       messageManager.loadFrameScript("chrome://browser/content/contenthandlers/FormHelper.js", true);
       messageManager.loadFrameScript("chrome://browser/content/library/SelectionPrototype.js", true);
       messageManager.loadFrameScript("chrome://browser/content/contenthandlers/SelectionHandler.js", true);
       messageManager.loadFrameScript("chrome://browser/content/contenthandlers/ContextMenuHandler.js", true);
-      messageManager.loadFrameScript("chrome://browser/content/contenthandlers/FindHandler.js", true);
       messageManager.loadFrameScript("chrome://browser/content/contenthandlers/ConsoleAPIObserver.js", true);
     } catch (e) {
       // XXX whatever is calling startup needs to dump errors!
       dump("###########" + e + "\n");
     }
 
     if (!Services.metro) {
       // Services.metro is only available on Windows Metro. We want to be able
@@ -1012,17 +1011,17 @@ nsBrowserAccess.prototype = {
     if (aIID.equals(Ci.nsIBrowserDOMWindow) || aIID.equals(Ci.nsISupports))
       return this;
     throw Cr.NS_NOINTERFACE;
   },
 
   _getOpenAction: function _getOpenAction(aURI, aOpener, aWhere, aContext) {
     let where = aWhere;
     /*
-     * aWhere: 
+     * aWhere:
      * OPEN_DEFAULTWINDOW: default action
      * OPEN_CURRENTWINDOW: current window/tab
      * OPEN_NEWWINDOW: not allowed, converted to newtab below
      * OPEN_NEWTAB: open a new tab
      * OPEN_SWITCHTAB: open in an existing tab if it matches, otherwise open
      * a new tab. afaict we always open these in the current tab.
      */
     if (where == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) {
deleted file mode 100644
--- a/browser/metro/base/content/contenthandlers/FindHandler.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-let Ci = Components.interfaces;
-let Cc = Components.classes;
-
-dump("### FindHandler.js loaded\n");
-
-var FindHandler = {
-  get _fastFind() {
-    delete this._fastFind;
-    this._fastFind = Cc["@mozilla.org/typeaheadfind;1"].createInstance(Ci.nsITypeAheadFind);
-    this._fastFind.init(docShell);
-    return this._fastFind;
-  },
-
-  init: function findHandlerInit() {
-    addMessageListener("FindAssist:Find", this);
-    addMessageListener("FindAssist:Next", this);
-    addMessageListener("FindAssist:Previous", this);
-  },
-
-  receiveMessage: function findHandlerReceiveMessage(aMessage) {
-    let findResult = Ci.nsITypeAheadFind.FIND_NOTFOUND;
-    let json = aMessage.json;
-    switch (aMessage.name) {
-      case "FindAssist:Find":
-        findResult = this._fastFind.find(json.searchString, false);
-        break;
-
-      case "FindAssist:Previous":
-        findResult = this._fastFind.findAgain(true, false);
-        break;
-
-      case "FindAssist:Next":
-        findResult = this._fastFind.findAgain(false, false);
-        break;
-    }
-
-    if (findResult == Ci.nsITypeAheadFind.FIND_NOTFOUND) {
-      sendAsyncMessage("FindAssist:Show", { rect: null, result: findResult });
-      return;
-    }
-
-    if (!this._fastFind.currentWindow)
-      return;
-
-    let selection = this._fastFind.currentWindow.getSelection();
-    if (!selection.rangeCount || selection.isCollapsed) {
-      // The selection can be into an input or a textarea element
-      let nodes = content.document.querySelectorAll("input[type='text'], textarea");
-      for (let i = 0; i < nodes.length; i++) {
-        let node = nodes[i];
-        if (node instanceof Ci.nsIDOMNSEditableElement && node.editor) {
-          selection = node.editor.selectionController.getSelection(Ci.nsISelectionController.SELECTION_NORMAL);
-          if (selection.rangeCount && !selection.isCollapsed)
-            break;
-        }
-      }
-    }
-
-    // Return the bounding selection rect in content coordinates
-    // including the scroll offset.
-
-    let offset = ContentScroll.getScrollOffset(content);
-    for (let frame = this._fastFind.currentWindow; frame != content; frame = frame.parent) {
-      let rect = frame.frameElement.getBoundingClientRect();
-      let left = frame.getComputedStyle(frame.frameElement, "").borderLeftWidth;
-      let top = frame.getComputedStyle(frame.frameElement, "").borderTopWidth;
-      offset.add(rect.left + parseInt(left), rect.top + parseInt(top));
-    }
-
-    let rangeRect = selection.getRangeAt(0).getBoundingClientRect();
-    let rect = new Rect(offset.x + rangeRect.left, offset.y + rangeRect.top, 
-                        rangeRect.width, rangeRect.height);
-
-    // Ensure the potential "scroll" event fired during a search as already fired
-    let timer = new Util.Timeout(function() {
-      sendAsyncMessage("FindAssist:Show", {
-        rect: rect.isEmpty() ? null: rect,
-        contentHeight: content.document.documentElement.scrollHeight,
-        result: findResult
-      });
-    });
-    timer.once(0);
-  }
-};
-this.FindHandler = FindHandler;
-
-FindHandler.init();
--- a/browser/metro/base/content/helperui/FindHelperUI.js
+++ b/browser/metro/base/content/helperui/FindHelperUI.js
@@ -10,18 +10,20 @@ const kBrowserFindZoomLevelMax = 1;
 var FindHelperUI = {
   type: "find",
   commands: {
     next: "cmd_findNext",
     previous: "cmd_findPrevious",
     close: "cmd_findClose"
   },
 
+  _finder: null,
   _open: false,
   _status: null,
+  _searchString: "",
 
   /*
    * Properties
    */
 
   get isActive() {
     return this._open;
   },
@@ -45,63 +47,37 @@ var FindHelperUI = {
     this._textbox = document.getElementById("findbar-textbox");
     this._container = Elements.findbar;
 
     this._cmdPrevious = document.getElementById(this.commands.previous);
     this._cmdNext = document.getElementById(this.commands.next);
 
     this._textbox.addEventListener("keydown", this);
 
-    // Listen for find assistant messages from content
-    messageManager.addMessageListener("FindAssist:Show", this);
-    messageManager.addMessageListener("FindAssist:Hide", this);
-
     // Listen for events where form assistant should be closed
     Elements.tabList.addEventListener("TabSelect", this, true);
     Elements.browsers.addEventListener("URLChanged", this, true);
     window.addEventListener("MozAppbarShowing", this);
   },
 
-  receiveMessage: function findHelperReceiveMessage(aMessage) {
-    let json = aMessage.json;
-    switch(aMessage.name) {
-      case "FindAssist:Show":
-        ContextUI.dismiss();
-        this.status = json.result;
-        // null rect implies nothing found
-        if (json.rect) {
-          this._zoom(Rect.fromRect(json.rect), json.contentHeight);
-        }
-        break;
-
-      case "FindAssist:Hide":
-        if (this._container.getAttribute("type") == this.type)
-          this.hide();
-        break;
-    }
-  },
-
   handleEvent: function findHelperHandleEvent(aEvent) {
     switch (aEvent.type) {
       case "TabSelect":
         this.hide();
         break;
 
       case "URLChanged":
         if (aEvent.detail && aEvent.target == getBrowser())
           this.hide();
         break;
 
       case "keydown":
         if (aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_RETURN) {
-          if (aEvent.shiftKey) {
-            this.goToPrevious();
-          } else {
-            this.goToNext();
-          }
+          let backwardsSearch = aEvent.shiftKey;
+          this.searchAgain(this._searchString, backwardsSearch);
         }
         break;
 
       case "MozAppbarShowing":
         if (aEvent.target != this._container) {
           this.hide();
         }
         break;
@@ -146,42 +122,67 @@ var FindHelperUI = {
 
     ContentAreaObserver.shiftBrowserDeck(0);
 
     let onTransitionEnd = () => {
       this._container.removeEventListener("transitionend", onTransitionEnd, true);
       this._textbox.value = "";
       this.status = null;
       this._open = false;
-
+      if (this._finder) {
+        this._finder.removeResultListener(this);
+        this._finder = null
+      }
       // Restore the scroll synchronisation
       Browser.selectedBrowser.scrollSync = true;
     };
 
     this._textbox.blur();
     this._container.addEventListener("transitionend", onTransitionEnd, true);
     this._container.dismiss();
   },
 
+  search: function findHelperSearch(aValue) {
+    if (!this._finder) {
+      this._finder = Browser.selectedBrowser.finder;
+      this._finder.addResultListener(this);
+    }
+    this._searchString = aValue;
+    if (aValue != "") {
+      this._finder.fastFind(aValue, false, false);
+    } else {
+      this.updateCommands();
+    }
+  },
+
+  searchAgain: function findHelperSearchAgain(aValue, aFindBackwards) {
+    // This can happen if the user taps next/previous after re-opening the search bar
+    if (!this._finder) {
+      this.search(aValue);
+      return;
+    }
+
+    this._finder.findAgain(aFindBackwards, false, false);
+  },
+
   goToPrevious: function findHelperGoToPrevious() {
-    Browser.selectedBrowser.messageManager.sendAsyncMessage("FindAssist:Previous", { });
+    this.searchAgain(this._searchString, true);
   },
 
   goToNext: function findHelperGoToNext() {
-    Browser.selectedBrowser.messageManager.sendAsyncMessage("FindAssist:Next", { });
+    this.searchAgain(this._searchString, false);
   },
 
-  search: function findHelperSearch(aValue) {
-    this.updateCommands(aValue);
-
-    Browser.selectedBrowser.messageManager.sendAsyncMessage("FindAssist:Find", { searchString: aValue });
+  onFindResult: function(aResult, aFindBackwards, aLinkURL) {
+    this._status = aResult;
+    this.updateCommands();
   },
 
-  updateCommands: function findHelperUpdateCommands(aValue) {
-    let disabled = (this._status == Ci.nsITypeAheadFind.FIND_NOTFOUND) || (aValue == "");
+  updateCommands: function findHelperUpdateCommands() {
+    let disabled = (this._status == Ci.nsITypeAheadFind.FIND_NOTFOUND) || (this._searchString == "");
     this._cmdPrevious.setAttribute("disabled", disabled);
     this._cmdNext.setAttribute("disabled", disabled);
   },
 
   _zoom: function _findHelperZoom(aElementRect, aContentHeight) {
     // The rect we get here is the content rect including scroll offset
     // in the page.
 
--- a/browser/metro/base/jar.mn
+++ b/browser/metro/base/jar.mn
@@ -51,17 +51,16 @@ chrome.jar:
   content/helperui/ChromeSelectionHandler.js   (content/helperui/ChromeSelectionHandler.js)
   content/helperui/FormHelperUI.js             (content/helperui/FormHelperUI.js)
   content/helperui/FindHelperUI.js             (content/helperui/FindHelperUI.js)
   content/helperui/ItemPinHelper.js            (content/helperui/ItemPinHelper.js)
 
   content/contenthandlers/ContextMenuHandler.js (content/contenthandlers/ContextMenuHandler.js)
   content/contenthandlers/SelectionHandler.js  (content/contenthandlers/SelectionHandler.js)
   content/contenthandlers/FormHelper.js        (content/contenthandlers/FormHelper.js)
-  content/contenthandlers/FindHandler.js       (content/contenthandlers/FindHandler.js)
   content/contenthandlers/ConsoleAPIObserver.js (content/contenthandlers/ConsoleAPIObserver.js)
   content/contenthandlers/Content.js           (content/contenthandlers/Content.js)
 
   content/library/SelectionPrototype.js        (content/library/SelectionPrototype.js)
 
   content/ContentAreaObserver.js               (content/ContentAreaObserver.js)
   content/BrowserTouchHandler.js               (content/BrowserTouchHandler.js)
 * content/WebProgress.js                       (content/WebProgress.js)