* add snackbar in settings activity to inform the user of the reboot required when change the flag * removed BrowserRestartActivity in favor of ApplicationLifetime
661 lines
35 KiB
Diff
661 lines
35 KiB
Diff
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 +
|
|
.../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 +++++++
|
|
19 files changed, 243 insertions(+), 35 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
|
|
@@ -28,6 +28,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;
|
|
@@ -1756,8 +1757,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;
|
|
@@ -1872,6 +1873,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
|
|
@@ -378,6 +378,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 isMenuGroupTabsVisible = TabUiFeatureUtilities.isTabGroupsAndroidEnabled(mContext)
|
|
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;
|
|
@@ -409,6 +410,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()) {
|
|
@@ -427,6 +432,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));
|
|
}
|
|
@@ -451,7 +457,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
|
|
@@ -50,6 +50,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;
|
|
@@ -727,7 +730,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
|
|
@@ -27,6 +27,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;
|
|
@@ -41,7 +45,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";
|
|
@@ -84,6 +93,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(
|
|
@@ -115,6 +143,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);
|
|
@@ -192,4 +223,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/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;
|
|
@@ -56,6 +57,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;
|
|
@@ -687,6 +690,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
|
|
@@ -28,6 +28,9 @@ import org.chromium.chrome.browser.browserservices.intents.WebappExtras;
|
|
import org.chromium.chrome.browser.flags.ActivityType;
|
|
import org.chromium.components.browser_ui.widget.TintedDrawable;
|
|
|
|
+import org.chromium.base.ContextUtils;
|
|
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
|
|
+
|
|
/**
|
|
* Stores info about a web app.
|
|
*/
|
|
@@ -41,6 +44,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.
|
|
*/
|
|
@@ -62,6 +67,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
|
|
@@ -150,6 +159,11 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider
|
|
return mWebApkExtras;
|
|
}
|
|
|
|
+ @Override
|
|
+ public boolean isIncognito() {
|
|
+ return mIsIncognito;
|
|
+ }
|
|
+
|
|
@Override
|
|
public 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
|
|
@@ -447,7 +447,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
|
|
@@ -907,6 +907,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.17.1
|
|
|