From d2ed0af5dac20472c64dd1c5f259c6b987803a28 Mon Sep 17 00:00:00 2001 From: wchen342 Date: Fri, 19 Feb 2021 20:40:24 +0200 Subject: [PATCH] DoH and WebGL fix; add GPC --- CHANGELOG.md | 6 + README.md | 6 +- build.sh | 2 +- .../Add-bookmark-import-export-actions.patch | 26 +- .../Bromite/Add-flag-to-disable-WebGL.patch | 6 +- ...-to-not-persist-tabs-across-sessions.patch | 18 +- .../Bromite/DoH-secure-mode-by-default.patch | 24 +- patches/series | 1 + .../Add-global-privacy-control.patch | 1025 +++++++++++++++++ 9 files changed, 1078 insertions(+), 36 deletions(-) create mode 100644 patches/ungoogled-chromium-android/Add-global-privacy-control.patch diff --git a/CHANGELOG.md b/CHANGELOG.md index 4826706..8fb4774 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 88.0.4324.182-2 +* Add fix for DoH +* Change description for WebGL flag +* Add GPC (Global Privacy Control) support (Warning: turning this on may *increase* your browser's fingerprint!) +* Add separate `arm64` and `x86` F-Droid repo + # 88.0.4324.182-1 * Upstream important security fix
diff --git a/README.md b/README.md index 07c9be4..5fd1d7f 100644 --- a/README.md +++ b/README.md @@ -186,9 +186,11 @@ There are three methods to install extensions: ## F-Droid Repository -I have set up a F-Droid repository. Because of the limitation of its server tools, the binaries are compiled towards `arm`. They are compatible on 64-bit `arm64` devices too. +I have set up a F-Droid repository. You can use F-Droid client and add the following repository, depending on your device: -You can use F-Droid client and add [this repository](https://www.droidware.info/fdroid/repo?fingerprint=2144449AB1DD270EC31B6087409B5D0EA39A75A9F290DA62AC1B238A0EAAF851). + - For 32-bit `arm` devices, add [this repository](https://www.droidware.info/fdroid/repo?fingerprint=2144449AB1DD270EC31B6087409B5D0EA39A75A9F290DA62AC1B238A0EAAF851) + - For 64-bit `arm64` devices, add [this repository](https://www.droidware.info/arm64/fdroid/repo?fingerprint=2144449AB1DD270EC31B6087409B5D0EA39A75A9F290DA62AC1B238A0EAAF851) + - For `x86` devices, add [this repository](https://www.droidware.info/x86/fdroid/repo?fingerprint=2144449AB1DD270EC31B6087409B5D0EA39A75A9F290DA62AC1B238A0EAAF851) ## Credits diff --git a/build.sh b/build.sh index b7ddba7..fd6d082 100755 --- a/build.sh +++ b/build.sh @@ -14,7 +14,7 @@ trichrome_webview_target=trichrome_webview_apk chromium_version=88.0.4324.182 ungoogled_chromium_version=88.0.4324.182 ungoogled_chromium_revision=1 -ungoogled_chromium_android_revision=1 +ungoogled_chromium_android_revision=2 # Show env pwd diff --git a/patches/Bromite/Add-bookmark-import-export-actions.patch b/patches/Bromite/Add-bookmark-import-export-actions.patch index a860e89..31085e1 100644 --- a/patches/Bromite/Add-bookmark-import-export-actions.patch +++ b/patches/Bromite/Add-bookmark-import-export-actions.patch @@ -374,7 +374,7 @@ Completely remove contacts picker permission from the file dialog protected NativePage buildDownloadsPage(Tab tab) { --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn -@@ -190,6 +190,8 @@ static_library("browser") { +@@ -192,6 +192,8 @@ static_library("browser") { "bitmap_fetcher/bitmap_fetcher_service.h", "bitmap_fetcher/bitmap_fetcher_service_factory.cc", "bitmap_fetcher/bitmap_fetcher_service_factory.h", @@ -383,7 +383,7 @@ Completely remove contacts picker permission from the file dialog "bluetooth/bluetooth_chooser_context.cc", "bluetooth/bluetooth_chooser_context.h", "bluetooth/bluetooth_chooser_context_factory.cc", -@@ -1862,6 +1864,8 @@ static_library("browser") { +@@ -1865,6 +1867,8 @@ static_library("browser") { "web_data_service_factory.h", "window_placement/window_placement_permission_context.cc", "window_placement/window_placement_permission_context.h", @@ -392,7 +392,7 @@ Completely remove contacts picker permission from the file dialog ] configs += [ -@@ -3395,8 +3399,6 @@ static_library("browser") { +@@ -3396,8 +3400,6 @@ static_library("browser") { "badging/badge_manager_factory.h", "banners/app_banner_manager_desktop.cc", "banners/app_banner_manager_desktop.h", @@ -834,8 +834,8 @@ Completely remove contacts picker permission from the file dialog + "importer/imported_bookmark_entry.cc", + "importer/imported_bookmark_entry.h", ] - } else { # Non-Android. + public_deps += [ "//chrome/common/importer" ] --- a/chrome/utility/BUILD.gn +++ b/chrome/utility/BUILD.gn @@ -71,8 +71,6 @@ static_library("utility") { @@ -959,7 +959,7 @@ Completely remove contacts picker permission from the file dialog // than true bookmarks. --- a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java +++ b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java -@@ -35,6 +35,7 @@ import org.chromium.base.task.AsyncTask; +@@ -38,6 +38,7 @@ import org.chromium.base.task.AsyncTask; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; import org.chromium.ui.R; @@ -967,7 +967,7 @@ Completely remove contacts picker permission from the file dialog import org.chromium.ui.UiUtils; import java.io.File; -@@ -53,6 +54,7 @@ public class SelectFileDialog implements +@@ -58,6 +59,7 @@ public class SelectFileDialog implements private static final String TAG = "SelectFileDialog"; private static final String IMAGE_TYPE = "image"; private static final String VIDEO_TYPE = "video"; @@ -975,7 +975,7 @@ Completely remove contacts picker permission from the file dialog private static final String AUDIO_TYPE = "audio"; private static final String ALL_TYPES = "*/*"; -@@ -143,6 +145,11 @@ public class SelectFileDialog implements +@@ -149,6 +151,11 @@ public class SelectFileDialog implements mFileTypes = fileTypes; } @@ -987,7 +987,7 @@ Completely remove contacts picker permission from the file dialog /** * Creates and starts an intent based on the passed fileTypes and capture value. * @param fileTypes MIME types requested (i.e. "image/*") -@@ -170,7 +177,7 @@ public class SelectFileDialog implements +@@ -177,7 +184,7 @@ public class SelectFileDialog implements List missingPermissions = new ArrayList<>(); String storagePermission = Manifest.permission.READ_EXTERNAL_STORAGE; boolean shouldUsePhotoPicker = shouldUsePhotoPicker(); @@ -996,7 +996,7 @@ Completely remove contacts picker permission from the file dialog if (!window.hasPermission(storagePermission)) missingPermissions.add(storagePermission); } else { if (((mSupportsImageCapture && shouldShowImageTypes()) -@@ -198,7 +205,7 @@ public class SelectFileDialog implements +@@ -205,7 +212,7 @@ public class SelectFileDialog implements } // TODO(finnur): Remove once we figure out the cause of crbug.com/950024. @@ -1005,7 +1005,7 @@ Completely remove contacts picker permission from the file dialog if (permissions.length != requestPermissions.length) { throw new RuntimeException( String.format("Permissions arrays misaligned: %d != %d", -@@ -212,7 +219,7 @@ public class SelectFileDialog implements +@@ -219,7 +226,7 @@ public class SelectFileDialog implements } } @@ -1014,7 +1014,7 @@ Completely remove contacts picker permission from the file dialog onFileNotSelected(); return; } -@@ -358,6 +365,7 @@ public class SelectFileDialog implements +@@ -385,6 +392,7 @@ public class SelectFileDialog implements } if (!mimeTypes.contains(mimeType)) mimeTypes.add(mimeType); } @@ -1022,7 +1022,7 @@ Completely remove contacts picker permission from the file dialog return mimeTypes; } -@@ -659,6 +667,10 @@ public class SelectFileDialog implements +@@ -686,6 +694,10 @@ public class SelectFileDialog implements return countAcceptTypesFor(superType) == mFileTypes.size(); } @@ -1046,7 +1046,7 @@ Completely remove contacts picker permission from the file dialog --- a/ui/shell_dialogs/select_file_dialog_android.cc +++ b/ui/shell_dialogs/select_file_dialog_android.cc -@@ -140,6 +140,12 @@ void SelectFileDialogImpl::SelectFileImp +@@ -144,6 +144,12 @@ void SelectFileDialogImpl::SelectFileImp owning_window->GetJavaObject()); } diff --git a/patches/Bromite/Add-flag-to-disable-WebGL.patch b/patches/Bromite/Add-flag-to-disable-WebGL.patch index 56752fa..4d48caf 100644 --- a/patches/Bromite/Add-flag-to-disable-WebGL.patch +++ b/patches/Bromite/Add-flag-to-disable-WebGL.patch @@ -27,11 +27,11 @@ Subject: Add flag to disable WebGL "enable-autofill-account-wallet-storage is also enabled."; +const char kDisableWebGLName[] = "Disable all versions of WebGL"; -+const char kDisableWebGLDescription[] = "Disable all versions of WebGL"; ++const char kDisableWebGLDescription[] = "Disable all versions of WebGL. Note that selecting 'enable' for this flag will enable, and selecting 'disable' will disable WebGL."; + // Non-Android ----------------------------------------------------------------- - #else // !defined(OS_ANDROID) + --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h @@ -1877,6 +1877,9 @@ extern const char kTabbedAppOverflowMenu @@ -43,4 +43,4 @@ Subject: Add flag to disable WebGL + // Non-Android ---------------------------------------------------------------- - #else // !defined(OS_ANDROID) + diff --git a/patches/Bromite/Add-option-to-not-persist-tabs-across-sessions.patch b/patches/Bromite/Add-option-to-not-persist-tabs-across-sessions.patch index 94def9e..a544392 100644 --- a/patches/Bromite/Add-option-to-not-persist-tabs-across-sessions.patch +++ b/patches/Bromite/Add-option-to-not-persist-tabs-across-sessions.patch @@ -11,16 +11,16 @@ Subject: Add option to not persist tabs across sessions --- a/chrome/android/java/res/xml/privacy_preferences.xml +++ b/chrome/android/java/res/xml/privacy_preferences.xml -@@ -45,4 +45,10 @@ +@@ -50,4 +50,10 @@ android:summary="@string/prefs_safe_browsing_summary" android:fragment="org.chromium.chrome.browser.safe_browsing.settings.SafeBrowsingSettingsFragment" - android:order="6"/> + android:order="7"/> + ++ android:order="8"/> --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java @@ -62,17 +62,17 @@ Subject: Add option to not persist tabs across sessions 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_SECURE_DNS = "secure_dns"; -@@ -52,7 +55,8 @@ public class PrivacySettings +@@ -53,7 +56,8 @@ public class PrivacySettings private static final String PREF_CLEAR_BROWSING_DATA = "clear_browsing_data"; private static final String[] NEW_PRIVACY_PREFERENCE_ORDER = {PREF_CLEAR_BROWSING_DATA, PREF_SAFE_BROWSING, PREF_CAN_MAKE_PAYMENT, PREF_NETWORK_PREDICTIONS, PREF_USAGE_STATS, -- PREF_SECURE_DNS, PREF_DO_NOT_TRACK}; -+ PREF_SECURE_DNS, PREF_DO_NOT_TRACK, +- PREF_SECURE_DNS, PREF_DO_NOT_TRACK, PREF_GLOBAL_PRIVACY_CONTROL}; ++ PREF_SECURE_DNS, PREF_DO_NOT_TRACK, PREF_GLOBAL_PRIVACY_CONTROL, + PREF_CLOSE_TABS_ON_EXIT}; private ManagedPreferenceDelegate mManagedPreferenceDelegate; -@@ -145,7 +149,11 @@ public class PrivacySettings +@@ -146,7 +150,11 @@ public class PrivacySettings @Override public boolean onPreferenceChange(Preference preference, Object newValue) { String key = preference.getKey(); @@ -85,7 +85,7 @@ Subject: Add option to not persist tabs across sessions UserPrefs.get(Profile.getLastUsedRegularProfile()) .setBoolean(Pref.CAN_MAKE_PAYMENT_ENABLED, (boolean) newValue); } else if (PREF_NETWORK_PREDICTIONS.equals(key)) { -@@ -207,6 +215,11 @@ public class PrivacySettings +@@ -215,6 +223,11 @@ public class PrivacySettings getPreferenceScreen().removePreference(usageStatsPref); } } @@ -99,7 +99,7 @@ Subject: Add option to not persist tabs across sessions private ChromeManagedPreferenceDelegate createManagedPreferenceDelegate() { --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -3747,6 +3747,12 @@ Data from your Incognito session will on +@@ -3753,6 +3753,12 @@ Data from your Incognito session will on IMAGE diff --git a/patches/Bromite/DoH-secure-mode-by-default.patch b/patches/Bromite/DoH-secure-mode-by-default.patch index f1b2a71..806f299 100644 --- a/patches/Bromite/DoH-secure-mode-by-default.patch +++ b/patches/Bromite/DoH-secure-mode-by-default.patch @@ -3,13 +3,13 @@ Date: Sat, 26 Sep 2020 14:23:19 +0100 Subject: DoH secure mode by default --- - .../browser/net/stub_resolver_config_reader.cc | 17 +---------------- - 1 file changed, 1 insertion(+), 16 deletions(-) + chrome/android/java/src/org/chromium/chrome/browser/policy/EnterpriseInfo.java | 2 - + chrome/browser/net/stub_resolver_config_reader.cc | 17 ---------- + 2 files changed, 2 insertions(+), 17 deletions(-) -diff --git a/chrome/browser/net/stub_resolver_config_reader.cc b/chrome/browser/net/stub_resolver_config_reader.cc --- a/chrome/browser/net/stub_resolver_config_reader.cc +++ b/chrome/browser/net/stub_resolver_config_reader.cc -@@ -153,7 +153,7 @@ StubResolverConfigReader::StubResolverConfigReader(PrefService* local_state, +@@ -153,7 +153,7 @@ StubResolverConfigReader::StubResolverCo if (entries.count("dns-over-https@1")) { // The user has "Enabled" selected. local_state_->SetString(prefs::kDnsOverHttpsMode, @@ -18,7 +18,7 @@ diff --git a/chrome/browser/net/stub_resolver_config_reader.cc b/chrome/browser/ } else if (entries.count("dns-over-https@2")) { // The user has "Disabled" selected. local_state_->SetString(prefs::kDnsOverHttpsMode, -@@ -327,22 +327,7 @@ SecureDnsConfig StubResolverConfigReader::GetAndUpdateConfiguration( +@@ -327,22 +327,7 @@ SecureDnsConfig StubResolverConfigReader check_parental_controls = false; } @@ -41,6 +41,14 @@ diff --git a/chrome/browser/net/stub_resolver_config_reader.cc b/chrome/browser/ parental_controls_checked_ = true; } --- -2.17.1 - +--- a/chrome/android/java/src/org/chromium/chrome/browser/policy/EnterpriseInfo.java ++++ b/chrome/android/java/src/org/chromium/chrome/browser/policy/EnterpriseInfo.java +@@ -43,7 +43,7 @@ public class EnterpriseInfo { + private OwnedState mOwnedState; + private Queue> mCallbackList; + +- private boolean mSkipAsyncCheckForTesting; ++ private boolean mSkipAsyncCheckForTesting = true; + + /** A simple tuple to hold onto named fields about the state of ownership. */ + public static class OwnedState { diff --git a/patches/series b/patches/series index 48abc6e..8d2abb2 100644 --- a/patches/series +++ b/patches/series @@ -39,6 +39,7 @@ ungoogled-chromium-android/Remove-ntp-sites.patch ungoogled-chromium-android/Add-save-data-flag.patch ungoogled-chromium-android/Add-always-desktop-option.patch ungoogled-chromium-android/Add-force-tablet-ui-option.patch +ungoogled-chromium-android/Add-global-privacy-control.patch Bromite/Add-exit-menu-item.patch Bromite/Add-flag-to-disable-WebGL.patch Bromite/Add-flags-to-disable-device-motion-orientation-APIs.patch diff --git a/patches/ungoogled-chromium-android/Add-global-privacy-control.patch b/patches/ungoogled-chromium-android/Add-global-privacy-control.patch new file mode 100644 index 0000000..dc11b9d --- /dev/null +++ b/patches/ungoogled-chromium-android/Add-global-privacy-control.patch @@ -0,0 +1,1025 @@ +From: Wengling Chen +Fri, 19 Feb 2021 20:26:12 +0200 +Subject: Add Global Privacy Control support + +--- + chrome/android/chrome_java_resources.gni | 1 + chrome/android/chrome_java_sources.gni | 1 + chrome/android/java/res/xml/global_privacy_control_preferences.xml | 33 +++ + chrome/android/java/res/xml/privacy_preferences.xml | 11 - + chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/GlobalPrivacyControlSettings.java | 57 ++++++ + chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java | 10 - + chrome/app/settings_strings.grdp | 9 + chrome/browser/extensions/api/preference/preference_api.cc | 2 + chrome/browser/extensions/api/settings_private/prefs_util.cc | 2 + chrome/browser/renderer_preferences_util.cc | 2 + chrome/browser/resources/settings/BUILD.gn | 1 + chrome/browser/resources/settings/privacy_page/BUILD.gn | 12 + + chrome/browser/resources/settings/privacy_page/cookies_page.html | 3 + chrome/browser/resources/settings/privacy_page/cookies_page.js | 1 + chrome/browser/resources/settings/privacy_page/global_privacy_control_toggle.html | 25 ++ + chrome/browser/resources/settings/privacy_page/global_privacy_control_toggle.js | 91 ++++++++++ + chrome/browser/ui/android/strings/android_chrome_strings.grd | 6 + chrome/browser/ui/browser_ui_prefs.cc | 3 + chrome/browser/ui/prefs/pref_watcher.cc | 2 + chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc | 7 + chrome/common/extensions/api/privacy.json | 5 + chrome/common/pref_names.cc | 3 + chrome/common/pref_names.h | 1 + chrome/common/url_constants.cc | 3 + chrome/common/url_constants.h | 3 + content/browser/loader/browser_initiated_resource_request.cc | 8 + content/common/content_constants_internal.cc | 1 + content/common/content_constants_internal.h | 3 + content/public/common/common_param_traits_macros.h | 1 + content/renderer/loader/web_worker_fetch_context_impl.cc | 4 + content/renderer/render_frame_impl.cc | 10 + + content/renderer/render_frame_impl.h | 1 + content/renderer/service_worker/service_worker_fetch_context_impl.cc | 4 + third_party/blink/common/renderer_preferences/renderer_preferences_mojom_traits.cc | 1 + third_party/blink/public/common/renderer_preferences/renderer_preferences.h | 1 + third_party/blink/public/common/renderer_preferences/renderer_preferences_mojom_traits.h | 5 + third_party/blink/public/mojom/renderer_preferences.mojom | 3 + third_party/blink/public/mojom/web_feature/web_feature.mojom | 1 + third_party/blink/public/web/web_local_frame_client.h | 7 + third_party/blink/renderer/bindings/idl_in_modules.gni | 1 + third_party/blink/renderer/core/frame/local_frame_client.h | 1 + third_party/blink/renderer/core/frame/local_frame_client_impl.cc | 7 + third_party/blink/renderer/core/frame/local_frame_client_impl.h | 1 + third_party/blink/renderer/core/loader/empty_clients.h | 1 + third_party/blink/renderer/modules/BUILD.gn | 1 + third_party/blink/renderer/modules/globalprivacycontrol/BUILD.gn | 26 ++ + third_party/blink/renderer/modules/globalprivacycontrol/idls.gni | 19 ++ + third_party/blink/renderer/modules/globalprivacycontrol/navigator_global_privacy_control.cc | 40 ++++ + third_party/blink/renderer/modules/globalprivacycontrol/navigator_global_privacy_control.h | 36 +++ + third_party/blink/renderer/modules/globalprivacycontrol/navigator_global_privacy_control.idl | 25 ++ + third_party/blink/renderer/modules/modules_idl_files.gni | 1 + 51 files changed, 499 insertions(+), 4 deletions(-) + + +--- a/chrome/android/chrome_java_resources.gni ++++ b/chrome/android/chrome_java_resources.gni +@@ -1057,6 +1057,7 @@ chrome_java_resources = [ + "java/res/xml/data_reduction_preferences_off_lite_mode.xml", + "java/res/xml/developer_preferences.xml", + "java/res/xml/do_not_track_preferences.xml", ++ "java/res/xml/global_privacy_control_preferences.xml", + "java/res/xml/google_services_preferences.xml", + "java/res/xml/homepage_preferences.xml", + "java/res/xml/languages_detailed_preferences.xml", +--- /dev/null ++++ b/chrome/android/java/res/xml/global_privacy_control_preferences.xml +@@ -0,0 +1,33 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +--- a/chrome/android/java/res/xml/privacy_preferences.xml ++++ b/chrome/android/java/res/xml/privacy_preferences.xml +@@ -28,21 +28,26 @@ + android:key="do_not_track" + android:title="@string/do_not_track_title" + android:order="3"/> ++ + ++ android:order="5"/> + ++ android:order="6"/> + ++ android:order="7"/> + +--- a/chrome/app/settings_strings.grdp ++++ b/chrome/app/settings_strings.grdp +@@ -1338,6 +1338,15 @@ + + Enabling "Do Not Track" means that a request will be included with your browsing traffic. Any effect depends on whether a website responds to the request, and how the request is interpreted. For example, some websites may respond to this request by showing you ads that aren't based on other websites you've visited. Many websites will still collect and use your browsing data - for example to improve security, to provide content, services, ads and recommendations on their websites, and to generate reporting statistics. <a target="_blank" href="$1">Learn more</a></a> + ++ ++ Enable Global Privacy Control to communicate your privacy preferences ++ ++ ++ Global Privacy Control ++ ++ ++ Global Privacy Control (GPC) is a proposed specification designed to allow Internet users to notify businesses of their privacy preferences, such as whether or not they want their personal information to be sold or shared. It consists of a setting or extension in the user’s browser or mobile device and acts as a mechanism that websites can use to indicate they support the specification. <a target="_blank" href="$1">Learn more</a></a> ++ + + Permissions and content settings + +--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd ++++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd +@@ -785,6 +785,12 @@ Touch & hold any word to search. To + + For example, some websites may respond to this request by showing you ads that aren’t based on other websites you’ve visited. Many websites will still collect and use your browsing data — for example to improve security, to provide content, ads and recommendations, and to generate reporting statistics. + ++ ++ “Global Privacy Control” ++ ++ ++ Global Privacy Control (GPC) is a proposed specification designed to allow Internet users to notify businesses of their privacy preferences, such as whether or not they want their personal information to be sold or shared. It consists of a setting or extension in the user’s browser or mobile device and acts as a mechanism that websites can use to indicate they support the specification. ++ + + Access payment methods + +--- /dev/null ++++ b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/GlobalPrivacyControlSettings.java +@@ -0,0 +1,57 @@ ++// Copyright 2021 The Ungoogled Chromium Authors. All rights reserved. ++// ++// This file is part of Ungoogled Chromium Android. ++// ++// Ungoogled Chromium Android 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 any later version. ++// ++// Ungoogled Chromium Android 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 Ungoogled Chromium Android. If not, ++// see . ++ ++package org.chromium.chrome.browser.privacy.settings; ++ ++import android.os.Bundle; ++ ++import androidx.preference.PreferenceFragmentCompat; ++ ++import org.chromium.chrome.R; ++import org.chromium.chrome.browser.preferences.Pref; ++import org.chromium.chrome.browser.profiles.Profile; ++import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; ++import org.chromium.components.browser_ui.settings.SettingsUtils; ++import org.chromium.components.prefs.PrefService; ++import org.chromium.components.user_prefs.UserPrefs; ++ ++/** ++ * Fragment to manage Global Privacy Control preference and to explain to the user what it does. ++ */ ++public class GlobalPrivacyControlSettings extends PreferenceFragmentCompat { ++ // Must match key in global_privacy_control_preferences.xml. ++ private static final String PREF_GLOBAL_PRIVACY_CONTROL_SWITCH = "global_privacy_control_switch"; ++ ++ @Override ++ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { ++ SettingsUtils.addPreferencesFromResource(this, R.xml.global_privacy_control_preferences); ++ getActivity().setTitle(R.string.global_privacy_control_title); ++ ++ ChromeSwitchPreference globalPrivacyControlSwitch = ++ (ChromeSwitchPreference) findPreference(PREF_GLOBAL_PRIVACY_CONTROL_SWITCH); ++ ++ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); ++ boolean isGlobalPrivacyControlEnabled = prefService.getBoolean(Pref.ENABLE_GLOBAL_PRIVACY_CONTROL); ++ globalPrivacyControlSwitch.setChecked(isGlobalPrivacyControlEnabled); ++ ++ globalPrivacyControlSwitch.setOnPreferenceChangeListener((preference, newValue) -> { ++ prefService.setBoolean(Pref.ENABLE_GLOBAL_PRIVACY_CONTROL, (boolean) newValue); ++ return true; ++ }); ++ } ++} +--- 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 +@@ -48,11 +48,12 @@ public class PrivacySettings + private static final String PREF_SECURE_DNS = "secure_dns"; + private static final String PREF_USAGE_STATS = "usage_stats_reporting"; + private static final String PREF_DO_NOT_TRACK = "do_not_track"; ++ private static final String PREF_GLOBAL_PRIVACY_CONTROL = "global_privacy_control"; + private static final String PREF_SAFE_BROWSING = "safe_browsing"; + private static final String PREF_CLEAR_BROWSING_DATA = "clear_browsing_data"; + private static final String[] NEW_PRIVACY_PREFERENCE_ORDER = {PREF_CLEAR_BROWSING_DATA, + PREF_SAFE_BROWSING, PREF_CAN_MAKE_PAYMENT, PREF_NETWORK_PREDICTIONS, PREF_USAGE_STATS, +- PREF_SECURE_DNS, PREF_DO_NOT_TRACK}; ++ PREF_SECURE_DNS, PREF_DO_NOT_TRACK, PREF_GLOBAL_PRIVACY_CONTROL}; + + private ManagedPreferenceDelegate mManagedPreferenceDelegate; + +@@ -179,6 +180,13 @@ public class PrivacySettings + ? R.string.text_on + : R.string.text_off); + } ++ ++ Preference globalPrivacyControlPref = findPreference(PREF_GLOBAL_PRIVACY_CONTROL); ++ if (globalPrivacyControlPref != null) { ++ globalPrivacyControlPref.setSummary(prefService.getBoolean(Pref.ENABLE_GLOBAL_PRIVACY_CONTROL) ++ ? R.string.text_on ++ : R.string.text_off); ++ } + + Preference secureDnsPref = findPreference(PREF_SECURE_DNS); + if (secureDnsPref != null && secureDnsPref.isVisible()) { +--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc ++++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +@@ -1272,6 +1272,8 @@ void AddPrivacyStrings(content::WebUIDat + {"discardedPerSiteSetting", IDS_POLICY_LABEL_IGNORED}, + {"doNotTrack", IDS_SETTINGS_ENABLE_DO_NOT_TRACK}, + {"doNotTrackDialogTitle", IDS_SETTINGS_ENABLE_DO_NOT_TRACK_DIALOG_TITLE}, ++ {"globalPrivacyControl", IDS_SETTINGS_ENABLE_GLOBAL_PRIVACY_CONTROL}, ++ {"globalPrivacyControlTitle", IDS_SETTINGS_ENABLE_GLOBAL_PRIVACY_CONTROL_DIALOG_TITLE}, + // TODO(crbug.com/1062607): This string is no longer used. Remove. + {"permissionsPageTitle", IDS_SETTINGS_PERMISSIONS}, + {"permissionsPageDescription", IDS_SETTINGS_PERMISSIONS_DESCRIPTION}, +@@ -1372,6 +1374,11 @@ void AddPrivacyStrings(content::WebUIDat + IDS_SETTINGS_ENABLE_DO_NOT_TRACK_DIALOG_TEXT, + base::ASCIIToUTF16(chrome::kDoNotTrackLearnMoreURL))); + html_source->AddString( ++ "globalPrivacyControlDialogMessage", ++ l10n_util::GetStringFUTF16( ++ IDS_SETTINGS_ENABLE_GLOBAL_PRIVACY_CONTROL_DIALOG_TEXT, ++ base::ASCIIToUTF16(chrome::kGlobalPrivacyControlLearnMoreURL))); ++ html_source->AddString( + "exceptionsLearnMoreURL", + base::ASCIIToUTF16(chrome::kContentSettingsExceptionsLearnMoreURL)); + html_source->AddBoolean( +--- a/chrome/common/url_constants.cc ++++ b/chrome/common/url_constants.cc +@@ -141,6 +141,9 @@ const char kDoNotTrackLearnMoreURL[] = + "https://support.9oo91e.qjz9zk/chrome/?p=settings_do_not_track"; + #endif + ++const char kGlobalPrivacyControlLearnMoreURL[] = ++ "https://globalprivacycontrol.org/#faq"; ++ + const char kDownloadInterruptedLearnMoreURL[] = + "https://support.9oo91e.qjz9zk/chrome/?p=ui_download_errors"; + +--- a/chrome/common/url_constants.h ++++ b/chrome/common/url_constants.h +@@ -139,6 +139,9 @@ extern const char kCrashReasonFeedbackDi + // "Learn more" URL for the "Do not track" setting in the privacy section. + extern const char kDoNotTrackLearnMoreURL[]; + ++// "Learn more" URL for the "Do not track" setting in the privacy section. ++extern const char kGlobalPrivacyControlLearnMoreURL[]; ++ + // The URL for the "Learn more" page for interrupted downloads. + extern const char kDownloadInterruptedLearnMoreURL[]; + +--- a/content/public/common/common_param_traits_macros.h ++++ b/content/public/common/common_param_traits_macros.h +@@ -126,6 +126,7 @@ IPC_STRUCT_TRAITS_BEGIN(blink::RendererP + IPC_STRUCT_TRAITS_MEMBER(use_custom_colors) + IPC_STRUCT_TRAITS_MEMBER(enable_referrers) + IPC_STRUCT_TRAITS_MEMBER(enable_do_not_track) ++ IPC_STRUCT_TRAITS_MEMBER(enable_global_privacy_control) + IPC_STRUCT_TRAITS_MEMBER(enable_encrypted_media) + IPC_STRUCT_TRAITS_MEMBER(webrtc_ip_handling_policy) + IPC_STRUCT_TRAITS_MEMBER(webrtc_udp_min_port) +--- a/content/renderer/loader/web_worker_fetch_context_impl.cc ++++ b/content/renderer/loader/web_worker_fetch_context_impl.cc +@@ -454,6 +454,10 @@ void WebWorkerFetchContextImpl::WillSend + request.SetHttpHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader), + "1"); + } ++ if (renderer_preferences_.enable_global_privacy_control) { ++ request.SetHttpHeaderField(blink::WebString::FromUTF8(kGlobalPrivacyControlHeader), ++ "1"); ++ } + + auto url_request_extra_data = + base::MakeRefCounted(); +--- a/content/browser/loader/browser_initiated_resource_request.cc ++++ b/content/browser/loader/browser_initiated_resource_request.cc +@@ -38,6 +38,14 @@ void UpdateAdditionalHeadersForBrowserIn + headers->SetHeaderIfMissing(kDoNotTrackHeader, "1"); + } + ++ // Set the GlobalPrivacyControl header if appropriate. ++ if (renderer_preferences.enable_global_privacy_control) { ++ if (should_update_existing_headers) { ++ headers->RemoveHeader(kGlobalPrivacyControlHeader); ++ } ++ headers->SetHeaderIfMissing(kGlobalPrivacyControlHeader, "1"); ++ } ++ + // Set the Save-Data header if appropriate. + // https://tools.ietf.org/html/draft-grigorik-http-client-hints-03#section-7 + if ((GetContentClient()->browser()->IsDataSaverEnabled(browser_context) && +--- a/content/common/content_constants_internal.cc ++++ b/content/common/content_constants_internal.cc +@@ -18,6 +18,7 @@ const int kTraceEventGpuProcessSortIndex + const int kTraceEventRendererMainThreadSortIndex = -1; + + const char kDoNotTrackHeader[] = "DNT"; ++const char kGlobalPrivacyControlHeader[] = "Sec-GPC"; + + const int kChildProcessReceiverAttachmentName = 0; + const int kChildProcessHostRemoteAttachmentName = 1; +--- a/content/common/content_constants_internal.h ++++ b/content/common/content_constants_internal.h +@@ -41,6 +41,9 @@ CONTENT_EXPORT extern const int kTraceEv + // HTTP header set in requests to indicate they should be marked DoNotTrack. + extern const char kDoNotTrackHeader[]; + ++// HTTP header set in requests to indicate the Global Privacy Control signal. ++extern const char kGlobalPrivacyControlHeader[]; ++ + // Constants for attaching message pipes to the mojo invitation used to + // initialize child processes. + extern const int kChildProcessReceiverAttachmentName; +--- a/content/renderer/render_frame_impl.cc ++++ b/content/renderer/render_frame_impl.cc +@@ -4632,6 +4632,10 @@ void RenderFrameImpl::WillSendRequestInt + request.SetHttpHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader), + "1"); + } ++ if (render_view_->GetRendererPreferences().enable_global_privacy_control) { ++ request.SetHttpHeaderField(blink::WebString::FromUTF8(kGlobalPrivacyControlHeader), ++ "1"); ++ } + + ApplyFilePathAlias(&request); + GURL new_url; +@@ -4910,6 +4914,12 @@ blink::WebString RenderFrameImpl::DoNotT + return WebString::FromUTF8("1"); + return WebString(); + } ++ ++blink::WebString RenderFrameImpl::GlobalPrivacyControlValue() { ++ if (render_view_->GetRendererPreferences().enable_global_privacy_control) ++ return WebString::FromUTF8("1"); ++ return WebString(); ++} + + blink::mojom::RendererAudioInputStreamFactory* + RenderFrameImpl::GetAudioInputStreamFactory() { +--- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc ++++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc +@@ -118,6 +118,10 @@ void ServiceWorkerFetchContextImpl::Will + request.SetHttpHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader), + "1"); + } ++ if (renderer_preferences_.enable_global_privacy_control) { ++ request.SetHttpHeaderField(blink::WebString::FromUTF8(kGlobalPrivacyControlHeader), ++ "1"); ++ } + auto url_request_extra_data = + base::MakeRefCounted(); + url_request_extra_data->set_originated_from_service_worker(true); +--- a/content/renderer/render_frame_impl.h ++++ b/content/renderer/render_frame_impl.h +@@ -679,6 +679,7 @@ class CONTENT_EXPORT RenderFrameImpl + blink::WebString UserAgentOverride() override; + base::Optional UserAgentMetadataOverride() override; + blink::WebString DoNotTrackValue() override; ++ blink::WebString GlobalPrivacyControlValue() override; + blink::mojom::RendererAudioInputStreamFactory* GetAudioInputStreamFactory(); + bool AllowContentInitiatedDataUrlNavigations( + const blink::WebURL& url) override; +--- a/third_party/blink/public/web/web_local_frame_client.h ++++ b/third_party/blink/public/web/web_local_frame_client.h +@@ -588,6 +588,13 @@ class BLINK_EXPORT WebLocalFrameClient { + // header. An empty string indicates that no DNT header will be send. + virtual WebString DoNotTrackValue() { return WebString(); } + ++ // Global privacy control ---------------------------------------------------- ++ ++ // Asks the embedder what value the network stack will send for the ++ // Global Privacy Control header. An empty string indicates that ++ // no Global Privacy Control header will be send. ++ virtual WebString GlobalPrivacyControlValue() { return WebString(); } ++ + // + // Accessibility ------------------------------------------------------- + // +--- a/third_party/blink/renderer/core/frame/local_frame_client.h ++++ b/third_party/blink/renderer/core/frame/local_frame_client.h +@@ -234,6 +234,7 @@ class CORE_EXPORT LocalFrameClient : pub + virtual base::Optional UserAgentMetadata() = 0; + + virtual String DoNotTrackValue() = 0; ++ virtual String GlobalPrivacyControlValue() = 0; + + virtual void TransitionToCommittedForNewPage() = 0; + +--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc ++++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc +@@ -883,6 +883,13 @@ String LocalFrameClientImpl::DoNotTrackV + return String(); + } + ++String LocalFrameClientImpl::GlobalPrivacyControlValue() { ++ WebString global_privacy_control = web_frame_->Client()->GlobalPrivacyControlValue(); ++ if (!global_privacy_control.IsEmpty()) ++ return global_privacy_control; ++ return String(); ++} ++ + // Called when the FrameLoader goes into a state in which a new page load + // will occur. + void LocalFrameClientImpl::TransitionToCommittedForNewPage() { +--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h ++++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h +@@ -164,6 +164,7 @@ class CORE_EXPORT LocalFrameClientImpl f + WTF::String UserAgent() override; + base::Optional UserAgentMetadata() override; + WTF::String DoNotTrackValue() override; ++ WTF::String GlobalPrivacyControlValue() override; + void TransitionToCommittedForNewPage() override; + LocalFrame* CreateFrame(const WTF::AtomicString& name, + HTMLFrameOwnerElement*) override; +--- a/third_party/blink/renderer/core/loader/empty_clients.h ++++ b/third_party/blink/renderer/core/loader/empty_clients.h +@@ -294,6 +294,7 @@ class CORE_EXPORT EmptyLocalFrameClient + } + + String DoNotTrackValue() override { return String(); } ++ String GlobalPrivacyControlValue() override { return String(); } + + void TransitionToCommittedForNewPage() override {} + +--- a/chrome/browser/extensions/api/preference/preference_api.cc ++++ b/chrome/browser/extensions/api/preference/preference_api.cc +@@ -115,6 +115,8 @@ const PrefMappingEntry kPrefMapping[] = + APIPermission::kPrivacy}, + {"doNotTrackEnabled", prefs::kEnableDoNotTrack, APIPermission::kPrivacy, + APIPermission::kPrivacy}, ++ {"globalPrivacyControlEnabled", prefs::kEnableGlobalPrivacyControl, APIPermission::kPrivacy, ++ APIPermission::kPrivacy}, + {"searchSuggestEnabled", prefs::kSearchSuggestEnabled, + APIPermission::kPrivacy, APIPermission::kPrivacy}, + {"spellingServiceEnabled", spellcheck::prefs::kSpellCheckUseSpellingService, +--- /dev/null ++++ b/chrome/browser/resources/settings/privacy_page/global_privacy_control_toggle.html +@@ -0,0 +1,25 @@ ++ ++ ++ ++ +--- /dev/null ++++ b/chrome/browser/resources/settings/privacy_page/global_privacy_control_toggle.js +@@ -0,0 +1,91 @@ ++// Copyright 2020 The Chromium Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; ++import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; ++import '../settings_shared_css.m.js'; ++import '../controls/settings_toggle_button.m.js'; ++ ++import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js'; ++import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; ++ ++import {MetricsBrowserProxyImpl, PrivacyElementInteractions} from '../metrics_browser_proxy.js'; ++ ++Polymer({ ++ is: 'settings-global-privacy-control-toggle', ++ ++ _template: html`{__html_template__}`, ++ ++ properties: { ++ /** ++ * Preferences state. ++ */ ++ prefs: { ++ type: Object, ++ notify: true, ++ }, ++ ++ /** @private */ ++ showDialog_: { ++ type: Boolean, ++ value: false, ++ }, ++ }, ++ ++ /** @private */ ++ onDomChange_() { ++ if (this.showDialog_) { ++ this.$$('#confirmDialog').showModal(); ++ } ++ }, ++ ++ /** ++ * Handles the change event for the global-privacy-control toggle. Shows a ++ * confirmation dialog when enabling the setting. ++ * @param {!Event} event ++ * @private ++ */ ++ onToggleChange_(event) { ++ const target = /** @type {!SettingsToggleButtonElement} */ (event.target); ++ if (!target.checked) { ++ // Always allow disabling the pref. ++ target.sendPrefChange(); ++ return; ++ } ++ ++ this.showDialog_ = true; ++ }, ++ ++ /** @private */ ++ closeDialog_() { ++ this.$$('#confirmDialog').close(); ++ this.showDialog_ = false; ++ }, ++ ++ /** @private */ ++ onDialogClosed_() { ++ focusWithoutInk(this.$.toggle); ++ }, ++ ++ /** ++ * Handles the shared proxy confirmation dialog 'Confirm' button. ++ * @private ++ */ ++ onDialogConfirm_() { ++ /** @type {!SettingsToggleButtonElement} */ (this.$.toggle) ++ .sendPrefChange(); ++ this.closeDialog_(); ++ }, ++ ++ /** ++ * Handles the shared proxy confirmation dialog 'Cancel' button or a cancel ++ * event. ++ * @private ++ */ ++ onDialogCancel_() { ++ /** @type {!SettingsToggleButtonElement} */ (this.$.toggle) ++ .resetToPrefValue(); ++ this.closeDialog_(); ++ }, ++}); +--- a/chrome/common/extensions/api/privacy.json ++++ b/chrome/common/extensions/api/privacy.json +@@ -105,6 +105,11 @@ + "value": ["doNotTrackEnabled", {"type":"boolean"}], + "description": "If enabled, Chrome sends 'Do Not Track' (DNT: 1) header with your requests. The value of this preference is of type boolean, and the default value is false." + }, ++ "globalPrivacyControlEnabled": { ++ "$ref": "types.ChromeSetting", ++ "value": ["globalPrivacyControlEnabled", {"type":"boolean"}], ++ "description": "If enabled, Chrome sends 'Global Privacy Control' (Sec-GPC: 1) header with your requests. The value of this preference is of type boolean, and the default value is false." ++ }, + "protectedContentEnabled": { + "$ref": "types.ChromeSetting", + "value": ["protectedContentEnabled", {"type":"boolean"}], +--- a/chrome/browser/resources/settings/BUILD.gn ++++ b/chrome/browser/resources/settings/BUILD.gn +@@ -231,6 +231,7 @@ preprocess_grit("preprocess_generated") + "privacy_page/collapse_radio_button.js", + "privacy_page/cookies_page.js", + "privacy_page/do_not_track_toggle.js", ++ "privacy_page/global_privacy_control_toggle.js", + "privacy_page/privacy_page.js", + "privacy_page/personalization_options.m.js", + "privacy_page/privacy_page_browser_proxy.m.js", +--- a/chrome/browser/resources/settings/privacy_page/BUILD.gn ++++ b/chrome/browser/resources/settings/privacy_page/BUILD.gn +@@ -45,6 +45,7 @@ js_type_check("closure_compile_module") + ":cookies_page", + ":disable_safebrowsing_dialog", + ":do_not_track_toggle", ++ ":global_privacy_control_toggle", + ":personalization_options.m", + ":privacy_page", + ":privacy_page_browser_proxy.m", +@@ -65,6 +66,7 @@ js_library("cookies_page") { + deps = [ + ":collapse_radio_button", + ":do_not_track_toggle", ++ ":global_privacy_control_toggle", + "..:metrics_browser_proxy", + "..:route", + "..:router.m", +@@ -120,6 +122,15 @@ js_library("do_not_track_toggle") { + ] + } + ++js_library("global_privacy_control_toggle") { ++ deps = [ ++ "..:metrics_browser_proxy", ++ "../controls:settings_toggle_button.m", ++ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ++ "//ui/webui/resources/js/cr/ui:focus_without_ink.m", ++ ] ++} ++ + js_library("personalization_options.m") { + sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/personalization_options.m.js" ] + deps = [ +@@ -256,6 +267,7 @@ html_to_js("v3_ready_elements") { + "cookies_page.js", + "disable_safebrowsing_dialog.js", + "do_not_track_toggle.js", ++ "global_privacy_control_toggle.js", + "privacy_page.js", + "secure_dns.js", + "secure_dns_input.js", +--- a/chrome/browser/resources/settings/privacy_page/cookies_page.html ++++ b/chrome/browser/resources/settings/privacy_page/cookies_page.html +@@ -128,6 +128,9 @@ + + ++ ++ +