Bug 870110 - Part 1: search changes to support FHR on Android. r=wesj,cpeterson
authorRichard Newman <rnewman@mozilla.com>
Thu, 09 May 2013 17:07:53 -0700
changeset 131438 797f695d4cb6340f0d4b527508be531f2962070c
parent 131437 c3626167f6d84ba374db0ab99cabdfde1be20463
child 131439 01aa2993c04f85c03cf249f0ee13326b1c59ed2d
push id27857
push userrnewman@mozilla.com
push dateFri, 10 May 2013 00:08:16 +0000
treeherdermozilla-inbound@797f695d4cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswesj, cpeterson
bugs870110
milestone23.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 870110 - Part 1: search changes to support FHR on Android. r=wesj,cpeterson
mobile/android/base/AwesomeBar.java
mobile/android/base/AwesomeBarTabs.java
mobile/android/base/Makefile.in
mobile/android/base/SearchEngine.java
mobile/android/base/awesomebar/AllPagesTab.java
mobile/android/chrome/content/browser.js
--- a/mobile/android/base/AwesomeBar.java
+++ b/mobile/android/base/AwesomeBar.java
@@ -94,18 +94,22 @@ public class AwesomeBar extends GeckoAct
         mAwesomeTabs = (AwesomeBarTabs) findViewById(R.id.awesomebar_tabs);
         mAwesomeTabs.setOnUrlOpenListener(new AwesomeBarTabs.OnUrlOpenListener() {
             @Override
             public void onUrlOpen(String url, String title) {
                 openUrlAndFinish(url, title, false);
             }
 
             @Override
-            public void onSearch(String engine, String text) {
-                openSearchAndFinish(text, engine);
+            public void onSearch(SearchEngine engine, String text) {
+                Intent resultIntent = new Intent();
+                resultIntent.putExtra(URL_KEY, text);
+                resultIntent.putExtra(TARGET_KEY, mTarget);
+                resultIntent.putExtra(SEARCH_KEY, engine.name);
+                finishWithResult(resultIntent);
             }
 
             @Override
             public void onEditSuggestion(final String text) {
                 ThreadUtils.postToUiThread(new Runnable() {
                     @Override
                     public void run() {
                         mText.setText(text);
@@ -374,47 +378,41 @@ public class AwesomeBar extends GeckoAct
         resultIntent.putExtra(TARGET_KEY, mTarget);
         finishWithResult(resultIntent);
     }
 
     private void openUserEnteredAndFinish(final String url) {
         final int index = url.indexOf(' ');
 
         // Check for a keyword if the URL looks like a search query
-        if (StringUtils.isSearchQuery(url, true)) {
-            ThreadUtils.postToBackgroundThread(new Runnable() {
-                @Override
-                public void run() {
-                    String keywordUrl = null;
-                    String keywordSearch = "";
-                    if (index == -1) {
-                        keywordUrl = BrowserDB.getUrlForKeyword(getContentResolver(), url);
-                    } else {
-                        keywordUrl = BrowserDB.getUrlForKeyword(getContentResolver(), url.substring(0, index));
-                        keywordSearch = url.substring(index + 1);
-                    }
-                    if (keywordUrl == null) {
-                        openUrlAndFinish(url, "", true);
-                    } else {
-                        String search = URLEncoder.encode(keywordSearch);
-                        openUrlAndFinish(keywordUrl.replace("%s", search), "", true);
-                    }
+        if (!StringUtils.isSearchQuery(url, true)) {
+            openUrlAndFinish(url, "", true);
+            return;
+        }
+        ThreadUtils.postToBackgroundThread(new Runnable() {
+            @Override
+            public void run() {
+                final String keyword;
+                final String keywordSearch;
+
+                if (index == -1) {
+                    keyword = url;
+                    keywordSearch = "";
+                } else {
+                    keyword = url.substring(0, index);
+                    keywordSearch = url.substring(index + 1);
                 }
-            });
-        } else {
-            openUrlAndFinish(url, "", true);
-        }
-    }
 
-    private void openSearchAndFinish(String url, String engine) {
-        Intent resultIntent = new Intent();
-        resultIntent.putExtra(URL_KEY, url);
-        resultIntent.putExtra(TARGET_KEY, mTarget);
-        resultIntent.putExtra(SEARCH_KEY, engine);
-        finishWithResult(resultIntent);
+                final String keywordUrl = BrowserDB.getUrlForKeyword(getContentResolver(), keyword);
+                final String searchUrl = (keywordUrl != null)
+                                       ? keywordUrl.replace("%s", URLEncoder.encode(keywordSearch))
+                                       : url;
+                openUrlAndFinish(searchUrl, "", true);
+            }
+        });
     }
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         // Galaxy Note sends key events for the stylus that are outside of the
         // valid keyCode range (see bug 758427)
         if (keyCode > KeyEvent.getMaxKeyCode())
             return true;
--- a/mobile/android/base/AwesomeBarTabs.java
+++ b/mobile/android/base/AwesomeBarTabs.java
@@ -35,17 +35,17 @@ public class AwesomeBarTabs extends TabH
     private String mTarget;
     private ViewPager mViewPager;
     private AwesomePagerAdapter mPagerAdapter;
 
     private AwesomeBarTab mTabs[];
 
     public interface OnUrlOpenListener {
         public void onUrlOpen(String url, String title);
-        public void onSearch(String engine, String text);
+        public void onSearch(SearchEngine engine, String text);
         public void onEditSuggestion(String suggestion);
     }
 
     private class AwesomePagerAdapter extends PagerAdapter {
         public AwesomePagerAdapter() {
             super();
         }
 
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -132,16 +132,17 @@ FENNEC_JAVA_FILES = \
   NSSBridge.java \
   CustomEditText.java \
   PrefsHelper.java \
   PrivateDataPreference.java \
   PrivateTab.java \
   ProfileMigrator.java \
   PromptService.java \
   Restarter.java \
+  SearchEngine.java \
   sqlite/ByteBufferInputStream.java \
   sqlite/MatrixBlobCursor.java \
   sqlite/SQLiteBridge.java \
   sqlite/SQLiteBridgeException.java \
   ReaderModeUtils.java \
   RemoteTabs.java \
   RobocopAPI.java \
   ServiceNotificationClient.java \
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/SearchEngine.java
@@ -0,0 +1,29 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * 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/. */
+
+package org.mozilla.gecko;
+
+import android.graphics.Bitmap;
+
+import java.util.ArrayList;
+
+public class SearchEngine {
+    public String name;
+    public String identifier;
+    public Bitmap icon;
+    public ArrayList<String> suggestions;
+
+    public SearchEngine(String name, String identifier) {
+        this(name, identifier, null);
+    }
+
+    public SearchEngine(String name, String identifier, Bitmap icon) {
+        this.name = name;
+        this.identifier = identifier;
+        this.icon = icon;
+        this.suggestions = new ArrayList<String>();
+    }
+}
+
--- a/mobile/android/base/awesomebar/AllPagesTab.java
+++ b/mobile/android/base/awesomebar/AllPagesTab.java
@@ -354,19 +354,19 @@ public class AllPagesTab extends Awesome
             return new ContextMenuSubject(id, url, favicon,
                                           mCursor.getString(mCursor.getColumnIndexOrThrow(URLColumns.TITLE)),
                                           keyword,
                                           mCursor.getInt(mCursor.getColumnIndexOrThrow(Combined.DISPLAY)));
         }
     }
 
     private class AwesomeBarSearchEngineItem implements AwesomeBarItem {
-        private String mSearchEngine;
+        private SearchEngine mSearchEngine;
 
-        public AwesomeBarSearchEngineItem(String searchEngine) {
+        public AwesomeBarSearchEngineItem(SearchEngine searchEngine) {
             mSearchEngine = searchEngine;
         }
 
         @Override
         public void onClick() {
             AwesomeBarTabs.OnUrlOpenListener listener = getUrlListener();
             if (listener != null)
                 listener.onSearch(mSearchEngine, mSearchTerm);
@@ -423,17 +423,17 @@ public class AllPagesTab extends Awesome
 
             if (engineIndex == -1) {
                 // return awesomebar result
                 position -= getSuggestEngineCount();
                 return new AwesomeBarCursorItem((Cursor) super.getItem(position));
             }
 
             // return search engine
-            return new AwesomeBarSearchEngineItem(mSearchEngines.get(engineIndex).name);
+            return new AwesomeBarSearchEngineItem(mSearchEngines.get(engineIndex));
         }
 
         private int getEngineIndex(int position) {
             final int resultCount = super.getCount();
             final int suggestEngineCount = getSuggestEngineCount();
 
             // return suggest engine index
             if (position < suggestEngineCount)
@@ -544,17 +544,17 @@ public class AllPagesTab extends Awesome
 
                         // If we're not clicking the user-entered view (the
                         // first suggestion item) and the search matches a URL
                         // pattern, go to that URL. Otherwise, do a search for
                         // the term.
                         if (v != viewHolder.userEnteredView && !StringUtils.isSearchQuery(suggestion, false)) {
                             listener.onUrlOpen(suggestion, null);
                         } else {
-                            listener.onSearch(engine.name, suggestion);
+                            listener.onSearch(engine, suggestion);
                         }
                     }
                 }
             };
 
             // when a suggestion is long-clicked, copy the suggestion into the URL EditText
             OnLongClickListener longClickListener = new OnLongClickListener() {
                 @Override
@@ -614,32 +614,16 @@ public class AllPagesTab extends Awesome
                 suggestionView.getChildAt(i).setVisibility(View.GONE);
             }
 
             if (showedSuggestions)
                 mAnimateSuggestions = false;
         }
     };
 
-    private class SearchEngine {
-        public String name;
-        public Bitmap icon;
-        public ArrayList<String> suggestions;
-
-        public SearchEngine(String name) {
-            this(name, null);
-        }
-
-        public SearchEngine(String name, Bitmap icon) {
-            this.name = name;
-            this.icon = icon;
-            this.suggestions = new ArrayList<String>();
-        }
-    };
-
     /**
      * Sets suggestions associated with the current suggest engine.
      * If there is no suggest engine, this does nothing.
      */
     private void setSuggestions(final ArrayList<String> suggestions) {
         if (mSuggestClient != null) {
             mSearchEngines.get(0).suggestions = suggestions;
             getCursorAdapter().notifyDataSetChanged();
@@ -657,31 +641,32 @@ public class AllPagesTab extends Awesome
             mSuggestionsEnabled = suggest.getBoolean("enabled");
             boolean suggestionsPrompted = suggest.getBoolean("prompted");
             JSONArray engines = data.getJSONArray("searchEngines");
 
             ArrayList<SearchEngine> searchEngines = new ArrayList<SearchEngine>();
             for (int i = 0; i < engines.length(); i++) {
                 JSONObject engineJSON = engines.getJSONObject(i);
                 String name = engineJSON.getString("name");
+                String identifier = engineJSON.getString("identifier");
                 String iconURI = engineJSON.getString("iconURI");
                 Bitmap icon = BitmapUtils.getBitmapFromDataURI(iconURI);
                 if (name.equals(suggestEngine) && suggestTemplate != null) {
                     // suggest engine should be at the front of the list
-                    searchEngines.add(0, new SearchEngine(name, icon));
+                    searchEngines.add(0, new SearchEngine(name, identifier, icon));
 
                     // The only time Tabs.getInstance().getSelectedTab() should
                     // be null is when we're restoring after a crash. We should
                     // never restore private tabs when that happens, so it
                     // should be safe to assume that null means non-private.
                     Tab tab = Tabs.getInstance().getSelectedTab();
                     if (tab == null || !tab.isPrivate())
                         mSuggestClient = new SuggestClient(GeckoApp.mAppContext, suggestTemplate, SUGGESTION_TIMEOUT, SUGGESTION_MAX);
                 } else {
-                    searchEngines.add(new SearchEngine(name, icon));
+                    searchEngines.add(new SearchEngine(name, identifier, icon));
                 }
             }
 
             mSearchEngines = searchEngines;
             mCursorAdapter.notifyDataSetChanged();
 
             // show suggestions opt-in if user hasn't been prompted
             if (!suggestionsPrompted && mSuggestClient != null) {
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1306,18 +1306,25 @@ var BrowserApp = {
         this._handleTabSelected(this.getTabForId(parseInt(aData)));
         break;
 
       case "Tab:Closed":
         this._handleTabClosed(this.getTabForId(parseInt(aData)));
         break;
 
       case "keyword-search":
-        // This assumes the user can only perform a keyword serach on the selected tab.
+        // This assumes that the user can only perform a keyword search on the selected tab.
         this.selectedTab.userSearch = aData;
+
+        let engine = aSubject.QueryInterface(Ci.nsISearchEngine);
+        sendMessageToJava({
+          type: "Search:Keyword",
+          identifier: engine.identifier,
+          name: engine.name,
+        });
         break;
 
       case "Browser:Quit":
         this.quit();
         break;
 
       case "SaveAs:PDF":
         this.saveAsPDF(browser);
@@ -5890,16 +5897,17 @@ var SearchEngines = {
     if (!Components.isSuccessCode(rv)) {
       Cu.reportError("Could not initialize search service, bailing out.");
       return;
     }
     let engineData = Services.search.getVisibleEngines({});
     let searchEngines = engineData.map(function (engine) {
       return {
         name: engine.name,
+        identifier: engine.identifier,
         iconURI: (engine.iconURI ? engine.iconURI.spec : null)
       };
     });
 
     let suggestTemplate = null;
     let suggestEngine = null;
     let engine = this.getSuggestionEngine();
     if (engine != null) {