Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(633)

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.tabmodel;
6
7 import android.content.Context;
8 import android.os.Handler;
9
10 import org.chromium.base.metrics.RecordHistogram;
11 import org.chromium.chrome.browser.ChromeActivity;
12 import org.chromium.chrome.browser.Tab;
13 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
14 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
15 import org.chromium.chrome.browser.ntp.NativePageFactory;
16 import org.chromium.chrome.browser.tabmodel.OffTheRecordTabModel.OffTheRecordTab ModelDelegate;
17 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
18 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
19 import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStor eObserver;
20 import org.chromium.content_public.browser.LoadUrlParams;
21 import org.chromium.ui.base.WindowAndroid;
22
23 import java.util.concurrent.atomic.AtomicBoolean;
24
25 /**
26 * This class manages all the ContentViews in the app. As it manipulates views, it must be
27 * instantiated and used in the UI Thread. It acts as a TabModel which delegate s all
28 * TabModel methods to the active model that it contains.
29 */
30 public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod elDelegate {
31
32 private final ChromeActivity mActivity;
33
34 /** Flag set to false when the asynchronous loading of tabs is finished. */
35 private final AtomicBoolean mSessionRestoreInProgress =
36 new AtomicBoolean(true);
37 private final TabPersistentStore mTabSaver;
38
39 // This flag signifies the object has gotten an onNativeReady callback and
40 // has not been destroyed.
41 private boolean mActiveState = false;
42
43 private final TabModelOrderController mOrderController;
44
45 private OverviewModeBehavior mOverviewModeBehavior;
46
47 private TabContentManager mTabContentManager;
48
49 private Tab mVisibleTab;
50
51 private final TabModelSelectorUma mUma;
52
53 private CloseAllTabsDelegate mCloseAllTabsDelegate;
54
55 private static class TabModelImplCreator implements OffTheRecordTabModelDele gate {
56 private final ChromeActivity mActivity;
57 private final TabModelSelectorUma mUma;
58 private final TabModelOrderController mOrderController;
59 private final TabContentManager mTabContentManager;
60 private final TabPersistentStore mTabSaver;
61 private final TabModelDelegate mModelDelegate;
62
63 /**
64 * Constructor for an Incognito TabModelImpl.
65 *
66 * @param activity The activity owning this TabModel.
67 * @param uma Handles UMA tracking for the model.
68 * @param orderController Determines the order for inserting new Tabs .
69 * @param tabContentManager Manages the display content of the tab.
70 * @param tabSaver Handler for saving tabs.
71 * @param modelDelegate Delegate to handle external dependencies an d interactions.
72 */
73 public TabModelImplCreator(ChromeActivity activity, TabModelSelectorUma uma,
74 TabModelOrderController orderController, TabContentManager tabCo ntentManager,
75 TabPersistentStore tabSaver, TabModelDelegate modelDelegate) {
76 mActivity = activity;
77 mUma = uma;
78 mOrderController = orderController;
79 mTabContentManager = tabContentManager;
80 mTabSaver = tabSaver;
81 mModelDelegate = modelDelegate;
82 }
83
84 @Override
85 public TabModel createTabModel() {
86 return new TabModelImpl(true, mActivity, mUma, mOrderController,
87 mTabContentManager, mTabSaver, mModelDelegate);
88 }
89
90 @Override
91 public boolean doOffTheRecordTabsExist() {
92 return TabWindowManager.getInstance().getIncognitoTabCount() > 0;
93 }
94 }
95
96 /**
97 * Builds a {@link TabModelSelectorImpl} instance.
98 * @param activity The {@link ChromeActivity} this model selector lives in.
99 * @param selectorIndex The index this selector represents in the list of se lectors.
100 * @param windowAndroid The {@link WindowAndroid} associated with this model selector.
101 */
102 public TabModelSelectorImpl(ChromeActivity activity, int selectorIndex,
103 WindowAndroid windowAndroid) {
104 super();
105 mActivity = activity;
106 mUma = new TabModelSelectorUma(mActivity);
107 final TabPersistentStoreObserver persistentStoreObserver =
108 new TabPersistentStoreObserver() {
109 @Override
110 public void onStateLoaded(Context context) {
111 markTabStateInitialized();
112 }
113
114 @Override
115 public void onInitialized(int tabCountAtStartup) {
116 RecordHistogram.recordCountHistogram("Tabs.CountAtStartup", tabC ountAtStartup);
117 }
118 };
119 mTabSaver = new TabPersistentStore(this, selectorIndex, mActivity, mActi vity,
120 persistentStoreObserver);
121 mOrderController = new TabModelOrderController(this);
122 ChromeTabCreator regularTabCreator = new ChromeTabCreator(mActivity, win dowAndroid,
123 mOrderController, mTabSaver, false);
124 ChromeTabCreator incognitoTabCreator = new ChromeTabCreator(mActivity, w indowAndroid,
125 mOrderController, mTabSaver, true);
126 mActivity.setTabCreators(regularTabCreator, incognitoTabCreator);
127 }
128
129 @Override
130 protected void markTabStateInitialized() {
131 super.markTabStateInitialized();
132 if (!mSessionRestoreInProgress.getAndSet(false)) return;
133
134 // This is the first time we set
135 // |mSessionRestoreInProgress|, so we need to broadcast.
136 TabModelImpl model = (TabModelImpl) getModel(false);
137
138 if (model != null) {
139 model.broadcastSessionRestoreComplete();
140 } else {
141 assert false : "Normal tab model is null after tab state loaded.";
142 }
143 }
144
145 private void handleOnPageLoadStopped(Tab tab) {
146 if (tab != null) mTabSaver.addTabToSaveQueue(tab);
147 }
148
149 /**
150 *
151 * @param overviewModeBehavior The {@link OverviewModeBehavior} that should be used to determine
152 * when the app is in overview mode or not.
153 */
154 public void setOverviewModeBehavior(OverviewModeBehavior overviewModeBehavio r) {
155 assert overviewModeBehavior != null;
156 mOverviewModeBehavior = overviewModeBehavior;
157 }
158
159 /**
160 * Should be called when the app starts showing a view with multiple tabs.
161 */
162 public void onTabsViewShown() {
163 mUma.onTabsViewShown();
164 }
165
166 /**
167 * Should be called once the native library is loaded so that the actual int ernals of this
168 * class can be initialized.
169 * @param tabContentProvider A {@link TabContentManager } instance.
170 */
171 public void onNativeLibraryReady(TabContentManager tabContentProvider) {
172 assert !mActiveState : "onNativeLibraryReady called twice!";
173 mTabContentManager = tabContentProvider;
174
175 TabModel normalModel = new TabModelImpl(false, mActivity, mUma, mOrderCo ntroller,
176 mTabContentManager, mTabSaver, this);
177 TabModel incognitoModel = new OffTheRecordTabModel(new TabModelImplCreat or(
178 mActivity, mUma, mOrderController, mTabContentManager, mTabSaver , this));
179 initialize(isIncognitoSelected(), normalModel, incognitoModel);
180 mActivity.getTabCreator(false).setTabModel(normalModel, mTabContentManag er);
181 mActivity.getTabCreator(true).setTabModel(incognitoModel, mTabContentMan ager);
182
183 mTabSaver.setTabContentManager(tabContentProvider);
184
185 addObserver(new EmptyTabModelSelectorObserver() {
186 @Override
187 public void onNewTabCreated(Tab tab) {
188 // Only invalidate if the tab exists in the currently selected m odel.
189 if (TabModelUtils.getTabById(getCurrentModel(), tab.getId()) != null) {
190 mTabContentManager.invalidateIfChanged(tab.getId(), tab.getU rl());
191 }
192 }
193 });
194
195 mActiveState = true;
196
197 new TabModelSelectorTabObserver(this) {
198 @Override
199 public void onUrlUpdated(Tab tab) {
200 TabModel model = getModelForTabId(tab.getId());
201 if (model == getCurrentModel()) {
202 mTabContentManager.invalidateIfChanged(tab.getId(), tab.getU rl());
203 }
204 }
205
206 @Override
207 public void onLoadStopped(Tab tab) {
208 handleOnPageLoadStopped(tab);
209 }
210
211 @Override
212 public void onPageLoadStarted(Tab tab) {
213 String url = tab.getUrl();
214 if (NativePageFactory.isNativePageUrl(url, tab.isIncognito())) {
215 mTabContentManager.invalidateTabThumbnail(tab.getId(), url);
216 } else {
217 mTabContentManager.removeTabThumbnail(tab.getId());
218 }
219 }
220
221 @Override
222 public void onPageLoadFinished(Tab tab) {
223 mUma.onPageLoadFinished(tab.getId());
224 }
225
226 @Override
227 public void onPageLoadFailed(Tab tab, int errorCode) {
228 mUma.onPageLoadFailed(tab.getId());
229 }
230
231 @Override
232 public void onCrash(Tab tab, boolean sadTabShown) {
233 if (sadTabShown) {
234 mTabContentManager.removeTabThumbnail(tab.getId());
235 }
236 mUma.onTabCrashed(tab.getId());
237 }
238 };
239 }
240
241 @Override
242 public void setCloseAllTabsDelegate(CloseAllTabsDelegate delegate) {
243 mCloseAllTabsDelegate = delegate;
244 }
245
246 @Override
247 public TabModel getModelAt(int index) {
248 return mActiveState ? super.getModelAt(index) : EmptyTabModel.getInstanc e();
249 }
250
251 @Override
252 public void selectModel(boolean incognito) {
253 TabModel oldModel = getCurrentModel();
254 super.selectModel(incognito);
255 TabModel newModel = getCurrentModel();
256 if (oldModel != newModel) {
257 TabModelUtils.setIndex(newModel, newModel.index());
258
259 // Make the call to notifyDataSetChanged() after any delayed events
260 // have had a chance to fire. Otherwise, this may result in some
261 // drawing to occur before animations have a chance to work.
262 new Handler().post(new Runnable() {
263 @Override
264 public void run() {
265 notifyChanged();
266 }
267 });
268 }
269 }
270
271 /**
272 * Commits all pending tab closures for all {@link TabModel}s in this {@link TabModelSelector}.
273 */
274 @Override
275 public void commitAllTabClosures() {
276 for (int i = 0; i < getModels().size(); i++) {
277 getModelAt(i).commitAllTabClosures();
278 }
279 }
280
281 @Override
282 public boolean closeAllTabsRequest(boolean incognito) {
283 return mCloseAllTabsDelegate.closeAllTabsRequest(incognito);
284 }
285
286 public void saveState() {
287 commitAllTabClosures();
288 mTabSaver.saveState();
289 }
290
291 /**
292 * Load the saved tab state. This should be called before any new tabs are c reated. The saved
293 * tabs shall not be restored until {@link #restoreTabs} is called.
294 */
295 public void loadState() {
296 int nextId = mTabSaver.loadState();
297 if (nextId >= 0) Tab.incrementIdCounterTo(nextId);
298 }
299
300 /**
301 * Restore the saved tabs which were loaded by {@link #loadState}.
302 *
303 * @param setActiveTab If true, synchronously load saved active tab and set it as the current
304 * active tab.
305 */
306 public void restoreTabs(boolean setActiveTab) {
307 mTabSaver.restoreTabs(setActiveTab);
308 }
309
310 /**
311 * If there is an asynchronous session restore in-progress, try to synchrono usly restore
312 * the state of a tab with the given url as a frozen tab. This method has no effect if
313 * there isn't a tab being restored with this url, or the tab has already be en restored.
314 *
315 * @return true if there exists a tab with the url.
316 */
317 public boolean tryToRestoreTabStateForUrl(String url) {
318 if (!isSessionRestoreInProgress()) return false;
319 return mTabSaver.restoreTabStateForUrl(url);
320 }
321
322 /**
323 * If there is an asynchronous session restore in-progress, try to synchrono usly restore
324 * the state of a tab with the given id as a frozen tab. This method has no effect if
325 * there isn't a tab being restored with this id, or the tab has already bee n restored.
326 *
327 * @return true if there exists a tab with the id.
328 */
329 public boolean tryToRestoreTabStateForId(int id) {
330 if (!isSessionRestoreInProgress()) return false;
331 return mTabSaver.restoreTabStateForId(id);
332 }
333
334 public void clearState() {
335 mTabSaver.clearState();
336 }
337
338 public void clearEncryptedState() {
339 mTabSaver.clearEncryptedState();
340 }
341
342 @Override
343 public void destroy() {
344 mTabSaver.destroy();
345 mUma.destroy();
346 super.destroy();
347 mActiveState = false;
348 }
349
350 @Override
351 public Tab openNewTab(LoadUrlParams loadUrlParams, TabLaunchType type, Tab p arent,
352 boolean incognito) {
353 return mActivity.getTabCreator(incognito).createNewTab(loadUrlParams, ty pe, parent);
354 }
355
356 /**
357 * @return Number of restored tabs on cold startup.
358 */
359 public int getRestoredTabCount() {
360 return mTabSaver.getRestoredTabCount();
361 }
362
363 @Override
364 public void requestToShowTab(Tab tab, TabSelectionType type) {
365 boolean isFromExternalApp = tab != null
366 && tab.getLaunchType() == TabLaunchType.FROM_EXTERNAL_APP;
367
368 if (mVisibleTab != tab && tab != null && !tab.isNativePage()) {
369 TabModelBase.startTabSwitchLatencyTiming(type);
370 }
371 if (mVisibleTab != null && mVisibleTab != tab && !mVisibleTab.needsReloa d()) {
372 // TODO(dtrainor): Once we figure out why we can't grab a snapshot f rom the current
373 // tab when we have other tabs loading from external apps remove the checks for
374 // FROM_EXTERNAL_APP/FROM_NEW.
375 if (!mVisibleTab.isClosing()
376 && (!isFromExternalApp || type != TabSelectionType.FROM_NEW) ) {
377 cacheTabBitmap(mVisibleTab);
378 }
379 mVisibleTab.hide();
380 mVisibleTab.setFullscreenManager(null);
381 mTabSaver.addTabToSaveQueue(mVisibleTab);
382 mVisibleTab = null;
383 }
384
385 if (tab == null) {
386 notifyChanged();
387 return;
388 }
389
390 // We hit this case when the user enters tab switcher and comes back to the current tab
391 // without actual tab switch.
392 if (mVisibleTab == tab && !mVisibleTab.isHidden()) {
393 // The current tab might have been killed by the os while in tab swi tcher.
394 tab.loadIfNeeded();
395 return;
396 }
397
398 tab.setFullscreenManager(mActivity.getFullscreenManager());
399 mVisibleTab = tab;
400
401 // Don't execute the tab display part if Chrome has just been sent to ba ckground. This
402 // avoids uneccessary work (tab restore) and prevents pollution of tab d isplay metrics - see
403 // http://crbug.com/316166.
404 if (type != TabSelectionType.FROM_EXIT) {
405 tab.show(type);
406 mUma.onShowTab(tab.getId(), tab.isBeingRestored());
407 }
408 }
409
410 private void cacheTabBitmap(Tab tabToCache) {
411 // Trigger a capture of this tab.
412 if (tabToCache == null) return;
413 mTabContentManager.cacheTabThumbnail(tabToCache);
414 }
415
416 @Override
417 public boolean isInOverviewMode() {
418 return mOverviewModeBehavior != null && mOverviewModeBehavior.overviewVi sible();
419 }
420
421 @Override
422 public boolean isSessionRestoreInProgress() {
423 return mSessionRestoreInProgress.get();
424 }
425
426 // TODO(tedchoc): Remove the need for this to be exposed.
427 @Override
428 public void notifyChanged() {
429 super.notifyChanged();
430 }
431 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698