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 162718 faa87475ab44087f7a5e92ef3e365da57aa6ad6d
parent 162717 06bc8e68d4fcd9fbb4bf8170d94ee192045f8cb5
child 162719 18acca8fc68166f566149926a58fe6db951d1ec3
push id4259
push usermbrubeck@mozilla.com
push dateThu, 09 Jan 2014 15:59:43 +0000
treeherderfx-team@18acca8fc681 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs916481
milestone29.0a1
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)