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 219d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck SnapshotTab createSnapshotTab(long snapshotId) { 220d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck SnapshotTab t = new SnapshotTab(mController, snapshotId); 221d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck mTabs.add(t); 222d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck return t; 223d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck } 224d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck 225f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project /** 226fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins * Remove the parent child relationships from all tabs. 227fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins */ 228fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins void removeParentChildRelationShips() { 229fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins for (Tab tab : mTabs) { 230fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins tab.removeFromTree(); 231fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins } 232fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins } 233fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins 234fde9746ac3055848e110c35f19ec5893c621f766Leon Scroggins /** 2350c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Remove the tab from the list. If the tab is the current tab shown, the 2360c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * last created tab will be shown. 2370c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * @param t The tab to be removed. 2380c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */ 2390c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project boolean removeTab(Tab t) { 2400c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project if (t == null) { 2410c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return false; 2420c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 24322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba 244d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott // Grab the current tab before modifying the list. 245d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott Tab current = getCurrentTab(); 246d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott 247d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott // Remove t from our list of tabs. 248d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott mTabs.remove(t); 249d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott 250d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott // Put the tab in the background only if it is the current one. 251d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott if (current == t) { 25222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba t.putInBackground(); 25322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba mCurrentTab = -1; 254d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott } else { 255d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott // If a tab that is earlier in the list gets removed, the current 256d944d4d63c9e93b51fae38fc86f0d87fff0e3a21Patrick Scott // index no longer points to the correct tab. 257c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb mCurrentTab = getTabPosition(current); 2580c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 2590c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 26022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba // destroy the tab 26122ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba t.destroy(); 2620c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // clear it's references to parent and children 2630c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project t.removeFromTree(); 2640c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 2650c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // Remove it from the queue of viewed tabs. 2660c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project mTabQueue.remove(t); 2670c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return true; 2680c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 2690c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 2700c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project /** 2710c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Destroy all the tabs and subwindows 2720c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */ 2730c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project void destroy() { 2740c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project for (Tab t : mTabs) { 27522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba t.destroy(); 2760c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 2770c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project mTabs.clear(); 2780c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project mTabQueue.clear(); 2790c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 2800c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 2810c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project /** 2820c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Returns the number of tabs created. 2830c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * @return The number of tabs created. 2840c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */ 2850c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project int getTabCount() { 2860c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return mTabs.size(); 2870c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 2880c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 2890c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project /** 290c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb * save the tab state: 291c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb * current position 292c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb * position sorted array of tab ids 293c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb * for each tab id, save the tab state 294c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb * @param outState 295aed9c54d8e67bb683a5a415b3775525a3ac00508John Reck * @param saveImages 2960c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */ 2971cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck void saveState(Bundle outState) { 2980c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project final int numTabs = getTabCount(); 29924f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck if (numTabs == 0) { 30024f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck return; 30124f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck } 302c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb long[] ids = new long[numTabs]; 303c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb int i = 0; 304c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb for (Tab tab : mTabs) { 3051cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck Bundle tabState = tab.saveState(); 3061cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck if (tabState != null) { 3073ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb ids[i++] = tab.getId(); 30852be4785a258687055515117775d5bcb8bec1c12John Reck String key = Long.toString(tab.getId()); 30952be4785a258687055515117775d5bcb8bec1c12John Reck if (outState.containsKey(key)) { 31052be4785a258687055515117775d5bcb8bec1c12John Reck // Dump the tab state for debugging purposes 31152be4785a258687055515117775d5bcb8bec1c12John Reck for (Tab dt : mTabs) { 31252be4785a258687055515117775d5bcb8bec1c12John Reck Log.e(LOGTAG, dt.toString()); 31352be4785a258687055515117775d5bcb8bec1c12John Reck } 31452be4785a258687055515117775d5bcb8bec1c12John Reck throw new IllegalStateException( 31552be4785a258687055515117775d5bcb8bec1c12John Reck "Error saving state, duplicate tab ids!"); 31652be4785a258687055515117775d5bcb8bec1c12John Reck } 31752be4785a258687055515117775d5bcb8bec1c12John Reck outState.putBundle(key, tabState); 3183ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb } else { 3193ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb ids[i++] = -1; 32052be4785a258687055515117775d5bcb8bec1c12John Reck // Since we won't be restoring the thumbnail, delete it 32152be4785a258687055515117775d5bcb8bec1c12John Reck tab.deleteThumbnail(); 3220c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 3230c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 32424f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck if (!outState.isEmpty()) { 32524f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck outState.putLongArray(POSITIONS, ids); 32624f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck Tab current = getCurrentTab(); 32724f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck long cid = -1; 32824f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck if (current != null) { 32924f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck cid = current.getId(); 33024f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck } 33124f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck outState.putLong(CURRENT, cid); 332dbf3981ccbacb11a99c262fc5ebbece62b207a2dMichael Kolb } 3330c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 3340c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 3350c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project /** 3367d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott * Check if the state can be restored. If the state can be restored, the 337c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb * current tab id is returned. This can be passed to restoreState below 3387d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott * in order to restore the correct tab. Otherwise, -1 is returned and the 3397d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott * state cannot be restored. 3407d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott */ 341c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb long canRestoreState(Bundle inState, boolean restoreIncognitoTabs) { 342c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb final long[] ids = (inState == null) ? null : inState.getLongArray(POSITIONS); 343c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb if (ids == null) { 3447d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott return -1; 3457d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 346c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb final long oldcurrent = inState.getLong(CURRENT); 347c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb long current = -1; 3483ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb if (restoreIncognitoTabs || (hasState(oldcurrent, inState) && !isIncognito(oldcurrent, inState))) { 3491cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck current = oldcurrent; 3507d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } else { 351c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb // pick first non incognito tab 352c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb for (long id : ids) { 3533ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb if (hasState(id, inState) && !isIncognito(id, inState)) { 354c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb current = id; 3557d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott break; 3567d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 3577d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 3587d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 359c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb return current; 3607d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 3617d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott 3623ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb private boolean hasState(long id, Bundle state) { 3633ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb if (id == -1) return false; 3643ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb Bundle tab = state.getBundle(Long.toString(id)); 3653ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb return ((tab != null) && !tab.isEmpty()); 3663ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb } 3673ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb 3683ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb private boolean isIncognito(long id, Bundle state) { 3693ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb Bundle tabstate = state.getBundle(Long.toString(id)); 3703ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb if ((tabstate != null) && !tabstate.isEmpty()) { 3713ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb return tabstate.getBoolean(Tab.INCOGNITO); 3723ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb } 3733ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb return false; 3743ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb } 3753ae7f74a64fd1dc101910f1b14f315b34d1f1274Michael Kolb 3767d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott /** 3770c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Restore the state of all the tabs. 378c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb * @param currentId The tab id to restore. 3790c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * @param inState The saved state of all the tabs. 3801bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb * @param restoreIncognitoTabs Restoring private browsing tabs 3811bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb * @param restoreAll All webviews get restored, not just the current tab 3821bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb * (this does not override handling of incognito tabs) 3830c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */ 384c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb void restoreState(Bundle inState, long currentId, 3857d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott boolean restoreIncognitoTabs, boolean restoreAll) { 386c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb if (currentId == -1) { 3877d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott return; 3887d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 389c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb long[] ids = inState.getLongArray(POSITIONS); 390c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb long maxId = -Long.MAX_VALUE; 391c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb HashMap<Long, Tab> tabMap = new HashMap<Long, Tab>(); 392c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb for (long id : ids) { 393c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb if (id > maxId) { 394c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb maxId = id; 395c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb } 396c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb final String idkey = Long.toString(id); 397c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb Bundle state = inState.getBundle(idkey); 398d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck if (state == null || state.isEmpty()) { 399d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck // Skip tab 400d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck continue; 401d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck } else if (!restoreIncognitoTabs 402c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb && state.getBoolean(Tab.INCOGNITO)) { 403c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb // ignore tab 404c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb } else if (id == currentId || restoreAll) { 4051cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck Tab t = createNewTab(state, false); 40679e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath if (t == null) { 40779e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath // We could "break" at this point, but we want 40879e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath // sNextId to be set correctly. 40979e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath continue; 41079e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath } 411c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb tabMap.put(id, t); 4127d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // Me must set the current tab before restoring the state 4137d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // so that all the client classes are set. 414c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb if (id == currentId) { 4157d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott setCurrentTab(t); 4167d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 4177d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } else { 4187d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // Create a new tab and don't restore the state yet, add it 4197d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // to the tab list 4201cf4b79a0020bc18c83ca8bde0e318ecd5252bc2John Reck Tab t = new Tab(mController, state); 421c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb tabMap.put(id, t); 4227d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott mTabs.add(t); 4237d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // added the tab to the front as they are not current 4247d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott mTabQueue.add(0, t); 4250c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 426c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb } 42779e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath 42879e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath // make sure that there is no id overlap between the restored 42979e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath // and new tabs 43079e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath sNextId = maxId + 1; 43179e5d8d14609a2d5bc5cac8daf7cad1cc9a98d4eNarayan Kamath 432d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck if (mCurrentTab == -1) { 433d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck if (getTabCount() > 0) { 434d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck setCurrentTab(getTab(0)); 435d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck } 436d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck } 437c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb // restore parent/child relationships 438c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb for (long id : ids) { 439c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb final Tab tab = tabMap.get(id); 440c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb final Bundle b = inState.getBundle(Long.toString(id)); 441c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb if ((b != null) && (tab != null)) { 442c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb final long parentId = b.getLong(Tab.PARENTTAB, -1); 443c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb if (parentId != -1) { 444c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb final Tab parent = tabMap.get(parentId); 4457d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott if (parent != null) { 446c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb parent.addChildTab(tab); 4470c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4480c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4490c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4500c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4510c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4520c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 4530c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project /** 454f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba * Free the memory in this order, 1) free the background tabs; 2) free the 4550c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * WebView cache; 4560c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */ 4570c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project void freeMemory() { 45892c18a52ca7a79c114028b5ba22c3dfe443bd1a4Grace Kloba if (getTabCount() == 0) return; 45992c18a52ca7a79c114028b5ba22c3dfe443bd1a4Grace Kloba 460f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba // free the least frequently used background tabs 461f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba Vector<Tab> tabs = getHalfLeastUsedTabs(getCurrentTab()); 462f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba if (tabs.size() > 0) { 463f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba Log.w(LOGTAG, "Free " + tabs.size() + " tabs in the browser"); 464f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba for (Tab t : tabs) { 465f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba // store the WebView's state. 466f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba t.saveState(); 467f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba // destroy the tab 468f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba t.destroy(); 469f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba } 4700c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return; 4710c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4720c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 4734433d0333f18ea1e5c5c531db48908665c6f8446Derek Sollenberger // free the WebView's unused memory (this includes the cache) 4744433d0333f18ea1e5c5c531db48908665c6f8446Derek Sollenberger Log.w(LOGTAG, "Free WebView's unused memory and cache"); 4750c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project WebView view = getCurrentWebView(); 4760c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project if (view != null) { 4774433d0333f18ea1e5c5c531db48908665c6f8446Derek Sollenberger view.freeMemory(); 4780c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4790c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4800c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 481f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba private Vector<Tab> getHalfLeastUsedTabs(Tab current) { 482f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba Vector<Tab> tabsToGo = new Vector<Tab>(); 483f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba 4842a67de4059775466071da52c07b18627c51c677cPatrick Scott // Don't do anything if we only have 1 tab or if the current tab is 4852a67de4059775466071da52c07b18627c51c677cPatrick Scott // null. 4862a67de4059775466071da52c07b18627c51c677cPatrick Scott if (getTabCount() == 1 || current == null) { 487f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba return tabsToGo; 4880c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 4890c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 490f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba if (mTabQueue.size() == 0) { 491f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba return tabsToGo; 4920c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 493f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba 494f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba // Rip through the queue starting at the beginning and tear down half of 495f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba // available tabs which are not the current tab or the parent of the 496f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba // current tab. 497f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba int openTabCount = 0; 498f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba for (Tab t : mTabQueue) { 499f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba if (t != null && t.getWebView() != null) { 500f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba openTabCount++; 501c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb if (t != current && t != current.getParent()) { 502f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba tabsToGo.add(t); 503f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba } 504f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba } 5050c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 5060c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 507f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba openTabCount /= 2; 508f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba if (tabsToGo.size() > openTabCount) { 509f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba tabsToGo.setSize(openTabCount); 510f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba } 511f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba 512f56f68d291ae26ff25db4dc62122692c1dd1f4f9Grace Kloba return tabsToGo; 5130c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 5140c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 515ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb Tab getLeastUsedTab(Tab current) { 516ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb if (getTabCount() == 1 || current == null) { 517ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb return null; 518ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb } 519ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb if (mTabQueue.size() == 0) { 520ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb return null; 521ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb } 522ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb // find a tab which is not the current tab or the parent of the 523ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb // current tab 524ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb for (Tab t : mTabQueue) { 525ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb if (t != null && t.getWebView() != null) { 526ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb if (t != current && t != current.getParent()) { 527ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb return t; 528ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb } 529ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb } 530ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb } 531ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb return null; 532ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb } 533ff6a748ae78165cc2298f5120a4374b4ed6f836bMichael Kolb 5340c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project /** 5350c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Show the tab that contains the given WebView. 5360c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * @param view The WebView used to find the tab. 5370c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */ 5380c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project Tab getTabFromView(WebView view) { 539c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb for (Tab t : mTabs) { 54022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba if (t.getSubWebView() == view || t.getWebView() == view) { 5410c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return t; 5420c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 5430c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 5440c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return null; 5450c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 5460c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 5470c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project /** 548f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project * Return the tab with the matching application id. 549f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project * @param id The application identifier. 550f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project */ 551c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb Tab getTabFromAppId(String id) { 552f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project if (id == null) { 553f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project return null; 554f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project } 555c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb for (Tab t : mTabs) { 55622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba if (id.equals(t.getAppId())) { 557f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project return t; 558f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project } 559f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project } 560f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project return null; 561f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project } 562f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project 56322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba /** 56422ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba * Stop loading in all opened WebView including subWindows. 56522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba */ 5665d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba void stopAllLoading() { 567c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb for (Tab t : mTabs) { 56822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba final WebView webview = t.getWebView(); 5695d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba if (webview != null) { 5705d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba webview.stopLoading(); 5715d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba } 57222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba final WebView subview = t.getSubWebView(); 57322ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba if (subview != null) { 5749727af8453990808bd0a104bd9ceb8671e335ab5Mattias Nilsson subview.stopLoading(); 57522ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba } 5765d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba } 5775d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba } 5785d0e02e646e46b14289168f75c2a8f6ed43cac54Grace Kloba 579db22ec4ee014900988062d910bc810172a07df56John Reck // This method checks if a tab matches the given url. 580cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott private boolean tabMatchesUrl(Tab t, String url) { 581db22ec4ee014900988062d910bc810172a07df56John Reck return url.equals(t.getUrl()) || url.equals(t.getOriginalUrl()); 582cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott } 583cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott 584cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott /** 585db22ec4ee014900988062d910bc810172a07df56John Reck * Return the tab that matches the given url. 586cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott * @param url The url to search for. 587cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott */ 588db22ec4ee014900988062d910bc810172a07df56John Reck Tab findTabWithUrl(String url) { 589cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott if (url == null) { 590cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott return null; 591cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott } 592cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott // Check the current tab first. 593db22ec4ee014900988062d910bc810172a07df56John Reck Tab currentTab = getCurrentTab(); 594db22ec4ee014900988062d910bc810172a07df56John Reck if (currentTab != null && tabMatchesUrl(currentTab, url)) { 595db22ec4ee014900988062d910bc810172a07df56John Reck return currentTab; 596cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott } 597cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott // Now check all the rest. 598c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb for (Tab tab : mTabs) { 599c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb if (tabMatchesUrl(tab, url)) { 600db22ec4ee014900988062d910bc810172a07df56John Reck return tab; 601cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott } 602cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott } 603cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott return null; 604cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott } 605cd11589fc3930906d4b9b7dd18aa52a9f1eb0c8aPatrick Scott 606f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project /** 60730c714c853a4239e72ab1e238ce2a92472d06ab0John Reck * Recreate the main WebView of the given tab. 608f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project */ 60930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck void recreateWebView(Tab t) { 61022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba final WebView w = t.getWebView(); 611f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project if (w != null) { 61222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba t.destroy(); 613f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project } 614f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project // Create a new WebView. If this tab is the current tab, we need to put 615f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project // back all the clients so force it to be the current tab. 61691911a26058418e622950cffc616f99ada49df1dMichael Kolb t.setWebView(createNewWebView(), false); 617f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project if (getCurrentTab() == t) { 618f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project setCurrentTab(t, true); 619f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project } 620f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project } 621f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project 622f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project /** 623f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project * Creates a new WebView and registers it with the global settings. 624f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project */ 625f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project private WebView createNewWebView() { 626f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter return createNewWebView(false); 627f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter } 628f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter 629f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter /** 630f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter * Creates a new WebView and registers it with the global settings. 631f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter * @param privateBrowsing When true, enables private browsing in the new 632f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter * WebView. 633f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter */ 634f0f03954b3092296c58dcb040e2dabd1696dd5c4Elliott Slaughter private WebView createNewWebView(boolean privateBrowsing) { 6358233facddcc51865d612a919d450db6954aa48e3Michael Kolb return mController.getWebViewFactory().createWebView(privateBrowsing); 636f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project } 637f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project 638f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project /** 6390c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Put the current tab in the background and set newTab as the current tab. 6400c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * @param newTab The new tab. If newTab is null, the current tab is not 6410c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * set. 6420c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */ 6430c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project boolean setCurrentTab(Tab newTab) { 644f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project return setCurrentTab(newTab, false); 645f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project } 646f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project 647f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project /** 648f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project * If force is true, this method skips the check for newTab == current. 649f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project */ 650f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project private boolean setCurrentTab(Tab newTab, boolean force) { 6510c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project Tab current = getTab(mCurrentTab); 652f59ec877363eaf43118677f249008eddc7a9ce11The Android Open Source Project if (current == newTab && !force) { 6530c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return true; 6540c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 6550c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project if (current != null) { 65622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba current.putInBackground(); 65722ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba mCurrentTab = -1; 6580c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 6590c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project if (newTab == null) { 6600c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return false; 6610c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 6620c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 6630c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // Move the newTab to the end of the queue 6640c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project int index = mTabQueue.indexOf(newTab); 6650c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project if (index != -1) { 6660c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project mTabQueue.remove(index); 6670c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 6680c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project mTabQueue.add(newTab); 6690c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project 6700c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // Display the new current tab 6710c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project mCurrentTab = mTabs.indexOf(newTab); 67222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba WebView mainView = newTab.getWebView(); 673d8c7452a7d8975a2d60414c5a33842b4a743e631John Reck boolean needRestore = !newTab.isSnapshot() && (mainView == null); 6740c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project if (needRestore) { 6750c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project // Same work as in createNewTab() except don't do new Tab() 6762bc69918d97a767a02132090e58718077381ba1aSteve Block mainView = createNewWebView(); 6772bc69918d97a767a02132090e58718077381ba1aSteve Block newTab.setWebView(mainView); 6780c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 67922ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba newTab.putInForeground(); 6800c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project return true; 6810c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project } 682fe25199a6f975c67d28afcc1de56b0f987b66cd8Michael Kolb 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