Index: chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java |
index 174fe57208416eb277155a98bf729f609075da52..3d354275010133f80fd8e213ff63031599b39ab4 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java |
@@ -14,6 +14,7 @@ import android.os.Build; |
import android.os.Bundle; |
import android.os.SystemClock; |
import android.provider.Browser; |
+import android.support.annotation.IntDef; |
import android.support.annotation.Nullable; |
import android.text.TextUtils; |
import android.view.KeyEvent; |
@@ -60,6 +61,7 @@ import org.chromium.chrome.browser.firstrun.FirstRunActivity; |
import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer; |
import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; |
import org.chromium.chrome.browser.firstrun.FirstRunStatus; |
+import org.chromium.chrome.browser.metrics.ActivityStopMetrics; |
import org.chromium.chrome.browser.metrics.LaunchMetrics; |
import org.chromium.chrome.browser.metrics.StartupMetrics; |
import org.chromium.chrome.browser.metrics.UmaUtils; |
@@ -99,6 +101,9 @@ import org.chromium.ui.base.DeviceFormFactor; |
import org.chromium.ui.base.PageTransition; |
import org.chromium.ui.widget.Toast; |
+import java.lang.annotation.Retention; |
+import java.lang.annotation.RetentionPolicy; |
+ |
/** |
* This is the main activity for ChromeMobile when not running in document mode. All the tabs |
* are accessible via a chrome specific tab switching UI. |
@@ -108,6 +113,30 @@ public class ChromeTabbedActivity extends ChromeActivity implements OverviewMode |
private static final int FIRST_RUN_EXPERIENCE_RESULT = 101; |
private static final int CCT_RESULT = 102; |
+ @Retention(RetentionPolicy.SOURCE) |
+ @IntDef({ |
+ BACK_PRESSED_NOTHING_HAPPENED, |
+ BACK_PRESSED_HELP_URL_CLOSED, |
+ BACK_PRESSED_MINIMIZED_NO_TAB_CLOSED, |
+ BACK_PRESSED_MINIMIZED_TAB_CLOSED, |
+ BACK_PRESSED_TAB_CLOSED, |
+ BACK_PRESSED_TAB_IS_NULL, |
+ BACK_PRESSED_EXITED_TAB_SWITCHER, |
+ BACK_PRESSED_EXITED_FULLSCREEN, |
+ BACK_PRESSED_NAVIGATED_BACK |
+ }) |
+ private @interface BackPressedResult {} |
+ private static final int BACK_PRESSED_NOTHING_HAPPENED = 0; |
+ private static final int BACK_PRESSED_HELP_URL_CLOSED = 1; |
+ private static final int BACK_PRESSED_MINIMIZED_NO_TAB_CLOSED = 2; |
+ private static final int BACK_PRESSED_MINIMIZED_TAB_CLOSED = 3; |
+ private static final int BACK_PRESSED_TAB_CLOSED = 4; |
+ private static final int BACK_PRESSED_TAB_IS_NULL = 5; |
+ private static final int BACK_PRESSED_EXITED_TAB_SWITCHER = 6; |
+ private static final int BACK_PRESSED_EXITED_FULLSCREEN = 7; |
+ private static final int BACK_PRESSED_NAVIGATED_BACK = 8; |
+ private static final int BACK_PRESSED_COUNT = 9; |
+ |
private static final String TAG = "ChromeTabbedActivity"; |
private static final String HELP_URL_PREFIX = "https://support.google.com/chrome/"; |
@@ -139,6 +168,8 @@ public class ChromeTabbedActivity extends ChromeActivity implements OverviewMode |
private static final String ACTION_CLOSE_TABS = |
"com.google.android.apps.chrome.ACTION_CLOSE_TABS"; |
+ private final ActivityStopMetrics mActivityStopMetrics = new ActivityStopMetrics(); |
+ |
private FindToolbarManager mFindToolbarManager; |
private UndoBarPopupController mUndoBarPopupController; |
@@ -322,6 +353,7 @@ public class ChromeTabbedActivity extends ChromeActivity implements OverviewMode |
// This may happen when onStop get called very early in UI test. |
} |
StartupMetrics.getInstance().recordHistogram(true); |
+ mActivityStopMetrics.onStopWithNative(this); |
} |
@Override |
@@ -475,7 +507,11 @@ public class ChromeTabbedActivity extends ChromeActivity implements OverviewMode |
getToolbarManager().getToolbar().setReturnButtonListener(new OnClickListener() { |
@Override |
public void onClick(View v) { |
- if (getActivityTab() != null) handleBackPressedWithoutBackStack(true); |
+ if (getActivityTab() == null) return; |
+ mActivityStopMetrics.setStopReason( |
+ ActivityStopMetrics.STOP_REASON_RETURN_BUTTON); |
+ RecordUserAction.record("TaskManagement.ReturnButtonClicked"); |
+ sendToBackground(getActivityTab()); |
} |
}); |
@@ -613,7 +649,10 @@ public class ChromeTabbedActivity extends ChromeActivity implements OverviewMode |
data.getDataString()), TabLaunchType.FROM_CHROME_UI, null); |
} else if ((resultCode == CustomTabActivity.RESULT_BACK_PRESSED |
|| resultCode == CustomTabActivity.RESULT_CLOSED) && data != null) { |
+ // Herb UMA should have already been recorded by the CustomTabActivity. |
Log.d(TAG, "Herb: Sending app to the background"); |
+ mActivityStopMetrics.setStopReason( |
+ ActivityStopMetrics.STOP_REASON_CUSTOM_TAB_STOPPED); |
sendToBackground(null); |
} |
return true; |
@@ -770,6 +809,8 @@ public class ChromeTabbedActivity extends ChromeActivity implements OverviewMode |
&& ChromeLauncherActivity.canBeHijackedByHerb(intent) |
&& TextUtils.equals(ChromeSwitches.HERB_FLAVOR_DILL, herbFlavor)) { |
Log.d(TAG, "Sending to CustomTabActivity"); |
+ mActivityStopMetrics.setStopReason( |
+ ActivityStopMetrics.STOP_REASON_CUSTOM_TAB_STARTED); |
Intent newIntent = ChromeLauncherActivity.createCustomTabActivityIntent( |
ChromeTabbedActivity.this, intent, false); |
@@ -1037,90 +1078,69 @@ public class ChromeTabbedActivity extends ChromeActivity implements OverviewMode |
return true; |
} |
+ private void recordBackPressedUma(String logMessage, @BackPressedResult int action) { |
+ Log.i(TAG, "Back pressed: " + logMessage); |
+ RecordHistogram.recordEnumeratedHistogram( |
+ "Android.Activity.ChromeTabbedActivity.SystemBackAction", |
+ action, BACK_PRESSED_COUNT); |
+ } |
+ |
@Override |
public boolean handleBackPressed() { |
+ RecordUserAction.record("SystemBack"); |
+ |
if (!mUIInitialized) return false; |
final Tab currentTab = getActivityTab(); |
if (currentTab == null) { |
- if (getToolbarManager().back()) { |
- RecordUserAction.record("SystemBackForNavigation"); |
- RecordUserAction.record("MobileTabClobbered"); |
- } else { |
- moveTaskToBack(true); |
- } |
- RecordUserAction.record("SystemBack"); |
- Log.i(TAG, "handleBackPressed() - currentTab is null"); |
+ recordBackPressedUma("currentTab is null", BACK_PRESSED_TAB_IS_NULL); |
+ moveTaskToBack(true); |
return true; |
} |
// If we are in overview mode and not a tablet, then leave overview mode on back. |
if (mLayoutManager.overviewVisible() && !isTablet()) { |
+ recordBackPressedUma("Hid overview", BACK_PRESSED_EXITED_TAB_SWITCHER); |
mLayoutManager.hideOverview(true); |
- // TODO(benm): Record any user metrics in this case? |
- Log.i(TAG, "handleBackPressed() - hide overview"); |
return true; |
} |
if (exitFullscreenIfShowing()) { |
- Log.i(TAG, "handleBackPressed() - exit fullscreen"); |
+ recordBackPressedUma("Exited fullscreen", BACK_PRESSED_EXITED_FULLSCREEN); |
return true; |
} |
- if (!getToolbarManager().back()) { |
- Log.i(TAG, "handleBackPressed() - no back stack"); |
- if (handleBackPressedWithoutBackStack(false)) return true; |
- } else { |
- Log.i(TAG, "handleBackPressed() - moving back in navigation"); |
- RecordUserAction.record("SystemBackForNavigation"); |
+ if (getToolbarManager().back()) { |
+ recordBackPressedUma("Navigating backward", BACK_PRESSED_NAVIGATED_BACK); |
RecordUserAction.record("MobileTabClobbered"); |
+ return true; |
} |
- RecordUserAction.record("SystemBack"); |
- |
- return true; |
- } |
- |
- /** |
- * Additional logic for handling situations where a user hits a 'back' or 'return' button. |
- * |
- * May result in closing the foreground tab or returning to the app that opened Chrome. |
- * |
- * @param alwaysAllowTabClosure Setting this to true always allows a tab opened by an external |
- * app to be closed. |
- * @return Whether the tab closed was opened for a help page. |
- */ |
- private boolean handleBackPressedWithoutBackStack(boolean alwaysAllowTabClosure) { |
- final Tab currentTab = getActivityTab(); |
- final TabLaunchType type = currentTab.getLaunchType(); |
- final int parentId = currentTab.getParentId(); |
- final boolean helpUrl = currentTab.getUrl().startsWith(HELP_URL_PREFIX); |
// If the current tab url is HELP_URL, then the back button should close the tab to |
// get back to the previous state. The reason for startsWith check is that the |
// actual redirected URL is a different system language based help url. |
+ final TabLaunchType type = currentTab.getLaunchType(); |
+ final boolean helpUrl = currentTab.getUrl().startsWith(HELP_URL_PREFIX); |
if (type == TabLaunchType.FROM_CHROME_UI && helpUrl) { |
getCurrentTabModel().closeTab(currentTab); |
- Log.i(TAG, "handleBackPressedWithoutBackStack() - help url"); |
+ recordBackPressedUma("Closed tab for help URL", BACK_PRESSED_HELP_URL_CLOSED); |
return true; |
} |
- // Herb: Current spec says that tabs are closed only when there is NO "X" visible, i.e. when |
- // the tab is NOT allowed to return to the external app. |
+ // The current spec says that tabs are closed only when there is NO "X" visible, i.e. when |
+ // the tab is NOT allowed to return to the external app. |
boolean isAllowedToCloseTab = true; |
- if (alwaysAllowTabClosure) { |
- isAllowedToCloseTab = true; |
- } else { |
- String herbFlavor = FeatureUtilities.getHerbFlavor(); |
- if (TextUtils.equals(ChromeSwitches.HERB_FLAVOR_BASIL, herbFlavor) |
- || TextUtils.equals(ChromeSwitches.HERB_FLAVOR_CHIVE, herbFlavor)) { |
- isAllowedToCloseTab = !currentTab.isAllowedToReturnToExternalApp(); |
- } |
+ String herbFlavor = FeatureUtilities.getHerbFlavor(); |
+ if (TextUtils.equals(ChromeSwitches.HERB_FLAVOR_BASIL, herbFlavor) |
+ || TextUtils.equals(ChromeSwitches.HERB_FLAVOR_CHIVE, herbFlavor)) { |
+ isAllowedToCloseTab = !currentTab.isAllowedToReturnToExternalApp(); |
} |
// [true]: Reached the bottom of the back stack on a tab the user did not explicitly |
// create (i.e. it was created by an external app or opening a link in background, etc). |
// [false]: Reached the bottom of the back stack on a tab that the user explicitly |
// created (e.g. selecting "new tab" from menu). |
+ final int parentId = currentTab.getParentId(); |
final boolean shouldCloseTab = type == TabLaunchType.FROM_LINK |
|| (type == TabLaunchType.FROM_EXTERNAL_APP && isAllowedToCloseTab) |
|| type == TabLaunchType.FROM_LONGPRESS_FOREGROUND |
@@ -1134,10 +1154,25 @@ public class ChromeTabbedActivity extends ChromeActivity implements OverviewMode |
final boolean minimizeApp = !shouldCloseTab || currentTab.isCreatedForExternalApp(); |
if (minimizeApp) { |
- sendToBackground(shouldCloseTab ? currentTab : null); |
+ if (shouldCloseTab) { |
+ recordBackPressedUma("Minimized and closed tab", BACK_PRESSED_MINIMIZED_TAB_CLOSED); |
+ mActivityStopMetrics.setStopReason(ActivityStopMetrics.STOP_REASON_BACK_BUTTON); |
+ sendToBackground(currentTab); |
+ return true; |
+ } else { |
+ recordBackPressedUma("Minimized, kept tab", BACK_PRESSED_MINIMIZED_NO_TAB_CLOSED); |
+ mActivityStopMetrics.setStopReason(ActivityStopMetrics.STOP_REASON_BACK_BUTTON); |
+ sendToBackground(null); |
+ return true; |
+ } |
} else if (shouldCloseTab) { |
+ recordBackPressedUma("Tab closed", BACK_PRESSED_TAB_CLOSED); |
getCurrentTabModel().closeTab(currentTab, true, false, false); |
+ return true; |
} |
+ |
+ assert false : "The back button should have already been handled by this point"; |
+ recordBackPressedUma("Unhandled", BACK_PRESSED_NOTHING_HAPPENED); |
return false; |
} |