import java.io.File;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedList;
+import java.util.Map;
import java.util.Vector;
import android.app.AlertDialog;
import android.webkit.URLUtil;
import android.webkit.ValueCallback;
import android.webkit.WebBackForwardList;
+import android.webkit.WebBackForwardListClient;
import android.webkit.WebChromeClient;
import android.webkit.WebHistoryItem;
import android.webkit.WebIconDatabase;
// The listener that gets invoked when a download is started from the
// mMainView
private final DownloadListener mDownloadListener;
+ // Listener used to know when we move forward or back in the history list.
+ private final WebBackForwardListClient mWebBackForwardListClient;
// AsyncTask for downloading touch icons
DownloadTouchIcon mTouchIconLoader;
}
mVoiceSearchData = new VoiceSearchData(results, urls, htmls,
baseUrls);
+ mVoiceSearchData.mHeaders = intent.getParcelableArrayListExtra(
+ RecognizerResultsIntent
+ .EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS);
mVoiceSearchData.mSourceIsGoogle = intent.getBooleanExtra(
VoiceSearchData.SOURCE_IS_GOOGLE, false);
- } else {
- String extraData = intent.getStringExtra(
- SearchManager.EXTRA_DATA_KEY);
- if (extraData != null) {
- index = Integer.parseInt(extraData);
- if (index >= mVoiceSearchData.mVoiceSearchResults.size()) {
- throw new AssertionError("index must be less than "
- + " size of mVoiceSearchResults");
- }
- if (mVoiceSearchData.mSourceIsGoogle) {
- Intent logIntent = new Intent(
- LoggingEvents.ACTION_LOG_EVENT);
- logIntent.putExtra(LoggingEvents.EXTRA_EVENT,
- LoggingEvents.VoiceSearch.N_BEST_CHOOSE);
- logIntent.putExtra(
- LoggingEvents.VoiceSearch.EXTRA_N_BEST_CHOOSE_INDEX,
- index);
- mActivity.sendBroadcast(logIntent);
- }
+ mVoiceSearchData.mVoiceSearchIntent = new Intent(intent);
+ }
+ String extraData = intent.getStringExtra(
+ SearchManager.EXTRA_DATA_KEY);
+ if (extraData != null) {
+ index = Integer.parseInt(extraData);
+ if (index >= mVoiceSearchData.mVoiceSearchResults.size()) {
+ throw new AssertionError("index must be less than "
+ + "size of mVoiceSearchResults");
+ }
+ if (mVoiceSearchData.mSourceIsGoogle) {
+ Intent logIntent = new Intent(
+ LoggingEvents.ACTION_LOG_EVENT);
+ logIntent.putExtra(LoggingEvents.EXTRA_EVENT,
+ LoggingEvents.VoiceSearch.N_BEST_CHOOSE);
+ logIntent.putExtra(
+ LoggingEvents.VoiceSearch.EXTRA_N_BEST_CHOOSE_INDEX,
+ index);
+ mActivity.sendBroadcast(logIntent);
+ }
+ if (mVoiceSearchData.mVoiceSearchIntent != null) {
+ // Copy the Intent, so that each history item will have its own
+ // Intent, with different (or none) extra data.
+ Intent latest = new Intent(mVoiceSearchData.mVoiceSearchIntent);
+ latest.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
+ mVoiceSearchData.mVoiceSearchIntent = latest;
}
}
mVoiceSearchData.mLastVoiceSearchTitle
mVoiceSearchData.mLastVoiceSearchUrl = mActivity.smartUrlFilter(
mVoiceSearchData.mLastVoiceSearchTitle);
}
- mMainView.loadUrl(mVoiceSearchData.mLastVoiceSearchUrl);
+ Map<String, String> headers = null;
+ if (mVoiceSearchData.mHeaders != null) {
+ int bundleIndex = mVoiceSearchData.mHeaders.size() == 1 ? 0
+ : index;
+ Bundle bundle = mVoiceSearchData.mHeaders.get(bundleIndex);
+ if (bundle != null && !bundle.isEmpty()) {
+ Iterator<String> iter = bundle.keySet().iterator();
+ headers = new HashMap<String, String>();
+ while (iter.hasNext()) {
+ String key = iter.next();
+ headers.put(key, bundle.getString(key));
+ }
+ }
+ }
+ mMainView.loadUrl(mVoiceSearchData.mLastVoiceSearchUrl, headers);
}
/* package */ static class VoiceSearchData {
public VoiceSearchData(ArrayList<String> results,
*/
public boolean mSourceIsGoogle;
/**
+ * List of headers to be passed into the WebView containing location
+ * information
+ */
+ public ArrayList<Bundle> mHeaders;
+ /**
+ * The Intent used to invoke voice search. Placed on the
+ * WebHistoryItem so that when coming back to a previous voice search
+ * page we can again activate voice search.
+ */
+ public Intent mVoiceSearchIntent;
+ /**
* String used to identify Google as the source of voice search.
*/
public static String SOURCE_IS_GOOGLE
}
@Override
- public void onReceivedTitle(WebView view, String title) {
- String url = view.getUrl();
+ public void onReceivedTitle(WebView view, final String title) {
+ final String pageUrl = view.getUrl();
if (mInForeground) {
// here, if url is null, we want to reset the title
- mActivity.setUrlTitle(url, title);
+ mActivity.setUrlTitle(pageUrl, title);
}
- if (url == null ||
- url.length() >= SQLiteDatabase.SQLITE_MAX_LIKE_PATTERN_LENGTH) {
+ if (pageUrl == null || pageUrl.length()
+ >= SQLiteDatabase.SQLITE_MAX_LIKE_PATTERN_LENGTH) {
return;
}
- // See if we can find the current url in our history database and
- // add the new title to it.
- if (url.startsWith("http://www.")) {
- url = url.substring(11);
- } else if (url.startsWith("http://")) {
- url = url.substring(4);
- }
- try {
- final ContentResolver cr = mActivity.getContentResolver();
- url = "%" + url;
- String [] selArgs = new String[] { url };
- String where = Browser.BookmarkColumns.URL + " LIKE ? AND "
- + Browser.BookmarkColumns.BOOKMARK + " = 0";
- Cursor c = cr.query(Browser.BOOKMARKS_URI,
- Browser.HISTORY_PROJECTION, where, selArgs, null);
- if (c.moveToFirst()) {
- // Current implementation of database only has one entry per
- // url.
- ContentValues map = new ContentValues();
- map.put(Browser.BookmarkColumns.TITLE, title);
- cr.update(Browser.BOOKMARKS_URI, map, "_id = "
- + c.getInt(0), null);
+ new AsyncTask<Void, Void, Void>() {
+ protected Void doInBackground(Void... unused) {
+ // See if we can find the current url in our history
+ // database and add the new title to it.
+ String url = pageUrl;
+ if (url.startsWith("http://www.")) {
+ url = url.substring(11);
+ } else if (url.startsWith("http://")) {
+ url = url.substring(4);
+ }
+ Cursor c = null;
+ try {
+ final ContentResolver cr
+ = mActivity.getContentResolver();
+ url = "%" + url;
+ String [] selArgs = new String[] { url };
+ String where = Browser.BookmarkColumns.URL
+ + " LIKE ? AND "
+ + Browser.BookmarkColumns.BOOKMARK + " = 0";
+ c = cr.query(Browser.BOOKMARKS_URI, new String[]
+ { Browser.BookmarkColumns._ID }, where, selArgs,
+ null);
+ if (c.moveToFirst()) {
+ // Current implementation of database only has one
+ // entry per url.
+ ContentValues map = new ContentValues();
+ map.put(Browser.BookmarkColumns.TITLE, title);
+ String[] projection = new String[]
+ { Integer.valueOf(c.getInt(0)).toString() };
+ cr.update(Browser.BOOKMARKS_URI, map, "_id = ?",
+ projection);
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "Tab onReceived title", e);
+ } catch (SQLiteException ex) {
+ Log.e(LOGTAG,
+ "onReceivedTitle() caught SQLiteException: ",
+ ex);
+ } finally {
+ if (c != null) c.close();
+ }
+ return null;
}
- c.close();
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "Tab onReceived title", e);
- } catch (SQLiteException ex) {
- Log.e(LOGTAG, "onReceivedTitle() caught SQLiteException: ", ex);
- }
+ }.execute();
}
@Override
mTouchIconLoader = new DownloadTouchIcon(Tab.this, cr,
c, view);
mTouchIconLoader.execute(url);
+ } else {
+ c.close();
}
} else {
c.close();
}
}
};
+ mWebBackForwardListClient = new WebBackForwardListClient() {
+ @Override
+ public void onNewHistoryItem(WebHistoryItem item) {
+ if (isInVoiceSearchMode()) {
+ item.setCustomData(mVoiceSearchData.mVoiceSearchIntent);
+ }
+ }
+ @Override
+ public void onIndexChanged(WebHistoryItem item, int index) {
+ Object data = item.getCustomData();
+ if (data != null && data instanceof Intent) {
+ activateVoiceSearchMode((Intent) data);
+ }
+ }
+ };
setWebView(w);
}
// does a redirect after a period of time. The user could have
// switched to another tab while waiting for the download to start.
mMainView.setDownloadListener(mDownloadListener);
+ mMainView.setWebBackForwardListClient(mWebBackForwardListClient);
}
}
mMainView.hashCode() + "_pic.save");
if (mMainView.savePicture(mSavedState, f)) {
mSavedState.putString(CURRPICTURE, f.getPath());
+ } else {
+ // if savePicture returned false, we can't trust the contents,
+ // and it may be large, so we delete it right away
+ f.delete();
}
}