10c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project/*
20c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
30c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project *
40c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
50c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * you may not use this file except in compliance with the License.
60c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * You may obtain a copy of the License at
70c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project *
80c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
90c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project *
100c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
110c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
120c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * See the License for the specific language governing permissions and
140c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * limitations under the License.
150c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */
160c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
170c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectpackage com.android.browser;
180c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
190c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.os.Bundle;
200c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.util.Log;
210c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.webkit.WebView;
220c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
230c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport java.util.ArrayList;
243d6df16f1c9a64cf2dc5b41a2078f4c49b0c296aElliott Slaughterimport java.util.HashMap;
251bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolbimport java.util.List;
260c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport java.util.Vector;
270c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
280c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectclass TabControl {
290c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    // Log Tag
300c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    private static final String LOGTAG = "TabControl";
31c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb
32d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck    // next Tab ID, starting at 1
33d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck    private static long sNextId = 1;
34c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb
35c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    private static final String POSITIONS = "positions";
36c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    private static final String CURRENT = "current";
37c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb
388ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck    public static interface OnThumbnailUpdatedListener {
398ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        void onThumbnailUpdated(Tab t);
408ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck    }
418ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck
420c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    // Maximum number of tabs.
436e4653ee2adbee765d210e44ed38600d79135a06Michael Kolb    private int mMaxTabs;
440c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    // Private array of WebViews that are used as tabs.
456e4653ee2adbee765d210e44ed38600d79135a06Michael Kolb    private ArrayList<Tab> mTabs;
460c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    // Queue of most recently viewed tabs.
476e4653ee2adbee765d210e44ed38600d79135a06Michael Kolb    private ArrayList<Tab> mTabQueue;
480c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    // Current position in mTabs.
490c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    private int mCurrentTab = -1;
508233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // the main browser controller
518233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private final Controller mController;
528233facddcc51865d612a919d450db6954aa48e3Michael Kolb
538ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck    private OnThumbnailUpdatedListener mOnThumbnailUpdatedListener;
540c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
550c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
568233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Construct a new TabControl object
570c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
588233facddcc51865d612a919d450db6954aa48e3Michael Kolb    TabControl(Controller controller) {
598233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mController = controller;
608233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mMaxTabs = mController.getMaxTabs();
616e4653ee2adbee765d210e44ed38600d79135a06Michael Kolb        mTabs = new ArrayList<Tab>(mMaxTabs);
626e4653ee2adbee765d210e44ed38600d79135a06Michael Kolb        mTabQueue = new ArrayList<Tab>(mMaxTabs);
630c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
640c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
6552be4785a258687055515117775d5bcb8bec1c12John Reck    synchronized static long getNextId() {
66c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        return sNextId++;
67c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    }
68c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb
6968775756e20243d73f273e4ce25ff3edeb148e41Michael Kolb    /**
700c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * Return the current tab's main WebView. This will always return the main
710c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * WebView for a given tab and not a subwindow.
720c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @return The current tab's WebView.
730c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
740c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    WebView getCurrentWebView() {
750c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        Tab t = getTab(mCurrentTab);
760c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (t == null) {
770c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            return null;
780c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
7922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        return t.getWebView();
80bff2d603c022691237c31d9a57ad8c217c6e7e11Ben Murdoch    }
81bff2d603c022691237c31d9a57ad8c217c6e7e11Ben Murdoch
82bff2d603c022691237c31d9a57ad8c217c6e7e11Ben Murdoch    /**
830c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * Return the current tab's top-level WebView. This can return a subwindow
840c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * if one exists.
850c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @return The top-level WebView of the current tab.
860c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
870c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    WebView getCurrentTopWebView() {
880c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        Tab t = getTab(mCurrentTab);
890c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (t == null) {
900c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            return null;
910c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
9222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        return t.getTopWindow();
930c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
940c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
950c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
960c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * Return the current tab's subwindow if it exists.
970c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @return The subwindow of the current tab or null if it doesn't exist.
980c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
990c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    WebView getCurrentSubWindow() {
1000c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        Tab t = getTab(mCurrentTab);
1010c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (t == null) {
1020c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            return null;
1030c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
10422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        return t.getSubWebView();
1050c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
1060c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
1070c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
1081bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb     * return the list of tabs
1091bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb     */
1101bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb    List<Tab> getTabs() {
1111bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        return mTabs;
1121bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb    }
1131bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb
1141bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb    /**
115c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * Return the tab at the specified position.
116c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * @return The Tab for the specified position or null if the tab does not
1170c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     *         exist.
1180c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
119c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    Tab getTab(int position) {
120c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        if (position >= 0 && position < mTabs.size()) {
121c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            return mTabs.get(position);
1220c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
1230c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        return null;
1240c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
1250c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
1260c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
1270c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * Return the current tab.
1280c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @return The current tab.
1290c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
1300c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    Tab getCurrentTab() {
1310c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        return getTab(mCurrentTab);
1320c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
1330c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
1340c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
135c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * Return the current tab position.
136c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * @return The current tab position
1370c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
138c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    int getCurrentPosition() {
1390c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        return mCurrentTab;
1400c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
141fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolb
1420c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
143c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * Given a Tab, find it's position
1440c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @param Tab to find
145c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * @return position of Tab or -1 if not found
1460c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
147c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    int getTabPosition(Tab tab) {
148ae641ac4bbe1c7c3fb235774cb84d910573595c7Patrick Scott        if (tab == null) {
149ae641ac4bbe1c7c3fb235774cb84d910573595c7Patrick Scott            return -1;
150ae641ac4bbe1c7c3fb235774cb84d910573595c7Patrick Scott        }
1510c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        return mTabs.indexOf(tab);
1520c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
1530c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
15422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    boolean canCreateNewTab() {
155c3ad9eada3ab7acac5d194fd4a8d30443079e80eNarayan Kamath        return mMaxTabs > mTabs.size();
15622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    }
15722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
1580c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
159e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter     * Returns true if there are any incognito tabs open.
160e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter     * @return True when any incognito tabs are open, false otherwise.
161e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter     */
162e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter    boolean hasAnyOpenIncognitoTabs() {
163e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter        for (Tab tab : mTabs) {
164c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            if (tab.getWebView() != null
165c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                    && tab.getWebView().isPrivateBrowsingEnabled()) {
166e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter                return true;
167e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter            }
168e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter        }
169e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter        return false;
170e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter    }
171e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter
1721461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb    void addPreloadedTab(Tab tab) {
173e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood        for (Tab current : mTabs) {
174e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood            if (current != null && current.getId() == tab.getId()) {
175e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood                throw new IllegalStateException("Tab with id " + tab.getId() + " already exists: "
176e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood                        + current.toString());
177e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood            }
178e09305e4ad0430571efb8ae880762204ddeaeb33Mathew Inwood        }
1791461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        mTabs.add(tab);
1801461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        tab.setController(mController);
1811461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        mController.onSetWebView(tab, tab.getWebView());
1821461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        tab.putInBackground();
1831461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb    }
1841461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb
185e440a88fd81c86d1ca6fc18b8b3f68e383e574b4Elliott Slaughter    /**
186f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     * Create a new tab.
1870c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @return The newly createTab or null if we have reached the maximum
1880c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     *         number of open tabs.
1890c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
1907bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb    Tab createNewTab(boolean privateBrowsing) {
1911cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        return createNewTab(null, privateBrowsing);
1921cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    }
1931cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck
1941cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    Tab createNewTab(Bundle state, boolean privateBrowsing) {
1951cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        int size = mTabs.size();
1961cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        // Return false if we have maxed out on tabs
197c3ad9eada3ab7acac5d194fd4a8d30443079e80eNarayan Kamath        if (!canCreateNewTab()) {
1980c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            return null;
1990c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
200c3ad9eada3ab7acac5d194fd4a8d30443079e80eNarayan Kamath
201f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter        final WebView w = createNewWebView(privateBrowsing);
2022bc69918d97a767a02132090e58718077381ba1aSteve Block
2030c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        // Create a new tab and add it to the tab list
2041cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck        Tab t = new Tab(mController, w, state);
2050c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        mTabs.add(t);
2064e5f58704099c37186d4825c3d55ea5b0527867fThe Android Open Source Project        // Initially put the tab in the background.
20722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        t.putInBackground();
2080c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        return t;
2090c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
2100c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
2110c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
212f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     * Create a new tab with default values for closeOnExit(false),
213f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter     * appId(null), url(null), and privateBrowsing(false).
214f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     */
215f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    Tab createNewTab() {
2167bcafde2ba532941c1eb8c9022eebd5398aeae2aMichael Kolb        return createNewTab(false);
217f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    }
218f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project
219f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    /**
220fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins     * Remove the parent child relationships from all tabs.
221fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins     */
222fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins    void removeParentChildRelationShips() {
223fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins        for (Tab tab : mTabs) {
224fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins            tab.removeFromTree();
225fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins        }
226fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins    }
227fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins
228fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins    /**
2290c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * Remove the tab from the list. If the tab is the current tab shown, the
2300c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * last created tab will be shown.
2310c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @param t The tab to be removed.
2320c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
2330c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    boolean removeTab(Tab t) {
2340c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (t == null) {
2350c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            return false;
2360c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
23722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba
238d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott        // Grab the current tab before modifying the list.
239d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott        Tab current = getCurrentTab();
240d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott
241d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott        // Remove t from our list of tabs.
242d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott        mTabs.remove(t);
243d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott
244d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott        // Put the tab in the background only if it is the current one.
245d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott        if (current == t) {
24622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            t.putInBackground();
24722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mCurrentTab = -1;
248d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott        } else {
249d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott            // If a tab that is earlier in the list gets removed, the current
250d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott            // index no longer points to the correct tab.
251c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            mCurrentTab = getTabPosition(current);
2520c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
2530c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
25422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        // destroy the tab
25522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        t.destroy();
2560c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        // clear it's references to parent and children
2570c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        t.removeFromTree();
2580c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
2590c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        // Remove it from the queue of viewed tabs.
2600c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        mTabQueue.remove(t);
2610c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        return true;
2620c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
2630c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
2640c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
2650c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * Destroy all the tabs and subwindows
2660c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
2670c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    void destroy() {
2680c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        for (Tab t : mTabs) {
26922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            t.destroy();
2700c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
2710c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        mTabs.clear();
2720c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        mTabQueue.clear();
2730c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
2740c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
2750c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
2760c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * Returns the number of tabs created.
2770c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @return The number of tabs created.
2780c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
2790c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    int getTabCount() {
2800c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        return mTabs.size();
2810c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
2820c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
2830c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
284c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * save the tab state:
285c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * current position
286c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * position sorted array of tab ids
287c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * for each tab id, save the tab state
288c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * @param outState
289aed9c54d8e67bb683a5a415b3775525a3ac00508John Reck     * @param saveImages
2900c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
2911cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck    void saveState(Bundle outState) {
2920c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        final int numTabs = getTabCount();
29324f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck        if (numTabs == 0) {
29424f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck            return;
29524f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck        }
296c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        long[] ids = new long[numTabs];
297c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        int i = 0;
298c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        for (Tab tab : mTabs) {
2991cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            Bundle tabState = tab.saveState();
3001cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            if (tabState != null) {
3013ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb                ids[i++] = tab.getId();
30252be4785a258687055515117775d5bcb8bec1c12John Reck                String key = Long.toString(tab.getId());
30352be4785a258687055515117775d5bcb8bec1c12John Reck                if (outState.containsKey(key)) {
30452be4785a258687055515117775d5bcb8bec1c12John Reck                    // Dump the tab state for debugging purposes
30552be4785a258687055515117775d5bcb8bec1c12John Reck                    for (Tab dt : mTabs) {
30652be4785a258687055515117775d5bcb8bec1c12John Reck                        Log.e(LOGTAG, dt.toString());
30752be4785a258687055515117775d5bcb8bec1c12John Reck                    }
30852be4785a258687055515117775d5bcb8bec1c12John Reck                    throw new IllegalStateException(
30952be4785a258687055515117775d5bcb8bec1c12John Reck                            "Error saving state, duplicate tab ids!");
31052be4785a258687055515117775d5bcb8bec1c12John Reck                }
31152be4785a258687055515117775d5bcb8bec1c12John Reck                outState.putBundle(key, tabState);
3123ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb            } else {
3133ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb                ids[i++] = -1;
31452be4785a258687055515117775d5bcb8bec1c12John Reck                // Since we won't be restoring the thumbnail, delete it
31552be4785a258687055515117775d5bcb8bec1c12John Reck                tab.deleteThumbnail();
3160c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            }
3170c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
31824f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck        if (!outState.isEmpty()) {
31924f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck            outState.putLongArray(POSITIONS, ids);
32024f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck            Tab current = getCurrentTab();
32124f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck            long cid = -1;
32224f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck            if (current != null) {
32324f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck                cid = current.getId();
32424f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck            }
32524f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck            outState.putLong(CURRENT, cid);
326dbf3981ccbacb11a99c262fc5ebbece62b207a2dMichael Kolb        }
3270c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
3280c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
3290c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
3307d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott     * Check if the state can be restored.  If the state can be restored, the
331c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * current tab id is returned.  This can be passed to restoreState below
3327d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott     * in order to restore the correct tab.  Otherwise, -1 is returned and the
3337d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott     * state cannot be restored.
3347d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott     */
335c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    long canRestoreState(Bundle inState, boolean restoreIncognitoTabs) {
336c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        final long[] ids = (inState == null) ? null : inState.getLongArray(POSITIONS);
337c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        if (ids == null) {
3387d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott            return -1;
3397d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott        }
340c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        final long oldcurrent = inState.getLong(CURRENT);
341c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        long current = -1;
3423ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb        if (restoreIncognitoTabs || (hasState(oldcurrent, inState) && !isIncognito(oldcurrent, inState))) {
3431cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck            current = oldcurrent;
3447d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott        } else {
345c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            // pick first non incognito tab
346c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            for (long id : ids) {
3473ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb                if (hasState(id, inState) && !isIncognito(id, inState)) {
348c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                    current = id;
3497d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                    break;
3507d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                }
3517d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott            }
3527d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott        }
353c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        return current;
3547d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott    }
3557d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott
3563ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb    private boolean hasState(long id, Bundle state) {
3573ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb        if (id == -1) return false;
3583ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb        Bundle tab = state.getBundle(Long.toString(id));
3593ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb        return ((tab != null) && !tab.isEmpty());
3603ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb    }
3613ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb
3623ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb    private boolean isIncognito(long id, Bundle state) {
3633ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb        Bundle tabstate = state.getBundle(Long.toString(id));
3643ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb        if ((tabstate != null) && !tabstate.isEmpty()) {
3653ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb            return tabstate.getBoolean(Tab.INCOGNITO);
3663ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb        }
3673ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb        return false;
3683ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb    }
3693ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb
3707d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott    /**
3710c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * Restore the state of all the tabs.
372c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb     * @param currentId The tab id to restore.
3730c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @param inState The saved state of all the tabs.
3741bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb     * @param restoreIncognitoTabs Restoring private browsing tabs
3751bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb     * @param restoreAll All webviews get restored, not just the current tab
3761bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb     *        (this does not override handling of incognito tabs)
3770c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
378c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    void restoreState(Bundle inState, long currentId,
3797d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott            boolean restoreIncognitoTabs, boolean restoreAll) {
380c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        if (currentId == -1) {
3817d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott            return;
3827d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott        }
383c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        long[] ids = inState.getLongArray(POSITIONS);
384c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        long maxId = -Long.MAX_VALUE;
385c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        HashMap<Long, Tab> tabMap = new HashMap<Long, Tab>();
386c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        for (long id : ids) {
387c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            if (id > maxId) {
388c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                maxId = id;
389c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            }
390c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            final String idkey = Long.toString(id);
391c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            Bundle state = inState.getBundle(idkey);
392d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck            if (state == null || state.isEmpty()) {
393d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck                // Skip tab
394d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck                continue;
395d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck            } else if (!restoreIncognitoTabs
396c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                    && state.getBoolean(Tab.INCOGNITO)) {
397c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                // ignore tab
398c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            } else if (id == currentId || restoreAll) {
3991cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                Tab t = createNewTab(state, false);
40079e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath                if (t == null) {
40179e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath                    // We could "break" at this point, but we want
40279e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath                    // sNextId to be set correctly.
40379e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath                    continue;
40479e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath                }
405c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                tabMap.put(id, t);
4067d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                // Me must set the current tab before restoring the state
4077d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                // so that all the client classes are set.
408c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                if (id == currentId) {
4097d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                    setCurrentTab(t);
4107d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                }
4117d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott            } else {
4127d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                // Create a new tab and don't restore the state yet, add it
4137d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                // to the tab list
4141cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck                Tab t = new Tab(mController, state);
415c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                tabMap.put(id, t);
4167d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                mTabs.add(t);
4177d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                // added the tab to the front as they are not current
4187d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                mTabQueue.add(0, t);
4190c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            }
420c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        }
42179e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath
42279e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath        // make sure that there is no id overlap between the restored
42379e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath        // and new tabs
42479e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath        sNextId = maxId + 1;
42579e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath
426d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        if (mCurrentTab == -1) {
427d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck            if (getTabCount() > 0) {
428d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck                setCurrentTab(getTab(0));
429d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck            }
430d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck        }
431c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        // restore parent/child relationships
432c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        for (long id : ids) {
433c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            final Tab tab = tabMap.get(id);
434c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            final Bundle b = inState.getBundle(Long.toString(id));
435c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            if ((b != null) && (tab != null)) {
436c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                final long parentId = b.getLong(Tab.PARENTTAB, -1);
437c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                if (parentId != -1) {
438c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                    final Tab parent = tabMap.get(parentId);
4397d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott                    if (parent != null) {
440c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                        parent.addChildTab(tab);
4410c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project                    }
4420c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project                }
4430c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            }
4440c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
4450c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
4460c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
4470c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
448f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba     * Free the memory in this order, 1) free the background tabs; 2) free the
4490c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * WebView cache;
4500c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
4510c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    void freeMemory() {
45292c18a52ca7a79c114028b5ba22c3dfe443bd1a4Grace Kloba        if (getTabCount() == 0) return;
45392c18a52ca7a79c114028b5ba22c3dfe443bd1a4Grace Kloba
454f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        // free the least frequently used background tabs
455f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        Vector<Tab> tabs = getHalfLeastUsedTabs(getCurrentTab());
456f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        if (tabs.size() > 0) {
457f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba            Log.w(LOGTAG, "Free " + tabs.size() + " tabs in the browser");
458f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba            for (Tab t : tabs) {
459f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba                // store the WebView's state.
460f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba                t.saveState();
461f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba                // destroy the tab
462f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba                t.destroy();
463f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba            }
4640c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            return;
4650c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
4660c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
4674433d0333f18ea1e5c5c531db48908665c6f8446Derek Sollenberger        // free the WebView's unused memory (this includes the cache)
4684433d0333f18ea1e5c5c531db48908665c6f8446Derek Sollenberger        Log.w(LOGTAG, "Free WebView's unused memory and cache");
4690c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        WebView view = getCurrentWebView();
4700c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (view != null) {
4714433d0333f18ea1e5c5c531db48908665c6f8446Derek Sollenberger            view.freeMemory();
4720c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
4730c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
4740c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
475f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba    private Vector<Tab> getHalfLeastUsedTabs(Tab current) {
476f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        Vector<Tab> tabsToGo = new Vector<Tab>();
477f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba
4782a67de4059775466071da52c07b18627c51c677cPatrick Scott        // Don't do anything if we only have 1 tab or if the current tab is
4792a67de4059775466071da52c07b18627c51c677cPatrick Scott        // null.
4802a67de4059775466071da52c07b18627c51c677cPatrick Scott        if (getTabCount() == 1 || current == null) {
481f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba            return tabsToGo;
4820c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
4830c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
484f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        if (mTabQueue.size() == 0) {
485f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba            return tabsToGo;
4860c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
487f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba
488f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        // Rip through the queue starting at the beginning and tear down half of
489f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        // available tabs which are not the current tab or the parent of the
490f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        // current tab.
491f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        int openTabCount = 0;
492f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        for (Tab t : mTabQueue) {
493f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba            if (t != null && t.getWebView() != null) {
494f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba                openTabCount++;
495c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                if (t != current && t != current.getParent()) {
496f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba                    tabsToGo.add(t);
497f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba                }
498f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba            }
4990c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
5000c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
501f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        openTabCount /= 2;
502f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        if (tabsToGo.size() > openTabCount) {
503f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba            tabsToGo.setSize(openTabCount);
504f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        }
505f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba
506f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba        return tabsToGo;
5070c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
5080c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
509ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb    Tab getLeastUsedTab(Tab current) {
510ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        if (getTabCount() == 1 || current == null) {
511ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb            return null;
512ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        }
513ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        if (mTabQueue.size() == 0) {
514ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb            return null;
515ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        }
516ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        // find a tab which is not the current tab or the parent of the
517ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        // current tab
518ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        for (Tab t : mTabQueue) {
519ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb            if (t != null && t.getWebView() != null) {
520ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb                if (t != current && t != current.getParent()) {
521ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb                    return t;
522ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb                }
523ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb            }
524ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        }
525ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb        return null;
526ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb    }
527ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb
5280c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
5290c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * Show the tab that contains the given WebView.
5300c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @param view The WebView used to find the tab.
5310c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
5320c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    Tab getTabFromView(WebView view) {
533c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        for (Tab t : mTabs) {
53422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (t.getSubWebView() == view || t.getWebView() == view) {
5350c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project                return t;
5360c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            }
5370c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
5380c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        return null;
5390c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
5400c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
5410c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
542f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     * Return the tab with the matching application id.
543f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     * @param id The application identifier.
544f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     */
545c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb    Tab getTabFromAppId(String id) {
546f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        if (id == null) {
547f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project            return null;
548f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        }
549c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        for (Tab t : mTabs) {
55022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (id.equals(t.getAppId())) {
551f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project                return t;
552f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project            }
553f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        }
554f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        return null;
555f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    }
556f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project
55722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /**
55822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     * Stop loading in all opened WebView including subWindows.
55922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba     */
5605d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba    void stopAllLoading() {
561c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        for (Tab t : mTabs) {
56222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            final WebView webview = t.getWebView();
5635d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba            if (webview != null) {
5645d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba                webview.stopLoading();
5655d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba            }
56622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            final WebView subview = t.getSubWebView();
56722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            if (subview != null) {
5689727af8453990808bd0a104bd9ceb8671e335ab5Mattias Nilsson                subview.stopLoading();
56922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            }
5705d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba        }
5715d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba    }
5725d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba
573db22ec4ee014900988062d910bc810172a07df56John Reck    // This method checks if a tab matches the given url.
574cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott    private boolean tabMatchesUrl(Tab t, String url) {
575db22ec4ee014900988062d910bc810172a07df56John Reck        return url.equals(t.getUrl()) || url.equals(t.getOriginalUrl());
576cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott    }
577cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott
578cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott    /**
579db22ec4ee014900988062d910bc810172a07df56John Reck     * Return the tab that matches the given url.
580cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott     * @param url The url to search for.
581cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott     */
582db22ec4ee014900988062d910bc810172a07df56John Reck    Tab findTabWithUrl(String url) {
583cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott        if (url == null) {
584cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott            return null;
585cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott        }
586cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott        // Check the current tab first.
587db22ec4ee014900988062d910bc810172a07df56John Reck        Tab currentTab = getCurrentTab();
588db22ec4ee014900988062d910bc810172a07df56John Reck        if (currentTab != null && tabMatchesUrl(currentTab, url)) {
589db22ec4ee014900988062d910bc810172a07df56John Reck            return currentTab;
590cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott        }
591cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott        // Now check all the rest.
592c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        for (Tab tab : mTabs) {
593c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            if (tabMatchesUrl(tab, url)) {
594db22ec4ee014900988062d910bc810172a07df56John Reck                return tab;
595cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott            }
596cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott        }
597cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott        return null;
598cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott    }
599cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott
600f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    /**
60130c714c853a4239e72ab1e238ce2a92472d06ab0John Reck     * Recreate the main WebView of the given tab.
602f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     */
60330c714c853a4239e72ab1e238ce2a92472d06ab0John Reck    void recreateWebView(Tab t) {
60422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        final WebView w = t.getWebView();
605f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        if (w != null) {
60622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            t.destroy();
607f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        }
608f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        // Create a new WebView. If this tab is the current tab, we need to put
609f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        // back all the clients so force it to be the current tab.
61091911a26058418e622950cffc616f99ada49df1dMichael Kolb        t.setWebView(createNewWebView(), false);
611f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        if (getCurrentTab() == t) {
612f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project            setCurrentTab(t, true);
613f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        }
614f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    }
615f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project
616f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    /**
617f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     * Creates a new WebView and registers it with the global settings.
618f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     */
619f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    private WebView createNewWebView() {
620f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter        return createNewWebView(false);
621f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter    }
622f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter
623f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter    /**
624f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter     * Creates a new WebView and registers it with the global settings.
625f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter     * @param privateBrowsing When true, enables private browsing in the new
626f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter     *        WebView.
627f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter     */
628f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter    private WebView createNewWebView(boolean privateBrowsing) {
6298233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return mController.getWebViewFactory().createWebView(privateBrowsing);
630f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    }
631f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project
632f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    /**
6330c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * Put the current tab in the background and set newTab as the current tab.
6340c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     * @param newTab The new tab. If newTab is null, the current tab is not
6350c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     *               set.
6360c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
6370c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    boolean setCurrentTab(Tab newTab) {
638f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        return setCurrentTab(newTab, false);
639f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    }
640f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project
641f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    /**
642f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     * If force is true, this method skips the check for newTab == current.
643f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project     */
644f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project    private boolean setCurrentTab(Tab newTab, boolean force) {
6450c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        Tab current = getTab(mCurrentTab);
646f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project        if (current == newTab && !force) {
6470c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            return true;
6480c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
6490c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (current != null) {
65022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            current.putInBackground();
65122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mCurrentTab = -1;
6520c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
6530c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (newTab == null) {
6540c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            return false;
6550c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
6560c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
6570c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        // Move the newTab to the end of the queue
6580c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        int index = mTabQueue.indexOf(newTab);
6590c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (index != -1) {
6600c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            mTabQueue.remove(index);
6610c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
6620c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        mTabQueue.add(newTab);
6630c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
6640c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        // Display the new current tab
6650c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        mCurrentTab = mTabs.indexOf(newTab);
66622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        WebView mainView = newTab.getWebView();
667f9e1705d4012706664a2bdf63a50b8a784b833ddJonathan Dixon        boolean needRestore = mainView == null;
6680c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (needRestore) {
6690c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            // Same work as in createNewTab() except don't do new Tab()
6702bc69918d97a767a02132090e58718077381ba1aSteve Block            mainView = createNewWebView();
6712bc69918d97a767a02132090e58718077381ba1aSteve Block            newTab.setWebView(mainView);
6720c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
67322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        newTab.putInForeground();
6740c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        return true;
6750c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
676fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolb
677e6db7dcd06e8ea0dee6a476c03640dd61d9d54aePaul Miller    // Used by Tab.onJsAlert() and friends
678e6db7dcd06e8ea0dee6a476c03640dd61d9d54aePaul Miller    void setActiveTab(Tab tab) {
679e6db7dcd06e8ea0dee6a476c03640dd61d9d54aePaul Miller        // Calls TabControl.setCurrentTab()
680e6db7dcd06e8ea0dee6a476c03640dd61d9d54aePaul Miller        mController.setActiveTab(tab);
681e6db7dcd06e8ea0dee6a476c03640dd61d9d54aePaul Miller    }
682e6db7dcd06e8ea0dee6a476c03640dd61d9d54aePaul Miller
6838ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck    public void setOnThumbnailUpdatedListener(OnThumbnailUpdatedListener listener) {
6848ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        mOnThumbnailUpdatedListener = listener;
6858ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        for (Tab t : mTabs) {
6868ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            WebView web = t.getWebView();
6878ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            if (web != null) {
6888ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck                web.setPictureListener(listener != null ? t : null);
6898ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck            }
6908ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        }
6918ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck    }
6928ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck
6938ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck    public OnThumbnailUpdatedListener getOnThumbnailUpdatedListener() {
6948ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck        return mOnThumbnailUpdatedListener;
6958ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck    }
6968ee633fd62f94cd66c85c2904232d7c9e204cc9cJohn Reck
6970c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project}
698