blob: 050ad9493b2235b2a3a20942be56a54be7709114 [file] [log] [blame]
The Android Open Source Project0c908882009-03-03 19:32:16 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.browser;
18
Michael Kolb8233fac2010-10-26 16:08:53 -070019import com.android.browser.IntentHandler.UrlData;
20
The Android Open Source Project0c908882009-03-03 19:32:16 -080021import android.os.Bundle;
The Android Open Source Project0c908882009-03-03 19:32:16 -080022import android.util.Log;
The Android Open Source Project0c908882009-03-03 19:32:16 -080023import android.webkit.WebBackForwardList;
The Android Open Source Project0c908882009-03-03 19:32:16 -080024import android.webkit.WebView;
The Android Open Source Project0c908882009-03-03 19:32:16 -080025
26import java.io.File;
27import java.util.ArrayList;
Elliott Slaughter3d6df162010-08-25 13:17:44 -070028import java.util.HashMap;
Michael Kolb1bf23132010-11-19 12:55:12 -080029import java.util.List;
The Android Open Source Project0c908882009-03-03 19:32:16 -080030import java.util.Vector;
31
32class TabControl {
33 // Log Tag
34 private static final String LOGTAG = "TabControl";
35 // Maximum number of tabs.
Michael Kolb6e4653e2010-09-27 16:22:38 -070036 private int mMaxTabs;
The Android Open Source Project0c908882009-03-03 19:32:16 -080037 // Private array of WebViews that are used as tabs.
Michael Kolb6e4653e2010-09-27 16:22:38 -070038 private ArrayList<Tab> mTabs;
The Android Open Source Project0c908882009-03-03 19:32:16 -080039 // Queue of most recently viewed tabs.
Michael Kolb6e4653e2010-09-27 16:22:38 -070040 private ArrayList<Tab> mTabQueue;
The Android Open Source Project0c908882009-03-03 19:32:16 -080041 // Current position in mTabs.
42 private int mCurrentTab = -1;
Michael Kolb8233fac2010-10-26 16:08:53 -070043 // the main browser controller
44 private final Controller mController;
45
The Android Open Source Project0c908882009-03-03 19:32:16 -080046 private final File mThumbnailDir;
47
48 /**
Michael Kolb8233fac2010-10-26 16:08:53 -070049 * Construct a new TabControl object
The Android Open Source Project0c908882009-03-03 19:32:16 -080050 */
Michael Kolb8233fac2010-10-26 16:08:53 -070051 TabControl(Controller controller) {
52 mController = controller;
53 mThumbnailDir = mController.getActivity()
54 .getDir("thumbnails", 0);
55 mMaxTabs = mController.getMaxTabs();
Michael Kolb6e4653e2010-09-27 16:22:38 -070056 mTabs = new ArrayList<Tab>(mMaxTabs);
57 mTabQueue = new ArrayList<Tab>(mMaxTabs);
The Android Open Source Project0c908882009-03-03 19:32:16 -080058 }
59
60 File getThumbnailDir() {
61 return mThumbnailDir;
62 }
63
Michael Kolb68775752010-08-19 12:42:01 -070064 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -080065 * Return the current tab's main WebView. This will always return the main
66 * WebView for a given tab and not a subwindow.
67 * @return The current tab's WebView.
68 */
69 WebView getCurrentWebView() {
70 Tab t = getTab(mCurrentTab);
71 if (t == null) {
72 return null;
73 }
Grace Kloba22ac16e2009-10-07 18:00:23 -070074 return t.getWebView();
Ben Murdochbff2d602009-07-01 20:19:05 +010075 }
76
77 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -080078 * Return the current tab's top-level WebView. This can return a subwindow
79 * if one exists.
80 * @return The top-level WebView of the current tab.
81 */
82 WebView getCurrentTopWebView() {
83 Tab t = getTab(mCurrentTab);
84 if (t == null) {
85 return null;
86 }
Grace Kloba22ac16e2009-10-07 18:00:23 -070087 return t.getTopWindow();
The Android Open Source Project0c908882009-03-03 19:32:16 -080088 }
89
90 /**
91 * Return the current tab's subwindow if it exists.
92 * @return The subwindow of the current tab or null if it doesn't exist.
93 */
94 WebView getCurrentSubWindow() {
95 Tab t = getTab(mCurrentTab);
96 if (t == null) {
97 return null;
98 }
Grace Kloba22ac16e2009-10-07 18:00:23 -070099 return t.getSubWebView();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800100 }
101
102 /**
Michael Kolb1bf23132010-11-19 12:55:12 -0800103 * return the list of tabs
104 */
105 List<Tab> getTabs() {
106 return mTabs;
107 }
108
109 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -0800110 * Return the tab at the specified index.
111 * @return The Tab for the specified index or null if the tab does not
112 * exist.
113 */
114 Tab getTab(int index) {
115 if (index >= 0 && index < mTabs.size()) {
116 return mTabs.get(index);
117 }
118 return null;
119 }
120
121 /**
122 * Return the current tab.
123 * @return The current tab.
124 */
125 Tab getCurrentTab() {
126 return getTab(mCurrentTab);
127 }
128
129 /**
130 * Return the current tab index.
131 * @return The current tab index
132 */
133 int getCurrentIndex() {
134 return mCurrentTab;
135 }
Michael Kolbfe251992010-07-08 15:41:55 -0700136
The Android Open Source Project0c908882009-03-03 19:32:16 -0800137 /**
138 * Given a Tab, find it's index
139 * @param Tab to find
140 * @return index of Tab or -1 if not found
141 */
142 int getTabIndex(Tab tab) {
Patrick Scottae641ac2009-04-20 13:51:49 -0400143 if (tab == null) {
144 return -1;
145 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800146 return mTabs.indexOf(tab);
147 }
148
Grace Kloba22ac16e2009-10-07 18:00:23 -0700149 boolean canCreateNewTab() {
Michael Kolb6e4653e2010-09-27 16:22:38 -0700150 return mMaxTabs != mTabs.size();
Grace Kloba22ac16e2009-10-07 18:00:23 -0700151 }
152
The Android Open Source Project0c908882009-03-03 19:32:16 -0800153 /**
Elliott Slaughtere440a882010-08-20 13:54:45 -0700154 * Returns true if there are any incognito tabs open.
155 * @return True when any incognito tabs are open, false otherwise.
156 */
157 boolean hasAnyOpenIncognitoTabs() {
158 for (Tab tab : mTabs) {
Elliott Slaughter3d6df162010-08-25 13:17:44 -0700159 if (tab.getWebView() != null && tab.getWebView().isPrivateBrowsingEnabled()) {
Elliott Slaughtere440a882010-08-20 13:54:45 -0700160 return true;
161 }
162 }
163 return false;
164 }
165
166 /**
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700167 * Create a new tab.
The Android Open Source Project0c908882009-03-03 19:32:16 -0800168 * @return The newly createTab or null if we have reached the maximum
169 * number of open tabs.
170 */
Elliott Slaughterf0f03952010-07-14 18:10:36 -0700171 Tab createNewTab(boolean closeOnExit, String appId, String url,
172 boolean privateBrowsing) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800173 int size = mTabs.size();
174 // Return false if we have maxed out on tabs
Michael Kolb6e4653e2010-09-27 16:22:38 -0700175 if (mMaxTabs == size) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800176 return null;
177 }
Elliott Slaughterf0f03952010-07-14 18:10:36 -0700178 final WebView w = createNewWebView(privateBrowsing);
Steve Block2bc69912009-07-30 14:45:13 +0100179
The Android Open Source Project0c908882009-03-03 19:32:16 -0800180 // Create a new tab and add it to the tab list
Michael Kolb8233fac2010-10-26 16:08:53 -0700181 Tab t = new Tab(mController, w, closeOnExit, appId, url);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800182 mTabs.add(t);
The Android Open Source Project4e5f5872009-03-09 11:52:14 -0700183 // Initially put the tab in the background.
Grace Kloba22ac16e2009-10-07 18:00:23 -0700184 t.putInBackground();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800185 return t;
186 }
187
188 /**
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700189 * Create a new tab with default values for closeOnExit(false),
Elliott Slaughterf0f03952010-07-14 18:10:36 -0700190 * appId(null), url(null), and privateBrowsing(false).
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700191 */
192 Tab createNewTab() {
Elliott Slaughterf0f03952010-07-14 18:10:36 -0700193 return createNewTab(false, null, null, false);
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700194 }
195
196 /**
Leon Scrogginsfde97462010-01-11 13:06:21 -0500197 * Remove the parent child relationships from all tabs.
198 */
199 void removeParentChildRelationShips() {
200 for (Tab tab : mTabs) {
201 tab.removeFromTree();
202 }
203 }
204
205 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -0800206 * Remove the tab from the list. If the tab is the current tab shown, the
207 * last created tab will be shown.
208 * @param t The tab to be removed.
209 */
210 boolean removeTab(Tab t) {
211 if (t == null) {
212 return false;
213 }
Grace Kloba22ac16e2009-10-07 18:00:23 -0700214
Patrick Scottd944d4d2010-01-27 16:39:11 -0500215 // Grab the current tab before modifying the list.
216 Tab current = getCurrentTab();
217
218 // Remove t from our list of tabs.
219 mTabs.remove(t);
220
221 // Put the tab in the background only if it is the current one.
222 if (current == t) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700223 t.putInBackground();
224 mCurrentTab = -1;
Patrick Scottd944d4d2010-01-27 16:39:11 -0500225 } else {
226 // If a tab that is earlier in the list gets removed, the current
227 // index no longer points to the correct tab.
228 mCurrentTab = getTabIndex(current);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800229 }
230
Grace Kloba22ac16e2009-10-07 18:00:23 -0700231 // destroy the tab
232 t.destroy();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800233 // clear it's references to parent and children
234 t.removeFromTree();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800235
236 // The tab indices have shifted, update all the saved state so we point
237 // to the correct index.
238 for (Tab tab : mTabs) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700239 Vector<Tab> children = tab.getChildTabs();
240 if (children != null) {
241 for (Tab child : children) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800242 child.setParentTab(tab);
243 }
244 }
245 }
246
The Android Open Source Project0c908882009-03-03 19:32:16 -0800247 // Remove it from the queue of viewed tabs.
248 mTabQueue.remove(t);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800249 return true;
250 }
251
252 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -0800253 * Destroy all the tabs and subwindows
254 */
255 void destroy() {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800256 for (Tab t : mTabs) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700257 t.destroy();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800258 }
259 mTabs.clear();
260 mTabQueue.clear();
261 }
262
263 /**
264 * Returns the number of tabs created.
265 * @return The number of tabs created.
266 */
267 int getTabCount() {
268 return mTabs.size();
269 }
270
The Android Open Source Project0c908882009-03-03 19:32:16 -0800271
272 /**
273 * Save the state of all the Tabs.
274 * @param outState The Bundle to save the state to.
275 */
276 void saveState(Bundle outState) {
277 final int numTabs = getTabCount();
Grace Kloba22ac16e2009-10-07 18:00:23 -0700278 outState.putInt(Tab.NUMTABS, numTabs);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800279 final int index = getCurrentIndex();
Grace Kloba22ac16e2009-10-07 18:00:23 -0700280 outState.putInt(Tab.CURRTAB, (index >= 0 && index < numTabs) ? index : 0);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800281 for (int i = 0; i < numTabs; i++) {
282 final Tab t = getTab(i);
Grace Kloba22ac16e2009-10-07 18:00:23 -0700283 if (t.saveState()) {
284 outState.putBundle(Tab.WEBVIEW + i, t.getSavedState());
The Android Open Source Project0c908882009-03-03 19:32:16 -0800285 }
286 }
287 }
288
289 /**
290 * Restore the state of all the tabs.
291 * @param inState The saved state of all the tabs.
Michael Kolb1bf23132010-11-19 12:55:12 -0800292 * @param restoreIncognitoTabs Restoring private browsing tabs
293 * @param restoreAll All webviews get restored, not just the current tab
294 * (this does not override handling of incognito tabs)
The Android Open Source Project0c908882009-03-03 19:32:16 -0800295 * @return True if there were previous tabs that were restored. False if
296 * there was no saved state or restoring the state failed.
297 */
Michael Kolb1bf23132010-11-19 12:55:12 -0800298 boolean restoreState(Bundle inState, boolean restoreIncognitoTabs,
299 boolean restoreAll) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800300 final int numTabs = (inState == null)
Grace Kloba22ac16e2009-10-07 18:00:23 -0700301 ? -1 : inState.getInt(Tab.NUMTABS, -1);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800302 if (numTabs == -1) {
303 return false;
304 } else {
Elliott Slaughter3d6df162010-08-25 13:17:44 -0700305 final int oldCurrentTab = inState.getInt(Tab.CURRTAB, -1);
306
307 // Determine whether the saved current tab can be restored, and
308 // if not, which tab will take its place.
309 int currentTab = -1;
Michael Kolb1bf23132010-11-19 12:55:12 -0800310 if (restoreIncognitoTabs
Elliott Slaughter3d6df162010-08-25 13:17:44 -0700311 || !inState.getBundle(Tab.WEBVIEW + oldCurrentTab).getBoolean(Tab.INCOGNITO)) {
312 currentTab = oldCurrentTab;
313 } else {
314 for (int i = 0; i < numTabs; i++) {
315 if (!inState.getBundle(Tab.WEBVIEW + i).getBoolean(Tab.INCOGNITO)) {
316 currentTab = i;
317 break;
318 }
319 }
320 }
321 if (currentTab < 0) {
322 return false;
323 }
324
325 // Map saved tab indices to new indices, in case any incognito tabs
326 // need to not be restored.
327 HashMap<Integer, Integer> originalTabIndices = new HashMap<Integer, Integer>();
328 originalTabIndices.put(-1, -1);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800329 for (int i = 0; i < numTabs; i++) {
Elliott Slaughter3d6df162010-08-25 13:17:44 -0700330 Bundle state = inState.getBundle(Tab.WEBVIEW + i);
331
Michael Kolb1bf23132010-11-19 12:55:12 -0800332 if (!restoreIncognitoTabs && state != null && state.getBoolean(Tab.INCOGNITO)) {
Elliott Slaughter3d6df162010-08-25 13:17:44 -0700333 originalTabIndices.put(i, -1);
Michael Kolb1bf23132010-11-19 12:55:12 -0800334 } else if (i == currentTab || restoreAll) {
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700335 Tab t = createNewTab();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800336 // Me must set the current tab before restoring the state
337 // so that all the client classes are set.
Michael Kolb1bf23132010-11-19 12:55:12 -0800338 if (i == currentTab) {
339 setCurrentTab(t);
340 }
Elliott Slaughter3d6df162010-08-25 13:17:44 -0700341 if (!t.restoreState(state)) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800342 Log.w(LOGTAG, "Fail in restoreState, load home page.");
Grace Kloba22ac16e2009-10-07 18:00:23 -0700343 t.getWebView().loadUrl(BrowserSettings.getInstance()
The Android Open Source Project0c908882009-03-03 19:32:16 -0800344 .getHomePage());
345 }
Elliott Slaughter3d6df162010-08-25 13:17:44 -0700346 originalTabIndices.put(i, getTabCount() - 1);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800347 } else {
348 // Create a new tab and don't restore the state yet, add it
349 // to the tab list
Michael Kolb8233fac2010-10-26 16:08:53 -0700350 Tab t = new Tab(mController, null, false, null, null);
Grace Kloba22ac16e2009-10-07 18:00:23 -0700351 if (state != null) {
352 t.setSavedState(state);
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700353 // Need to maintain the app id and original url so we
354 // can possibly reuse this tab.
Grace Kloba22ac16e2009-10-07 18:00:23 -0700355 t.setAppId(state.getString(Tab.APPID));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800356 }
357 mTabs.add(t);
Grace Klobaf56f68d2010-04-11 22:53:42 -0700358 // added the tab to the front as they are not current
359 mTabQueue.add(0, t);
Elliott Slaughter3d6df162010-08-25 13:17:44 -0700360 originalTabIndices.put(i, getTabCount() - 1);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800361 }
362 }
Elliott Slaughter3d6df162010-08-25 13:17:44 -0700363
The Android Open Source Project0c908882009-03-03 19:32:16 -0800364 // Rebuild the tree of tabs. Do this after all tabs have been
365 // created/restored so that the parent tab exists.
366 for (int i = 0; i < numTabs; i++) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700367 final Bundle b = inState.getBundle(Tab.WEBVIEW + i);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800368 final Tab t = getTab(i);
369 if (b != null && t != null) {
Elliott Slaughter3d6df162010-08-25 13:17:44 -0700370 final Integer parentIndex = originalTabIndices.get(b.getInt(Tab.PARENTTAB, -1));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800371 if (parentIndex != -1) {
372 final Tab parent = getTab(parentIndex);
373 if (parent != null) {
374 parent.addChildTab(t);
375 }
376 }
377 }
378 }
379 }
380 return true;
381 }
382
383 /**
Grace Klobaf56f68d2010-04-11 22:53:42 -0700384 * Free the memory in this order, 1) free the background tabs; 2) free the
The Android Open Source Project0c908882009-03-03 19:32:16 -0800385 * WebView cache;
386 */
387 void freeMemory() {
Grace Kloba92c18a52009-07-31 23:48:32 -0700388 if (getTabCount() == 0) return;
389
Grace Klobaf56f68d2010-04-11 22:53:42 -0700390 // free the least frequently used background tabs
391 Vector<Tab> tabs = getHalfLeastUsedTabs(getCurrentTab());
392 if (tabs.size() > 0) {
393 Log.w(LOGTAG, "Free " + tabs.size() + " tabs in the browser");
394 for (Tab t : tabs) {
395 // store the WebView's state.
396 t.saveState();
397 // destroy the tab
398 t.destroy();
399 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800400 return;
401 }
402
Derek Sollenberger4433d032009-06-10 15:37:21 -0400403 // free the WebView's unused memory (this includes the cache)
404 Log.w(LOGTAG, "Free WebView's unused memory and cache");
The Android Open Source Project0c908882009-03-03 19:32:16 -0800405 WebView view = getCurrentWebView();
406 if (view != null) {
Derek Sollenberger4433d032009-06-10 15:37:21 -0400407 view.freeMemory();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800408 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800409 }
410
Grace Klobaf56f68d2010-04-11 22:53:42 -0700411 private Vector<Tab> getHalfLeastUsedTabs(Tab current) {
412 Vector<Tab> tabsToGo = new Vector<Tab>();
413
Patrick Scott2a67de42009-08-31 09:48:37 -0400414 // Don't do anything if we only have 1 tab or if the current tab is
415 // null.
416 if (getTabCount() == 1 || current == null) {
Grace Klobaf56f68d2010-04-11 22:53:42 -0700417 return tabsToGo;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800418 }
419
Grace Klobaf56f68d2010-04-11 22:53:42 -0700420 if (mTabQueue.size() == 0) {
421 return tabsToGo;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800422 }
423
Grace Klobaf56f68d2010-04-11 22:53:42 -0700424 // Rip through the queue starting at the beginning and tear down half of
425 // available tabs which are not the current tab or the parent of the
426 // current tab.
427 int openTabCount = 0;
428 for (Tab t : mTabQueue) {
429 if (t != null && t.getWebView() != null) {
430 openTabCount++;
431 if (t != current && t != current.getParentTab()) {
432 tabsToGo.add(t);
433 }
434 }
435 }
436
437 openTabCount /= 2;
438 if (tabsToGo.size() > openTabCount) {
439 tabsToGo.setSize(openTabCount);
440 }
441
442 return tabsToGo;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800443 }
444
The Android Open Source Project0c908882009-03-03 19:32:16 -0800445 /**
446 * Show the tab that contains the given WebView.
447 * @param view The WebView used to find the tab.
448 */
449 Tab getTabFromView(WebView view) {
450 final int size = getTabCount();
451 for (int i = 0; i < size; i++) {
452 final Tab t = getTab(i);
Grace Kloba22ac16e2009-10-07 18:00:23 -0700453 if (t.getSubWebView() == view || t.getWebView() == view) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800454 return t;
455 }
456 }
457 return null;
458 }
459
460 /**
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700461 * Return the tab with the matching application id.
462 * @param id The application identifier.
463 */
464 Tab getTabFromId(String id) {
465 if (id == null) {
466 return null;
467 }
468 final int size = getTabCount();
469 for (int i = 0; i < size; i++) {
470 final Tab t = getTab(i);
Grace Kloba22ac16e2009-10-07 18:00:23 -0700471 if (id.equals(t.getAppId())) {
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700472 return t;
473 }
474 }
475 return null;
476 }
477
Grace Kloba22ac16e2009-10-07 18:00:23 -0700478 /**
479 * Stop loading in all opened WebView including subWindows.
480 */
Grace Kloba5d0e02e2009-10-05 15:15:36 -0700481 void stopAllLoading() {
482 final int size = getTabCount();
483 for (int i = 0; i < size; i++) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700484 final Tab t = getTab(i);
485 final WebView webview = t.getWebView();
Grace Kloba5d0e02e2009-10-05 15:15:36 -0700486 if (webview != null) {
487 webview.stopLoading();
488 }
Grace Kloba22ac16e2009-10-07 18:00:23 -0700489 final WebView subview = t.getSubWebView();
490 if (subview != null) {
491 webview.stopLoading();
492 }
Grace Kloba5d0e02e2009-10-05 15:15:36 -0700493 }
494 }
495
Patrick Scottcd115892009-07-16 09:42:58 -0400496 // This method checks if a non-app tab (one created within the browser)
497 // matches the given url.
498 private boolean tabMatchesUrl(Tab t, String url) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700499 if (t.getAppId() != null) {
Patrick Scottcd115892009-07-16 09:42:58 -0400500 return false;
Grace Kloba22ac16e2009-10-07 18:00:23 -0700501 }
502 WebView webview = t.getWebView();
503 if (webview == null) {
Patrick Scottcd115892009-07-16 09:42:58 -0400504 return false;
Grace Kloba22ac16e2009-10-07 18:00:23 -0700505 } else if (url.equals(webview.getUrl())
506 || url.equals(webview.getOriginalUrl())) {
Patrick Scottcd115892009-07-16 09:42:58 -0400507 return true;
508 }
509 return false;
510 }
511
512 /**
513 * Return the tab that has no app id associated with it and the url of the
514 * tab matches the given url.
515 * @param url The url to search for.
516 */
517 Tab findUnusedTabWithUrl(String url) {
518 if (url == null) {
519 return null;
520 }
521 // Check the current tab first.
522 Tab t = getCurrentTab();
523 if (t != null && tabMatchesUrl(t, url)) {
524 return t;
525 }
526 // Now check all the rest.
527 final int size = getTabCount();
528 for (int i = 0; i < size; i++) {
529 t = getTab(i);
530 if (tabMatchesUrl(t, url)) {
531 return t;
532 }
533 }
534 return null;
535 }
536
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700537 /**
John Reck30c714c2010-12-16 17:30:34 -0800538 * Recreate the main WebView of the given tab.
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700539 */
John Reck30c714c2010-12-16 17:30:34 -0800540 void recreateWebView(Tab t) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700541 final WebView w = t.getWebView();
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700542 if (w != null) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700543 t.destroy();
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700544 }
545 // Create a new WebView. If this tab is the current tab, we need to put
546 // back all the clients so force it to be the current tab.
Steve Block2bc69912009-07-30 14:45:13 +0100547 t.setWebView(createNewWebView());
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700548 if (getCurrentTab() == t) {
549 setCurrentTab(t, true);
550 }
Grace Kloba22ac16e2009-10-07 18:00:23 -0700551 // Clear the saved state and picker data
552 t.setSavedState(null);
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700553 }
554
555 /**
556 * Creates a new WebView and registers it with the global settings.
557 */
558 private WebView createNewWebView() {
Elliott Slaughterf0f03952010-07-14 18:10:36 -0700559 return createNewWebView(false);
560 }
561
562 /**
563 * Creates a new WebView and registers it with the global settings.
564 * @param privateBrowsing When true, enables private browsing in the new
565 * WebView.
566 */
567 private WebView createNewWebView(boolean privateBrowsing) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700568 return mController.getWebViewFactory().createWebView(privateBrowsing);
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700569 }
570
571 /**
The Android Open Source Project0c908882009-03-03 19:32:16 -0800572 * Put the current tab in the background and set newTab as the current tab.
573 * @param newTab The new tab. If newTab is null, the current tab is not
574 * set.
575 */
576 boolean setCurrentTab(Tab newTab) {
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700577 return setCurrentTab(newTab, false);
578 }
579
580 /**
581 * If force is true, this method skips the check for newTab == current.
582 */
583 private boolean setCurrentTab(Tab newTab, boolean force) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800584 Tab current = getTab(mCurrentTab);
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700585 if (current == newTab && !force) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800586 return true;
587 }
588 if (current != null) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700589 current.putInBackground();
590 mCurrentTab = -1;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800591 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800592 if (newTab == null) {
593 return false;
594 }
595
596 // Move the newTab to the end of the queue
597 int index = mTabQueue.indexOf(newTab);
598 if (index != -1) {
599 mTabQueue.remove(index);
600 }
601 mTabQueue.add(newTab);
602
The Android Open Source Project0c908882009-03-03 19:32:16 -0800603 // Display the new current tab
604 mCurrentTab = mTabs.indexOf(newTab);
Grace Kloba22ac16e2009-10-07 18:00:23 -0700605 WebView mainView = newTab.getWebView();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800606 boolean needRestore = (mainView == null);
607 if (needRestore) {
608 // Same work as in createNewTab() except don't do new Tab()
Steve Block2bc69912009-07-30 14:45:13 +0100609 mainView = createNewWebView();
610 newTab.setWebView(mainView);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800611 }
Grace Kloba22ac16e2009-10-07 18:00:23 -0700612 newTab.putInForeground();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800613 if (needRestore) {
614 // Have to finish setCurrentTab work before calling restoreState
Grace Kloba22ac16e2009-10-07 18:00:23 -0700615 if (!newTab.restoreState(newTab.getSavedState())) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800616 mainView.loadUrl(BrowserSettings.getInstance().getHomePage());
617 }
618 }
619 return true;
620 }
Michael Kolbfe251992010-07-08 15:41:55 -0700621
The Android Open Source Project0c908882009-03-03 19:32:16 -0800622}