From: csagan5 <32685696+csagan5@users.noreply.github.com>
Date: Wed, 29 Aug 2018 11:03:44 +0200
Subject: Add custom tab intents privacy option

Add custom tab intents privacy option and force
open external links in incognito flag.

Flags are mutually exclusive.

See also: https://github.com/bromite/bromite/issues/1474

License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
---
 .../java/res/xml/privacy_preferences.xml      | 10 ++++++++
 .../browser/LaunchIntentDispatcher.java       | 22 +++++++++++++++++
 .../IncognitoCustomTabIntentDataProvider.java |  6 +++++
 .../privacy/settings/PrivacySettings.java     | 24 +++++++++++++++++++
 .../chrome/browser/tab/TabAssociatedApp.java  |  6 ++++-
 .../strings/android_chrome_strings.grd        | 15 ++++++++++++
 6 files changed, 82 insertions(+), 1 deletion(-)

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
@@ -58,6 +58,16 @@ found in the LICENSE file.
         android:fragment="org.chromium.chrome.browser.privacy.settings.DoNotTrackSettings"
         android:key="do_not_track"
         android:title="@string/do_not_track_title"/>
+    <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
+        android:key="allow_custom_tab_intents"
+        android:title="@string/allow_custom_tab_intents_title"
+        android:summary="@string/allow_custom_tab_intents_summary"
+        android:defaultValue="false" />
+    <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
+        android:key="open_external_links_incognito"
+        android:title="@string/open_external_links_incognito_title"
+        android:summary="@string/open_external_links_incognito_summary"
+        android:defaultValue="false" />
     <Preference
         android:key="privacy_sandbox"
         android:title="@string/prefs_privacy_sandbox"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -45,6 +45,7 @@ import org.chromium.chrome.browser.notifications.NotificationPlatformBridge;
 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
 import org.chromium.chrome.browser.searchwidget.SearchActivity;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.translate.TranslateIntentHandler;
 import org.chromium.chrome.browser.util.AndroidTaskUtils;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
@@ -58,6 +59,8 @@ import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Set;
 
+import org.chromium.chrome.browser.privacy.settings.PrivacySettings;
+
 /**
  * Dispatches incoming intents to the appropriate activity based on the current configuration and
  * Intent fired.
@@ -268,6 +271,9 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega
      */
     public static boolean isCustomTabIntent(Intent intent) {
         if (intent == null) return false;
+        if (!ContextUtils.getAppSharedPreferences()
+                .getBoolean(PrivacySettings.PREF_ALLOW_CUSTOM_TAB_INTENTS, false))
+            return false;
         if (CustomTabsIntent.shouldAlwaysUseBrowserUI(intent)
                 || !intent.hasExtra(CustomTabsIntent.EXTRA_SESSION)) {
             return false;
@@ -287,6 +293,10 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega
         newIntent.setData(uri);
         newIntent.setClassName(context, CustomTabActivity.class.getName());
 
+        if (ContextUtils.getAppSharedPreferences()
+                .getBoolean(PrivacySettings.PREF_OPEN_EXTERNAL_LINKS_INCOGNITO, false))
+            newIntent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true);
+
         // Since configureIntentForResizableCustomTab() might change the componenet/class
         // associated with the passed intent, it needs to be called after #setClassName(context,
         // CustomTabActivity.class.getName());
@@ -433,6 +443,18 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega
 
         if (Intent.ACTION_VIEW.equals(newIntent.getAction())
                 && !IntentHandler.wasIntentSenderChrome(newIntent)) {
+
+            if (ContextUtils.getAppSharedPreferences().getBoolean(
+                    PrivacySettings.PREF_OPEN_EXTERNAL_LINKS_INCOGNITO, false)) {
+                Context applicationContext = ContextUtils.getApplicationContext();
+                newIntent = IntentHandler.createTrustedOpenNewTabIntent(applicationContext,
+                    /*incognito*/true);
+                newIntent.setData(mIntent.getData());
+                newIntent.setPackage(applicationContext.getPackageName());
+                IntentHandler.setTabLaunchType(newIntent, TabLaunchType.FROM_EXTERNAL_APP);
+                newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            }
+
             long time = SystemClock.elapsedRealtime();
             if (!chromeTabbedTaskExists()) {
                 newIntent.putExtra(IntentHandler.EXTRA_STARTED_TABBED_CHROME_TASK, true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabIntentDataProvider.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabIntentDataProvider.java
@@ -35,6 +35,9 @@ import org.chromium.components.browser_ui.widget.TintedDrawable;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.chromium.base.ContextUtils;
+import org.chromium.chrome.browser.privacy.settings.PrivacySettings;
+
 /**
  * A model class that parses the incoming intent for incognito Custom Tabs specific customization
  * data.
@@ -108,6 +111,9 @@ public class IncognitoCustomTabIntentDataProvider extends BrowserServicesIntentD
     }
 
     private static boolean isIntentFromThirdPartyAllowed() {
+        if (ContextUtils.getAppSharedPreferences()
+                        .getBoolean(PrivacySettings.PREF_OPEN_EXTERNAL_LINKS_INCOGNITO, false))
+            return true;
         return ChromeFeatureList.sCctIncognitoAvailableToThirdParty.isEnabled();
     }
 
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
@@ -76,6 +76,9 @@ public class PrivacySettings
     private ManagedPreferenceDelegate mManagedPreferenceDelegate;
     private IncognitoLockSettings mIncognitoLockSettings;
 
+    private ChromeSwitchPreference allowCustomTabIntentsPref;
+    private ChromeSwitchPreference openExternalLinksPref;
+
     @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         PrivacyPreferencesManagerImpl privacyPrefManager =
@@ -135,6 +138,9 @@ public class PrivacySettings
         updatePreferences();
     }
 
+    public static final String PREF_ALLOW_CUSTOM_TAB_INTENTS = "allow_custom_tab_intents";
+    public static final String PREF_OPEN_EXTERNAL_LINKS_INCOGNITO = "open_external_links_incognito";
+
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         String key = preference.getKey();
@@ -151,6 +157,14 @@ public class PrivacySettings
         } else if (PREF_SEARCH_SUGGESTIONS.equals(key)) {
             UserPrefs.get(Profile.getLastUsedRegularProfile())
                     .setBoolean(Pref.SEARCH_SUGGEST_ENABLED, (boolean) newValue);
+        } else if (PREF_ALLOW_CUSTOM_TAB_INTENTS.equals(key)) {
+            SharedPreferences.Editor sharedPreferencesEditor = ContextUtils.getAppSharedPreferences().edit();
+            sharedPreferencesEditor.putBoolean(PREF_ALLOW_CUSTOM_TAB_INTENTS, (boolean)newValue);
+            sharedPreferencesEditor.apply();
+        } else if (PREF_OPEN_EXTERNAL_LINKS_INCOGNITO.equals(key)) {
+            SharedPreferences.Editor sharedPreferencesEditor = ContextUtils.getAppSharedPreferences().edit();
+            sharedPreferencesEditor.putBoolean(PREF_OPEN_EXTERNAL_LINKS_INCOGNITO, (boolean)newValue);
+            sharedPreferencesEditor.apply();
         }
         return true;
     }
@@ -173,6 +187,16 @@ public class PrivacySettings
             canMakePaymentPref.setChecked(prefService.getBoolean(Pref.CAN_MAKE_PAYMENT_ENABLED));
         }
 
+        allowCustomTabIntentsPref =
+                (ChromeSwitchPreference) findPreference(PREF_ALLOW_CUSTOM_TAB_INTENTS);
+        allowCustomTabIntentsPref.setOnPreferenceChangeListener(this);
+        allowCustomTabIntentsPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate);
+
+        openExternalLinksPref =
+                (ChromeSwitchPreference) findPreference(PREF_OPEN_EXTERNAL_LINKS_INCOGNITO);
+        openExternalLinksPref.setOnPreferenceChangeListener(this);
+        openExternalLinksPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate);
+
         Preference doNotTrackPref = findPreference(PREF_DO_NOT_TRACK);
         if (doNotTrackPref != null) {
             doNotTrackPref.setSummary(prefService.getBoolean(Pref.ENABLE_DO_NOT_TRACK)
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java
@@ -84,7 +84,11 @@ public final class TabAssociatedApp extends TabWebContentsUserData implements Im
     public static boolean isOpenedFromExternalApp(Tab tab) {
         TabAssociatedApp app = get(tab);
         if (app == null) return false;
-
+        if (ContextUtils.getAppSharedPreferences()
+                        .getBoolean("open_external_links_incognito", false) &&
+                tab.isIncognito() &&
+                tab.getLaunchType() == TabLaunchType.FROM_EXTERNAL_APP)
+            return true;
         String packageName = ContextUtils.getApplicationContext().getPackageName();
         return tab.getLaunchType() == TabLaunchType.FROM_EXTERNAL_APP
                 && !TextUtils.equals(app.getAppId(), packageName);
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
@@ -4788,6 +4788,21 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
       <message name="IDS_NEAR_OOM_REDUCTION_DECLINE" desc="The text of the button letting the user decline the browser's intervention, so that the page can be reloaded.">
          Show original
       </message>
+      <!-- Allow custom tab intents -->
+      <message name="IDS_ALLOW_CUSTOM_TAB_INTENTS_TITLE" desc="Text for 'Allow custom tab intents' settings-privacy option.">
+        Allow custom tab intents
+      </message>
+      <message name="IDS_ALLOW_CUSTOM_TAB_INTENTS_SUMMARY" desc="Summary text for 'Allow custom tab intents' settings-privacy option.">
+        Allow applications to open custom tab intents, similar to webview.
+      </message>
+
+      <!-- Open External Links in Incognito -->
+      <message name="IDS_OPEN_EXTERNAL_LINKS_INCOGNITO_TITLE" desc="Text for 'Open external links in incognito' settings-privacy option.">
+        Open external links in incognito
+      </message>
+      <message name="IDS_OPEN_EXTERNAL_LINKS_INCOGNITO_SUMMARY" desc="Summary text for 'Open external links in incognito' settings-privacy option.">
+        Force the opening of all external links in incognito mode
+      </message>
 
       <!-- Autofill Assistant preferences -->
       <!-- TODO(b/168178344): Move to Assistant settings strings section below. -->
--
2.25.1
