resolved conflicts for merge of 565505 to master
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d95877e..aec23a2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -53,9 +53,9 @@
(android.test) library. -->
<uses-library android:name="android.test.runner" />
- <provider android:name="BrowserProvider"
- android:authorities="browser"
- android:multiprocess="true"
+ <provider android:name="BrowserProvider"
+ android:authorities="browser"
+ android:multiprocess="true"
android:readPermission="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
android:writePermission="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"/>
<activity android:name="BrowserActivity"
@@ -112,7 +112,6 @@
<data android:scheme="https" />
</intent-filter>
<intent-filter>
- <action android:name="android.intent.action.WEB_SEARCH" />
<action android:name="android.intent.action.MEDIA_SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@@ -149,7 +148,7 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
- </activity-alias>
+ </activity-alias>
<activity android:name="BrowserDownloadPage" android:label=""
android:configChanges="orientation|keyboardHidden">
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 7d6be9e..b5864e6 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -170,6 +170,13 @@
private WebStorage.QuotaUpdater mWebStorageQuotaUpdater = null;
+ // These are single-character shortcuts for searching popular sources.
+ private static final int SHORTCUT_INVALID = 0;
+ private static final int SHORTCUT_GOOGLE_SEARCH = 1;
+ private static final int SHORTCUT_WIKIPEDIA_SEARCH = 2;
+ private static final int SHORTCUT_DICTIONARY_SEARCH = 3;
+ private static final int SHORTCUT_GOOGLE_MOBILE_LOCAL_SEARCH = 4;
+
/* Whitelisted webpages
private static HashSet<String> sWhiteList;
@@ -687,6 +694,12 @@
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Browser");
+ // If this was a web search request, pass it on to the default web search provider.
+ if (handleWebSearchIntent(getIntent())) {
+ moveTaskToBack(true);
+ return;
+ }
+
if (!mTabControl.restoreState(icicle)) {
// clear up the thumbnail directory if we can't restore the state as
// none of the files in the directory are referenced any more.
@@ -836,6 +849,12 @@
|| Intent.ACTION_SEARCH.equals(action)
|| MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
|| Intent.ACTION_WEB_SEARCH.equals(action)) {
+ // If this was a search request (e.g. search query directly typed into the address bar),
+ // pass it on to the default web search provider.
+ if (handleWebSearchIntent(intent)) {
+ return;
+ }
+
String url = getUrlFromIntent(intent);
if (url == null || url.length() == 0) {
url = mSettings.getHomePage();
@@ -904,6 +923,71 @@
}
}
+ private int parseUrlShortcut(String url) {
+ if (url == null) return SHORTCUT_INVALID;
+
+ // FIXME: quick search, need to be customized by setting
+ if (url.length() > 2 && url.charAt(1) == ' ') {
+ switch (url.charAt(0)) {
+ case 'g': return SHORTCUT_GOOGLE_SEARCH;
+ case 'w': return SHORTCUT_WIKIPEDIA_SEARCH;
+ case 'd': return SHORTCUT_DICTIONARY_SEARCH;
+ case 'l': return SHORTCUT_GOOGLE_MOBILE_LOCAL_SEARCH;
+ }
+ }
+ return SHORTCUT_INVALID;
+ }
+
+ /**
+ * Launches the default web search activity with the query parameters if the given intent's data
+ * are identified as plain search terms and not URLs/shortcuts.
+ * @return true if the intent was handled and web search activity was launched, false if not.
+ */
+ private boolean handleWebSearchIntent(Intent intent) {
+ if (intent == null) return false;
+
+ String url = null;
+ final String action = intent.getAction();
+ if (Intent.ACTION_VIEW.equals(action)) {
+ url = intent.getData().toString();
+ } else if (Intent.ACTION_SEARCH.equals(action)
+ || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
+ || Intent.ACTION_WEB_SEARCH.equals(action)) {
+ url = intent.getStringExtra(SearchManager.QUERY);
+ }
+ return handleWebSearchRequest(url);
+ }
+
+ /**
+ * Launches the default web search activity with the query parameters if the given url string
+ * was identified as plain search terms and not URL/shortcut.
+ * @return true if the request was handled and web search activity was launched, false if not.
+ */
+ private boolean handleWebSearchRequest(String inUrl) {
+ if (inUrl == null) return false;
+
+ // In general, we shouldn't modify URL from Intent.
+ // But currently, we get the user-typed URL from search box as well.
+ String url = fixUrl(inUrl).trim();
+
+ // URLs and site specific search shortcuts are handled by the regular flow of control, so
+ // return early.
+ if (Regex.WEB_URL_PATTERN.matcher(url).matches()
+ || parseUrlShortcut(url) != SHORTCUT_INVALID) {
+ return false;
+ }
+
+ Browser.updateVisitedHistory(mResolver, url, false);
+ Browser.addSearchUrl(mResolver, url);
+
+ Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.putExtra(SearchManager.QUERY, url);
+ startActivity(intent);
+
+ return true;
+ }
+
private String getUrlFromIntent(Intent intent) {
String url = null;
if (intent != null) {
@@ -4581,34 +4665,22 @@
return inUrl;
}
if (hasSpace) {
- // FIXME: quick search, need to be customized by setting
- if (inUrl.length() > 2 && inUrl.charAt(1) == ' ') {
- // FIXME: Is this the correct place to add to searches?
- // what if someone else calls this function?
- char char0 = inUrl.charAt(0);
-
- if (char0 == 'g') {
- Browser.addSearchUrl(mResolver, inUrl);
- return composeSearchUrl(inUrl.substring(2));
-
- } else if (char0 == 'w') {
- Browser.addSearchUrl(mResolver, inUrl);
- return URLUtil.composeSearchUrl(inUrl.substring(2),
- QuickSearch_W,
- QUERY_PLACE_HOLDER);
-
- } else if (char0 == 'd') {
- Browser.addSearchUrl(mResolver, inUrl);
- return URLUtil.composeSearchUrl(inUrl.substring(2),
- QuickSearch_D,
- QUERY_PLACE_HOLDER);
-
- } else if (char0 == 'l') {
- Browser.addSearchUrl(mResolver, inUrl);
+ // FIXME: Is this the correct place to add to searches?
+ // what if someone else calls this function?
+ int shortcut = parseUrlShortcut(inUrl);
+ if (shortcut != SHORTCUT_INVALID) {
+ Browser.addSearchUrl(mResolver, inUrl);
+ String query = inUrl.substring(2);
+ switch (shortcut) {
+ case SHORTCUT_GOOGLE_SEARCH:
+ return composeSearchUrl(query);
+ case SHORTCUT_WIKIPEDIA_SEARCH:
+ return URLUtil.composeSearchUrl(query, QuickSearch_W, QUERY_PLACE_HOLDER);
+ case SHORTCUT_DICTIONARY_SEARCH:
+ return URLUtil.composeSearchUrl(query, QuickSearch_D, QUERY_PLACE_HOLDER);
+ case SHORTCUT_GOOGLE_MOBILE_LOCAL_SEARCH:
// FIXME: we need location in this case
- return URLUtil.composeSearchUrl(inUrl.substring(2),
- QuickSearch_L,
- QUERY_PLACE_HOLDER);
+ return URLUtil.composeSearchUrl(query, QuickSearch_L, QUERY_PLACE_HOLDER);
}
}
} else {
diff --git a/src/com/android/browser/BrowserProvider.java b/src/com/android/browser/BrowserProvider.java
index df52d80..8ed889e 100644
--- a/src/com/android/browser/BrowserProvider.java
+++ b/src/com/android/browser/BrowserProvider.java
@@ -28,6 +28,8 @@
import android.content.SharedPreferences;
import android.content.UriMatcher;
import android.content.SharedPreferences.Editor;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.database.AbstractCursor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
@@ -62,7 +64,7 @@
private static final String[] SUGGEST_PROJECTION = new String[] {
"_id", "url", "title", "bookmark"
};
- private static final String SUGGEST_SELECTION =
+ private static final String SUGGEST_SELECTION =
"url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ?"
+ " OR title LIKE ?";
private String[] SUGGEST_ARGS = new String[5];
@@ -141,11 +143,11 @@
// 17 -> 18 Added favicon in bookmarks table for Home shortcuts
// 18 -> 19 Remove labels table
private static final int DATABASE_VERSION = 19;
-
+
// Regular expression which matches http://, followed by some stuff, followed by
// optionally a trailing slash, all matched as separate groups.
private static final Pattern STRIP_URL_PATTERN = Pattern.compile("^(http://)(.*?)(/$)?");
-
+
// The hex color string to be applied to urls of website suggestions, as derived from
// the current theme. This is not set until/unless beautifyUrl is called, at which point
// this variable caches the color value.
@@ -153,12 +155,12 @@
public BrowserProvider() {
}
-
+
private static CharSequence replaceSystemPropertyInString(Context context, CharSequence srcString) {
StringBuffer sb = new StringBuffer();
int lastCharLoc = 0;
-
+
final String client_id = Partner.getString(context.getContentResolver(), Partner.CLIENT_ID);
for (int i = 0; i < srcString.length(); ++i) {
@@ -220,7 +222,7 @@
CharSequence bookmarkDestination = replaceSystemPropertyInString(mContext, bookmarks[i + 1]);
db.execSQL("INSERT INTO bookmarks (title, url, visits, " +
"date, created, bookmark)" + " VALUES('" +
- bookmarks[i] + "', '" + bookmarkDestination +
+ bookmarks[i] + "', '" + bookmarkDestination +
"', 0, 0, 0, 1);");
}
} catch (ArrayIndexOutOfBoundsException e) {
@@ -251,7 +253,7 @@
public boolean onCreate() {
final Context context = getContext();
mOpenHelper = new DatabaseHelper(context);
- // we added "picasa web album" into default bookmarks for version 19.
+ // we added "picasa web album" into default bookmarks for version 19.
// To avoid erasing the bookmark table, we added it explicitly for
// version 18 and 19 as in the other cases, we will erase the table.
if (DATABASE_VERSION == 18 || DATABASE_VERSION == 19) {
@@ -292,9 +294,9 @@
* Subclass AbstractCursor so we can combine multiple Cursors and add
* "Google Search".
* Here are the rules.
- * 1. We only have MAX_SUGGESTION_LONG_ENTRIES in the list plus
+ * 1. We only have MAX_SUGGESTION_LONG_ENTRIES in the list plus
* "Google Search";
- * 2. If bookmark/history entries are less than
+ * 2. If bookmark/history entries are less than
* (MAX_SUGGESTION_SHORT_ENTRIES -1), we include Google suggest.
*/
private class MySuggestionCursor extends AbstractCursor {
@@ -304,6 +306,9 @@
private int mSuggestionCount;
private boolean mBeyondCursor;
private String mString;
+ private int mSuggestText1Id;
+ private int mSuggestText2Id;
+ private int mSuggestQueryId;
public MySuggestionCursor(Cursor hc, Cursor sc, String string) {
mHistoryCursor = hc;
@@ -315,6 +320,22 @@
}
mString = string;
mBeyondCursor = false;
+
+ // Some web suggest providers only give suggestions and have no description string for
+ // items. The order of the result columns may be different as well. So retrieve the
+ // column indices for the fields we need now and check before using below.
+ if (mSuggestCursor == null) {
+ mSuggestText1Id = -1;
+ mSuggestText2Id = -1;
+ mSuggestQueryId = -1;
+ } else {
+ mSuggestText1Id = mSuggestCursor.getColumnIndex(
+ SearchManager.SUGGEST_COLUMN_TEXT_1);
+ mSuggestText2Id = mSuggestCursor.getColumnIndex(
+ SearchManager.SUGGEST_COLUMN_TEXT_2);
+ mSuggestQueryId = mSuggestCursor.getColumnIndex(
+ SearchManager.SUGGEST_COLUMN_QUERY);
+ }
}
@Override
@@ -347,7 +368,7 @@
public String[] getColumnNames() {
return COLUMNS;
}
-
+
@Override
public String getString(int columnIndex) {
if ((mPos != -1 && mHistoryCursor != null)) {
@@ -370,7 +391,8 @@
if (mHistoryCount > mPos) {
return getHistoryTitle();
} else if (!mBeyondCursor) {
- return mSuggestCursor.getString(1);
+ if (mSuggestText1Id == -1) return null;
+ return mSuggestCursor.getString(mSuggestText1Id);
} else {
return mString;
}
@@ -379,7 +401,8 @@
if (mHistoryCount > mPos) {
return getHistorySubtitle();
} else if (!mBeyondCursor) {
- return mSuggestCursor.getString(2);
+ if (mSuggestText2Id == -1) return null;
+ return mSuggestCursor.getString(mSuggestText2Id);
} else {
return getContext().getString(R.string.search_the_web);
}
@@ -408,11 +431,12 @@
if (mHistoryCount > mPos) {
return null;
} else if (!mBeyondCursor) {
- return mSuggestCursor.getString(3);
+ if (mSuggestQueryId == -1) return null;
+ return mSuggestCursor.getString(mSuggestQueryId);
} else {
return mString;
}
-
+
case SUGGEST_COLUMN_FORMAT:
return "html";
}
@@ -481,11 +505,11 @@
mSuggestCursor = null;
}
}
-
+
/**
* Provides the title (text line 1) for a browser suggestion, which should be the
* webpage title. If the webpage title is empty, returns the stripped url instead.
- *
+ *
* @return the title string to use
*/
private String getHistoryTitle() {
@@ -495,12 +519,12 @@
}
return title;
}
-
+
/**
* Provides the subtitle (text line 2) for a browser suggestion, which should be the
* webpage url. If the webpage title is empty, then the url should go in the title
* instead, and the subtitle should be empty, so this would return null.
- *
+ *
* @return the subtitle string to use, or null if none
*/
private String getHistorySubtitle() {
@@ -511,7 +535,7 @@
return beautifyUrl(mHistoryCursor.getString(1 /* url */));
}
}
-
+
/**
* Strips "http://" from the beginning of a url and "/" from the end,
* and adds html formatting to make it green.
@@ -523,19 +547,19 @@
getContext().getTheme().resolveAttribute(
com.android.internal.R.attr.textColorSearchUrl, colorValue, true);
int color = getContext().getResources().getColor(colorValue.resourceId);
-
+
// Convert the int color value into a hex string, and strip the first two
// characters which will be the alpha transparency (html doesn't want this).
mSearchUrlColorHex = Integer.toHexString(color).substring(2);
}
-
+
return "<font color=\"#" + mSearchUrlColorHex + "\">" + stripUrl(url) + "</font>";
}
}
@Override
public Cursor query(Uri url, String[] projectionIn, String selection,
- String[] selectionArgs, String sortOrder)
+ String[] selectionArgs, String sortOrder)
throws IllegalStateException {
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
@@ -580,15 +604,20 @@
// get Google suggest if there is still space in the list
if (myArgs != null && myArgs.length > 1
&& c.getCount() < (MAX_SUGGESTION_SHORT_ENTRIES - 1)) {
- // TODO: This shouldn't be hard-coded. Instead, it should use the
- // default web search provider. But the API for that is not implemented yet.
- ComponentName googleSearchComponent =
- new ComponentName("com.android.googlesearch",
- "com.android.googlesearch.GoogleSearch");
- SearchableInfo si =
- SearchManager.getSearchableInfo(googleSearchComponent, false);
- Cursor sc = SearchManager.getSuggestions(getContext(), si, selectionArgs[0]);
- return new MySuggestionCursor(c, sc, selectionArgs[0]);
+ Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ ResolveInfo info = getContext().getPackageManager().resolveActivity(
+ intent, PackageManager.MATCH_DEFAULT_ONLY);
+ if (info != null) {
+ ComponentName googleSearchComponent =
+ new ComponentName(info.activityInfo.packageName,
+ info.activityInfo.name);
+ SearchableInfo si =
+ SearchManager.getSearchableInfo(googleSearchComponent, false);
+ Cursor sc = SearchManager.getSuggestions(
+ getContext(), si, selectionArgs[0]);
+ return new MySuggestionCursor(c, sc, selectionArgs[0]);
+ }
}
return new MySuggestionCursor(c, null, selectionArgs[0]);
}
@@ -740,14 +769,14 @@
getContext().getContentResolver().notifyChange(url, null);
return ret;
}
-
+
/**
* Strips the provided url of preceding "http://" and any trailing "/". Does not
* strip "https://". If the provided string cannot be stripped, the original string
* is returned.
- *
+ *
* TODO: Put this in TextUtils to be used by other packages doing something similar.
- *
+ *
* @param url a url to strip, like "http://www.google.com/"
* @return a stripped url like "www.google.com", or the original string if it could
* not be stripped