123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688 |
- From: Ryan Archer <ryan.bradley.archer@gmail.com>
- Date: Wed, 2 Aug 2017 01:41:28 -0400
- Subject: Add an always-incognito mode
- More specifically, add a preference that causes all new tabs and all
- clicked links to launch as incognito.
- Make sure initial incognito status is correctly recognized.
- Enable incognito custom tabs and fix crashes for incognito/custom tab intents (credits to @uazo)
- ---
- chrome/android/chrome_java_sources.gni | 1 +
- .../java/res/xml/privacy_preferences.xml | 5 ++
- .../AlwaysIncognitoLinkInterceptor.java | 80 +++++++++++++++++++
- .../chrome/browser/ChromeTabbedActivity.java | 6 +-
- .../chrome/browser/app/ChromeActivity.java | 4 +
- .../AppMenuPropertiesDelegateImpl.java | 6 ++
- .../ChromeContextMenuPopulator.java | 8 +-
- .../CustomTabActivityLifecycleUmaTracker.java | 25 ------
- .../CustomTabIntentDataProvider.java | 5 +-
- .../browser/init/StartupTabPreloader.java | 14 +++-
- .../privacy/settings/PrivacySettings.java | 37 ++++++++-
- .../browser/settings/SettingsActivity.java | 4 +
- .../tabbed_mode/TabbedRootUiCoordinator.java | 6 +-
- .../browser/tabmodel/ChromeTabCreator.java | 16 +++-
- .../browser/tabmodel/TabPersistentStore.java | 10 +++
- .../webapps/WebappIntentDataProvider.java | 14 ++++
- .../flags/android/chrome_feature_list.cc | 2 +-
- .../strings/android_chrome_strings.grd | 13 +++
- chrome/browser/ui/messages/android/BUILD.gn | 1 +
- .../snackbar/INeedSnackbarManager.java | 27 +++++++
- 20 files changed, 248 insertions(+), 36 deletions(-)
- create mode 100644 chrome/android/java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.java
- create mode 100644 chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/INeedSnackbarManager.java
- diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
- --- a/chrome/android/chrome_java_sources.gni
- +++ b/chrome/android/chrome_java_sources.gni
- @@ -3,6 +3,7 @@
- # found in the LICENSE file.
-
- chrome_java_sources = [
- + "java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.java",
- "java/src/com/google/android/apps/chrome/appwidget/bookmarks/BookmarkThumbnailWidgetProvider.java",
- "java/src/org/chromium/chrome/browser/ActivityTabProvider.java",
- "java/src/org/chromium/chrome/browser/ActivityUtils.java",
- diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/android/java/res/xml/privacy_preferences.xml
- --- a/chrome/android/java/res/xml/privacy_preferences.xml
- +++ b/chrome/android/java/res/xml/privacy_preferences.xml
- @@ -37,6 +37,11 @@
- android:key="secure_dns"
- android:title="@string/settings_secure_dns_title"
- android:fragment="org.chromium.chrome.browser.privacy.secure_dns.SecureDnsSettings"/>
- + <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
- + android:key="always_incognito"
- + android:title="@string/always_incognito_title"
- + android:summary="@string/always_incognito_summary"
- + android:defaultValue="false" />
- <Preference
- android:fragment="org.chromium.chrome.browser.privacy.settings.DoNotTrackSettings"
- android:key="do_not_track"
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.java b/chrome/android/java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.java
- new file mode 100644
- --- /dev/null
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.java
- @@ -0,0 +1,80 @@
- +/* This Source Code Form is subject to the terms of the Mozilla Public
- + * License, v. 2.0. If a copy of the MPL was not distributed with this
- + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- +
- +package org.chromium.chrome.browser;
- +
- +import android.content.SharedPreferences;
- +
- +import org.chromium.chrome.browser.tab.EmptyTabObserver;
- +import org.chromium.chrome.browser.tab.Tab;
- +import org.chromium.chrome.browser.tab.TabImpl;
- +import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
- +import org.chromium.chrome.browser.tab.TabLaunchType;
- +import org.chromium.chrome.browser.tabmodel.TabModel;
- +import org.chromium.content_public.browser.LoadUrlParams;
- +import org.chromium.url.GURL;
- +
- +import java.util.HashMap;
- +import java.util.HashSet;
- +import java.util.Map;
- +import java.util.Set;
- +/**
- + * A {@link TabObserver} that implements the always-incognito preference behavior for links. When the preference is set
- + * to true, it intercepts links opened within observed {@link Tab}s and opens them in new incognito <code>Tab</code>s instead.
- + */
- +public class AlwaysIncognitoLinkInterceptor extends EmptyTabObserver {
- +
- + public static final String PREF_ALWAYS_INCOGNITO = "always_incognito";
- +
- + private final SharedPreferences alwaysIncognitoContainer;
- + private final Map<Tab, String> lastUrls;
- + private final Set<Tab> revertingTabs;
- +
- + public AlwaysIncognitoLinkInterceptor(final SharedPreferences alwaysIncognitoContainer) {
- +
- + assert alwaysIncognitoContainer != null;
- +
- + this.alwaysIncognitoContainer = alwaysIncognitoContainer;
- + lastUrls = new HashMap<Tab, String>();
- + revertingTabs = new HashSet<Tab>();
- + }
- +
- + @Override
- + public void onDestroyed(final Tab tab)
- + {
- + lastUrls.remove(tab);
- + revertingTabs.remove(tab);
- + }
- +
- + @Override
- + public void onUpdateUrl(Tab tab, GURL gurl) {
- +
- + if (tab == null) return;
- + if (gurl == null) return;
- + if (tab.isIncognito()) return;
- + if (alwaysIncognitoContainer == null) return;
- +
- + String spec = gurl.getValidSpecOrEmpty();
- + if (spec == null) return;
- +
- + final String lastUrl = lastUrls.put(tab, spec);
- +
- + if (!alwaysIncognitoContainer.getBoolean(PREF_ALWAYS_INCOGNITO, false)) return;
- + if (revertingTabs.contains(tab)) {
- + revertingTabs.remove(tab);
- + return;
- + }
- +
- + ((ChromeTabbedActivity)tab.getWindowAndroid().getActivity().get())
- + .getTabCreator(true)
- + .createNewTab(new LoadUrlParams(spec), TabLaunchType.FROM_LINK, tab);
- +
- + if ((spec.equals(lastUrl)) || (!tab.canGoBack())) {
- + // this call was triggered by a reload
- + } else {
- + revertingTabs.add(tab);
- + tab.goBack();
- + }
- + }
- +}
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
- @@ -56,6 +56,7 @@ import org.chromium.base.supplier.UnownedUserDataSupplier;
- import org.chromium.base.task.PostTask;
- import org.chromium.cc.input.BrowserControlsState;
- import org.chromium.chrome.R;
- +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
- import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
- import org.chromium.chrome.browser.IntentHandler.TabOpenType;
- import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout;
- @@ -1770,8 +1771,9 @@ public class ChromeTabbedActivity extends ChromeActivity<ChromeActivityComponent
- Bundle savedInstanceState = getSavedInstanceState();
-
- // We determine the model as soon as possible so every systems get initialized coherently.
- - boolean startIncognito = savedInstanceState != null
- - && savedInstanceState.getBoolean(IS_INCOGNITO_SELECTED, false);
- + boolean startIncognito = ContextUtils.getAppSharedPreferences().getBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false)
- + || (savedInstanceState != null
- + && savedInstanceState.getBoolean(IS_INCOGNITO_SELECTED, false));
-
- mNextTabPolicySupplier = new ChromeNextTabPolicySupplier(mOverviewModeBehaviorSupplier);
-
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
- @@ -101,6 +101,7 @@ import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial;
- import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
- import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager.ContextualSearchTabPromotionDelegate;
- import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
- +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
- import org.chromium.chrome.browser.dependency_injection.ChromeActivityComponent;
- import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
- import org.chromium.chrome.browser.device.DeviceClassManager;
- @@ -1891,6 +1892,9 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
- throw new IllegalStateException(
- "Attempting to access TabCreator before initialization");
- }
- + if (ContextUtils.getAppSharedPreferences().getBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false)) {
- + incognito = true;
- + }
- return mTabCreatorManagerSupplier.get().getTabCreator(incognito);
- }
-
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
- @@ -538,6 +538,12 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
- }
-
- private void prepareCommonMenuItems(Menu menu, @MenuGroup int menuGroup, boolean isIncognito) {
- + if (ContextUtils.getAppSharedPreferences().getBoolean("always_incognito", false)) {
- + final MenuItem newTabOption = menu.findItem(R.id.new_tab_menu_id);
- + if (newTabOption != null)
- + newTabOption.setVisible(false);
- + }
- +
- // We have to iterate all menu items since same menu item ID may be associated with more
- // than one menu items.
- boolean isOverviewModeMenu = menuGroup == MenuGroup.OVERVIEW_MODE_MENU;
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
- @@ -31,6 +31,7 @@ import org.chromium.base.ContextUtils;
- import org.chromium.base.metrics.RecordHistogram;
- import org.chromium.base.supplier.Supplier;
- import org.chromium.chrome.R;
- +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
- import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabCoordinator;
- import org.chromium.chrome.browser.contextmenu.ChromeContextMenuItem.Item;
- import org.chromium.chrome.browser.contextmenu.ContextMenuCoordinator.ListItemType;
- @@ -408,6 +409,10 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
- boolean hasSaveImage = false;
- mShowEphemeralTabNewLabel = null;
-
- + boolean always_incognito =
- + ContextUtils.getAppSharedPreferences().getBoolean(
- + AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false);
- +
- List<Pair<Integer, ModelList>> groupedItems = new ArrayList<>();
-
- if (mParams.isAnchor()) {
- @@ -426,6 +431,7 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
- linkGroup.add(createListItem(Item.OPEN_IN_NEW_TAB_IN_GROUP));
- }
- }
- +
- if (!mItemDelegate.isIncognito() && mItemDelegate.isIncognitoSupported()) {
- linkGroup.add(createListItem(Item.OPEN_IN_INCOGNITO_TAB));
- }
- @@ -450,7 +456,7 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
- }
- }
- if (FirstRunStatus.getFirstRunFlowComplete()) {
- - if (!mItemDelegate.isIncognito()
- + if ((always_incognito || !mItemDelegate.isIncognito())
- && UrlUtilities.isDownloadableScheme(mParams.getLinkUrl())) {
- linkGroup.add(createListItem(Item.SAVE_LINK_AS));
- }
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java
- @@ -39,31 +39,6 @@ public class CustomTabActivityLifecycleUmaTracker implements PauseResumeWithNati
- private boolean mIsInitialResume = true;
-
- private void recordIncognitoLaunchReason() {
- - IncognitoCustomTabIntentDataProvider incognitoProvider =
- - (IncognitoCustomTabIntentDataProvider) mIntentDataProvider;
- -
- - @IntentHandler.IncognitoCCTCallerId
- - int incognitoCCTCallerId = incognitoProvider.getFeatureIdForMetricsCollection();
- - RecordHistogram.recordEnumeratedHistogram("CustomTabs.IncognitoCCTCallerId",
- - incognitoCCTCallerId, IntentHandler.IncognitoCCTCallerId.NUM_ENTRIES);
- -
- - // Record which 1P app launched Incognito CCT.
- - if (incognitoCCTCallerId == IntentHandler.IncognitoCCTCallerId.GOOGLE_APPS) {
- - String sendersPackageName = incognitoProvider.getSendersPackageName();
- - @IntentHandler.ExternalAppId
- - int externalId = IntentHandler.mapPackageToExternalAppId(sendersPackageName);
- - if (externalId != IntentHandler.ExternalAppId.OTHER) {
- - RecordHistogram.recordEnumeratedHistogram("CustomTabs.ClientAppId.Incognito",
- - externalId, IntentHandler.ExternalAppId.NUM_ENTRIES);
- - } else {
- - // Using package name didn't give any meaningful insight on who launched the
- - // Incognito CCT, falling back to check if they provided EXTRA_APPLICATION_ID.
- - externalId =
- - IntentHandler.determineExternalIntentSource(incognitoProvider.getIntent());
- - RecordHistogram.recordEnumeratedHistogram("CustomTabs.ClientAppId.Incognito",
- - externalId, IntentHandler.ExternalAppId.NUM_ENTRIES);
- - }
- - }
- }
-
- private void recordUserAction() {
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
- @@ -49,6 +49,9 @@ import org.chromium.components.browser_ui.widget.TintedDrawable;
- import org.chromium.components.embedder_support.util.UrlConstants;
- import org.chromium.device.mojom.ScreenOrientationLockType;
-
- +import org.chromium.base.ContextUtils;
- +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
- +
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.util.ArrayList;
- @@ -726,7 +729,7 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid
-
- @Override
- public boolean isIncognito() {
- - return false;
- + return ContextUtils.getAppSharedPreferences().getBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false);
- }
-
- @Nullable
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/StartupTabPreloader.java b/chrome/android/java/src/org/chromium/chrome/browser/init/StartupTabPreloader.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/init/StartupTabPreloader.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/StartupTabPreloader.java
- @@ -34,6 +34,9 @@ import org.chromium.content_public.browser.WebContents;
- import org.chromium.ui.base.WindowAndroid;
- import org.chromium.url.GURL;
-
- +import org.chromium.base.ContextUtils;
- +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
- +
- /**
- * This class attempts to preload the tab if the url is known from the intent when the profile
- * is created. This is done to improve startup latency.
- @@ -185,17 +188,22 @@ public class StartupTabPreloader implements ProfileManager.Observer, DestroyObse
- Intent intent = mIntentSupplier.get();
- GURL url = UrlFormatter.fixupUrl(getUrlFromIntent(intent));
-
- + boolean isIncognito = ContextUtils.getAppSharedPreferences().getBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false);
- +
- + Profile profile = Profile.getLastUsedRegularProfile();
- ChromeTabCreator chromeTabCreator =
- - (ChromeTabCreator) mTabCreatorManager.getTabCreator(false);
- + (ChromeTabCreator) mTabCreatorManager.getTabCreator(isIncognito);
- WebContents webContents =
- - WebContentsFactory.createWebContents(Profile.getLastUsedRegularProfile(), false);
- + WebContentsFactory.createWebContents(
- + isIncognito ? profile.getPrimaryOTRProfile(true /* createIfNeeded */) : profile,
- + false);
-
- mLoadUrlParams = mIntentHandler.createLoadUrlParamsForIntent(url.getSpec(), intent);
-
- // Create a detached tab, but don't add it to the tab model yet. We'll do that
- // later if the loadUrlParams etc... match.
- mTab = TabBuilder.createLiveTab(false)
- - .setIncognito(false)
- + .setIncognito(isIncognito)
- .setLaunchType(TabLaunchType.FROM_EXTERNAL_APP)
- .setWindow(mWindowAndroid)
- .setWebContents(webContents)
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
- @@ -29,6 +29,10 @@ import org.chromium.chrome.browser.profiles.Profile;
- import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
- import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
- import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
- +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
- +import org.chromium.chrome.browser.ui.messages.snackbar.INeedSnackbarManager;
- +import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
- +import org.chromium.chrome.browser.ApplicationLifetime;
- import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
- import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate;
- import org.chromium.components.browser_ui.settings.SettingsLauncher;
- @@ -43,7 +47,12 @@ import org.chromium.ui.text.SpanApplier;
- * Fragment to keep track of the all the privacy related preferences.
- */
- public class PrivacySettings
- - extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener {
- + extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener,
- + INeedSnackbarManager {
- + private SnackbarManager mSnackbarManager;
- + private Snackbar mSnackbar;
- +
- + private static final String PREF_ALWAYS_INCOGNITO = "always_incognito";
- private static final String PREF_CAN_MAKE_PAYMENT = "can_make_payment";
- private static final String PREF_NETWORK_PREDICTIONS = "preload_pages";
- private static final String PREF_HTTPS_FIRST_MODE = "https_first_mode";
- @@ -96,6 +105,25 @@ public class PrivacySettings
- (ChromeSwitchPreference) findPreference(PREF_CAN_MAKE_PAYMENT);
- canMakePaymentPref.setOnPreferenceChangeListener(this);
-
- + ChromeSwitchPreference alwaysIncognitoPref =
- + (ChromeSwitchPreference) findPreference(PREF_ALWAYS_INCOGNITO);
- + alwaysIncognitoPref.setOnPreferenceChangeListener(this);
- +
- + mSnackbar = Snackbar.make(getActivity().getString(R.string.ui_relaunch_notice),
- + new SnackbarManager.SnackbarController() {
- + @Override
- + public void onDismissNoAction(Object actionData) { }
- +
- + @Override
- + public void onAction(Object actionData) {
- + ApplicationLifetime.terminate(true);
- + }
- + }, Snackbar.TYPE_NOTIFICATION, Snackbar.UMA_UNKNOWN)
- + .setSingleLine(false)
- + .setAction(getActivity().getString(R.string.relaunch),
- + /*actionData*/null)
- + .setDuration(/*durationMs*/70000);
- +
- ChromeSwitchPreference networkPredictionPref =
- (ChromeSwitchPreference) findPreference(PREF_NETWORK_PREDICTIONS);
- networkPredictionPref.setChecked(
- @@ -156,6 +184,9 @@ public class PrivacySettings
- } else if (PREF_NETWORK_PREDICTIONS.equals(key)) {
- PrivacyPreferencesManagerImpl.getInstance().setNetworkPredictionEnabled(
- (boolean) newValue);
- + } else if (PREF_ALWAYS_INCOGNITO.equals(key)) {
- + if (!mSnackbarManager.isShowing())
- + mSnackbarManager.showSnackbar(mSnackbar);
- } else if (PREF_HTTPS_FIRST_MODE.equals(key)) {
- UserPrefs.get(Profile.getLastUsedRegularProfile())
- .setBoolean(Pref.HTTPS_ONLY_MODE_ENABLED, (boolean) newValue);
- @@ -238,4 +269,8 @@ public class PrivacySettings
- }
- return false;
- }
- +
- + public void setSnackbarManager(SnackbarManager manager) {
- + mSnackbarManager = manager;
- + }
- }
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
- @@ -51,6 +51,7 @@ import org.chromium.chrome.browser.safety_check.SafetyCheckSettingsFragment;
- import org.chromium.chrome.browser.safety_check.SafetyCheckUpdatesDelegateImpl;
- import org.chromium.chrome.browser.search_engines.settings.SearchEngineSettings;
- import org.chromium.chrome.browser.site_settings.ChromeSiteSettingsDelegate;
- +import org.chromium.chrome.browser.ui.messages.snackbar.INeedSnackbarManager;
- import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
- import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarManageable;
- import org.chromium.components.browser_ui.settings.FragmentSettingsLauncher;
- @@ -171,6 +172,9 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity
- .getSiteSettingsDelegate());
- delegate.setSnackbarManager(mSnackbarManager);
- }
- + if (fragment instanceof INeedSnackbarManager) {
- + ((INeedSnackbarManager)fragment).setSnackbarManager(mSnackbarManager);
- + }
- }
-
- @Override
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
- @@ -121,6 +121,8 @@ import org.chromium.ui.base.DeviceFormFactor;
- import org.chromium.ui.base.IntentRequestTracker;
- import org.chromium.ui.modaldialog.ModalDialogManager;
- import org.chromium.ui.util.TokenHolder;
- +import org.chromium.base.ContextUtils;
- +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
-
- /**
- * A {@link RootUiCoordinator} variant that controls tabbed-mode specific UI.
- @@ -483,11 +485,13 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator {
-
- // TODO(twellington): Supply TabModelSelector as well and move initialization earlier.
- if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity)) {
- + boolean tabModel = ContextUtils.getAppSharedPreferences().getBoolean(
- + AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false);
- AppMenuHandler appMenuHandler =
- mAppMenuCoordinator == null ? null : mAppMenuCoordinator.getAppMenuHandler();
- mEmptyBackgroundViewWrapper = new EmptyBackgroundViewWrapper(
- mTabModelSelectorSupplier.get(),
- - mTabCreatorManagerSupplier.get().getTabCreator(false), mActivity,
- + mTabCreatorManagerSupplier.get().getTabCreator(tabModel), mActivity,
- appMenuHandler, mSnackbarManagerSupplier.get(), mOverviewModeBehaviorSupplier);
- mEmptyBackgroundViewWrapper.initialize();
- }
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
- @@ -44,6 +44,10 @@ import org.chromium.url.GURL;
-
- import java.nio.ByteBuffer;
-
- +import org.chromium.base.ContextUtils;
- +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
- +import org.chromium.chrome.browser.tab.TabObserver;
- +
- /**
- * This class creates various kinds of new tabs and adds them to the right {@link TabModel}.
- */
- @@ -74,6 +78,7 @@ public class ChromeTabCreator extends TabCreator {
- private final Activity mActivity;
- private final StartupTabPreloader mStartupTabPreloader;
- private final boolean mIncognito;
- + private final TabObserver mExtraLogic;
-
- private WindowAndroid mNativeWindow;
- private TabModel mTabModel;
- @@ -96,6 +101,10 @@ public class ChromeTabCreator extends TabCreator {
- mNativeWindow = nativeWindow;
- mTabDelegateFactorySupplier = tabDelegateFactory;
- mIncognito = incognito;
- + if (!mIncognito)
- + mExtraLogic = new AlwaysIncognitoLinkInterceptor(ContextUtils.getAppSharedPreferences());
- + else
- + mExtraLogic = null;
- mOverviewNTPCreator = overviewNTPCreator;
- mAsyncTabParamsManager = asyncTabParamsManager;
- mTabModelSelectorSupplier = tabModelSelectorSupplier;
- @@ -259,6 +268,8 @@ public class ChromeTabCreator extends TabCreator {
- if (creationState == TabCreationState.LIVE_IN_FOREGROUND && !openInForeground) {
- creationState = TabCreationState.LIVE_IN_BACKGROUND;
- }
- + if (mExtraLogic != null)
- + tab.addObserver(mExtraLogic);
- mTabModel.addTab(tab, position, type, creationState);
- return tab;
- } finally {
- @@ -293,6 +304,8 @@ public class ChromeTabCreator extends TabCreator {
- @TabCreationState
- int creationState = openInForeground ? TabCreationState.LIVE_IN_FOREGROUND
- : TabCreationState.LIVE_IN_BACKGROUND;
- + if (mExtraLogic != null)
- + tab.addObserver(mExtraLogic);
- mTabModel.addTab(tab, position, type, creationState);
- return true;
- }
- @@ -333,7 +346,6 @@ public class ChromeTabCreator extends TabCreator {
- // TODO(crbug.com/1081924): Clean up the launches from SearchActivity/Chrome.
- public Tab launchUrlFromExternalApp(
- LoadUrlParams loadUrlParams, String appId, boolean forceNewTab, Intent intent) {
- - assert !mIncognito;
- // Don't re-use tabs for intents from Chrome. Note that this can be spoofed so shouldn't be
- // relied on for anything security sensitive.
- boolean isLaunchedFromChrome = TextUtils.equals(appId, mActivity.getPackageName());
- @@ -428,6 +440,8 @@ public class ChromeTabCreator extends TabCreator {
- .setSerializedCriticalPersistedTabData(serializedCriticalPersistedTabData)
- .build();
- }
- + if (mExtraLogic != null)
- + tab.addObserver(mExtraLogic);
-
- if (isIncognito != mIncognito) {
- throw new IllegalStateException("Incognito state mismatch. TabState: "
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
- @@ -18,6 +18,7 @@ import androidx.core.util.AtomicFile;
-
- import org.chromium.base.Callback;
- import org.chromium.base.CallbackController;
- +import org.chromium.base.ContextUtils;
- import org.chromium.base.Log;
- import org.chromium.base.ObserverList;
- import org.chromium.base.StreamUtil;
- @@ -55,6 +56,8 @@ import org.chromium.content_public.browser.LoadUrlParams;
- import org.chromium.content_public.browser.UiThreadTaskTraits;
- import org.chromium.url.GURL;
-
- +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
- +
- import java.io.BufferedInputStream;
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- @@ -643,6 +646,13 @@ public class TabPersistentStore {
- }
- }
- }
- + if (ContextUtils.getAppSharedPreferences().getBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false)) {
- + if (!isIncognito) {
- + Log.w(TAG, "Failed to restore tab: not in incognito mode.");
- + return;
- + }
- + }
- +
- TabModel model = mTabModelSelector.getModel(isIncognito);
-
- if (model.isIncognito() != isIncognito) {
- diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java
- --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java
- +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java
- @@ -29,6 +29,9 @@ import org.chromium.chrome.browser.flags.ActivityType;
- import org.chromium.components.browser_ui.widget.TintedDrawable;
- import org.chromium.device.mojom.ScreenOrientationLockType;
-
- +import org.chromium.base.ContextUtils;
- +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
- +
- /**
- * Stores info about a web app.
- */
- @@ -42,6 +45,8 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider
- private final Intent mIntent;
- private final ColorProviderImpl mColorProvider;
-
- + private boolean mIsIncognito = false;
- +
- /**
- * Returns the toolbar color to use if a custom color is not specified by the webapp.
- */
- @@ -63,6 +68,10 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider
- mWebappExtras = webappExtras;
- mWebApkExtras = webApkExtras;
- mActivityType = (webApkExtras != null) ? ActivityType.WEB_APK : ActivityType.WEBAPP;
- +
- + if (ContextUtils.getAppSharedPreferences().getBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false)) {
- + mIsIncognito = true;
- + }
- }
-
- @Override
- @@ -151,6 +160,11 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider
- return mWebApkExtras;
- }
-
- + @Override
- + public boolean isIncognito() {
- + return mIsIncognito;
- + }
- +
- @Override
- public @ScreenOrientationLockType.EnumType int getDefaultOrientation() {
- return mWebappExtras.orientation;
- diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
- --- a/chrome/browser/flags/android/chrome_feature_list.cc
- +++ b/chrome/browser/flags/android/chrome_feature_list.cc
- @@ -455,7 +455,7 @@ const base::Feature kCCTIncognito{"CCTIncognito",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
- const base::Feature kCCTIncognitoAvailableToThirdParty{
- - "CCTIncognitoAvailableToThirdParty", base::FEATURE_DISABLED_BY_DEFAULT};
- + "CCTIncognitoAvailableToThirdParty", base::FEATURE_ENABLED_BY_DEFAULT};
-
- const base::Feature kCCTPostMessageAPI{"CCTPostMessageAPI",
- base::FEATURE_ENABLED_BY_DEFAULT};
- diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
- --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
- +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
- @@ -930,6 +930,19 @@ Your Google account may have other forms of browsing history like searches and a
- <message name="IDS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNCED_NO_LINK" desc="A text for the basic tab explaining browsing history for users with history sync. This version is shown when the link to MyActivity is displayed separately.">
- Clears history from all synced devices.
- </message>
- + <!-- always incognito -->
- + <message name="IDS_ALWAYS_INCOGNITO_TITLE" desc="Title for always incognito mode">
- + Open links in incognito tabs always
- + </message>
- + <message name="IDS_ALWAYS_INCOGNITO_SUMMARY" desc="Summary for always incognito mode">
- + Opens links in incognito tabs when you click on new tab or on a link
- + </message>
- + <message name="IDS_RELAUNCH" desc="Summary for always incognito mode">
- + Relaunch
- + </message>
- + <message name="IDS_UI_RELAUNCH_NOTICE" desc="Summary for always incognito mode">
- + Your changes will take effect the next time you relaunch Bromite.
- + </message>
- <message name="IDS_CLEAR_BROWSING_HISTORY_SUMMARY_SIGNED_IN" desc="A text explaining other forms of activity for signed in users.">
- Clears history and autocompletions in the address bar. Your Google Account may have other forms of browsing history at <ph name="BEGIN_LINK"><link></ph>myactivity.google.com<ph name="END_LINK"></link></ph>.
- </message>
- diff --git a/chrome/browser/ui/messages/android/BUILD.gn b/chrome/browser/ui/messages/android/BUILD.gn
- --- a/chrome/browser/ui/messages/android/BUILD.gn
- +++ b/chrome/browser/ui/messages/android/BUILD.gn
- @@ -22,6 +22,7 @@ android_resources("java_resources") {
- android_library("java") {
- sources = [
- "java/src/org/chromium/chrome/browser/ui/messages/infobar/SimpleConfirmInfoBarBuilder.java",
- + "java/src/org/chromium/chrome/browser/ui/messages/snackbar/INeedSnackbarManager.java",
- "java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java",
- "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollection.java",
- "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarManager.java",
- diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/INeedSnackbarManager.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/INeedSnackbarManager.java
- new file mode 100644
- --- /dev/null
- +++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/INeedSnackbarManager.java
- @@ -0,0 +1,27 @@
- +/*
- + This file is part of Bromite.
- +
- + Bromite is free software: you can redistribute it and/or modify
- + it under the terms of the GNU General Public License as published by
- + the Free Software Foundation, either version 3 of the License, or
- + (at your option) any later version.
- +
- + Bromite is distributed in the hope that it will be useful,
- + but WITHOUT ANY WARRANTY; without even the implied warranty of
- + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + GNU General Public License for more details.
- +
- + You should have received a copy of the GNU General Public License
- + along with Bromite. If not, see <https://www.gnu.org/licenses/>.
- +*/
- +
- +package org.chromium.chrome.browser.ui.messages.snackbar;
- +
- +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
- +
- +/**
- + * An interface that allows using snackbars in the settings
- + */
- +public interface INeedSnackbarManager {
- + void setSnackbarManager(SnackbarManager manager);
- +}
- --
- 2.20.1
|