OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser; | 5 package org.chromium.chrome.browser; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.app.ActivityManager; | 8 import android.app.ActivityManager; |
9 import android.content.Context; | 9 import android.content.Context; |
10 import android.content.Intent; | 10 import android.content.Intent; |
11 import android.graphics.Color; | 11 import android.graphics.Color; |
12 import android.net.Uri; | 12 import android.net.Uri; |
13 import android.os.Build; | 13 import android.os.Build; |
14 import android.os.Bundle; | 14 import android.os.Bundle; |
15 import android.os.SystemClock; | 15 import android.os.SystemClock; |
16 import android.provider.Browser; | 16 import android.provider.Browser; |
| 17 import android.support.annotation.IntDef; |
17 import android.support.annotation.Nullable; | 18 import android.support.annotation.Nullable; |
18 import android.text.TextUtils; | 19 import android.text.TextUtils; |
19 import android.view.KeyEvent; | 20 import android.view.KeyEvent; |
20 import android.view.View; | 21 import android.view.View; |
21 import android.view.View.OnClickListener; | 22 import android.view.View.OnClickListener; |
22 import android.view.ViewGroup; | 23 import android.view.ViewGroup; |
23 import android.view.Window; | 24 import android.view.Window; |
24 import android.view.WindowManager; | 25 import android.view.WindowManager; |
25 import android.widget.FrameLayout; | 26 import android.widget.FrameLayout; |
26 | 27 |
(...skipping 26 matching lines...) Expand all Loading... |
53 import org.chromium.chrome.browser.cookies.CookiesFetcher; | 54 import org.chromium.chrome.browser.cookies.CookiesFetcher; |
54 import org.chromium.chrome.browser.customtabs.CustomTabActivity; | 55 import org.chromium.chrome.browser.customtabs.CustomTabActivity; |
55 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; | 56 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; |
56 import org.chromium.chrome.browser.device.DeviceClassManager; | 57 import org.chromium.chrome.browser.device.DeviceClassManager; |
57 import org.chromium.chrome.browser.document.ChromeLauncherActivity; | 58 import org.chromium.chrome.browser.document.ChromeLauncherActivity; |
58 import org.chromium.chrome.browser.document.DocumentUma; | 59 import org.chromium.chrome.browser.document.DocumentUma; |
59 import org.chromium.chrome.browser.firstrun.FirstRunActivity; | 60 import org.chromium.chrome.browser.firstrun.FirstRunActivity; |
60 import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer; | 61 import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer; |
61 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; | 62 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; |
62 import org.chromium.chrome.browser.firstrun.FirstRunStatus; | 63 import org.chromium.chrome.browser.firstrun.FirstRunStatus; |
| 64 import org.chromium.chrome.browser.metrics.ActivityStopMetrics; |
63 import org.chromium.chrome.browser.metrics.LaunchMetrics; | 65 import org.chromium.chrome.browser.metrics.LaunchMetrics; |
64 import org.chromium.chrome.browser.metrics.StartupMetrics; | 66 import org.chromium.chrome.browser.metrics.StartupMetrics; |
65 import org.chromium.chrome.browser.metrics.UmaUtils; | 67 import org.chromium.chrome.browser.metrics.UmaUtils; |
66 import org.chromium.chrome.browser.ntp.NativePageAssassin; | 68 import org.chromium.chrome.browser.ntp.NativePageAssassin; |
67 import org.chromium.chrome.browser.omaha.OmahaClient; | 69 import org.chromium.chrome.browser.omaha.OmahaClient; |
68 import org.chromium.chrome.browser.omnibox.AutocompleteController; | 70 import org.chromium.chrome.browser.omnibox.AutocompleteController; |
69 import org.chromium.chrome.browser.partnercustomizations.HomepageManager; | 71 import org.chromium.chrome.browser.partnercustomizations.HomepageManager; |
70 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomiza
tions; | 72 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomiza
tions; |
71 import org.chromium.chrome.browser.preferences.ChromePreferenceManager; | 73 import org.chromium.chrome.browser.preferences.ChromePreferenceManager; |
72 import org.chromium.chrome.browser.preferences.ConnectionChangeReceiver; | 74 import org.chromium.chrome.browser.preferences.ConnectionChangeReceiver; |
(...skipping 19 matching lines...) Expand all Loading... |
92 import org.chromium.chrome.browser.widget.findinpage.FindToolbarManager; | 94 import org.chromium.chrome.browser.widget.findinpage.FindToolbarManager; |
93 import org.chromium.content.browser.ContentVideoView; | 95 import org.chromium.content.browser.ContentVideoView; |
94 import org.chromium.content.browser.ContentViewCore; | 96 import org.chromium.content.browser.ContentViewCore; |
95 import org.chromium.content.browser.crypto.CipherFactory; | 97 import org.chromium.content.browser.crypto.CipherFactory; |
96 import org.chromium.content.common.ContentSwitches; | 98 import org.chromium.content.common.ContentSwitches; |
97 import org.chromium.content_public.browser.LoadUrlParams; | 99 import org.chromium.content_public.browser.LoadUrlParams; |
98 import org.chromium.ui.base.DeviceFormFactor; | 100 import org.chromium.ui.base.DeviceFormFactor; |
99 import org.chromium.ui.base.PageTransition; | 101 import org.chromium.ui.base.PageTransition; |
100 import org.chromium.ui.widget.Toast; | 102 import org.chromium.ui.widget.Toast; |
101 | 103 |
| 104 import java.lang.annotation.Retention; |
| 105 import java.lang.annotation.RetentionPolicy; |
| 106 |
102 /** | 107 /** |
103 * This is the main activity for ChromeMobile when not running in document mode.
All the tabs | 108 * This is the main activity for ChromeMobile when not running in document mode.
All the tabs |
104 * are accessible via a chrome specific tab switching UI. | 109 * are accessible via a chrome specific tab switching UI. |
105 */ | 110 */ |
106 public class ChromeTabbedActivity extends ChromeActivity implements OverviewMode
Observer { | 111 public class ChromeTabbedActivity extends ChromeActivity implements OverviewMode
Observer { |
107 | 112 |
108 private static final int FIRST_RUN_EXPERIENCE_RESULT = 101; | 113 private static final int FIRST_RUN_EXPERIENCE_RESULT = 101; |
109 private static final int CCT_RESULT = 102; | 114 private static final int CCT_RESULT = 102; |
110 | 115 |
| 116 @Retention(RetentionPolicy.SOURCE) |
| 117 @IntDef({ |
| 118 BACK_PRESSED_NOTHING_HAPPENED, |
| 119 BACK_PRESSED_HELP_URL_CLOSED, |
| 120 BACK_PRESSED_MINIMIZED_NO_TAB_CLOSED, |
| 121 BACK_PRESSED_MINIMIZED_TAB_CLOSED, |
| 122 BACK_PRESSED_TAB_CLOSED, |
| 123 BACK_PRESSED_TAB_IS_NULL, |
| 124 BACK_PRESSED_EXITED_TAB_SWITCHER, |
| 125 BACK_PRESSED_EXITED_FULLSCREEN, |
| 126 BACK_PRESSED_NAVIGATED_BACK |
| 127 }) |
| 128 private @interface BackPressedResult {} |
| 129 private static final int BACK_PRESSED_NOTHING_HAPPENED = 0; |
| 130 private static final int BACK_PRESSED_HELP_URL_CLOSED = 1; |
| 131 private static final int BACK_PRESSED_MINIMIZED_NO_TAB_CLOSED = 2; |
| 132 private static final int BACK_PRESSED_MINIMIZED_TAB_CLOSED = 3; |
| 133 private static final int BACK_PRESSED_TAB_CLOSED = 4; |
| 134 private static final int BACK_PRESSED_TAB_IS_NULL = 5; |
| 135 private static final int BACK_PRESSED_EXITED_TAB_SWITCHER = 6; |
| 136 private static final int BACK_PRESSED_EXITED_FULLSCREEN = 7; |
| 137 private static final int BACK_PRESSED_NAVIGATED_BACK = 8; |
| 138 private static final int BACK_PRESSED_COUNT = 9; |
| 139 |
111 private static final String TAG = "ChromeTabbedActivity"; | 140 private static final String TAG = "ChromeTabbedActivity"; |
112 | 141 |
113 private static final String HELP_URL_PREFIX = "https://support.google.com/ch
rome/"; | 142 private static final String HELP_URL_PREFIX = "https://support.google.com/ch
rome/"; |
114 | 143 |
115 private static final String FRE_RUNNING = "First run is running"; | 144 private static final String FRE_RUNNING = "First run is running"; |
116 | 145 |
117 private static final String WINDOW_INDEX = "window_index"; | 146 private static final String WINDOW_INDEX = "window_index"; |
118 | 147 |
119 // How long to delay closing the current tab when our app is minimized. Hav
e to delay this | 148 // How long to delay closing the current tab when our app is minimized. Hav
e to delay this |
120 // so that we don't show the contents of the next tab while minimizing. | 149 // so that we don't show the contents of the next tab while minimizing. |
(...skipping 11 matching lines...) Expand all Loading... |
132 public static final String INTENT_EXTRA_TEST_RENDER_PROCESS_LIMIT = "render_
process_limit"; | 161 public static final String INTENT_EXTRA_TEST_RENDER_PROCESS_LIMIT = "render_
process_limit"; |
133 | 162 |
134 /** | 163 /** |
135 * Sending an intent with this action to Chrome will cause it to close all t
abs | 164 * Sending an intent with this action to Chrome will cause it to close all t
abs |
136 * (iff the --enable-test-intents command line flag is set). If a URL is sup
plied in the | 165 * (iff the --enable-test-intents command line flag is set). If a URL is sup
plied in the |
137 * intent data, this will be loaded and unaffected by the close all action. | 166 * intent data, this will be loaded and unaffected by the close all action. |
138 */ | 167 */ |
139 private static final String ACTION_CLOSE_TABS = | 168 private static final String ACTION_CLOSE_TABS = |
140 "com.google.android.apps.chrome.ACTION_CLOSE_TABS"; | 169 "com.google.android.apps.chrome.ACTION_CLOSE_TABS"; |
141 | 170 |
| 171 private final ActivityStopMetrics mActivityStopMetrics = |
| 172 new ActivityStopMetrics("Android.Activity.ChromeTabbedActivity.StopR
eason"); |
| 173 |
142 private FindToolbarManager mFindToolbarManager; | 174 private FindToolbarManager mFindToolbarManager; |
143 | 175 |
144 private UndoBarPopupController mUndoBarPopupController; | 176 private UndoBarPopupController mUndoBarPopupController; |
145 | 177 |
146 private LayoutManagerChrome mLayoutManager; | 178 private LayoutManagerChrome mLayoutManager; |
147 | 179 |
148 private ViewGroup mContentContainer; | 180 private ViewGroup mContentContainer; |
149 | 181 |
150 private ToolbarControlContainer mControlContainer; | 182 private ToolbarControlContainer mControlContainer; |
151 | 183 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 | 347 |
316 if (getActivityTab() != null) getActivityTab().setIsAllowedToReturnToExt
ernalApp(false); | 348 if (getActivityTab() != null) getActivityTab().setIsAllowedToReturnToExt
ernalApp(false); |
317 | 349 |
318 mTabModelSelectorImpl.saveState(); | 350 mTabModelSelectorImpl.saveState(); |
319 try { | 351 try { |
320 getConnectionChangeReceiver().unregisterReceiver(ChromeTabbedActivit
y.this); | 352 getConnectionChangeReceiver().unregisterReceiver(ChromeTabbedActivit
y.this); |
321 } catch (IllegalArgumentException e) { | 353 } catch (IllegalArgumentException e) { |
322 // This may happen when onStop get called very early in UI test. | 354 // This may happen when onStop get called very early in UI test. |
323 } | 355 } |
324 StartupMetrics.getInstance().recordHistogram(true); | 356 StartupMetrics.getInstance().recordHistogram(true); |
| 357 mActivityStopMetrics.onStopWithNative(this); |
325 } | 358 } |
326 | 359 |
327 @Override | 360 @Override |
328 public void onStart() { | 361 public void onStart() { |
329 super.onStart(); | 362 super.onStart(); |
330 StartupMetrics.getInstance().updateIntent(getIntent()); | 363 StartupMetrics.getInstance().updateIntent(getIntent()); |
331 } | 364 } |
332 | 365 |
333 @Override | 366 @Override |
334 public void onStartWithNative() { | 367 public void onStartWithNative() { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 addOrEditBookmark(getActivityTab()); | 501 addOrEditBookmark(getActivityTab()); |
469 } | 502 } |
470 }; | 503 }; |
471 | 504 |
472 getToolbarManager().initializeWithNative(mTabModelSelectorImpl, getF
ullscreenManager(), | 505 getToolbarManager().initializeWithNative(mTabModelSelectorImpl, getF
ullscreenManager(), |
473 mFindToolbarManager, mLayoutManager, mLayoutManager, | 506 mFindToolbarManager, mLayoutManager, mLayoutManager, |
474 tabSwitcherClickHandler, newTabClickHandler, bookmarkClickHa
ndler, null); | 507 tabSwitcherClickHandler, newTabClickHandler, bookmarkClickHa
ndler, null); |
475 getToolbarManager().getToolbar().setReturnButtonListener(new OnClick
Listener() { | 508 getToolbarManager().getToolbar().setReturnButtonListener(new OnClick
Listener() { |
476 @Override | 509 @Override |
477 public void onClick(View v) { | 510 public void onClick(View v) { |
478 if (getActivityTab() != null) handleBackPressedWithoutBackSt
ack(true); | 511 if (getActivityTab() == null) return; |
| 512 mActivityStopMetrics.setStopReason( |
| 513 ActivityStopMetrics.STOP_REASON_RETURN_BUTTON); |
| 514 RecordUserAction.record("TaskManagement.ReturnButtonClicked"
); |
| 515 sendToBackground(getActivityTab()); |
479 } | 516 } |
480 }); | 517 }); |
481 | 518 |
482 removeWindowBackground(); | 519 removeWindowBackground(); |
483 | 520 |
484 if (isTablet()) { | 521 if (isTablet()) { |
485 EmptyBackgroundViewWrapper bgViewWrapper = new EmptyBackgroundVi
ewWrapper( | 522 EmptyBackgroundViewWrapper bgViewWrapper = new EmptyBackgroundVi
ewWrapper( |
486 getTabModelSelector(), getTabCreator(false), ChromeTabbe
dActivity.this, | 523 getTabModelSelector(), getTabCreator(false), ChromeTabbe
dActivity.this, |
487 getAppMenuHandler(), mLayoutManager); | 524 getAppMenuHandler(), mLayoutManager); |
488 bgViewWrapper.initialize(); | 525 bgViewWrapper.initialize(); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 // Open the last URL shown in the CustomTabActivity. Unfortunat
ely, there isn't a | 643 // Open the last URL shown in the CustomTabActivity. Unfortunat
ely, there isn't a |
607 // good TabLaunchType to use here (FROM_EXTERNAL_APP changes bac
k behavior, e.g.), | 644 // good TabLaunchType to use here (FROM_EXTERNAL_APP changes bac
k behavior, e.g.), |
608 // but this shouldn't be a problem once Tab reparenting lands. | 645 // but this shouldn't be a problem once Tab reparenting lands. |
609 // | 646 // |
610 // TODO(dfalcantara): Use real tab reparenting here when possibl
e. We should fall | 647 // TODO(dfalcantara): Use real tab reparenting here when possibl
e. We should fall |
611 // back to using the TabState file or URL, in
that order. | 648 // back to using the TabState file or URL, in
that order. |
612 getTabCreator(false).createNewTab(new LoadUrlParams( | 649 getTabCreator(false).createNewTab(new LoadUrlParams( |
613 data.getDataString()), TabLaunchType.FROM_CHROME_UI, nul
l); | 650 data.getDataString()), TabLaunchType.FROM_CHROME_UI, nul
l); |
614 } else if ((resultCode == CustomTabActivity.RESULT_BACK_PRESSED | 651 } else if ((resultCode == CustomTabActivity.RESULT_BACK_PRESSED |
615 || resultCode == CustomTabActivity.RESULT_CLOSED) && data !=
null) { | 652 || resultCode == CustomTabActivity.RESULT_CLOSED) && data !=
null) { |
| 653 // Herb UMA should have already been recorded by the CustomTabAc
tivity. |
616 Log.d(TAG, "Herb: Sending app to the background"); | 654 Log.d(TAG, "Herb: Sending app to the background"); |
| 655 mActivityStopMetrics.setStopReason( |
| 656 ActivityStopMetrics.STOP_REASON_CUSTOM_TAB_STOPPED); |
617 sendToBackground(null); | 657 sendToBackground(null); |
618 } | 658 } |
619 return true; | 659 return true; |
620 } | 660 } |
621 return false; | 661 return false; |
622 } | 662 } |
623 | 663 |
624 @Override | 664 @Override |
625 public void onAccessibilityModeChanged(boolean enabled) { | 665 public void onAccessibilityModeChanged(boolean enabled) { |
626 super.onAccessibilityModeChanged(enabled); | 666 super.onAccessibilityModeChanged(enabled); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 private void openNewTab(String url, String referer, String headers, | 803 private void openNewTab(String url, String referer, String headers, |
764 String externalAppId, Intent intent, boolean forceNewTab) { | 804 String externalAppId, Intent intent, boolean forceNewTab) { |
765 boolean isAllowedToReturnToExternalApp = IntentUtils.safeGetBooleanE
xtra(intent, | 805 boolean isAllowedToReturnToExternalApp = IntentUtils.safeGetBooleanE
xtra(intent, |
766 ChromeLauncherActivity.EXTRA_IS_ALLOWED_TO_RETURN_TO_PARENT,
true); | 806 ChromeLauncherActivity.EXTRA_IS_ALLOWED_TO_RETURN_TO_PARENT,
true); |
767 | 807 |
768 String herbFlavor = FeatureUtilities.getHerbFlavor(); | 808 String herbFlavor = FeatureUtilities.getHerbFlavor(); |
769 if (isAllowedToReturnToExternalApp | 809 if (isAllowedToReturnToExternalApp |
770 && ChromeLauncherActivity.canBeHijackedByHerb(intent) | 810 && ChromeLauncherActivity.canBeHijackedByHerb(intent) |
771 && TextUtils.equals(ChromeSwitches.HERB_FLAVOR_DILL, herbFla
vor)) { | 811 && TextUtils.equals(ChromeSwitches.HERB_FLAVOR_DILL, herbFla
vor)) { |
772 Log.d(TAG, "Sending to CustomTabActivity"); | 812 Log.d(TAG, "Sending to CustomTabActivity"); |
| 813 mActivityStopMetrics.setStopReason( |
| 814 ActivityStopMetrics.STOP_REASON_CUSTOM_TAB_STARTED); |
773 | 815 |
774 Intent newIntent = ChromeLauncherActivity.createCustomTabActivit
yIntent( | 816 Intent newIntent = ChromeLauncherActivity.createCustomTabActivit
yIntent( |
775 ChromeTabbedActivity.this, intent, false); | 817 ChromeTabbedActivity.this, intent, false); |
776 newIntent.putExtra(Browser.EXTRA_APPLICATION_ID, getPackageName(
)); | 818 newIntent.putExtra(Browser.EXTRA_APPLICATION_ID, getPackageName(
)); |
777 newIntent.putExtra( | 819 newIntent.putExtra( |
778 CustomTabIntentDataProvider.EXTRA_OPENED_BY_BROWSER, tru
e); | 820 CustomTabIntentDataProvider.EXTRA_OPENED_BY_BROWSER, tru
e); |
779 ChromeLauncherActivity.addHerbIntentExtras(ChromeTabbedActivity.
this, | 821 ChromeLauncherActivity.addHerbIntentExtras(ChromeTabbedActivity.
this, |
780 newIntent, Uri.parse(IntentHandler.getUrlFromIntent(newI
ntent))); | 822 newIntent, Uri.parse(IntentHandler.getUrlFromIntent(newI
ntent))); |
781 | 823 |
782 // Launch the Activity on top of this task. | 824 // Launch the Activity on top of this task. |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1030 && (!isTablet() || getCurrentTabModel().getCount() != 0); | 1072 && (!isTablet() || getCurrentTabModel().getCount() != 0); |
1031 if (isUrlBarVisible) { | 1073 if (isUrlBarVisible) { |
1032 getToolbarManager().setUrlBarFocus(true); | 1074 getToolbarManager().setUrlBarFocus(true); |
1033 } | 1075 } |
1034 } else { | 1076 } else { |
1035 return super.onMenuOrKeyboardAction(id, fromMenu); | 1077 return super.onMenuOrKeyboardAction(id, fromMenu); |
1036 } | 1078 } |
1037 return true; | 1079 return true; |
1038 } | 1080 } |
1039 | 1081 |
| 1082 private void recordBackPressedUma(String logMessage, @BackPressedResult int
action) { |
| 1083 Log.i(TAG, "Back pressed: " + logMessage); |
| 1084 RecordHistogram.recordEnumeratedHistogram( |
| 1085 "Android.Activity.ChromeTabbedActivity.SystemBackAction", |
| 1086 action, BACK_PRESSED_COUNT); |
| 1087 } |
| 1088 |
1040 @Override | 1089 @Override |
1041 public boolean handleBackPressed() { | 1090 public boolean handleBackPressed() { |
| 1091 RecordUserAction.record("SystemBack"); |
| 1092 |
1042 if (!mUIInitialized) return false; | 1093 if (!mUIInitialized) return false; |
1043 final Tab currentTab = getActivityTab(); | 1094 final Tab currentTab = getActivityTab(); |
1044 | 1095 |
1045 if (currentTab == null) { | 1096 if (currentTab == null) { |
1046 if (getToolbarManager().back()) { | 1097 recordBackPressedUma("currentTab is null", BACK_PRESSED_TAB_IS_NULL)
; |
1047 RecordUserAction.record("SystemBackForNavigation"); | 1098 moveTaskToBack(true); |
1048 RecordUserAction.record("MobileTabClobbered"); | |
1049 } else { | |
1050 moveTaskToBack(true); | |
1051 } | |
1052 RecordUserAction.record("SystemBack"); | |
1053 Log.i(TAG, "handleBackPressed() - currentTab is null"); | |
1054 return true; | 1099 return true; |
1055 } | 1100 } |
1056 | 1101 |
1057 // If we are in overview mode and not a tablet, then leave overview mode
on back. | 1102 // If we are in overview mode and not a tablet, then leave overview mode
on back. |
1058 if (mLayoutManager.overviewVisible() && !isTablet()) { | 1103 if (mLayoutManager.overviewVisible() && !isTablet()) { |
| 1104 recordBackPressedUma("Hid overview", BACK_PRESSED_EXITED_TAB_SWITCHE
R); |
1059 mLayoutManager.hideOverview(true); | 1105 mLayoutManager.hideOverview(true); |
1060 // TODO(benm): Record any user metrics in this case? | |
1061 Log.i(TAG, "handleBackPressed() - hide overview"); | |
1062 return true; | 1106 return true; |
1063 } | 1107 } |
1064 | 1108 |
1065 if (exitFullscreenIfShowing()) { | 1109 if (exitFullscreenIfShowing()) { |
1066 Log.i(TAG, "handleBackPressed() - exit fullscreen"); | 1110 recordBackPressedUma("Exited fullscreen", BACK_PRESSED_EXITED_FULLSC
REEN); |
1067 return true; | 1111 return true; |
1068 } | 1112 } |
1069 | 1113 |
1070 if (!getToolbarManager().back()) { | 1114 if (getToolbarManager().back()) { |
1071 Log.i(TAG, "handleBackPressed() - no back stack"); | 1115 recordBackPressedUma("Navigating backward", BACK_PRESSED_NAVIGATED_B
ACK); |
1072 if (handleBackPressedWithoutBackStack(false)) return true; | |
1073 } else { | |
1074 Log.i(TAG, "handleBackPressed() - moving back in navigation"); | |
1075 RecordUserAction.record("SystemBackForNavigation"); | 1116 RecordUserAction.record("SystemBackForNavigation"); |
1076 RecordUserAction.record("MobileTabClobbered"); | 1117 RecordUserAction.record("MobileTabClobbered"); |
| 1118 return true; |
1077 } | 1119 } |
1078 RecordUserAction.record("SystemBack"); | |
1079 | |
1080 return true; | |
1081 } | |
1082 | |
1083 /** | |
1084 * Additional logic for handling situations where a user hits a 'back' or 'r
eturn' button. | |
1085 * | |
1086 * May result in closing the foreground tab or returning to the app that ope
ned Chrome. | |
1087 * | |
1088 * @param alwaysAllowTabClosure Setting this to true always allows a tab ope
ned by an external | |
1089 * app to be closed. | |
1090 * @return Whether the tab closed was opened for a help page. | |
1091 */ | |
1092 private boolean handleBackPressedWithoutBackStack(boolean alwaysAllowTabClos
ure) { | |
1093 final Tab currentTab = getActivityTab(); | |
1094 final TabLaunchType type = currentTab.getLaunchType(); | |
1095 final int parentId = currentTab.getParentId(); | |
1096 final boolean helpUrl = currentTab.getUrl().startsWith(HELP_URL_PREFIX); | |
1097 | 1120 |
1098 // If the current tab url is HELP_URL, then the back button should close
the tab to | 1121 // If the current tab url is HELP_URL, then the back button should close
the tab to |
1099 // get back to the previous state. The reason for startsWith check is th
at the | 1122 // get back to the previous state. The reason for startsWith check is th
at the |
1100 // actual redirected URL is a different system language based help url. | 1123 // actual redirected URL is a different system language based help url. |
| 1124 final TabLaunchType type = currentTab.getLaunchType(); |
| 1125 final boolean helpUrl = currentTab.getUrl().startsWith(HELP_URL_PREFIX); |
1101 if (type == TabLaunchType.FROM_CHROME_UI && helpUrl) { | 1126 if (type == TabLaunchType.FROM_CHROME_UI && helpUrl) { |
1102 getCurrentTabModel().closeTab(currentTab); | 1127 getCurrentTabModel().closeTab(currentTab); |
1103 Log.i(TAG, "handleBackPressedWithoutBackStack() - help url"); | 1128 recordBackPressedUma("Closed tab for help URL", BACK_PRESSED_HELP_UR
L_CLOSED); |
1104 return true; | 1129 return true; |
1105 } | 1130 } |
1106 | 1131 |
1107 // Herb: Current spec says that tabs are closed only when there is NO "X
" visible, i.e. when | 1132 // The current spec says that tabs are closed only when there is NO "X"
visible, i.e. when |
1108 // the tab is NOT allowed to return to the external app. | 1133 // the tab is NOT allowed to return to the external app. |
1109 boolean isAllowedToCloseTab = true; | 1134 boolean isAllowedToCloseTab = true; |
1110 if (alwaysAllowTabClosure) { | 1135 String herbFlavor = FeatureUtilities.getHerbFlavor(); |
1111 isAllowedToCloseTab = true; | 1136 if (TextUtils.equals(ChromeSwitches.HERB_FLAVOR_BASIL, herbFlavor) |
1112 } else { | 1137 || TextUtils.equals(ChromeSwitches.HERB_FLAVOR_CHIVE, herbFlavor
)) { |
1113 String herbFlavor = FeatureUtilities.getHerbFlavor(); | 1138 isAllowedToCloseTab = !currentTab.isAllowedToReturnToExternalApp(); |
1114 if (TextUtils.equals(ChromeSwitches.HERB_FLAVOR_BASIL, herbFlavor) | |
1115 || TextUtils.equals(ChromeSwitches.HERB_FLAVOR_CHIVE, herbFl
avor)) { | |
1116 isAllowedToCloseTab = !currentTab.isAllowedToReturnToExternalApp
(); | |
1117 } | |
1118 } | 1139 } |
1119 | 1140 |
1120 // [true]: Reached the bottom of the back stack on a tab the user did no
t explicitly | 1141 // [true]: Reached the bottom of the back stack on a tab the user did no
t explicitly |
1121 // create (i.e. it was created by an external app or opening a link in b
ackground, etc). | 1142 // create (i.e. it was created by an external app or opening a link in b
ackground, etc). |
1122 // [false]: Reached the bottom of the back stack on a tab that the user
explicitly | 1143 // [false]: Reached the bottom of the back stack on a tab that the user
explicitly |
1123 // created (e.g. selecting "new tab" from menu). | 1144 // created (e.g. selecting "new tab" from menu). |
| 1145 final int parentId = currentTab.getParentId(); |
1124 final boolean shouldCloseTab = type == TabLaunchType.FROM_LINK | 1146 final boolean shouldCloseTab = type == TabLaunchType.FROM_LINK |
1125 || (type == TabLaunchType.FROM_EXTERNAL_APP && isAllowedToCloseT
ab) | 1147 || (type == TabLaunchType.FROM_EXTERNAL_APP && isAllowedToCloseT
ab) |
1126 || type == TabLaunchType.FROM_LONGPRESS_FOREGROUND | 1148 || type == TabLaunchType.FROM_LONGPRESS_FOREGROUND |
1127 || type == TabLaunchType.FROM_LONGPRESS_BACKGROUND | 1149 || type == TabLaunchType.FROM_LONGPRESS_BACKGROUND |
1128 || (type == TabLaunchType.FROM_RESTORE && parentId != Tab.INVALI
D_TAB_ID); | 1150 || (type == TabLaunchType.FROM_RESTORE && parentId != Tab.INVALI
D_TAB_ID); |
1129 | 1151 |
1130 // Minimize the app if either: | 1152 // Minimize the app if either: |
1131 // - we decided not to close the tab | 1153 // - we decided not to close the tab |
1132 // - we decided to close the tab, but it was opened by an external app,
so we will go | 1154 // - we decided to close the tab, but it was opened by an external app,
so we will go |
1133 // exit Chrome on top of closing the tab | 1155 // exit Chrome on top of closing the tab |
1134 final boolean minimizeApp = !shouldCloseTab || currentTab.isCreatedForEx
ternalApp(); | 1156 final boolean minimizeApp = !shouldCloseTab || currentTab.isCreatedForEx
ternalApp(); |
1135 | 1157 |
1136 if (minimizeApp) { | 1158 if (minimizeApp) { |
1137 sendToBackground(shouldCloseTab ? currentTab : null); | 1159 if (shouldCloseTab) { |
| 1160 recordBackPressedUma("Minimized and closed tab", BACK_PRESSED_MI
NIMIZED_TAB_CLOSED); |
| 1161 mActivityStopMetrics.setStopReason(ActivityStopMetrics.STOP_REAS
ON_BACK_BUTTON); |
| 1162 sendToBackground(currentTab); |
| 1163 return true; |
| 1164 } else { |
| 1165 recordBackPressedUma("Minimized, kept tab", BACK_PRESSED_MINIMIZ
ED_NO_TAB_CLOSED); |
| 1166 mActivityStopMetrics.setStopReason(ActivityStopMetrics.STOP_REAS
ON_BACK_BUTTON); |
| 1167 sendToBackground(null); |
| 1168 return true; |
| 1169 } |
1138 } else if (shouldCloseTab) { | 1170 } else if (shouldCloseTab) { |
| 1171 recordBackPressedUma("Tab closed", BACK_PRESSED_TAB_CLOSED); |
1139 getCurrentTabModel().closeTab(currentTab, true, false, false); | 1172 getCurrentTabModel().closeTab(currentTab, true, false, false); |
| 1173 return true; |
1140 } | 1174 } |
| 1175 |
| 1176 assert false : "The back button should have already been handled by this
point"; |
| 1177 recordBackPressedUma("Unhandled", BACK_PRESSED_NOTHING_HAPPENED); |
1141 return false; | 1178 return false; |
1142 } | 1179 } |
1143 | 1180 |
1144 /** | 1181 /** |
1145 * Sends this Activity to the background. | 1182 * Sends this Activity to the background. |
1146 * | 1183 * |
1147 * @param tabToClose Tab that will be closed once the app is not visible. | 1184 * @param tabToClose Tab that will be closed once the app is not visible. |
1148 */ | 1185 */ |
1149 private void sendToBackground(@Nullable final Tab tabToClose) { | 1186 private void sendToBackground(@Nullable final Tab tabToClose) { |
1150 Log.i(TAG, "sendToBackground(): " + tabToClose); | 1187 Log.i(TAG, "sendToBackground(): " + tabToClose); |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1383 if (getActivityTab() != null) { | 1420 if (getActivityTab() != null) { |
1384 setStatusBarColor(getActivityTab(), getActivityTab().getThemeColor()
); | 1421 setStatusBarColor(getActivityTab(), getActivityTab().getThemeColor()
); |
1385 } | 1422 } |
1386 } | 1423 } |
1387 | 1424 |
1388 @Override | 1425 @Override |
1389 protected void setStatusBarColor(Tab tab, int color) { | 1426 protected void setStatusBarColor(Tab tab, int color) { |
1390 super.setStatusBarColor(tab, isInOverviewMode() ? Color.BLACK : color); | 1427 super.setStatusBarColor(tab, isInOverviewMode() ? Color.BLACK : color); |
1391 } | 1428 } |
1392 } | 1429 } |
OLD | NEW |