Bug 828254 - Add context menu item to query default search provider using selection. r=mleibovic
authorChris Kitching <ckitching@mozilla.com>
Mon, 29 Jul 2013 12:17:32 -0400
changeset 152653 22c60e4b3242514a93317fb78df7747209bff4de
parent 152652 b05c1dba6ad9e2f1b27e6865f132703986658300
child 152654 00c1c1de3e0fd760fb601d5b1b3f0713a5ee244e
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmleibovic
bugs828254
milestone25.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 828254 - Add context menu item to query default search provider using selection. r=mleibovic
mobile/android/chrome/content/SelectionHandler.js
mobile/android/chrome/content/browser.js
mobile/android/locales/en-US/chrome/browser.properties
--- a/mobile/android/chrome/content/SelectionHandler.js
+++ b/mobile/android/chrome/content/SelectionHandler.js
@@ -391,16 +391,25 @@ var SelectionHandler = {
       sendMessageToJava({
         type: "Share:Text",
         text: selectedText
       });
     }
     this._closeSelection();
   },
 
+  searchSelection: function sh_searchSelection() {
+    let selectedText = this._getSelectedText();
+    if (selectedText.length) {
+      let req = Services.search.defaultEngine.getSubmission(selectedText);
+      BrowserApp.selectOrOpenTab(req.uri.spec);
+    }
+    this._closeSelection();
+  },
+
   /*
    * Called if for any reason we fail during the selection
    * process. Cancels the selection.
    */
   _onFail: function sh_onFail(aDbgMessage) {
     if (aDbgMessage && aDbgMessage.length > 0)
       Cu.reportError("SelectionHandler - " + aDbgMessage);
     this._closeSelection();
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2060,16 +2060,18 @@ var NativeWindow = {
         return;
 
       // store a weakref to the target to be used when the context menu event returns
       this._target = target;
 
       this.menuitems = [];
       let menuitemsSet = false;
 
+      Services.obs.notifyObservers(null, "before-build-contextmenu", "");
+
       // now walk up the tree and for each node look for any context menu items that apply
       let element = target;
       this._nativeItemsSeparator = 0;
       while (element) {
         // first check for any html5 context menus that might exist
         let contextmenu = element.contextMenu;
         if (contextmenu) {
           // send this before we build the list to make sure the site can update the menu
@@ -5957,24 +5959,47 @@ var IndexedDB = {
     // Set the timeoutId after the popup has been created, and use the long
     // timeout value. If the user doesn't notice the popup after this amount of
     // time then it is most likely not visible and we want to alert the page.
     timeoutId = setTimeout(timeoutNotification, firstTimeoutDuration);
   }
 };
 
 var ClipboardHelper = {
+  // Recorded so search with option can be removed/replaced when default engine changed.
+  _searchMenuItem: -1,
+
   init: function() {
     NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.copy"), ClipboardHelper.getCopyContext(false), ClipboardHelper.copy.bind(ClipboardHelper));
     NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.copyAll"), ClipboardHelper.getCopyContext(true), ClipboardHelper.copy.bind(ClipboardHelper));
     NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.selectWord"), ClipboardHelper.selectWordContext, ClipboardHelper.selectWord.bind(ClipboardHelper));
     NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.selectAll"), ClipboardHelper.selectAllContext, ClipboardHelper.selectAll.bind(ClipboardHelper));
     NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.share"), ClipboardHelper.shareContext, ClipboardHelper.share.bind(ClipboardHelper));
     NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.paste"), ClipboardHelper.pasteContext, ClipboardHelper.paste.bind(ClipboardHelper));
     NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.changeInputMethod"), NativeWindow.contextmenus.textContext, ClipboardHelper.inputMethod.bind(ClipboardHelper));
+
+    // We add this contextmenu item right before the menu is built to avoid having to initialise the search service early.
+    Services.obs.addObserver(this, "before-build-contextmenu", false);
+  },
+
+  uninit: function ch_uninit() {
+    Services.obs.removeObserver(this, "before-build-contextmenu");
+  },
+
+  observe: function observe(aSubject, aTopic) {
+    if (aTopic == "ContextMenu:Open") {
+      this._setSearchMenuItem();
+    }
+  },
+
+  _setSearchMenuItem: function setSearchMenuItem() {
+    if (this._searchMenuItem) {
+      NativeWindow.contextmenus.remove(this._searchMenuItem);
+    }
+    this._searchMenuItem = NativeWindow.contextmenus.add(Strings.browser.formatStringFromName("contextmenu.search", [Services.search.defaultEngine.name], 1), ClipboardHelper.searchWithContext, ClipboardHelper.searchWith.bind(ClipboardHelper));
   },
 
   get clipboardHelper() {
     delete this.clipboardHelper;
     return this.clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
   },
 
   get clipboard() {
@@ -6001,16 +6026,20 @@ var ClipboardHelper = {
   selectWord: function(aElement, aX, aY) {
     SelectionHandler.startSelection(aElement, aX, aY);
   },
 
   selectAll: function(aElement, aX, aY) {
     SelectionHandler.selectAll(aElement, aX, aY);
   },
 
+  searchWith: function(aElement) {
+    SelectionHandler.searchSelection(aElement);
+  },
+
   share: function() {
     SelectionHandler.shareSelection();
   },
 
   paste: function(aElement) {
     if (!aElement || !(aElement instanceof Ci.nsIDOMNSEditableElement))
       return;
     let target = aElement.QueryInterface(Ci.nsIDOMNSEditableElement);
@@ -6070,16 +6099,22 @@ var ClipboardHelper = {
   },
 
   shareContext: {
     matches: function shareContextMatches(aElement, aX, aY) {
       return SelectionHandler.shouldShowContextMenu(aX, aY);
     }
   },
 
+  searchWithContext: {
+    matches: function searchWithContextMatches(aElement, aX, aY) {
+      return SelectionHandler.shouldShowContextMenu(aX, aY);
+    }
+  },
+
   pasteContext: {
     matches: function(aElement) {
       if (NativeWindow.contextmenus.textContext.matches(aElement)) {
         let flavors = ["text/unicode"];
         return ClipboardHelper.clipboard.hasDataMatchingFlavors(flavors, flavors.length, Ci.nsIClipboard.kGlobalClipboard);
       }
       return false;
     }
--- a/mobile/android/locales/en-US/chrome/browser.properties
+++ b/mobile/android/locales/en-US/chrome/browser.properties
@@ -160,16 +160,17 @@ contextmenu.bookmarkLink=Bookmark Link
 contextmenu.copyEmailAddress=Copy Email Address
 contextmenu.shareEmailAddress=Share Email Address
 contextmenu.copyPhoneNumber=Copy Phone Number
 contextmenu.sharePhoneNumber=Share Phone Number
 contextmenu.changeInputMethod=Select Input Method
 contextmenu.fullScreen=Full Screen
 contextmenu.copyImageLocation=Copy Image Location
 contextmenu.shareImage=Share Image
+contextmenu.search=%S Search
 contextmenu.saveImage=Save Image
 contextmenu.setWallpaper=Set as Wallpaper
 contextmenu.addSearchEngine=Add Search Engine
 contextmenu.playMedia=Play
 contextmenu.pauseMedia=Pause
 contextmenu.shareMedia=Share Video
 contextmenu.showControls2=Show Controls
 contextmenu.mute=Mute