auto import from //depot/cupcake/@135843
diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java
new file mode 100644
index 0000000..2f39302
--- /dev/null
+++ b/src/com/android/browser/TabControl.java
@@ -0,0 +1,937 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser;
+
+import android.content.Context;
+import android.net.http.SslError;
+import android.os.Bundle;
+import android.os.Message;
+import android.util.Config;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.webkit.HttpAuthHandler;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebBackForwardList;
+import android.webkit.WebChromeClient;
+import android.webkit.WebHistoryItem;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Vector;
+
+class TabControl {
+    // Log Tag
+    private static final String LOGTAG = "TabControl";
+    // Maximum number of tabs.
+    static final int MAX_TABS = 8;
+    // Static instance of an empty callback.
+    private static final WebViewClient mEmptyClient =
+            new WebViewClient();
+    // Instance of BackgroundChromeClient for background tabs.
+    private final BackgroundChromeClient mBackgroundChromeClient =
+            new BackgroundChromeClient();
+    // Private array of WebViews that are used as tabs.
+    private ArrayList<Tab> mTabs = new ArrayList<Tab>(MAX_TABS);
+    // Queue of most recently viewed tabs.
+    private ArrayList<Tab> mTabQueue = new ArrayList<Tab>(MAX_TABS);
+    // Current position in mTabs.
+    private int mCurrentTab = -1;
+    // A private instance of BrowserActivity to interface with when adding and
+    // switching between tabs.
+    private final BrowserActivity mActivity;
+    // Inflation service for making subwindows.
+    private final LayoutInflater mInflateService;
+    // Subclass of WebViewClient used in subwindows to notify the main
+    // WebViewClient of certain WebView activities.
+    private class SubWindowClient extends WebViewClient {
+        // The main WebViewClient.
+        private final WebViewClient mClient;
+
+        SubWindowClient(WebViewClient client) {
+            mClient = client;
+        }
+        @Override
+        public void doUpdateVisitedHistory(WebView view, String url,
+                boolean isReload) {
+            mClient.doUpdateVisitedHistory(view, url, isReload);
+        }
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView view, String url) {
+            return mClient.shouldOverrideUrlLoading(view, url);
+        }
+        @Override
+        public void onReceivedSslError(WebView view, SslErrorHandler handler,
+                SslError error) {
+            mClient.onReceivedSslError(view, handler, error);
+        }
+        @Override
+        public void onReceivedHttpAuthRequest(WebView view,
+                HttpAuthHandler handler, String host, String realm) {
+            mClient.onReceivedHttpAuthRequest(view, handler, host, realm);
+        }
+        @Override
+        public void onFormResubmission(WebView view, Message dontResend,
+                Message resend) {
+            mClient.onFormResubmission(view, dontResend, resend);
+        }
+        @Override
+        public void onReceivedError(WebView view, int errorCode,
+                String description, String failingUrl) {
+            mClient.onReceivedError(view, errorCode, description, failingUrl);
+        }
+    }
+    // Subclass of WebChromeClient to display javascript dialogs.
+    private class SubWindowChromeClient extends WebChromeClient {
+        // This subwindow's tab.
+        private final Tab mTab;
+        // The main WebChromeClient.
+        private final WebChromeClient mClient;
+
+        SubWindowChromeClient(Tab t, WebChromeClient client) {
+            mTab = t;
+            mClient = client;
+        }
+        @Override
+        public void onProgressChanged(WebView view, int newProgress) {
+            mClient.onProgressChanged(view, newProgress);
+        }
+        @Override
+        public boolean onCreateWindow(WebView view, boolean dialog,
+                boolean userGesture, android.os.Message resultMsg) {
+            return mClient.onCreateWindow(view, dialog, userGesture, resultMsg);
+        }
+        @Override
+        public void onCloseWindow(WebView window) {
+            if (Config.DEBUG && window != mTab.mSubView) {
+                throw new AssertionError("Can't close the window");
+            }
+            mActivity.dismissSubWindow(mTab);
+        }
+    }
+    // Background WebChromeClient for focusing tabs
+    private class BackgroundChromeClient extends WebChromeClient {
+        @Override
+        public void onRequestFocus(WebView view) {
+            Tab t = getTabFromView(view);
+            if (t != getCurrentTab()) {
+                mActivity.showTab(t);
+            }
+        }
+    }
+
+    /**
+     * Private class for maintaining Tabs with a main WebView and a subwindow.
+     */
+    public class Tab {
+        // Main WebView
+        private WebView mMainView;
+        // Subwindow WebView
+        private WebView mSubView;
+        // Subwindow container
+        private View mSubViewContainer;
+        // Subwindow callback
+        private SubWindowClient mSubViewClient;
+        // Subwindow chrome callback
+        private SubWindowChromeClient mSubViewChromeClient;
+        // Saved bundle for when we are running low on memory. It contains the
+        // information needed to restore the WebView if the user goes back to
+        // the tab.
+        private Bundle mSavedState;
+        // Extra saved information for displaying the tab in the picker.
+        private String mUrl;
+        private String mTitle;
+ 
+        // Parent Tab. This is the Tab that created this Tab, or null
+        // if the Tab was created by the UI
+        private Tab mParentTab;
+        // Tab that constructed by this Tab. This is used when this
+        // Tab is destroyed, it clears all mParentTab values in the 
+        // children.
+        private Vector<Tab> mChildTabs;
+
+        private Boolean mCloseOnExit;
+
+        // Construct a new tab
+        private Tab(WebView w, boolean closeOnExit) {
+            mMainView = w;
+            mCloseOnExit = closeOnExit;
+        }
+
+        /**
+         * Return the top window of this tab; either the subwindow if it is not
+         * null or the main window.
+         * @return The top window of this tab.
+         */
+        public WebView getTopWindow() {
+            if (mSubView != null) {
+                return mSubView;
+            }
+            return mMainView;
+        }
+
+        /**
+         * Return the main window of this tab. Note: if a tab is freed in the
+         * background, this can return null. It is only guaranteed to be 
+         * non-null for the current tab.
+         * @return The main WebView of this tab.
+         */
+        public WebView getWebView() {
+            return mMainView;
+        }
+
+        /**
+         * Return the subwindow of this tab or null if there is no subwindow.
+         * @return The subwindow of this tab or null.
+         */
+        public WebView getSubWebView() {
+            return mSubView;
+        }
+
+        /**
+         * Return the subwindow container of this tab or null if there is no
+         * subwindow.
+         * @return The subwindow's container View.
+         */
+        public View getSubWebViewContainer() {
+            return mSubViewContainer;
+        }
+
+        /**
+         * Get the url of this tab.  Valid after calling populatePickerData, but
+         * before calling wipePickerData, or if the webview has been destroyed.
+         * 
+         * @return The WebView's url or null.
+         */
+        public String getUrl() {
+            return mUrl;
+        }
+
+        /**
+         * Get the title of this tab.  Valid after calling populatePickerData, 
+         * but before calling wipePickerData, or if the webview has been 
+         * destroyed.  If the url has no title, use the url instead.
+         * 
+         * @return The WebView's title (or url) or null.
+         */
+        public String getTitle() {
+            return mTitle;
+        }
+
+        private void setParentTab(Tab parent) {
+            mParentTab = parent;
+            // This tab may have been freed due to low memory. If that is the
+            // case, the parent tab index is already saved. If we are changing
+            // that index (most likely due to removing the parent tab) we must
+            // update the parent tab index in the saved Bundle.
+            if (mSavedState != null) {
+                if (parent == null) {
+                    mSavedState.remove(PARENTTAB);
+                } else {
+                    mSavedState.putInt(PARENTTAB, getTabIndex(parent));
+                }
+            }
+        }
+        
+        /**
+         * When a Tab is created through the content of another Tab, then 
+         * we associate the Tabs. 
+         * @param child the Tab that was created from this Tab
+         */
+        public void addChildTab(Tab child) {
+            if (mChildTabs == null) {
+                mChildTabs = new Vector<Tab>();
+            }
+            mChildTabs.add(child);
+            child.setParentTab(this);
+        }
+        
+        private void removeFromTree() {
+            // detach the children
+            if (mChildTabs != null) {
+                for(Tab t : mChildTabs) {
+                    t.setParentTab(null);
+                }
+            }
+            
+            // Find myself in my parent list
+            if (mParentTab != null) {
+                mParentTab.mChildTabs.remove(this);
+            }
+        }
+        
+        /**
+         * If this Tab was created through another Tab, then this method
+         * returns that Tab.
+         * @return the Tab parent or null
+         */
+        public Tab getParentTab() {
+            return mParentTab;
+        }
+
+        /**
+         * Return whether this tab should be closed when it is backing out of
+         * the first page.
+         * @return TRUE if this tab should be closed when exit.
+         */
+        public boolean closeOnExit() {
+            return mCloseOnExit;
+        }
+    };
+
+    // Directory to store thumbnails for each WebView.
+    private final File mThumbnailDir;
+
+    /**
+     * Construct a new TabControl object that interfaces with the given
+     * BrowserActivity instance.
+     * @param activity A BrowserActivity instance that TabControl will interface
+     *                 with.
+     */
+    TabControl(BrowserActivity activity) {
+        mActivity = activity;
+        mInflateService =
+                ((LayoutInflater) activity.getSystemService(
+                        Context.LAYOUT_INFLATER_SERVICE));
+        mThumbnailDir = activity.getDir("thumbnails", 0);
+    }
+
+    File getThumbnailDir() {
+        return mThumbnailDir;
+    }
+
+    BrowserActivity getBrowserActivity() {
+        return mActivity;
+    }
+
+    /**
+     * Return the current tab's main WebView. This will always return the main
+     * WebView for a given tab and not a subwindow.
+     * @return The current tab's WebView.
+     */
+    WebView getCurrentWebView() {
+        Tab t = getTab(mCurrentTab);
+        if (t == null) {
+            return null;
+        }
+        return t.mMainView;
+    }
+
+    /**
+     * Return the current tab's top-level WebView. This can return a subwindow
+     * if one exists.
+     * @return The top-level WebView of the current tab.
+     */
+    WebView getCurrentTopWebView() {
+        Tab t = getTab(mCurrentTab);
+        if (t == null) {
+            return null;
+        }
+        return t.mSubView != null ? t.mSubView : t.mMainView;
+    }
+
+    /**
+     * Return the current tab's subwindow if it exists.
+     * @return The subwindow of the current tab or null if it doesn't exist.
+     */
+    WebView getCurrentSubWindow() {
+        Tab t = getTab(mCurrentTab);
+        if (t == null) {
+            return null;
+        }
+        return t.mSubView;
+    }
+
+    /**
+     * Return the tab at the specified index.
+     * @return The Tab for the specified index or null if the tab does not
+     *         exist.
+     */
+    Tab getTab(int index) {
+        if (index >= 0 && index < mTabs.size()) {
+            return mTabs.get(index);
+        }
+        return null;
+    }
+
+    /**
+     * Return the current tab.
+     * @return The current tab.
+     */
+    Tab getCurrentTab() {
+        return getTab(mCurrentTab);
+    }
+
+    /**
+     * Return the current tab index.
+     * @return The current tab index
+     */
+    int getCurrentIndex() {
+        return mCurrentTab;
+    }
+    
+    /**
+     * Given a Tab, find it's index
+     * @param Tab to find
+     * @return index of Tab or -1 if not found
+     */
+    int getTabIndex(Tab tab) {
+        return mTabs.indexOf(tab);
+    }
+
+    /**
+     * Create a new tab and display the new tab immediately.
+     * @return The newly createTab or null if we have reached the maximum
+     *         number of open tabs.
+     */
+    Tab createNewTab(boolean closeOnExit) {
+        int size = mTabs.size();
+        // Return false if we have maxed out on tabs
+        if (MAX_TABS == size) {
+            return null;
+        }
+        // Create a new WebView
+        WebView w = new WebView(mActivity);
+        w.setMapTrackballToArrowKeys(false); // use trackball directly
+        // Add this WebView to the settings observer list and update the
+        // settings
+        final BrowserSettings s = BrowserSettings.getInstance();
+        s.addObserver(w.getSettings()).update(s, null);
+        // Create a new tab and add it to the tab list
+        Tab t = new Tab(w, closeOnExit);
+        mTabs.add(t);
+        return t;
+    }
+
+    /**
+     * Remove the tab from the list. If the tab is the current tab shown, the
+     * last created tab will be shown.
+     * @param t The tab to be removed.
+     */
+    boolean removeTab(Tab t) {
+        if (t == null) {
+            return false;
+        }
+        // Only remove the tab if it is the current one.
+        if (getCurrentTab() == t) {
+            putTabInBackground(t);
+        }
+
+        // Only destroy the WebView if it still exists.
+        if (t.mMainView != null) {
+            // Take down the sub window.
+            dismissSubWindow(t);
+            // Remove the WebView's settings from the BrowserSettings list of
+            // observers.
+            BrowserSettings.getInstance().deleteObserver(
+                    t.mMainView.getSettings());
+            // Destroy the main view and subview
+            t.mMainView.destroy();
+            t.mMainView = null;
+        }
+        // clear it's references to parent and children
+        t.removeFromTree();
+        
+        // Remove it from our list of tabs.
+        mTabs.remove(t);
+
+        // The tab indices have shifted, update all the saved state so we point
+        // to the correct index.
+        for (Tab tab : mTabs) {
+            if (tab.mChildTabs != null) {
+                for (Tab child : tab.mChildTabs) {
+                    child.setParentTab(tab);
+                }
+            }
+        }
+
+
+        // This tab may have been pushed in to the background and then closed.
+        // If the saved state contains a picture file, delete the file.
+        if (t.mSavedState != null) {
+            if (t.mSavedState.containsKey("picture")) {
+                new File(t.mSavedState.getString("picture")).delete();
+            }
+        }
+
+        // Remove it from the queue of viewed tabs.
+        mTabQueue.remove(t);
+        mCurrentTab = -1;
+        return true;
+    }
+
+    /**
+     * Clear the back/forward list for all the current tabs.
+     */
+    void clearHistory() {
+        int size = getTabCount();
+        for (int i = 0; i < size; i++) {
+            Tab t = mTabs.get(i);
+            // TODO: if a tab is freed due to low memory, its history is not
+            // cleared here.
+            if (t.mMainView != null) {
+                t.mMainView.clearHistory();
+            }
+            if (t.mSubView != null) {
+                t.mSubView.clearHistory();
+            }
+        }
+    }
+
+    /**
+     * Destroy all the tabs and subwindows
+     */
+    void destroy() {
+        BrowserSettings s = BrowserSettings.getInstance();
+        for (Tab t : mTabs) {
+            if (t.mMainView != null) {
+                dismissSubWindow(t);
+                s.deleteObserver(t.mMainView.getSettings());
+                t.mMainView.destroy();
+                t.mMainView = null;
+            }
+        }
+        mTabs.clear();
+        mTabQueue.clear();
+    }
+
+    /**
+     * Returns the number of tabs created.
+     * @return The number of tabs created.
+     */
+    int getTabCount() {
+        return mTabs.size();
+    }
+
+    // Used for saving and restoring each Tab
+    private static final String WEBVIEW = "webview";
+    private static final String NUMTABS = "numTabs";
+    private static final String CURRTAB = "currentTab";
+    private static final String CURRURL = "currentUrl";
+    private static final String CURRTITLE = "currentTitle";
+    private static final String CLOSEONEXIT = "closeonexit";
+    private static final String PARENTTAB = "parentTab";
+
+    /**
+     * Save the state of all the Tabs.
+     * @param outState The Bundle to save the state to.
+     */
+    void saveState(Bundle outState) {
+        final int numTabs = getTabCount();
+        outState.putInt(NUMTABS, numTabs);
+        final int index = getCurrentIndex();
+        outState.putInt(CURRTAB, (index >= 0 && index < numTabs) ? index : 0);
+        for (int i = 0; i < numTabs; i++) {
+            final Tab t = getTab(i);
+            if (saveState(t)) {
+                outState.putBundle(WEBVIEW + i, t.mSavedState);
+            }
+        }
+    }
+
+    /**
+     * Restore the state of all the tabs.
+     * @param inState The saved state of all the tabs.
+     * @return True if there were previous tabs that were restored. False if
+     *         there was no saved state or restoring the state failed.
+     */
+    boolean restoreState(Bundle inState) {
+        final int numTabs = (inState == null)
+                ? -1 : inState.getInt(NUMTABS, -1);
+        if (numTabs == -1) {
+            return false;
+        } else {
+            final int currentTab = inState.getInt(CURRTAB, -1);
+            for (int i = 0; i < numTabs; i++) {
+                if (i == currentTab) {
+                    Tab t = createNewTab(false);
+                    // Me must set the current tab before restoring the state
+                    // so that all the client classes are set.
+                    setCurrentTab(t);
+                    if (!restoreState(inState.getBundle(WEBVIEW + i), t)) {
+                        Log.w(LOGTAG, "Fail in restoreState, load home page.");
+                        t.mMainView.loadUrl(BrowserSettings.getInstance()
+                                .getHomePage());
+                    }
+                } else {
+                    // Create a new tab and don't restore the state yet, add it
+                    // to the tab list
+                    Tab t = new Tab(null, false);
+                    t.mSavedState = inState.getBundle(WEBVIEW + i);
+                    if (t.mSavedState != null) {
+                        t.mUrl = t.mSavedState.getString(CURRURL);
+                        t.mTitle = t.mSavedState.getString(CURRTITLE);
+                    }
+                    mTabs.add(t);
+                    mTabQueue.add(t);
+                }
+            }
+            // Rebuild the tree of tabs. Do this after all tabs have been
+            // created/restored so that the parent tab exists.
+            for (int i = 0; i < numTabs; i++) {
+                final Bundle b = inState.getBundle(WEBVIEW + i);
+                final Tab t = getTab(i);
+                if (b != null && t != null) {
+                    final int parentIndex = b.getInt(PARENTTAB, -1);
+                    if (parentIndex != -1) {
+                        final Tab parent = getTab(parentIndex);
+                        if (parent != null) {
+                            parent.addChildTab(t);
+                        }
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Free the memory in this order, 1) free the background tab; 2) free the
+     * WebView cache;
+     */
+    void freeMemory() {
+        // free the least frequently used background tab
+        Tab t = getLeastUsedTab();
+        if (t != null) {
+            Log.w(LOGTAG, "Free a tab in the browser");
+            freeTab(t);
+            // force a gc
+            System.gc();
+            return;
+        }
+
+        // free the WebView cache
+        Log.w(LOGTAG, "Free WebView cache");
+        WebView view = getCurrentWebView();
+        if (view != null) {
+            view.clearCache(false);
+        }
+        // force a gc
+        System.gc();
+    }
+
+    private Tab getLeastUsedTab() {
+        // Don't do anything if we only have 1 tab.
+        if (getTabCount() == 1) {
+            return null;
+        }
+
+        // Rip through the queue starting at the beginning and teardown the
+        // next available tab.
+        Tab t = null;
+        int i = 0;
+        final int queueSize = mTabQueue.size();
+        if (queueSize == 0) {
+            return null;
+        }
+        do {
+            t = mTabQueue.get(i++);
+        } while (i < queueSize && t != null && t.mMainView == null);
+
+        // Don't do anything if the last remaining tab is the current one.
+        if (t == getCurrentTab()) {
+            return null;
+        }
+
+        return t;
+    }
+
+    private void freeTab(Tab t) {
+        // Store the WebView's state.
+        saveState(t);
+
+        // Tear down the tab.
+        dismissSubWindow(t);
+        // Remove the WebView's settings from the BrowserSettings list of
+        // observers.
+        BrowserSettings.getInstance().deleteObserver(t.mMainView.getSettings());
+        t.mMainView.destroy();
+        t.mMainView = null;
+    }
+
+    /**
+     * Create a new subwindow unless a subwindow already exists.
+     * @return True if a new subwindow was created. False if one already exists.
+     */
+    void createSubWindow() {
+        Tab t = getTab(mCurrentTab);
+        if (t != null && t.mSubView == null) {
+            final View v = mInflateService.inflate(R.layout.browser_subwindow, null);
+            final WebView w = (WebView) v.findViewById(R.id.webview);
+            w.setMapTrackballToArrowKeys(false); // use trackball directly
+            final SubWindowClient subClient =
+                    new SubWindowClient(mActivity.getWebViewClient());
+            final SubWindowChromeClient subChromeClient =
+                    new SubWindowChromeClient(t,
+                            mActivity.getWebChromeClient());
+            w.setWebViewClient(subClient);
+            w.setWebChromeClient(subChromeClient);
+            w.setDownloadListener(mActivity);
+            w.setOnCreateContextMenuListener(mActivity);
+            final BrowserSettings s = BrowserSettings.getInstance();
+            s.addObserver(w.getSettings()).update(s, null);
+            t.mSubView = w;
+            t.mSubViewClient = subClient;
+            t.mSubViewChromeClient = subChromeClient;
+            // FIXME: I really hate having to know the name of the view
+            // containing the webview.
+            t.mSubViewContainer = v.findViewById(R.id.subwindow_container);
+            final ImageButton cancel =
+                    (ImageButton) v.findViewById(R.id.subwindow_close);
+            cancel.setOnClickListener(new OnClickListener() {
+                    public void onClick(View v) {
+                        subChromeClient.onCloseWindow(w);
+                    }
+                });
+        }
+    }
+
+    /**
+     * Show the tab that contains the given WebView.
+     * @param view The WebView used to find the tab.
+     */
+    Tab getTabFromView(WebView view) {
+        final int size = getTabCount();
+        for (int i = 0; i < size; i++) {
+            final Tab t = getTab(i);
+            if (t.mSubView == view || t.mMainView == view) {
+                return t;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Put the current tab in the background and set newTab as the current tab.
+     * @param newTab The new tab. If newTab is null, the current tab is not
+     *               set.
+     */
+    boolean setCurrentTab(Tab newTab) {
+        Tab current = getTab(mCurrentTab);
+        if (current == newTab) {
+            return true;
+        }
+        if (current != null) {
+            // Remove the current WebView and the container of the subwindow
+            putTabInBackground(current);
+        }
+
+        if (newTab == null) {
+            return false;
+        }
+
+        // Move the newTab to the end of the queue
+        int index = mTabQueue.indexOf(newTab);
+        if (index != -1) {
+            mTabQueue.remove(index);
+        }
+        mTabQueue.add(newTab);
+
+        WebView mainView;
+        WebView subView;
+
+        // Display the new current tab
+        mCurrentTab = mTabs.indexOf(newTab);
+        mainView = newTab.mMainView;
+        boolean needRestore = (mainView == null);
+        if (needRestore) {
+            // Same work as in createNewTab() except don't do new Tab()
+            newTab.mMainView = mainView = new WebView(mActivity);
+            mainView.setMapTrackballToArrowKeys(false); // use t-ball directly
+
+            // Add this WebView to the settings observer list and update the
+            // settings
+            final BrowserSettings s = BrowserSettings.getInstance();
+            s.addObserver(mainView.getSettings()).update(s, null);
+        }
+        mainView.setWebViewClient(mActivity.getWebViewClient());
+        mainView.setWebChromeClient(mActivity.getWebChromeClient());
+        mainView.setOnCreateContextMenuListener(mActivity);
+        mainView.setDownloadListener(mActivity);
+        // Add the subwindow if it exists
+        if (newTab.mSubViewContainer != null) {
+            subView = newTab.mSubView;
+            subView.setWebViewClient(newTab.mSubViewClient);
+            subView.setWebChromeClient(newTab.mSubViewChromeClient);
+            subView.setOnCreateContextMenuListener(mActivity);
+            subView.setDownloadListener(mActivity);
+        }
+        if (needRestore) {
+            // Have to finish setCurrentTab work before calling restoreState
+            if (!restoreState(newTab.mSavedState, newTab)) {
+                mainView.loadUrl(BrowserSettings.getInstance().getHomePage());
+            }
+        }
+        return true;
+    }
+
+    /*
+     * Put the tab in the background using all the empty/background clients.
+     */
+    private void putTabInBackground(Tab t) {
+        WebView mainView = t.mMainView;
+        // Set an empty callback so that default actions are not triggered.
+        mainView.setWebViewClient(mEmptyClient);
+        mainView.setWebChromeClient(mBackgroundChromeClient);
+        mainView.setOnCreateContextMenuListener(null);
+        // Leave the DownloadManager attached so that downloads can start in
+        // a non-active window. This can happen when going to a site that does
+        // a redirect after a period of time. The user could have switched to
+        // another tab while waiting for the download to start.
+        mainView.setDownloadListener(mActivity);
+        WebView subView = t.mSubView;
+        if (subView != null) {
+            // Set an empty callback so that default actions are not triggered.
+            subView.setWebViewClient(mEmptyClient);
+            subView.setWebChromeClient(mBackgroundChromeClient);
+            subView.setOnCreateContextMenuListener(null);
+            subView.setDownloadListener(mActivity);
+        }
+    }
+
+    /*
+     * Dismiss the subwindow for the given tab.
+     */
+    void dismissSubWindow(Tab t) {
+        if (t != null && t.mSubView != null) {
+            BrowserSettings.getInstance().deleteObserver(
+                    t.mSubView.getSettings());
+            t.mSubView.destroy();
+            t.mSubView = null;
+            t.mSubViewContainer = null;
+        }
+    }
+
+    /**
+     * Ensure that Tab t has a title, url, and favicon.
+     * @param  t   Tab to populate.
+     */
+    /* package */ void populatePickerData(Tab t) {
+        if (t == null || t.mMainView == null) {
+            return;
+        }
+        // FIXME: The only place we cared about subwindow was for 
+        // bookmarking (i.e. not when saving state). Was this deliberate?
+        final WebBackForwardList list = t.mMainView.copyBackForwardList();
+        final WebHistoryItem item =
+                list != null ? list.getCurrentItem() : null;
+        populatePickerData(t, item);
+    }
+
+    // Populate the picker data
+    private void populatePickerData(Tab t, WebHistoryItem item) {
+        if (item != null) {
+            t.mUrl = item.getUrl();
+            t.mTitle = item.getTitle();
+            if (t.mTitle == null) {
+                t.mTitle = t.mUrl;
+            }
+        }
+    }
+    
+    /**
+     * Clean up the data for all tabs.
+     */
+    /* package */ void wipeAllPickerData() {
+        int size = getTabCount();
+        for (int i = 0; i < size; i++) {
+            final Tab t = getTab(i);
+            if (t != null && t.mSavedState == null) {
+                t.mUrl = null;
+                t.mTitle = null;
+            }
+        }
+    }
+
+    /*
+     * Save the state for an individual tab.
+     */
+    private boolean saveState(Tab t) {
+        if (t != null) {
+            final WebView w = t.mMainView;
+            // If the WebView is null it means we ran low on memory and we
+            // already stored the saved state in mSavedState.
+            if (w == null) {
+                return true;
+            }
+            final Bundle b = new Bundle();
+            final WebBackForwardList list = w.saveState(b);
+            if (list != null) {
+                final File f = new File(mThumbnailDir, w.hashCode()
+                        + "_pic.save");
+                if (w.savePicture(b, f)) {
+                    b.putString("picture", f.getPath());
+                }
+            }
+
+            // Store some extra info for displaying the tab in the picker.
+            final WebHistoryItem item =
+                    list != null ? list.getCurrentItem() : null;
+            populatePickerData(t, item);
+            if (t.mUrl != null) {
+                b.putString(CURRURL, t.mUrl);
+            }
+            if (t.mTitle != null) {
+                b.putString(CURRTITLE, t.mTitle);
+            }
+            b.putBoolean(CLOSEONEXIT, t.mCloseOnExit);
+
+            // Remember the parent tab so the relationship can be restored.
+            if (t.mParentTab != null) {
+                b.putInt(PARENTTAB, getTabIndex(t.mParentTab));
+            }
+
+            // Remember the saved state.
+            t.mSavedState = b;
+            return true;
+        }
+        return false;
+    }
+
+    /*
+     * Restore the state of the tab.
+     */
+    private boolean restoreState(Bundle b, Tab t) {
+        if (b == null) {
+            return false;
+        }
+        final WebView w = t.mMainView;
+        final WebBackForwardList list = w.restoreState(b);
+        if (list == null) {
+            return false;
+        }
+        if (b.containsKey("picture")) {
+            final File f = new File(b.getString("picture"));
+            w.restorePicture(b, f);
+            f.delete();
+        }
+        t.mSavedState = null;
+        t.mUrl = null;
+        t.mTitle = null;
+        t.mCloseOnExit = b.getBoolean(CLOSEONEXIT);
+        return true;
+    }
+}