下面列出了android.view.ViewTreeObserver.OnGlobalFocusChangeListener#org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Called on the foreground tab when the Activity showing the Tab gets started. This is called
* on both cold and warm starts.
*/
public void onActivityShown() {
if (isHidden()) {
show(TabSelectionType.FROM_USER);
} else {
// The visible Tab's renderer process may have died after the activity was paused.
// Ensure that it's restored appropriately.
loadIfNeeded();
}
// When resuming the activity, force an update to the fullscreen state to ensure a
// subactivity did not change the fullscreen configuration of this ChromeTab's renderer in
// the case where it was shared (i.e. via an EmbedContentViewActivity).
updateFullscreenEnabledState();
}
@Override
public void finishNativeInitialization() {
mTab = createTab();
getTabModelSelector().setTab(mTab);
mTab.show(TabSelectionType.FROM_NEW);
ControlContainer controlContainer = (ControlContainer) findViewById(R.id.control_container);
initializeCompositorContent(new LayoutManagerDocument(getCompositorViewHolder()),
(View) controlContainer, (ViewGroup) findViewById(android.R.id.content),
controlContainer);
getActivityTab().setFullscreenManager(getFullscreenManager());
super.finishNativeInitialization();
}
/**
* Called on the foreground tab when the Activity showing the Tab gets started. This is called
* on both cold and warm starts.
*/
public void onActivityShown() {
if (isHidden()) {
show(TabSelectionType.FROM_USER);
} else {
// The visible Tab's renderer process may have died after the activity was paused.
// Ensure that it's restored appropriately.
loadIfNeeded();
}
// When resuming the activity, force an update to the fullscreen state to ensure a
// subactivity did not change the fullscreen configuration of this ChromeTab's renderer in
// the case where it was shared (i.e. via an EmbedContentViewActivity).
updateFullscreenEnabledState();
}
@Override
public void finishNativeInitialization() {
mTab = createTab();
handleTabContentChanged();
getTabModelSelector().setTab(mTab);
mTab.show(TabSelectionType.FROM_NEW);
ControlContainer controlContainer = (ControlContainer) findViewById(R.id.control_container);
initializeCompositorContent(new LayoutManagerDocument(getCompositorViewHolder()),
(View) controlContainer, (ViewGroup) findViewById(android.R.id.content),
controlContainer);
if (getFullscreenManager() != null) getFullscreenManager().setTab(getActivityTab());
super.finishNativeInitialization();
}
/**
* Signal that an intent with ACTION_MAIN was received.
*
* This must only be called after the native libraries have been initialized.
*/
@SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
public void onMainIntentWithNative(long backgroundDurationMs) {
sLastMainIntentBehavior = null;
RecordUserAction.record("MobileStartup.MainIntentReceived");
if (backgroundDurationMs >= BACKGROUND_TIME_24_HOUR_MS) {
RecordUserAction.record("MobileStartup.MainIntentReceived.After24Hours");
} else if (backgroundDurationMs >= BACKGROUND_TIME_12_HOUR_MS) {
RecordUserAction.record("MobileStartup.MainIntentReceived.After12Hours");
} else if (backgroundDurationMs >= BACKGROUND_TIME_6_HOUR_MS) {
RecordUserAction.record("MobileStartup.MainIntentReceived.After6Hours");
} else if (backgroundDurationMs >= BACKGROUND_TIME_1_HOUR_MS) {
RecordUserAction.record("MobileStartup.MainIntentReceived.After1Hour");
}
if (mPendingActionRecordForMainIntent) return;
mBackgroundDurationMs = backgroundDurationMs;
ApplicationStatus.registerStateListenerForActivity(this, mActivity);
mPendingActionRecordForMainIntent = true;
mHandler.postDelayed(mTimeoutRunnable, sTimeoutDurationMs);
mTabModelObserver = new TabModelSelectorTabModelObserver(
mActivity.getTabModelSelector()) {
@Override
public void didAddTab(Tab tab, TabLaunchType type) {
if (TabLaunchType.FROM_RESTORE.equals(type)) return;
if (NewTabPage.isNTPUrl(tab.getUrl())) recordUserBehavior(NTP_CREATED);
}
@Override
public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
recordUserBehavior(SWITCH_TABS);
}
};
}
/**
* Called on the foreground tab when the Activity showing the Tab gets started. This is called
* on both cold and warm starts.
*/
public void onActivityShown() {
if (isHidden()) {
show(TabSelectionType.FROM_USER);
} else {
// The visible Tab's renderer process may have died after the activity was paused.
// Ensure that it's restored appropriately.
loadIfNeeded();
}
// When resuming the activity, force an update to the fullscreen state to ensure a
// subactivity did not change the fullscreen configuration of this ChromeTab's renderer in
// the case where it was shared.
updateFullscreenEnabledState();
}
@Override
public void initializeState() {
super.initializeState();
Tab tab = createTab();
getTabModelSelector().setTab(tab);
handleTabContentChanged();
tab.show(TabSelectionType.FROM_NEW);
}
@Override
public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
if (tab.getId() != lastId) tabSelected(tab.getId(), lastId, tab.isIncognito());
}
@Override
public void requestToShowTab(Tab tab, TabSelectionType type) {
boolean isFromExternalApp = tab != null
&& tab.getLaunchType() == TabLaunchType.FROM_EXTERNAL_APP;
if (mVisibleTab != tab && tab != null && !tab.isNativePage()) {
TabModelImpl.startTabSwitchLatencyTiming(type);
}
if (mVisibleTab != null && mVisibleTab != tab && !mVisibleTab.needsReload()) {
if (mVisibleTab.isInitialized() && !mVisibleTab.isDetachedForReparenting()) {
// TODO(dtrainor): Once we figure out why we can't grab a snapshot from the current
// tab when we have other tabs loading from external apps remove the checks for
// FROM_EXTERNAL_APP/FROM_NEW.
if (!mVisibleTab.isClosing()
&& (!isFromExternalApp || type != TabSelectionType.FROM_NEW)) {
cacheTabBitmap(mVisibleTab);
}
mVisibleTab.hide();
mVisibleTab.setFullscreenManager(null);
mTabSaver.addTabToSaveQueue(mVisibleTab);
}
mVisibleTab = null;
}
if (tab == null) {
notifyChanged();
return;
}
// We hit this case when the user enters tab switcher and comes back to the current tab
// without actual tab switch.
if (mVisibleTab == tab && !mVisibleTab.isHidden()) {
// The current tab might have been killed by the os while in tab switcher.
tab.loadIfNeeded();
return;
}
tab.setFullscreenManager(mActivity.getFullscreenManager());
mVisibleTab = tab;
// Don't execute the tab display part if Chrome has just been sent to background. This
// avoids uneccessary work (tab restore) and prevents pollution of tab display metrics - see
// http://crbug.com/316166.
if (type != TabSelectionType.FROM_EXIT) {
tab.show(type);
mUma.onShowTab(tab.getId(), tab.isBeingRestored());
}
}
@Override
public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
}
/**
* Called upon tab display.
* @param selectionType determines how the tab was being shown
* @param previousTimestampMillis time of the previous display or creation time for the tabs
* opened in background and not yet displayed
* @param rank The MRU rank for this tab within the model.
*/
void onShow(TabSelectionType selectionType, long previousTimestampMillis, int rank) {
long now = SystemClock.elapsedRealtime();
// Do not collect the tab switching data for the first switch to a tab after the cold start
// and for the tab switches that were not user-originated (e.g. the user closes the last
// incognito tab and the current normal mode tab is shown).
if (mLastShownTimestamp != -1 && selectionType == TabSelectionType.FROM_USER) {
long age = now - mLastShownTimestamp;
RecordHistogram.recordCountHistogram("Tab.SwitchedToForegroundAge", (int) age);
RecordHistogram.recordCountHistogram("Tab.SwitchedToForegroundMRURank", rank);
}
increaseTabShowCount();
boolean isOnBrowserStartup = sAllTabsShowCount == 1;
boolean performsLazyLoad = mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD
&& mLastShownTimestamp == -1;
int status;
if (mRestoreStartedAtMillis == -1 && !performsLazyLoad) {
// The tab is *not* being restored or loaded lazily on first display.
status = TAB_STATUS_MEMORY_RESIDENT;
} else if (mLastShownTimestamp == -1) {
// This is first display and the tab is being restored or loaded lazily.
if (isOnBrowserStartup) {
status = TAB_STATUS_RELOAD_COLD_START_FG;
} else if (mTabCreationState == TabCreationState.FROZEN_ON_RESTORE) {
status = TAB_STATUS_RELOAD_COLD_START_BG;
} else if (mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD) {
status = TAB_STATUS_LAZY_LOAD_FOR_BG_TAB;
} else {
assert mTabCreationState == TabCreationState.LIVE_IN_FOREGROUND
|| mTabCreationState == TabCreationState.LIVE_IN_BACKGROUND;
status = TAB_STATUS_RELOAD_EVICTED;
}
} else {
// The tab is being restored and this is *not* the first time the tab is shown.
status = TAB_STATUS_RELOAD_EVICTED;
}
// Record only user-visible switches to existing tabs. Do not record displays of newly
// created tabs (FROM_NEW) or selections of the previous tab that happen when we close the
// tab opened from intent while exiting Chrome (FROM_CLOSE).
if (selectionType == TabSelectionType.FROM_USER) {
RecordHistogram.recordEnumeratedHistogram(
"Tab.StatusWhenSwitchedBackToForeground", status, TAB_STATUS_LIM);
}
// Record Tab.BackgroundLoadStatus.
if (mLastShownTimestamp == -1) {
if (mTabCreationState == TabCreationState.LIVE_IN_BACKGROUND) {
if (mRestoreStartedAtMillis == -1) {
RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
TAB_BACKGROUND_LOAD_SHOWN, TAB_BACKGROUND_LOAD_LIM);
} else {
RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
TAB_BACKGROUND_LOAD_LOST, TAB_BACKGROUND_LOAD_LIM);
if (previousTimestampMillis > 0) {
RecordHistogram.recordMediumTimesHistogram(
"Tab.LostTabAgeWhenSwitchedToForeground",
System.currentTimeMillis() - previousTimestampMillis,
TimeUnit.MILLISECONDS);
}
}
} else if (mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD) {
assert mRestoreStartedAtMillis == -1;
RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
TAB_BACKGROUND_LOAD_SKIPPED, TAB_BACKGROUND_LOAD_LIM);
}
}
// Record "tab age upon first display" metrics. previousTimestampMillis is persisted through
// cold starts.
if (mLastShownTimestamp == -1 && previousTimestampMillis > 0) {
if (isOnBrowserStartup) {
RecordHistogram.recordCountHistogram("Tabs.ForegroundTabAgeAtStartup",
(int) millisecondsToMinutes(System.currentTimeMillis()
- previousTimestampMillis));
} else if (selectionType == TabSelectionType.FROM_USER) {
RecordHistogram.recordCountHistogram("Tab.AgeUponRestoreFromColdStart",
(int) millisecondsToMinutes(System.currentTimeMillis()
- previousTimestampMillis));
}
}
mLastShownTimestamp = now;
updateTabState(TAB_STATE_ACTIVE);
}
/**
* Prepares the tab to be shown. This method is supposed to be called before the tab is
* displayed. It restores the ContentView if it is not available after the cold start and
* reloads the tab if its renderer has crashed.
* @param type Specifies how the tab was selected.
*/
public final void show(TabSelectionType type) {
try {
TraceEvent.begin("Tab.show");
if (!isHidden()) return;
// Keep unsetting mIsHidden above loadIfNeeded(), so that we pass correct visibility
// when spawning WebContents in loadIfNeeded().
mIsHidden = false;
loadIfNeeded();
assert !isFrozen();
if (mContentViewCore != null) mContentViewCore.onShow();
if (mTabUma != null) {
mTabUma.onShow(type, getTimestampMillis(),
computeMRURank(this, getTabModelSelector().getModel(mIncognito)));
}
// If the NativePage was frozen while in the background (see NativePageAssassin),
// recreate the NativePage now.
if (getNativePage() instanceof FrozenNativePage) {
maybeShowNativePage(getUrl(), true);
}
NativePageAssassin.getInstance().tabShown(this);
// If the page is still loading, update the progress bar (otherwise it would not show
// until the renderer notifies of new progress being made).
if (getProgress() < 100 && !isShowingInterstitialPage()) {
notifyLoadProgress(getProgress());
}
// Updating the timestamp has to happen after the showInternal() call since subclasses
// may use it for logging.
mTimestampMillis = System.currentTimeMillis();
for (TabObserver observer : mObservers) observer.onShown(this);
} finally {
TraceEvent.end("Tab.show");
}
}
@Override
public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
if (tab == null || tab.getId() != lastId) onDismiss();
}
@Override
public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
if (tab.getId() != lastId) tabSelected(tab.getId(), lastId, tab.isIncognito());
}
@Override
public void requestToShowTab(Tab tab, TabSelectionType type) {
boolean isFromExternalApp = tab != null
&& tab.getLaunchType() == TabLaunchType.FROM_EXTERNAL_APP;
if (mVisibleTab != tab && tab != null && !tab.isNativePage()) {
TabModelImpl.startTabSwitchLatencyTiming(type);
}
if (mVisibleTab != null && mVisibleTab != tab && !mVisibleTab.needsReload()) {
if (mVisibleTab.isInitialized() && !mVisibleTab.isDetachedForReparenting()) {
// TODO(dtrainor): Once we figure out why we can't grab a snapshot from the current
// tab when we have other tabs loading from external apps remove the checks for
// FROM_EXTERNAL_APP/FROM_NEW.
if (!mVisibleTab.isClosing()
&& (!isFromExternalApp || type != TabSelectionType.FROM_NEW)) {
cacheTabBitmap(mVisibleTab);
}
mVisibleTab.hide();
mTabSaver.addTabToSaveQueue(mVisibleTab);
}
mVisibleTab = null;
}
if (tab == null) {
notifyChanged();
return;
}
// We hit this case when the user enters tab switcher and comes back to the current tab
// without actual tab switch.
if (mVisibleTab == tab && !mVisibleTab.isHidden()) {
// The current tab might have been killed by the os while in tab switcher.
tab.loadIfNeeded();
return;
}
mVisibleTab = tab;
// Don't execute the tab display part if Chrome has just been sent to background. This
// avoids uneccessary work (tab restore) and prevents pollution of tab display metrics - see
// http://crbug.com/316166.
if (type != TabSelectionType.FROM_EXIT) {
tab.show(type);
mUma.onShowTab(tab.getId(), tab.isBeingRestored());
}
}
@Override
public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
}
/**
* Called upon tab display.
* @param selectionType determines how the tab was being shown
* @param previousTimestampMillis time of the previous display or creation time for the tabs
* opened in background and not yet displayed
* @param rank The MRU rank for this tab within the model.
*/
void onShow(TabSelectionType selectionType, long previousTimestampMillis, int rank) {
long now = SystemClock.elapsedRealtime();
// Do not collect the tab switching data for the first switch to a tab after the cold start
// and for the tab switches that were not user-originated (e.g. the user closes the last
// incognito tab and the current normal mode tab is shown).
if (mLastShownTimestamp != -1 && selectionType == TabSelectionType.FROM_USER) {
long age = now - mLastShownTimestamp;
RecordHistogram.recordCountHistogram("Tab.SwitchedToForegroundAge", (int) age);
RecordHistogram.recordCountHistogram("Tab.SwitchedToForegroundMRURank", rank);
}
increaseTabShowCount();
boolean isOnBrowserStartup = sAllTabsShowCount == 1;
boolean performsLazyLoad = mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD
&& mLastShownTimestamp == -1;
int status;
if (mRestoreStartedAtMillis == -1 && !performsLazyLoad) {
// The tab is *not* being restored or loaded lazily on first display.
status = TAB_STATUS_MEMORY_RESIDENT;
} else if (mLastShownTimestamp == -1) {
// This is first display and the tab is being restored or loaded lazily.
if (isOnBrowserStartup) {
status = TAB_STATUS_RELOAD_COLD_START_FG;
} else if (mTabCreationState == TabCreationState.FROZEN_ON_RESTORE) {
status = TAB_STATUS_RELOAD_COLD_START_BG;
} else if (mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD) {
status = TAB_STATUS_LAZY_LOAD_FOR_BG_TAB;
} else {
assert mTabCreationState == TabCreationState.LIVE_IN_FOREGROUND
|| mTabCreationState == TabCreationState.LIVE_IN_BACKGROUND;
status = TAB_STATUS_RELOAD_EVICTED;
}
} else {
// The tab is being restored and this is *not* the first time the tab is shown.
status = TAB_STATUS_RELOAD_EVICTED;
}
// Record only user-visible switches to existing tabs. Do not record displays of newly
// created tabs (FROM_NEW) or selections of the previous tab that happen when we close the
// tab opened from intent while exiting Chrome (FROM_CLOSE).
if (selectionType == TabSelectionType.FROM_USER) {
RecordHistogram.recordEnumeratedHistogram(
"Tab.StatusWhenSwitchedBackToForeground", status, TAB_STATUS_LIM);
}
// Record Tab.BackgroundLoadStatus.
if (mLastShownTimestamp == -1) {
if (mTabCreationState == TabCreationState.LIVE_IN_BACKGROUND) {
if (mRestoreStartedAtMillis == -1) {
RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
TAB_BACKGROUND_LOAD_SHOWN, TAB_BACKGROUND_LOAD_LIM);
} else {
RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
TAB_BACKGROUND_LOAD_LOST, TAB_BACKGROUND_LOAD_LIM);
if (previousTimestampMillis > 0) {
RecordHistogram.recordMediumTimesHistogram(
"Tab.LostTabAgeWhenSwitchedToForeground",
System.currentTimeMillis() - previousTimestampMillis,
TimeUnit.MILLISECONDS);
}
}
} else if (mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD) {
assert mRestoreStartedAtMillis == -1;
RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
TAB_BACKGROUND_LOAD_SKIPPED, TAB_BACKGROUND_LOAD_LIM);
}
}
// Record "tab age upon first display" metrics. previousTimestampMillis is persisted through
// cold starts.
if (mLastShownTimestamp == -1 && previousTimestampMillis > 0) {
if (isOnBrowserStartup) {
RecordHistogram.recordCountHistogram("Tabs.ForegroundTabAgeAtStartup",
(int) millisecondsToMinutes(System.currentTimeMillis()
- previousTimestampMillis));
} else if (selectionType == TabSelectionType.FROM_USER) {
RecordHistogram.recordCountHistogram("Tab.AgeUponRestoreFromColdStart",
(int) millisecondsToMinutes(System.currentTimeMillis()
- previousTimestampMillis));
}
}
mLastShownTimestamp = now;
updateTabState(TAB_STATE_ACTIVE);
}
/**
* Prepares the tab to be shown. This method is supposed to be called before the tab is
* displayed. It restores the ContentView if it is not available after the cold start and
* reloads the tab if its renderer has crashed.
* @param type Specifies how the tab was selected.
*/
public final void show(TabSelectionType type) {
try {
TraceEvent.begin("Tab.show");
if (!isHidden()) return;
// Keep unsetting mIsHidden above loadIfNeeded(), so that we pass correct visibility
// when spawning WebContents in loadIfNeeded().
mIsHidden = false;
loadIfNeeded();
assert !isFrozen();
if (mContentViewCore != null) mContentViewCore.onShow();
if (mBlimpContents != null) mBlimpContents.show();
if (mTabUma != null) {
mTabUma.onShow(type, getTimestampMillis(),
computeMRURank(this, getTabModelSelector().getModel(mIncognito)));
}
// If the NativePage was frozen while in the background (see NativePageAssassin),
// recreate the NativePage now.
if (getNativePage() instanceof FrozenNativePage) {
maybeShowNativePage(getUrl(), true);
}
NativePageAssassin.getInstance().tabShown(this);
// If the page is still loading, update the progress bar (otherwise it would not show
// until the renderer notifies of new progress being made).
if (getProgress() < 100 && !isShowingInterstitialPage()) {
notifyLoadProgress(getProgress());
}
// Updating the timestamp has to happen after the showInternal() call since subclasses
// may use it for logging.
mTimestampMillis = System.currentTimeMillis();
for (TabObserver observer : mObservers) observer.onShown(this);
} finally {
TraceEvent.end("Tab.show");
}
}
@Override
public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
if (tab == null || tab.getId() != lastId) onDismiss();
}
@Override
public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
if (tab.getId() != lastId) tabSelected(tab.getId(), lastId, tab.isIncognito());
}
@Override
public void requestToShowTab(Tab tab, TabSelectionType type) {
boolean isFromExternalApp = tab != null
&& tab.getLaunchType() == TabLaunchType.FROM_EXTERNAL_APP;
if (mVisibleTab != tab && tab != null && !tab.isNativePage()) {
TabModelImpl.startTabSwitchLatencyTiming(type);
}
if (mVisibleTab != null && mVisibleTab != tab && !mVisibleTab.needsReload()) {
if (mVisibleTab.isInitialized() && !mVisibleTab.isDetached()) {
// TODO(dtrainor): Once we figure out why we can't grab a snapshot from the current
// tab when we have other tabs loading from external apps remove the checks for
// FROM_EXTERNAL_APP/FROM_NEW.
if (!mVisibleTab.isClosing()
&& (!isFromExternalApp || type != TabSelectionType.FROM_NEW)) {
cacheTabBitmap(mVisibleTab);
}
mVisibleTab.hide();
mTabSaver.addTabToSaveQueue(mVisibleTab);
}
mVisibleTab = null;
}
if (tab == null) {
notifyChanged();
return;
}
// We hit this case when the user enters tab switcher and comes back to the current tab
// without actual tab switch.
if (mVisibleTab == tab && !mVisibleTab.isHidden()) {
// The current tab might have been killed by the os while in tab switcher.
tab.loadIfNeeded();
return;
}
mVisibleTab = tab;
// Don't execute the tab display part if Chrome has just been sent to background. This
// avoids uneccessary work (tab restore) and prevents pollution of tab display metrics - see
// http://crbug.com/316166.
if (type != TabSelectionType.FROM_EXIT) {
tab.show(type);
mUma.onShowTab(tab.getId(), tab.isBeingRestored());
}
}
@Override
public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {}
/**
* Called upon tab display.
* @param selectionType determines how the tab was being shown
* @param previousTimestampMillis time of the previous display or creation time for the tabs
* opened in background and not yet displayed
* @param rank The MRU rank for this tab within the model.
*/
void onShow(TabSelectionType selectionType, long previousTimestampMillis, int rank) {
long now = SystemClock.elapsedRealtime();
// Do not collect the tab switching data for the first switch to a tab after the cold start
// and for the tab switches that were not user-originated (e.g. the user closes the last
// incognito tab and the current normal mode tab is shown).
if (mLastShownTimestamp != -1 && selectionType == TabSelectionType.FROM_USER) {
long age = now - mLastShownTimestamp;
RecordHistogram.recordCountHistogram("Tab.SwitchedToForegroundAge", (int) age);
RecordHistogram.recordCountHistogram("Tab.SwitchedToForegroundMRURank", rank);
}
increaseTabShowCount();
boolean isOnBrowserStartup = sAllTabsShowCount == 1;
boolean performsLazyLoad = mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD
&& mLastShownTimestamp == -1;
int status;
if (mRestoreStartedAtMillis == -1 && !performsLazyLoad) {
// The tab is *not* being restored or loaded lazily on first display.
status = TAB_STATUS_MEMORY_RESIDENT;
} else if (mLastShownTimestamp == -1) {
// This is first display and the tab is being restored or loaded lazily.
if (isOnBrowserStartup) {
status = TAB_STATUS_RELOAD_COLD_START_FG;
} else if (mTabCreationState == TabCreationState.FROZEN_ON_RESTORE) {
status = TAB_STATUS_RELOAD_COLD_START_BG;
} else if (mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD) {
status = TAB_STATUS_LAZY_LOAD_FOR_BG_TAB;
} else {
assert mTabCreationState == TabCreationState.LIVE_IN_FOREGROUND
|| mTabCreationState == TabCreationState.LIVE_IN_BACKGROUND;
status = TAB_STATUS_RELOAD_EVICTED;
}
} else {
// The tab is being restored and this is *not* the first time the tab is shown.
status = TAB_STATUS_RELOAD_EVICTED;
}
// Record only user-visible switches to existing tabs. Do not record displays of newly
// created tabs (FROM_NEW) or selections of the previous tab that happen when we close the
// tab opened from intent while exiting Chrome (FROM_CLOSE).
if (selectionType == TabSelectionType.FROM_USER) {
RecordHistogram.recordEnumeratedHistogram(
"Tab.StatusWhenSwitchedBackToForeground", status, TAB_STATUS_LIM);
}
// Record Tab.BackgroundLoadStatus.
if (mLastShownTimestamp == -1) {
if (mTabCreationState == TabCreationState.LIVE_IN_BACKGROUND) {
if (mRestoreStartedAtMillis == -1) {
RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
TAB_BACKGROUND_LOAD_SHOWN, TAB_BACKGROUND_LOAD_LIM);
} else {
RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
TAB_BACKGROUND_LOAD_LOST, TAB_BACKGROUND_LOAD_LIM);
if (previousTimestampMillis > 0) {
RecordHistogram.recordMediumTimesHistogram(
"Tab.LostTabAgeWhenSwitchedToForeground",
System.currentTimeMillis() - previousTimestampMillis,
TimeUnit.MILLISECONDS);
}
}
} else if (mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD) {
assert mRestoreStartedAtMillis == -1;
RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
TAB_BACKGROUND_LOAD_SKIPPED, TAB_BACKGROUND_LOAD_LIM);
}
}
// Record "tab age upon first display" metrics. previousTimestampMillis is persisted through
// cold starts.
if (mLastShownTimestamp == -1 && previousTimestampMillis > 0) {
if (isOnBrowserStartup) {
RecordHistogram.recordCountHistogram("Tabs.ForegroundTabAgeAtStartup",
(int) millisecondsToMinutes(System.currentTimeMillis()
- previousTimestampMillis));
} else if (selectionType == TabSelectionType.FROM_USER) {
RecordHistogram.recordCountHistogram("Tab.AgeUponRestoreFromColdStart",
(int) millisecondsToMinutes(System.currentTimeMillis()
- previousTimestampMillis));
}
}
mLastShownTimestamp = now;
updateTabState(TAB_STATE_ACTIVE);
}
/**
* Prepares the tab to be shown. This method is supposed to be called before the tab is
* displayed. It restores the ContentView if it is not available after the cold start and
* reloads the tab if its renderer has crashed.
* @param type Specifies how the tab was selected.
*/
public final void show(TabSelectionType type) {
try {
TraceEvent.begin("Tab.show");
if (!isHidden()) return;
// Keep unsetting mIsHidden above loadIfNeeded(), so that we pass correct visibility
// when spawning WebContents in loadIfNeeded().
mIsHidden = false;
loadIfNeeded();
assert !isFrozen();
if (mContentViewCore != null) mContentViewCore.onShow();
if (mTabUma != null) {
mTabUma.onShow(type, getTimestampMillis(),
computeMRURank(this, getTabModelSelector().getModel(mIncognito)));
}
// If the NativePage was frozen while in the background (see NativePageAssassin),
// recreate the NativePage now.
NativePage nativePage = getNativePage();
if (nativePage instanceof FrozenNativePage) {
maybeShowNativePage(nativePage.getUrl(), true);
}
NativePageAssassin.getInstance().tabShown(this);
// If the page is still loading, update the progress bar (otherwise it would not show
// until the renderer notifies of new progress being made).
if (getProgress() < 100 && !isShowingInterstitialPage()) {
notifyLoadProgress(getProgress());
}
// Updating the timestamp has to happen after the showInternal() call since subclasses
// may use it for logging.
mTimestampMillis = System.currentTimeMillis();
for (TabObserver observer : mObservers) observer.onShown(this);
} finally {
TraceEvent.end("Tab.show");
}
}
/**
* Called when a tab is selected.
*
* @param tab The newly selected tab.
* @param type The type of selection.
* @param lastId The ID of the last selected tab, or {@link Tab#INVALID_TAB_ID} if no tab was
* selected.
*/
void didSelectTab(Tab tab, TabSelectionType type, int lastId);
/**
* Requests the specified to be shown.
* @param tab The tab that is requested to be shown.
* @param type The reason why this tab was requested to be shown.
*/
void requestToShowTab(Tab tab, TabSelectionType type);
/**
* A helper method that automatically passes {@link TabSelectionType#FROM_USER} as the selection
* type to {@link TabModel#setIndex(int, TabSelectionType)}.
* @param model The {@link TabModel} to act on.
* @param index The index of the {@link Tab} to select.
*/
public static void setIndex(TabModel model, int index) {
model.setIndex(index, TabSelectionType.FROM_USER);
}
/**
* Called when a tab is selected.
*
* @param tab The newly selected tab.
* @param type The type of selection.
* @param lastId The ID of the last selected tab, or {@link Tab#INVALID_TAB_ID} if no tab was
* selected.
*/
void didSelectTab(Tab tab, TabSelectionType type, int lastId);
/**
* Requests the specified to be shown.
* @param tab The tab that is requested to be shown.
* @param type The reason why this tab was requested to be shown.
*/
void requestToShowTab(Tab tab, TabSelectionType type);
/**
* A helper method that automatically passes {@link TabSelectionType#FROM_USER} as the selection
* type to {@link TabModel#setIndex(int, TabSelectionType)}.
* @param model The {@link TabModel} to act on.
* @param index The index of the {@link Tab} to select.
*/
public static void setIndex(TabModel model, int index) {
model.setIndex(index, TabSelectionType.FROM_USER);
}