diff --git a/android/brave_java_resources.gni b/android/brave_java_resources.gni index e3baaa3a1bc5..3f836459502a 100644 --- a/android/brave_java_resources.gni +++ b/android/brave_java_resources.gni @@ -707,6 +707,7 @@ brave_java_resources = [ "java/res/layout/brave_sync_done.xml", "java/res/layout/brave_sync_layout.xml", "java/res/layout/brave_toolbar.xml", + "java/res/layout/brave_webrtc_policy_preference.xml", "java/res/layout/bre_bottom_banner.xml", "java/res/layout/crypto_widget_layout.xml", "java/res/layout/ddg_offer_layout.xml", @@ -774,6 +775,7 @@ brave_java_resources = [ "java/res/xml/brave_rewards_preferences.xml", "java/res/xml/brave_stats_preferences.xml", "java/res/xml/brave_theme_preferences.xml", + "java/res/xml/brave_webrtc_policy_preferences.xml", "java/res/xml/clear_browsing_data_preferences_tab.xml", "java/res/xml/closing_all_tabs_closes_brave_preference.xml", "java/res/xml/desktop_mode_preferences.xml", diff --git a/android/brave_java_sources.gni b/android/brave_java_sources.gni index 5ecd8a70f8ae..1855299e9fc7 100644 --- a/android/brave_java_sources.gni +++ b/android/brave_java_sources.gni @@ -156,6 +156,8 @@ brave_java_sources = [ "../../brave/android/java/org/chromium/chrome/browser/settings/BraveSettingsLauncherImpl.java", "../../brave/android/java/org/chromium/chrome/browser/settings/BraveStandardSearchEnginePreference.java", "../../brave/android/java/org/chromium/chrome/browser/settings/BraveStatsPreferences.java", + "../../brave/android/java/org/chromium/chrome/browser/settings/BraveWebrtcPolicyPreference.java", + "../../brave/android/java/org/chromium/chrome/browser/settings/BraveWebrtcPolicyPreferencesFragment.java", "../../brave/android/java/org/chromium/chrome/browser/settings/ClosingAllTabsClosesBravePreference.java", "../../brave/android/java/org/chromium/chrome/browser/settings/SearchEngineTabModelSelectorObserver.java", "../../brave/android/java/org/chromium/chrome/browser/settings/developer/BraveQAPreferences.java", diff --git a/android/java/org/chromium/chrome/browser/preferences/BravePrefServiceBridge.java b/android/java/org/chromium/chrome/browser/preferences/BravePrefServiceBridge.java index 182727c85fda..ddc224f6e5b7 100644 --- a/android/java/org/chromium/chrome/browser/preferences/BravePrefServiceBridge.java +++ b/android/java/org/chromium/chrome/browser/preferences/BravePrefServiceBridge.java @@ -218,6 +218,14 @@ public int getENSResolveMethod() { return BravePrefServiceBridgeJni.get().getENSResolveMethod(); } + public void setWebrtcPolicy(int policy) { + BravePrefServiceBridgeJni.get().setWebrtcPolicy(policy); + } + + public int getWebrtcPolicy() { + return BravePrefServiceBridgeJni.get().getWebrtcPolicy(); + } + @NativeMethods interface Natives { void setHTTPSEEnabled(boolean enabled); @@ -275,5 +283,8 @@ interface Natives { void setENSResolveMethod(int method); int getUnstoppableDomainsResolveMethod(); int getENSResolveMethod(); + + void setWebrtcPolicy(int policy); + int getWebrtcPolicy(); } } diff --git a/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java b/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java index 0059be715b39..fe7a1351a8bb 100644 --- a/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java +++ b/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java @@ -19,8 +19,10 @@ import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.privacy.settings.PrivacySettings; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.settings.BraveWebrtcPolicyPreference; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.components.browser_ui.settings.ChromeBaseCheckBoxPreference; +import org.chromium.components.browser_ui.settings.ChromeBasePreference; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.prefs.PrefService; @@ -43,6 +45,7 @@ public class BravePrivacySettings extends PrivacySettings { private static final String PREF_SOCIAL_BLOCKING_TWITTER = "social_blocking_twitter"; private static final String PREF_SOCIAL_BLOCKING_LINKEDIN = "social_blocking_linkedin"; private static final String PREF_DO_NOT_TRACK = "do_not_track"; + private static final String PREF_WEBRTC_POLICY = "webrtc_policy"; private final PrefService mPrefServiceBridge = UserPrefs.get(Profile.getLastUsedRegularProfile()); private final ChromeManagedPreferenceDelegate mManagedPreferenceDelegate = @@ -61,6 +64,7 @@ public class BravePrivacySettings extends PrivacySettings { private ChromeSwitchPreference mSocialBlockingFacebook; private ChromeSwitchPreference mSocialBlockingTwitter; private ChromeSwitchPreference mSocialBlockingLinkedin; + private ChromeBasePreference mWebrtcPolicy; @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { @@ -114,6 +118,8 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { mSocialBlockingLinkedin = (ChromeSwitchPreference) findPreference(PREF_SOCIAL_BLOCKING_LINKEDIN); mSocialBlockingLinkedin.setOnPreferenceChangeListener(this); + mWebrtcPolicy = (ChromeBasePreference) findPreference(PREF_WEBRTC_POLICY); + updatePreferences(); } @@ -184,6 +190,9 @@ private void updatePreferences() { mAdBlockPref.setOrder(++order); mFingerprintingProtectionPref.setOrder(++order); mSearchSuggestions.setOrder(++order); + mWebrtcPolicy.setOrder(++order); + mWebrtcPolicy.setSummary( + webrtcPolicyToString(BravePrefServiceBridge.getInstance().getWebrtcPolicy())); mAutocompleteTopSites .setChecked(UserPrefs.get(Profile.getLastUsedRegularProfile()).getBoolean(BravePref.TOP_SITE_SUGGESTIONS_ENABLED)); mAutocompleteTopSites.setOrder(++order); @@ -209,4 +218,23 @@ private ChromeManagedPreferenceDelegate createManagedPreferenceDelegate() { return false; }; } + + private String webrtcPolicyToString(@BraveWebrtcPolicyPreference.WebrtcPolicy int policy) { + switch (policy) { + case BraveWebrtcPolicyPreference.WebrtcPolicy.DEFAULT: + return getActivity().getResources().getString( + R.string.settings_webrtc_policy_default); + case BraveWebrtcPolicyPreference.WebrtcPolicy.DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES: + return getActivity().getResources().getString( + R.string.settings_webrtc_policy_default_public_and_private_interfaces); + case BraveWebrtcPolicyPreference.WebrtcPolicy.DEFAULT_PUBLIC_INTERFACE_ONLY: + return getActivity().getResources().getString( + R.string.settings_webrtc_policy_default_public_interface_only); + case BraveWebrtcPolicyPreference.WebrtcPolicy.DISABLE_NON_PROXIED_UDP: + return getActivity().getResources().getString( + R.string.settings_webrtc_policy_disable_non_proxied_udp); + } + assert false : "Setting is out of range!"; + return ""; + } } diff --git a/android/java/org/chromium/chrome/browser/settings/BraveWebrtcPolicyPreference.java b/android/java/org/chromium/chrome/browser/settings/BraveWebrtcPolicyPreference.java new file mode 100644 index 000000000000..ea0442eef603 --- /dev/null +++ b/android/java/org/chromium/chrome/browser/settings/BraveWebrtcPolicyPreference.java @@ -0,0 +1,89 @@ +/* Copyright (c) 2021 The Brave Authors. All rights reserved. + * 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.settings; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.RadioGroup; + +import androidx.annotation.IntDef; +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; + +import org.chromium.chrome.R; +import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; +import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout; + +import java.util.ArrayList; +import java.util.Collections; + +public class BraveWebrtcPolicyPreference + extends Preference implements RadioGroup.OnCheckedChangeListener { + @IntDef({WebrtcPolicy.DEFAULT, WebrtcPolicy.DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES, + WebrtcPolicy.DEFAULT_PUBLIC_INTERFACE_ONLY, WebrtcPolicy.DISABLE_NON_PROXIED_UDP}) + public @interface WebrtcPolicy { + int DEFAULT = 0; + int DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES = 1; + int DEFAULT_PUBLIC_INTERFACE_ONLY = 2; + int DISABLE_NON_PROXIED_UDP = 3; + + int NUM_ENTRIES = 4; + } + + private @WebrtcPolicy int mSetting; + private RadioButtonWithDescription mSettingRadioButton; + private RadioButtonWithDescriptionLayout mGroup; + private ArrayList mButtons; + + public BraveWebrtcPolicyPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + setLayoutResource(R.layout.brave_webrtc_policy_preference); + + mButtons = new ArrayList<>(Collections.nCopies(WebrtcPolicy.NUM_ENTRIES, null)); + } + + public void initialize(@WebrtcPolicy int policy) { + mSetting = policy; + } + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + + mGroup = (RadioButtonWithDescriptionLayout) holder.findViewById(R.id.radio_button_layout); + mGroup.setOnCheckedChangeListener(this); + + mButtons.set(WebrtcPolicy.DEFAULT, + (RadioButtonWithDescription) holder.findViewById(R.id.webrtc_policy_default)); + mButtons.set(WebrtcPolicy.DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES, + (RadioButtonWithDescription) holder.findViewById( + R.id.webrtc_policy_default_public_and_private_interfaces)); + mButtons.set(WebrtcPolicy.DEFAULT_PUBLIC_INTERFACE_ONLY, + (RadioButtonWithDescription) holder.findViewById( + R.id.webrtc_policy_default_public_interface_only)); + mButtons.set(WebrtcPolicy.DISABLE_NON_PROXIED_UDP, + (RadioButtonWithDescription) holder.findViewById( + R.id.webrtc_policy_disable_non_proxied_udp)); + + mSettingRadioButton = mButtons.get(mSetting); + mSettingRadioButton.setChecked(true); + } + + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + for (int i = 0; i < WebrtcPolicy.NUM_ENTRIES; i++) { + if (mButtons.get(i).isChecked()) { + mSetting = i; + mSettingRadioButton = mButtons.get(i); + break; + } + } + assert mSetting >= 0 && mSetting < WebrtcPolicy.NUM_ENTRIES : "No matching setting found."; + + callChangeListener(mSetting); + } +} diff --git a/android/java/org/chromium/chrome/browser/settings/BraveWebrtcPolicyPreferencesFragment.java b/android/java/org/chromium/chrome/browser/settings/BraveWebrtcPolicyPreferencesFragment.java new file mode 100644 index 000000000000..dc3d829a1f6a --- /dev/null +++ b/android/java/org/chromium/chrome/browser/settings/BraveWebrtcPolicyPreferencesFragment.java @@ -0,0 +1,50 @@ +/* Copyright (c) 2021 The Brave Authors. All rights reserved. + * 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.settings; + +import android.os.Build; +import android.os.Bundle; + +import androidx.annotation.Nullable; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.preferences.BravePrefServiceBridge; +import org.chromium.components.browser_ui.settings.SettingsUtils; +import org.chromium.ui.UiUtils; + +/** + * Fragment to manage webrtc policy settings. + */ +public class BraveWebrtcPolicyPreferencesFragment extends BravePreferenceFragment { + static final String PREF_WEBRTC_POLICY = "webrtc_policy"; + + @Override + public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) { + SettingsUtils.addPreferencesFromResource(this, R.xml.brave_webrtc_policy_preferences); + getActivity().setTitle(R.string.settings_webrtc_policy_label); + + BraveWebrtcPolicyPreference webrtcPolicyPreference = + (BraveWebrtcPolicyPreference) findPreference(PREF_WEBRTC_POLICY); + webrtcPolicyPreference.initialize(BravePrefServiceBridge.getInstance().getWebrtcPolicy()); + + webrtcPolicyPreference.setOnPreferenceChangeListener((preference, newValue) -> { + BravePrefServiceBridge.getInstance().setWebrtcPolicy((int) newValue); + return true; + }); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) { + UiUtils.setNavigationBarIconColor(getActivity().getWindow().getDecorView(), + getResources().getBoolean(R.bool.window_light_navigation_bar)); + } + + setDivider(null); + } +} diff --git a/android/java/res/layout/brave_webrtc_policy_preference.xml b/android/java/res/layout/brave_webrtc_policy_preference.xml new file mode 100644 index 000000000000..462b99a72590 --- /dev/null +++ b/android/java/res/layout/brave_webrtc_policy_preference.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + diff --git a/android/java/res/xml/brave_privacy_preferences.xml b/android/java/res/xml/brave_privacy_preferences.xml index d472a6100f93..6d357f5326ac 100644 --- a/android/java/res/xml/brave_privacy_preferences.xml +++ b/android/java/res/xml/brave_privacy_preferences.xml @@ -57,6 +57,11 @@ android:key="autocomplete_brave_suggested_sites" android:title="@string/autocomplete_brave_suggested_sites_title" android:persistent="false"/> + diff --git a/android/java/res/xml/brave_webrtc_policy_preferences.xml b/android/java/res/xml/brave_webrtc_policy_preferences.xml new file mode 100644 index 000000000000..c9e4c8e4484b --- /dev/null +++ b/android/java/res/xml/brave_webrtc_policy_preferences.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/browser/android/preferences/brave_pref_service_bridge.cc b/browser/android/preferences/brave_pref_service_bridge.cc index 10aa1e48996d..a5e1a38bd3f8 100644 --- a/browser/android/preferences/brave_pref_service_bridge.cc +++ b/browser/android/preferences/brave_pref_service_bridge.cc @@ -21,8 +21,10 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/common/pref_names.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/prefs/pref_service.h" +#include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h" #include "url/gurl.h" #if BUILDFLAG(ENABLE_BRAVE_PERF_PREDICTOR) @@ -53,6 +55,34 @@ Profile* GetOriginalProfile() { return ProfileManager::GetActiveUserProfile()->GetOriginalProfile(); } +enum WebRTCIPHandlingPolicy { + DEFAULT, + DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES, + DEFAULT_PUBLIC_INTERFACE_ONLY, + DISABLE_NON_PROXIED_UDP, +}; + +WebRTCIPHandlingPolicy GetWebRTCIPHandlingPolicy( + const std::string& preference) { + if (preference == blink::kWebRTCIPHandlingDefaultPublicAndPrivateInterfaces) + return DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES; + if (preference == blink::kWebRTCIPHandlingDefaultPublicInterfaceOnly) + return DEFAULT_PUBLIC_INTERFACE_ONLY; + if (preference == blink::kWebRTCIPHandlingDisableNonProxiedUdp) + return DISABLE_NON_PROXIED_UDP; + return DEFAULT; +} + +std::string GetWebRTCIPHandlingPreference(WebRTCIPHandlingPolicy policy) { + if (policy == DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES) + return blink::kWebRTCIPHandlingDefaultPublicAndPrivateInterfaces; + if (policy == DEFAULT_PUBLIC_INTERFACE_ONLY) + return blink::kWebRTCIPHandlingDefaultPublicInterfaceOnly; + if (policy == DISABLE_NON_PROXIED_UDP) + return blink::kWebRTCIPHandlingDisableNonProxiedUdp; + return blink::kWebRTCIPHandlingDefault; +} + } // namespace namespace chrome { @@ -312,6 +342,18 @@ void JNI_BravePrefServiceBridge_SetReferralDownloadId( kReferralDownloadID, ConvertJavaStringToUTF8(env, downloadId)); } +jint JNI_BravePrefServiceBridge_GetWebrtcPolicy(JNIEnv* env) { + return static_cast( + GetWebRTCIPHandlingPolicy(GetOriginalProfile()->GetPrefs()->GetString( + prefs::kWebRTCIPHandlingPolicy))); +} + +void JNI_BravePrefServiceBridge_SetWebrtcPolicy(JNIEnv* env, jint policy) { + GetOriginalProfile()->GetPrefs()->SetString( + prefs::kWebRTCIPHandlingPolicy, + GetWebRTCIPHandlingPreference((WebRTCIPHandlingPolicy)policy)); +} + #if BUILDFLAG(BRAVE_P3A_ENABLED) void JNI_BravePrefServiceBridge_SetP3AEnabled( JNIEnv* env, diff --git a/browser/ui/android/strings/android_brave_strings.grd b/browser/ui/android/strings/android_brave_strings.grd index be705151ca64..32c5c8d0607c 100644 --- a/browser/ui/android/strings/android_brave_strings.grd +++ b/browser/ui/android/strings/android_brave_strings.grd @@ -1652,6 +1652,21 @@ until they verify, or until 90 days have passed. 0.00 USD + + WebRTC IP handling policy + + + Default + + + Default public and private interfaces + + + Default public interface only + + + Disable non-proxied UDP + diff --git a/build/commands/lib/config.js b/build/commands/lib/config.js index 652933cfdc3f..21173514f961 100755 --- a/build/commands/lib/config.js +++ b/build/commands/lib/config.js @@ -352,6 +352,9 @@ Config.prototype.buildArgs = function () { // TODO(fixme) args.enable_tor = false + // Fixes WebRTC IP leak with default option + args.enable_mdns = true + // These do not exist on android // TODO - recheck delete args.enable_nacl