18233facddcc51865d612a919d450db6954aa48e3Michael Kolb/*
28233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Copyright (C) 2010 The Android Open Source Project
38233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
48233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
58233facddcc51865d612a919d450db6954aa48e3Michael Kolb * you may not use this file except in compliance with the License.
68233facddcc51865d612a919d450db6954aa48e3Michael Kolb * You may obtain a copy of the License at
78233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
88233facddcc51865d612a919d450db6954aa48e3Michael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
98233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
108233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Unless required by applicable law or agreed to in writing, software
118233facddcc51865d612a919d450db6954aa48e3Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
128233facddcc51865d612a919d450db6954aa48e3Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138233facddcc51865d612a919d450db6954aa48e3Michael Kolb * See the License for the specific language governing permissions and
148233facddcc51865d612a919d450db6954aa48e3Michael Kolb * limitations under the License.
158233facddcc51865d612a919d450db6954aa48e3Michael Kolb */
168233facddcc51865d612a919d450db6954aa48e3Michael Kolb
178233facddcc51865d612a919d450db6954aa48e3Michael Kolbpackage com.android.browser;
188233facddcc51865d612a919d450db6954aa48e3Michael Kolb
198233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.Activity;
2068234a9351dfca2e68769de46e60d22ec2f03818John Reckimport android.app.Dialog;
218233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.DownloadManager;
2268234a9351dfca2e68769de46e60d22ec2f03818John Reckimport android.app.ProgressDialog;
238233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.ClipboardManager;
248233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.ContentResolver;
25d8c7452a7d8975a2d60414c5a33842b4a743e631John Reckimport android.content.ContentUris;
268233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.ContentValues;
278233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.Context;
2868234a9351dfca2e68769de46e60d22ec2f03818John Reckimport android.content.DialogInterface;
2968234a9351dfca2e68769de46e60d22ec2f03818John Reckimport android.content.DialogInterface.OnCancelListener;
308233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.Intent;
318233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.pm.PackageManager;
328233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.pm.ResolveInfo;
338233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.res.Configuration;
3430b065e9c311ab1a8973caeb85a0861c8802b043John Reckimport android.content.res.TypedArray;
351961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scrogginsimport android.database.ContentObserver;
368233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.database.Cursor;
378233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.database.sqlite.SQLiteDatabase;
38561d1954d552fe1beff6e1ec7d22147935b32c0fMattias Nilssonimport android.database.sqlite.SQLiteException;
398233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.graphics.Bitmap;
408233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.graphics.Canvas;
418233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.net.Uri;
428233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.net.http.SslError;
438233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.os.AsyncTask;
448233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.os.Bundle;
45387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mountimport android.os.Environment;
468233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.os.Handler;
478233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.os.Message;
488233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.os.PowerManager;
498233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.os.PowerManager.WakeLock;
508029a777106fa6fb911ee1d58402b0de768a583aBen Murdochimport android.preference.PreferenceActivity;
518233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.provider.Browser;
528233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.provider.BrowserContract;
538233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.provider.BrowserContract.Images;
548233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.provider.ContactsContract;
558233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.provider.ContactsContract.Intents.Insert;
560b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolbimport android.speech.RecognizerIntent;
578233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.text.TextUtils;
588233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.util.Log;
59a00cbbde0b77a3e1eef5691a7adb17edd5d8ab9eJohn Reckimport android.util.Patterns;
608233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.ActionMode;
618233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.ContextMenu;
628233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.ContextMenu.ContextMenuInfo;
638233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.Gravity;
648233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.KeyEvent;
658233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.Menu;
668233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.MenuInflater;
678233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.MenuItem;
688233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.MenuItem.OnMenuItemClickListener;
69c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolbimport android.view.MotionEvent;
708233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.View;
718233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.CookieManager;
728233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.CookieSyncManager;
738233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.HttpAuthHandler;
74387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mountimport android.webkit.MimeTypeMap;
758233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.SslErrorHandler;
768233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.ValueCallback;
778233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.WebChromeClient;
788233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.WebIconDatabase;
798233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.WebSettings;
808233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.WebView;
814d2fcaba7fb8eb1723943ac9a10e76d509330bd1Jonathan Dixonimport android.webkit.WebViewClassic;
82ac993841b3f810dd55a985141c574d4dfebd8c1aLeon Scrogginsimport android.widget.Toast;
838233facddcc51865d612a919d450db6954aa48e3Michael Kolb
844bd767d2f4ce166a44687170c6af18e242447205Michael Kolbimport com.android.browser.IntentHandler.UrlData;
852bc8042224be51966d748b870768ec1b376a1621John Reckimport com.android.browser.UI.ComboViews;
861cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reckimport com.android.browser.provider.BrowserProvider2.Thumbnails;
878cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reckimport com.android.browser.provider.SnapshotProvider.Snapshots;
884bd767d2f4ce166a44687170c6af18e242447205Michael Kolb
898233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport java.io.ByteArrayOutputStream;
90387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mountimport java.io.File;
91387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mountimport java.io.FileOutputStream;
92387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mountimport java.io.IOException;
938233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport java.net.URLEncoder;
94387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mountimport java.text.DateFormat;
95387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mountimport java.text.SimpleDateFormat;
961cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reckimport java.util.ArrayList;
978233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport java.util.Calendar;
98387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mountimport java.util.Date;
998233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport java.util.HashMap;
1001bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolbimport java.util.List;
101aa67618bf9711a45fff7d0bdf93c9d3d29bf5817Johan Redestigimport java.util.Locale;
10226b183292dc087b16af10f482744c3bb30e1f163John Reckimport java.util.Map;
1038233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1048233facddcc51865d612a919d450db6954aa48e3Michael Kolb/**
1058233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Controller for browser
1068233facddcc51865d612a919d450db6954aa48e3Michael Kolb */
1078233facddcc51865d612a919d450db6954aa48e3Michael Kolbpublic class Controller
1089c35b9c41d756d59f5356edd2e08432e01f351f6John Reck        implements WebViewController, UiController, ActivityController {
1098233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1108233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private static final String LOGTAG = "Controller";
111cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb    private static final String SEND_APP_ID_EXTRA =
112cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb        "android.speech.extras.SEND_APPLICATION_ID_EXTRA";
113a4261fd53fef2b311e733fcfee4be3a9967ad967Michael Kolb    private static final String INCOGNITO_URI = "browser:incognito";
114cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb
1158233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1168233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // public message ids
1178233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public final static int LOAD_URL = 1001;
1188233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public final static int STOP_LOAD = 1002;
1198233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1208233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // Message Ids
1218233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private static final int FOCUS_NODE_HREF = 102;
1228233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private static final int RELEASE_WAKELOCK = 107;
1238233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1248233facddcc51865d612a919d450db6954aa48e3Michael Kolb    static final int UPDATE_BOOKMARK_THUMBNAIL = 108;
1258233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1268233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private static final int OPEN_BOOKMARKS = 201;
1278233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1288233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private static final int EMPTY_MENU = -1;
1298233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1308233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // activity requestCode
131d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck    final static int COMBO_VIEW = 1;
1328233facddcc51865d612a919d450db6954aa48e3Michael Kolb    final static int PREFERENCES_PAGE = 3;
1338233facddcc51865d612a919d450db6954aa48e3Michael Kolb    final static int FILE_SELECTED = 4;
1348029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch    final static int AUTOFILL_SETUP = 5;
1350b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb    final static int VOICE_RESULT = 6;
1368029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch
1378233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private final static int WAKELOCK_TIMEOUT = 5 * 60 * 1000; // 5 minutes
1388233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1398233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // As the ids are dynamically created, we can't guarantee that they will
1408233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // be in sequence, so this static array maps ids to a window number.
1418233facddcc51865d612a919d450db6954aa48e3Michael Kolb    final static private int[] WINDOW_SHORTCUT_ID_ARRAY =
1428233facddcc51865d612a919d450db6954aa48e3Michael Kolb    { R.id.window_one_menu_id, R.id.window_two_menu_id,
1438233facddcc51865d612a919d450db6954aa48e3Michael Kolb      R.id.window_three_menu_id, R.id.window_four_menu_id,
1448233facddcc51865d612a919d450db6954aa48e3Michael Kolb      R.id.window_five_menu_id, R.id.window_six_menu_id,
1458233facddcc51865d612a919d450db6954aa48e3Michael Kolb      R.id.window_seven_menu_id, R.id.window_eight_menu_id };
1468233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1478233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // "source" parameter for Google search through search key
1488233facddcc51865d612a919d450db6954aa48e3Michael Kolb    final static String GOOGLE_SEARCH_SOURCE_SEARCHKEY = "browser-key";
1498233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // "source" parameter for Google search through simplily type
1508233facddcc51865d612a919d450db6954aa48e3Michael Kolb    final static String GOOGLE_SEARCH_SOURCE_TYPE = "browser-type";
1518233facddcc51865d612a919d450db6954aa48e3Michael Kolb
152387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount    // "no-crash-recovery" parameter in intent to suppress crash recovery
1539e78f51d14b9a16d645b754e073f549a5891db26Guang Zhu    final static String NO_CRASH_RECOVERY = "no-crash-recovery";
1549e78f51d14b9a16d645b754e073f549a5891db26Guang Zhu
155d7dd9b2ecb12da278c053291b684b885ee574301John Reck    // A bitmap that is re-used in createScreenshot as scratch space
156d7dd9b2ecb12da278c053291b684b885ee574301John Reck    private static Bitmap sThumbnailBitmap;
157d7dd9b2ecb12da278c053291b684b885ee574301John Reck
1588233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Activity mActivity;
1598233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private UI mUi;
1608233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private TabControl mTabControl;
1618233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private BrowserSettings mSettings;
1628233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private WebViewFactory mFactory;
1638233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1648233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private WakeLock mWakeLock;
1658233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1668233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private UrlHandler mUrlHandler;
1678233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private UploadHandler mUploadHandler;
1688233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private IntentHandler mIntentHandler;
1698233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private PageDialogsHandler mPageDialogsHandler;
1708233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private NetworkStateHandler mNetworkHandler;
1718233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1728029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch    private Message mAutoFillSetupMessage;
1738029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch
1748233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private boolean mShouldShowErrorConsole;
1758233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1768233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private SystemAllowGeolocationOrigins mSystemAllowGeolocationOrigins;
1778233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1788233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // FIXME, temp address onPrepareMenu performance problem.
1798233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // When we move everything out of view, we should rewrite this.
1808233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private int mCurrentMenuState = 0;
1818233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private int mMenuState = R.id.MAIN_MENU;
1828233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private int mOldMenuState = EMPTY_MENU;
1838233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Menu mCachedMenu;
1848233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1858233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private boolean mMenuIsDown;
1868233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1878233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // For select and find, we keep track of the ActionMode so that
1888233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // finish() can be called as desired.
1898233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private ActionMode mActionMode;
1908233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1918233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
1928233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Only meaningful when mOptionsMenuOpen is true.  This variable keeps track
1938233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * of whether the configuration has changed.  The first onMenuOpened call
1948233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * after a configuration change is simply a reopening of the same menu
1958233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * (i.e. mIconView did not change).
1968233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
1978233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private boolean mConfigChanged;
1988233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1998233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
2008233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Keeps track of whether the options menu is open. This is important in
2018233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * determining whether to show or hide the title bar overlay
2028233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
2038233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private boolean mOptionsMenuOpen;
2048233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2058233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
2068233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Whether or not the options menu is in its bigger, popup menu form. When
2078233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * true, we want the title bar overlay to be gone. When false, we do not.
2088233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Only meaningful if mOptionsMenuOpen is true.
2098233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
2108233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private boolean mExtendedMenuOpen;
2118233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2128233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private boolean mActivityPaused = true;
2138233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private boolean mLoadStopped;
2148233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2158233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Handler mHandler;
2161961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins    // Checks to see when the bookmarks database has changed, and updates the
2171961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins    // Tabs' notion of whether they represent bookmarked sites.
2181961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins    private ContentObserver mBookmarksObserver;
219847b532045e3cb117a847ebb956c9919401f332dJohn Reck    private CrashRecoveryHandler mCrashRecoveryHandler;
2208233facddcc51865d612a919d450db6954aa48e3Michael Kolb
221c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    private boolean mBlockEvents;
222c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb
2230b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb    private String mVoiceResult;
2240b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb
2253636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount    public Controller(Activity browser) {
2268233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActivity = browser;
2278233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSettings = BrowserSettings.getInstance();
2288233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mTabControl = new TabControl(this);
2298233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSettings.setController(this);
230378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck        mCrashRecoveryHandler = CrashRecoveryHandler.initialize(this);
2313636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        mCrashRecoveryHandler.preloadCrashState();
2321461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        mFactory = new BrowserWebViewFactory(browser);
2338233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2348233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUrlHandler = new UrlHandler(this);
2358233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mIntentHandler = new IntentHandler(mActivity, this);
2368233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mPageDialogsHandler = new PageDialogsHandler(mActivity, this);
2378233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2388233facddcc51865d612a919d450db6954aa48e3Michael Kolb        startHandler();
2391961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins        mBookmarksObserver = new ContentObserver(mHandler) {
2401961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins            @Override
2411961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins            public void onChange(boolean selfChange) {
2421961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins                int size = mTabControl.getTabCount();
2431961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins                for (int i = 0; i < size; i++) {
2441961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins                    mTabControl.getTab(i).updateBookmarkedStatus();
2451961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins                }
2461961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins            }
2471961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins
2481961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins        };
2491961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins        browser.getContentResolver().registerContentObserver(
2501961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins                BrowserContract.Bookmarks.CONTENT_URI, true, mBookmarksObserver);
2518233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2528233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mNetworkHandler = new NetworkStateHandler(mActivity, this);
2538233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Start watching the default geolocation permissions
2548233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSystemAllowGeolocationOrigins =
2558233facddcc51865d612a919d450db6954aa48e3Michael Kolb                new SystemAllowGeolocationOrigins(mActivity.getApplicationContext());
2568233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSystemAllowGeolocationOrigins.start();
2578233facddcc51865d612a919d450db6954aa48e3Michael Kolb
258af262e703038106aef2e5187d120617836ffe9ceJohn Reck        openIconDatabase();
2598233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
2608233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2619c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
2629c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public void start(final Intent intent) {
263e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon        if (BrowserWebView.isClassic()) WebViewClassic.setShouldMonitorWebCoreThread();
2643636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        // mCrashRecoverHandler has any previously saved state.
2653636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        mCrashRecoveryHandler.startRecovery(intent);
266847b532045e3cb117a847ebb956c9919401f332dJohn Reck    }
267847b532045e3cb117a847ebb956c9919401f332dJohn Reck
2683636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount    void doStart(final Bundle icicle, final Intent intent) {
2698233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Unless the last browser usage was within 24 hours, destroy any
2708233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // remaining incognito tabs.
2718233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2728233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Calendar lastActiveDate = icicle != null ?
2738233facddcc51865d612a919d450db6954aa48e3Michael Kolb                (Calendar) icicle.getSerializable("lastActiveDate") : null;
2748233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Calendar today = Calendar.getInstance();
2758233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Calendar yesterday = Calendar.getInstance();
2768233facddcc51865d612a919d450db6954aa48e3Michael Kolb        yesterday.add(Calendar.DATE, -1);
2778233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2787d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott        final boolean restoreIncognitoTabs = !(lastActiveDate == null
2798233facddcc51865d612a919d450db6954aa48e3Michael Kolb            || lastActiveDate.before(yesterday)
2801bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb            || lastActiveDate.after(today));
2818233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2827d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott        // Find out if we will restore any state and remember the tab.
283c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        final long currentTabId =
2847d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                mTabControl.canRestoreState(icicle, restoreIncognitoTabs);
2857d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott
286c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        if (currentTabId == -1) {
2877d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott            // Not able to restore so we go ahead and clear session cookies.  We
2887d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott            // must do this before trying to login the user as we don't want to
2897d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott            // clear any session cookies set during login.
2903a4e8091e246e42ebd0add6342eb4eaed88012a3Kristian Monsen            CookieManager.getInstance().removeSessionCookie();
2917d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott        }
2927d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott
293d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott        GoogleAccountLogin.startLoginIfNeeded(mActivity,
2947d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                new Runnable() {
2957d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                    @Override public void run() {
2963636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                        onPreloginFinished(icicle, intent, currentTabId,
2973636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                                restoreIncognitoTabs);
2987d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                    }
2997d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                });
3007d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott    }
3012cd9701de79c8e4e37971498b91ff2530bc58694Kristian Monsen
302c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    private void onPreloginFinished(Bundle icicle, Intent intent, long currentTabId,
3033636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount            boolean restoreIncognitoTabs) {
304c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        if (currentTabId == -1) {
3051cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            BackgroundHandler.execute(new PruneThumbnails(mActivity, null));
3063636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount            if (intent == null) {
3073636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                // This won't happen under common scenarios. The icicle is
3083636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                // not null, but there aren't any tabs to restore.
3093636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                openTabToHomePage();
3107bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb            } else {
3113636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                final Bundle extra = intent.getExtras();
3123636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                // Create an initial tab.
3133636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                // If the intent is ACTION_VIEW and data is not null, the Browser is
3143636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                // invoked to view the content by another application. In this case,
3153636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                // the tab will be close when exit.
3163636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                UrlData urlData = IntentHandler.getUrlDataFromIntent(intent);
3173636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                Tab t = null;
3183636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                if (urlData.isEmpty()) {
3193636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                    t = openTabToHomePage();
3203636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                } else {
3213636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                    t = openTab(urlData);
3223636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                }
3233636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                if (t != null) {
3243636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                    t.setAppId(intent.getStringExtra(Browser.EXTRA_APPLICATION_ID));
3253636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                }
3263636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                WebView webView = t.getWebView();
3273636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                if (extra != null) {
3283636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                    int scale = extra.getInt(Browser.INITIAL_ZOOM_LEVEL, 0);
3293636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                    if (scale > 0 && scale <= 1000) {
3303636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                        webView.setInitialScale(scale);
3313636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                    }
3328233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
3338233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
334d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck            mUi.updateTabs(mTabControl.getTabs());
3358233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else {
336c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            mTabControl.restoreState(icicle, currentTabId, restoreIncognitoTabs,
3377d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                    mUi.needsRestoreAllTabs());
3381cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            List<Tab> tabs = mTabControl.getTabs();
3391cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            ArrayList<Long> restoredTabs = new ArrayList<Long>(tabs.size());
3401cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            for (Tab t : tabs) {
3411cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                restoredTabs.add(t.getId());
3421cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
3431cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            BackgroundHandler.execute(new PruneThumbnails(mActivity, restoredTabs));
34452be4785a258687055515117775d5bcb8bec1c12John Reck            if (tabs.size() == 0) {
34552be4785a258687055515117775d5bcb8bec1c12John Reck                openTabToHomePage();
34652be4785a258687055515117775d5bcb8bec1c12John Reck            }
3471cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            mUi.updateTabs(tabs);
3488233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // TabControl.restoreState() will create a new tab even if
3498233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // restoring the state fails.
3508233facddcc51865d612a919d450db6954aa48e3Michael Kolb            setActiveTab(mTabControl.getCurrentTab());
3513636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount            // Intent is non-null when framework thinks the browser should be
3523636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount            // launching with a new intent (icicle is null).
3533636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount            if (intent != null) {
3549dd4a4129b91343b7b21e2389519ff1a795a447dJohn Reck                mIntentHandler.onNewIntent(intent);
3559dd4a4129b91343b7b21e2389519ff1a795a447dJohn Reck            }
3568233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
3578233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Read JavaScript flags if it exists.
35835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        String jsFlags = getSettings().getJsEngineFlags();
359e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon        if (jsFlags.trim().length() != 0 && BrowserWebView.isClassic()) {
3604d2fcaba7fb8eb1723943ac9a10e76d509330bd1Jonathan Dixon            WebViewClassic.fromWebView(getCurrentWebView()).setJsFlags(jsFlags);
3618233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
3623636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        if (intent != null
3633636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount                && BrowserActivity.ACTION_SHOW_BOOKMARKS.equals(intent.getAction())) {
364315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb            bookmarksOrHistoryPicker(ComboViews.Bookmarks);
365439c9a58765aa6aab95d55422ee61ea8360e912dJohn Reck        }
3668233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
3678233facddcc51865d612a919d450db6954aa48e3Michael Kolb
3681cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    private static class PruneThumbnails implements Runnable {
3691cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        private Context mContext;
3701cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        private List<Long> mIds;
3711cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
3721cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        PruneThumbnails(Context context, List<Long> preserveIds) {
3731cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            mContext = context.getApplicationContext();
3741cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            mIds = preserveIds;
3751cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
3761cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
3771cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        @Override
3781cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        public void run() {
3791cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            ContentResolver cr = mContext.getContentResolver();
3801cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            if (mIds == null || mIds.size() == 0) {
3811cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                cr.delete(Thumbnails.CONTENT_URI, null, null);
3821cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            } else {
3831cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                int length = mIds.size();
3841cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                StringBuilder where = new StringBuilder();
3851cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                where.append(Thumbnails._ID);
3861cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                where.append(" not in (");
3871cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                for (int i = 0; i < length; i++) {
3881cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    where.append(mIds.get(i));
3891cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    if (i < (length - 1)) {
3901cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                        where.append(",");
3911cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                    }
3921cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                }
3931cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                where.append(")");
3941cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                cr.delete(Thumbnails.CONTENT_URI, where.toString(), null);
3951cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            }
3961cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        }
3971cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
3981cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
3991cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
4001514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb    @Override
4011514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb    public WebViewFactory getWebViewFactory() {
4028233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mFactory;
4038233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
4048233facddcc51865d612a919d450db6954aa48e3Michael Kolb
4058233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
406a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb    public void onSetWebView(Tab tab, WebView view) {
407a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb        mUi.onSetWebView(tab, view);
408a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb    }
409a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb
410a713ec8cc9da6c0c8078cd297c6240eb8bf01bbbMichael Kolb    @Override
4111514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb    public void createSubWindow(Tab tab) {
4121514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb        endActionMode();
4131514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb        WebView mainView = tab.getWebView();
4141514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb        WebView subView = mFactory.createWebView((mainView == null)
4151514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb                ? false
4161514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb                : mainView.isPrivateBrowsingEnabled());
4171514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb        mUi.createSubWindow(tab, subView);
4181514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb    }
4191514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb
4201514bb7ed5656316a8dac966cee21653f3c59affMichael Kolb    @Override
4211461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb    public Context getContext() {
4221461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        return mActivity;
4231461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb    }
4241461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb
4251461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb    @Override
4268233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public Activity getActivity() {
4278233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mActivity;
4288233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
4298233facddcc51865d612a919d450db6954aa48e3Michael Kolb
4308233facddcc51865d612a919d450db6954aa48e3Michael Kolb    void setUi(UI ui) {
4318233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi = ui;
4328233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
4338233facddcc51865d612a919d450db6954aa48e3Michael Kolb
434af63dbadb04a963f3513bff2f6ec5f34d31c24d6Michael Kolb    @Override
435af63dbadb04a963f3513bff2f6ec5f34d31c24d6Michael Kolb    public BrowserSettings getSettings() {
4368233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mSettings;
4378233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
4388233facddcc51865d612a919d450db6954aa48e3Michael Kolb
4398233facddcc51865d612a919d450db6954aa48e3Michael Kolb    IntentHandler getIntentHandler() {
4408233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mIntentHandler;
4418233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
4428233facddcc51865d612a919d450db6954aa48e3Michael Kolb
4438233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
4448233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public UI getUi() {
4458233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mUi;
4468233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
4478233facddcc51865d612a919d450db6954aa48e3Michael Kolb
4488233facddcc51865d612a919d450db6954aa48e3Michael Kolb    int getMaxTabs() {
4498233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mActivity.getResources().getInteger(R.integer.max_tabs);
4508233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
4518233facddcc51865d612a919d450db6954aa48e3Michael Kolb
4528233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
4538233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public TabControl getTabControl() {
4548233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mTabControl;
4558233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
4568233facddcc51865d612a919d450db6954aa48e3Michael Kolb
4571bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb    @Override
4581bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb    public List<Tab> getTabs() {
4591bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        return mTabControl.getTabs();
4601bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb    }
4611bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb
462af262e703038106aef2e5187d120617836ffe9ceJohn Reck    // Open the icon database.
463af262e703038106aef2e5187d120617836ffe9ceJohn Reck    private void openIconDatabase() {
464af262e703038106aef2e5187d120617836ffe9ceJohn Reck        // We have to call getInstance on the UI thread
465af262e703038106aef2e5187d120617836ffe9ceJohn Reck        final WebIconDatabase instance = WebIconDatabase.getInstance();
466af262e703038106aef2e5187d120617836ffe9ceJohn Reck        BackgroundHandler.execute(new Runnable() {
4679446b9351cec1ffddd211ba02d985b91853f8398Ben Murdoch
468af262e703038106aef2e5187d120617836ffe9ceJohn Reck            @Override
469af262e703038106aef2e5187d120617836ffe9ceJohn Reck            public void run() {
470af262e703038106aef2e5187d120617836ffe9ceJohn Reck                instance.open(mActivity.getDir("icons", 0).getPath());
4718233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
472af262e703038106aef2e5187d120617836ffe9ceJohn Reck        });
4738233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
4748233facddcc51865d612a919d450db6954aa48e3Michael Kolb
4758233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private void startHandler() {
4768233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mHandler = new Handler() {
4778233facddcc51865d612a919d450db6954aa48e3Michael Kolb
4788233facddcc51865d612a919d450db6954aa48e3Michael Kolb            @Override
4798233facddcc51865d612a919d450db6954aa48e3Michael Kolb            public void handleMessage(Message msg) {
4808233facddcc51865d612a919d450db6954aa48e3Michael Kolb                switch (msg.what) {
4818233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    case OPEN_BOOKMARKS:
482315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb                        bookmarksOrHistoryPicker(ComboViews.Bookmarks);
4838233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        break;
4848233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    case FOCUS_NODE_HREF:
4858233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    {
4868233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        String url = (String) msg.getData().get("url");
4878233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        String title = (String) msg.getData().get("title");
488043c2d63f65464e13a50e831f054a8f18414b9e6Cary Clark                        String src = (String) msg.getData().get("src");
489043c2d63f65464e13a50e831f054a8f18414b9e6Cary Clark                        if (url == "") url = src; // use image if no anchor
4908233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        if (TextUtils.isEmpty(url)) {
4918233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            break;
4928233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
4938233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        HashMap focusNodeMap = (HashMap) msg.obj;
4948233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        WebView view = (WebView) focusNodeMap.get("webview");
4958233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        // Only apply the action if the top window did not change.
4968233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        if (getCurrentTopWebView() != view) {
4978233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            break;
4988233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
4998233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        switch (msg.arg1) {
5008233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            case R.id.open_context_menu_id:
50126b183292dc087b16af10f482744c3bb30e1f163John Reck                                loadUrlFromContext(url);
5028233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                break;
503043c2d63f65464e13a50e831f054a8f18414b9e6Cary Clark                            case R.id.view_image_context_menu_id:
50426b183292dc087b16af10f482744c3bb30e1f163John Reck                                loadUrlFromContext(src);
505043c2d63f65464e13a50e831f054a8f18414b9e6Cary Clark                                break;
506026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                            case R.id.open_newtab_context_menu_id:
507026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                final Tab parent = mTabControl.getCurrentTab();
5085949c661b51295148706d53a03b41df2eb840ae3John Reck                                openTab(url, parent,
5095949c661b51295148706d53a03b41df2eb840ae3John Reck                                        !mSettings.openInBackground(), true);
510026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                break;
5118233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            case R.id.copy_link_context_menu_id:
5128233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                copy(url);
5138233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                break;
5148233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            case R.id.save_link_context_menu_id:
5158233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            case R.id.download_context_menu_id:
51663c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                                DownloadHandler.onDownloadStartNoStream(
5178e4ce660cd8576237b4ff30c40b21570af3af4f3Andreas Sandblad                                        mActivity, url, view.getSettings().getUserAgentString(),
5182584c31de479fa27971455b1e70b8e58b754c0e9Jean-Baptiste Queru                                        null, null, null, view.isPrivateBrowsingEnabled());
5198233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                break;
5208233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
5218233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        break;
5228233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
5238233facddcc51865d612a919d450db6954aa48e3Michael Kolb
5248233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    case LOAD_URL:
52526b183292dc087b16af10f482744c3bb30e1f163John Reck                        loadUrlFromContext((String) msg.obj);
5268233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        break;
5278233facddcc51865d612a919d450db6954aa48e3Michael Kolb
5288233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    case STOP_LOAD:
5298233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        stopLoading();
5308233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        break;
5318233facddcc51865d612a919d450db6954aa48e3Michael Kolb
5328233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    case RELEASE_WAKELOCK:
533f57c029329e874399199259b5e69f4d0b8a12a38John Reck                        if (mWakeLock != null && mWakeLock.isHeld()) {
5348233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            mWakeLock.release();
5358233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            // if we reach here, Browser should be still in the
5368233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            // background loading after WAKELOCK_TIMEOUT (5-min).
5378233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            // To avoid burning the battery, stop loading.
5388233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            mTabControl.stopAllLoading();
5398233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
5408233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        break;
5418233facddcc51865d612a919d450db6954aa48e3Michael Kolb
5428233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    case UPDATE_BOOKMARK_THUMBNAIL:
54334ef26756a751b99b5c021ee2b9221c582c88208John Reck                        Tab tab = (Tab) msg.obj;
54434ef26756a751b99b5c021ee2b9221c582c88208John Reck                        if (tab != null) {
54534ef26756a751b99b5c021ee2b9221c582c88208John Reck                            updateScreenshot(tab);
5468233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
5478233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        break;
5488233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
5498233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
5508233facddcc51865d612a919d450db6954aa48e3Michael Kolb        };
5518233facddcc51865d612a919d450db6954aa48e3Michael Kolb
5528233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
5538233facddcc51865d612a919d450db6954aa48e3Michael Kolb
554ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck    @Override
555b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen    public Tab getCurrentTab() {
556b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen        return mTabControl.getCurrentTab();
557b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen    }
558b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen
559ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb    @Override
560ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb    public void shareCurrentPage() {
561ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb        shareCurrentPage(mTabControl.getCurrentTab());
562ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb    }
563ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb
564ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb    private void shareCurrentPage(Tab tab) {
565ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb        if (tab != null) {
566ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb            sharePage(mActivity, tab.getTitle(),
567ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb                    tab.getUrl(), tab.getFavicon(),
568ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb                    createScreenshot(tab.getWebView(),
569ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb                            getDesiredThumbnailWidth(mActivity),
570ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb                            getDesiredThumbnailHeight(mActivity)));
571ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb        }
572ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb    }
573ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb
5748233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
5758233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Share a page, providing the title, url, favicon, and a screenshot.  Uses
5768233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * an {@link Intent} to launch the Activity chooser.
5778233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param c Context used to launch a new Activity.
5788233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param title Title of the page.  Stored in the Intent with
5798233facddcc51865d612a919d450db6954aa48e3Michael Kolb     *          {@link Intent#EXTRA_SUBJECT}
5808233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param url URL of the page.  Stored in the Intent with
5818233facddcc51865d612a919d450db6954aa48e3Michael Kolb     *          {@link Intent#EXTRA_TEXT}
5828233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param favicon Bitmap of the favicon for the page.  Stored in the Intent
5838233facddcc51865d612a919d450db6954aa48e3Michael Kolb     *          with {@link Browser#EXTRA_SHARE_FAVICON}
5848233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param screenshot Bitmap of a screenshot of the page.  Stored in the
5858233facddcc51865d612a919d450db6954aa48e3Michael Kolb     *          Intent with {@link Browser#EXTRA_SHARE_SCREENSHOT}
5868233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
5878233facddcc51865d612a919d450db6954aa48e3Michael Kolb    static final void sharePage(Context c, String title, String url,
5888233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Bitmap favicon, Bitmap screenshot) {
5898233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Intent send = new Intent(Intent.ACTION_SEND);
5908233facddcc51865d612a919d450db6954aa48e3Michael Kolb        send.setType("text/plain");
5918233facddcc51865d612a919d450db6954aa48e3Michael Kolb        send.putExtra(Intent.EXTRA_TEXT, url);
5928233facddcc51865d612a919d450db6954aa48e3Michael Kolb        send.putExtra(Intent.EXTRA_SUBJECT, title);
5938233facddcc51865d612a919d450db6954aa48e3Michael Kolb        send.putExtra(Browser.EXTRA_SHARE_FAVICON, favicon);
5948233facddcc51865d612a919d450db6954aa48e3Michael Kolb        send.putExtra(Browser.EXTRA_SHARE_SCREENSHOT, screenshot);
5958233facddcc51865d612a919d450db6954aa48e3Michael Kolb        try {
5968233facddcc51865d612a919d450db6954aa48e3Michael Kolb            c.startActivity(Intent.createChooser(send, c.getString(
5978233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    R.string.choosertitle_sharevia)));
5988233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } catch(android.content.ActivityNotFoundException ex) {
5998233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // if no app handles it, do nothing
6008233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
6018233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
6028233facddcc51865d612a919d450db6954aa48e3Michael Kolb
6038233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private void copy(CharSequence text) {
6048233facddcc51865d612a919d450db6954aa48e3Michael Kolb        ClipboardManager cm = (ClipboardManager) mActivity
6058233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .getSystemService(Context.CLIPBOARD_SERVICE);
6068233facddcc51865d612a919d450db6954aa48e3Michael Kolb        cm.setText(text);
6078233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
6088233facddcc51865d612a919d450db6954aa48e3Michael Kolb
6098233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // lifecycle
6108233facddcc51865d612a919d450db6954aa48e3Michael Kolb
6119c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
6129c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public void onConfgurationChanged(Configuration config) {
6138233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mConfigChanged = true;
61418f252ff8b7f787fd3129706650eafb74fcabef4Michael Kolb        // update the menu in case of a locale change
61518f252ff8b7f787fd3129706650eafb74fcabef4Michael Kolb        mActivity.invalidateOptionsMenu();
6168233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mPageDialogsHandler != null) {
6178233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mPageDialogsHandler.onConfigurationChanged(config);
6188233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
6198233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.onConfigurationChanged(config);
6208233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
6218233facddcc51865d612a919d450db6954aa48e3Michael Kolb
6228233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
6238233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void handleNewIntent(Intent intent) {
62459e232c77d354839fd5fc8d6fcfcd968e4f1497aMichael Kolb        if (!mUi.isWebShowing()) {
62559e232c77d354839fd5fc8d6fcfcd968e4f1497aMichael Kolb            mUi.showWeb(false);
62659e232c77d354839fd5fc8d6fcfcd968e4f1497aMichael Kolb        }
6278233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mIntentHandler.onNewIntent(intent);
6288233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
6298233facddcc51865d612a919d450db6954aa48e3Michael Kolb
6309c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
6319c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public void onPause() {
63211fe02d7b0a9956284fc0677b84b5fdacdd668e8Michael Kolb        if (mUi.isCustomViewShowing()) {
63311fe02d7b0a9956284fc0677b84b5fdacdd668e8Michael Kolb            hideCustomView();
63411fe02d7b0a9956284fc0677b84b5fdacdd668e8Michael Kolb        }
6358233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mActivityPaused) {
6368233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Log.e(LOGTAG, "BrowserActivity is already paused.");
6378233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
6388233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
6398233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActivityPaused = true;
64070976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb        Tab tab = mTabControl.getCurrentTab();
64170976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb        if (tab != null) {
64270976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb            tab.pause();
64370976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb            if (!pauseWebViewTimers(tab)) {
644f57c029329e874399199259b5e69f4d0b8a12a38John Reck                if (mWakeLock == null) {
645f57c029329e874399199259b5e69f4d0b8a12a38John Reck                    PowerManager pm = (PowerManager) mActivity
646f57c029329e874399199259b5e69f4d0b8a12a38John Reck                            .getSystemService(Context.POWER_SERVICE);
647f57c029329e874399199259b5e69f4d0b8a12a38John Reck                    mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Browser");
648f57c029329e874399199259b5e69f4d0b8a12a38John Reck                }
64970976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb                mWakeLock.acquire();
65070976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb                mHandler.sendMessageDelayed(mHandler
65170976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb                        .obtainMessage(RELEASE_WAKELOCK), WAKELOCK_TIMEOUT);
65270976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb            }
6538233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
6548233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.onPause();
6558233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mNetworkHandler.onPause();
6568233facddcc51865d612a919d450db6954aa48e3Michael Kolb
6578233facddcc51865d612a919d450db6954aa48e3Michael Kolb        WebView.disablePlatformNotifications();
658015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch        NfcHandler.unregister(mActivity);
659d7dd9b2ecb12da278c053291b684b885ee574301John Reck        if (sThumbnailBitmap != null) {
660d7dd9b2ecb12da278c053291b684b885ee574301John Reck            sThumbnailBitmap.recycle();
661d7dd9b2ecb12da278c053291b684b885ee574301John Reck            sThumbnailBitmap = null;
662d7dd9b2ecb12da278c053291b684b885ee574301John Reck        }
6638233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
6648233facddcc51865d612a919d450db6954aa48e3Michael Kolb
6659c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
6669c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public void onSaveInstanceState(Bundle outState) {
6678233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Save all the tabs
6683636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        Bundle saveState = createSaveState();
6693636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount
6703636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        // crash recovery manages all save & restore state
6713636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        mCrashRecoveryHandler.writeState(saveState);
6723636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        mSettings.setLastRunPaused(true);
6733636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount    }
6743636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount
6753636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount    /**
6763636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount     * Save the current state to outState. Does not write the state to
6773636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount     * disk.
6783636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount     * @return Bundle containing the current state of all tabs.
6793636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount     */
6803636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount    /* package */ Bundle createSaveState() {
6813636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        Bundle saveState = new Bundle();
6823636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        mTabControl.saveState(saveState);
6833636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        if (!saveState.isEmpty()) {
68424f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck            // Save time so that we know how old incognito tabs (if any) are.
6853636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount            saveState.putSerializable("lastActiveDate", Calendar.getInstance());
68624f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck        }
6873636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        return saveState;
6888233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
6898233facddcc51865d612a919d450db6954aa48e3Michael Kolb
6909c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
6919c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public void onResume() {
6928233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (!mActivityPaused) {
6938233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Log.e(LOGTAG, "BrowserActivity is already resumed.");
6948233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
6958233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
6963636d0a6d90fd8de55a4894210b2dbe23f32aac9George Mount        mSettings.setLastRunPaused(false);
6978233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActivityPaused = false;
69870976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb        Tab current = mTabControl.getCurrentTab();
69970976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb        if (current != null) {
70070976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb            current.resume();
70170976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb            resumeWebViewTimers(current);
70270976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb        }
703f57c029329e874399199259b5e69f4d0b8a12a38John Reck        releaseWakeLock();
704b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen
7058233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.onResume();
7068233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mNetworkHandler.onResume();
7078233facddcc51865d612a919d450db6954aa48e3Michael Kolb        WebView.enablePlatformNotifications();
708015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch        NfcHandler.register(mActivity, this);
7090b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb        if (mVoiceResult != null) {
7100b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb            mUi.onVoiceResult(mVoiceResult);
7110b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb            mVoiceResult = null;
7120b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb        }
7138233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
7148233facddcc51865d612a919d450db6954aa48e3Michael Kolb
715f57c029329e874399199259b5e69f4d0b8a12a38John Reck    private void releaseWakeLock() {
716f57c029329e874399199259b5e69f4d0b8a12a38John Reck        if (mWakeLock != null && mWakeLock.isHeld()) {
717f57c029329e874399199259b5e69f4d0b8a12a38John Reck            mHandler.removeMessages(RELEASE_WAKELOCK);
718f57c029329e874399199259b5e69f4d0b8a12a38John Reck            mWakeLock.release();
719f57c029329e874399199259b5e69f4d0b8a12a38John Reck        }
720f57c029329e874399199259b5e69f4d0b8a12a38John Reck    }
721f57c029329e874399199259b5e69f4d0b8a12a38John Reck
72270976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb    /**
723ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb     * resume all WebView timers using the WebView instance of the given tab
72470976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb     * @param tab guaranteed non-null
72570976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb     */
72670976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb    private void resumeWebViewTimers(Tab tab) {
7278233facddcc51865d612a919d450db6954aa48e3Michael Kolb        boolean inLoad = tab.inPageLoad();
7288233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if ((!mActivityPaused && !inLoad) || (mActivityPaused && inLoad)) {
7298233facddcc51865d612a919d450db6954aa48e3Michael Kolb            CookieSyncManager.getInstance().startSync();
7308233facddcc51865d612a919d450db6954aa48e3Michael Kolb            WebView w = tab.getWebView();
731e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood            WebViewTimersControl.getInstance().onBrowserActivityResume(w);
7328233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
7338233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
7348233facddcc51865d612a919d450db6954aa48e3Michael Kolb
73570976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb    /**
73670976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb     * Pause all WebView timers using the WebView of the given tab
73770976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb     * @param tab
73870976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb     * @return true if the timers are paused or tab is null
73970976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb     */
74070976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb    private boolean pauseWebViewTimers(Tab tab) {
74170976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb        if (tab == null) {
74270976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb            return true;
74370976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb        } else if (!tab.inPageLoad()) {
7448233facddcc51865d612a919d450db6954aa48e3Michael Kolb            CookieSyncManager.getInstance().stopSync();
745e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood            WebViewTimersControl.getInstance().onBrowserActivityPause(getCurrentWebView());
7468233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return true;
7478233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
74870976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb        return false;
7498233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
7508233facddcc51865d612a919d450db6954aa48e3Michael Kolb
7519c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
7529c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public void onDestroy() {
75338b4bf5f9cbb6adf2c5ca353e3b0c2a4ae9eeb87John Reck        if (mUploadHandler != null && !mUploadHandler.handled()) {
7548233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mUploadHandler.onResult(Activity.RESULT_CANCELED, null);
7558233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mUploadHandler = null;
7568233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
7578233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mTabControl == null) return;
7588233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.onDestroy();
7598233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Remove the current tab and sub window
7608233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Tab t = mTabControl.getCurrentTab();
7618233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (t != null) {
7628233facddcc51865d612a919d450db6954aa48e3Michael Kolb            dismissSubWindow(t);
7638233facddcc51865d612a919d450db6954aa48e3Michael Kolb            removeTab(t);
7648233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
7651961ed2f2856ca0993c8c4d15924bbb4e4ef98c0Leon Scroggins        mActivity.getContentResolver().unregisterContentObserver(mBookmarksObserver);
7668233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Destroy all the tabs
7678233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mTabControl.destroy();
7688233facddcc51865d612a919d450db6954aa48e3Michael Kolb        WebIconDatabase.getInstance().close();
7698233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Stop watching the default geolocation permissions
7708233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSystemAllowGeolocationOrigins.stop();
7718233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSystemAllowGeolocationOrigins = null;
7728233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
7738233facddcc51865d612a919d450db6954aa48e3Michael Kolb
7748233facddcc51865d612a919d450db6954aa48e3Michael Kolb    protected boolean isActivityPaused() {
7758233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mActivityPaused;
7768233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
7778233facddcc51865d612a919d450db6954aa48e3Michael Kolb
7789c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
7799c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public void onLowMemory() {
7808233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mTabControl.freeMemory();
7818233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
7828233facddcc51865d612a919d450db6954aa48e3Michael Kolb
7838233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
7848233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public boolean shouldShowErrorConsole() {
7858233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mShouldShowErrorConsole;
7868233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
7878233facddcc51865d612a919d450db6954aa48e3Michael Kolb
7888233facddcc51865d612a919d450db6954aa48e3Michael Kolb    protected void setShouldShowErrorConsole(boolean show) {
7898233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (show == mShouldShowErrorConsole) {
7908233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // Nothing to do.
7918233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
7928233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
7938233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mShouldShowErrorConsole = show;
7948233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Tab t = mTabControl.getCurrentTab();
7958233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (t == null) {
7968233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // There is no current tab so we cannot toggle the error console
7978233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
7988233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
7998233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.setShouldShowErrorConsole(t, show);
8008233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
8018233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8028233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
8038233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void stopLoading() {
8048233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mLoadStopped = true;
8058233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Tab tab = mTabControl.getCurrentTab();
8068233facddcc51865d612a919d450db6954aa48e3Michael Kolb        WebView w = getCurrentTopWebView();
807778a48868401c777eef3b88de8e4b84dd98d58ddMichael Kolb        if (w != null) {
808778a48868401c777eef3b88de8e4b84dd98d58ddMichael Kolb            w.stopLoading();
809778a48868401c777eef3b88de8e4b84dd98d58ddMichael Kolb            mUi.onPageStopped(tab);
810778a48868401c777eef3b88de8e4b84dd98d58ddMichael Kolb        }
8118233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
8128233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8138233facddcc51865d612a919d450db6954aa48e3Michael Kolb    boolean didUserStopLoading() {
8148233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mLoadStopped;
8158233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
8168233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8178233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // WebViewController
8188233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8198233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
820324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck    public void onPageStarted(Tab tab, WebView view, Bitmap favicon) {
8218233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8228233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // We've started to load a new page. If there was a pending message
8238233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // to save a screenshot then we will now take the new page and save
8248233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // an incorrect screenshot. Therefore, remove any pending thumbnail
8258233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // messages from the queue.
8268233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mHandler.removeMessages(Controller.UPDATE_BOOKMARK_THUMBNAIL,
82734ef26756a751b99b5c021ee2b9221c582c88208John Reck                tab);
8288233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8298233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // reset sync timer to avoid sync starts during loading a page
8308233facddcc51865d612a919d450db6954aa48e3Michael Kolb        CookieSyncManager.getInstance().resetSync();
8318233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8328233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (!mNetworkHandler.isNetworkUp()) {
8338233facddcc51865d612a919d450db6954aa48e3Michael Kolb            view.setNetworkAvailable(false);
8348233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
8358233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8368233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // when BrowserActivity just starts, onPageStarted may be called before
8378233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // onResume as it is triggered from onCreate. Call resumeWebViewTimers
8388233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // to start the timer. As we won't switch tabs while an activity is in
8398233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // pause state, we can ensure calling resume and pause in pair.
8408233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mActivityPaused) {
84170976938146d1b13b9e183ceec41edce50c5d6afMichael Kolb            resumeWebViewTimers(tab);
8428233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
8438233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mLoadStopped = false;
8448233facddcc51865d612a919d450db6954aa48e3Michael Kolb        endActionMode();
8458233facddcc51865d612a919d450db6954aa48e3Michael Kolb
84630c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mUi.onTabDataChanged(tab);
8478233facddcc51865d612a919d450db6954aa48e3Michael Kolb
848324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck        String url = tab.getUrl();
8498233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // update the bookmark database for favicon
8508233facddcc51865d612a919d450db6954aa48e3Michael Kolb        maybeUpdateFavicon(tab, null, url, favicon);
8518233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8528233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Performance.tracePageStart(url);
8538233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8548233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Performance probe
8558233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (false) {
8568233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Performance.onPageStarted();
8578233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
8588233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8598233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
8608233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8618233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
862324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck    public void onPageFinished(Tab tab) {
8637286427ee44435acf5f0ccd1146d9d0b15a36d02Michael Kolb        mCrashRecoveryHandler.backupState();
86430c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mUi.onTabDataChanged(tab);
865b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen
8668233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Performance probe
8678233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (false) {
868324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck            Performance.onPageFinished(tab.getUrl());
8698233facddcc51865d612a919d450db6954aa48e3Michael Kolb         }
8708233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8718233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Performance.tracePageFinished();
8728233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
8738233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8748233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
87530c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    public void onProgressChanged(Tab tab) {
87630c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        int newProgress = tab.getLoadProgress();
8778233facddcc51865d612a919d450db6954aa48e3Michael Kolb
8788233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (newProgress == 100) {
8798233facddcc51865d612a919d450db6954aa48e3Michael Kolb            CookieSyncManager.getInstance().sync();
8808233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // onProgressChanged() may continue to be called after the main
8818233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // frame has finished loading, as any remaining sub frames continue
8828233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // to load. We'll only get called once though with newProgress as
8838233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // 100 when everything is loaded. (onPageFinished is called once
8848233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // when the main frame completes loading regardless of the state of
8858233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // any sub frames so calls to onProgressChanges may continue after
8868233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // onPageFinished has executed)
887b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb            if (tab.inPageLoad()) {
888b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb                updateInLoadMenuItems(mCachedMenu, tab);
8899cc2d03bddf3d11804fa5ac06662220f1e21b3ceMattias Falk            } else if (mActivityPaused && pauseWebViewTimers(tab)) {
8909cc2d03bddf3d11804fa5ac06662220f1e21b3ceMattias Falk                // pause the WebView timer and release the wake lock if it is
8919cc2d03bddf3d11804fa5ac06662220f1e21b3ceMattias Falk                // finished while BrowserActivity is in pause state.
8929cc2d03bddf3d11804fa5ac06662220f1e21b3ceMattias Falk                releaseWakeLock();
8938233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
894d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck            if (!tab.isPrivateBrowsingEnabled()
895d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                    && !TextUtils.isEmpty(tab.getUrl())
896d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                    && !tab.isSnapshot()) {
897d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                // Only update the bookmark screenshot if the user did not
898d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                // cancel the load early and there is not already
899d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                // a pending update for the tab.
9007286427ee44435acf5f0ccd1146d9d0b15a36d02Michael Kolb                if (tab.shouldUpdateThumbnail() &&
9017286427ee44435acf5f0ccd1146d9d0b15a36d02Michael Kolb                        (tab.inForeground() && !didUserStopLoading()
9027286427ee44435acf5f0ccd1146d9d0b15a36d02Michael Kolb                        || !tab.inForeground())) {
903d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                    if (!mHandler.hasMessages(UPDATE_BOOKMARK_THUMBNAIL, tab)) {
904d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                        mHandler.sendMessageDelayed(mHandler.obtainMessage(
905d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                                UPDATE_BOOKMARK_THUMBNAIL, 0, 0, tab),
906d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                                500);
907d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                    }
908d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck                }
909d98623751ffc44ab04e75f04cfac87db330bc82bJohn Reck            }
9108233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else {
911b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb            if (!tab.inPageLoad()) {
9128233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // onPageFinished may have already been called but a subframe is
913b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb                // still loading
914b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb                // updating the progress and
9158233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // update the menu items.
916b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb                updateInLoadMenuItems(mCachedMenu, tab);
9178233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
9188233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
91930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mUi.onProgressChanged(tab);
92030c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    }
92130c714c853a4239e72ab1e238ce2a92472d06ab0John Reck
92230c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    @Override
9232466effd6ef97aa17396c214d51f9f19a4760260Steve Block    public void onUpdatedSecurityState(Tab tab) {
92430c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mUi.onTabDataChanged(tab);
9258233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
9268233facddcc51865d612a919d450db6954aa48e3Michael Kolb
9278233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
9288233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void onReceivedTitle(Tab tab, final String title) {
92930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mUi.onTabDataChanged(tab);
93049a603c11b00b6e68a54e070abf4eb33eaddfa84John Reck        final String pageUrl = tab.getOriginalUrl();
931324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck        if (TextUtils.isEmpty(pageUrl) || pageUrl.length()
9328233facddcc51865d612a919d450db6954aa48e3Michael Kolb                >= SQLiteDatabase.SQLITE_MAX_LIKE_PATTERN_LENGTH) {
9338233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
9348233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
9358233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Update the title in the history database if not in private browsing mode
9368233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (!tab.isPrivateBrowsingEnabled()) {
937f57c029329e874399199259b5e69f4d0b8a12a38John Reck            DataController.getInstance(mActivity).updateHistoryTitle(pageUrl, title);
9388233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
9398233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
9408233facddcc51865d612a919d450db6954aa48e3Michael Kolb
9418233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
9428233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void onFavicon(Tab tab, WebView view, Bitmap icon) {
94330c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mUi.onTabDataChanged(tab);
9448233facddcc51865d612a919d450db6954aa48e3Michael Kolb        maybeUpdateFavicon(tab, view.getOriginalUrl(), view.getUrl(), icon);
9458233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
9468233facddcc51865d612a919d450db6954aa48e3Michael Kolb
9478233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
94818eb377badf8e6f9ea2925bcb7e978facf3171d9Michael Kolb    public boolean shouldOverrideUrlLoading(Tab tab, WebView view, String url) {
94918eb377badf8e6f9ea2925bcb7e978facf3171d9Michael Kolb        return mUrlHandler.shouldOverrideUrlLoading(tab, view, url);
9508233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
9518233facddcc51865d612a919d450db6954aa48e3Michael Kolb
9528233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
9538233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public boolean shouldOverrideKeyEvent(KeyEvent event) {
9548233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mMenuIsDown) {
9558233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // only check shortcut key when MENU is held
9568233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return mActivity.getWindow().isShortcutKey(event.getKeyCode(),
9578233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    event);
9588233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else {
9598233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return false;
9608233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
9618233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
9628233facddcc51865d612a919d450db6954aa48e3Michael Kolb
9638233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
964997b1b7695822cb2dc2deca0458a5649d00b9953John Reck    public boolean onUnhandledKeyEvent(KeyEvent event) {
9658233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (!isActivityPaused()) {
9668233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (event.getAction() == KeyEvent.ACTION_DOWN) {
967997b1b7695822cb2dc2deca0458a5649d00b9953John Reck                return mActivity.onKeyDown(event.getKeyCode(), event);
9688233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else {
969997b1b7695822cb2dc2deca0458a5649d00b9953John Reck                return mActivity.onKeyUp(event.getKeyCode(), event);
9708233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
9718233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
972997b1b7695822cb2dc2deca0458a5649d00b9953John Reck        return false;
9738233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
9748233facddcc51865d612a919d450db6954aa48e3Michael Kolb
9758233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
976324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck    public void doUpdateVisitedHistory(Tab tab, boolean isReload) {
9778233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Don't save anything in private browsing mode
9788233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (tab.isPrivateBrowsingEnabled()) return;
97949a603c11b00b6e68a54e070abf4eb33eaddfa84John Reck        String url = tab.getOriginalUrl();
9808233facddcc51865d612a919d450db6954aa48e3Michael Kolb
981324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck        if (TextUtils.isEmpty(url)
982324d440ea7dc44da8beef8a6c2e6f7a33b20a41dJohn Reck                || url.regionMatches(true, 0, "about:", 0, 6)) {
9838233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
9848233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
985f57c029329e874399199259b5e69f4d0b8a12a38John Reck        DataController.getInstance(mActivity).updateVisitedHistory(url);
9866c2e2f34718043f36488b4a94879dc2605aaac49John Reck        mCrashRecoveryHandler.backupState();
9878233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
9888233facddcc51865d612a919d450db6954aa48e3Michael Kolb
9898233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
9908233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void getVisitedHistory(final ValueCallback<String[]> callback) {
9918233facddcc51865d612a919d450db6954aa48e3Michael Kolb        AsyncTask<Void, Void, String[]> task =
9928233facddcc51865d612a919d450db6954aa48e3Michael Kolb                new AsyncTask<Void, Void, String[]>() {
9938233facddcc51865d612a919d450db6954aa48e3Michael Kolb            @Override
9948233facddcc51865d612a919d450db6954aa48e3Michael Kolb            public String[] doInBackground(Void... unused) {
9958233facddcc51865d612a919d450db6954aa48e3Michael Kolb                return Browser.getVisitedHistory(mActivity.getContentResolver());
9968233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
9978233facddcc51865d612a919d450db6954aa48e3Michael Kolb            @Override
9988233facddcc51865d612a919d450db6954aa48e3Michael Kolb            public void onPostExecute(String[] result) {
9998233facddcc51865d612a919d450db6954aa48e3Michael Kolb                callback.onReceiveValue(result);
10008233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
10018233facddcc51865d612a919d450db6954aa48e3Michael Kolb        };
10028233facddcc51865d612a919d450db6954aa48e3Michael Kolb        task.execute();
10038233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
10048233facddcc51865d612a919d450db6954aa48e3Michael Kolb
10058233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
10068233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void onReceivedHttpAuthRequest(Tab tab, WebView view,
10078233facddcc51865d612a919d450db6954aa48e3Michael Kolb            final HttpAuthHandler handler, final String host,
10088233facddcc51865d612a919d450db6954aa48e3Michael Kolb            final String realm) {
10098233facddcc51865d612a919d450db6954aa48e3Michael Kolb        String username = null;
10108233facddcc51865d612a919d450db6954aa48e3Michael Kolb        String password = null;
10118233facddcc51865d612a919d450db6954aa48e3Michael Kolb
10128233facddcc51865d612a919d450db6954aa48e3Michael Kolb        boolean reuseHttpAuthUsernamePassword
10138233facddcc51865d612a919d450db6954aa48e3Michael Kolb                = handler.useHttpAuthUsernamePassword();
10148233facddcc51865d612a919d450db6954aa48e3Michael Kolb
10158233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (reuseHttpAuthUsernamePassword && view != null) {
10168233facddcc51865d612a919d450db6954aa48e3Michael Kolb            String[] credentials = view.getHttpAuthUsernamePassword(host, realm);
10178233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (credentials != null && credentials.length == 2) {
10188233facddcc51865d612a919d450db6954aa48e3Michael Kolb                username = credentials[0];
10198233facddcc51865d612a919d450db6954aa48e3Michael Kolb                password = credentials[1];
10208233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
10218233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
10228233facddcc51865d612a919d450db6954aa48e3Michael Kolb
10238233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (username != null && password != null) {
10248233facddcc51865d612a919d450db6954aa48e3Michael Kolb            handler.proceed(username, password);
10258233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else {
1026fdd371115259fad344d552b8b7121823b1466804Ben Murdoch            if (tab.inForeground() && !handler.suppressDialog()) {
10278233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mPageDialogsHandler.showHttpAuthentication(tab, handler, host, realm);
10288233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else {
10298233facddcc51865d612a919d450db6954aa48e3Michael Kolb                handler.cancel();
10308233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
10318233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
10328233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
10338233facddcc51865d612a919d450db6954aa48e3Michael Kolb
10348233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
10358233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void onDownloadStart(Tab tab, String url, String userAgent,
10360b3d66fc2275fb5270cb7166cc991be7dc9d8ff7Selim Gurun            String contentDisposition, String mimetype, String referer,
10370b3d66fc2275fb5270cb7166cc991be7dc9d8ff7Selim Gurun            long contentLength) {
1038bc5cc75c302eb49d15258155fc6f672fcbd62842Kristian Monsen        WebView w = tab.getWebView();
103963c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins        DownloadHandler.onDownloadStart(mActivity, url, userAgent,
10400b3d66fc2275fb5270cb7166cc991be7dc9d8ff7Selim Gurun                contentDisposition, mimetype, referer, w.isPrivateBrowsingEnabled());
1041bc5cc75c302eb49d15258155fc6f672fcbd62842Kristian Monsen        if (w.copyBackForwardList().getSize() == 0) {
10428233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // This Tab was opened for the sole purpose of downloading a
10438233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // file. Remove it.
10448233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (tab == mTabControl.getCurrentTab()) {
10458233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // In this case, the Tab is still on top.
10468233facddcc51865d612a919d450db6954aa48e3Michael Kolb                goBackOnePageOrQuit();
10478233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else {
10488233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // In this case, it is not.
10498233facddcc51865d612a919d450db6954aa48e3Michael Kolb                closeTab(tab);
10508233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
10518233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
10528233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
10538233facddcc51865d612a919d450db6954aa48e3Michael Kolb
10548233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
10558233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public Bitmap getDefaultVideoPoster() {
10568233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mUi.getDefaultVideoPoster();
10578233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
10588233facddcc51865d612a919d450db6954aa48e3Michael Kolb
10598233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
10608233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public View getVideoLoadingProgressView() {
10618233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mUi.getVideoLoadingProgressView();
10628233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
10638233facddcc51865d612a919d450db6954aa48e3Michael Kolb
10648233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
10658233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void showSslCertificateOnError(WebView view, SslErrorHandler handler,
10668233facddcc51865d612a919d450db6954aa48e3Michael Kolb            SslError error) {
10678233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mPageDialogsHandler.showSSLCertificateOnError(view, handler, error);
10688233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
10698233facddcc51865d612a919d450db6954aa48e3Michael Kolb
10709206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    @Override
10719206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    public void showAutoLogin(Tab tab) {
10729206677e461328f15854c5fcb1366d0e261534c6Patrick Scott        assert tab.inForeground();
10739206677e461328f15854c5fcb1366d0e261534c6Patrick Scott        // Update the title bar to show the auto-login request.
10749206677e461328f15854c5fcb1366d0e261534c6Patrick Scott        mUi.showAutoLogin(tab);
10759206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    }
10769206677e461328f15854c5fcb1366d0e261534c6Patrick Scott
10779206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    @Override
10789206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    public void hideAutoLogin(Tab tab) {
10799206677e461328f15854c5fcb1366d0e261534c6Patrick Scott        assert tab.inForeground();
10809206677e461328f15854c5fcb1366d0e261534c6Patrick Scott        mUi.hideAutoLogin(tab);
10819206677e461328f15854c5fcb1366d0e261534c6Patrick Scott    }
10829206677e461328f15854c5fcb1366d0e261534c6Patrick Scott
10838233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // helper method
10848233facddcc51865d612a919d450db6954aa48e3Michael Kolb
10858233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /*
10868233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Update the favorites icon if the private browsing isn't enabled and the
10878233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * icon is valid.
10888233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
10898233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private void maybeUpdateFavicon(Tab tab, final String originalUrl,
10908233facddcc51865d612a919d450db6954aa48e3Michael Kolb            final String url, Bitmap favicon) {
10918233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (favicon == null) {
10928233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
10938233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
10948233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (!tab.isPrivateBrowsingEnabled()) {
10958233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Bookmarks.updateFavicon(mActivity
10968233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    .getContentResolver(), originalUrl, url, favicon);
10978233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
10988233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
10998233facddcc51865d612a919d450db6954aa48e3Michael Kolb
11004cd97793901e8f5681cf642d0b2684697964a37aLeon Scroggins    @Override
11014cd97793901e8f5681cf642d0b2684697964a37aLeon Scroggins    public void bookmarkedStatusHasChanged(Tab tab) {
1102e969cc59ddcc763ab9d6349a854dd17a6456d1a4John Reck        // TODO: Switch to using onTabDataChanged after b/3262950 is fixed
11034cd97793901e8f5681cf642d0b2684697964a37aLeon Scroggins        mUi.bookmarkedStatusHasChanged(tab);
11044cd97793901e8f5681cf642d0b2684697964a37aLeon Scroggins    }
11054cd97793901e8f5681cf642d0b2684697964a37aLeon Scroggins
11068233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // end WebViewController
11078233facddcc51865d612a919d450db6954aa48e3Michael Kolb
11088233facddcc51865d612a919d450db6954aa48e3Michael Kolb    protected void pageUp() {
11098233facddcc51865d612a919d450db6954aa48e3Michael Kolb        getCurrentTopWebView().pageUp(false);
11108233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
11118233facddcc51865d612a919d450db6954aa48e3Michael Kolb
11128233facddcc51865d612a919d450db6954aa48e3Michael Kolb    protected void pageDown() {
11138233facddcc51865d612a919d450db6954aa48e3Michael Kolb        getCurrentTopWebView().pageDown(false);
11148233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
11158233facddcc51865d612a919d450db6954aa48e3Michael Kolb
11168233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // callback from phone title bar
11179c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
11188233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void editUrl() {
11198233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mOptionsMenuOpen) mActivity.closeOptionsMenu();
11201f9b3565dbd1911dfe4d9bfd8b833a5ac5f2e0c4Michael Kolb        mUi.editUrl(false, true);
11218233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
11228233facddcc51865d612a919d450db6954aa48e3Michael Kolb
11239c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
11242d4f1e2553dee6bce5a12162ff6d4459babe2512Derek Sollenberger    public void showCustomView(Tab tab, View view, int requestedOrientation,
11258233facddcc51865d612a919d450db6954aa48e3Michael Kolb            WebChromeClient.CustomViewCallback callback) {
11268233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (tab.inForeground()) {
11278233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (mUi.isCustomViewShowing()) {
11288233facddcc51865d612a919d450db6954aa48e3Michael Kolb                callback.onCustomViewHidden();
11298233facddcc51865d612a919d450db6954aa48e3Michael Kolb                return;
11308233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
11312d4f1e2553dee6bce5a12162ff6d4459babe2512Derek Sollenberger            mUi.showCustomView(view, requestedOrientation, callback);
11328233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // Save the menu state and set it to empty while the custom
11338233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // view is showing.
11348233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mOldMenuState = mMenuState;
11358233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mMenuState = EMPTY_MENU;
1136d73c5a2bd0cee6801dce425c31d0c3e027588bcaJohn Reck            mActivity.invalidateOptionsMenu();
11378233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
11388233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
11398233facddcc51865d612a919d450db6954aa48e3Michael Kolb
11408233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
11418233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void hideCustomView() {
11428233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mUi.isCustomViewShowing()) {
11438233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mUi.onHideCustomView();
11448233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // Reset the old menu state.
11458233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mMenuState = mOldMenuState;
11468233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mOldMenuState = EMPTY_MENU;
1147d73c5a2bd0cee6801dce425c31d0c3e027588bcaJohn Reck            mActivity.invalidateOptionsMenu();
11488233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
11498233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
11508233facddcc51865d612a919d450db6954aa48e3Michael Kolb
11519c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
11529c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public void onActivityResult(int requestCode, int resultCode,
11538233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Intent intent) {
11548233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (getCurrentTopWebView() == null) return;
11558233facddcc51865d612a919d450db6954aa48e3Michael Kolb        switch (requestCode) {
11568233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case PREFERENCES_PAGE:
11578233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (resultCode == Activity.RESULT_OK && intent != null) {
11588233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    String action = intent.getStringExtra(Intent.EXTRA_TEXT);
115935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                    if (PreferenceKeys.PREF_PRIVACY_CLEAR_HISTORY.equals(action)) {
11608233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        mTabControl.removeParentChildRelationShips();
11618233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
11628233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
11638233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
11648233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case FILE_SELECTED:
116551f6a2f1dc524b31476fb71de36f2bd79f499d08Ben Murdoch                // Chose a file from the file picker.
11669dfcdb1490d7abac107e4d2b1c2fef51ccdf6b98John Reck                if (null == mUploadHandler) break;
11678233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mUploadHandler.onResult(resultCode, intent);
11688233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
11698029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch            case AUTOFILL_SETUP:
11708029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch                // Determine whether a profile was actually set up or not
11718029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch                // and if so, send the message back to the WebTextView to
11728029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch                // fill the form with the new profile.
11738029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch                if (getSettings().getAutoFillProfile() != null) {
11748029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch                    mAutoFillSetupMessage.sendToTarget();
11758029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch                    mAutoFillSetupMessage = null;
11768029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch                }
11778029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch                break;
1178d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck            case COMBO_VIEW:
1179d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                if (intent == null || resultCode != Activity.RESULT_OK) {
1180d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    break;
1181d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                }
11823ba455394dd3413b6246f00d2bf2083547862735John Reck                mUi.showWeb(false);
1183d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                if (Intent.ACTION_VIEW.equals(intent.getAction())) {
1184d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    Tab t = getCurrentTab();
1185d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    Uri uri = intent.getData();
1186d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    loadUrl(t, uri.toString());
1187d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                } else if (intent.hasExtra(ComboViewActivity.EXTRA_OPEN_ALL)) {
1188d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    String[] urls = intent.getStringArrayExtra(
1189d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                            ComboViewActivity.EXTRA_OPEN_ALL);
1190d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    Tab parent = getCurrentTab();
1191d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    for (String url : urls) {
1192d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                        parent = openTab(url, parent,
1193d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                                !mSettings.openInBackground(), true);
1194d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    }
1195d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                } else if (intent.hasExtra(ComboViewActivity.EXTRA_OPEN_SNAPSHOT)) {
1196d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    long id = intent.getLongExtra(
1197d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                            ComboViewActivity.EXTRA_OPEN_SNAPSHOT, -1);
1198d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    if (id >= 0) {
1199e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon                        if (BrowserWebView.isClassic()) {
1200e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon                            createNewSnapshotTab(id, true);
1201e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon                        } else {
1202e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon                            Toast.makeText(mActivity, "Snapshot Tab requires WebViewClassic",
1203e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon                                Toast.LENGTH_LONG).show();
1204e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon                        }
1205d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                    }
1206d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                }
1207d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck                break;
12080b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb            case VOICE_RESULT:
12090b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb                if (resultCode == Activity.RESULT_OK && intent != null) {
12100b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb                    ArrayList<String> results = intent.getStringArrayListExtra(
12110b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb                            RecognizerIntent.EXTRA_RESULTS);
12120b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb                    if (results.size() >= 1) {
12130b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb                        mVoiceResult = results.get(0);
12140b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb                    }
12150b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb                }
12160b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb                break;
12178233facddcc51865d612a919d450db6954aa48e3Michael Kolb            default:
12188233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
12198233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
12208233facddcc51865d612a919d450db6954aa48e3Michael Kolb        getCurrentTopWebView().requestFocus();
12218233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
12228233facddcc51865d612a919d450db6954aa48e3Michael Kolb
12238233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
12248233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Open the Go page.
12258233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param startWithHistory If true, open starting on the history tab.
12268233facddcc51865d612a919d450db6954aa48e3Michael Kolb     *                         Otherwise, start with the bookmarks tab.
12278233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
12288233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
1229315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb    public void bookmarksOrHistoryPicker(ComboViews startView) {
12308233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mTabControl.getCurrentWebView() == null) {
12318233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
12328233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1233bd3dd948312df22888a8a90aef21e3460ba2f0b3Michael Kolb        // clear action mode
1234bd3dd948312df22888a8a90aef21e3460ba2f0b3Michael Kolb        if (isInCustomActionMode()) {
1235bd3dd948312df22888a8a90aef21e3460ba2f0b3Michael Kolb            endActionMode();
1236bd3dd948312df22888a8a90aef21e3460ba2f0b3Michael Kolb        }
12378233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Bundle extras = new Bundle();
12388233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Disable opening in a new window if we have maxed out the windows
12398233facddcc51865d612a919d450db6954aa48e3Michael Kolb        extras.putBoolean(BrowserBookmarksPage.EXTRA_DISABLE_WINDOW,
12408233facddcc51865d612a919d450db6954aa48e3Michael Kolb                !mTabControl.canCreateNewTab());
1241315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb        mUi.showComboView(startView, extras);
12428233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
12438233facddcc51865d612a919d450db6954aa48e3Michael Kolb
12448233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // combo view callbacks
12458233facddcc51865d612a919d450db6954aa48e3Michael Kolb
12468233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // key handling
12478233facddcc51865d612a919d450db6954aa48e3Michael Kolb    protected void onBackKey() {
12488233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (!mUi.onBackKey()) {
12498233facddcc51865d612a919d450db6954aa48e3Michael Kolb            WebView subwindow = mTabControl.getCurrentSubWindow();
12508233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (subwindow != null) {
12518233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (subwindow.canGoBack()) {
12528233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    subwindow.goBack();
12538233facddcc51865d612a919d450db6954aa48e3Michael Kolb                } else {
12548233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    dismissSubWindow(mTabControl.getCurrentTab());
12558233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
12568233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else {
12578233facddcc51865d612a919d450db6954aa48e3Michael Kolb                goBackOnePageOrQuit();
12588233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
12598233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
12608233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
12618233facddcc51865d612a919d450db6954aa48e3Michael Kolb
12624bd767d2f4ce166a44687170c6af18e242447205Michael Kolb    protected boolean onMenuKey() {
12634bd767d2f4ce166a44687170c6af18e242447205Michael Kolb        return mUi.onMenuKey();
12642814a362c21ac219410d9b54e1bd3e8152b845c7Michael Kolb    }
12652814a362c21ac219410d9b54e1bd3e8152b845c7Michael Kolb
12668233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // menu handling and state
12678233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // TODO: maybe put into separate handler
12688233facddcc51865d612a919d450db6954aa48e3Michael Kolb
12699c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
12709c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public boolean onCreateOptionsMenu(Menu menu) {
1271d73c5a2bd0cee6801dce425c31d0c3e027588bcaJohn Reck        if (mMenuState == EMPTY_MENU) {
1272d73c5a2bd0cee6801dce425c31d0c3e027588bcaJohn Reck            return false;
1273d73c5a2bd0cee6801dce425c31d0c3e027588bcaJohn Reck        }
12748233facddcc51865d612a919d450db6954aa48e3Michael Kolb        MenuInflater inflater = mActivity.getMenuInflater();
12758233facddcc51865d612a919d450db6954aa48e3Michael Kolb        inflater.inflate(R.menu.browser, menu);
12768233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return true;
12778233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
12788233facddcc51865d612a919d450db6954aa48e3Michael Kolb
12799c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
12809c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public void onCreateContextMenu(ContextMenu menu, View v,
12818233facddcc51865d612a919d450db6954aa48e3Michael Kolb            ContextMenuInfo menuInfo) {
12820f602f3933dcd88702fdb514b6611e3066ca7a2bJohn Reck        if (v instanceof TitleBar) {
12838233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
12848233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
12858233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (!(v instanceof WebView)) {
12868233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
12878233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1288026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins        final WebView webview = (WebView) v;
12898233facddcc51865d612a919d450db6954aa48e3Michael Kolb        WebView.HitTestResult result = webview.getHitTestResult();
12908233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (result == null) {
12918233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
12928233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
12938233facddcc51865d612a919d450db6954aa48e3Michael Kolb
12948233facddcc51865d612a919d450db6954aa48e3Michael Kolb        int type = result.getType();
12958233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (type == WebView.HitTestResult.UNKNOWN_TYPE) {
12968233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Log.w(LOGTAG,
12978233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    "We should not show context menu when nothing is touched");
12988233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
12998233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
13008233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (type == WebView.HitTestResult.EDIT_TEXT_TYPE) {
13018233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // let TextView handles context menu
13028233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
13038233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
13048233facddcc51865d612a919d450db6954aa48e3Michael Kolb
13058233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Note, http://b/issue?id=1106666 is requesting that
13068233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // an inflated menu can be used again. This is not available
13078233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // yet, so inflate each time (yuk!)
13088233facddcc51865d612a919d450db6954aa48e3Michael Kolb        MenuInflater inflater = mActivity.getMenuInflater();
13098233facddcc51865d612a919d450db6954aa48e3Michael Kolb        inflater.inflate(R.menu.browsercontext, menu);
13108233facddcc51865d612a919d450db6954aa48e3Michael Kolb
13118233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Show the correct menu group
13128233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final String extra = result.getExtra();
1313c159c1a79e28904b8755e5f0947b279f96475f6bMichael Kolb        if (extra == null) return;
13148233facddcc51865d612a919d450db6954aa48e3Michael Kolb        menu.setGroupVisible(R.id.PHONE_MENU,
13158233facddcc51865d612a919d450db6954aa48e3Michael Kolb                type == WebView.HitTestResult.PHONE_TYPE);
13168233facddcc51865d612a919d450db6954aa48e3Michael Kolb        menu.setGroupVisible(R.id.EMAIL_MENU,
13178233facddcc51865d612a919d450db6954aa48e3Michael Kolb                type == WebView.HitTestResult.EMAIL_TYPE);
13188233facddcc51865d612a919d450db6954aa48e3Michael Kolb        menu.setGroupVisible(R.id.GEO_MENU,
13198233facddcc51865d612a919d450db6954aa48e3Michael Kolb                type == WebView.HitTestResult.GEO_TYPE);
13208233facddcc51865d612a919d450db6954aa48e3Michael Kolb        menu.setGroupVisible(R.id.IMAGE_MENU,
13218233facddcc51865d612a919d450db6954aa48e3Michael Kolb                type == WebView.HitTestResult.IMAGE_TYPE
13228233facddcc51865d612a919d450db6954aa48e3Michael Kolb                || type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
13238233facddcc51865d612a919d450db6954aa48e3Michael Kolb        menu.setGroupVisible(R.id.ANCHOR_MENU,
13248233facddcc51865d612a919d450db6954aa48e3Michael Kolb                type == WebView.HitTestResult.SRC_ANCHOR_TYPE
13258233facddcc51865d612a919d450db6954aa48e3Michael Kolb                || type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
13268974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark        boolean hitText = type == WebView.HitTestResult.SRC_ANCHOR_TYPE
13278974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark                || type == WebView.HitTestResult.PHONE_TYPE
13288974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark                || type == WebView.HitTestResult.EMAIL_TYPE
13298974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark                || type == WebView.HitTestResult.GEO_TYPE;
13308974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark        menu.setGroupVisible(R.id.SELECT_TEXT_MENU, hitText);
13318974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark        if (hitText) {
13328974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark            menu.findItem(R.id.select_text_menu_id)
13338974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark                    .setOnMenuItemClickListener(new SelectText(webview));
13348974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark        }
13358233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Setup custom handling depending on the type
13368233facddcc51865d612a919d450db6954aa48e3Michael Kolb        switch (type) {
13378233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case WebView.HitTestResult.PHONE_TYPE:
13388233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.setHeaderTitle(Uri.decode(extra));
13398233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.findItem(R.id.dial_context_menu_id).setIntent(
13408233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new Intent(Intent.ACTION_VIEW, Uri
13418233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                .parse(WebView.SCHEME_TEL + extra)));
13428233facddcc51865d612a919d450db6954aa48e3Michael Kolb                Intent addIntent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
13438233facddcc51865d612a919d450db6954aa48e3Michael Kolb                addIntent.putExtra(Insert.PHONE, Uri.decode(extra));
13448233facddcc51865d612a919d450db6954aa48e3Michael Kolb                addIntent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
13458233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.findItem(R.id.add_contact_context_menu_id).setIntent(
13468233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        addIntent);
13478233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.findItem(R.id.copy_phone_context_menu_id)
13488233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        .setOnMenuItemClickListener(
13498233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new Copy(extra));
13508233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
13518233facddcc51865d612a919d450db6954aa48e3Michael Kolb
13528233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case WebView.HitTestResult.EMAIL_TYPE:
13538233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.setHeaderTitle(extra);
13548233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.findItem(R.id.email_context_menu_id).setIntent(
13558233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new Intent(Intent.ACTION_VIEW, Uri
13568233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                .parse(WebView.SCHEME_MAILTO + extra)));
13578233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.findItem(R.id.copy_mail_context_menu_id)
13588233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        .setOnMenuItemClickListener(
13598233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new Copy(extra));
13608233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
13618233facddcc51865d612a919d450db6954aa48e3Michael Kolb
13628233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case WebView.HitTestResult.GEO_TYPE:
13638233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.setHeaderTitle(extra);
13648233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.findItem(R.id.map_context_menu_id).setIntent(
13658233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new Intent(Intent.ACTION_VIEW, Uri
13668233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                .parse(WebView.SCHEME_GEO
13678233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                        + URLEncoder.encode(extra))));
13688233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.findItem(R.id.copy_geo_context_menu_id)
13698233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        .setOnMenuItemClickListener(
13708233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new Copy(extra));
13718233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
13728233facddcc51865d612a919d450db6954aa48e3Michael Kolb
13738233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case WebView.HitTestResult.SRC_ANCHOR_TYPE:
13748233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
13754c537ce641be22ca0ce49a73bbbf92c36bd061feMichael Kolb                menu.setHeaderTitle(extra);
13768233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // decide whether to show the open link in new tab option
13778233facddcc51865d612a919d450db6954aa48e3Michael Kolb                boolean showNewTab = mTabControl.canCreateNewTab();
13788233facddcc51865d612a919d450db6954aa48e3Michael Kolb                MenuItem newTabItem
13798233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        = menu.findItem(R.id.open_newtab_context_menu_id);
138035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                newTabItem.setTitle(getSettings().openInBackground()
13812dd65c8bf13b11c99c78ec22a0fef2c58494bb9eMichael Kolb                        ? R.string.contextmenu_openlink_newwindow_background
13822dd65c8bf13b11c99c78ec22a0fef2c58494bb9eMichael Kolb                        : R.string.contextmenu_openlink_newwindow);
13838233facddcc51865d612a919d450db6954aa48e3Michael Kolb                newTabItem.setVisible(showNewTab);
13848233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (showNewTab) {
1385026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                    if (WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE == type) {
1386026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                        newTabItem.setOnMenuItemClickListener(
1387026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                new MenuItem.OnMenuItemClickListener() {
1388026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                    @Override
1389026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                    public boolean onMenuItemClick(MenuItem item) {
1390026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                        final HashMap<String, WebView> hrefMap =
1391026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                                new HashMap<String, WebView>();
1392026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                        hrefMap.put("webview", webview);
1393026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                        final Message msg = mHandler.obtainMessage(
1394026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                                FOCUS_NODE_HREF,
1395026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                                R.id.open_newtab_context_menu_id,
1396026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                                0, hrefMap);
1397026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                        webview.requestFocusNodeHref(msg);
1398026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                        return true;
13998233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                    }
1400026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                });
1401026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                    } else {
1402026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                        newTabItem.setOnMenuItemClickListener(
1403026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                new MenuItem.OnMenuItemClickListener() {
1404026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                    @Override
1405026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                    public boolean onMenuItemClick(MenuItem item) {
1406026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                        final Tab parent = mTabControl.getCurrentTab();
14075949c661b51295148706d53a03b41df2eb840ae3John Reck                                        openTab(extra, parent,
14085949c661b51295148706d53a03b41df2eb840ae3John Reck                                                !mSettings.openInBackground(),
14095949c661b51295148706d53a03b41df2eb840ae3John Reck                                                true);
1410026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                        return true;
1411026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                    }
1412026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                                });
1413026f254cff9d762a9f9c9d9bf74f15809d730cd2Leon Scroggins                    }
14148233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
14158233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (type == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
14168233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    break;
14178233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
14188233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // otherwise fall through to handle image part
14198233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case WebView.HitTestResult.IMAGE_TYPE:
14205987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                MenuItem shareItem = menu.findItem(R.id.share_link_context_menu_id);
14215987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                shareItem.setVisible(type == WebView.HitTestResult.IMAGE_TYPE);
14228233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (type == WebView.HitTestResult.IMAGE_TYPE) {
14238233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    menu.setHeaderTitle(extra);
14245987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                    shareItem.setOnMenuItemClickListener(
14255987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                            new MenuItem.OnMenuItemClickListener() {
14265987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                                @Override
14275987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                                public boolean onMenuItemClick(MenuItem item) {
14285987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                                    sharePage(mActivity, null, extra, null,
14295987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                                    null);
14305987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                                    return true;
14315987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                                }
14325987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                            }
14335987b806b08b9511d139555d529bbe11ddbdc8b4Victoria Lease                        );
14348233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
14353639c4c7f0be061143869bce30a3f62dbeb0f773Michael Kolb                menu.findItem(R.id.view_image_context_menu_id)
14363639c4c7f0be061143869bce30a3f62dbeb0f773Michael Kolb                        .setOnMenuItemClickListener(new OnMenuItemClickListener() {
14373639c4c7f0be061143869bce30a3f62dbeb0f773Michael Kolb                    @Override
14383639c4c7f0be061143869bce30a3f62dbeb0f773Michael Kolb                    public boolean onMenuItemClick(MenuItem item) {
14393639c4c7f0be061143869bce30a3f62dbeb0f773Michael Kolb                        openTab(extra, mTabControl.getCurrentTab(), true, true);
14403639c4c7f0be061143869bce30a3f62dbeb0f773Michael Kolb                        return false;
14413639c4c7f0be061143869bce30a3f62dbeb0f773Michael Kolb                    }
14423639c4c7f0be061143869bce30a3f62dbeb0f773Michael Kolb                });
14438e4ce660cd8576237b4ff30c40b21570af3af4f3Andreas Sandblad                menu.findItem(R.id.download_context_menu_id).setOnMenuItemClickListener(
14448e4ce660cd8576237b4ff30c40b21570af3af4f3Andreas Sandblad                        new Download(mActivity, extra, webview.isPrivateBrowsingEnabled(),
14458e4ce660cd8576237b4ff30c40b21570af3af4f3Andreas Sandblad                                webview.getSettings().getUserAgentString()));
14463527dd1ff849ec4798eab6289593aa404dcae40bJohn Reck                menu.findItem(R.id.set_wallpaper_context_menu_id).
14473527dd1ff849ec4798eab6289593aa404dcae40bJohn Reck                        setOnMenuItemClickListener(new WallpaperHandler(mActivity,
14483527dd1ff849ec4798eab6289593aa404dcae40bJohn Reck                                extra));
14498233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
14508233facddcc51865d612a919d450db6954aa48e3Michael Kolb
14518233facddcc51865d612a919d450db6954aa48e3Michael Kolb            default:
14528233facddcc51865d612a919d450db6954aa48e3Michael Kolb                Log.w(LOGTAG, "We should not get here.");
14538233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
14548233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
14558233facddcc51865d612a919d450db6954aa48e3Michael Kolb        //update the ui
14568233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.onContextMenuCreated(menu);
14578233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
14588233facddcc51865d612a919d450db6954aa48e3Michael Kolb
14598233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
14608233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * As the menu can be open when loading state changes
14618233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * we must manually update the state of the stop/reload menu
14628233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * item
14638233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
1464b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb    private void updateInLoadMenuItems(Menu menu, Tab tab) {
14658233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (menu == null) {
14668233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
14678233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
14688233facddcc51865d612a919d450db6954aa48e3Michael Kolb        MenuItem dest = menu.findItem(R.id.stop_reload_menu_id);
1469b8337131d2e1b9a3ad0d8f619c47407b4349ea89Michael Kolb        MenuItem src = ((tab != null) && tab.inPageLoad()) ?
14708233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.findItem(R.id.stop_menu_id):
14718233facddcc51865d612a919d450db6954aa48e3Michael Kolb                menu.findItem(R.id.reload_menu_id);
14728233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (src != null) {
14738233facddcc51865d612a919d450db6954aa48e3Michael Kolb            dest.setIcon(src.getIcon());
14748233facddcc51865d612a919d450db6954aa48e3Michael Kolb            dest.setTitle(src.getTitle());
14758233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
14768233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
14778233facddcc51865d612a919d450db6954aa48e3Michael Kolb
14789c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
14799c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public boolean onPrepareOptionsMenu(Menu menu) {
1480b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb        updateInLoadMenuItems(menu, getCurrentTab());
1481e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck        // hold on to the menu reference here; it is used by the page callbacks
1482e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck        // to update the menu based on loading state
1483e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck        mCachedMenu = menu;
14848233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Note: setVisible will decide whether an item is visible; while
14858233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // setEnabled() will decide whether an item is enabled, which also means
14868233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // whether the matching shortcut key will function.
14878233facddcc51865d612a919d450db6954aa48e3Michael Kolb        switch (mMenuState) {
14888233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case EMPTY_MENU:
14898233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (mCurrentMenuState != mMenuState) {
14908233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    menu.setGroupVisible(R.id.MAIN_MENU, false);
14918233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    menu.setGroupEnabled(R.id.MAIN_MENU, false);
14928233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    menu.setGroupEnabled(R.id.MAIN_SHORTCUT_MENU, false);
14938233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
14948233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
14958233facddcc51865d612a919d450db6954aa48e3Michael Kolb            default:
14968233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (mCurrentMenuState != mMenuState) {
14978233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    menu.setGroupVisible(R.id.MAIN_MENU, true);
14988233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    menu.setGroupEnabled(R.id.MAIN_MENU, true);
14998233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    menu.setGroupEnabled(R.id.MAIN_SHORTCUT_MENU, true);
15008233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
15014bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb                updateMenuState(getCurrentTab(), menu);
15028233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
15038233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
15048233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mCurrentMenuState = mMenuState;
15051acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        return mUi.onPrepareOptionsMenu(menu);
15068233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
15078233facddcc51865d612a919d450db6954aa48e3Michael Kolb
15084bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb    @Override
15094bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb    public void updateMenuState(Tab tab, Menu menu) {
15104bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        boolean canGoBack = false;
15114bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        boolean canGoForward = false;
15124bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        boolean isHome = false;
151342229bcdea8a1623d9ac3fce099793a3767fb14dJohn Reck        boolean isDesktopUa = false;
1514e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck        boolean isLive = false;
15154bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        if (tab != null) {
15164bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb            canGoBack = tab.canGoBack();
15174bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb            canGoForward = tab.canGoForward();
15184bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb            isHome = mSettings.getHomePage().equals(tab.getUrl());
151942229bcdea8a1623d9ac3fce099793a3767fb14dJohn Reck            isDesktopUa = mSettings.hasDesktopUseragent(tab.getWebView());
1520e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck            isLive = !tab.isSnapshot();
15214bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        }
15224bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        final MenuItem back = menu.findItem(R.id.back_menu_id);
15234bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        back.setEnabled(canGoBack);
15244bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb
15254bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        final MenuItem home = menu.findItem(R.id.homepage_menu_id);
15264bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        home.setEnabled(!isHome);
15274bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb
15284bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        final MenuItem forward = menu.findItem(R.id.forward_menu_id);
15294bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        forward.setEnabled(canGoForward);
15304bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb
1531b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb        final MenuItem source = menu.findItem(isInLoad() ? R.id.stop_menu_id
1532b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb                : R.id.reload_menu_id);
15334bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        final MenuItem dest = menu.findItem(R.id.stop_reload_menu_id);
15347ab75ee486cd0e316dda66d2c6a73b0de1f16332Michael Kolb        if (source != null && dest != null) {
15357ab75ee486cd0e316dda66d2c6a73b0de1f16332Michael Kolb            dest.setTitle(source.getTitle());
15367ab75ee486cd0e316dda66d2c6a73b0de1f16332Michael Kolb            dest.setIcon(source.getIcon());
15377ab75ee486cd0e316dda66d2c6a73b0de1f16332Michael Kolb        }
1538e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck        menu.setGroupVisible(R.id.NAV_MENU, isLive);
15394bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb
15404bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        // decide whether to show the share link option
15414bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        PackageManager pm = mActivity.getPackageManager();
15424bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        Intent send = new Intent(Intent.ACTION_SEND);
15434bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        send.setType("text/plain");
15444bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        ResolveInfo ri = pm.resolveActivity(send,
15454bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb                PackageManager.MATCH_DEFAULT_ONLY);
15464bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        menu.findItem(R.id.share_page_menu_id).setVisible(ri != null);
15474bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb
15484bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        boolean isNavDump = mSettings.enableNavDump();
15494bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        final MenuItem nav = menu.findItem(R.id.dump_nav_menu_id);
15504bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        nav.setVisible(isNavDump);
15514bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        nav.setEnabled(isNavDump);
15524bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb
15534bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb        boolean showDebugSettings = mSettings.isDebugEnabled();
155442229bcdea8a1623d9ac3fce099793a3767fb14dJohn Reck        final MenuItem uaSwitcher = menu.findItem(R.id.ua_desktop_menu_id);
155542229bcdea8a1623d9ac3fce099793a3767fb14dJohn Reck        uaSwitcher.setChecked(isDesktopUa);
1556e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck        menu.setGroupVisible(R.id.LIVE_MENU, isLive);
1557e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck        menu.setGroupVisible(R.id.SNAPSHOT_MENU, !isLive);
1558315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb        menu.setGroupVisible(R.id.COMBO_MENU, false);
15594bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb
15607bdee0b303d8969aace4d3e43be5bb9f16e276bfMichael Kolb        mUi.updateMenuState(tab, menu);
15614bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb    }
15624bf7971ed99aa273dc8ea9cf610cd6fa168c5dcbMichael Kolb
15639c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
15648233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public boolean onOptionsItemSelected(MenuItem item) {
15658233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (null == getCurrentTopWebView()) {
15668233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return false;
15678233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
15688233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mMenuIsDown) {
15698233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // The shortcut action consumes the MENU. Even if it is still down,
15708233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // it won't trigger the next shortcut action. In the case of the
15718233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // shortcut action triggering a new activity, like Bookmarks, we
15728233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // won't get onKeyUp for MENU. So it is important to reset it here.
15738233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mMenuIsDown = false;
15748233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
15753ca12750f9b6231b00a1856dcb25c2d2e07e8784Michael Kolb        if (mUi.onOptionsItemSelected(item)) {
15763ca12750f9b6231b00a1856dcb25c2d2e07e8784Michael Kolb            // ui callback handled it
15773ca12750f9b6231b00a1856dcb25c2d2e07e8784Michael Kolb            return true;
15783ca12750f9b6231b00a1856dcb25c2d2e07e8784Michael Kolb        }
15798233facddcc51865d612a919d450db6954aa48e3Michael Kolb        switch (item.getItemId()) {
15808233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // -- Main menu
15818233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.new_tab_menu_id:
15828233facddcc51865d612a919d450db6954aa48e3Michael Kolb                openTabToHomePage();
15838233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
15848233facddcc51865d612a919d450db6954aa48e3Michael Kolb
15858233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.incognito_menu_id:
1586519d22840ea587988214a625dc8106e1302ac4a9Michael Kolb                openIncognitoTab();
15878233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
15888233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1589d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam            case R.id.close_other_tabs_id:
1590d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam                closeOtherTabs();
1591d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam                break;
1592d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam
15938233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.goto_menu_id:
15948233facddcc51865d612a919d450db6954aa48e3Michael Kolb                editUrl();
15958233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
15968233facddcc51865d612a919d450db6954aa48e3Michael Kolb
15978233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.bookmarks_menu_id:
1598315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb                bookmarksOrHistoryPicker(ComboViews.Bookmarks);
1599315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb                break;
1600315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb
1601315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb            case R.id.history_menu_id:
1602315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb                bookmarksOrHistoryPicker(ComboViews.History);
1603315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb                break;
1604315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb
1605315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb            case R.id.snapshots_menu_id:
1606315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb                bookmarksOrHistoryPicker(ComboViews.Snapshots);
16078233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16088233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16098233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.add_bookmark_menu_id:
161080f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb                bookmarkCurrentPage();
16118233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16128233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16138233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.stop_reload_menu_id:
1614b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb                if (isInLoad()) {
16158233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    stopLoading();
16168233facddcc51865d612a919d450db6954aa48e3Michael Kolb                } else {
16178233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    getCurrentTopWebView().reload();
16188233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
16198233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16208233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16218233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.back_menu_id:
1622ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck                getCurrentTab().goBack();
16238233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16248233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16258233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.forward_menu_id:
1626ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck                getCurrentTab().goForward();
16278233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16288233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16298233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.close_menu_id:
16308233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // Close the subwindow if it exists.
16318233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (mTabControl.getCurrentSubWindow() != null) {
16328233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    dismissSubWindow(mTabControl.getCurrentTab());
16338233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    break;
16348233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
16358233facddcc51865d612a919d450db6954aa48e3Michael Kolb                closeCurrentTab();
16368233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16378233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16388233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.homepage_menu_id:
16398233facddcc51865d612a919d450db6954aa48e3Michael Kolb                Tab current = mTabControl.getCurrentTab();
164026b183292dc087b16af10f482744c3bb30e1f163John Reck                loadUrl(current, mSettings.getHomePage());
16418233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16428233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16438233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.preferences_menu_id:
164480f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb                openPreferences();
16458233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16468233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16478233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.find_menu_id:
1648e11b9212f201f787652737cab586f7cf28c27dd0Michael Kolb                findOnPage();
16498233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16508233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16512bc8042224be51966d748b870768ec1b376a1621John Reck            case R.id.save_snapshot_menu_id:
16522bc8042224be51966d748b870768ec1b376a1621John Reck                final Tab source = getTabControl().getCurrentTab();
1653f33b1637487af3786ee30f295f2c84db6db1e6b3John Reck                if (source == null) break;
165468234a9351dfca2e68769de46e60d22ec2f03818John Reck                new SaveSnapshotTask(source).execute();
1655ac993841b3f810dd55a985141c574d4dfebd8c1aLeon Scroggins                break;
1656ac993841b3f810dd55a985141c574d4dfebd8c1aLeon Scroggins
16578233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.page_info_menu_id:
1658315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb                showPageInfo();
16598233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16608233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1661e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck            case R.id.snapshot_go_live:
1662e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck                goLive();
1663e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck                return true;
1664e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck
16658233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.share_page_menu_id:
16668233facddcc51865d612a919d450db6954aa48e3Michael Kolb                Tab currentTab = mTabControl.getCurrentTab();
16678233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (null == currentTab) {
16688233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    return false;
16698233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
1670ba99c5d1a71c384c930152f7c98e2fbe15bd1e85Michael Kolb                shareCurrentPage(currentTab);
16718233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16728233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16738233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.dump_nav_menu_id:
16748233facddcc51865d612a919d450db6954aa48e3Michael Kolb                getCurrentTopWebView().debugDump();
16758233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16768233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16778233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.zoom_in_menu_id:
16788233facddcc51865d612a919d450db6954aa48e3Michael Kolb                getCurrentTopWebView().zoomIn();
16798233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16808233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16818233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.zoom_out_menu_id:
16828233facddcc51865d612a919d450db6954aa48e3Michael Kolb                getCurrentTopWebView().zoomOut();
16838233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16848233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16858233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.view_downloads_menu_id:
16868233facddcc51865d612a919d450db6954aa48e3Michael Kolb                viewDownloads();
16878233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
16888233facddcc51865d612a919d450db6954aa48e3Michael Kolb
168942229bcdea8a1623d9ac3fce099793a3767fb14dJohn Reck            case R.id.ua_desktop_menu_id:
169080f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb                toggleUserAgent();
169142229bcdea8a1623d9ac3fce099793a3767fb14dJohn Reck                break;
169242229bcdea8a1623d9ac3fce099793a3767fb14dJohn Reck
16938233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.window_one_menu_id:
16948233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.window_two_menu_id:
16958233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.window_three_menu_id:
16968233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.window_four_menu_id:
16978233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.window_five_menu_id:
16988233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.window_six_menu_id:
16998233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.window_seven_menu_id:
17008233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.window_eight_menu_id:
17018233facddcc51865d612a919d450db6954aa48e3Michael Kolb                {
17028233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    int menuid = item.getItemId();
17038233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    for (int id = 0; id < WINDOW_SHORTCUT_ID_ARRAY.length; id++) {
17048233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        if (WINDOW_SHORTCUT_ID_ARRAY[id] == menuid) {
17058233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            Tab desiredTab = mTabControl.getTab(id);
17068233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            if (desiredTab != null &&
17078233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                    desiredTab != mTabControl.getCurrentTab()) {
1708c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                                switchToTab(desiredTab);
17098233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            }
17108233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            break;
17118233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
17128233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
17138233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
17148233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
17158233facddcc51865d612a919d450db6954aa48e3Michael Kolb
17168233facddcc51865d612a919d450db6954aa48e3Michael Kolb            default:
17178233facddcc51865d612a919d450db6954aa48e3Michael Kolb                return false;
17188233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
17198233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return true;
17208233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
17218233facddcc51865d612a919d450db6954aa48e3Michael Kolb
172268234a9351dfca2e68769de46e60d22ec2f03818John Reck    private class SaveSnapshotTask extends AsyncTask<Void, Void, Long>
172368234a9351dfca2e68769de46e60d22ec2f03818John Reck            implements OnCancelListener {
172468234a9351dfca2e68769de46e60d22ec2f03818John Reck
172568234a9351dfca2e68769de46e60d22ec2f03818John Reck        private Tab mTab;
172668234a9351dfca2e68769de46e60d22ec2f03818John Reck        private Dialog mProgressDialog;
172768234a9351dfca2e68769de46e60d22ec2f03818John Reck        private ContentValues mValues;
172868234a9351dfca2e68769de46e60d22ec2f03818John Reck
172968234a9351dfca2e68769de46e60d22ec2f03818John Reck        private SaveSnapshotTask(Tab tab) {
173068234a9351dfca2e68769de46e60d22ec2f03818John Reck            mTab = tab;
173168234a9351dfca2e68769de46e60d22ec2f03818John Reck        }
173268234a9351dfca2e68769de46e60d22ec2f03818John Reck
173368234a9351dfca2e68769de46e60d22ec2f03818John Reck        @Override
173468234a9351dfca2e68769de46e60d22ec2f03818John Reck        protected void onPreExecute() {
173568234a9351dfca2e68769de46e60d22ec2f03818John Reck            CharSequence message = mActivity.getText(R.string.saving_snapshot);
173668234a9351dfca2e68769de46e60d22ec2f03818John Reck            mProgressDialog = ProgressDialog.show(mActivity, null, message,
173768234a9351dfca2e68769de46e60d22ec2f03818John Reck                    true, true, this);
173868234a9351dfca2e68769de46e60d22ec2f03818John Reck            mValues = mTab.createSnapshotValues();
173968234a9351dfca2e68769de46e60d22ec2f03818John Reck        }
174068234a9351dfca2e68769de46e60d22ec2f03818John Reck
174168234a9351dfca2e68769de46e60d22ec2f03818John Reck        @Override
174268234a9351dfca2e68769de46e60d22ec2f03818John Reck        protected Long doInBackground(Void... params) {
174368234a9351dfca2e68769de46e60d22ec2f03818John Reck            if (!mTab.saveViewState(mValues)) {
174468234a9351dfca2e68769de46e60d22ec2f03818John Reck                return null;
174568234a9351dfca2e68769de46e60d22ec2f03818John Reck            }
174668234a9351dfca2e68769de46e60d22ec2f03818John Reck            if (isCancelled()) {
174768234a9351dfca2e68769de46e60d22ec2f03818John Reck                String path = mValues.getAsString(Snapshots.VIEWSTATE_PATH);
174868234a9351dfca2e68769de46e60d22ec2f03818John Reck                File file = mActivity.getFileStreamPath(path);
174968234a9351dfca2e68769de46e60d22ec2f03818John Reck                if (!file.delete()) {
175068234a9351dfca2e68769de46e60d22ec2f03818John Reck                    file.deleteOnExit();
175168234a9351dfca2e68769de46e60d22ec2f03818John Reck                }
175268234a9351dfca2e68769de46e60d22ec2f03818John Reck                return null;
175368234a9351dfca2e68769de46e60d22ec2f03818John Reck            }
175468234a9351dfca2e68769de46e60d22ec2f03818John Reck            final ContentResolver cr = mActivity.getContentResolver();
175568234a9351dfca2e68769de46e60d22ec2f03818John Reck            Uri result = cr.insert(Snapshots.CONTENT_URI, mValues);
175668234a9351dfca2e68769de46e60d22ec2f03818John Reck            if (result == null) {
175768234a9351dfca2e68769de46e60d22ec2f03818John Reck                return null;
175868234a9351dfca2e68769de46e60d22ec2f03818John Reck            }
175968234a9351dfca2e68769de46e60d22ec2f03818John Reck            long id = ContentUris.parseId(result);
176068234a9351dfca2e68769de46e60d22ec2f03818John Reck            return id;
176168234a9351dfca2e68769de46e60d22ec2f03818John Reck        }
176268234a9351dfca2e68769de46e60d22ec2f03818John Reck
176368234a9351dfca2e68769de46e60d22ec2f03818John Reck        @Override
176468234a9351dfca2e68769de46e60d22ec2f03818John Reck        protected void onPostExecute(Long id) {
176568234a9351dfca2e68769de46e60d22ec2f03818John Reck            if (isCancelled()) {
176668234a9351dfca2e68769de46e60d22ec2f03818John Reck                return;
176768234a9351dfca2e68769de46e60d22ec2f03818John Reck            }
176868234a9351dfca2e68769de46e60d22ec2f03818John Reck            mProgressDialog.dismiss();
176968234a9351dfca2e68769de46e60d22ec2f03818John Reck            if (id == null) {
177068234a9351dfca2e68769de46e60d22ec2f03818John Reck                Toast.makeText(mActivity, R.string.snapshot_failed,
177168234a9351dfca2e68769de46e60d22ec2f03818John Reck                        Toast.LENGTH_SHORT).show();
177268234a9351dfca2e68769de46e60d22ec2f03818John Reck                return;
177368234a9351dfca2e68769de46e60d22ec2f03818John Reck            }
177468234a9351dfca2e68769de46e60d22ec2f03818John Reck            Bundle b = new Bundle();
177568234a9351dfca2e68769de46e60d22ec2f03818John Reck            b.putLong(BrowserSnapshotPage.EXTRA_ANIMATE_ID, id);
177668234a9351dfca2e68769de46e60d22ec2f03818John Reck            mUi.showComboView(ComboViews.Snapshots, b);
177768234a9351dfca2e68769de46e60d22ec2f03818John Reck        }
177868234a9351dfca2e68769de46e60d22ec2f03818John Reck
177968234a9351dfca2e68769de46e60d22ec2f03818John Reck        @Override
178068234a9351dfca2e68769de46e60d22ec2f03818John Reck        public void onCancel(DialogInterface dialog) {
178168234a9351dfca2e68769de46e60d22ec2f03818John Reck            cancel(true);
178268234a9351dfca2e68769de46e60d22ec2f03818John Reck        }
178368234a9351dfca2e68769de46e60d22ec2f03818John Reck    }
178468234a9351dfca2e68769de46e60d22ec2f03818John Reck
178580f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    @Override
178680f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    public void toggleUserAgent() {
178780f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb        WebView web = getCurrentWebView();
178880f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb        mSettings.toggleDesktopUseragent(web);
178980f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb        web.loadUrl(web.getOriginalUrl());
179080f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    }
179180f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb
179280f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    @Override
179380f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    public void findOnPage() {
179480f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb        getCurrentTopWebView().showFindDialog(null, true);
179580f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    }
179680f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb
179780f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    @Override
179880f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    public void openPreferences() {
179980f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb        Intent intent = new Intent(mActivity, BrowserPreferencesPage.class);
180080f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb        intent.putExtra(BrowserPreferencesPage.CURRENT_PAGE,
180180f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb                getCurrentTopWebView().getUrl());
180280f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb        mActivity.startActivityForResult(intent, PREFERENCES_PAGE);
180380f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    }
180480f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb
180580f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    @Override
180680f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    public void bookmarkCurrentPage() {
180780f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb        Intent bookmarkIntent = createBookmarkCurrentPageIntent(false);
180880f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb        if (bookmarkIntent != null) {
180980f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb            mActivity.startActivity(bookmarkIntent);
181080f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb        }
181180f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb    }
181280f750852edf43c6b09e5633f2c6ebdb2ed94a5bMichael Kolb
1813e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck    private void goLive() {
1814e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck        Tab t = getCurrentTab();
1815e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck        t.loadUrl(t.getUrl(), null);
1816e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck    }
1817e1a03a366ff90ebcd8568a86b84a5917610cf512John Reck
1818315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb    @Override
1819315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb    public void showPageInfo() {
1820315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb        mPageDialogsHandler.showPageInfo(mTabControl.getCurrentTab(), false, null);
1821315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb    }
1822315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb
18239c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
18248233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public boolean onContextItemSelected(MenuItem item) {
1825dbf57df890f091286f0107933b0034d39629a9a8John Reck        // Let the History and Bookmark fragments handle menus they created.
1826dbf57df890f091286f0107933b0034d39629a9a8John Reck        if (item.getGroupId() == R.id.CONTEXT_MENU) {
1827dbf57df890f091286f0107933b0034d39629a9a8John Reck            return false;
1828dbf57df890f091286f0107933b0034d39629a9a8John Reck        }
1829dbf57df890f091286f0107933b0034d39629a9a8John Reck
18308233facddcc51865d612a919d450db6954aa48e3Michael Kolb        int id = item.getItemId();
18318233facddcc51865d612a919d450db6954aa48e3Michael Kolb        boolean result = true;
18328233facddcc51865d612a919d450db6954aa48e3Michael Kolb        switch (id) {
18338233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // -- Browser context menu
18348233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.open_context_menu_id:
18358233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.save_link_context_menu_id:
18368233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case R.id.copy_link_context_menu_id:
18378233facddcc51865d612a919d450db6954aa48e3Michael Kolb                final WebView webView = getCurrentTopWebView();
18388233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (null == webView) {
18398233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    result = false;
18408233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    break;
18418233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
18428233facddcc51865d612a919d450db6954aa48e3Michael Kolb                final HashMap<String, WebView> hrefMap =
18438233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new HashMap<String, WebView>();
18448233facddcc51865d612a919d450db6954aa48e3Michael Kolb                hrefMap.put("webview", webView);
18458233facddcc51865d612a919d450db6954aa48e3Michael Kolb                final Message msg = mHandler.obtainMessage(
18468233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        FOCUS_NODE_HREF, id, 0, hrefMap);
18478233facddcc51865d612a919d450db6954aa48e3Michael Kolb                webView.requestFocusNodeHref(msg);
18488233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
18498233facddcc51865d612a919d450db6954aa48e3Michael Kolb
18508233facddcc51865d612a919d450db6954aa48e3Michael Kolb            default:
18518233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // For other context menus
18528233facddcc51865d612a919d450db6954aa48e3Michael Kolb                result = onOptionsItemSelected(item);
18538233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
18548233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return result;
18558233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
18568233facddcc51865d612a919d450db6954aa48e3Michael Kolb
18578233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
18588233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * support programmatically opening the context menu
18598233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
18608233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void openContextMenu(View view) {
18618233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActivity.openContextMenu(view);
18628233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
18638233facddcc51865d612a919d450db6954aa48e3Michael Kolb
18648233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
18658233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * programmatically open the options menu
18668233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
18678233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void openOptionsMenu() {
18688233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActivity.openOptionsMenu();
18698233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
18708233facddcc51865d612a919d450db6954aa48e3Michael Kolb
18719c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
18728233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public boolean onMenuOpened(int featureId, Menu menu) {
18738233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mOptionsMenuOpen) {
18748233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (mConfigChanged) {
18758233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // We do not need to make any changes to the state of the
18768233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // title bar, since the only thing that happened was a
18778233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // change in orientation
18788233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mConfigChanged = false;
18798233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else {
18808233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (!mExtendedMenuOpen) {
18818233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    mExtendedMenuOpen = true;
18828233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    mUi.onExtendedMenuOpened();
18838233facddcc51865d612a919d450db6954aa48e3Michael Kolb                } else {
18848233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    // Switching the menu back to icon view, so show the
18858233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    // title bar once again.
18868233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    mExtendedMenuOpen = false;
1887b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb                    mUi.onExtendedMenuClosed(isInLoad());
18888233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
18898233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
18908233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else {
18918233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // The options menu is closed, so open it, and show the title
18928233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mOptionsMenuOpen = true;
18938233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mConfigChanged = false;
18948233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mExtendedMenuOpen = false;
18958233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mUi.onOptionsMenuOpened();
18968233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
18978233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return true;
18988233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
18998233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19009c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
19018233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void onOptionsMenuClosed(Menu menu) {
19028233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mOptionsMenuOpen = false;
1903b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb        mUi.onOptionsMenuClosed(isInLoad());
19048233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
19058233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19069c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
19078233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void onContextMenuClosed(Menu menu) {
1908b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb        mUi.onContextMenuClosed(menu, isInLoad());
19098233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
19108233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19118233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // Helper method for getting the top window.
19128233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
19138233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public WebView getCurrentTopWebView() {
19148233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mTabControl.getCurrentTopWebView();
19158233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
19168233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19178233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
19188233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public WebView getCurrentWebView() {
19198233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mTabControl.getCurrentWebView();
19208233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
19218233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19228233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /*
19238233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * This method is called as a result of the user selecting the options
19248233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * menu to see the download window. It shows the download window on top of
19258233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * the current window.
19268233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
19278233facddcc51865d612a919d450db6954aa48e3Michael Kolb    void viewDownloads() {
19288233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Intent intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
19298233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActivity.startActivity(intent);
19308233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
19318233facddcc51865d612a919d450db6954aa48e3Michael Kolb
193230b065e9c311ab1a8973caeb85a0861c8802b043John Reck    int getActionModeHeight() {
193330b065e9c311ab1a8973caeb85a0861c8802b043John Reck        TypedArray actionBarSizeTypedArray = mActivity.obtainStyledAttributes(
193430b065e9c311ab1a8973caeb85a0861c8802b043John Reck                    new int[] { android.R.attr.actionBarSize });
193530b065e9c311ab1a8973caeb85a0861c8802b043John Reck        int size = (int) actionBarSizeTypedArray.getDimension(0, 0f);
193630b065e9c311ab1a8973caeb85a0861c8802b043John Reck        actionBarSizeTypedArray.recycle();
193730b065e9c311ab1a8973caeb85a0861c8802b043John Reck        return size;
193830b065e9c311ab1a8973caeb85a0861c8802b043John Reck    }
193930b065e9c311ab1a8973caeb85a0861c8802b043John Reck
19408233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // action mode
19418233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19429c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
19439c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public void onActionModeStarted(ActionMode mode) {
19448233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.onActionModeStarted(mode);
19458233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActionMode = mode;
19468233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
19478233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19488233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /*
19498233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * True if a custom ActionMode (i.e. find or select) is in use.
19508233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
19518233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
19528233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public boolean isInCustomActionMode() {
19538233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mActionMode != null;
19548233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
19558233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19568233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /*
19578233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * End the current ActionMode.
19588233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
19598233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
19608233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void endActionMode() {
19618233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mActionMode != null) {
19628233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mActionMode.finish();
19638233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
19648233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
19658233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19668233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /*
19678233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Called by find and select when they are finished.  Replace title bars
19688233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * as necessary.
19698233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
19709c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
19718233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void onActionModeFinished(ActionMode mode) {
19728233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (!isInCustomActionMode()) return;
1973b1fb70cee9e24f3f9e648dff1816403c427976d1Michael Kolb        mUi.onActionModeFinished(isInLoad());
19748233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActionMode = null;
19758233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
19768233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19778233facddcc51865d612a919d450db6954aa48e3Michael Kolb    boolean isInLoad() {
1978c5b0b2db3b917e658700642763fb50da0057716bMichael Kolb        final Tab tab = getCurrentTab();
1979c5b0b2db3b917e658700642763fb50da0057716bMichael Kolb        return (tab != null) && tab.inPageLoad();
19808233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
19818233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19828233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // bookmark handling
19838233facddcc51865d612a919d450db6954aa48e3Michael Kolb
19848233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
19858233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * add the current page as a bookmark to the given folder id
19868233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param folderId use -1 for the default folder
1987d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck     * @param editExisting If true, check to see whether the site is already
1988bdff8a72bd9894fc59ca658442e6ead37a56fa5dLeon Scroggins     *          bookmarked, and if it is, edit that bookmark.  If false, and
1989bdff8a72bd9894fc59ca658442e6ead37a56fa5dLeon Scroggins     *          the site is already bookmarked, do not attempt to edit the
1990bdff8a72bd9894fc59ca658442e6ead37a56fa5dLeon Scroggins     *          existing bookmark.
19918233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
19928233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
1993d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck    public Intent createBookmarkCurrentPageIntent(boolean editExisting) {
1994a60fffaa18e26b29880c7ce21548af4f8ec0e443John Reck        WebView w = getCurrentTopWebView();
1995a60fffaa18e26b29880c7ce21548af4f8ec0e443John Reck        if (w == null) {
1996a60fffaa18e26b29880c7ce21548af4f8ec0e443John Reck            return null;
1997a60fffaa18e26b29880c7ce21548af4f8ec0e443John Reck        }
19988233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Intent i = new Intent(mActivity,
19998233facddcc51865d612a919d450db6954aa48e3Michael Kolb                AddBookmarkPage.class);
20008233facddcc51865d612a919d450db6954aa48e3Michael Kolb        i.putExtra(BrowserContract.Bookmarks.URL, w.getUrl());
20018233facddcc51865d612a919d450db6954aa48e3Michael Kolb        i.putExtra(BrowserContract.Bookmarks.TITLE, w.getTitle());
20028233facddcc51865d612a919d450db6954aa48e3Michael Kolb        String touchIconUrl = w.getTouchIconUrl();
20038233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (touchIconUrl != null) {
20048233facddcc51865d612a919d450db6954aa48e3Michael Kolb            i.putExtra(AddBookmarkPage.TOUCH_ICON_URL, touchIconUrl);
20058233facddcc51865d612a919d450db6954aa48e3Michael Kolb            WebSettings settings = w.getSettings();
20068233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (settings != null) {
20078233facddcc51865d612a919d450db6954aa48e3Michael Kolb                i.putExtra(AddBookmarkPage.USER_AGENT,
20088233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        settings.getUserAgentString());
20098233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
20108233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
20118233facddcc51865d612a919d450db6954aa48e3Michael Kolb        i.putExtra(BrowserContract.Bookmarks.THUMBNAIL,
20128233facddcc51865d612a919d450db6954aa48e3Michael Kolb                createScreenshot(w, getDesiredThumbnailWidth(mActivity),
20138233facddcc51865d612a919d450db6954aa48e3Michael Kolb                getDesiredThumbnailHeight(mActivity)));
20148233facddcc51865d612a919d450db6954aa48e3Michael Kolb        i.putExtra(BrowserContract.Bookmarks.FAVICON, w.getFavicon());
2015d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck        if (editExisting) {
2016bdff8a72bd9894fc59ca658442e6ead37a56fa5dLeon Scroggins            i.putExtra(AddBookmarkPage.CHECK_FOR_DUPE, true);
2017bdff8a72bd9894fc59ca658442e6ead37a56fa5dLeon Scroggins        }
20188233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Put the dialog at the upper right of the screen, covering the
20198233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // star on the title bar.
20208233facddcc51865d612a919d450db6954aa48e3Michael Kolb        i.putExtra("gravity", Gravity.RIGHT | Gravity.TOP);
2021d3e4d5b4ffdf374b836ec9d4d3e315040c8c3779John Reck        return i;
20228233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
20238233facddcc51865d612a919d450db6954aa48e3Michael Kolb
20248233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // file chooser
20259c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
20268cad413fe902010140cf20aad47c2f4e7a51f8d2Ben Murdoch    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
20278233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUploadHandler = new UploadHandler(this);
20288cad413fe902010140cf20aad47c2f4e7a51f8d2Ben Murdoch        mUploadHandler.openFileChooser(uploadMsg, acceptType, capture);
20298233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
20308233facddcc51865d612a919d450db6954aa48e3Michael Kolb
20318233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // thumbnails
20328233facddcc51865d612a919d450db6954aa48e3Michael Kolb
20338233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
20348233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Return the desired width for thumbnail screenshots, which are stored in
20358233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * the database, and used on the bookmarks screen.
20368233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param context Context for finding out the density of the screen.
20378233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @return desired width for thumbnail screenshot.
20388233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
20398233facddcc51865d612a919d450db6954aa48e3Michael Kolb    static int getDesiredThumbnailWidth(Context context) {
20408233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return context.getResources().getDimensionPixelOffset(
20418233facddcc51865d612a919d450db6954aa48e3Michael Kolb                R.dimen.bookmarkThumbnailWidth);
20428233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
20438233facddcc51865d612a919d450db6954aa48e3Michael Kolb
20448233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
20458233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Return the desired height for thumbnail screenshots, which are stored in
20468233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * the database, and used on the bookmarks screen.
20478233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param context Context for finding out the density of the screen.
20488233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @return desired height for thumbnail screenshot.
20498233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
20508233facddcc51865d612a919d450db6954aa48e3Michael Kolb    static int getDesiredThumbnailHeight(Context context) {
20518233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return context.getResources().getDimensionPixelOffset(
20528233facddcc51865d612a919d450db6954aa48e3Michael Kolb                R.dimen.bookmarkThumbnailHeight);
20538233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
20548233facddcc51865d612a919d450db6954aa48e3Michael Kolb
20558cc9235816ac9b3f1b3551d6234684f0455746dcJohn Reck    static Bitmap createScreenshot(WebView view, int width, int height) {
2056d7dd9b2ecb12da278c053291b684b885ee574301John Reck        if (view == null || view.getContentHeight() == 0
2057d7dd9b2ecb12da278c053291b684b885ee574301John Reck                || view.getContentWidth() == 0) {
2058d7dd9b2ecb12da278c053291b684b885ee574301John Reck            return null;
2059d7dd9b2ecb12da278c053291b684b885ee574301John Reck        }
20605c6ac2f0bc02b9e91154f7c0b82a67c0a7bdd9b9John Reck        // We render to a bitmap 2x the desired size so that we can then
20615c6ac2f0bc02b9e91154f7c0b82a67c0a7bdd9b9John Reck        // re-scale it with filtering since canvas.scale doesn't filter
20625c6ac2f0bc02b9e91154f7c0b82a67c0a7bdd9b9John Reck        // This helps reduce aliasing at the cost of being slightly blurry
20635c6ac2f0bc02b9e91154f7c0b82a67c0a7bdd9b9John Reck        final int filter_scale = 2;
2064d7dd9b2ecb12da278c053291b684b885ee574301John Reck        int scaledWidth = width * filter_scale;
2065d7dd9b2ecb12da278c053291b684b885ee574301John Reck        int scaledHeight = height * filter_scale;
2066d7dd9b2ecb12da278c053291b684b885ee574301John Reck        if (sThumbnailBitmap == null || sThumbnailBitmap.getWidth() != scaledWidth
2067d7dd9b2ecb12da278c053291b684b885ee574301John Reck                || sThumbnailBitmap.getHeight() != scaledHeight) {
2068d7dd9b2ecb12da278c053291b684b885ee574301John Reck            if (sThumbnailBitmap != null) {
2069d7dd9b2ecb12da278c053291b684b885ee574301John Reck                sThumbnailBitmap.recycle();
2070d7dd9b2ecb12da278c053291b684b885ee574301John Reck                sThumbnailBitmap = null;
2071d7dd9b2ecb12da278c053291b684b885ee574301John Reck            }
2072d7dd9b2ecb12da278c053291b684b885ee574301John Reck            sThumbnailBitmap =
2073d7dd9b2ecb12da278c053291b684b885ee574301John Reck                    Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.RGB_565);
20748233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2075d7dd9b2ecb12da278c053291b684b885ee574301John Reck        Canvas canvas = new Canvas(sThumbnailBitmap);
2076d7dd9b2ecb12da278c053291b684b885ee574301John Reck        int contentWidth = view.getContentWidth();
2077d7dd9b2ecb12da278c053291b684b885ee574301John Reck        float overviewScale = scaledWidth / (view.getScale() * contentWidth);
2078d7dd9b2ecb12da278c053291b684b885ee574301John Reck        if (view instanceof BrowserWebView) {
2079d7dd9b2ecb12da278c053291b684b885ee574301John Reck            int dy = -((BrowserWebView)view).getTitleHeight();
2080d7dd9b2ecb12da278c053291b684b885ee574301John Reck            canvas.translate(0, dy * overviewScale);
20818233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
20828233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2083d7dd9b2ecb12da278c053291b684b885ee574301John Reck        canvas.scale(overviewScale, overviewScale);
20848233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2085d7dd9b2ecb12da278c053291b684b885ee574301John Reck        if (view instanceof BrowserWebView) {
2086d7dd9b2ecb12da278c053291b684b885ee574301John Reck            ((BrowserWebView)view).drawContent(canvas);
2087d7dd9b2ecb12da278c053291b684b885ee574301John Reck        } else {
2088d7dd9b2ecb12da278c053291b684b885ee574301John Reck            view.draw(canvas);
2089d7dd9b2ecb12da278c053291b684b885ee574301John Reck        }
2090d7dd9b2ecb12da278c053291b684b885ee574301John Reck        Bitmap ret = Bitmap.createScaledBitmap(sThumbnailBitmap,
2091d7dd9b2ecb12da278c053291b684b885ee574301John Reck                width, height, true);
209243cfe8a4521b5c153055fbfa181940bc56bb3b06Dianne Hackborn        canvas.setBitmap(null);
20935c6ac2f0bc02b9e91154f7c0b82a67c0a7bdd9b9John Reck        return ret;
20948233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
20958233facddcc51865d612a919d450db6954aa48e3Michael Kolb
209634ef26756a751b99b5c021ee2b9221c582c88208John Reck    private void updateScreenshot(Tab tab) {
20978233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // If this is a bookmarked site, add a screenshot to the database.
20988233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // FIXME: Would like to make sure there is actually something to
20998233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // draw, but the API for that (WebViewCore.pictureReady()) is not
21008233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // currently accessible here.
21018233facddcc51865d612a919d450db6954aa48e3Michael Kolb
210234ef26756a751b99b5c021ee2b9221c582c88208John Reck        WebView view = tab.getWebView();
21037a59120d6e25f9f6ae9a5f7e0cb177a9f4775d54John Reck        if (view == null) {
21047a59120d6e25f9f6ae9a5f7e0cb177a9f4775d54John Reck            // Tab was destroyed
21057a59120d6e25f9f6ae9a5f7e0cb177a9f4775d54John Reck            return;
21067a59120d6e25f9f6ae9a5f7e0cb177a9f4775d54John Reck        }
210734ef26756a751b99b5c021ee2b9221c582c88208John Reck        final String url = tab.getUrl();
210834ef26756a751b99b5c021ee2b9221c582c88208John Reck        final String originalUrl = view.getOriginalUrl();
210934ef26756a751b99b5c021ee2b9221c582c88208John Reck        if (TextUtils.isEmpty(url)) {
211034ef26756a751b99b5c021ee2b9221c582c88208John Reck            return;
211134ef26756a751b99b5c021ee2b9221c582c88208John Reck        }
211234ef26756a751b99b5c021ee2b9221c582c88208John Reck
211334ef26756a751b99b5c021ee2b9221c582c88208John Reck        // Only update thumbnails for web urls (http(s)://), not for
211434ef26756a751b99b5c021ee2b9221c582c88208John Reck        // about:, javascript:, data:, etc...
211534ef26756a751b99b5c021ee2b9221c582c88208John Reck        // Unless it is a bookmarked site, then always update
211634ef26756a751b99b5c021ee2b9221c582c88208John Reck        if (!Patterns.WEB_URL.matcher(url).matches() && !tab.isBookmarkedSite()) {
211734ef26756a751b99b5c021ee2b9221c582c88208John Reck            return;
211834ef26756a751b99b5c021ee2b9221c582c88208John Reck        }
211934ef26756a751b99b5c021ee2b9221c582c88208John Reck
21208233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final Bitmap bm = createScreenshot(view, getDesiredThumbnailWidth(mActivity),
21218233facddcc51865d612a919d450db6954aa48e3Michael Kolb                getDesiredThumbnailHeight(mActivity));
21228233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (bm == null) {
21238233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
21248233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
21258233facddcc51865d612a919d450db6954aa48e3Michael Kolb
21268233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final ContentResolver cr = mActivity.getContentResolver();
212734ef26756a751b99b5c021ee2b9221c582c88208John Reck        new AsyncTask<Void, Void, Void>() {
212834ef26756a751b99b5c021ee2b9221c582c88208John Reck            @Override
212934ef26756a751b99b5c021ee2b9221c582c88208John Reck            protected Void doInBackground(Void... unused) {
213034ef26756a751b99b5c021ee2b9221c582c88208John Reck                Cursor cursor = null;
213134ef26756a751b99b5c021ee2b9221c582c88208John Reck                try {
213234ef26756a751b99b5c021ee2b9221c582c88208John Reck                    // TODO: Clean this up
213334ef26756a751b99b5c021ee2b9221c582c88208John Reck                    cursor = Bookmarks.queryCombinedForUrl(cr, originalUrl, url);
213434ef26756a751b99b5c021ee2b9221c582c88208John Reck                    if (cursor != null && cursor.moveToFirst()) {
213534ef26756a751b99b5c021ee2b9221c582c88208John Reck                        final ByteArrayOutputStream os =
213634ef26756a751b99b5c021ee2b9221c582c88208John Reck                                new ByteArrayOutputStream();
213734ef26756a751b99b5c021ee2b9221c582c88208John Reck                        bm.compress(Bitmap.CompressFormat.PNG, 100, os);
213834ef26756a751b99b5c021ee2b9221c582c88208John Reck
213934ef26756a751b99b5c021ee2b9221c582c88208John Reck                        ContentValues values = new ContentValues();
214034ef26756a751b99b5c021ee2b9221c582c88208John Reck                        values.put(Images.THUMBNAIL, os.toByteArray());
214134ef26756a751b99b5c021ee2b9221c582c88208John Reck
214234ef26756a751b99b5c021ee2b9221c582c88208John Reck                        do {
2143617fd83615f490817db7d288d732d6cdd0b47ae5John Reck                            values.put(Images.URL, cursor.getString(0));
214434ef26756a751b99b5c021ee2b9221c582c88208John Reck                            cr.update(Images.CONTENT_URI, values, null, null);
214534ef26756a751b99b5c021ee2b9221c582c88208John Reck                        } while (cursor.moveToNext());
21468233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
214734ef26756a751b99b5c021ee2b9221c582c88208John Reck                } catch (IllegalStateException e) {
214834ef26756a751b99b5c021ee2b9221c582c88208John Reck                    // Ignore
2149561d1954d552fe1beff6e1ec7d22147935b32c0fMattias Nilsson                } catch (SQLiteException s) {
2150561d1954d552fe1beff6e1ec7d22147935b32c0fMattias Nilsson                    // Added for possible error when user tries to remove the same bookmark
2151561d1954d552fe1beff6e1ec7d22147935b32c0fMattias Nilsson                    // that is being updated with a screen shot
2152561d1954d552fe1beff6e1ec7d22147935b32c0fMattias Nilsson                    Log.w(LOGTAG, "Error when running updateScreenshot ", s);
215334ef26756a751b99b5c021ee2b9221c582c88208John Reck                } finally {
215434ef26756a751b99b5c021ee2b9221c582c88208John Reck                    if (cursor != null) cursor.close();
21558233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
215634ef26756a751b99b5c021ee2b9221c582c88208John Reck                return null;
215734ef26756a751b99b5c021ee2b9221c582c88208John Reck            }
215834ef26756a751b99b5c021ee2b9221c582c88208John Reck        }.execute();
21598233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
21608233facddcc51865d612a919d450db6954aa48e3Michael Kolb
21618233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private class Copy implements OnMenuItemClickListener {
21628233facddcc51865d612a919d450db6954aa48e3Michael Kolb        private CharSequence mText;
21638233facddcc51865d612a919d450db6954aa48e3Michael Kolb
21649c35b9c41d756d59f5356edd2e08432e01f351f6John Reck        @Override
21658233facddcc51865d612a919d450db6954aa48e3Michael Kolb        public boolean onMenuItemClick(MenuItem item) {
21668233facddcc51865d612a919d450db6954aa48e3Michael Kolb            copy(mText);
21678233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return true;
21688233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
21698233facddcc51865d612a919d450db6954aa48e3Michael Kolb
21708233facddcc51865d612a919d450db6954aa48e3Michael Kolb        public Copy(CharSequence toCopy) {
21718233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mText = toCopy;
21728233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
21738233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
21748233facddcc51865d612a919d450db6954aa48e3Michael Kolb
217563c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins    private static class Download implements OnMenuItemClickListener {
217663c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins        private Activity mActivity;
21778233facddcc51865d612a919d450db6954aa48e3Michael Kolb        private String mText;
2178bc5cc75c302eb49d15258155fc6f672fcbd62842Kristian Monsen        private boolean mPrivateBrowsing;
21798e4ce660cd8576237b4ff30c40b21570af3af4f3Andreas Sandblad        private String mUserAgent;
2180387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount        private static final String FALLBACK_EXTENSION = "dat";
2181387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount        private static final String IMAGE_BASE_FORMAT = "yyyy-MM-dd-HH-mm-ss-";
21828233facddcc51865d612a919d450db6954aa48e3Michael Kolb
21839c35b9c41d756d59f5356edd2e08432e01f351f6John Reck        @Override
21848233facddcc51865d612a919d450db6954aa48e3Michael Kolb        public boolean onMenuItemClick(MenuItem item) {
2185387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            if (DataUri.isDataUri(mText)) {
2186387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                saveDataUri();
2187387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            } else {
21888e4ce660cd8576237b4ff30c40b21570af3af4f3Andreas Sandblad                DownloadHandler.onDownloadStartNoStream(mActivity, mText, mUserAgent,
21890b3d66fc2275fb5270cb7166cc991be7dc9d8ff7Selim Gurun                        null, null, null, mPrivateBrowsing);
2190387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            }
21918233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return true;
21928233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
21938233facddcc51865d612a919d450db6954aa48e3Michael Kolb
21948e4ce660cd8576237b4ff30c40b21570af3af4f3Andreas Sandblad        public Download(Activity activity, String toDownload, boolean privateBrowsing,
21958e4ce660cd8576237b4ff30c40b21570af3af4f3Andreas Sandblad                String userAgent) {
219663c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins            mActivity = activity;
21978233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mText = toDownload;
2198bc5cc75c302eb49d15258155fc6f672fcbd62842Kristian Monsen            mPrivateBrowsing = privateBrowsing;
21998e4ce660cd8576237b4ff30c40b21570af3af4f3Andreas Sandblad            mUserAgent = userAgent;
22008233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2201387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount
2202387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount        /**
2203387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount         * Treats mText as a data URI and writes its contents to a file
2204387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount         * based on the current time.
2205387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount         */
2206387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount        private void saveDataUri() {
2207387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            FileOutputStream outputStream = null;
2208387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            try {
2209387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                DataUri uri = new DataUri(mText);
2210387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                File target = getTarget(uri);
2211387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                outputStream = new FileOutputStream(target);
2212387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                outputStream.write(uri.getData());
2213387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                final DownloadManager manager =
2214387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                        (DownloadManager) mActivity.getSystemService(Context.DOWNLOAD_SERVICE);
2215387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                 manager.addCompletedDownload(target.getName(),
2216387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                        mActivity.getTitle().toString(), false,
2217387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                        uri.getMimeType(), target.getAbsolutePath(),
22189c35b9c41d756d59f5356edd2e08432e01f351f6John Reck                        uri.getData().length, true);
2219387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            } catch (IOException e) {
2220387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                Log.e(LOGTAG, "Could not save data URL");
2221387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            } finally {
2222387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                if (outputStream != null) {
2223387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                    try {
2224387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                        outputStream.close();
2225387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                    } catch (IOException e) {
2226387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                        // ignore close errors
2227387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                    }
2228387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                }
2229387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            }
2230387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount        }
2231387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount
2232387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount        /**
2233387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount         * Creates a File based on the current time stamp and uses
2234387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount         * the mime type of the DataUri to get the extension.
2235387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount         */
2236387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount        private File getTarget(DataUri uri) throws IOException {
2237387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            File dir = mActivity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
2238aa67618bf9711a45fff7d0bdf93c9d3d29bf5817Johan Redestig            DateFormat format = new SimpleDateFormat(IMAGE_BASE_FORMAT, Locale.US);
2239387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            String nameBase = format.format(new Date());
2240387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            String mimeType = uri.getMimeType();
2241387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
2242387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            String extension = mimeTypeMap.getExtensionFromMimeType(mimeType);
2243387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            if (extension == null) {
2244387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                Log.w(LOGTAG, "Unknown mime type in data URI" + mimeType);
2245387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount                extension = FALLBACK_EXTENSION;
2246387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            }
2247387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            extension = "." + extension; // createTempFile needs the '.'
2248387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            File targetFile = File.createTempFile(nameBase, extension, dir);
2249387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount            return targetFile;
2250387d45d2284c7fd7f12cbadc96161f946ae29cadGeorge Mount        }
22518233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
22528233facddcc51865d612a919d450db6954aa48e3Michael Kolb
22538974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark    private static class SelectText implements OnMenuItemClickListener {
22544d2fcaba7fb8eb1723943ac9a10e76d509330bd1Jonathan Dixon        private WebViewClassic mWebView;
22558974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark
22569c35b9c41d756d59f5356edd2e08432e01f351f6John Reck        @Override
22578974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark        public boolean onMenuItemClick(MenuItem item) {
22588974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark            if (mWebView != null) {
22598974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark                return mWebView.selectText();
22608974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark            }
22618974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark            return false;
22628974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark        }
22638974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark
22648974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark        public SelectText(WebView webView) {
2265e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon          if (BrowserWebView.isClassic()) {
2266e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon              mWebView = WebViewClassic.fromWebView(webView);
2267e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon          }
22688974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark        }
22698974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark
22708974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark    }
22718974d281fa5c96bf50d5f5bac665cae44568f6e8Cary Clark
22728233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /********************** TODO: UI stuff *****************************/
22738233facddcc51865d612a919d450db6954aa48e3Michael Kolb
22748233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // these methods have been copied, they still need to be cleaned up
22758233facddcc51865d612a919d450db6954aa48e3Michael Kolb
22768233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /****************** tabs ***************************************************/
22778233facddcc51865d612a919d450db6954aa48e3Michael Kolb
22788233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // basic tab interactions:
22798233facddcc51865d612a919d450db6954aa48e3Michael Kolb
22808233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // it is assumed that tabcontrol already knows about the tab
22818233facddcc51865d612a919d450db6954aa48e3Michael Kolb    protected void addTab(Tab tab) {
22828233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.addTab(tab);
22838233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
22848233facddcc51865d612a919d450db6954aa48e3Michael Kolb
22858233facddcc51865d612a919d450db6954aa48e3Michael Kolb    protected void removeTab(Tab tab) {
22868233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.removeTab(tab);
22878233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mTabControl.removeTab(tab);
2288378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck        mCrashRecoveryHandler.backupState();
22898233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
22908233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2291f205560dacc8a85f0443ca1949a68962404321e8Michael Kolb    @Override
2292f205560dacc8a85f0443ca1949a68962404321e8Michael Kolb    public void setActiveTab(Tab tab) {
2293cd424e99aa19d00933e6540a95805042659f596fMichael Kolb        // monkey protection against delayed start
2294cd424e99aa19d00933e6540a95805042659f596fMichael Kolb        if (tab != null) {
2295cd424e99aa19d00933e6540a95805042659f596fMichael Kolb            mTabControl.setCurrentTab(tab);
2296cd424e99aa19d00933e6540a95805042659f596fMichael Kolb            // the tab is guaranteed to have a webview after setCurrentTab
2297cd424e99aa19d00933e6540a95805042659f596fMichael Kolb            mUi.setActiveTab(tab);
2298cd424e99aa19d00933e6540a95805042659f596fMichael Kolb        }
22998233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
23008233facddcc51865d612a919d450db6954aa48e3Michael Kolb
23018bcafc149bc49b84c8dfbaacf88c178d8bc9eda6John Reck    protected void closeEmptyTab() {
23028233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Tab current = mTabControl.getCurrentTab();
23038233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (current != null
23048233facddcc51865d612a919d450db6954aa48e3Michael Kolb                && current.getWebView().copyBackForwardList().getSize() == 0) {
23058bcafc149bc49b84c8dfbaacf88c178d8bc9eda6John Reck            closeCurrentTab();
23068233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
23078233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
23088233facddcc51865d612a919d450db6954aa48e3Michael Kolb
230926b183292dc087b16af10f482744c3bb30e1f163John Reck    protected void reuseTab(Tab appTab, UrlData urlData) {
23108233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Dismiss the subwindow if applicable.
23118233facddcc51865d612a919d450db6954aa48e3Michael Kolb        dismissSubWindow(appTab);
23128233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Since we might kill the WebView, remove it from the
23138233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // content view first.
23148233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.detachTab(appTab);
23158233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Recreate the main WebView after destroying the old one.
231630c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        mTabControl.recreateWebView(appTab);
23178233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // TODO: analyze why the remove and add are necessary
23188233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.attachTab(appTab);
23198233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mTabControl.getCurrentTab() != appTab) {
2320c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            switchToTab(appTab);
232130c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            loadUrlDataIn(appTab, urlData);
23228233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else {
23238233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // If the tab was the current tab, we have to attach
23248233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // it to the view system again.
23258233facddcc51865d612a919d450db6954aa48e3Michael Kolb            setActiveTab(appTab);
232630c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            loadUrlDataIn(appTab, urlData);
23278233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
23288233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
23298233facddcc51865d612a919d450db6954aa48e3Michael Kolb
23308233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // Remove the sub window if it exists. Also called by TabControl when the
23318233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // user clicks the 'X' to dismiss a sub window.
23329c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
23338233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void dismissSubWindow(Tab tab) {
23348233facddcc51865d612a919d450db6954aa48e3Michael Kolb        removeSubWindow(tab);
23358233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // dismiss the subwindow. This will destroy the WebView.
23368233facddcc51865d612a919d450db6954aa48e3Michael Kolb        tab.dismissSubWindow();
2337e8c975772600287793549407927281131757868cMichael Kolb        WebView wv = getCurrentTopWebView();
2338e8c975772600287793549407927281131757868cMichael Kolb        if (wv != null) {
2339e8c975772600287793549407927281131757868cMichael Kolb            wv.requestFocus();
2340e8c975772600287793549407927281131757868cMichael Kolb        }
23418233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
23428233facddcc51865d612a919d450db6954aa48e3Michael Kolb
23438233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
23448233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void removeSubWindow(Tab t) {
23458233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (t.getSubWebView() != null) {
23468233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mUi.removeSubWindow(t.getSubViewContainer());
23478233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
23488233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
23498233facddcc51865d612a919d450db6954aa48e3Michael Kolb
23508233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
23518233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void attachSubWindow(Tab tab) {
23528233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (tab.getSubWebView() != null) {
23538233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mUi.attachSubWindow(tab.getSubViewContainer());
23548233facddcc51865d612a919d450db6954aa48e3Michael Kolb            getCurrentTopWebView().requestFocus();
23558233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
23568233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
23578233facddcc51865d612a919d450db6954aa48e3Michael Kolb
235829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    private Tab showPreloadedTab(final UrlData urlData) {
235929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        if (!urlData.isPreloaded()) {
236029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            return null;
236129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        }
236229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        final PreloadedTabControl tabControl = urlData.getPreloadedTab();
236329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        final String sbQuery = urlData.getSearchBoxQueryToSubmit();
236429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        if (sbQuery != null) {
23659ad1eac377ffa6ffd34afae4c6580b7ba7508c31Mathew Inwood            if (!tabControl.searchBoxSubmit(sbQuery, urlData.mUrl, urlData.mHeaders)) {
236629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                // Could not submit query. Fallback to regular tab creation
236729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                tabControl.destroy();
236829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                return null;
236929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            }
237029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        }
2371ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        // check tab count and make room for new tab
2372ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        if (!mTabControl.canCreateNewTab()) {
2373ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb            Tab leastUsed = mTabControl.getLeastUsedTab(getCurrentTab());
2374ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb            if (leastUsed != null) {
2375ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb                closeTab(leastUsed);
2376ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb            }
2377ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        }
237829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        Tab t = tabControl.getTab();
2379e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood        t.refreshIdAfterPreload();
238029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        mTabControl.addPreloadedTab(t);
238129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        addTab(t);
238229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        setActiveTab(t);
238329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        return t;
238429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    }
238529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
23867bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    // open a non inconito tab with the given url data
23877bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    // and set as active tab
23887bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    public Tab openTab(UrlData urlData) {
238929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        Tab tab = showPreloadedTab(urlData);
239029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        if (tab == null) {
239129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            tab = createNewTab(false, true, true);
23921461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            if ((tab != null) && !urlData.isEmpty()) {
23931461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                loadUrlDataIn(tab, urlData);
23941461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            }
239518eb377badf8e6f9ea2925bcb7e978facf3171d9Michael Kolb        }
239629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        return tab;
23978233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
23988233facddcc51865d612a919d450db6954aa48e3Michael Kolb
23997bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    @Override
24007bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    public Tab openTabToHomePage() {
24017bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb        return openTab(mSettings.getHomePage(), false, true, false);
24028233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
24038233facddcc51865d612a919d450db6954aa48e3Michael Kolb
24048233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
2405519d22840ea587988214a625dc8106e1302ac4a9Michael Kolb    public Tab openIncognitoTab() {
2406519d22840ea587988214a625dc8106e1302ac4a9Michael Kolb        return openTab(INCOGNITO_URI, true, true, false);
2407519d22840ea587988214a625dc8106e1302ac4a9Michael Kolb    }
2408519d22840ea587988214a625dc8106e1302ac4a9Michael Kolb
2409519d22840ea587988214a625dc8106e1302ac4a9Michael Kolb    @Override
24107bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    public Tab openTab(String url, boolean incognito, boolean setActive,
24117bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb            boolean useCurrent) {
24125949c661b51295148706d53a03b41df2eb840ae3John Reck        return openTab(url, incognito, setActive, useCurrent, null);
24135949c661b51295148706d53a03b41df2eb840ae3John Reck    }
24145949c661b51295148706d53a03b41df2eb840ae3John Reck
24155949c661b51295148706d53a03b41df2eb840ae3John Reck    @Override
24165949c661b51295148706d53a03b41df2eb840ae3John Reck    public Tab openTab(String url, Tab parent, boolean setActive,
24175949c661b51295148706d53a03b41df2eb840ae3John Reck            boolean useCurrent) {
24185949c661b51295148706d53a03b41df2eb840ae3John Reck        return openTab(url, (parent != null) && parent.isPrivateBrowsingEnabled(),
24195949c661b51295148706d53a03b41df2eb840ae3John Reck                setActive, useCurrent, parent);
24205949c661b51295148706d53a03b41df2eb840ae3John Reck    }
24215949c661b51295148706d53a03b41df2eb840ae3John Reck
24225949c661b51295148706d53a03b41df2eb840ae3John Reck    public Tab openTab(String url, boolean incognito, boolean setActive,
24235949c661b51295148706d53a03b41df2eb840ae3John Reck            boolean useCurrent, Tab parent) {
24247bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb        Tab tab = createNewTab(incognito, setActive, useCurrent);
24257bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb        if (tab != null) {
24265949c661b51295148706d53a03b41df2eb840ae3John Reck            if (parent != null && parent != tab) {
24275949c661b51295148706d53a03b41df2eb840ae3John Reck                parent.addChildTab(tab);
24285949c661b51295148706d53a03b41df2eb840ae3John Reck            }
2429519d22840ea587988214a625dc8106e1302ac4a9Michael Kolb            if (url != null) {
243026b183292dc087b16af10f482744c3bb30e1f163John Reck                loadUrl(tab, url);
2431519d22840ea587988214a625dc8106e1302ac4a9Michael Kolb            }
2432a4261fd53fef2b311e733fcfee4be3a9967ad967Michael Kolb        }
24337bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb        return tab;
2434a4261fd53fef2b311e733fcfee4be3a9967ad967Michael Kolb    }
2435a4261fd53fef2b311e733fcfee4be3a9967ad967Michael Kolb
24367bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    // this method will attempt to create a new tab
24377bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    // incognito: private browsing tab
24387bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    // setActive: ste tab as current tab
24397bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    // useCurrent: if no new tab can be created, return current tab
24407bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    private Tab createNewTab(boolean incognito, boolean setActive,
24417bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb            boolean useCurrent) {
24427bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb        Tab tab = null;
2443a4261fd53fef2b311e733fcfee4be3a9967ad967Michael Kolb        if (mTabControl.canCreateNewTab()) {
24447bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb            tab = mTabControl.createNewTab(incognito);
2445a4261fd53fef2b311e733fcfee4be3a9967ad967Michael Kolb            addTab(tab);
24467bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb            if (setActive) {
24477bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb                setActiveTab(tab);
24487bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb            }
2449843510fb4f36a9a834c69d8773156db20ca3d740Michael Kolb        } else {
24507bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb            if (useCurrent) {
24517bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb                tab = mTabControl.getCurrentTab();
245226b183292dc087b16af10f482744c3bb30e1f163John Reck                reuseTab(tab, null);
24537bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb            } else {
24547bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb                mUi.showMaxTabsWarning();
24557bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb            }
24568233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
24577bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb        return tab;
24588233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
24598233facddcc51865d612a919d450db6954aa48e3Michael Kolb
24602bc8042224be51966d748b870768ec1b376a1621John Reck    @Override
24612bc8042224be51966d748b870768ec1b376a1621John Reck    public SnapshotTab createNewSnapshotTab(long snapshotId, boolean setActive) {
24622bc8042224be51966d748b870768ec1b376a1621John Reck        SnapshotTab tab = null;
24632bc8042224be51966d748b870768ec1b376a1621John Reck        if (mTabControl.canCreateNewTab()) {
24642bc8042224be51966d748b870768ec1b376a1621John Reck            tab = mTabControl.createSnapshotTab(snapshotId);
24652bc8042224be51966d748b870768ec1b376a1621John Reck            addTab(tab);
24662bc8042224be51966d748b870768ec1b376a1621John Reck            if (setActive) {
24672bc8042224be51966d748b870768ec1b376a1621John Reck                setActiveTab(tab);
24682bc8042224be51966d748b870768ec1b376a1621John Reck            }
24692bc8042224be51966d748b870768ec1b376a1621John Reck        } else {
24702bc8042224be51966d748b870768ec1b376a1621John Reck            mUi.showMaxTabsWarning();
2471d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        }
2472d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        return tab;
2473d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck    }
2474d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck
24758233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
2476c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * @param tab the tab to switch to
24778233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @return boolean True if we successfully switched to a different tab.  If
24788233facddcc51865d612a919d450db6954aa48e3Michael Kolb     *                 the indexth tab is null, or if that tab is the same as
24798233facddcc51865d612a919d450db6954aa48e3Michael Kolb     *                 the current one, return false.
24808233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
24818233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
2482c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    public boolean switchToTab(Tab tab) {
24838233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Tab currentTab = mTabControl.getCurrentTab();
24848233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (tab == null || tab == currentTab) {
24858233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return false;
24868233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
24878233facddcc51865d612a919d450db6954aa48e3Michael Kolb        setActiveTab(tab);
24888233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return true;
24898233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
24908233facddcc51865d612a919d450db6954aa48e3Michael Kolb
24918233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
24928233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void closeCurrentTab() {
24932ae6ef7f6c146a5bc3a4c7ef8de56505eb02399eMichael Kolb        closeCurrentTab(false);
24942ae6ef7f6c146a5bc3a4c7ef8de56505eb02399eMichael Kolb    }
24952ae6ef7f6c146a5bc3a4c7ef8de56505eb02399eMichael Kolb
24962ae6ef7f6c146a5bc3a4c7ef8de56505eb02399eMichael Kolb    protected void closeCurrentTab(boolean andQuit) {
24978233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mTabControl.getTabCount() == 1) {
2498bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck            mCrashRecoveryHandler.clearState();
2499c1eeb12b6e4570520c3571aba9c04be91b4a20d5Michael Kolb            mTabControl.removeTab(getCurrentTab());
2500958b24285bba0163bc4121a3fc0fb116aa563ed9John Reck            mActivity.finish();
25018233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
25028233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2503c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        final Tab current = mTabControl.getCurrentTab();
2504c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        final int pos = mTabControl.getCurrentPosition();
2505c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        Tab newTab = current.getParent();
2506c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        if (newTab == null) {
2507c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            newTab = mTabControl.getTab(pos + 1);
2508c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            if (newTab == null) {
2509c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                newTab = mTabControl.getTab(pos - 1);
25108233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
25118233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
25122ae6ef7f6c146a5bc3a4c7ef8de56505eb02399eMichael Kolb        if (andQuit) {
25132ae6ef7f6c146a5bc3a4c7ef8de56505eb02399eMichael Kolb            mTabControl.setCurrentTab(newTab);
25142ae6ef7f6c146a5bc3a4c7ef8de56505eb02399eMichael Kolb            closeTab(current);
25152ae6ef7f6c146a5bc3a4c7ef8de56505eb02399eMichael Kolb        } else if (switchToTab(newTab)) {
25168233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // Close window
25178233facddcc51865d612a919d450db6954aa48e3Michael Kolb            closeTab(current);
25188233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
25198233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
25208233facddcc51865d612a919d450db6954aa48e3Michael Kolb
25218233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
25228233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Close the tab, remove its associated title bar, and adjust mTabControl's
25238233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * current tab to a valid value.
25248233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
25258233facddcc51865d612a919d450db6954aa48e3Michael Kolb    @Override
25268233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void closeTab(Tab tab) {
2527282637771aaffd93f29fd72bf5cd49dd82d24d0dJohn Reck        if (tab == mTabControl.getCurrentTab()) {
2528282637771aaffd93f29fd72bf5cd49dd82d24d0dJohn Reck            closeCurrentTab();
2529282637771aaffd93f29fd72bf5cd49dd82d24d0dJohn Reck        } else {
2530282637771aaffd93f29fd72bf5cd49dd82d24d0dJohn Reck            removeTab(tab);
2531282637771aaffd93f29fd72bf5cd49dd82d24d0dJohn Reck        }
25328233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
25338233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2534d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam    /**
2535d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam     * Close all tabs except the current one
2536d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam     */
2537d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam    @Override
2538d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam    public void closeOtherTabs() {
2539d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam        int inactiveTabs = mTabControl.getTabCount() - 1;
2540d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam        for (int i = inactiveTabs; i >= 0; i--) {
2541d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam            Tab tab = mTabControl.getTab(i);
2542d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam            if (tab != mTabControl.getCurrentTab()) {
2543d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam                removeTab(tab);
2544d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam            }
2545d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam        }
2546d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam    }
2547d4e3331a3cfa368e8e26f18700ed3474a24ff553Afzal Najam
25488233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // Called when loading from context menu or LOAD_URL message
254926b183292dc087b16af10f482744c3bb30e1f163John Reck    protected void loadUrlFromContext(String url) {
255026b183292dc087b16af10f482744c3bb30e1f163John Reck        Tab tab = getCurrentTab();
255126b183292dc087b16af10f482744c3bb30e1f163John Reck        WebView view = tab != null ? tab.getWebView() : null;
25528233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // In case the user enters nothing.
255326b183292dc087b16af10f482744c3bb30e1f163John Reck        if (url != null && url.length() != 0 && tab != null && view != null) {
25548233facddcc51865d612a919d450db6954aa48e3Michael Kolb            url = UrlUtils.smartUrlFilter(url);
2555e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon            if (!((BrowserWebView) view).getWebViewClient().
25564d2fcaba7fb8eb1723943ac9a10e76d509330bd1Jonathan Dixon                    shouldOverrideUrlLoading(view, url)) {
255726b183292dc087b16af10f482744c3bb30e1f163John Reck                loadUrl(tab, url);
25588233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
25598233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
25608233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
25618233facddcc51865d612a919d450db6954aa48e3Michael Kolb
25628233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
25638233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Load the URL into the given WebView and update the title bar
25648233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * to reflect the new load.  Call this instead of WebView.loadUrl
25658233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * directly.
25668233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param view The WebView used to load url.
25678233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param url The URL to load.
25688233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
256971e5142e4237a0f9d51a93504da36b778e8b79e4John Reck    @Override
257071e5142e4237a0f9d51a93504da36b778e8b79e4John Reck    public void loadUrl(Tab tab, String url) {
257126b183292dc087b16af10f482744c3bb30e1f163John Reck        loadUrl(tab, url, null);
257226b183292dc087b16af10f482744c3bb30e1f163John Reck    }
257326b183292dc087b16af10f482744c3bb30e1f163John Reck
257426b183292dc087b16af10f482744c3bb30e1f163John Reck    protected void loadUrl(Tab tab, String url, Map<String, String> headers) {
257526b183292dc087b16af10f482744c3bb30e1f163John Reck        if (tab != null) {
257626b183292dc087b16af10f482744c3bb30e1f163John Reck            dismissSubWindow(tab);
257726b183292dc087b16af10f482744c3bb30e1f163John Reck            tab.loadUrl(url, headers);
2578a53c98902be0f9f959b6af06227254e5ad2130c9Michael Kolb            mUi.onProgressChanged(tab);
257926b183292dc087b16af10f482744c3bb30e1f163John Reck        }
25808233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
25818233facddcc51865d612a919d450db6954aa48e3Michael Kolb
25828233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
25838233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Load UrlData into a Tab and update the title bar to reflect the new
25848233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * load.  Call this instead of UrlData.loadIn directly.
25858233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param t The Tab used to load.
25868233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param data The UrlData being loaded.
25878233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
25888233facddcc51865d612a919d450db6954aa48e3Michael Kolb    protected void loadUrlDataIn(Tab t, UrlData data) {
258926b183292dc087b16af10f482744c3bb30e1f163John Reck        if (data != null) {
25905ff5c8b88968fa794eab4b7a263cae25f05bd4d3Michael Kolb            if (data.isPreloaded()) {
25911461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                // this isn't called for preloaded tabs
259226b183292dc087b16af10f482744c3bb30e1f163John Reck            } else {
259338b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck                if (t != null && data.mDisableUrlOverride) {
259438b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck                    t.disableUrlOverridingForLoad();
259538b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck                }
259626b183292dc087b16af10f482744c3bb30e1f163John Reck                loadUrl(t, data.mUrl, data.mHeaders);
259726b183292dc087b16af10f482744c3bb30e1f163John Reck            }
259826b183292dc087b16af10f482744c3bb30e1f163John Reck        }
25998233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
26008233facddcc51865d612a919d450db6954aa48e3Michael Kolb
260130c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    @Override
260230c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    public void onUserCanceledSsl(Tab tab) {
260330c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        // TODO: Figure out the "right" behavior
2604ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck        if (tab.canGoBack()) {
2605ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck            tab.goBack();
260630c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        } else {
2607ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck            tab.loadUrl(mSettings.getHomePage(), null);
260830c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        }
26098233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
26108233facddcc51865d612a919d450db6954aa48e3Michael Kolb
26118233facddcc51865d612a919d450db6954aa48e3Michael Kolb    void goBackOnePageOrQuit() {
26128233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Tab current = mTabControl.getCurrentTab();
26138233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (current == null) {
26148233facddcc51865d612a919d450db6954aa48e3Michael Kolb            /*
26158233facddcc51865d612a919d450db6954aa48e3Michael Kolb             * Instead of finishing the activity, simply push this to the back
26168233facddcc51865d612a919d450db6954aa48e3Michael Kolb             * of the stack and let ActivityManager to choose the foreground
26178233facddcc51865d612a919d450db6954aa48e3Michael Kolb             * activity. As BrowserActivity is singleTask, it will be always the
26188233facddcc51865d612a919d450db6954aa48e3Michael Kolb             * root of the task. So we can use either true or false for
26198233facddcc51865d612a919d450db6954aa48e3Michael Kolb             * moveTaskToBack().
26208233facddcc51865d612a919d450db6954aa48e3Michael Kolb             */
26218233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mActivity.moveTaskToBack(true);
26228233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
26238233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2624ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck        if (current.canGoBack()) {
2625ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck            current.goBack();
26268233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else {
26278233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // Check to see if we are closing a window that was created by
26288233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // another window. If so, we switch back to that window.
2629c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            Tab parent = current.getParent();
26308233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (parent != null) {
2631c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                switchToTab(parent);
26328233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // Now we close the other tab
26338233facddcc51865d612a919d450db6954aa48e3Michael Kolb                closeTab(current);
26348233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else {
2635e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb                if ((current.getAppId() != null) || current.closeOnBack()) {
26362ae6ef7f6c146a5bc3a4c7ef8de56505eb02399eMichael Kolb                    closeCurrentTab(true);
2637e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb                }
26388233facddcc51865d612a919d450db6954aa48e3Michael Kolb                /*
26398233facddcc51865d612a919d450db6954aa48e3Michael Kolb                 * Instead of finishing the activity, simply push this to the back
26408233facddcc51865d612a919d450db6954aa48e3Michael Kolb                 * of the stack and let ActivityManager to choose the foreground
26418233facddcc51865d612a919d450db6954aa48e3Michael Kolb                 * activity. As BrowserActivity is singleTask, it will be always the
26428233facddcc51865d612a919d450db6954aa48e3Michael Kolb                 * root of the task. So we can use either true or false for
26438233facddcc51865d612a919d450db6954aa48e3Michael Kolb                 * moveTaskToBack().
26448233facddcc51865d612a919d450db6954aa48e3Michael Kolb                 */
26458233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mActivity.moveTaskToBack(true);
26468233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
26478233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
26488233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
26498233facddcc51865d612a919d450db6954aa48e3Michael Kolb
26508233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
26510035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb     * helper method for key handler
26520035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb     * returns the current tab if it can't advance
26530035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb     */
2654c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    private Tab getNextTab() {
2655f5261da39d50e722587772e5c230c4cc19f8deccMichael Kolb        int pos = mTabControl.getCurrentPosition() + 1;
2656f5261da39d50e722587772e5c230c4cc19f8deccMichael Kolb        if (pos >= mTabControl.getTabCount()) {
2657f5261da39d50e722587772e5c230c4cc19f8deccMichael Kolb            pos = 0;
2658f5261da39d50e722587772e5c230c4cc19f8deccMichael Kolb        }
2659f5261da39d50e722587772e5c230c4cc19f8deccMichael Kolb        return mTabControl.getTab(pos);
26600035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb    }
26610035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb
26620035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb    /**
26630035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb     * helper method for key handler
26640035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb     * returns the current tab if it can't advance
26650035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb     */
2666c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    private Tab getPrevTab() {
2667f5261da39d50e722587772e5c230c4cc19f8deccMichael Kolb        int pos  = mTabControl.getCurrentPosition() - 1;
2668f5261da39d50e722587772e5c230c4cc19f8deccMichael Kolb        if ( pos < 0) {
2669f5261da39d50e722587772e5c230c4cc19f8deccMichael Kolb            pos = mTabControl.getTabCount() - 1;
2670f5261da39d50e722587772e5c230c4cc19f8deccMichael Kolb        }
2671f5261da39d50e722587772e5c230c4cc19f8deccMichael Kolb        return  mTabControl.getTab(pos);
26720035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb    }
26730035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb
2674bcef87fe4a6cc084695bc6c3a1716ebb005230c5John Reck    boolean isMenuOrCtrlKey(int keyCode) {
2675bcef87fe4a6cc084695bc6c3a1716ebb005230c5John Reck        return (KeyEvent.KEYCODE_MENU == keyCode)
2676bcef87fe4a6cc084695bc6c3a1716ebb005230c5John Reck                || (KeyEvent.KEYCODE_CTRL_LEFT == keyCode)
2677bcef87fe4a6cc084695bc6c3a1716ebb005230c5John Reck                || (KeyEvent.KEYCODE_CTRL_RIGHT == keyCode);
2678bcef87fe4a6cc084695bc6c3a1716ebb005230c5John Reck    }
2679bcef87fe4a6cc084695bc6c3a1716ebb005230c5John Reck
26800035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb    /**
26818233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * handle key events in browser
26828233facddcc51865d612a919d450db6954aa48e3Michael Kolb     *
26838233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param keyCode
26848233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param event
26858233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @return true if handled, false to pass to super
26868233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
26879c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
26889c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public boolean onKeyDown(int keyCode, KeyEvent event) {
2689160bbb9565b63302c88b032e4653f8268553175fCary Clark        boolean noModifiers = event.hasNoModifiers();
26908233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Even if MENU is already held down, we need to call to super to open
26918233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // the IME on long press.
2692bcef87fe4a6cc084695bc6c3a1716ebb005230c5John Reck        if (!noModifiers && isMenuOrCtrlKey(keyCode)) {
26938233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mMenuIsDown = true;
26948233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return false;
26958233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
26968233facddcc51865d612a919d450db6954aa48e3Michael Kolb
26978ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark        WebView webView = getCurrentTopWebView();
2698ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck        Tab tab = getCurrentTab();
2699ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck        if (webView == null || tab == null) return false;
27008ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark
2701160bbb9565b63302c88b032e4653f8268553175fCary Clark        boolean ctrl = event.hasModifiers(KeyEvent.META_CTRL_ON);
2702160bbb9565b63302c88b032e4653f8268553175fCary Clark        boolean shift = event.hasModifiers(KeyEvent.META_SHIFT_ON);
27038ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark
27048233facddcc51865d612a919d450db6954aa48e3Michael Kolb        switch(keyCode) {
27050035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb            case KeyEvent.KEYCODE_TAB:
27060035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb                if (event.isCtrlPressed()) {
27070035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb                    if (event.isShiftPressed()) {
27080035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb                        // prev tab
2709c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                        switchToTab(getPrevTab());
27100035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb                    } else {
27110035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb                        // next tab
2712c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                        switchToTab(getNextTab());
27130035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb                    }
27140035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb                    return true;
27150035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb                }
27160035fadb375ff0b549b84605eb9aea150d31677aMichael Kolb                break;
27178233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case KeyEvent.KEYCODE_SPACE:
27188233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // WebView/WebTextView handle the keys in the KeyDown. As
27198233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // the Activity's shortcut keys are only handled when WebView
27208233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // doesn't, have to do it in onKeyDown instead of onKeyUp.
2721160bbb9565b63302c88b032e4653f8268553175fCary Clark                if (shift) {
27228233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    pageUp();
2723160bbb9565b63302c88b032e4653f8268553175fCary Clark                } else if (noModifiers) {
27248233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    pageDown();
27258233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
27268233facddcc51865d612a919d450db6954aa48e3Michael Kolb                return true;
27278233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case KeyEvent.KEYCODE_BACK:
2728160bbb9565b63302c88b032e4653f8268553175fCary Clark                if (!noModifiers) break;
2729e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck                event.startTracking();
2730e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck                return true;
2731e9e1d4af4971e09392627e8e53d69d1b70bcb572Michael Kolb            case KeyEvent.KEYCODE_FORWARD:
2732e9e1d4af4971e09392627e8e53d69d1b70bcb572Michael Kolb                if (!noModifiers) break;
2733e9e1d4af4971e09392627e8e53d69d1b70bcb572Michael Kolb                tab.goForward();
2734e9e1d4af4971e09392627e8e53d69d1b70bcb572Michael Kolb                return true;
27358ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark            case KeyEvent.KEYCODE_DPAD_LEFT:
27368ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                if (ctrl) {
2737ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck                    tab.goBack();
27388ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                    return true;
27398ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                }
27408ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                break;
27418ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark            case KeyEvent.KEYCODE_DPAD_RIGHT:
27428ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                if (ctrl) {
2743ef654f1dd80f55609060005342fc4f2cde62990cJohn Reck                    tab.goForward();
27448ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                    return true;
27458ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                }
27468ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                break;
27478ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark            case KeyEvent.KEYCODE_A:
2748e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon                if (ctrl && BrowserWebView.isClassic()) {
27494d2fcaba7fb8eb1723943ac9a10e76d509330bd1Jonathan Dixon                    WebViewClassic.fromWebView(webView).selectAll();
27508ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                    return true;
27518ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                }
27528ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                break;
2753a418306e08e008da99cef929c48e05d2a101ceafMichael Kolb//          case KeyEvent.KEYCODE_B:    // menu
27548ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark            case KeyEvent.KEYCODE_C:
2755e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon                if (ctrl && BrowserWebView.isClassic()) {
27564d2fcaba7fb8eb1723943ac9a10e76d509330bd1Jonathan Dixon                    WebViewClassic.fromWebView(webView).copySelection();
27578ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                    return true;
27588ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                }
27598ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                break;
2760a418306e08e008da99cef929c48e05d2a101ceafMichael Kolb//          case KeyEvent.KEYCODE_D:    // menu
27618ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_E:    // in Chrome: puts '?' in URL bar
2762a418306e08e008da99cef929c48e05d2a101ceafMichael Kolb//          case KeyEvent.KEYCODE_F:    // menu
27638ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_G:    // in Chrome: finds next match
2764a418306e08e008da99cef929c48e05d2a101ceafMichael Kolb//          case KeyEvent.KEYCODE_H:    // menu
27658ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_I:    // unused
2766a418306e08e008da99cef929c48e05d2a101ceafMichael Kolb//          case KeyEvent.KEYCODE_J:    // menu
27678ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_K:    // in Chrome: puts '?' in URL bar
2768a418306e08e008da99cef929c48e05d2a101ceafMichael Kolb//          case KeyEvent.KEYCODE_L:    // menu
27698ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_M:    // unused
27708ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_N:    // in Chrome: new window
27718ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_O:    // in Chrome: open file
27728ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_P:    // in Chrome: print page
27738ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_Q:    // unused
2774dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb//          case KeyEvent.KEYCODE_R:
27758ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_S:    // in Chrome: saves page
27768ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark            case KeyEvent.KEYCODE_T:
2777dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb                // we can't use the ctrl/shift flags, they check for
2778dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb                // exclusive use of a modifier
2779dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb                if (event.isCtrlPressed()) {
27808ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                    if (event.isShiftPressed()) {
2781519d22840ea587988214a625dc8106e1302ac4a9Michael Kolb                        openIncognitoTab();
27828ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                    } else {
27838ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                        openTabToHomePage();
27848ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                    }
27858ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                    return true;
27868ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                }
27878ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark                break;
27888ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_U:    // in Chrome: opens source of page
27898ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_V:    // text view intercepts to paste
27905ae15bd3b32860c471ed4cbfa4ba46b2e1a9911dMichael Kolb//          case KeyEvent.KEYCODE_W:    // menu
27918ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_X:    // text view intercepts to cut
27928ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_Y:    // unused
27938ff8c66a4b2351add40d391a9bd5ea91e840c5f6Cary Clark//          case KeyEvent.KEYCODE_Z:    // unused
27948233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2795dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb        // it is a regular key and webview is not null
2796dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb         return mUi.dispatchKey(keyCode, event);
27978233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
27988233facddcc51865d612a919d450db6954aa48e3Michael Kolb
27999c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
28009c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
2801e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck        switch(keyCode) {
2802e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck        case KeyEvent.KEYCODE_BACK:
28033ba455394dd3413b6246f00d2bf2083547862735John Reck            if (mUi.isWebShowing()) {
2804315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb                bookmarksOrHistoryPicker(ComboViews.History);
2805e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck                return true;
2806e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck            }
2807e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck            break;
2808e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck        }
2809e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck        return false;
2810e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck    }
2811e6bf4abbb12a83fc0256d98d9d5cb36ee326f1ceJohn Reck
28129c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
28139c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    public boolean onKeyUp(int keyCode, KeyEvent event) {
2814bcef87fe4a6cc084695bc6c3a1716ebb005230c5John Reck        if (isMenuOrCtrlKey(keyCode)) {
28152814a362c21ac219410d9b54e1bd3e8152b845c7Michael Kolb            mMenuIsDown = false;
2816bcef87fe4a6cc084695bc6c3a1716ebb005230c5John Reck            if (KeyEvent.KEYCODE_MENU == keyCode
2817bcef87fe4a6cc084695bc6c3a1716ebb005230c5John Reck                    && event.isTracking() && !event.isCanceled()) {
28184bd767d2f4ce166a44687170c6af18e242447205Michael Kolb                return onMenuKey();
28192814a362c21ac219410d9b54e1bd3e8152b845c7Michael Kolb            }
28202814a362c21ac219410d9b54e1bd3e8152b845c7Michael Kolb        }
2821160bbb9565b63302c88b032e4653f8268553175fCary Clark        if (!event.hasNoModifiers()) return false;
28228233facddcc51865d612a919d450db6954aa48e3Michael Kolb        switch(keyCode) {
28238233facddcc51865d612a919d450db6954aa48e3Michael Kolb            case KeyEvent.KEYCODE_BACK:
28248233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (event.isTracking() && !event.isCanceled()) {
28258233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    onBackKey();
28268233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    return true;
28278233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
28288233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
28298233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
28308233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return false;
28318233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
28328233facddcc51865d612a919d450db6954aa48e3Michael Kolb
28338233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public boolean isMenuDown() {
28348233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mMenuIsDown;
28358233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
28368233facddcc51865d612a919d450db6954aa48e3Michael Kolb
28379c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
28388029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch    public void setupAutoFill(Message message) {
28398029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch        // Open the settings activity at the AutoFill profile fragment so that
28408029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch        // the user can create a new profile. When they return, we will dispatch
28418029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch        // the message so that we can autofill the form using their new profile.
28428029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch        Intent intent = new Intent(mActivity, BrowserPreferencesPage.class);
28438029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch        intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT,
28448029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch                AutoFillSettingsFragment.class.getName());
28458029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch        mAutoFillSetupMessage = message;
28468029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch        mActivity.startActivityForResult(intent, AUTOFILL_SETUP);
28478029a777106fa6fb911ee1d58402b0de768a583aBen Murdoch    }
2848b3417f0a68a1efc64604ea354ae7f856ce79cb16John Reck
28499c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
2850fbc579af4749526882c764cd176a167205306fe9Michael Kolb    public boolean onSearchRequested() {
28511f9b3565dbd1911dfe4d9bfd8b833a5ac5f2e0c4Michael Kolb        mUi.editUrl(false, true);
2852fbc579af4749526882c764cd176a167205306fe9Michael Kolb        return true;
2853fbc579af4749526882c764cd176a167205306fe9Michael Kolb    }
2854fbc579af4749526882c764cd176a167205306fe9Michael Kolb
28551cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    @Override
28561cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    public boolean shouldCaptureThumbnails() {
28571cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        return mUi.shouldCaptureThumbnails();
28581cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
28591cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
2860c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    @Override
28610b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb    public boolean supportsVoice() {
28620b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb        PackageManager pm = mActivity.getPackageManager();
28630b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb        List activities = pm.queryIntentActivities(new Intent(
28640b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb                RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
28650b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb        return activities.size() != 0;
28660b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb    }
28670b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb
28680b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb    @Override
28690b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb    public void startVoiceRecognizer() {
28700b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb        Intent voice = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
28710b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb        voice.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
28720b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb                RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
28730b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb        voice.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
28740b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb        mActivity.startActivityForResult(voice, VOICE_RESULT);
28750b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb    }
28760b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb
28770b12912da64ff5b2917d4f50eb91df2e76457d08Michael Kolb    @Override
2878c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    public void setBlockEvents(boolean block) {
2879c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb        mBlockEvents = block;
2880c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    }
2881c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb
28829c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
2883c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    public boolean dispatchKeyEvent(KeyEvent event) {
288487357644efd5940876deb29820d3049bc9c6b13aMichael Kolb        return mBlockEvents;
2885c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    }
2886c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb
28879c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
2888c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
288987357644efd5940876deb29820d3049bc9c6b13aMichael Kolb        return mBlockEvents;
2890c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    }
2891c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb
28929c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
2893c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    public boolean dispatchTouchEvent(MotionEvent ev) {
289487357644efd5940876deb29820d3049bc9c6b13aMichael Kolb        return mBlockEvents;
2895c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    }
2896c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb
28979c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
2898c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    public boolean dispatchTrackballEvent(MotionEvent ev) {
289987357644efd5940876deb29820d3049bc9c6b13aMichael Kolb        return mBlockEvents;
2900c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    }
2901c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb
29029c35b9c41d756d59f5356edd2e08432e01f351f6John Reck    @Override
2903c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    public boolean dispatchGenericMotionEvent(MotionEvent ev) {
290487357644efd5940876deb29820d3049bc9c6b13aMichael Kolb        return mBlockEvents;
2905c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb    }
2906c3af06776be83ba64a0d3549cb72ca6e5e7f03cdMichael Kolb
29078233facddcc51865d612a919d450db6954aa48e3Michael Kolb}
2908