Tab.java revision e09305e4ad0430571efb8ae880762204ddeaeb33
122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba/*
222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * Copyright (C) 2009 The Android Open Source Project
322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba *
422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * Licensed under the Apache License, Version 2.0 (the "License");
522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * you may not use this file except in compliance with the License.
622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * You may obtain a copy of the License at
722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba *
822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba *      http://www.apache.org/licenses/LICENSE-2.0
922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba *
1022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * Unless required by applicable law or agreed to in writing, software
1122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * distributed under the License is distributed on an "AS IS" BASIS,
1222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * See the License for the specific language governing permissions and
1422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * limitations under the License.
1522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba */
1622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
1722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobapackage com.android.browser;
1822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
198233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.Activity;
2022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.app.AlertDialog;
2158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scrogginsimport android.app.SearchManager;
2222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.content.ContentResolver;
231cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reckimport android.content.ContentUris;
24d8c7452a7d8975a2d60414c5a33842b4a743e631John Reckimport android.content.ContentValues;
2530c714c853a4239e72ab1e238ce2a92472d06ab0John Reckimport android.content.Context;
2622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.content.DialogInterface;
27fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolbimport android.content.DialogInterface.OnCancelListener;
288ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamiltonimport android.content.Intent;
291cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reckimport android.database.Cursor;
3022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.graphics.Bitmap;
318cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reckimport android.graphics.Bitmap.CompressFormat;
329ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolbimport android.graphics.BitmapFactory;
339ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolbimport android.graphics.Canvas;
34c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolbimport android.graphics.Color;
359ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolbimport android.graphics.Picture;
3622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.net.Uri;
3722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.net.http.SslError;
3822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.os.Bundle;
399ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolbimport android.os.Handler;
4022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.os.Message;
414dce3bf588b7eaf4de555a93b67f5ddf9bc1ba77Kristian Monsenimport android.os.SystemClock;
428862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstromimport android.security.KeyChain;
43aa09cd8dc20c9134b69ace4a7b84fe0103220fb4Brian Carlstromimport android.security.KeyChainAliasCallback;
44a1cc3fdce19a336c251297c61cd83ac6cf767cd1Leon Scrogginsimport android.speech.RecognizerResultsIntent;
4524f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reckimport android.text.TextUtils;
4622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.util.Log;
4722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.view.KeyEvent;
4822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.view.LayoutInflater;
4922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.view.View;
5050c241e6339c681c2427a57a31a357d35927c2acGrace Klobaimport android.view.ViewStub;
518862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstromimport android.webkit.ClientCertRequestHandler;
52c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdochimport android.webkit.ConsoleMessage;
53dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scrogginsimport android.webkit.DownloadListener;
5422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.webkit.GeolocationPermissions;
5522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.webkit.HttpAuthHandler;
5622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.webkit.SslErrorHandler;
5722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.webkit.URLUtil;
5822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.webkit.ValueCallback;
596c2e2f34718043f36488b4a94879dc2605aaac49John Reckimport android.webkit.WebBackForwardList;
600c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scrogginsimport android.webkit.WebBackForwardListClient;
6122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.webkit.WebChromeClient;
6222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.webkit.WebHistoryItem;
63438bf46c98890b5fe1356e75b4bc759033c6fc57John Reckimport android.webkit.WebResourceResponse;
6422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.webkit.WebStorage;
6522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.webkit.WebView;
669ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolbimport android.webkit.WebView.PictureListener;
6722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.webkit.WebViewClient;
681d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdochimport android.widget.CheckBox;
6922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.widget.LinearLayout;
7022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Klobaimport android.widget.TextView;
718029a777106fa6fb911ee1d58402b0de768a583aBen Murdochimport android.widget.Toast;
7222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
738ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reckimport com.android.browser.TabControl.OnThumbnailUpdatedListener;
74541f55a0178da7c09fb32aa5385effae031ea071John Reckimport com.android.browser.homepages.HomeProvider;
751cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reckimport com.android.browser.provider.BrowserProvider2.Thumbnails;
768cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reckimport com.android.browser.provider.SnapshotProvider.Snapshots;
77541f55a0178da7c09fb32aa5385effae031ea071John Reckimport com.android.common.speech.LoggingEvents;
78541f55a0178da7c09fb32aa5385effae031ea071John Reck
79541f55a0178da7c09fb32aa5385effae031ea071John Reckimport java.io.ByteArrayOutputStream;
801cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reckimport java.nio.ByteBuffer;
81fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolbimport java.util.ArrayList;
82fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolbimport java.util.HashMap;
83fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolbimport java.util.Iterator;
84fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolbimport java.util.LinkedList;
85fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolbimport java.util.Map;
86fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolbimport java.util.Vector;
878cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reckimport java.util.zip.GZIPOutputStream;
88fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolb
8922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba/**
9022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * Class for maintaining Tabs with a main WebView and a subwindow.
9122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba */
929ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolbclass Tab implements PictureListener {
938233facddcc51865d612a919d450db6954aa48e3Michael Kolb
9422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Log Tag
9522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private static final String LOGTAG = "Tab";
961dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood    private static final boolean LOGD_ENABLED = com.android.browser.Browser.LOGD_ENABLED;
97c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch    // Special case the logtag for messages for the Console to make it easier to
98c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch    // filter them and match the logtag used for these messages in older versions
99c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch    // of the browser.
100c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch    private static final String CONSOLE_LOGTAG = "browser";
101c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch
1029ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb    private static final int MSG_CAPTURE = 42;
1038ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck    private static final int CAPTURE_DELAY = 100;
1049ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb
1051cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private static Bitmap sDefaultFavicon;
1061cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
10730c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    public enum LockIcon {
10830c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        LOCK_ICON_UNSECURE,
10930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        LOCK_ICON_SECURE,
11030c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        LOCK_ICON_MIXED,
11130c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    }
1128233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1131461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb    Context mContext;
114d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck    protected WebViewController mWebViewController;
1158233facddcc51865d612a919d450db6954aa48e3Michael Kolb
116c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    // The tab ID
117d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck    private long mId = -1;
118c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb
11922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // The Geolocation permissions prompt
12022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private GeolocationPermissionsPrompt mGeolocationPermissionsPrompt;
12122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Main WebView wrapper
122a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb    private View mContainer;
12322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Main WebView
12422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private WebView mMainView;
12522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Subwindow container
12622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private View mSubViewContainer;
12722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Subwindow WebView
12822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private WebView mSubView;
12922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Saved bundle for when we are running low on memory. It contains the
13022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // information needed to restore the WebView if the user goes back to the
13122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // tab.
13222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private Bundle mSavedState;
13322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Parent Tab. This is the Tab that created this Tab, or null if the Tab was
13422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // created by the UI
135c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    private Tab mParent;
13622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Tab that constructed by this Tab. This is used when this Tab is
13722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // destroyed, it clears all mParentTab values in the children.
138c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    private Vector<Tab> mChildren;
13922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // If true, the tab is in the foreground of the current activity.
14022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private boolean mInForeground;
1418233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // If true, the tab is in page loading state (after onPageStarted,
1428233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // before onPageFinsihed)
1438233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private boolean mInPageLoad;
14430c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    // The last reported progress of the current page
14530c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    private int mPageLoadProgress;
1464dce3bf588b7eaf4de555a93b67f5ddf9bc1ba77Kristian Monsen    // The time the load started, used to find load page time
1474dce3bf588b7eaf4de555a93b67f5ddf9bc1ba77Kristian Monsen    private long mLoadStartTime;
14822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Application identifier used to find tabs that another application wants
14922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // to reuse.
15022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private String mAppId;
151e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb    // flag to indicate if tab should be closed on back
152e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb    private boolean mCloseOnBack;
15322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Keep the original url around to avoid killing the old WebView if the url
15422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // has not changed.
15522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Error console for the tab
15622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private ErrorConsoleView mErrorConsole;
157dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins    // The listener that gets invoked when a download is started from the
158dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins    // mMainView
159dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins    private final DownloadListener mDownloadListener;
1600c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins    // Listener used to know when we move forward or back in the history list.
1610c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins    private final WebBackForwardListClient mWebBackForwardListClient;
162e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck    private DataController mDataController;
1639206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    // State of the auto-login request.
1649206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    private DeviceAccountLogin mDeviceAccountLogin;
16522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
16622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // AsyncTask for downloading touch icons
16722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    DownloadTouchIcon mTouchIconLoader;
16822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
16935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    private BrowserSettings mSettings;
1709ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb    private int mCaptureWidth;
1719ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb    private int mCaptureHeight;
1729ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb    private Bitmap mCapture;
1739ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb    private Handler mHandler;
1749ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb
1751dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood    /**
1761dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood     * See {@link #clearBackStackWhenItemAdded(String)}.
1771dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood     */
1781dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood    private String mClearHistoryMatchUrl;
1791dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood
1801cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private static synchronized Bitmap getDefaultFavicon(Context context) {
1811cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        if (sDefaultFavicon == null) {
1821cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            sDefaultFavicon = BitmapFactory.decodeResource(
1831cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    context.getResources(), R.drawable.app_web_browser_sm);
1841cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
1851cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        return sDefaultFavicon;
1861cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
187eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb
18830c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    // All the state needed for a page
189d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck    protected static class PageState {
19030c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        String mUrl;
191db22ec4ee014900988062d910bc810172a07df56John Reck        String mOriginalUrl;
19230c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        String mTitle;
19330c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        LockIcon mLockIcon;
19430c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        Bitmap mFavicon;
195502a353bb815bee8bec6a60f3b741dc62e4729cdJohn Reck        boolean mIsBookmarkedSite = false;
196502a353bb815bee8bec6a60f3b741dc62e4729cdJohn Reck        boolean mIncognito = false;
19730c714c853a4239e72ab1e238ce2a92472d06ab0John Reck
19830c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        PageState(Context c, boolean incognito) {
199502a353bb815bee8bec6a60f3b741dc62e4729cdJohn Reck            mIncognito = incognito;
200502a353bb815bee8bec6a60f3b741dc62e4729cdJohn Reck            if (mIncognito) {
201db22ec4ee014900988062d910bc810172a07df56John Reck                mOriginalUrl = mUrl = "browser:incognito";
20230c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                mTitle = c.getString(R.string.new_incognito_tab);
20330c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            } else {
204db22ec4ee014900988062d910bc810172a07df56John Reck                mOriginalUrl = mUrl = "";
20530c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                mTitle = c.getString(R.string.new_tab);
20630c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            }
2071cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            mFavicon = null;
20830c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            mLockIcon = LockIcon.LOCK_ICON_UNSECURE;
20930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        }
21030c714c853a4239e72ab1e238ce2a92472d06ab0John Reck
21130c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        PageState(Context c, boolean incognito, String url, Bitmap favicon) {
212502a353bb815bee8bec6a60f3b741dc62e4729cdJohn Reck            mIncognito = incognito;
213db22ec4ee014900988062d910bc810172a07df56John Reck            mOriginalUrl = mUrl = url;
21430c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            mTitle = null;
21530c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            if (URLUtil.isHttpsUrl(url)) {
21630c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                mLockIcon = LockIcon.LOCK_ICON_SECURE;
21730c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            } else {
21830c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                mLockIcon = LockIcon.LOCK_ICON_UNSECURE;
21930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            }
2201cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            mFavicon = favicon;
22130c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        }
2221cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
22322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
22422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
22530c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    // The current/loading page's state
226d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck    protected PageState mCurrentState;
22730c714c853a4239e72ab1e238ce2a92472d06ab0John Reck
22822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Used for saving and restoring each Tab
229c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    static final String ID = "ID";
23022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    static final String CURRURL = "currentUrl";
23122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    static final String CURRTITLE = "currentTitle";
23222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    static final String PARENTTAB = "parentTab";
23322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    static final String APPID = "appid";
2343d6df16f1c9a64cf2dc5b41a2078f4c49b0c296aElliott Slaughter    static final String INCOGNITO = "privateBrowsingEnabled";
235b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck    static final String USERAGENT = "useragent";
236e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb    static final String CLOSEFLAG = "closeOnBack";
23722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
23822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // -------------------------------------------------------------------------
23922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
24058d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    /**
24158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     * Private information regarding the latest voice search.  If the Tab is not
24258d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     * in voice search mode, this will be null.
24358d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     */
24458d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    private VoiceSearchData mVoiceSearchData;
24558d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    /**
24695d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III     * Remove voice search mode from this tab.
24795d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III     */
24895d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III    public void revertVoiceSearchMode() {
24995d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III        if (mVoiceSearchData != null) {
25095d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III            mVoiceSearchData = null;
25195d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III            if (mInForeground) {
2528233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mWebViewController.revertVoiceSearchMode(this);
25395d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III            }
25495d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III        }
25595d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III    }
2568233facddcc51865d612a919d450db6954aa48e3Michael Kolb
25795d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III    /**
25858d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     * Return whether the tab is in voice search mode.
25958d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     */
26058d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    public boolean isInVoiceSearchMode() {
26158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        return mVoiceSearchData != null;
26258d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    }
26358d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    /**
264c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III     * Return true if the Tab is in voice search mode and the voice search
265c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III     * Intent came with a String identifying that Google provided the Intent.
2661fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins     */
2671fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins    public boolean voiceSearchSourceIsGoogle() {
2681fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins        return mVoiceSearchData != null && mVoiceSearchData.mSourceIsGoogle;
2691fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins    }
2701fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins    /**
27158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     * Get the title to display for the current voice search page.  If the Tab
27258d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     * is not in voice search mode, return null.
27358d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     */
27458d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    public String getVoiceDisplayTitle() {
27558d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        if (mVoiceSearchData == null) return null;
27658d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        return mVoiceSearchData.mLastVoiceSearchTitle;
27758d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    }
27858d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    /**
27958d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     * Get the latest array of voice search results, to be passed to the
28058d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     * BrowserProvider.  If the Tab is not in voice search mode, return null.
28158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     */
28258d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    public ArrayList<String> getVoiceSearchResults() {
28358d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        if (mVoiceSearchData == null) return null;
28458d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        return mVoiceSearchData.mVoiceSearchResults;
28558d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    }
28658d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    /**
28758d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     * Activate voice search mode.
28858d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     * @param intent Intent which has the results to use, or an index into the
28958d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     *      results when reusing the old results.
29058d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins     */
29158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    /* package */ void activateVoiceSearchMode(Intent intent) {
29282c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins        int index = 0;
29358d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        ArrayList<String> results = intent.getStringArrayListExtra(
294a1cc3fdce19a336c251297c61cd83ac6cf767cd1Leon Scroggins                    RecognizerResultsIntent.EXTRA_VOICE_SEARCH_RESULT_STRINGS);
29558d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        if (results != null) {
29682c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            ArrayList<String> urls = intent.getStringArrayListExtra(
29782c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                        RecognizerResultsIntent.EXTRA_VOICE_SEARCH_RESULT_URLS);
29882c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            ArrayList<String> htmls = intent.getStringArrayListExtra(
29982c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                        RecognizerResultsIntent.EXTRA_VOICE_SEARCH_RESULT_HTML);
30082c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            ArrayList<String> baseUrls = intent.getStringArrayListExtra(
30182c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                        RecognizerResultsIntent
30282c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                        .EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS);
30358d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins            // This tab is now entering voice search mode for the first time, or
30458d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins            // a new voice search was done.
30582c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            int size = results.size();
30682c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            if (urls == null || size != urls.size()) {
30758d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins                throw new AssertionError("improper extras passed in Intent");
30858d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins            }
30982c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            if (htmls == null || htmls.size() != size || baseUrls == null ||
31082c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                    (baseUrls.size() != size && baseUrls.size() != 1)) {
31182c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                // If either of these arrays are empty/incorrectly sized, ignore
31282c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                // them.
31382c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                htmls = null;
31482c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                baseUrls = null;
31582c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            }
31682c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            mVoiceSearchData = new VoiceSearchData(results, urls, htmls,
31782c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                    baseUrls);
3189df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins            mVoiceSearchData.mHeaders = intent.getParcelableArrayListExtra(
3199df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins                    RecognizerResultsIntent
3209df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins                    .EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS);
3211fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins            mVoiceSearchData.mSourceIsGoogle = intent.getBooleanExtra(
3221fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins                    VoiceSearchData.SOURCE_IS_GOOGLE, false);
3232ee4a5acc5c1ef87afa02830b31770cb1359b626Leon Scroggins            mVoiceSearchData.mVoiceSearchIntent = new Intent(intent);
324e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins        }
325e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins        String extraData = intent.getStringExtra(
326e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins                SearchManager.EXTRA_DATA_KEY);
327e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins        if (extraData != null) {
328e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins            index = Integer.parseInt(extraData);
329e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins            if (index >= mVoiceSearchData.mVoiceSearchResults.size()) {
330e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins                throw new AssertionError("index must be less than "
331e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins                        + "size of mVoiceSearchResults");
332e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins            }
333e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins            if (mVoiceSearchData.mSourceIsGoogle) {
334e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins                Intent logIntent = new Intent(
335e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins                        LoggingEvents.ACTION_LOG_EVENT);
336e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins                logIntent.putExtra(LoggingEvents.EXTRA_EVENT,
337e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins                        LoggingEvents.VoiceSearch.N_BEST_CHOOSE);
338e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins                logIntent.putExtra(
339e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins                        LoggingEvents.VoiceSearch.EXTRA_N_BEST_CHOOSE_INDEX,
340e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins                        index);
3411461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                mContext.sendBroadcast(logIntent);
342e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins            }
343e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins            if (mVoiceSearchData.mVoiceSearchIntent != null) {
3442ee4a5acc5c1ef87afa02830b31770cb1359b626Leon Scroggins                // Copy the Intent, so that each history item will have its own
3452ee4a5acc5c1ef87afa02830b31770cb1359b626Leon Scroggins                // Intent, with different (or none) extra data.
3462ee4a5acc5c1ef87afa02830b31770cb1359b626Leon Scroggins                Intent latest = new Intent(mVoiceSearchData.mVoiceSearchIntent);
3472ee4a5acc5c1ef87afa02830b31770cb1359b626Leon Scroggins                latest.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
3482ee4a5acc5c1ef87afa02830b31770cb1359b626Leon Scroggins                mVoiceSearchData.mVoiceSearchIntent = latest;
34958d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins            }
35058d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        }
35158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        mVoiceSearchData.mLastVoiceSearchTitle
35282c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                = mVoiceSearchData.mVoiceSearchResults.get(index);
35358d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        if (mInForeground) {
35411d1978d8d16004598347abc93918b54a5ef760bMichael Kolb            mWebViewController.activateVoiceSearchMode(
35511d1978d8d16004598347abc93918b54a5ef760bMichael Kolb                    mVoiceSearchData.mLastVoiceSearchTitle,
35611d1978d8d16004598347abc93918b54a5ef760bMichael Kolb                    mVoiceSearchData.mVoiceSearchResults);
35758d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        }
35882c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins        if (mVoiceSearchData.mVoiceSearchHtmls != null) {
35982c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            // When index was found it was already ensured that it was valid
36082c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            String uriString = mVoiceSearchData.mVoiceSearchHtmls.get(index);
36182c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            if (uriString != null) {
36282c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                Uri dataUri = Uri.parse(uriString);
36382c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                if (RecognizerResultsIntent.URI_SCHEME_INLINE.equals(
36482c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                        dataUri.getScheme())) {
36582c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                    // If there is only one base URL, use it.  If there are
36682c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                    // more, there will be one for each index, so use the base
36782c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                    // URL corresponding to the index.
36882c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                    String baseUrl = mVoiceSearchData.mVoiceSearchBaseUrls.get(
36982c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                            mVoiceSearchData.mVoiceSearchBaseUrls.size() > 1 ?
37082c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                            index : 0);
37182c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                    mVoiceSearchData.mLastVoiceSearchUrl = baseUrl;
37282c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                    mMainView.loadDataWithBaseURL(baseUrl,
37382c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                            uriString.substring(RecognizerResultsIntent
37482c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                            .URI_SCHEME_INLINE.length() + 1), "text/html",
37582c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                            "utf-8", baseUrl);
37682c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                    return;
37782c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                }
37882c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            }
37982c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins        }
38058d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        mVoiceSearchData.mLastVoiceSearchUrl
38182c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                = mVoiceSearchData.mVoiceSearchUrls.get(index);
38282c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins        if (null == mVoiceSearchData.mLastVoiceSearchUrl) {
3838233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mVoiceSearchData.mLastVoiceSearchUrl = UrlUtils.smartUrlFilter(
38482c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                    mVoiceSearchData.mLastVoiceSearchTitle);
38582c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins        }
3869df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins        Map<String, String> headers = null;
3879df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins        if (mVoiceSearchData.mHeaders != null) {
3889df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins            int bundleIndex = mVoiceSearchData.mHeaders.size() == 1 ? 0
3899df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins                    : index;
3909df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins            Bundle bundle = mVoiceSearchData.mHeaders.get(bundleIndex);
3919df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins            if (bundle != null && !bundle.isEmpty()) {
3929df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins                Iterator<String> iter = bundle.keySet().iterator();
3939df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins                headers = new HashMap<String, String>();
3949df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins                while (iter.hasNext()) {
3959df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins                    String key = iter.next();
3969df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins                    headers.put(key, bundle.getString(key));
3979df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins                }
3989df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins            }
3999df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins        }
4009df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins        mMainView.loadUrl(mVoiceSearchData.mLastVoiceSearchUrl, headers);
40158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    }
40258d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    /* package */ static class VoiceSearchData {
40358d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        public VoiceSearchData(ArrayList<String> results,
40482c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                ArrayList<String> urls, ArrayList<String> htmls,
40582c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins                ArrayList<String> baseUrls) {
40658d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins            mVoiceSearchResults = results;
40758d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins            mVoiceSearchUrls = urls;
40882c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            mVoiceSearchHtmls = htmls;
40982c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins            mVoiceSearchBaseUrls = baseUrls;
41058d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        }
41158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        /*
41258d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         * ArrayList of suggestions to be displayed when opening the
41358d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         * SearchManager
41458d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         */
41558d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        public ArrayList<String> mVoiceSearchResults;
41658d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        /*
41758d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         * ArrayList of urls, associated with the suggestions in
41858d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         * mVoiceSearchResults.
41958d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         */
42058d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        public ArrayList<String> mVoiceSearchUrls;
42158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        /*
42282c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins         * ArrayList holding content to load for each item in
42382c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins         * mVoiceSearchResults.
42482c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins         */
42582c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins        public ArrayList<String> mVoiceSearchHtmls;
42682c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins        /*
42782c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins         * ArrayList holding base urls for the items in mVoiceSearchResults.
42882c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins         * If non null, this will either have the same size as
42982c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins         * mVoiceSearchResults or have a size of 1, in which case all will use
43082c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins         * the same base url
43182c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins         */
43282c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins        public ArrayList<String> mVoiceSearchBaseUrls;
43382c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins        /*
43458d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         * The last url provided by voice search.  Used for comparison to see if
43582c1baa16a66eabdd7fd1eb6569e61cb6caac4fdLeon Scroggins         * we are going to a page by some method besides voice search.
43658d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         */
43758d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        public String mLastVoiceSearchUrl;
43858d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        /**
43958d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         * The last title used for voice search.  Needed to update the title bar
44058d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         * when switching tabs.
44158d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins         */
44258d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins        public String mLastVoiceSearchTitle;
4431fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins        /**
4441fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins         * Whether the Intent which turned on voice search mode contained the
4451fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins         * String signifying that Google was the source.
4461fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins         */
4471fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins        public boolean mSourceIsGoogle;
4481fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins        /**
4499df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins         * List of headers to be passed into the WebView containing location
4509df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins         * information
4519df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins         */
4529df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins        public ArrayList<Bundle> mHeaders;
4539df949776c726b05ead037a8ba2d2d2c14cb5dcaLeon Scroggins        /**
4540c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins         * The Intent used to invoke voice search.  Placed on the
4550c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins         * WebHistoryItem so that when coming back to a previous voice search
4560c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins         * page we can again activate voice search.
4570c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins         */
458e10dde5aab881bd791094edd80c6e438d4601787Leon Scroggins        public Intent mVoiceSearchIntent;
4590c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins        /**
4601fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins         * String used to identify Google as the source of voice search.
4611fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins         */
4621fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins        public static String SOURCE_IS_GOOGLE
4631fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins                = "android.speech.extras.SOURCE_IS_GOOGLE";
46458d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins    }
46558d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins
46622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Container class for the next error dialog that needs to be displayed
46722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private class ErrorDialog {
46822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public final int mTitle;
46922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public final String mDescription;
47022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public final int mError;
47122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        ErrorDialog(int title, String desc, int error) {
47222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mTitle = title;
47322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mDescription = desc;
47422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mError = error;
47522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
4768233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
47722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
47822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private void processNextError() {
47922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mQueuedErrors == null) {
48022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return;
48122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
48222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // The first one is currently displayed so just remove it.
48322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mQueuedErrors.removeFirst();
48422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mQueuedErrors.size() == 0) {
48522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mQueuedErrors = null;
48622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return;
48722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
48822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        showError(mQueuedErrors.getFirst());
48922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
49022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
49122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private DialogInterface.OnDismissListener mDialogListener =
49222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            new DialogInterface.OnDismissListener() {
49322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                public void onDismiss(DialogInterface d) {
49422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    processNextError();
49522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                }
49622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            };
49722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private LinkedList<ErrorDialog> mQueuedErrors;
49822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
49922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private void queueError(int err, String desc) {
50022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mQueuedErrors == null) {
50122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mQueuedErrors = new LinkedList<ErrorDialog>();
50222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
50322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        for (ErrorDialog d : mQueuedErrors) {
50422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (d.mError == err) {
50522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                // Already saw a similar error, ignore the new one.
50622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                return;
50722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
50822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
50922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        ErrorDialog errDialog = new ErrorDialog(
51022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                err == WebViewClient.ERROR_FILE_NOT_FOUND ?
51122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                R.string.browserFrameFileErrorLabel :
51222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                R.string.browserFrameNetworkErrorLabel,
51322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                desc, err);
51422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mQueuedErrors.addLast(errDialog);
51522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
51622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // Show the dialog now if the queue was empty and it is in foreground
51722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mQueuedErrors.size() == 1 && mInForeground) {
51822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            showError(errDialog);
51922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
52022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
52122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
52222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private void showError(ErrorDialog errDialog) {
52322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mInForeground) {
5241461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            AlertDialog d = new AlertDialog.Builder(mContext)
52522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .setTitle(errDialog.mTitle)
52622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .setMessage(errDialog.mDescription)
52722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .setPositiveButton(R.string.ok, null)
52822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .create();
52922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            d.setOnDismissListener(mDialogListener);
53022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            d.show();
53122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
53222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
53322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
53422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // -------------------------------------------------------------------------
53522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // WebViewClient implementation for the main WebView
53622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // -------------------------------------------------------------------------
53722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
53822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private final WebViewClient mWebViewClient = new WebViewClient() {
5394a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins        private Message mDontResend;
5404a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins        private Message mResend;
54147bd1e4867a73db641a6f157e4a1f1e278b10cf3Michael Kolb
54247bd1e4867a73db641a6f157e4a1f1e278b10cf3Michael Kolb        private boolean providersDiffer(String url, String otherUrl) {
54347bd1e4867a73db641a6f157e4a1f1e278b10cf3Michael Kolb            Uri uri1 = Uri.parse(url);
54447bd1e4867a73db641a6f157e4a1f1e278b10cf3Michael Kolb            Uri uri2 = Uri.parse(otherUrl);
54547bd1e4867a73db641a6f157e4a1f1e278b10cf3Michael Kolb            return !uri1.getEncodedAuthority().equals(uri2.getEncodedAuthority());
54647bd1e4867a73db641a6f157e4a1f1e278b10cf3Michael Kolb        }
54747bd1e4867a73db641a6f157e4a1f1e278b10cf3Michael Kolb
54822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
54922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onPageStarted(WebView view, String url, Bitmap favicon) {
5508233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mInPageLoad = true;
55130c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            mPageLoadProgress = 0;
5521461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            mCurrentState = new PageState(mContext,
55330c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                    view.isPrivateBrowsingEnabled(), url, favicon);
5544dce3bf588b7eaf4de555a93b67f5ddf9bc1ba77Kristian Monsen            mLoadStartTime = SystemClock.uptimeMillis();
55558d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins            if (mVoiceSearchData != null
55647bd1e4867a73db641a6f157e4a1f1e278b10cf3Michael Kolb                    && providersDiffer(url, mVoiceSearchData.mLastVoiceSearchUrl)) {
5571fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins                if (mVoiceSearchData.mSourceIsGoogle) {
5581fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins                    Intent i = new Intent(LoggingEvents.ACTION_LOG_EVENT);
5591fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins                    i.putExtra(LoggingEvents.EXTRA_FLUSH, true);
5601461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                    mContext.sendBroadcast(i);
5611fe13a5230e319df42b21939a14d127bd9bf3856Leon Scroggins                }
56295d9bfd1d67902a8aa5d2e529db7f7064db081b7Leon Scroggins III                revertVoiceSearchMode();
56358d56c6b5052faa86083965132cd51b1a9594d0eLeon Scroggins            }
56422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
56522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
56622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // If we start a touch icon load and then load a new page, we don't
56722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // want to cancel the current touch icon loader. But, we do want to
56822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // create a new one when the touch icon url is known.
56922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (mTouchIconLoader != null) {
57022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                mTouchIconLoader.mTab = null;
57122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                mTouchIconLoader = null;
57222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
57322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
57422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // reset the error console
57522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (mErrorConsole != null) {
57622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                mErrorConsole.clearErrorMessages();
5778233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (mWebViewController.shouldShowErrorConsole()) {
57822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    mErrorConsole.showConsole(ErrorConsoleView.SHOW_NONE);
57922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                }
58022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
58122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
5829206677e461328f15854c5fcb1366d0e261534c6Patrick Scott            // Cancel the auto-login process.
5839206677e461328f15854c5fcb1366d0e261534c6Patrick Scott            if (mDeviceAccountLogin != null) {
5849206677e461328f15854c5fcb1366d0e261534c6Patrick Scott                mDeviceAccountLogin.cancel();
5859206677e461328f15854c5fcb1366d0e261534c6Patrick Scott                mDeviceAccountLogin = null;
5869206677e461328f15854c5fcb1366d0e261534c6Patrick Scott                mWebViewController.hideAutoLogin(Tab.this);
5879206677e461328f15854c5fcb1366d0e261534c6Patrick Scott            }
5889206677e461328f15854c5fcb1366d0e261534c6Patrick Scott
58922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // finally update the UI in the activity if it is in the foreground
590324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck            mWebViewController.onPageStarted(Tab.this, view, favicon);
5914cd97793901e8f5681cf642d0b2684697964a37aLeon Scroggins
592e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck            updateBookmarkedStatus();
59322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
59422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
59522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
59622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onPageFinished(WebView view, String url) {
597a169628f9424256e5bcf45807869c4c4eaa114c0John Reck            if (!mInPageLoad) {
598a169628f9424256e5bcf45807869c4c4eaa114c0John Reck                // In page navigation links (www.something.com#footer) will
599a169628f9424256e5bcf45807869c4c4eaa114c0John Reck                // trigger an onPageFinished which we don't care about.
600a169628f9424256e5bcf45807869c4c4eaa114c0John Reck                return;
601a169628f9424256e5bcf45807869c4c4eaa114c0John Reck            }
6025b69184c0f6b1d65eb444832cdff3f1e1304bdbdJohn Reck            if (!isPrivateBrowsingEnabled()) {
6035b69184c0f6b1d65eb444832cdff3f1e1304bdbdJohn Reck                LogTag.logPageFinishedLoading(
6045b69184c0f6b1d65eb444832cdff3f1e1304bdbdJohn Reck                        url, SystemClock.uptimeMillis() - mLoadStartTime);
6055b69184c0f6b1d65eb444832cdff3f1e1304bdbdJohn Reck            }
6068233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mInPageLoad = false;
6071cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            syncCurrentState(view, url);
608324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck            mWebViewController.onPageFinished(Tab.this);
60922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
61022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
61122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // return true if want to hijack the url to let another app to handle it
61222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
61322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public boolean shouldOverrideUrlLoading(WebView view, String url) {
614c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III            if (voiceSearchSourceIsGoogle()) {
615c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III                // This method is called when the user clicks on a link.
616c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III                // VoiceSearchMode is turned off when the user leaves the
617c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III                // Google results page, so at this point the user must be on
618c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III                // that page.  If the user clicked a link on that page, assume
619c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III                // that the voice search was effective, and broadcast an Intent
620c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III                // so a receiver can take note of that fact.
621c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III                Intent logIntent = new Intent(LoggingEvents.ACTION_LOG_EVENT);
622c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III                logIntent.putExtra(LoggingEvents.EXTRA_EVENT,
623c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III                        LoggingEvents.VoiceSearch.RESULT_CLICKED);
6241461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                mContext.sendBroadcast(logIntent);
625c1f5ae26d76a49e6bac9f3224ddb14eee74d4974Leon Scroggins III            }
62622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (mInForeground) {
62718eb377badf8e6f9ea2925bcb7e978facf3171d9Michael Kolb                return mWebViewController.shouldOverrideUrlLoading(Tab.this,
62818eb377badf8e6f9ea2925bcb7e978facf3171d9Michael Kolb                        view, url);
62922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            } else {
63022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                return false;
63122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
63222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
63322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
63422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
63522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Updates the lock icon. This method is called when we discover another
63622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * resource to be loaded for this page (for example, javascript). While
63722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * we update the icon type, we do not update the lock icon itself until
63822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * we are done loading, it is slightly more secure this way.
63922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
64022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
64122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onLoadResource(WebView view, String url) {
64222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (url != null && url.length() > 0) {
64322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                // It is only if the page claims to be secure that we may have
64422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                // to update the lock:
64530c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                if (mCurrentState.mLockIcon == LockIcon.LOCK_ICON_SECURE) {
64622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    // If NOT a 'safe' url, change the lock to mixed content!
64722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    if (!(URLUtil.isHttpsUrl(url) || URLUtil.isDataUrl(url)
64822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            || URLUtil.isAboutUrl(url))) {
64930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                        mCurrentState.mLockIcon = LockIcon.LOCK_ICON_MIXED;
65022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    }
65122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                }
65222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
65322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
65422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
65522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
65622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Show a dialog informing the user of the network error reported by
65722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * WebCore if it is in the foreground.
65822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
65922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
66022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onReceivedError(WebView view, int errorCode,
66122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                String description, String failingUrl) {
66222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (errorCode != WebViewClient.ERROR_HOST_LOOKUP &&
66322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    errorCode != WebViewClient.ERROR_CONNECT &&
66422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    errorCode != WebViewClient.ERROR_BAD_URL &&
66522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    errorCode != WebViewClient.ERROR_UNSUPPORTED_SCHEME &&
66622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    errorCode != WebViewClient.ERROR_FILE) {
66722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                queueError(errorCode, description);
66822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
66947654f464e2ecd65fb049817201fb00a9f8fe29cJeff Hamilton
67047654f464e2ecd65fb049817201fb00a9f8fe29cJeff Hamilton            // Don't log URLs when in private browsing mode
671f8bdfce9f2fc93bed2667694dc5b5ddf001d99d2Rob Tsuk            if (!isPrivateBrowsingEnabled()) {
67247654f464e2ecd65fb049817201fb00a9f8fe29cJeff Hamilton                Log.e(LOGTAG, "onReceivedError " + errorCode + " " + failingUrl
67347654f464e2ecd65fb049817201fb00a9f8fe29cJeff Hamilton                        + " " + description);
67447654f464e2ecd65fb049817201fb00a9f8fe29cJeff Hamilton            }
67522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
67622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
67722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
67822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Check with the user if it is ok to resend POST data as the page they
67922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * are trying to navigate to is the result of a POST.
68022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
68122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
68222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onFormResubmission(WebView view, final Message dontResend,
68322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                       final Message resend) {
68422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (!mInForeground) {
68522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                dontResend.sendToTarget();
68622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                return;
68722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
6884a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins            if (mDontResend != null) {
6894a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                Log.w(LOGTAG, "onFormResubmission should not be called again "
6904a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                        + "while dialog is still up");
6914a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                dontResend.sendToTarget();
6924a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                return;
6934a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins            }
6944a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins            mDontResend = dontResend;
6954a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins            mResend = resend;
6961461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            new AlertDialog.Builder(mContext).setTitle(
69722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    R.string.browserFrameFormResubmitLabel).setMessage(
69822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    R.string.browserFrameFormResubmitMessage)
69922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .setPositiveButton(R.string.ok,
70022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            new DialogInterface.OnClickListener() {
70122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                public void onClick(DialogInterface dialog,
70222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                        int which) {
7034a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                    if (mResend != null) {
7044a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                        mResend.sendToTarget();
7054a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                        mResend = null;
7064a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                        mDontResend = null;
7074a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                    }
70822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                }
70922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            }).setNegativeButton(R.string.cancel,
71022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            new DialogInterface.OnClickListener() {
71122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                public void onClick(DialogInterface dialog,
71222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                        int which) {
7134a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                    if (mDontResend != null) {
7144a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                        mDontResend.sendToTarget();
7154a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                        mResend = null;
7164a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                        mDontResend = null;
7174a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                    }
71822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                }
71922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            }).setOnCancelListener(new OnCancelListener() {
72022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        public void onCancel(DialogInterface dialog) {
7214a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                            if (mDontResend != null) {
7224a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                mDontResend.sendToTarget();
7234a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                mResend = null;
7244a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                                mDontResend = null;
7254a64a8a375b1531392a068039e3c4ee3a636b1ecLeon Scroggins                            }
72622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        }
72722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    }).show();
72822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
72922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
73022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
73122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Insert the url into the visited history database.
73222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param url The url to be inserted.
73322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param isReload True if this url is being reloaded.
73422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * FIXME: Not sure what to do when reloading the page.
73522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
73622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
73722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void doUpdateVisitedHistory(WebView view, String url,
73822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                boolean isReload) {
739324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck            mWebViewController.doUpdateVisitedHistory(Tab.this, isReload);
74022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
74122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
74222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
74322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Displays SSL error(s) dialog to the user.
74422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
74522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
74622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onReceivedSslError(final WebView view,
74722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                final SslErrorHandler handler, final SslError error) {
74822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (!mInForeground) {
74922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                handler.cancel();
75030c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                setLockIconType(LockIcon.LOCK_ICON_UNSECURE);
75122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                return;
75222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
75335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            if (mSettings.showSecurityWarnings()) {
754cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                new AlertDialog.Builder(mContext)
755cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                    .setTitle(R.string.security_warning)
756cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                    .setMessage(R.string.ssl_warnings_header)
757cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                    .setIcon(android.R.drawable.ic_dialog_alert)
758cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                    .setPositiveButton(R.string.ssl_continue,
75922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        new DialogInterface.OnClickListener() {
760cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                            @Override
76122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            public void onClick(DialogInterface dialog,
76222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                    int whichButton) {
76322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                handler.proceed();
76422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            }
765cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                        })
766cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                    .setNeutralButton(R.string.view_certificate,
76722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        new DialogInterface.OnClickListener() {
768cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                            @Override
76922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            public void onClick(DialogInterface dialog,
77022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                    int whichButton) {
771cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                                mWebViewController.showSslCertificateOnError(
772cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                                        view, handler, error);
77322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            }
774cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                        })
775cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                    .setNegativeButton(R.string.ssl_go_back,
77622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        new DialogInterface.OnClickListener() {
777cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                            @Override
77822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            public void onClick(DialogInterface dialog,
77922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                    int whichButton) {
78030c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                                dialog.cancel();
78122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            }
782cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                        })
783cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                    .setOnCancelListener(
78422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        new DialogInterface.OnCancelListener() {
785cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                            @Override
78622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            public void onCancel(DialogInterface dialog) {
78722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                handler.cancel();
78830c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                                setLockIconType(LockIcon.LOCK_ICON_UNSECURE);
78930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck                                mWebViewController.onUserCanceledSsl(Tab.this);
79022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            }
791cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                        })
792cb28b2cfe64bb1b8e1fe379aa59bf1b0e93ae790John Reck                    .show();
79322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            } else {
79422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                handler.proceed();
79522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
79622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
79722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
79822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
7998862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom         * Displays client certificate request to the user.
8008862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom         */
8018862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom        @Override
8028862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom        public void onReceivedClientCertRequest(final WebView view,
8038862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom                final ClientCertRequestHandler handler, final String host_and_port) {
8048862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom            if (!mInForeground) {
8058862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom                handler.ignore();
8068862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom                return;
8078862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom            }
8086d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom            int colon = host_and_port.lastIndexOf(':');
8096d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom            String host;
8106d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom            int port;
8116d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom            if (colon == -1) {
8126d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom                host = host_and_port;
8136d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom                port = -1;
8146d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom            } else {
8156d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom                String portString = host_and_port.substring(colon + 1);
8166d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom                try {
8176d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom                    port = Integer.parseInt(portString);
8186d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom                    host = host_and_port.substring(0, colon);
8196d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom                } catch  (NumberFormatException e) {
8206d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom                    host = host_and_port;
8216d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom                    port = -1;
8226d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom                }
8236d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom            }
8241461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            KeyChain.choosePrivateKeyAlias(
8251461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                    mWebViewController.getActivity(), new KeyChainAliasCallback() {
8268862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom                @Override public void alias(String alias) {
8278862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom                    if (alias == null) {
8288862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom                        handler.cancel();
8298862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom                        return;
8308862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom                    }
8311461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                    new KeyChainLookup(mContext, handler, alias).execute();
8328862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom                }
8336d85fab73e2c0359968fc6580594689940f5dabcBrian Carlstrom            }, null, null, host, port, null);
8348862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom        }
8358862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom
8368862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom        /**
83722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Handles an HTTP authentication request.
83822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         *
83922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param handler The authentication handler
84022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param host The host
84122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param realm The realm
84222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
84322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
84422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onReceivedHttpAuthRequest(WebView view,
84522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                final HttpAuthHandler handler, final String host,
84622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                final String realm) {
8478233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mWebViewController.onReceivedHttpAuthRequest(Tab.this, view, handler, host, realm);
84822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
84922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
85022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
851438bf46c98890b5fe1356e75b4bc759033c6fc57John Reck        public WebResourceResponse shouldInterceptRequest(WebView view,
852438bf46c98890b5fe1356e75b4bc759033c6fc57John Reck                String url) {
853438bf46c98890b5fe1356e75b4bc759033c6fc57John Reck            WebResourceResponse res = HomeProvider.shouldInterceptRequest(
8541461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                    mContext, url);
855438bf46c98890b5fe1356e75b4bc759033c6fc57John Reck            return res;
856438bf46c98890b5fe1356e75b4bc759033c6fc57John Reck        }
857438bf46c98890b5fe1356e75b4bc759033c6fc57John Reck
858438bf46c98890b5fe1356e75b4bc759033c6fc57John Reck        @Override
85922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
86022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (!mInForeground) {
86122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                return false;
86222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
8638233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return mWebViewController.shouldOverrideKeyEvent(event);
86422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
86522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
86622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
86722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
8688233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (!mInForeground) {
86922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                return;
87022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
8718233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mWebViewController.onUnhandledKeyEvent(event);
87222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
8739206677e461328f15854c5fcb1366d0e261534c6Patrick Scott
8749206677e461328f15854c5fcb1366d0e261534c6Patrick Scott        @Override
8759206677e461328f15854c5fcb1366d0e261534c6Patrick Scott        public void onReceivedLoginRequest(WebView view, String realm,
8769206677e461328f15854c5fcb1366d0e261534c6Patrick Scott                String account, String args) {
8771461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            new DeviceAccountLogin(mWebViewController.getActivity(), view, Tab.this, mWebViewController)
8789206677e461328f15854c5fcb1366d0e261534c6Patrick Scott                    .handleLogin(realm, account, args);
8799206677e461328f15854c5fcb1366d0e261534c6Patrick Scott        }
8809206677e461328f15854c5fcb1366d0e261534c6Patrick Scott
88122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    };
88222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
8831cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private void syncCurrentState(WebView view, String url) {
8841cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        // Sync state (in case of stop/timeout)
8851cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        mCurrentState.mUrl = view.getUrl();
8861cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        if (mCurrentState.mUrl == null) {
8878bcafc149bc49b84c8dfbaacf88c178d8bc9eda6John Reck            mCurrentState.mUrl = "";
8881cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
8891cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        mCurrentState.mOriginalUrl = view.getOriginalUrl();
8901cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        mCurrentState.mTitle = view.getTitle();
8911cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        mCurrentState.mFavicon = view.getFavicon();
8921cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        if (!URLUtil.isHttpsUrl(mCurrentState.mUrl)) {
8931cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            // In case we stop when loading an HTTPS page from an HTTP page
8941cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            // but before a provisional load occurred
8951cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            mCurrentState.mLockIcon = LockIcon.LOCK_ICON_UNSECURE;
8961cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
897502a353bb815bee8bec6a60f3b741dc62e4729cdJohn Reck        mCurrentState.mIncognito = view.isPrivateBrowsingEnabled();
8981cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
8991cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
9009206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    // Called by DeviceAccountLogin when the Tab needs to have the auto-login UI
9019206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    // displayed.
9029206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    void setDeviceAccountLogin(DeviceAccountLogin login) {
9039206677e461328f15854c5fcb1366d0e261534c6Patrick Scott        mDeviceAccountLogin = login;
9049206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    }
9059206677e461328f15854c5fcb1366d0e261534c6Patrick Scott
9069206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    // Returns non-null if the title bar should display the auto-login UI.
9079206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    DeviceAccountLogin getDeviceAccountLogin() {
9089206677e461328f15854c5fcb1366d0e261534c6Patrick Scott        return mDeviceAccountLogin;
9099206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    }
9109206677e461328f15854c5fcb1366d0e261534c6Patrick Scott
91122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // -------------------------------------------------------------------------
91222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // WebChromeClient implementation for the main WebView
91322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // -------------------------------------------------------------------------
91422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
91522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private final WebChromeClient mWebChromeClient = new WebChromeClient() {
91622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // Helper method to create a new tab or sub window.
91722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        private void createWindow(final boolean dialog, final Message msg) {
91822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            WebView.WebViewTransport transport =
91922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    (WebView.WebViewTransport) msg.obj;
92022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (dialog) {
92122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                createSubWindow();
9228233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mWebViewController.attachSubWindow(Tab.this);
92322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                transport.setWebView(mSubView);
92422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            } else {
9257bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb                final Tab newTab = mWebViewController.openTab(null,
9265949c661b51295148706d53a03b41df2eb840ae3John Reck                        Tab.this, true, true);
92722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                transport.setWebView(newTab.getWebView());
92822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
92922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            msg.sendToTarget();
93022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
93122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
93222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
93322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public boolean onCreateWindow(WebView view, final boolean dialog,
93422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                final boolean userGesture, final Message resultMsg) {
93522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // only allow new window or sub window for the foreground case
93622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (!mInForeground) {
93722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                return false;
93822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
93922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // Short-circuit if we can't create any more tabs or sub windows.
94022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (dialog && mSubView != null) {
9411461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                new AlertDialog.Builder(mContext)
94222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        .setTitle(R.string.too_many_subwindows_dialog_title)
94322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        .setIcon(android.R.drawable.ic_dialog_alert)
94422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        .setMessage(R.string.too_many_subwindows_dialog_message)
94522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        .setPositiveButton(R.string.ok, null)
94622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        .show();
94722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                return false;
9488233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else if (!mWebViewController.getTabControl().canCreateNewTab()) {
9491461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                new AlertDialog.Builder(mContext)
95022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        .setTitle(R.string.too_many_windows_dialog_title)
95122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        .setIcon(android.R.drawable.ic_dialog_alert)
95222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        .setMessage(R.string.too_many_windows_dialog_message)
95322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        .setPositiveButton(R.string.ok, null)
95422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        .show();
95522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                return false;
95622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
95722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
95822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // Short-circuit if this was a user gesture.
95922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (userGesture) {
96022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                createWindow(dialog, resultMsg);
96122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                return true;
96222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
96322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
96422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // Allow the popup and create the appropriate window.
96522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            final AlertDialog.OnClickListener allowListener =
96622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    new AlertDialog.OnClickListener() {
96722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        public void onClick(DialogInterface d,
96822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                                int which) {
96922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            createWindow(dialog, resultMsg);
97022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        }
97122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    };
97222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
97322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // Block the popup by returning a null WebView.
97422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            final AlertDialog.OnClickListener blockListener =
97522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    new AlertDialog.OnClickListener() {
97622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        public void onClick(DialogInterface d, int which) {
97722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            resultMsg.sendToTarget();
97822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                        }
97922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    };
98022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
98122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // Build a confirmation dialog to display to the user.
98222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            final AlertDialog d =
9831461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                    new AlertDialog.Builder(mContext)
98422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .setTitle(R.string.attention)
98522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .setIcon(android.R.drawable.ic_dialog_alert)
98622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .setMessage(R.string.popup_window_attempt)
98722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .setPositiveButton(R.string.allow, allowListener)
98822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .setNegativeButton(R.string.block, blockListener)
98922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .setCancelable(false)
99022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .create();
99122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
99222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // Show the confirmation dialog.
99322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            d.show();
99422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return true;
99522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
99622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
99722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
998eb5061b8e5de8ccb3667f002ef3ec6732a7d78baPatrick Scott        public void onRequestFocus(WebView view) {
999eb5061b8e5de8ccb3667f002ef3ec6732a7d78baPatrick Scott            if (!mInForeground) {
1000c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                mWebViewController.switchToTab(Tab.this);
1001eb5061b8e5de8ccb3667f002ef3ec6732a7d78baPatrick Scott            }
1002eb5061b8e5de8ccb3667f002ef3ec6732a7d78baPatrick Scott        }
1003eb5061b8e5de8ccb3667f002ef3ec6732a7d78baPatrick Scott
1004eb5061b8e5de8ccb3667f002ef3ec6732a7d78baPatrick Scott        @Override
100522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onCloseWindow(WebView window) {
1006c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            if (mParent != null) {
100722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                // JavaScript can only close popup window.
100822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                if (mInForeground) {
1009c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                    mWebViewController.switchToTab(mParent);
101022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                }
10118233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mWebViewController.closeTab(Tab.this);
101222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
101322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
101422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
101522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
101622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onProgressChanged(WebView view, int newProgress) {
101730c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            mPageLoadProgress = newProgress;
101830c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            mWebViewController.onProgressChanged(Tab.this);
101922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
102022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
102122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
102221d9b907ca3aac7f1ad693cbb8731f5d3e4215a8Leon Scroggins        public void onReceivedTitle(WebView view, final String title) {
102330c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            mCurrentState.mTitle = title;
10248233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mWebViewController.onReceivedTitle(Tab.this, title);
102522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
102622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
102722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
102822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onReceivedIcon(WebView view, Bitmap icon) {
102930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            mCurrentState.mFavicon = icon;
10308233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mWebViewController.onFavicon(Tab.this, view, icon);
103122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
103222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
103322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
103422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onReceivedTouchIconUrl(WebView view, String url,
103522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                boolean precomposed) {
10361461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            final ContentResolver cr = mContext.getContentResolver();
1037c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins            // Let precomposed icons take precedence over non-composed
1038c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins            // icons.
1039c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins            if (precomposed && mTouchIconLoader != null) {
1040c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins                mTouchIconLoader.cancel(false);
1041c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins                mTouchIconLoader = null;
1042c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins            }
1043c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins            // Have only one async task at a time.
1044c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins            if (mTouchIconLoader == null) {
10458233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mTouchIconLoader = new DownloadTouchIcon(Tab.this,
10461461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                        mContext, cr, view);
1047c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins                mTouchIconLoader.execute(url);
104822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
104922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
105022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
105122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
105222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onShowCustomView(View view,
105322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                WebChromeClient.CustomViewCallback callback) {
10541461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            Activity activity = mWebViewController.getActivity();
10551461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            if (activity != null) {
10561461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                onShowCustomView(view, activity.getRequestedOrientation(), callback);
10571461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            }
10582d4f1e2553dee6bce5a12162ff6d4459babe2512Derek Sollenberger        }
10592d4f1e2553dee6bce5a12162ff6d4459babe2512Derek Sollenberger
10602d4f1e2553dee6bce5a12162ff6d4459babe2512Derek Sollenberger        @Override
10612d4f1e2553dee6bce5a12162ff6d4459babe2512Derek Sollenberger        public void onShowCustomView(View view, int requestedOrientation,
10622d4f1e2553dee6bce5a12162ff6d4459babe2512Derek Sollenberger                WebChromeClient.CustomViewCallback callback) {
10638233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (mInForeground) mWebViewController.showCustomView(Tab.this, view,
10642d4f1e2553dee6bce5a12162ff6d4459babe2512Derek Sollenberger                    requestedOrientation, callback);
106522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
106622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
106722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
106822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onHideCustomView() {
10698233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (mInForeground) mWebViewController.hideCustomView();
107022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
107122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
107222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
107322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * The origin has exceeded its database quota.
107422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param url the URL that exceeded the quota
107522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param databaseIdentifier the identifier of the database on which the
107622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         *            transaction that caused the quota overflow was run
107722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param currentQuota the current quota for the origin.
107822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param estimatedSize the estimated size of the database.
107922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param totalUsedQuota is the sum of all origins' quota.
108022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param quotaUpdater The callback to run when a decision to allow or
108122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         *            deny quota has been made. Don't forget to call this!
108222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
108322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
108422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onExceededDatabaseQuota(String url,
108522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            String databaseIdentifier, long currentQuota, long estimatedSize,
108622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
108735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            mSettings.getWebStorageSizeManager()
108822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .onExceededDatabaseQuota(url, databaseIdentifier,
108922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            currentQuota, estimatedSize, totalUsedQuota,
109022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            quotaUpdater);
109122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
109222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
109322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
109422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * The Application Cache has exceeded its max size.
109522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param spaceNeeded is the amount of disk space that would be needed
109622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         *            in order for the last appcache operation to succeed.
109722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param totalUsedQuota is the sum of all origins' quota.
109822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param quotaUpdater A callback to inform the WebCore thread that a
109922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         *            new app cache size is available. This callback must always
110022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         *            be executed at some point to ensure that the sleeping
110122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         *            WebCore thread is woken up.
110222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
110322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
110422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onReachedMaxAppCacheSize(long spaceNeeded,
110522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
110635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            mSettings.getWebStorageSizeManager()
110722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    .onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota,
110822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                            quotaUpdater);
110922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
111022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
111122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
111222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Instructs the browser to show a prompt to ask the user to set the
111322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Geolocation permission state for the specified origin.
111422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param origin The origin for which Geolocation permissions are
111522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         *     requested.
111622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @param callback The callback to call once the user has set the
111722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         *     Geolocation permission state.
111822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
111922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
112022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onGeolocationPermissionsShowPrompt(String origin,
112122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                GeolocationPermissions.Callback callback) {
112222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (mInForeground) {
112350c241e6339c681c2427a57a31a357d35927c2acGrace Kloba                getGeolocationPermissionsPrompt().show(origin, callback);
112422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
112522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
112622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
112722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
112822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Instructs the browser to hide the Geolocation permissions prompt.
112922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
113022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
113122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onGeolocationPermissionsHidePrompt() {
113250c241e6339c681c2427a57a31a357d35927c2acGrace Kloba            if (mInForeground && mGeolocationPermissionsPrompt != null) {
113322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                mGeolocationPermissionsPrompt.hide();
113422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
113522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
113622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
113765acc3541e4bcf8d9a0b3f59941c40fdb106c703Ben Murdoch        /* Adds a JavaScript error message to the system log and if the JS
113865acc3541e4bcf8d9a0b3f59941c40fdb106c703Ben Murdoch         * console is enabled in the about:debug options, to that console
113965acc3541e4bcf8d9a0b3f59941c40fdb106c703Ben Murdoch         * also.
1140c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch         * @param consoleMessage the message object.
114122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
114222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
1143c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch        public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
114422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (mInForeground) {
114522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                // call getErrorConsole(true) so it will create one if needed
114622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                ErrorConsoleView errorConsole = getErrorConsole(true);
1147c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                errorConsole.addErrorMessage(consoleMessage);
11488233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (mWebViewController.shouldShowErrorConsole()
11498233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        && errorConsole.getShowState() !=
11508233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            ErrorConsoleView.SHOW_MAXIMIZED) {
115122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    errorConsole.showConsole(ErrorConsoleView.SHOW_MINIMIZED);
115222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                }
115322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
1154c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch
115547654f464e2ecd65fb049817201fb00a9f8fe29cJeff Hamilton            // Don't log console messages in private browsing mode
1156f8bdfce9f2fc93bed2667694dc5b5ddf001d99d2Rob Tsuk            if (isPrivateBrowsingEnabled()) return true;
115747654f464e2ecd65fb049817201fb00a9f8fe29cJeff Hamilton
1158c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch            String message = "Console: " + consoleMessage.message() + " "
1159c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    + consoleMessage.sourceId() +  ":"
1160c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    + consoleMessage.lineNumber();
1161c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch
1162c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch            switch (consoleMessage.messageLevel()) {
1163c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                case TIP:
1164c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    Log.v(CONSOLE_LOGTAG, message);
1165c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    break;
1166c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                case LOG:
1167c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    Log.i(CONSOLE_LOGTAG, message);
1168c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    break;
1169c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                case WARNING:
1170c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    Log.w(CONSOLE_LOGTAG, message);
1171c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    break;
1172c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                case ERROR:
1173c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    Log.e(CONSOLE_LOGTAG, message);
1174c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    break;
1175c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                case DEBUG:
1176c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    Log.d(CONSOLE_LOGTAG, message);
1177c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch                    break;
1178c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch            }
1179c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch
1180c42addfd5c76d543c63a83ef87c1257cea309edfBen Murdoch            return true;
118122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
118222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
118322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
118422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Ask the browser for an icon to represent a <video> element.
118522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * This icon will be used if the Web page did not specify a poster attribute.
118622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @return Bitmap The icon or null if no such icon is available.
118722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
118822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
118922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public Bitmap getDefaultVideoPoster() {
119022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (mInForeground) {
11918233facddcc51865d612a919d450db6954aa48e3Michael Kolb                return mWebViewController.getDefaultVideoPoster();
119222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
119322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return null;
119422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
119522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
119622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
119722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Ask the host application for a custom progress view to show while
119822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * a <video> is loading.
119922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * @return View The progress view.
120022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
120122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
120222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public View getVideoLoadingProgressView() {
120322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (mInForeground) {
12048233facddcc51865d612a919d450db6954aa48e3Michael Kolb                return mWebViewController.getVideoLoadingProgressView();
120522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
120622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return null;
120722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
120822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
120922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
121062b1b7ef20a1c9f4c6e6f7b73140701b3c6193c5Ben Murdoch        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
121122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (mInForeground) {
12128233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mWebViewController.openFileChooser(uploadMsg, acceptType);
121322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            } else {
121422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                uploadMsg.onReceiveValue(null);
121522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
121622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
121722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
121822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        /**
121922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         * Deliver a list of already-visited URLs
122022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba         */
122122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
122222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void getVisitedHistory(final ValueCallback<String[]> callback) {
12238233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mWebViewController.getVisitedHistory(callback);
12248233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
12258029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch
12268029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch        @Override
12278029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch        public void setupAutoFill(Message message) {
12288029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch            // Prompt the user to set up their profile.
12298029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch            final Message msg = message;
12301461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
12311461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
12321d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                    Context.LAYOUT_INFLATER_SERVICE);
12331d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch            final View layout = inflater.inflate(R.layout.setup_autofill_dialog, null);
12341d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch
12351d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch            builder.setView(layout)
1236b7e6f94a4728e284764a45b25985a05e0f5c6273Ben Murdoch                .setTitle(R.string.autofill_setup_dialog_title)
12371d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
12381d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                    @Override
12391d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                    public void onClick(DialogInterface dialog, int id) {
12401d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                        CheckBox disableAutoFill = (CheckBox) layout.findViewById(
12411d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                                R.id.setup_autofill_dialog_disable_autofill);
12421d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch
12431d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                        if (disableAutoFill.isChecked()) {
12441d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                            // Disable autofill and show a toast with how to turn it on again.
124535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                            mSettings.setAutofillEnabled(false);
12461461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                            Toast.makeText(mContext,
12471d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                                    R.string.autofill_setup_dialog_negative_toast,
12481d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                                    Toast.LENGTH_LONG).show();
12491d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                        } else {
12501d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                            // Take user to the AutoFill profile editor. When they return,
12511d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                            // we will send the message that we pass here which will trigger
12521d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                            // the form to get filled out with their new profile.
12531d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                            mWebViewController.setupAutoFill(msg);
12541d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                        }
12551d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                    }
12561d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                })
12571d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                .setNegativeButton(R.string.cancel, null)
12581d676b6d3080ea2e8206e2a601be8390f1bbd0edBen Murdoch                .show();
12598029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch        }
126022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    };
126122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
126222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // -------------------------------------------------------------------------
126322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // WebViewClient implementation for the sub window
126422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // -------------------------------------------------------------------------
126522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
126622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Subclass of WebViewClient used in subwindows to notify the main
126722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // WebViewClient of certain WebView activities.
126822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private static class SubWindowClient extends WebViewClient {
126922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // The main WebViewClient.
127022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        private final WebViewClient mClient;
12718233facddcc51865d612a919d450db6954aa48e3Michael Kolb        private final WebViewController mController;
127222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
12738233facddcc51865d612a919d450db6954aa48e3Michael Kolb        SubWindowClient(WebViewClient client, WebViewController controller) {
127422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mClient = client;
12758233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mController = controller;
1276211ba54a3052f7e68bf8af035ea1ef4e9445130cLeon Scroggins III        }
1277211ba54a3052f7e68bf8af035ea1ef4e9445130cLeon Scroggins III        @Override
1278211ba54a3052f7e68bf8af035ea1ef4e9445130cLeon Scroggins III        public void onPageStarted(WebView view, String url, Bitmap favicon) {
1279211ba54a3052f7e68bf8af035ea1ef4e9445130cLeon Scroggins III            // Unlike the others, do not call mClient's version, which would
1280211ba54a3052f7e68bf8af035ea1ef4e9445130cLeon Scroggins III            // change the progress bar.  However, we do want to remove the
128101cfcdd0b77d672f5c09d98af683c6732c8250d8Cary Clark            // find or select dialog.
12828233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mController.endActionMode();
128322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
128422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
128522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void doUpdateVisitedHistory(WebView view, String url,
128622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                boolean isReload) {
128722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mClient.doUpdateVisitedHistory(view, url, isReload);
128822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
128922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
129022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public boolean shouldOverrideUrlLoading(WebView view, String url) {
129122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return mClient.shouldOverrideUrlLoading(view, url);
129222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
129322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
129422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onReceivedSslError(WebView view, SslErrorHandler handler,
129522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                SslError error) {
129622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mClient.onReceivedSslError(view, handler, error);
129722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
129822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
12998862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom        public void onReceivedClientCertRequest(WebView view,
13008862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom                ClientCertRequestHandler handler, String host_and_port) {
13018862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom            mClient.onReceivedClientCertRequest(view, handler, host_and_port);
13028862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom        }
13038862c1dd48ac83011411c469afb5065b6d0c32f9Brian Carlstrom        @Override
130422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onReceivedHttpAuthRequest(WebView view,
130522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                HttpAuthHandler handler, String host, String realm) {
130622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mClient.onReceivedHttpAuthRequest(view, handler, host, realm);
130722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
130822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
130922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onFormResubmission(WebView view, Message dontResend,
131022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                Message resend) {
131122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mClient.onFormResubmission(view, dontResend, resend);
131222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
131322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
131422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onReceivedError(WebView view, int errorCode,
131522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                String description, String failingUrl) {
131622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mClient.onReceivedError(view, errorCode, description, failingUrl);
131722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
131822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
131922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public boolean shouldOverrideKeyEvent(WebView view,
132022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                android.view.KeyEvent event) {
132122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return mClient.shouldOverrideKeyEvent(view, event);
132222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
132322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
132422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onUnhandledKeyEvent(WebView view,
132522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                android.view.KeyEvent event) {
132622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mClient.onUnhandledKeyEvent(view, event);
132722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
132822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
132922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
133022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // -------------------------------------------------------------------------
133122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // WebChromeClient implementation for the sub window
133222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // -------------------------------------------------------------------------
133322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
133422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    private class SubWindowChromeClient extends WebChromeClient {
133522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // The main WebChromeClient.
133622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        private final WebChromeClient mClient;
133722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
133822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        SubWindowChromeClient(WebChromeClient client) {
133922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mClient = client;
134022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
134122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
134222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onProgressChanged(WebView view, int newProgress) {
134322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mClient.onProgressChanged(view, newProgress);
134422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
134522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
134622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public boolean onCreateWindow(WebView view, boolean dialog,
134722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                boolean userGesture, android.os.Message resultMsg) {
134822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return mClient.onCreateWindow(view, dialog, userGesture, resultMsg);
134922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
135022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        @Override
135122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        public void onCloseWindow(WebView window) {
135222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (window != mSubView) {
135322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                Log.e(LOGTAG, "Can't close the window");
135422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
13558233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mWebViewController.dismissSubWindow(Tab.this);
135622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
135722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
135822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
135922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // -------------------------------------------------------------------------
136022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
136122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // Construct a new tab
13627bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    Tab(WebViewController wvcontroller, WebView w) {
13631cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        this(wvcontroller, w, null);
13641cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
13651cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
13661cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    Tab(WebViewController wvcontroller, Bundle state) {
13671cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        this(wvcontroller, null, state);
13681cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
13691cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
13701cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    Tab(WebViewController wvcontroller, WebView w, Bundle state) {
13718233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mWebViewController = wvcontroller;
13721461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        mContext = mWebViewController.getContext();
137335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        mSettings = BrowserSettings.getInstance();
13741461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        mDataController = DataController.getInstance(mContext);
13751461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        mCurrentState = new PageState(mContext, w != null
1376847b532045e3cb117a847ebb956c9919401f332dJohn Reck                ? w.isPrivateBrowsingEnabled() : false);
13778233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mInPageLoad = false;
137822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mInForeground = false;
137922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
1380dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins        mDownloadListener = new DownloadListener() {
1381dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            public void onDownloadStart(String url, String userAgent,
1382dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                    String contentDisposition, String mimetype,
1383dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                    long contentLength) {
13848233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mWebViewController.onDownloadStart(Tab.this, url, userAgent, contentDisposition,
1385dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                        mimetype, contentLength);
1386dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            }
1387dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins        };
13880c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins        mWebBackForwardListClient = new WebBackForwardListClient() {
13890c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins            @Override
13900c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins            public void onNewHistoryItem(WebHistoryItem item) {
13910c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins                if (isInVoiceSearchMode()) {
13920c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins                    item.setCustomData(mVoiceSearchData.mVoiceSearchIntent);
13930c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins                }
13941dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                if (mClearHistoryMatchUrl != null) {
13951dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                    if (LOGD_ENABLED) {
13961dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                        Log.d(LOGTAG, "onNewHistoryItem:\n\t" + item.getUrl() + "\n\t"
13971dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                                + mClearHistoryMatchUrl);
13981dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                    }
13991dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                    if (TextUtils.equals(item.getOriginalUrl(), mClearHistoryMatchUrl)) {
14001dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                        if (mMainView != null) {
14011dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                            mMainView.clearHistory();
14021dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                        }
14031dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                    }
14041dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                    mClearHistoryMatchUrl = null;
14051dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                }
14060c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins            }
14070c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins            @Override
14080c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins            public void onIndexChanged(WebHistoryItem item, int index) {
14090c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins                Object data = item.getCustomData();
14100c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins                if (data != null && data instanceof Intent) {
14110c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins                    activateVoiceSearchMode((Intent) data);
14120c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins                }
14130c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins            }
14140c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins        };
1415dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins
14161cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        mCaptureWidth = mContext.getResources().getDimensionPixelSize(
14171cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                R.dimen.tab_thumbnail_width);
14181cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        mCaptureHeight = mContext.getResources().getDimensionPixelSize(
14191cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                R.dimen.tab_thumbnail_height);
14201cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        updateShouldCaptureThumbnails();
14211cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        restoreState(state);
142252be4785a258687055515117775d5bcb8bec1c12John Reck        if (getId() == -1) {
142352be4785a258687055515117775d5bcb8bec1c12John Reck            mId = TabControl.getNextId();
142452be4785a258687055515117775d5bcb8bec1c12John Reck        }
142522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        setWebView(w);
14269ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        mHandler = new Handler() {
14271dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood            @Override
14289ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb            public void handleMessage(Message m) {
14291cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                switch (m.what) {
14301cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                case MSG_CAPTURE:
14311cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    capture();
14321cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    break;
14331cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                }
14349ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb            }
14359ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        };
14361cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
14379ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb
1438e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood    /**
1439e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood     * This is used to get a new ID when the tab has been preloaded, before it is displayed and
1440e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood     * added to TabControl. Preloaded tabs can be created before restoreInstanceState, leading
1441e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood     * to overlapping IDs between the preloaded and restored tabs.
1442e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood     */
1443e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood    public void refreshIdAfterPreload() {
1444e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood        mId = TabControl.getNextId();
1445e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood    }
1446e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood
14471cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    public void updateShouldCaptureThumbnails() {
14481cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        if (mWebViewController.shouldCaptureThumbnails()) {
14491cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            synchronized (Tab.this) {
14501cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                if (mCapture == null) {
14511cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    mCapture = Bitmap.createBitmap(mCaptureWidth, mCaptureHeight,
14521cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                            Bitmap.Config.RGB_565);
1453c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb                    mCapture.eraseColor(Color.WHITE);
14541cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    if (mInForeground) {
14551cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                        postCapture();
14561cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    }
14571cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                }
14581cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
14591cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        } else {
14601cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            synchronized (Tab.this) {
14611cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                mCapture = null;
14621cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                deleteThumbnail();
14631cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
14641cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
146522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
146622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
14671461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb    public void setController(WebViewController ctl) {
14681461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        mWebViewController = ctl;
14691cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        updateShouldCaptureThumbnails();
14701461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb    }
14711461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb
1472c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    public long getId() {
1473c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        return mId;
1474c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    }
1475c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb
147622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
147722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Sets the WebView for this tab, correctly removing the old WebView from
147822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * the container view.
147922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
148022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    void setWebView(WebView w) {
148122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mMainView == w) {
148222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return;
148322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
1484a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb
148522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // If the WebView is changing, the page will be reloaded, so any ongoing
148622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // Geolocation permission requests are void.
148750c241e6339c681c2427a57a31a357d35927c2acGrace Kloba        if (mGeolocationPermissionsPrompt != null) {
148850c241e6339c681c2427a57a31a357d35927c2acGrace Kloba            mGeolocationPermissionsPrompt.hide();
148950c241e6339c681c2427a57a31a357d35927c2acGrace Kloba        }
149022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
1491a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb        mWebViewController.onSetWebView(this, w);
149222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
14931cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        if (mMainView != null) {
14948ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            mMainView.setPictureListener(null);
14951cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            if (w != null) {
14961cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                syncCurrentState(w, null);
14971cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            } else {
14981cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                mCurrentState = new PageState(mContext, false);
14991cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
15001cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
150122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // set the new one
150222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mMainView = w;
1503dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins        // attach the WebViewClient, WebChromeClient and DownloadListener
150422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mMainView != null) {
150522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mMainView.setWebViewClient(mWebViewClient);
150622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mMainView.setWebChromeClient(mWebChromeClient);
1507dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            // Attach DownloadManager so that downloads can start in an active
1508dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            // or a non-active window. This can happen when going to a site that
1509dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            // does a redirect after a period of time. The user could have
1510dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            // switched to another tab while waiting for the download to start.
1511dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            mMainView.setDownloadListener(mDownloadListener);
15120c75a8ed8d95d2f5278826222ca5ec4e96b2aee4Leon Scroggins            mMainView.setWebBackForwardListClient(mWebBackForwardListClient);
15138ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            TabControl tc = mWebViewController.getTabControl();
15148ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            if (tc != null && tc.getOnThumbnailUpdatedListener() != null) {
15158ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck                mMainView.setPictureListener(this);
15168ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            }
15171cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            if (mSavedState != null) {
15186c2e2f34718043f36488b4a94879dc2605aaac49John Reck                WebBackForwardList restoredState
15196c2e2f34718043f36488b4a94879dc2605aaac49John Reck                        = mMainView.restoreState(mSavedState);
15206c2e2f34718043f36488b4a94879dc2605aaac49John Reck                if (restoredState == null || restoredState.getSize() == 0) {
15216c2e2f34718043f36488b4a94879dc2605aaac49John Reck                    Log.w(LOGTAG, "Failed to restore WebView state!");
15226c2e2f34718043f36488b4a94879dc2605aaac49John Reck                    loadUrl(mCurrentState.mOriginalUrl, null);
15236c2e2f34718043f36488b4a94879dc2605aaac49John Reck                }
15241cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                mSavedState = null;
15251cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
152622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
152722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
152822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
152922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
153022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Destroy the tab's main WebView and subWindow if any
153122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
153222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    void destroy() {
153322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mMainView != null) {
153422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            dismissSubWindow();
1535ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck            // Make sure the embedded title bar isn't still attached
1536ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck            mMainView.setEmbeddedTitleBar(null);
153722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            // save the WebView to call destroy() after detach it from the tab
153822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            WebView webView = mMainView;
153922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            setWebView(null);
154022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            webView.destroy();
154122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
154222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
154322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
154422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
154522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Remove the tab from the parent
154622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
154722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    void removeFromTree() {
154822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // detach the children
1549c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        if (mChildren != null) {
1550c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            for(Tab t : mChildren) {
1551c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                t.setParent(null);
155222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
155322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
155422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // remove itself from the parent list
1555c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        if (mParent != null) {
1556c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            mParent.mChildren.remove(this);
155722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
15581cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        deleteThumbnail();
155922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
156022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
156122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
156222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Create a new subwindow unless a subwindow already exists.
156322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @return True if a new subwindow was created. False if one already exists.
156422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
156522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    boolean createSubWindow() {
156622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mSubView == null) {
15671514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb            mWebViewController.createSubWindow(this);
1568211ba54a3052f7e68bf8af035ea1ef4e9445130cLeon Scroggins III            mSubView.setWebViewClient(new SubWindowClient(mWebViewClient,
15698233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    mWebViewController));
157022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mSubView.setWebChromeClient(new SubWindowChromeClient(
157122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                    mWebChromeClient));
1572dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            // Set a different DownloadListener for the mSubView, since it will
1573dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            // just need to dismiss the mSubView, rather than close the Tab
1574dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            mSubView.setDownloadListener(new DownloadListener() {
1575dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                public void onDownloadStart(String url, String userAgent,
1576dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                        String contentDisposition, String mimetype,
1577dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                        long contentLength) {
15788233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    mWebViewController.onDownloadStart(Tab.this, url, userAgent,
1579dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                            contentDisposition, mimetype, contentLength);
1580dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                    if (mSubView.copyBackForwardList().getSize() == 0) {
1581dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                        // This subwindow was opened for the sole purpose of
1582dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                        // downloading a file. Remove it.
15838233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        mWebViewController.dismissSubWindow(Tab.this);
1584dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                    }
1585dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins                }
1586dcc5eeb63eadd597587a0b2b49998c267b0bcc11Leon Scroggins            });
15871461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            mSubView.setOnCreateContextMenuListener(mWebViewController.getActivity());
158822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return true;
158922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
159022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        return false;
159122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
159222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
159322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
159422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Dismiss the subWindow for the tab.
159522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
159622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    void dismissSubWindow() {
159722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mSubView != null) {
15988233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mWebViewController.endActionMode();
159922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mSubView.destroy();
160022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mSubView = null;
160122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mSubViewContainer = null;
160222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
160322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
160422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
160522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
160622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
160722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Set the parent tab of this tab.
160822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
1609c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    void setParent(Tab parent) {
161052be4785a258687055515117775d5bcb8bec1c12John Reck        if (parent == this) {
161152be4785a258687055515117775d5bcb8bec1c12John Reck            throw new IllegalStateException("Cannot set parent to self!");
161252be4785a258687055515117775d5bcb8bec1c12John Reck        }
1613c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        mParent = parent;
161422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // This tab may have been freed due to low memory. If that is the case,
1615c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        // the parent tab id is already saved. If we are changing that id
161622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // (most likely due to removing the parent tab) we must update the
1617c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        // parent tab id in the saved Bundle.
161822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mSavedState != null) {
161922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (parent == null) {
162022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                mSavedState.remove(PARENTTAB);
162122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            } else {
1622c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                mSavedState.putLong(PARENTTAB, parent.getId());
162322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
162422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
1625b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck
1626b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck        // Sync the WebView useragent with the parent
1627b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck        if (parent != null && mSettings.hasDesktopUseragent(parent.getWebView())
1628b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck                != mSettings.hasDesktopUseragent(getWebView())) {
1629b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck            mSettings.toggleDesktopUseragent(getWebView());
1630b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck        }
163152be4785a258687055515117775d5bcb8bec1c12John Reck
163252be4785a258687055515117775d5bcb8bec1c12John Reck        if (parent != null && parent.getId() == getId()) {
163352be4785a258687055515117775d5bcb8bec1c12John Reck            throw new IllegalStateException("Parent has same ID as child!");
163452be4785a258687055515117775d5bcb8bec1c12John Reck        }
163522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
163622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
163722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
1638c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * If this Tab was created through another Tab, then this method returns
1639c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * that Tab.
1640c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * @return the Tab parent or null
1641c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     */
1642c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    public Tab getParent() {
1643c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        return mParent;
1644c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    }
1645c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb
1646c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    /**
164722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * When a Tab is created through the content of another Tab, then we
164822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * associate the Tabs.
164922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @param child the Tab that was created from this Tab
165022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
165122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    void addChildTab(Tab child) {
1652c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        if (mChildren == null) {
1653c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            mChildren = new Vector<Tab>();
165422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
1655c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        mChildren.add(child);
1656c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        child.setParent(this);
165722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
165822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
1659c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    Vector<Tab> getChildren() {
1660c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        return mChildren;
166122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
166222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
166322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    void resume() {
166422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mMainView != null) {
166556c1fcf7774d4ee943fbda808e37840459502e20John Reck            setupHwAcceleration(mMainView);
166622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mMainView.onResume();
166722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (mSubView != null) {
166822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                mSubView.onResume();
166922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
167022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
167122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
167222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
167356c1fcf7774d4ee943fbda808e37840459502e20John Reck    private void setupHwAcceleration(View web) {
167456c1fcf7774d4ee943fbda808e37840459502e20John Reck        if (web == null) return;
167556c1fcf7774d4ee943fbda808e37840459502e20John Reck        BrowserSettings settings = BrowserSettings.getInstance();
167656c1fcf7774d4ee943fbda808e37840459502e20John Reck        if (settings.isHardwareAccelerated()) {
167756c1fcf7774d4ee943fbda808e37840459502e20John Reck            web.setLayerType(View.LAYER_TYPE_NONE, null);
167856c1fcf7774d4ee943fbda808e37840459502e20John Reck        } else {
167956c1fcf7774d4ee943fbda808e37840459502e20John Reck            web.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
168056c1fcf7774d4ee943fbda808e37840459502e20John Reck        }
168156c1fcf7774d4ee943fbda808e37840459502e20John Reck    }
168256c1fcf7774d4ee943fbda808e37840459502e20John Reck
168322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    void pause() {
168422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mMainView != null) {
168522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mMainView.onPause();
168622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (mSubView != null) {
168722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba                mSubView.onPause();
168822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
168922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
169022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
169122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
169222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    void putInForeground() {
16938ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        if (mInForeground) {
16948ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            return;
16958ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        }
169622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mInForeground = true;
169722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        resume();
16981461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        Activity activity = mWebViewController.getActivity();
16991461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        mMainView.setOnCreateContextMenuListener(activity);
170022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mSubView != null) {
17011461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            mSubView.setOnCreateContextMenuListener(activity);
170222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
170322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // Show the pending error dialog if the queue is not empty
170422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mQueuedErrors != null && mQueuedErrors.size() >  0) {
170522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            showError(mQueuedErrors.getFirst());
170622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
17071961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins        mWebViewController.bookmarkedStatusHasChanged(this);
170822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
170922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
171022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    void putInBackground() {
17118ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        if (!mInForeground) {
17128ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            return;
17138ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        }
171452be4785a258687055515117775d5bcb8bec1c12John Reck        capture();
171522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mInForeground = false;
171622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        pause();
171722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mMainView.setOnCreateContextMenuListener(null);
171822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mSubView != null) {
171922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mSubView.setOnCreateContextMenuListener(null);
172022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
172122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
172222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
17238233facddcc51865d612a919d450db6954aa48e3Michael Kolb    boolean inForeground() {
17248233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mInForeground;
17258233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
17268233facddcc51865d612a919d450db6954aa48e3Michael Kolb
172722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
172822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Return the top window of this tab; either the subwindow if it is not
172922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * null or the main window.
173022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @return The top window of this tab.
173122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
173222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    WebView getTopWindow() {
173322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mSubView != null) {
173422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            return mSubView;
173522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
173622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        return mMainView;
173722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
173822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
173922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
174022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Return the main window of this tab. Note: if a tab is freed in the
174122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * background, this can return null. It is only guaranteed to be
174222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * non-null for the current tab.
174322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @return The main WebView of this tab.
174422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
174522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    WebView getWebView() {
174622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        return mMainView;
174722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
174822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
1749a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb    void setViewContainer(View container) {
1750a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb        mContainer = container;
1751a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb    }
1752a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb
17538233facddcc51865d612a919d450db6954aa48e3Michael Kolb    View getViewContainer() {
17548233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mContainer;
17558233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
17568233facddcc51865d612a919d450db6954aa48e3Michael Kolb
175722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
1758f8bdfce9f2fc93bed2667694dc5b5ddf001d99d2Rob Tsuk     * Return whether private browsing is enabled for the main window of
1759f8bdfce9f2fc93bed2667694dc5b5ddf001d99d2Rob Tsuk     * this tab.
1760f8bdfce9f2fc93bed2667694dc5b5ddf001d99d2Rob Tsuk     * @return True if private browsing is enabled.
1761f8bdfce9f2fc93bed2667694dc5b5ddf001d99d2Rob Tsuk     */
17628233facddcc51865d612a919d450db6954aa48e3Michael Kolb    boolean isPrivateBrowsingEnabled() {
1763502a353bb815bee8bec6a60f3b741dc62e4729cdJohn Reck        return mCurrentState.mIncognito;
1764f8bdfce9f2fc93bed2667694dc5b5ddf001d99d2Rob Tsuk    }
1765f8bdfce9f2fc93bed2667694dc5b5ddf001d99d2Rob Tsuk
1766f8bdfce9f2fc93bed2667694dc5b5ddf001d99d2Rob Tsuk    /**
176722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Return the subwindow of this tab or null if there is no subwindow.
176822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @return The subwindow of this tab or null.
176922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
177022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    WebView getSubWebView() {
177122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        return mSubView;
177222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
177322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
17741514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb    void setSubWebView(WebView subView) {
17751514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb        mSubView = subView;
17761514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb    }
17771514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb
17788233facddcc51865d612a919d450db6954aa48e3Michael Kolb    View getSubViewContainer() {
17798233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mSubViewContainer;
17808233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
17818233facddcc51865d612a919d450db6954aa48e3Michael Kolb
17821514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb    void setSubViewContainer(View subViewContainer) {
17831514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb        mSubViewContainer = subViewContainer;
17841514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb    }
17851514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb
178622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
178722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @return The geolocation permissions prompt for this tab.
178822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
178922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    GeolocationPermissionsPrompt getGeolocationPermissionsPrompt() {
179050c241e6339c681c2427a57a31a357d35927c2acGrace Kloba        if (mGeolocationPermissionsPrompt == null) {
179150c241e6339c681c2427a57a31a357d35927c2acGrace Kloba            ViewStub stub = (ViewStub) mContainer
179250c241e6339c681c2427a57a31a357d35927c2acGrace Kloba                    .findViewById(R.id.geolocation_permissions_prompt);
179350c241e6339c681c2427a57a31a357d35927c2acGrace Kloba            mGeolocationPermissionsPrompt = (GeolocationPermissionsPrompt) stub
179450c241e6339c681c2427a57a31a357d35927c2acGrace Kloba                    .inflate();
179550c241e6339c681c2427a57a31a357d35927c2acGrace Kloba        }
179622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        return mGeolocationPermissionsPrompt;
179722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
179822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
179922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
180022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @return The application id string
180122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
180222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    String getAppId() {
180322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        return mAppId;
180422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
180522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
180622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
180722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Set the application id string
180822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @param id
180922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
181022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    void setAppId(String id) {
181122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mAppId = id;
181222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
181322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
1814e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb    boolean closeOnBack() {
1815e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb        return mCloseOnBack;
1816e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb    }
1817e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb
1818e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb    void setCloseOnBack(boolean close) {
1819e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb        mCloseOnBack = close;
1820e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb    }
1821e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb
182222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    String getUrl() {
1823324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck        return UrlUtils.filteredUrl(mCurrentState.mUrl);
182422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
182522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
182649a603c11b00b6e68a54e070abf4eb33eaddfa84John Reck    String getOriginalUrl() {
1827db22ec4ee014900988062d910bc810172a07df56John Reck        if (mCurrentState.mOriginalUrl == null) {
1828db22ec4ee014900988062d910bc810172a07df56John Reck            return getUrl();
182949a603c11b00b6e68a54e070abf4eb33eaddfa84John Reck        }
1830db22ec4ee014900988062d910bc810172a07df56John Reck        return UrlUtils.filteredUrl(mCurrentState.mOriginalUrl);
183149a603c11b00b6e68a54e070abf4eb33eaddfa84John Reck    }
183249a603c11b00b6e68a54e070abf4eb33eaddfa84John Reck
183322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
183430c714c853a4239e72ab1e238ce2a92472d06ab0John Reck     * Get the title of this tab.
183522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
183622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    String getTitle() {
183730c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        if (mCurrentState.mTitle == null && mInPageLoad) {
18381461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            return mContext.getString(R.string.title_bar_loading);
183922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
184030c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        return mCurrentState.mTitle;
184122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
184222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
184322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
184430c714c853a4239e72ab1e238ce2a92472d06ab0John Reck     * Get the favicon of this tab.
184522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
184622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    Bitmap getFavicon() {
18471cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        if (mCurrentState.mFavicon != null) {
18481cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            return mCurrentState.mFavicon;
18491cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
18501cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        return getDefaultFavicon(mContext);
185122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
185222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
1853e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck    public boolean isBookmarkedSite() {
1854e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck        return mCurrentState.mIsBookmarkedSite;
1855e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck    }
1856f8bdfce9f2fc93bed2667694dc5b5ddf001d99d2Rob Tsuk
185722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
185822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Return the tab's error console. Creates the console if createIfNEcessary
185922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * is true and we haven't already created the console.
186022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @param createIfNecessary Flag to indicate if the console should be
186122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     *            created if it has not been already.
186222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @return The tab's error console, or null if one has not been created and
186322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     *         createIfNecessary is false.
186422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
186522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    ErrorConsoleView getErrorConsole(boolean createIfNecessary) {
186622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (createIfNecessary && mErrorConsole == null) {
18671461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            mErrorConsole = new ErrorConsoleView(mContext);
186822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mErrorConsole.setWebView(mMainView);
186922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
187022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        return mErrorConsole;
187122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
187222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
187330c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    private void setLockIconType(LockIcon icon) {
187430c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mCurrentState.mLockIcon = icon;
187530c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mWebViewController.onUpdatedLockIcon(this);
187622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
187722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
187822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
187930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck     * @return The tab's lock icon type.
188022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
188130c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    LockIcon getLockIconType() {
188230c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        return mCurrentState.mLockIcon;
188322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
188422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
188530c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    int getLoadProgress() {
188630c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        if (mInPageLoad) {
188730c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            return mPageLoadProgress;
188830c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        }
188930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        return 100;
189022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
189122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
189222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
189322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * @return TRUE if onPageStarted is called while onPageFinished is not
189422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     *         called yet.
189522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
18968233facddcc51865d612a919d450db6954aa48e3Michael Kolb    boolean inPageLoad() {
18978233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mInPageLoad;
189822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
189922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
190022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // force mInLoad to be false. This should only be called before closing the
190122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    // tab to ensure BrowserActivity's pauseWebViewTimers() is called correctly.
19028233facddcc51865d612a919d450db6954aa48e3Michael Kolb    void clearInPageLoad() {
19038233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mInPageLoad = false;
190422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
190522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
190622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
19071cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck     * @return The Bundle with the tab's state if it can be saved, otherwise null
190822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
19091cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    public Bundle saveState() {
191022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // If the WebView is null it means we ran low on memory and we already
191122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // stored the saved state in mSavedState.
191222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mMainView == null) {
19131cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            return mSavedState;
191422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
19156c2e2f34718043f36488b4a94879dc2605aaac49John Reck
19166c2e2f34718043f36488b4a94879dc2605aaac49John Reck        if (TextUtils.isEmpty(mCurrentState.mUrl)) {
19171cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            return null;
191824f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck        }
191922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
192022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mSavedState = new Bundle();
19216c2e2f34718043f36488b4a94879dc2605aaac49John Reck        WebBackForwardList savedList = mMainView.saveState(mSavedState);
19226c2e2f34718043f36488b4a94879dc2605aaac49John Reck        if (savedList == null || savedList.getSize() == 0) {
19236c2e2f34718043f36488b4a94879dc2605aaac49John Reck            Log.w(LOGTAG, "Failed to save back/forward list for "
19246c2e2f34718043f36488b4a94879dc2605aaac49John Reck                    + mCurrentState.mUrl);
19256c2e2f34718043f36488b4a94879dc2605aaac49John Reck        }
192622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
1927c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        mSavedState.putLong(ID, mId);
192830c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mSavedState.putString(CURRURL, mCurrentState.mUrl);
192930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mSavedState.putString(CURRTITLE, mCurrentState.mTitle);
19301cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        mSavedState.putBoolean(INCOGNITO, mMainView.isPrivateBrowsingEnabled());
193122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mAppId != null) {
193222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mSavedState.putString(APPID, mAppId);
193322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
1934e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb        mSavedState.putBoolean(CLOSEFLAG, mCloseOnBack);
193522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // Remember the parent tab so the relationship can be restored.
1936c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        if (mParent != null) {
1937c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            mSavedState.putLong(PARENTTAB, mParent.mId);
193822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
1939b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck        mSavedState.putBoolean(USERAGENT,
1940b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck                mSettings.hasDesktopUseragent(getWebView()));
19411cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        return mSavedState;
194222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
194322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
194422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /*
194522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Restore the state of the tab.
194622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
19471cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private void restoreState(Bundle b) {
19481cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        mSavedState = b;
19491cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        if (mSavedState == null) {
19501cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            return;
195122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
195222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // Restore the internal state even if the WebView fails to restore.
195322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // This will maintain the app id, original url and close-on-exit values.
1954c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        mId = b.getLong(ID);
195522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mAppId = b.getString(APPID);
1956e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb        mCloseOnBack = b.getBoolean(CLOSEFLAG);
1957b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck        if (b.getBoolean(USERAGENT)
1958b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck                != mSettings.hasDesktopUseragent(getWebView())) {
1959b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck            mSettings.toggleDesktopUseragent(getWebView());
1960b0a86db3bfa39863977efd3bac5c9bf527d224aaJohn Reck        }
19611cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        String url = b.getString(CURRURL);
19621cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        String title = b.getString(CURRTITLE);
19631cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        boolean incognito = b.getBoolean(INCOGNITO);
19641cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        mCurrentState = new PageState(mContext, incognito, url, null);
19651cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        mCurrentState.mTitle = title;
19661cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        synchronized (Tab.this) {
19671cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            if (mCapture != null) {
19681cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                BackgroundHandler.execute(mLoadThumbnail);
19691cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
197022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        }
197122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
1972211ba54a3052f7e68bf8af035ea1ef4e9445130cLeon Scroggins III
19731961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins    public void updateBookmarkedStatus() {
1974e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck        mDataController.queryBookmarkStatus(getUrl(), mIsBookmarkCallback);
19751961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins    }
19761961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins
1977e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck    private DataController.OnQueryUrlIsBookmark mIsBookmarkCallback
1978e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck            = new DataController.OnQueryUrlIsBookmark() {
1979e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck        @Override
1980e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck        public void onQueryUrlIsBookmark(String url, boolean isBookmark) {
1981e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck            if (mCurrentState.mUrl.equals(url)) {
1982e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck                mCurrentState.mIsBookmarkedSite = isBookmark;
1983e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck                mWebViewController.bookmarkedStatusHasChanged(Tab.this);
19841961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins            }
1985e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck        }
1986e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck    };
19871acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
1988eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb    public Bitmap getScreenshot() {
19891cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        synchronized (Tab.this) {
19901cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            return mCapture;
19911cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
1992eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb    }
1993eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb
1994541f55a0178da7c09fb32aa5385effae031ea071John Reck    public boolean isSnapshot() {
1995541f55a0178da7c09fb32aa5385effae031ea071John Reck        return false;
1996541f55a0178da7c09fb32aa5385effae031ea071John Reck    }
1997541f55a0178da7c09fb32aa5385effae031ea071John Reck
1998d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck    public ContentValues createSnapshotValues() {
1999d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        if (mMainView == null) return null;
20008cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        ByteArrayOutputStream bos = new ByteArrayOutputStream();
20018cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        try {
20028cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck            GZIPOutputStream stream = new GZIPOutputStream(bos);
20038cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck            if (!mMainView.saveViewState(stream)) {
20048cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck                return null;
20058cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck            }
20068cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck            stream.flush();
20078cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck            stream.close();
20088cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        } catch (Exception e) {
20098cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck            Log.w(LOGTAG, "Failed to save view state", e);
2010541f55a0178da7c09fb32aa5385effae031ea071John Reck            return null;
2011541f55a0178da7c09fb32aa5385effae031ea071John Reck        }
20128cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        byte[] data = bos.toByteArray();
2013d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        ContentValues values = new ContentValues();
2014d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        values.put(Snapshots.TITLE, mCurrentState.mTitle);
2015d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        values.put(Snapshots.URL, mCurrentState.mUrl);
2016d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        values.put(Snapshots.VIEWSTATE, data);
2017d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        values.put(Snapshots.BACKGROUND, mMainView.getPageBackgroundColor());
20188cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        values.put(Snapshots.DATE_CREATED, System.currentTimeMillis());
20198cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        values.put(Snapshots.FAVICON, compressBitmap(getFavicon()));
20208cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        Bitmap screenshot = Controller.createScreenshot(mMainView,
20218cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck                Controller.getDesiredThumbnailWidth(mContext),
20228cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck                Controller.getDesiredThumbnailHeight(mContext));
20238cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        values.put(Snapshots.THUMBNAIL, compressBitmap(screenshot));
2024d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        return values;
2025541f55a0178da7c09fb32aa5385effae031ea071John Reck    }
2026541f55a0178da7c09fb32aa5385effae031ea071John Reck
20278cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck    public byte[] compressBitmap(Bitmap bitmap) {
20288cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        if (bitmap == null) {
20298cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck            return null;
20308cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        }
20318cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        ByteArrayOutputStream stream = new ByteArrayOutputStream();
20328cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        bitmap.compress(CompressFormat.PNG, 100, stream);
20338cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck        return stream.toByteArray();
20348cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck    }
20358cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck
203626b183292dc087b16af10f482744c3bb30e1f163John Reck    public void loadUrl(String url, Map<String, String> headers) {
203726b183292dc087b16af10f482744c3bb30e1f163John Reck        if (mMainView != null) {
20381461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            mCurrentState = new PageState(mContext, false, url, null);
203926b183292dc087b16af10f482744c3bb30e1f163John Reck            mWebViewController.onPageStarted(this, mMainView, null);
204026b183292dc087b16af10f482744c3bb30e1f163John Reck            mMainView.loadUrl(url, headers);
204126b183292dc087b16af10f482744c3bb30e1f163John Reck        }
204226b183292dc087b16af10f482744c3bb30e1f163John Reck    }
204326b183292dc087b16af10f482744c3bb30e1f163John Reck
20449ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb    protected void capture() {
20459ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        if (mMainView == null || mCapture == null) return;
20469ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        Canvas c = new Canvas(mCapture);
20479ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        final int left = mMainView.getScrollX();
20489ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        final int top = mMainView.getScrollY() + mMainView.getVisibleTitleHeight();
20499ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        c.translate(-left, -top);
20509ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        float scale = mCaptureWidth / (float) mMainView.getWidth();
20519ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        c.scale(scale, scale, left, top);
20528ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        if (mMainView instanceof BrowserWebView) {
20538ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            ((BrowserWebView)mMainView).drawContent(c);
20548ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        } else {
20558ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            mMainView.draw(c);
20568ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        }
205743cfe8a4521b5c153055fbfa181940bc56bb3b06Dianne Hackborn        c.setBitmap(null);
20588ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        mHandler.removeMessages(MSG_CAPTURE);
20591cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        persistThumbnail();
20608ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        TabControl tc = mWebViewController.getTabControl();
20618ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        if (tc != null) {
20628ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            OnThumbnailUpdatedListener updateListener
20638ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck                    = tc.getOnThumbnailUpdatedListener();
20648ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            if (updateListener != null) {
20658ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck                updateListener.onThumbnailUpdated(this);
20668ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            }
20678ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        }
20689ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb    }
20699ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb
20709ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb    @Override
20719ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb    public void onNewPicture(WebView view, Picture picture) {
20729ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        //update screenshot
20731cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        postCapture();
20741cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
20751cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
20761cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private void postCapture() {
20779ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        if (!mHandler.hasMessages(MSG_CAPTURE)) {
20789ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb            mHandler.sendEmptyMessageDelayed(MSG_CAPTURE, CAPTURE_DELAY);
20799ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb        }
20809ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb    }
20819ef259af433edc5aeb11b5d5d94dc9acc697c61eMichael Kolb
2082ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck    public boolean canGoBack() {
2083ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck        return mMainView != null ? mMainView.canGoBack() : false;
2084ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck    }
2085ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck
2086ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck    public boolean canGoForward() {
2087ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck        return mMainView != null ? mMainView.canGoForward() : false;
2088ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck    }
2089ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck
2090ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck    public void goBack() {
2091ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck        if (mMainView != null) {
2092ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck            mMainView.goBack();
2093ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck        }
2094ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck    }
2095ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck
2096ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck    public void goForward() {
2097ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck        if (mMainView != null) {
2098ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck            mMainView.goForward();
2099ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck        }
2100ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck    }
2101ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck
21021dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood    /**
21031dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood     * Causes the tab back/forward stack to be cleared once, if the given URL is the next URL
21041dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood     * to be added to the stack.
21051dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood     *
21061dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood     * This is used to ensure that preloaded URLs that are not subsequently seen by the user do
21071dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood     * not appear in the back stack.
21081dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood     */
21091dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood    public void clearBackStackWhenItemAdded(String urlToMatch) {
21101dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood        mClearHistoryMatchUrl = urlToMatch;
21111dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood    }
21121dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood
21131cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    protected void persistThumbnail() {
21141cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        BackgroundHandler.execute(mSaveThumbnail);
21151cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
21161cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
21171cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    protected void deleteThumbnail() {
21181cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        BackgroundHandler.execute(mDeleteThumbnail);
21191cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
21201cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
21211cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private void updateCaptureFromBlob(byte[] blob) {
21221cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        synchronized (Tab.this) {
21231cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            if (mCapture == null) {
21241cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                return;
21251cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
2126bd4c00a61a44637e04efeb837da490a2b51b11c1Michael Kolb            ByteBuffer buffer = ByteBuffer.wrap(blob);
2127d837a11b0ada5a4577af954e4cc0d33047f84ce8Michael Kolb            try {
2128d837a11b0ada5a4577af954e4cc0d33047f84ce8Michael Kolb                mCapture.copyPixelsFromBuffer(buffer);
2129d837a11b0ada5a4577af954e4cc0d33047f84ce8Michael Kolb            } catch (RuntimeException rex) {
2130d837a11b0ada5a4577af954e4cc0d33047f84ce8Michael Kolb                Log.e(LOGTAG, "Load capture has mismatched sizes; buffer: "
2131d837a11b0ada5a4577af954e4cc0d33047f84ce8Michael Kolb                        + buffer.capacity() + " blob: " + blob.length
2132d837a11b0ada5a4577af954e4cc0d33047f84ce8Michael Kolb                        + "capture: " + mCapture.getByteCount());
2133d837a11b0ada5a4577af954e4cc0d33047f84ce8Michael Kolb                throw rex;
2134bd4c00a61a44637e04efeb837da490a2b51b11c1Michael Kolb            }
21351cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
21361cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
21371cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
21381cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private byte[] getCaptureBlob() {
21391cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        synchronized (Tab.this) {
21401cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            if (mCapture == null) {
21411cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                return null;
21421cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
21431cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            ByteBuffer buffer = ByteBuffer.allocate(mCapture.getByteCount());
21441cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            mCapture.copyPixelsToBuffer(buffer);
21451cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            return buffer.array();
21461cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
21471cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
21481cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
21491cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private Runnable mSaveThumbnail = new Runnable() {
21501cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
21511cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        @Override
21521cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        public void run() {
21531cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            byte[] blob = getCaptureBlob();
21541cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            if (blob == null) {
21551cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                return;
21561cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
21571cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            ContentResolver cr = mContext.getContentResolver();
21581cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            ContentValues values = new ContentValues();
21591cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            values.put(Thumbnails._ID, mId);
21601cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            values.put(Thumbnails.THUMBNAIL, blob);
21611cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            cr.insert(Thumbnails.CONTENT_URI, values);
21621cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
21631cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    };
21641cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
21651cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private Runnable mDeleteThumbnail = new Runnable() {
21661cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
21671cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        @Override
21681cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        public void run() {
21691cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            ContentResolver cr = mContext.getContentResolver();
21701cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            try {
21711cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                cr.delete(ContentUris.withAppendedId(Thumbnails.CONTENT_URI, mId),
21721cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                        null, null);
21731cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            } catch (Throwable t) {}
21741cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
21751cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    };
21761cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
21771cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private Runnable mLoadThumbnail = new Runnable() {
21781cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
21791cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        @Override
21801cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        public void run() {
21811cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            ContentResolver cr = mContext.getContentResolver();
21821cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            Cursor c = null;
21831cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            try {
21841cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                Uri uri = ContentUris.withAppendedId(Thumbnails.CONTENT_URI, mId);
21851cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                c = cr.query(uri, new String[] {Thumbnails._ID,
21861cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                        Thumbnails.THUMBNAIL}, null, null, null);
21871cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                if (c.moveToFirst()) {
21881cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    byte[] data = c.getBlob(1);
21891cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    if (data != null && data.length > 0) {
21901cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                        updateCaptureFromBlob(data);
21911cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    }
21921cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                }
21931cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            } finally {
21941cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                if (c != null) {
21951cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    c.close();
21961cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                }
21971cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
21981cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
21991cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    };
22001cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
220152be4785a258687055515117775d5bcb8bec1c12John Reck    @Override
220252be4785a258687055515117775d5bcb8bec1c12John Reck    public String toString() {
220352be4785a258687055515117775d5bcb8bec1c12John Reck        StringBuilder builder = new StringBuilder(100);
220452be4785a258687055515117775d5bcb8bec1c12John Reck        builder.append(mId);
220552be4785a258687055515117775d5bcb8bec1c12John Reck        builder.append(") has parent: ");
220652be4785a258687055515117775d5bcb8bec1c12John Reck        if (getParent() != null) {
220752be4785a258687055515117775d5bcb8bec1c12John Reck            builder.append("true[");
220852be4785a258687055515117775d5bcb8bec1c12John Reck            builder.append(getParent().getId());
220952be4785a258687055515117775d5bcb8bec1c12John Reck            builder.append("]");
221052be4785a258687055515117775d5bcb8bec1c12John Reck        } else {
221152be4785a258687055515117775d5bcb8bec1c12John Reck            builder.append("false");
221252be4785a258687055515117775d5bcb8bec1c12John Reck        }
221352be4785a258687055515117775d5bcb8bec1c12John Reck        builder.append(", incog: ");
221452be4785a258687055515117775d5bcb8bec1c12John Reck        builder.append(isPrivateBrowsingEnabled());
221552be4785a258687055515117775d5bcb8bec1c12John Reck        if (!isPrivateBrowsingEnabled()) {
221652be4785a258687055515117775d5bcb8bec1c12John Reck            builder.append(", title: ");
221752be4785a258687055515117775d5bcb8bec1c12John Reck            builder.append(getTitle());
221852be4785a258687055515117775d5bcb8bec1c12John Reck            builder.append(", url: ");
221952be4785a258687055515117775d5bcb8bec1c12John Reck            builder.append(getUrl());
222052be4785a258687055515117775d5bcb8bec1c12John Reck        }
222152be4785a258687055515117775d5bcb8bec1c12John Reck        return builder.toString();
222252be4785a258687055515117775d5bcb8bec1c12John Reck    }
222352be4785a258687055515117775d5bcb8bec1c12John Reck
222422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba}
2225