summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
authorBjorn Bringert <bringert@android.com>2011-03-03 00:12:50 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-03-03 00:12:50 -0800
commit02f97585a675aba7ae81554060bbf2d526b76c61 (patch)
treeaa37d6a3eb88e6ac6b025f490e912aca9f4a1b20 /src/com/android
parent57996ae649fbfc157ec360f86d154e0c3b57b9ad (diff)
parent5119edd5744cfc6d3a8ed480a8853586c737bed4 (diff)
downloadpackages_apps_Browser-02f97585a675aba7ae81554060bbf2d526b76c61.zip
packages_apps_Browser-02f97585a675aba7ae81554060bbf2d526b76c61.tar.gz
packages_apps_Browser-02f97585a675aba7ae81554060bbf2d526b76c61.tar.bz2
Merge "Implement the psychic search engine."
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/browser/BaseUi.java4
-rw-r--r--src/com/android/browser/BrowserSettings.java59
-rw-r--r--src/com/android/browser/Controller.java5
-rw-r--r--src/com/android/browser/InstantSearchEngine.java407
-rw-r--r--src/com/android/browser/SuggestionsAdapter.java83
-rw-r--r--src/com/android/browser/TitleBarXLarge.java11
-rw-r--r--src/com/android/browser/UI.java5
-rw-r--r--src/com/android/browser/UiController.java4
-rw-r--r--src/com/android/browser/UrlInputView.java52
-rw-r--r--src/com/android/browser/XLargeUi.java5
-rw-r--r--src/com/android/browser/autocomplete/SuggestedTextController.java8
-rw-r--r--src/com/android/browser/autocomplete/SuggestiveAutoCompleteTextView.java100
-rw-r--r--src/com/android/browser/preferences/LabPreferencesFragment.java31
-rw-r--r--src/com/android/browser/search/DefaultSearchEngine.java5
-rw-r--r--src/com/android/browser/search/OpenSearchSearchEngine.java5
-rw-r--r--src/com/android/browser/search/SearchEngine.java5
-rw-r--r--src/com/android/browser/search/SearchEngines.java10
17 files changed, 690 insertions, 109 deletions
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java
index 93b0ec8..c01ec06 100644
--- a/src/com/android/browser/BaseUi.java
+++ b/src/com/android/browser/BaseUi.java
@@ -17,6 +17,7 @@
package com.android.browser;
import com.android.browser.Tab.LockIcon;
+import com.android.browser.UI.DropdownChangeListener;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
@@ -698,4 +699,7 @@ public abstract class BaseUi implements UI, WebViewFactory {
warning.show();
}
+ @Override
+ public void registerDropdownChangeListener(DropdownChangeListener d) {
+ }
}
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index f3bc48a..75e0cfb 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -113,6 +113,7 @@ public class BrowserSettings extends Observable implements OnSharedPreferenceCha
// Lab settings
private boolean quickControls = false;
private boolean useMostVisitedHomepage = false;
+ private boolean useInstant = false;
// By default the error console is shown once the user navigates to about:debug.
// The setting can be then toggled from the settings menu.
@@ -170,6 +171,7 @@ public class BrowserSettings extends Observable implements OnSharedPreferenceCha
public final static String PREF_AUTOLOGIN = "enable_autologin";
public final static String PREF_AUTOLOGIN_ACCOUNT = "autologin_account";
public final static String PREF_PLUGIN_STATE = "plugin_state";
+ public final static String PREF_USE_INSTANT = "use_instant_search";
private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; " +
"U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/533.16 (KHTML, " +
@@ -413,27 +415,37 @@ public class BrowserSettings extends Observable implements OnSharedPreferenceCha
}
}
+ private void updateSearchEngine(Context ctx, String searchEngineName, boolean force) {
+ if (force || searchEngine == null ||
+ !searchEngine.getName().equals(searchEngineName)) {
+ if (searchEngine != null) {
+ if (searchEngine.supportsVoiceSearch()) {
+ // One or more tabs could have been in voice search mode.
+ // Clear it, since the new SearchEngine may not support
+ // it, or may handle it differently.
+ for (int i = 0; i < mController.getTabControl().getTabCount(); i++) {
+ mController.getTabControl().getTab(i).revertVoiceSearchMode();
+ }
+ }
+ searchEngine.close();
+ }
+ searchEngine = SearchEngines.get(ctx, searchEngineName);
+
+ if (mController != null && (searchEngine instanceof InstantSearchEngine)) {
+ ((InstantSearchEngine) searchEngine).setController(mController);
+ }
+ }
+ }
+
/* package */ void syncSharedPreferences(Context ctx, SharedPreferences p) {
homeUrl =
p.getString(PREF_HOMEPAGE, homeUrl);
+
+ useInstant = p.getBoolean(PREF_USE_INSTANT, useInstant);
String searchEngineName = p.getString(PREF_SEARCH_ENGINE,
- SearchEngine.GOOGLE);
- if (searchEngine == null || !searchEngine.getName().equals(searchEngineName)) {
- if (searchEngine != null) {
- if (searchEngine.supportsVoiceSearch()) {
- // One or more tabs could have been in voice search mode.
- // Clear it, since the new SearchEngine may not support
- // it, or may handle it differently.
- for (int i = 0; i < mController.getTabControl().getTabCount(); i++) {
- mController.getTabControl().getTab(i).revertVoiceSearchMode();
- }
- }
- searchEngine.close();
- }
- searchEngine = SearchEngines.get(ctx, searchEngineName);
- }
- Log.i(TAG, "Selected search engine: " + searchEngine);
+ SearchEngine.GOOGLE);
+ updateSearchEngine(ctx, searchEngineName, false);
loadsImagesAutomatically = p.getBoolean("load_images",
loadsImagesAutomatically);
@@ -604,6 +616,10 @@ public class BrowserSettings extends Observable implements OnSharedPreferenceCha
return useMostVisitedHomepage;
}
+ public boolean useInstant() {
+ return useInstant;
+ }
+
public boolean showDebugSettings() {
return showDebugSettings;
}
@@ -723,6 +739,10 @@ public class BrowserSettings extends Observable implements OnSharedPreferenceCha
/* package */void setController(Controller ctrl) {
mController = ctrl;
updateTabControlSettings();
+
+ if (mController != null && (searchEngine instanceof InstantSearchEngine)) {
+ ((InstantSearchEngine) searchEngine).setController(mController);
+ }
}
/*
@@ -902,6 +922,13 @@ public class BrowserSettings extends Observable implements OnSharedPreferenceCha
quickControls = p.getBoolean(PREF_QUICK_CONTROLS, quickControls);
} else if (PREF_MOST_VISITED_HOMEPAGE.equals(key)) {
useMostVisitedHomepage = p.getBoolean(PREF_MOST_VISITED_HOMEPAGE, useMostVisitedHomepage);
+ } else if (PREF_USE_INSTANT.equals(key)) {
+ useInstant = p.getBoolean(PREF_USE_INSTANT, useInstant);
+ updateSearchEngine(mController.getActivity(), SearchEngine.GOOGLE, true);
+ } else if (PREF_SEARCH_ENGINE.equals(key)) {
+ final String searchEngineName = p.getString(PREF_SEARCH_ENGINE,
+ SearchEngine.GOOGLE);
+ updateSearchEngine(mController.getActivity(), searchEngineName, false);
}
}
}
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index ae91f11..e4b0a0c 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -17,6 +17,7 @@
package com.android.browser;
import com.android.browser.IntentHandler.UrlData;
+import com.android.browser.UI.DropdownChangeListener;
import com.android.browser.search.SearchEngine;
import com.android.common.Search;
@@ -2608,4 +2609,8 @@ public class Controller
}
}
+ @Override
+ public void registerDropdownChangeListener(DropdownChangeListener d) {
+ mUi.registerDropdownChangeListener(d);
+ }
}
diff --git a/src/com/android/browser/InstantSearchEngine.java b/src/com/android/browser/InstantSearchEngine.java
new file mode 100644
index 0000000..1d9bdd6
--- /dev/null
+++ b/src/com/android/browser/InstantSearchEngine.java
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.browser;
+
+import com.google.android.collect.Maps;
+import com.google.common.collect.Lists;
+
+import com.android.browser.Controller;
+import com.android.browser.R;
+import com.android.browser.UI.DropdownChangeListener;
+import com.android.browser.search.DefaultSearchEngine;
+import com.android.browser.search.SearchEngine;
+
+import android.app.SearchManager;
+import android.content.Context;
+import android.database.AbstractCursor;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.LruCache;
+import android.webkit.SearchBox;
+import android.webkit.WebView;
+
+import java.util.Collections;
+import java.util.List;
+
+public class InstantSearchEngine implements SearchEngine, DropdownChangeListener {
+ private static final String TAG = "Browser.InstantSearchEngine";
+ private static final boolean DBG = false;
+
+ private Controller mController;
+ private SearchBox mSearchBox;
+ private final BrowserSearchboxListener mListener = new BrowserSearchboxListener();
+ private int mHeight;
+
+ private String mInstantBaseUrl;
+ private final Context mContext;
+ // Used for startSearch( ) calls if for some reason instant
+ // is off, or no searchbox is present.
+ private final SearchEngine mWrapped;
+
+ public InstantSearchEngine(Context context, SearchEngine wrapped) {
+ mContext = context;
+ mWrapped = wrapped;
+ }
+
+ public void setController(Controller controller) {
+ mController = controller;
+ }
+
+ @Override
+ public String getName() {
+ return SearchEngine.GOOGLE;
+ }
+
+ @Override
+ public CharSequence getLabel() {
+ return mContext.getResources().getString(R.string.instant_search_label);
+ }
+
+ @Override
+ public void startSearch(Context context, String query, Bundle appData, String extraData) {
+ if (DBG) Log.d(TAG, "startSearch(" + query + ")");
+
+ switchSearchboxIfNeeded();
+
+ // If for some reason we are in a bad state, ensure that the
+ // user gets default search results at the very least.
+ if (mSearchBox == null & !isInstantPage()) {
+ mWrapped.startSearch(context, query, appData, extraData);
+ return;
+ }
+
+ mSearchBox.setQuery(query);
+ mSearchBox.setVerbatim(true);
+ mSearchBox.onsubmit();
+ }
+
+ private final class BrowserSearchboxListener implements SearchBox.SearchBoxListener {
+ /*
+ * The maximum number of out of order suggestions we accept
+ * before giving up the wait.
+ */
+ private static final int MAX_OUT_OF_ORDER = 5;
+
+ /*
+ * We wait for suggestions in increments of 600ms. This is primarily to
+ * guard against suggestions arriving out of order.
+ */
+ private static final int WAIT_INCREMENT_MS = 600;
+
+ /*
+ * A cache of suggestions received, keyed by the queries they were
+ * received for.
+ */
+ private final LruCache<String, List<String>> mSuggestions =
+ new LruCache<String, List<String>>(20);
+
+ /*
+ * The last set of suggestions received. We use this reduce UI flicker
+ * in case there is a delay in recieving suggestions.
+ */
+ private List<String> mLatestSuggestion = Collections.emptyList();
+
+ @Override
+ public synchronized void onSuggestionsReceived(String query, List<String> suggestions) {
+ if (DBG) Log.d(TAG, "onSuggestionsReceived(" + query + ")");
+
+ if (!TextUtils.isEmpty(query)) {
+ mSuggestions.put(query, suggestions);
+ mLatestSuggestion = suggestions;
+ }
+
+ notifyAll();
+ }
+
+ public synchronized List<String> tryWaitForSuggestions(String query) {
+ if (DBG) Log.d(TAG, "tryWait(" + query + ")");
+
+ int numWaitReturns = 0;
+
+ // This slightly unusual waiting construct is used to safeguard
+ // to some extent against suggestions arriving out of order. We
+ // wait for upto 5 notifyAll( ) calls to check if we received
+ // suggestions for a given query.
+ while (mSuggestions.get(query) == null) {
+ try {
+ wait(WAIT_INCREMENT_MS);
+ ++numWaitReturns;
+ if (numWaitReturns > MAX_OUT_OF_ORDER) {
+ // We've waited too long for suggestions to be returned.
+ // return the last available suggestion.
+ break;
+ }
+ } catch (InterruptedException e) {
+ return Collections.emptyList();
+ }
+ }
+
+ List<String> suggestions = mSuggestions.get(query);
+ if (suggestions == null) {
+ return mLatestSuggestion;
+ }
+
+ return suggestions;
+ }
+
+ public synchronized void clear() {
+ mSuggestions.evictAll();
+ }
+ }
+
+ private WebView getCurrentWebview() {
+ if (mController != null) {
+ return mController.getTabControl().getCurrentTopWebView();
+ }
+
+ return null;
+ }
+
+ /**
+ * Attaches the searchbox to the right browser page, i.e, the currently
+ * visible tab.
+ */
+ private void switchSearchboxIfNeeded() {
+ final SearchBox searchBox = getCurrentWebview().getSearchBox();
+ if (searchBox != mSearchBox) {
+ if (mSearchBox != null) {
+ mSearchBox.removeSearchBoxListener(mListener);
+ mListener.clear();
+ }
+ mSearchBox = searchBox;
+ mSearchBox.addSearchBoxListener(mListener);
+ }
+ }
+
+ private boolean isInstantPage() {
+ String currentUrl = getCurrentWebview().getUrl();
+
+ if (currentUrl != null) {
+ Uri uri = Uri.parse(currentUrl);
+ final String host = uri.getHost();
+ final String path = uri.getPath();
+
+ // Is there a utility class that does this ?
+ if (path != null && host != null) {
+ return host.startsWith("www.google.") &&
+ (path.startsWith("/search") || path.startsWith("/webhp"));
+ }
+ return false;
+ }
+
+ return false;
+ }
+
+ private void loadInstantPage() {
+ mController.getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getCurrentWebview().loadUrl(getInstantBaseUrl());
+ }
+ });
+ }
+
+ /**
+ * Queries for a given search term and returns a cursor containing
+ * suggestions ordered by best match.
+ */
+ @Override
+ public Cursor getSuggestions(Context context, String query) {
+ if (DBG) Log.d(TAG, "getSuggestions(" + query + ")");
+ if (query == null) {
+ return null;
+ }
+
+ if (!isInstantPage()) {
+ loadInstantPage();
+ }
+
+ switchSearchboxIfNeeded();
+
+ mController.registerDropdownChangeListener(this);
+
+ mSearchBox.setDimensions(0, 0, 0, mHeight);
+ mSearchBox.onresize();
+
+ if (TextUtils.isEmpty(query)) {
+ // To force the SRP to render an empty (no results) page.
+ mSearchBox.setVerbatim(true);
+ } else {
+ mSearchBox.setVerbatim(false);
+ }
+ mSearchBox.setQuery(query);
+ mSearchBox.onchange();
+
+ // Don't bother waiting for suggestions for an empty query. We still
+ // set the query so that the SRP clears itself.
+ if (TextUtils.isEmpty(query)) {
+ return new SuggestionsCursor(Collections.<String>emptyList());
+ } else {
+ return new SuggestionsCursor(mListener.tryWaitForSuggestions(query));
+ }
+ }
+
+ @Override
+ public boolean supportsSuggestions() {
+ return true;
+ }
+
+ @Override
+ public void close() {
+ if (mController != null) {
+ mController.registerDropdownChangeListener(null);
+ }
+ if (mSearchBox != null) {
+ mSearchBox.removeSearchBoxListener(mListener);
+ }
+ mListener.clear();
+ mWrapped.close();
+ }
+
+ @Override
+ public boolean supportsVoiceSearch() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "InstantSearchEngine {" + hashCode() + "}";
+ }
+
+ @Override
+ public boolean wantsEmptyQuery() {
+ return true;
+ }
+
+ private int rescaleHeight(int height) {
+ final float scale = getCurrentWebview().getScale();
+ if (scale != 0) {
+ return (int) (height / scale);
+ }
+
+ return height;
+ }
+
+ @Override
+ public void onNewDropdownDimensions(int height) {
+ final int rescaledHeight = rescaleHeight(height);
+
+ if (rescaledHeight != mHeight) {
+ mHeight = rescaledHeight;
+ mSearchBox.setDimensions(0, 0, 0, rescaledHeight);
+ mSearchBox.onresize();
+ }
+ }
+
+ private String getInstantBaseUrl() {
+ if (mInstantBaseUrl == null) {
+ String url = mContext.getResources().getString(R.string.instant_base);
+ if (url.indexOf("{CID}") != -1) {
+ url = url.replace("{CID}",
+ BrowserProvider.getClientId(mContext.getContentResolver()));
+ }
+ mInstantBaseUrl = url;
+ }
+
+ return mInstantBaseUrl;
+ }
+
+ // Indices of the columns in the below arrays.
+ private static final int COLUMN_INDEX_ID = 0;
+ private static final int COLUMN_INDEX_QUERY = 1;
+ private static final int COLUMN_INDEX_ICON = 2;
+ private static final int COLUMN_INDEX_TEXT_1 = 3;
+
+ private static final String[] COLUMNS_WITHOUT_DESCRIPTION = new String[] {
+ "_id",
+ SearchManager.SUGGEST_COLUMN_QUERY,
+ SearchManager.SUGGEST_COLUMN_ICON_1,
+ SearchManager.SUGGEST_COLUMN_TEXT_1,
+ };
+
+ private static class SuggestionsCursor extends AbstractCursor {
+ private final List<String> mSuggestions;
+
+ public SuggestionsCursor(List<String> suggestions) {
+ mSuggestions = suggestions;
+ }
+
+ @Override
+ public int getCount() {
+ return mSuggestions.size();
+ }
+
+ @Override
+ public String[] getColumnNames() {
+ return COLUMNS_WITHOUT_DESCRIPTION;
+ }
+
+ private String format(String suggestion) {
+ if (TextUtils.isEmpty(suggestion)) {
+ return "";
+ }
+ return suggestion;
+ }
+
+ @Override
+ public String getString(int column) {
+ if (mPos >= 0 && mPos < mSuggestions.size()) {
+ if ((column == COLUMN_INDEX_QUERY) || (column == COLUMN_INDEX_TEXT_1)) {
+ return format(mSuggestions.get(mPos));
+ } else if (column == COLUMN_INDEX_ICON) {
+ return String.valueOf(R.drawable.magnifying_glass);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public double getDouble(int column) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public float getFloat(int column) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getInt(int column) {
+ if (column == COLUMN_INDEX_ID) {
+ return mPos;
+ }
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getLong(int column) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public short getShort(int column) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isNull(int column) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/src/com/android/browser/SuggestionsAdapter.java b/src/com/android/browser/SuggestionsAdapter.java
index 3636bbf..6a9111f 100644
--- a/src/com/android/browser/SuggestionsAdapter.java
+++ b/src/com/android/browser/SuggestionsAdapter.java
@@ -24,6 +24,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.provider.BrowserContract;
+import android.text.Html;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -44,12 +45,12 @@ import java.util.List;
public class SuggestionsAdapter extends BaseAdapter implements Filterable,
OnClickListener {
- static final int TYPE_BOOKMARK = 0;
- static final int TYPE_HISTORY = 1;
- static final int TYPE_SUGGEST_URL = 2;
- static final int TYPE_SEARCH = 3;
- static final int TYPE_SUGGEST = 4;
- static final int TYPE_VOICE_SEARCH = 5;
+ public static final int TYPE_BOOKMARK = 0;
+ public static final int TYPE_HISTORY = 1;
+ public static final int TYPE_SUGGEST_URL = 2;
+ public static final int TYPE_SEARCH = 3;
+ public static final int TYPE_SUGGEST = 4;
+ public static final int TYPE_VOICE_SEARCH = 5;
private static final String[] COMBINED_PROJECTION =
{BrowserContract.Combined._ID, BrowserContract.Combined.TITLE,
@@ -58,16 +59,16 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable,
private static final String COMBINED_SELECTION =
"(url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ? OR title LIKE ?)";
- Context mContext;
- Filter mFilter;
+ final Context mContext;
+ final Filter mFilter;
SuggestionResults mMixedResults;
List<SuggestItem> mSuggestResults, mFilterResults;
List<CursorSource> mSources;
boolean mLandscapeMode;
- CompletionListener mListener;
- int mLinesPortrait;
- int mLinesLandscape;
- Object mResultsLock = new Object();
+ final CompletionListener mListener;
+ final int mLinesPortrait;
+ final int mLinesLandscape;
+ final Object mResultsLock = new Object();
List<String> mVoiceResults;
boolean mReverseResults;
boolean mIncognitoMode;
@@ -87,6 +88,7 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable,
getInteger(R.integer.max_suggest_lines_portrait);
mLinesLandscape = mContext.getResources().
getInteger(R.integer.max_suggest_lines_landscape);
+
mFilter = new SuggestFilter();
addSource(new CombinedCursor());
}
@@ -111,13 +113,12 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable,
@Override
public void onClick(View v) {
SuggestItem item = (SuggestItem) ((View) v.getParent()).getTag();
+
if (R.id.icon2 == v.getId()) {
// replace input field text with suggestion text
- mListener.onSearch(item.title);
+ mListener.onSearch(getSuggestionUrl(item));
} else {
- mListener.onSelect(
- (TextUtils.isEmpty(item.url)? item.title : item.url),
- item.type, item.extra);
+ mListener.onSelect(getSuggestionUrl(item), item.type, item.extra);
}
}
@@ -179,7 +180,7 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable,
ImageView ic1 = (ImageView) view.findViewById(R.id.icon1);
View ic2 = view.findViewById(R.id.icon2);
View div = view.findViewById(R.id.divider);
- tv1.setText(item.title);
+ tv1.setText(Html.fromHtml(item.title));
if (TextUtils.isEmpty(item.url)) {
tv2.setVisibility(View.GONE);
} else {
@@ -282,11 +283,16 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable,
}
}
+ private boolean shouldProcessEmptyQuery() {
+ final SearchEngine searchEngine = BrowserSettings.getInstance().getSearchEngine();
+ return searchEngine.wantsEmptyQuery();
+ }
+
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults res = new FilterResults();
if (mVoiceResults == null) {
- if (TextUtils.isEmpty(constraint)) {
+ if (TextUtils.isEmpty(constraint) && !shouldProcessEmptyQuery()) {
res.count = 0;
res.values = null;
return res;
@@ -313,8 +319,7 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable,
}
void mixResults(List<SuggestItem> results) {
- int maxLines = mLandscapeMode ? mLinesLandscape : mLinesPortrait;
- maxLines = (int) Math.ceil(maxLines / 2.0);
+ int maxLines = getMaxLines();
for (int i = 0; i < mSources.size(); i++) {
CursorSource s = mSources.get(i);
int n = Math.min(s.getCount(), maxLines);
@@ -334,7 +339,12 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable,
notifyDataSetChanged();
}
}
+ }
+ private int getMaxLines() {
+ int maxLines = mLandscapeMode ? mLinesLandscape : mLinesPortrait;
+ maxLines = (int) Math.ceil(maxLines / 2.0);
+ return maxLines;
}
/**
@@ -366,11 +376,7 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable,
}
int getLineCount() {
- if (mLandscapeMode) {
- return Math.min(mLinesLandscape, items.size());
- } else {
- return Math.min(mLinesPortrait, items.size());
- }
+ return Math.min((mLandscapeMode ? mLinesLandscape : mLinesPortrait), items.size());
}
@Override
@@ -543,8 +549,8 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable,
if (mCursor != null) {
mCursor.close();
}
+ SearchEngine searchEngine = BrowserSettings.getInstance().getSearchEngine();
if (!TextUtils.isEmpty(constraint)) {
- SearchEngine searchEngine = BrowserSettings.getInstance().getSearchEngine();
if (searchEngine != null && searchEngine.supportsSuggestions()) {
mCursor = searchEngine.getSuggestions(mContext, constraint.toString());
if (mCursor != null) {
@@ -552,19 +558,44 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable,
}
}
} else {
+ if (searchEngine.wantsEmptyQuery()) {
+ mCursor = searchEngine.getSuggestions(mContext, "");
+ }
mCursor = null;
}
}
}
+ private boolean useInstant() {
+ return BrowserSettings.getInstance().useInstant();
+ }
+
public void clearCache() {
mFilterResults = null;
mSuggestResults = null;
+ notifyDataSetInvalidated();
}
public void setIncognitoMode(boolean incognito) {
mIncognitoMode = incognito;
clearCache();
}
+
+ static String getSuggestionTitle(SuggestItem item) {
+ // There must be a better way to strip HTML from things.
+ // This method is used in multiple places. It is also more
+ // expensive than a standard html escaper.
+ return (item.title != null) ? Html.fromHtml(item.title).toString() : null;
+ }
+
+ static String getSuggestionUrl(SuggestItem item) {
+ final String title = SuggestionsAdapter.getSuggestionTitle(item);
+
+ if (TextUtils.isEmpty(item.url)) {
+ return title;
+ }
+
+ return item.url;
+ }
}
diff --git a/src/com/android/browser/TitleBarXLarge.java b/src/com/android/browser/TitleBarXLarge.java
index c0df47c..8a715b1 100644
--- a/src/com/android/browser/TitleBarXLarge.java
+++ b/src/com/android/browser/TitleBarXLarge.java
@@ -17,12 +17,15 @@
package com.android.browser;
import com.android.browser.autocomplete.SuggestedTextController.TextChangeWatcher;
+import com.android.browser.UI.DropdownChangeListener;
import com.android.browser.search.SearchEngine;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
+import android.database.DataSetObserver;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.view.KeyEvent;
@@ -37,6 +40,7 @@ import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -264,7 +268,7 @@ public class TitleBarXLarge extends TitleBarBase
void setFavicon(Bitmap icon) { }
private void clearOrClose() {
- if (TextUtils.isEmpty(mUrlInput.getText())) {
+ if (TextUtils.isEmpty(mUrlInput.getUserText())) {
// close
mUrlInput.clearFocus();
} else {
@@ -333,7 +337,7 @@ public class TitleBarXLarge extends TitleBarBase
}
private void updateSearchMode(boolean userEdited) {
- setSearchMode(!userEdited || TextUtils.isEmpty(mUrlInput.getText()));
+ setSearchMode(!userEdited || TextUtils.isEmpty(mUrlInput.getUserText()));
}
private void setSearchMode(boolean voiceSearchEnabled) {
@@ -411,4 +415,7 @@ public class TitleBarXLarge extends TitleBarBase
}
}
+ void registerDropdownChangeListener(DropdownChangeListener d) {
+ mUrlInput.registerDropdownChangeListener(d);
+ }
}
diff --git a/src/com/android/browser/UI.java b/src/com/android/browser/UI.java
index 34dcaee..bec7034 100644
--- a/src/com/android/browser/UI.java
+++ b/src/com/android/browser/UI.java
@@ -122,4 +122,9 @@ public interface UI {
boolean dispatchKey(int code, KeyEvent event);
+
+ public static interface DropdownChangeListener {
+ void onNewDropdownDimensions(int height);
+ }
+ void registerDropdownChangeListener(DropdownChangeListener d);
}
diff --git a/src/com/android/browser/UiController.java b/src/com/android/browser/UiController.java
index 6075d36..551d0ce 100644
--- a/src/com/android/browser/UiController.java
+++ b/src/com/android/browser/UiController.java
@@ -16,6 +16,8 @@
package com.android.browser;
+import com.android.browser.UI.DropdownChangeListener;
+
import android.content.Intent;
import android.webkit.WebView;
@@ -84,4 +86,6 @@ public interface UiController extends BookmarksHistoryCallbacks {
void registerOptionsMenuHandler(OptionsMenuHandler handler);
void unregisterOptionsMenuHandler(OptionsMenuHandler handler);
+
+ void registerDropdownChangeListener(DropdownChangeListener d);
}
diff --git a/src/com/android/browser/UrlInputView.java b/src/com/android/browser/UrlInputView.java
index 40c1bf6..b7f2bff 100644
--- a/src/com/android/browser/UrlInputView.java
+++ b/src/com/android/browser/UrlInputView.java
@@ -18,6 +18,7 @@ package com.android.browser;
import com.android.browser.SuggestionsAdapter.CompletionListener;
import com.android.browser.SuggestionsAdapter.SuggestItem;
+import com.android.browser.UI.DropdownChangeListener;
import com.android.browser.autocomplete.SuggestiveAutoCompleteTextView;
import com.android.browser.search.SearchEngine;
import com.android.browser.search.SearchEngineInfo;
@@ -25,11 +26,14 @@ import com.android.browser.search.SearchEngines;
import android.content.Context;
import android.content.res.Configuration;
+import android.database.DataSetObserver;
+import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Patterns;
import android.view.KeyEvent;
import android.view.View;
+import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
@@ -58,6 +62,7 @@ public class UrlInputView extends SuggestiveAutoCompleteTextView
private boolean mLandscape;
private boolean mIncognitoMode;
private boolean mNeedsUpdate;
+ private DropdownChangeListener mDropdownListener;
public UrlInputView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
@@ -84,6 +89,22 @@ public class UrlInputView extends SuggestiveAutoCompleteTextView
setThreshold(1);
setOnItemClickListener(this);
mNeedsUpdate = false;
+ mDropdownListener = null;
+
+ mAdapter.registerDataSetObserver(new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ if (!isPopupShowing()) {
+ return;
+ }
+ dispatchChange();
+ }
+
+ @Override
+ public void onInvalidated() {
+ dispatchChange();
+ }
+ });
}
/**
@@ -130,7 +151,7 @@ public class UrlInputView extends SuggestiveAutoCompleteTextView
mAdapter.setLandscapeMode(mLandscape);
if (isPopupShowing() && (getVisibility() == View.VISIBLE)) {
setupDropDown();
- performFiltering(getText(), 0);
+ performFiltering(getUserText(), 0);
}
}
@@ -158,12 +179,21 @@ public class UrlInputView extends SuggestiveAutoCompleteTextView
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- finishInput(getText().toString(), null, TYPED);
+ if (BrowserSettings.getInstance().useInstant() &&
+ (actionId == EditorInfo.IME_ACTION_NEXT)) {
+ // When instant is turned on AND the user chooses to complete
+ // using the tab key, then use the completion rather than the
+ // text that the user has typed.
+ finishInput(getText().toString(), null, TYPED);
+ } else {
+ finishInput(getUserText(), null, TYPED);
+ }
+
return true;
}
void forceFilter() {
- performFiltering(getText().toString(), 0);
+ performForcedFiltering();
showDropDown();
}
@@ -227,8 +257,7 @@ public class UrlInputView extends SuggestiveAutoCompleteTextView
public void onItemClick(
AdapterView<?> parent, View view, int position, long id) {
SuggestItem item = mAdapter.getItem(position);
- onSelect((TextUtils.isEmpty(item.url) ? item.title : item.url),
- item.type, item.extra);
+ onSelect(SuggestionsAdapter.getSuggestionUrl(item), item.type, item.extra);
}
interface UrlInputListener {
@@ -258,4 +287,17 @@ public class UrlInputView extends SuggestiveAutoCompleteTextView
public SuggestionsAdapter getAdapter() {
return mAdapter;
}
+
+ private void dispatchChange() {
+ final Rect popupRect = new Rect();
+ getPopupDrawableRect(popupRect);
+
+ if (mDropdownListener != null) {
+ mDropdownListener.onNewDropdownDimensions(popupRect.height());
+ }
+ }
+
+ void registerDropdownChangeListener(DropdownChangeListener d) {
+ mDropdownListener = d;
+ }
}
diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java
index d3f83f9..33151f7 100644
--- a/src/com/android/browser/XLargeUi.java
+++ b/src/com/android/browser/XLargeUi.java
@@ -17,6 +17,7 @@
package com.android.browser;
import com.android.browser.ScrollWebView.ScrollListener;
+import com.android.browser.UI.DropdownChangeListener;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
@@ -483,4 +484,8 @@ public class XLargeUi extends BaseUi implements ScrollListener {
return mTabBar;
}
+ @Override
+ public void registerDropdownChangeListener(DropdownChangeListener d) {
+ mTitleBar.registerDropdownChangeListener(d);
+ }
}
diff --git a/src/com/android/browser/autocomplete/SuggestedTextController.java b/src/com/android/browser/autocomplete/SuggestedTextController.java
index e9b74ce..95dfcab 100644
--- a/src/com/android/browser/autocomplete/SuggestedTextController.java
+++ b/src/com/android/browser/autocomplete/SuggestedTextController.java
@@ -57,6 +57,8 @@ public class SuggestedTextController {
private final SuggestedSpan mSuggested;
private String mSuggestedText;
private TextChangeAttributes mCurrentTextChange;
+ private boolean mSuspended = false;
+
/**
* While this is non-null, any changes made to the cursor position or selection are ignored. Is
* stored the selection state at the moment when selection change processing was disabled.
@@ -120,6 +122,10 @@ public class SuggestedTextController {
}
}
+ public boolean isCursorHandlingSuspended() {
+ return mSuspended;
+ }
+
public Parcelable saveInstanceState(Parcelable superState) {
assertNotIgnoringSelectionChanges();
SavedState ss = new SavedState(superState);
@@ -160,6 +166,7 @@ public class SuggestedTextController {
assertNotIgnoringSelectionChanges();
Editable buffer = mTextOwner.getText();
mTextSelectionBeforeIgnoringChanges = new BufferSelection(buffer);
+ mSuspended = true;
}
/**
@@ -181,6 +188,7 @@ public class SuggestedTextController {
oldSelection.mEnd, oldSelection.mEnd,
newSelection.mEnd, newSelection.mEnd);
}
+ mSuspended = false;
}
/**
diff --git a/src/com/android/browser/autocomplete/SuggestiveAutoCompleteTextView.java b/src/com/android/browser/autocomplete/SuggestiveAutoCompleteTextView.java
index d93066c..e8ca980 100644
--- a/src/com/android/browser/autocomplete/SuggestiveAutoCompleteTextView.java
+++ b/src/com/android/browser/autocomplete/SuggestiveAutoCompleteTextView.java
@@ -15,6 +15,7 @@
*/
package com.android.browser.autocomplete;
+import com.android.browser.BrowserSettings;
import com.android.browser.SuggestionsAdapter;
import com.android.browser.SuggestionsAdapter.SuggestItem;
import com.android.browser.autocomplete.SuggestedTextController.TextChangeWatcher;
@@ -26,9 +27,9 @@ import android.database.DataSetObserver;
import android.graphics.Rect;
import android.os.Parcelable;
import android.text.Editable;
+import android.text.Html;
import android.text.Selection;
import android.text.TextUtils;
-import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.AbsSavedState;
@@ -77,7 +78,6 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
private boolean mDropDownDismissedOnCompletion = true;
private int mLastKeyCode = KeyEvent.KEYCODE_UNKNOWN;
- private boolean mOpenBefore;
// Set to true when text is set directly and no filtering shall be performed
private boolean mBlockCompletion;
@@ -101,6 +101,8 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
public SuggestiveAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ // The completions are always shown in the same color as the hint
+ // text.
mController = new SuggestedTextController(this, getHintTextColors().getDefaultColor());
mPopup = new ListPopupWindow(context, attrs,
R.attr.autoCompleteTextViewStyle);
@@ -223,7 +225,7 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
return mPopup.getHorizontalOffset();
}
- protected void setThreshold(int threshold) {
+ public void setThreshold(int threshold) {
if (threshold <= 0) {
threshold = 1;
}
@@ -341,9 +343,9 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
* triggered.
*/
private boolean enoughToFilter() {
- if (DEBUG) Log.v(TAG, "Enough to filter: len=" + getText().length()
+ if (DEBUG) Log.v(TAG, "Enough to filter: len=" + getUserText().length()
+ " threshold=" + mThreshold);
- return getText().length() >= mThreshold;
+ return getUserText().length() >= mThreshold;
}
/**
@@ -351,18 +353,7 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
* to methods on the auto complete text view class so that we can access
* private vars without going through thunks.
*/
- private class MyWatcher implements TextWatcher, TextChangeWatcher {
- @Override
- public void afterTextChanged(Editable s) {
- doAfterTextChanged();
- }
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- doBeforeTextChanged();
- }
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
+ private class MyWatcher implements TextChangeWatcher {
@Override
public void onTextChanged(String newText) {
doAfterTextChanged();
@@ -376,34 +367,16 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
mBlockCompletion = block;
}
- void doBeforeTextChanged() {
- if (mBlockCompletion) return;
-
- // when text is changed, inserted or deleted, we attempt to show
- // the drop down
- mOpenBefore = isPopupShowing();
- if (DEBUG) Log.v(TAG, "before text changed: open=" + mOpenBefore);
- }
-
void doAfterTextChanged() {
if (DEBUG) Log.d(TAG, "doAfterTextChanged(" + getText() + ")");
if (mBlockCompletion) return;
- // if the list was open before the keystroke, but closed afterwards,
- // then something in the keystroke processing (an input filter perhaps)
- // called performCompletion() and we shouldn't do any more processing.
- if (DEBUG) Log.v(TAG, "after text changed: openBefore=" + mOpenBefore
- + " open=" + isPopupShowing());
- if (mOpenBefore && !isPopupShowing()) {
- return;
- }
-
// the drop down is shown only when a minimum number of characters
// was typed in the text view
if (enoughToFilter()) {
if (mFilter != null) {
mPopupCanBeUpdated = true;
- performFiltering(mController.getUserText(), mLastKeyCode);
+ performFiltering(getUserText(), mLastKeyCode);
buildImeCompletions();
}
} else {
@@ -413,7 +386,7 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
dismissDropDown();
}
if (mFilter != null) {
- mFilter.filter(null);
+ performFiltering(null, mLastKeyCode);
}
}
}
@@ -423,7 +396,7 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
*
* @return true if the popup menu is showing, false otherwise
*/
- protected boolean isPopupShowing() {
+ public boolean isPopupShowing() {
return mPopup.isShowing();
}
@@ -464,6 +437,20 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
mFilter.filter(text, this);
}
+ protected void performForcedFiltering() {
+ boolean wasSuspended = false;
+ if (mController.isCursorHandlingSuspended()) {
+ mController.resumeCursorMovementHandlingAndApplyChanges();
+ wasSuspended = true;
+ }
+
+ mFilter.filter(getUserText().toString(), this);
+
+ if (wasSuspended) {
+ mController.suspendCursorMovementHandling();
+ }
+ }
+
/**
* <p>Performs the text completion by converting the selected item from
* the drop down list into a string, replacing the text box's content with
@@ -553,7 +540,7 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
final boolean dropDownAlwaysVisible = mPopup.isDropDownAlwaysVisible();
if ((count > 0 || dropDownAlwaysVisible) && enoughToFilter() &&
- mController.getUserText().length() > 0) {
+ getUserText().length() > 0) {
if (hasFocus() && hasWindowFocus() && mPopupCanBeUpdated) {
showDropDown();
}
@@ -760,20 +747,28 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
}
}
+ public String getUserText() {
+ return mController.getUserText();
+ }
+
private void updateText(SuggestionsAdapter adapter) {
- // FIXME: Turn this on only when instant is being used.
- // if (!BrowserSettings.getInstance().useInstant()) {
- // return;
- // }
+ if (!BrowserSettings.getInstance().useInstant()) {
+ return;
+ }
if (!isPopupShowing()) {
setSuggestedText(null);
return;
}
- if (mAdapter.getCount() > 0 && !TextUtils.isEmpty(mController.getUserText())) {
- SuggestItem item = adapter.getItem(0);
- setSuggestedText(item.title);
+ if (mAdapter.getCount() > 0 && !TextUtils.isEmpty(getUserText())) {
+ for (int i = 0; i < mAdapter.getCount(); ++i) {
+ SuggestItem current = mAdapter.getItem(i);
+ if (current.type == SuggestionsAdapter.TYPE_SUGGEST) {
+ setSuggestedText(current.title);
+ break;
+ }
+ }
}
}
@@ -823,6 +818,17 @@ public class SuggestiveAutoCompleteTextView extends EditText implements Filter.F
}
public void setSuggestedText(String text) {
- mController.setSuggestedText(text);
+ if (!TextUtils.isEmpty(text)) {
+ String htmlStripped = Html.fromHtml(text).toString();
+ mController.setSuggestedText(htmlStripped);
+ } else {
+ mController.setSuggestedText(null);
+ }
+ }
+
+ public void getPopupDrawableRect(Rect rect) {
+ if (mPopup.getListView() != null) {
+ mPopup.getListView().getDrawingRect(rect);
+ }
}
}
diff --git a/src/com/android/browser/preferences/LabPreferencesFragment.java b/src/com/android/browser/preferences/LabPreferencesFragment.java
index 8a8546f..a06dc3e 100644
--- a/src/com/android/browser/preferences/LabPreferencesFragment.java
+++ b/src/com/android/browser/preferences/LabPreferencesFragment.java
@@ -18,33 +18,47 @@ package com.android.browser.preferences;
import com.android.browser.BrowserActivity;
import com.android.browser.BrowserSettings;
-import com.android.browser.Controller;
import com.android.browser.R;
+import com.android.browser.search.SearchEngine;
-import android.content.Context;
import android.content.Intent;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.PreferenceActivity.Header;
import android.preference.PreferenceFragment;
-import android.preference.PreferenceManager.OnActivityResultListener;
-
-import java.io.IOException;
-import java.io.Serializable;
public class LabPreferencesFragment extends PreferenceFragment
implements OnPreferenceChangeListener {
+ private BrowserSettings mBrowserSettings;
+ private Preference useInstantPref;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mBrowserSettings = BrowserSettings.getInstance();
+
// Load the XML preferences file
addPreferencesFromResource(R.xml.lab_preferences);
Preference e = findPreference(BrowserSettings.PREF_QUICK_CONTROLS);
e.setOnPreferenceChangeListener(this);
+ useInstantPref = findPreference(BrowserSettings.PREF_USE_INSTANT);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ useInstantPref.setEnabled(false);
+
+ // Enable the "use instant" preference only if the selected
+ // search engine is google.
+ if (mBrowserSettings.getSearchEngine() != null) {
+ final String currentName = mBrowserSettings.getSearchEngine().getName();
+ if (SearchEngine.GOOGLE.equals(currentName)) {
+ useInstantPref.setEnabled(true);
+ }
+ }
}
@Override
@@ -54,5 +68,4 @@ public class LabPreferencesFragment extends PreferenceFragment
getActivity(), BrowserActivity.class));
return true;
}
-
}
diff --git a/src/com/android/browser/search/DefaultSearchEngine.java b/src/com/android/browser/search/DefaultSearchEngine.java
index f282b0b..0a7afcf 100644
--- a/src/com/android/browser/search/DefaultSearchEngine.java
+++ b/src/com/android/browser/search/DefaultSearchEngine.java
@@ -120,4 +120,9 @@ public class DefaultSearchEngine implements SearchEngine {
return "ActivitySearchEngine{" + mSearchable + "}";
}
+ @Override
+ public boolean wantsEmptyQuery() {
+ return false;
+ }
+
}
diff --git a/src/com/android/browser/search/OpenSearchSearchEngine.java b/src/com/android/browser/search/OpenSearchSearchEngine.java
index a19e50d..50585c0 100644
--- a/src/com/android/browser/search/OpenSearchSearchEngine.java
+++ b/src/com/android/browser/search/OpenSearchSearchEngine.java
@@ -295,4 +295,9 @@ public class OpenSearchSearchEngine implements SearchEngine {
return "OpenSearchSearchEngine{" + mSearchEngineInfo + "}";
}
+ @Override
+ public boolean wantsEmptyQuery() {
+ return false;
+ }
+
}
diff --git a/src/com/android/browser/search/SearchEngine.java b/src/com/android/browser/search/SearchEngine.java
index b7e1859..3643005 100644
--- a/src/com/android/browser/search/SearchEngine.java
+++ b/src/com/android/browser/search/SearchEngine.java
@@ -61,4 +61,9 @@ public interface SearchEngine {
* Checks whether this search engine supports voice search.
*/
public boolean supportsVoiceSearch();
+
+ /**
+ * Checks whether this search engine should be sent zero char query.
+ */
+ public boolean wantsEmptyQuery();
}
diff --git a/src/com/android/browser/search/SearchEngines.java b/src/com/android/browser/search/SearchEngines.java
index a6ba3de..a159f17 100644
--- a/src/com/android/browser/search/SearchEngines.java
+++ b/src/com/android/browser/search/SearchEngines.java
@@ -15,13 +15,11 @@
*/
package com.android.browser.search;
+import com.android.browser.BrowserSettings;
+import com.android.browser.InstantSearchEngine;
import com.android.browser.R;
-import android.app.SearchManager;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.text.TextUtils;
import android.util.Log;
@@ -34,6 +32,10 @@ public class SearchEngines {
private static final String TAG = "SearchEngines";
public static SearchEngine getDefaultSearchEngine(Context context) {
+ if (BrowserSettings.getInstance().useInstant()) {
+ return new InstantSearchEngine(context, DefaultSearchEngine.create(context));
+ }
+
return DefaultSearchEngine.create(context);
}