Bug 786029: Fennec should integrate with Android's search. [f=mfinkle, r=lucasr]
authorSriram Ramasubramanian <sriram@mozilla.com>
Thu, 04 Oct 2012 16:57:39 -0700
changeset 109382 3c1d80269a137fc41bfdfd082692664f6021856d
parent 109381 92af89fcb63875b840314f1b0ad1f3d1094b68a9
child 109383 9859a8c681361bcb206f8ddd5cae39171e42d641
push id16004
push usersramasubramanian@mozilla.com
push dateFri, 05 Oct 2012 16:36:07 +0000
treeherdermozilla-inbound@3c1d80269a13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslucasr
bugs786029
milestone18.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 786029: Fennec should integrate with Android's search. [f=mfinkle, r=lucasr]
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/GeckoApp.java
mobile/android/base/Makefile.in
mobile/android/base/db/BrowserProvider.java.in
mobile/android/base/locales/Makefile.in
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/xml/searchable.xml.in
mobile/android/base/strings.xml.in
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -107,16 +107,23 @@
                 <action android:name="android.intent.action.WEB_SEARCH" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
                 <data android:scheme="" />
                 <data android:scheme="http" />
                 <data android:scheme="https" />
             </intent-filter>
 
+            <intent-filter>
+                <action android:name="android.intent.action.SEARCH" />
+            </intent-filter>
+
+            <meta-data android:name="android.app.searchable"
+                       android:resource="@xml/searchable" />
+
             <!-- For debugging -->
             <intent-filter>
                 <action android:name="org.mozilla.gecko.DEBUG" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
 
 #include @OBJDIR@/WebAppManifestFragment.xml.in
@@ -214,17 +221,22 @@
         <activity android:name="org.mozilla.gecko.GeckoPreferences"
                   android:theme="@style/Gecko.TitleBar.Preferences"
                   android:label="@string/settings_title"
                   android:configChanges="orientation|screenSize"
                   android:excludeFromRecents="true"/>
 
         <provider android:name="@ANDROID_PACKAGE_NAME@.db.BrowserProvider"
                   android:authorities="@ANDROID_PACKAGE_NAME@.db.browser"
-                  android:permission="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"/>
+                  android:permission="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER">
+
+            <path-permission android:pathPrefix="/search_suggest_query"
+                             android:readPermission="android.permission.GLOBAL_SEARCH" />
+
+        </provider>
 
         <!--
           Ensure that passwords provider runs in its own process. (Bug 718760.)
           Process name is per-application to avoid loading CPs from multiple
           Fennec versions into the same process. (Bug 749727.)
           Process name is a mangled version to avoid a Talos bug. (Bug 750548.)
           -->
         <provider android:name="@ANDROID_PACKAGE_NAME@.db.PasswordsProvider"
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1936,16 +1936,20 @@ abstract public class GeckoApp
         else if (action != null && action.startsWith(ACTION_WEBAPP_PREFIX)) {
             String uri = getURIFromIntent(intent);
             GeckoAppShell.sendEventToGecko(GeckoEvent.createWebappLoadEvent(uri));
         }
         else if (ACTION_BOOKMARK.equals(action)) {
             String uri = getURIFromIntent(intent);
             GeckoAppShell.sendEventToGecko(GeckoEvent.createBookmarkLoadEvent(uri));
         }
+        else if (Intent.ACTION_SEARCH.equals(action)) {
+            String uri = getURIFromIntent(intent);
+            GeckoAppShell.sendEventToGecko(GeckoEvent.createURILoadEvent(uri));
+        }
         else if (ACTION_ALERT_CALLBACK.equals(action)) {
             String alertName = "";
             String alertCookie = "";
             Uri data = intent.getData();
             if (data != null) {
                 alertName = data.getQueryParameter("name");
                 if (alertName == null)
                     alertName = "";
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -208,16 +208,17 @@ FENNEC_PP_XML_FILES = \
   res/layout-large-v11/browser_toolbar_menu.xml \
   res/layout-xlarge-v11/browser_toolbar_menu.xml \
   res/layout/gecko_app.xml \
   res/layout/text_selection_handles.xml \
   res/layout-xlarge-land-v11/abouthome_content.xml \
   res/layout-xlarge-v11/awesomebar_search.xml \
   res/layout-xlarge-v11/gecko_app.xml \
   res/xml/preferences.xml \
+  res/xml/searchable.xml \
   res/menu/browser_app_menu.xml \
   res/menu-v11/browser_app_menu.xml \
   res/menu-large-v11/browser_app_menu.xml \
   res/menu-xlarge-v11/browser_app_menu.xml \
   $(NULL)
 
 
 ifneq (,$(findstring -march=armv7,$(OS_CFLAGS)))
--- a/mobile/android/base/db/BrowserProvider.java.in
+++ b/mobile/android/base/db/BrowserProvider.java.in
@@ -34,16 +34,17 @@ import org.mozilla.gecko.db.BrowserContr
 import org.mozilla.gecko.db.BrowserContract.SyncColumns;
 import org.mozilla.gecko.db.BrowserContract.URLColumns;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.DBUtils;
 import org.mozilla.gecko.ProfileMigrator;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.util.GeckoBackgroundThread;
 
+import android.app.SearchManager;
 import android.content.ContentProvider;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.ContentProviderResult;
 import android.content.ContentProviderOperation;
 import android.content.OperationApplicationException;
 import android.content.Context;
 import android.content.UriMatcher;
@@ -112,16 +113,19 @@ public class BrowserProvider extends Con
     static final int SCHEMA = 400;
 
     // Combined bookmarks and history matches
     static final int COMBINED = 500;
 
     // Control matches
     static final int CONTROL = 600;
 
+    // Search Suggest matches
+    static final int SEARCH_SUGGEST = 700;
+
     static final String DEFAULT_BOOKMARKS_SORT_ORDER = Bookmarks.TYPE
             + " ASC, " + Bookmarks.POSITION + " ASC, " + Bookmarks._ID
             + " ASC";
 
     static final String DEFAULT_HISTORY_SORT_ORDER = History.DATE_LAST_VISITED + " DESC";
 
     static final String TABLE_BOOKMARKS_JOIN_IMAGES = TABLE_BOOKMARKS + " LEFT OUTER JOIN " +
             TABLE_IMAGES + " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " +
@@ -133,16 +137,17 @@ public class BrowserProvider extends Con
 
     static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
 
     static final Map<String, String> BOOKMARKS_PROJECTION_MAP;
     static final Map<String, String> HISTORY_PROJECTION_MAP;
     static final Map<String, String> IMAGES_PROJECTION_MAP;
     static final Map<String, String> COMBINED_PROJECTION_MAP;
     static final Map<String, String> SCHEMA_PROJECTION_MAP;
+    static final Map<String, String> SEARCH_SUGGEST_PROJECTION_MAP;
 
     static {
         // We will reuse this.
         HashMap<String, String> map;
 
         // Bookmarks
         URI_MATCHER.addURI(BrowserContract.AUTHORITY, "bookmarks", BOOKMARKS);
         URI_MATCHER.addURI(BrowserContract.AUTHORITY, "bookmarks/#", BOOKMARKS_ID);
@@ -223,16 +228,28 @@ public class BrowserProvider extends Con
 
         map = new HashMap<String, String>();
         map.put(Schema.VERSION, Schema.VERSION);
         SCHEMA_PROJECTION_MAP = Collections.unmodifiableMap(map);
 
 
         // Control
         URI_MATCHER.addURI(BrowserContract.AUTHORITY, "control", CONTROL);
+
+        // Search Suggest
+        URI_MATCHER.addURI(BrowserContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
+
+        map = new HashMap<String, String>();
+        map.put(SearchManager.SUGGEST_COLUMN_TEXT_1,
+                Combined.TITLE + " AS " + SearchManager.SUGGEST_COLUMN_TEXT_1);
+        map.put(SearchManager.SUGGEST_COLUMN_TEXT_2_URL,
+                Combined.URL + " AS " + SearchManager.SUGGEST_COLUMN_TEXT_2_URL);
+        map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA,
+                Combined.URL + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA);
+        SEARCH_SUGGEST_PROJECTION_MAP = Collections.unmodifiableMap(map);
     }
 
     private HashMap<String, DatabaseHelper> mDatabasePerProfile;
 
     private interface BookmarkMigrator {
         public void updateForNewTable(ContentValues bookmark);
     }
 
@@ -1369,16 +1386,19 @@ public class BrowserProvider extends Con
                 trace("URI is BOOKMARKS_ID: " + uri);
                 return Bookmarks.CONTENT_ITEM_TYPE;
             case HISTORY:
                 trace("URI is HISTORY: " + uri);
                 return History.CONTENT_TYPE;
             case HISTORY_ID:
                 trace("URI is HISTORY_ID: " + uri);
                 return History.CONTENT_ITEM_TYPE;
+            case SEARCH_SUGGEST:
+                trace("URI is SEARCH_SUGGEST: " + uri);
+                return SearchManager.SUGGEST_MIME_TYPE;
         }
 
         debug("URI has unrecognized type: " + uri);
 
         return null;
     }
 
     @Override
@@ -1856,16 +1876,38 @@ public class BrowserProvider extends Con
                 debug("Query is on control: " + uri);
 
                 Cursor controlCursor =
                     controlQuery(uri, projection, selection, selectionArgs, sortOrder);
 
                 return controlCursor;
             }
 
+            case SEARCH_SUGGEST: {
+                debug("Query is on search suggest: " + uri);
+                selection = DBUtils.concatenateWhere(selection, "(" + Combined.URL + " LIKE ? OR " +
+                                                                      Combined.TITLE + " LIKE ?)");
+
+                String keyword = uri.getLastPathSegment();
+                if (keyword == null)
+                    keyword = "";
+
+                selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
+                        new String[] { "%" + keyword + "%",
+                                       "%" + keyword + "%" });
+
+                if (TextUtils.isEmpty(sortOrder))
+                    sortOrder = DEFAULT_HISTORY_SORT_ORDER;
+
+                qb.setProjectionMap(SEARCH_SUGGEST_PROJECTION_MAP);
+                qb.setTables(VIEW_COMBINED_WITH_IMAGES);
+
+                break;
+            }
+
             default:
                 throw new UnsupportedOperationException("Unknown query URI " + uri);
         }
 
         trace("Running built query.");
         Cursor cursor = qb.query(db, projection, selection, selectionArgs, groupBy,
                 null, sortOrder, limit);
         cursor.setNotificationUri(getContext().getContentResolver(),
--- a/mobile/android/base/locales/Makefile.in
+++ b/mobile/android/base/locales/Makefile.in
@@ -68,12 +68,13 @@ strings-xml-preqs =\
 $(dir-strings-xml)/strings.xml: $(strings-xml-preqs)
 	$(NSINSTALL) -D $(dir-strings-xml)
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
       $(DEFINES) \
 	  -DBRANDPATH="$(BRANDPATH)" \
 	  -DSTRINGSPATH="$(STRINGSPATH)" \
 	  -DSYNCSTRINGSPATH="$(SYNCSTRINGSPATH)" \
 	  -DBOOKMARKSPATH="$(BOOKMARKSPATH)" \
+	  -DMOZ_APP_DISPLAYNAME="@MOZ_APP_DISPLAYNAME@" \
       $< \
 	  > $@
 
 include $(topsrcdir)/config/rules.mk
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -226,16 +226,18 @@ just addresses the organization to follo
 <!ENTITY bookmarkhistory_import_bookmarks "Importing bookmarks
                                            from Android">
 <!ENTITY bookmarkhistory_import_history "Importing history
                                          from Android">
 <!ENTITY bookmarkhistory_import_wait "Please wait...">
 
 <!ENTITY webapp_generic_name "App">
 
+<!ENTITY searchable_description "Bookmarks and history">
+
 <!-- Updater notifications -->
 <!ENTITY updater_start_title "Update available for &brandShortName;">
 <!ENTITY updater_start_select "Touch to download">
 
 <!ENTITY updater_downloading_title "Downloading &brandShortName;">
 <!ENTITY updater_downloading_title_failed "Download failed">
 <!ENTITY updater_downloading_select "Touch to apply update once downloaded">
 <!ENTITY updater_downloading_retry "Touch to retry">
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/xml/searchable.xml.in
@@ -0,0 +1,8 @@
+#filter substitution
+<?xml version="1.0" encoding="utf-8"?>
+<searchable xmlns:android="http://schemas.android.com/apk/res/android"
+            android:label="@string/moz_app_displayname"
+            android:searchSuggestAuthority="@ANDROID_PACKAGE_NAME@.db.browser"
+            android:searchSuggestIntentAction="android.intent.action.SEARCH"
+            android:searchSettingsDescription="@string/searchable_description"
+            android:includeInGlobalSearch="true"/>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -6,16 +6,17 @@
 
 <!DOCTYPE resources [
 #includesubst @BRANDPATH@
 #includesubst @STRINGSPATH@
 #includesubst @SYNCSTRINGSPATH@
 ]>
 #includesubst @BOOKMARKSPATH@
 <resources>
+  <string name="moz_app_displayname">@MOZ_APP_DISPLAYNAME@</string>
 #include ../sync/strings.xml.in
   <string name="splash_settingup">&splash_settingup;</string>
   <string name="splash_bookmarks_history">&splash_bookmarks_history;</string>
   <string name="no_space_to_start_error">&no_space_to_start_error;</string>
   <string name="error_loading_file">&error_loading_file;</string>
 
   <string name="awesomebar_all_pages_title">&awesomebar_all_pages_title;</string>
   <string name="awesomebar_bookmarks_title">&awesomebar_bookmarks_title;</string>
@@ -212,16 +213,18 @@
   <string name="bookmarkhistory_button_import">&bookmarkhistory_button_import;</string>
   <string name="bookmarkhistory_import_both">&bookmarkhistory_import_both;</string>
   <string name="bookmarkhistory_import_bookmarks">&bookmarkhistory_import_bookmarks;</string>
   <string name="bookmarkhistory_import_history">&bookmarkhistory_import_history;</string>
   <string name="bookmarkhistory_import_wait">&bookmarkhistory_import_wait;</string>
 
   <string name="webapp_generic_name">&webapp_generic_name;</string>
 
+  <string name="searchable_description">&searchable_description;</string>
+
   <!-- Updater notifications -->
   <string name="updater_start_title">&updater_start_title;</string>
   <string name="updater_start_select">&updater_start_select;</string>
 
   <string name="updater_downloading_title">&updater_downloading_title;</string>
   <string name="updater_downloading_title_failed">&updater_downloading_title_failed;</string>
   <string name="updater_downloading_select">&updater_downloading_select;</string>
   <string name="updater_downloading_retry">&updater_downloading_retry;</string>