// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.tabmodel;
import android.app.Activity;
import android.os.SystemClock;
import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.RecordUserAction;
/**
* Centralizes UMA data collection for TabModelSelector. All calls must be made from the UI thread.
*/
public final class TabModelSelectorUma implements ApplicationStatus.ActivityStateListener {
// TabRestoreUserAction defined in tools/metrics/histograms/histograms.xml.
private static final int USER_WAITED_FOR_RESTORE_COMPLETION = 0;
private static final int USER_LEFT_TAB_DURING_RESTORE = 1;
private static final int USER_LEFT_CHROME_DURING_RESTORE = 2;
private static final int USER_ACTION_DURING_RESTORE_MAX = 3;
// Id of the active tab being restored. Equals -1 when the active tab is not being restored.
private int mRestoredTabId = -1;
// Timestamp of the beginning of the most recent tab restore.
private long mRestoreStartedAtMsec = -1;
TabModelSelectorUma(Activity activity) {
ApplicationStatus.registerStateListenerForActivity(this, activity);
}
/**
* Cleans up any external dependencies of this class.
*/
public void destroy() {
ApplicationStatus.unregisterActivityStateListener(this);
}
@Override
public void onActivityStateChange(Activity activity, int newState) {
if (newState != ActivityState.STOPPED) return;
if (mRestoredTabId != -1) {
recordUserActionDuringTabRestore(USER_LEFT_CHROME_DURING_RESTORE);
mRestoredTabId = -1;
}
}
void userSwitchedToTab() {
RecordUserAction.record("MobileTabSwitched");
}
void onShowTab(int tabId, boolean isBeingRestored) {
if (mRestoredTabId != -1 && tabId != mRestoredTabId) {
recordUserActionDuringTabRestore(USER_LEFT_TAB_DURING_RESTORE);
mRestoredTabId = -1;
}
if (isBeingRestored) {
mRestoredTabId = tabId;
mRestoreStartedAtMsec = nowMsec();
}
}
void onTabClosing(int tabId) {
if (mRestoredTabId != -1 && tabId == mRestoredTabId) {
recordUserActionDuringTabRestore(USER_LEFT_TAB_DURING_RESTORE);
mRestoredTabId = -1;
}
}
void onTabCrashed(int tabId) {
if (mRestoredTabId != -1 && tabId == mRestoredTabId) {
mRestoredTabId = -1;
}
}
void onPageLoadFinished(int tabId) {
if (mRestoredTabId != -1 && tabId == mRestoredTabId) {
recordUserActionDuringTabRestore(USER_WAITED_FOR_RESTORE_COMPLETION);
mRestoredTabId = -1;
}
}
void onPageLoadFailed(int tabId) {
if (mRestoredTabId != -1 && tabId == mRestoredTabId) {
assert mRestoreStartedAtMsec != -1;
// If the pageload fails very quickly we cannot argue that the user "waited for
// completion".
if (nowMsec() - mRestoreStartedAtMsec >= 5000) {
recordUserActionDuringTabRestore(USER_WAITED_FOR_RESTORE_COMPLETION);
}
mRestoredTabId = -1;
}
}
void onTabsViewShown() {
if (mRestoredTabId != -1) {
recordUserActionDuringTabRestore(USER_LEFT_TAB_DURING_RESTORE);
mRestoredTabId = -1;
}
}
private static long nowMsec() {
return SystemClock.elapsedRealtime();
}
/**
* Logs action to a UMA histogram.
*/
private void recordUserActionDuringTabRestore(int action) {
assert action >= 0 && action < USER_ACTION_DURING_RESTORE_MAX;
RecordHistogram.recordEnumeratedHistogram(
"Tab.RestoreUserPersistence", action, USER_ACTION_DURING_RESTORE_MAX);
}
}