diff options
Diffstat (limited to 'src/com/android/browser/InstantSearchEngine.java')
-rw-r--r-- | src/com/android/browser/InstantSearchEngine.java | 430 |
1 files changed, 0 insertions, 430 deletions
diff --git a/src/com/android/browser/InstantSearchEngine.java b/src/com/android/browser/InstantSearchEngine.java deleted file mode 100644 index 7176c0a..0000000 --- a/src/com/android/browser/InstantSearchEngine.java +++ /dev/null @@ -1,430 +0,0 @@ -/* - * 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.android.browser.Controller; -import com.android.browser.R; -import com.android.browser.UI.DropdownChangeListener; -import com.android.browser.provider.BrowserProvider; -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.getApplicationContext(); - 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(null); - } - - private final class BrowserSearchboxListener extends 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 WebView current = getCurrentWebview(); - if (current == null) { - return; - } - - final SearchBox searchBox = current.getSearchBox(); - if (searchBox != mSearchBox) { - if (mSearchBox != null) { - mSearchBox.removeSearchBoxListener(mListener); - mListener.clear(); - } - mSearchBox = searchBox; - if (mSearchBox != null) { - mSearchBox.addSearchBoxListener(mListener); - } - } - } - - private boolean isInstantPage() { - final WebView current = getCurrentWebview(); - if (current == null) { - return false; - } - - final String currentUrl = mController.getCurrentTab().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() { - final WebView current = getCurrentWebview(); - if (current != null) { - current.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); - - if (mSearchBox == null) { - return mWrapped.getSuggestions(context, query); - } - - mSearchBox.setDimensions(0, 0, 0, mHeight); - mSearchBox.onresize(null); - - 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(null); - - // 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 WebView current = getCurrentWebview(); - if (current == null) { - return 0; - } - - final float scale = current.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; - if (mSearchBox != null) { - mSearchBox.setDimensions(0, 0, 0, rescaledHeight); - mSearchBox.onresize(null); - } - } - } - - 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(); - } - } -} |