Commit 21660590 authored by Ben Schwartz's avatar Ben Schwartz Committed by Commit Bot

Modularize the Secure DNS Android UI

Bug: 1098883
Change-Id: I52fd87ecd652e7224fd6190f1f58ba36b4f6b148
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2276311Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarNatalie Chouinard <chouinard@chromium.org>
Commit-Queue: Ben Schwartz <bemasc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791800}
parent a38220b8
......@@ -322,6 +322,7 @@ android_library("chrome_java") {
"//chrome/browser/password_check:public_java",
"//chrome/browser/performance_hints/android:java",
"//chrome/browser/preferences:java",
"//chrome/browser/privacy:java",
"//chrome/browser/profiles/android:java",
"//chrome/browser/safe_browsing/android:java",
"//chrome/browser/safety_check/android:java",
......@@ -517,7 +518,6 @@ android_library("chrome_java") {
"//chrome:supervised_user_url_filter_enum_javagen",
"//chrome/browser:sharing_dialog_type_generated_enum",
"//chrome/browser:sharing_send_message_result_generated_enum",
"//chrome/browser/net:secure_dns_management_mode_generated_enum",
"//chrome/browser/notifications/scheduler/public:jni_enums",
"//chrome/browser/supervised_user/supervised_user_error_page:enums_srcjar",
"//chrome/browser/updates/announcement_notification:jni_enums",
......@@ -536,7 +536,6 @@ android_library("chrome_java") {
"//components/ui_metrics:ui_metrics_enums_java",
"//content/public/browser:contacts_picker_properties_requested_javagen",
"//net:effective_connection_type_java",
"//net/dns:secure_dns_mode_generated_enum",
]
# From java_sources.gni.
......@@ -653,6 +652,7 @@ group("jni_headers") {
"//chrome/browser/image_fetcher:jni_headers",
"//chrome/browser/performance_hints/android:jni_headers",
"//chrome/browser/preferences:jni_headers",
"//chrome/browser/privacy:jni_headers",
"//chrome/browser/profiles/android:jni_headers",
"//chrome/browser/tab:jni_headers",
"//chrome/browser/touch_to_fill/android:jni_headers",
......
......@@ -989,8 +989,6 @@ chrome_java_resources = [
"java/res/layout/search_engine.xml",
"java/res/layout/search_engine_recent_title.xml",
"java/res/layout/search_widget_template.xml",
"java/res/layout/secure_dns_provider_preference.xml",
"java/res/layout/secure_dns_provider_spinner_item.xml",
"java/res/layout/send_tab_to_self_device_picker_item.xml",
"java/res/layout/send_tab_to_self_device_picker_list.xml",
"java/res/layout/send_tab_to_self_device_picker_toolbar.xml",
......@@ -1106,7 +1104,6 @@ chrome_java_resources = [
"java/res/xml/notifications_preferences.xml",
"java/res/xml/privacy_preferences.xml",
"java/res/xml/search_widget_info.xml",
"java/res/xml/secure_dns_settings.xml",
"java/res/xml/sync_and_services_preferences.xml",
"java/res/xml/theme_preferences.xml",
"java/res/xml/tracing_preferences.xml",
......
......@@ -1323,8 +1323,6 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/privacy/settings/DoNotTrackSettings.java",
"java/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManager.java",
"java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java",
"java/src/org/chromium/chrome/browser/privacy/settings/SecureDnsProviderPreference.java",
"java/src/org/chromium/chrome/browser/privacy/settings/SecureDnsSettings.java",
"java/src/org/chromium/chrome/browser/provider/BaseColumns.java",
"java/src/org/chromium/chrome/browser/provider/BookmarkColumns.java",
"java/src/org/chromium/chrome/browser/provider/ChromeBrowserProvider.java",
......
......@@ -3,6 +3,7 @@ include_rules = [
"+chrome/browser/android/lifecycle",
"+chrome/browser/android/thin_webview/java",
"+chrome/browser/privacy",
"+chrome/browser/profiles/android/java",
"+chrome/browser/share/android",
"+chrome/browser/tab",
......
......@@ -26,7 +26,7 @@
<org.chromium.components.browser_ui.settings.ChromeBasePreference
android:key="secure_dns"
android:title="@string/settings_secure_dns_title"
android:fragment="org.chromium.chrome.browser.privacy.settings.SecureDnsSettings" />
android:fragment="org.chromium.chrome.browser.privacy.secure_dns.SecureDnsSettings" />
<Preference
android:key="clear_browsing_data"
android:title="@string/clear_browsing_data_title"
......
......@@ -9,26 +9,19 @@ import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.CommandLine;
import org.chromium.base.ContextUtils;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.device.DeviceClassManager;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.net.SecureDnsManagementMode;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.survey.SurveyController;
import org.chromium.components.minidump_uploader.util.CrashReportingPermissionManager;
import org.chromium.components.minidump_uploader.util.NetworkPermissionUtil;
import org.chromium.content_public.browser.BrowserStartupController;
import org.chromium.net.SecureDnsMode;
import java.util.ArrayList;
import java.util.List;
/**
* Reads, writes, and migrates preferences related to network usage and privacy.
......@@ -37,27 +30,6 @@ public class PrivacyPreferencesManager implements CrashReportingPermissionManage
@SuppressLint("StaticFieldLeak")
private static PrivacyPreferencesManager sInstance;
/**
* A DohEntry represents the subset of a net::DohProviderEntry that is relevant
* for display in the UI.
*/
static class DohEntry {
public final @NonNull String name; // Display name
public final @NonNull String template; // URI template, or "" for the custom entry.
public final @NonNull String privacy; // Privacy policy link
DohEntry(String name, String template, String privacy) {
this.name = name;
this.template = template;
this.privacy = privacy;
}
@Override
public String toString() {
return name;
}
}
private final Context mContext;
private final SharedPreferencesManager mPrefs;
......@@ -343,123 +315,6 @@ public class PrivacyPreferencesManager implements CrashReportingPermissionManage
return PrivacyPreferencesManagerJni.get().isMetricsReportingManaged();
}
/**
* @return Whether the DoH UI field trial is active on this instance.
*/
public boolean isDnsOverHttpsUiEnabled() {
// Must match features::kDnsOverHttpsShowUiParam.
final String showUiParam = "ShowUi";
// Must match the default value for this param.
final boolean showUiParamDefault = false;
return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
ChromeFeatureList.DNS_OVER_HTTPS, showUiParam, showUiParamDefault);
}
/**
* @return The current Secure DNS mode (off, automatic, or secure).
*/
public @SecureDnsMode int getSecureDnsMode() {
return PrivacyPreferencesManagerJni.get().getSecureDnsMode();
}
/**
* Sets the current Secure DNS mode. Callers must successfully set a DoH template
* before changing the mode to "secure".
*
* @param mode The desired new Secure DNS mode.
*/
public void setSecureDnsMode(@SecureDnsMode int mode) {
PrivacyPreferencesManagerJni.get().setSecureDnsMode(mode);
}
/**
* @return True if the Secure DNS mode is controlled by a policy.
*/
public boolean isSecureDnsModeManaged() {
return PrivacyPreferencesManagerJni.get().isSecureDnsModeManaged();
}
/**
* @return The built-in DoH providers that should be displayed to the user.
*/
public List<DohEntry> getDohProviders() {
String[][] values = PrivacyPreferencesManagerJni.get().getDohProviders();
ArrayList<DohEntry> entries = new ArrayList<>(values.length);
for (String[] v : values) {
entries.add(new DohEntry(v[0], v[1], v[2]));
}
return entries;
}
/**
* Get the raw preference value, which can represent multiple templates separated
* by whitespace. The raw value is needed in order to allow direct editing while
* preserving whitespace.
*
* @return The templates (separated by spaces) of the DoH server
* currently selected for use in "secure" mode, or "" if there is none.
*/
public String getDnsOverHttpsTemplates() {
return PrivacyPreferencesManagerJni.get().getDnsOverHttpsTemplates();
}
/**
* Sets the templates to use for DoH in secure mode, if they are valid.
*
* @param templates The templates (separated by spaces) to store, or "" to clear
* the setting.
* @return True if the input was valid.
*/
public boolean setDnsOverHttpsTemplates(String templates) {
return PrivacyPreferencesManagerJni.get().setDnsOverHttpsTemplates(templates);
}
/**
* @return The current Secure DNS management mode. Note that this is entirely
* independent of isDnsOverHttpsModeManaged.
*/
public @SecureDnsManagementMode int getSecureDnsManagementMode() {
return PrivacyPreferencesManagerJni.get().getSecureDnsManagementMode();
}
/**
* Record a DoH selection action for statistical purposes.
* @param oldEntry The previous selection.
* @param newEntry The current selection.
*/
public void updateDohDropdownHistograms(DohEntry oldEntry, DohEntry newEntry) {
PrivacyPreferencesManagerJni.get().updateDohDropdownHistograms(
oldEntry.template, newEntry.template);
}
/**
* Record whether a custom template entered was valid for statistical purposes.
* @param valid True if the template was valid.
*/
public void updateDohValidationHistogram(boolean valid) {
PrivacyPreferencesManagerJni.get().updateDohValidationHistogram(valid);
}
/**
* @param group A collection of DoH templates in textual format.
* @return All templates in the group, or an empty array if the group is not valid.
*/
public String[] splitDohTemplateGroup(String group) {
return PrivacyPreferencesManagerJni.get().splitDohTemplateGroup(group);
}
/**
* Perform a probe to see if a server is working. This function blocks until the
* probe completes.
*
* @param template A valid DoH URI template.
* @return True if the server is reachable and functioning correctly.
*/
public boolean probeDohServer(String template) {
return PrivacyPreferencesManagerJni.get().probeDohServer(template);
}
@NativeMethods
public interface Natives {
boolean canPrefetchAndPrerender();
......@@ -470,18 +325,5 @@ public class PrivacyPreferencesManager implements CrashReportingPermissionManage
boolean isMetricsReportingEnabled();
void setMetricsReportingEnabled(boolean enabled);
boolean isMetricsReportingManaged();
@SecureDnsMode
int getSecureDnsMode();
void setSecureDnsMode(@SecureDnsMode int mode);
boolean isSecureDnsModeManaged();
String[][] getDohProviders();
String getDnsOverHttpsTemplates();
boolean setDnsOverHttpsTemplates(String templates);
@SecureDnsManagementMode
int getSecureDnsManagementMode();
void updateDohDropdownHistograms(String oldTemplate, String newTemplate);
void updateDohValidationHistogram(boolean valid);
String[] splitDohTemplateGroup(String group);
boolean probeDohServer(String dohTemplate);
}
}
......@@ -19,7 +19,7 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.help.HelpAndFeedback;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManager.DohEntry;
import org.chromium.chrome.browser.privacy.secure_dns.SecureDnsSettings;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
import org.chromium.chrome.browser.settings.SettingsLauncher;
......@@ -31,12 +31,9 @@ import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate;
import org.chromium.components.browser_ui.settings.SettingsUtils;
import org.chromium.components.prefs.PrefService;
import org.chromium.components.user_prefs.UserPrefs;
import org.chromium.net.SecureDnsMode;
import org.chromium.ui.text.NoUnderlineClickableSpan;
import org.chromium.ui.text.SpanApplier;
import java.util.List;
/**
* Fragment to keep track of the all the privacy related preferences.
*/
......@@ -83,7 +80,7 @@ public class PrivacySettings
networkPredictionPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate);
Preference secureDnsPref = findPreference(PREF_SECURE_DNS);
secureDnsPref.setVisible(privacyPrefManager.isDnsOverHttpsUiEnabled());
secureDnsPref.setVisible(SecureDnsSettings.isUiEnabled());
Preference syncAndServicesLink = findPreference(PREF_SYNC_AND_SERVICES_LINK);
NoUnderlineClickableSpan linkSpan = new NoUnderlineClickableSpan(getResources(), view -> {
......@@ -138,27 +135,7 @@ public class PrivacySettings
Preference secureDnsPref = findPreference(PREF_SECURE_DNS);
if (secureDnsPref != null && secureDnsPref.isVisible()) {
PrivacyPreferencesManager manager = PrivacyPreferencesManager.getInstance();
@SecureDnsMode
int mode = manager.getSecureDnsMode();
if (mode == SecureDnsMode.OFF) {
secureDnsPref.setSummary(R.string.text_off);
} else if (mode == SecureDnsMode.AUTOMATIC) {
secureDnsPref.setSummary(R.string.settings_automatic_mode_summary);
} else {
String templateGroup = manager.getDnsOverHttpsTemplates();
List<DohEntry> providers = manager.getDohProviders();
String serverName = templateGroup;
for (int i = 0; i < providers.size(); i++) {
DohEntry entry = providers.get(i);
if (entry.template.equals(templateGroup)) {
serverName = entry.name;
break;
}
}
secureDnsPref.setSummary(
String.format("%s - %s", getString(R.string.text_on), serverName));
}
secureDnsPref.setSummary(SecureDnsSettings.getSummary(getContext()));
}
Preference usageStatsPref = findPreference(PREF_USAGE_STATS);
......
......@@ -2822,6 +2822,7 @@ static_library("browser") {
"prerender/external_prerender_handler_android.h",
"previews/android/previews_android_bridge.cc",
"previews/android/previews_android_bridge.h",
"privacy/secure_dns_bridge.cc",
"profiles/android/profile_downloader_android.cc",
"profiles/android/profile_manager_utils.cc",
"profiles/incognito_utils_android.cc",
......@@ -2904,6 +2905,7 @@ static_library("browser") {
"//chrome/browser/password_check/android",
"//chrome/browser/password_check/android/internal",
"//chrome/browser/payments/android:jni_headers",
"//chrome/browser/privacy:jni_headers",
"//chrome/browser/safety_check/android",
"//chrome/browser/share",
"//chrome/browser/tab:android_internal",
......
......@@ -4,42 +4,13 @@
#include <jni.h>
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/android/chrome_jni_headers/PrivacyPreferencesManager_jni.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/dns_probe_runner.h"
#include "chrome/browser/net/prediction_options.h"
#include "chrome/browser/net/secure_dns_config.h"
#include "chrome/browser/net/secure_dns_util.h"
#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/pref_names.h"
#include "components/country_codes/country_codes.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/prefs/pref_service.h"
#include "net/dns/public/doh_provider_entry.h"
#include "net/dns/public/util.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;
using chrome_browser_net::DnsProbeRunner;
namespace secure_dns = chrome_browser_net::secure_dns;
namespace {
......@@ -49,33 +20,6 @@ PrefService* GetPrefService() {
->GetPrefs();
}
net::DohProviderEntry::List GetFilteredProviders() {
const auto local_providers = secure_dns::ProvidersForCountry(
net::DohProviderEntry::GetList(), country_codes::GetCurrentCountryID());
return secure_dns::RemoveDisabledProviders(
local_providers, secure_dns::GetDisabledProviders());
}
// Runs a DNS probe according to the configuration in |overrides|,
// asynchronously sets |success| to indicate the result, and signals
// |waiter| when the probe has completed. Must run on the UI thread.
void RunProbe(base::WaitableEvent* waiter,
bool* success,
net::DnsConfigOverrides overrides) {
auto* manager = g_browser_process->system_network_context_manager();
auto runner = std::make_unique<DnsProbeRunner>(
std::move(overrides),
base::BindRepeating(&SystemNetworkContextManager::GetContext,
base::Unretained(manager)));
runner->RunProbe(base::BindOnce(
[](base::WaitableEvent* waiter, bool* success,
std::unique_ptr<DnsProbeRunner> runner) {
*success = runner->result() == DnsProbeRunner::CORRECT;
waiter->Signal();
},
waiter, success, std::move(runner)));
}
} // namespace
static jboolean JNI_PrivacyPreferencesManager_GetNetworkPredictionEnabled(
......@@ -130,129 +74,3 @@ JNI_PrivacyPreferencesManager_ObsoleteNetworkPredictionOptionsHasUserSetting(
return GetPrefService()->GetUserPrefValue(prefs::kNetworkPredictionOptions) !=
nullptr;
}
static jint JNI_PrivacyPreferencesManager_GetSecureDnsMode(JNIEnv* env) {
return static_cast<int>(
SystemNetworkContextManager::GetStubResolverConfigReader()
->GetSecureDnsConfiguration(
true /* force_check_parental_controls_for_automatic_mode */)
.mode());
}
static void JNI_PrivacyPreferencesManager_SetSecureDnsMode(JNIEnv* env,
jint mode) {
PrefService* local_state = g_browser_process->local_state();
local_state->SetString(prefs::kDnsOverHttpsMode,
SecureDnsConfig::ModeToString(
static_cast<net::DnsConfig::SecureDnsMode>(mode)));
}
static jboolean JNI_PrivacyPreferencesManager_IsSecureDnsModeManaged(
JNIEnv* env) {
PrefService* local_state = g_browser_process->local_state();
return local_state->IsManagedPreference(prefs::kDnsOverHttpsMode);
}
static ScopedJavaLocalRef<jobjectArray>
JNI_PrivacyPreferencesManager_GetDohProviders(JNIEnv* env) {
net::DohProviderEntry::List providers = GetFilteredProviders();
std::vector<std::vector<base::string16>> ret;
ret.reserve(providers.size());
std::transform(providers.begin(), providers.end(), std::back_inserter(ret),
[](const auto* entry) {
return std::vector<base::string16>{
{base::UTF8ToUTF16(entry->ui_name),
base::UTF8ToUTF16(entry->dns_over_https_template),
base::UTF8ToUTF16(entry->privacy_policy)}};
});
return base::android::ToJavaArrayOfStringArray(env, ret);
}
static ScopedJavaLocalRef<jstring>
JNI_PrivacyPreferencesManager_GetDnsOverHttpsTemplates(JNIEnv* env) {
PrefService* local_state = g_browser_process->local_state();
return base::android::ConvertUTF8ToJavaString(
env, local_state->GetString(prefs::kDnsOverHttpsTemplates));
}
static jboolean JNI_PrivacyPreferencesManager_SetDnsOverHttpsTemplates(
JNIEnv* env,
const JavaParamRef<jstring>& jtemplates) {
PrefService* local_state = g_browser_process->local_state();
std::string templates = base::android::ConvertJavaStringToUTF8(jtemplates);
if (templates.empty()) {
local_state->ClearPref(prefs::kDnsOverHttpsTemplates);
return true;
}
if (secure_dns::IsValidGroup(templates)) {
local_state->SetString(prefs::kDnsOverHttpsTemplates, templates);
return true;
}
return false;
}
static jint JNI_PrivacyPreferencesManager_GetSecureDnsManagementMode(
JNIEnv* env) {
return static_cast<int>(
SystemNetworkContextManager::GetStubResolverConfigReader()
->GetSecureDnsConfiguration(
true /* force_check_parental_controls_for_automatic_mode */)
.management_mode());
}
static void JNI_PrivacyPreferencesManager_UpdateDohDropdownHistograms(
JNIEnv* env,
const JavaParamRef<jstring>& old_template,
const JavaParamRef<jstring>& new_template) {
secure_dns::UpdateDropdownHistograms(
GetFilteredProviders(),
base::android::ConvertJavaStringToUTF8(old_template),
base::android::ConvertJavaStringToUTF8(new_template));
}
static void JNI_PrivacyPreferencesManager_UpdateDohValidationHistogram(
JNIEnv* env,
jboolean valid) {
secure_dns::UpdateValidationHistogram(valid);
}
static ScopedJavaLocalRef<jobjectArray>
JNI_PrivacyPreferencesManager_SplitDohTemplateGroup(
JNIEnv* env,
const JavaParamRef<jstring>& jgroup) {
std::string group = base::android::ConvertJavaStringToUTF8(jgroup);
std::vector<base::StringPiece> templates = secure_dns::SplitGroup(group);
std::vector<std::string> templates_copy(templates.begin(), templates.end());
return base::android::ToJavaArrayOfStrings(env, templates_copy);
}
static jboolean JNI_PrivacyPreferencesManager_ProbeDohServer(
JNIEnv* env,
const JavaParamRef<jstring>& jtemplate) {
net::DnsConfigOverrides overrides;
overrides.search = std::vector<std::string>();
overrides.attempts = 1;
overrides.randomize_ports = false;
overrides.secure_dns_mode = net::DnsConfig::SecureDnsMode::SECURE;
secure_dns::ApplyTemplate(&overrides,
base::android::ConvertJavaStringToUTF8(jtemplate));
// Android recommends converting async functions to blocking when using JNI:
// https://developer.android.com/training/articles/perf-jni.
// This function converts the DnsProbeRunner, which can only be created and
// used on the UI thread, into a blocking function that can be called from an
// auxiliary Java thread.
// TODO: Use std::future if allowed in the future.
base::WaitableEvent waiter;
bool success;
bool posted = content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(RunProbe, &waiter, &success, std::move(overrides)));
DCHECK(posted);
waiter.Wait();
secure_dns::UpdateProbeHistogram(success);
return success;
}
# 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("//build/config/android/rules.gni")
android_library("java") {
visibility = [
":*",
"//chrome/android:chrome_all_java",
"//chrome/android:chrome_java",
]
sources = [
"java/src/org/chromium/chrome/browser/privacy/secure_dns/SecureDnsBridge.java",
"java/src/org/chromium/chrome/browser/privacy/secure_dns/SecureDnsProviderPreference.java",
"java/src/org/chromium/chrome/browser/privacy/secure_dns/SecureDnsSettings.java",
]
deps = [
":java_resources",
":jni_headers",
"//base:base_java",
"//base:jni_java",
"//chrome/browser/android/lifecycle:java",
"//chrome/browser/flags:java",
"//chrome/browser/net:secure_dns_management_mode_generated_enum",
"//chrome/browser/preferences:java",
"//chrome/browser/settings:java",
"//components/browser_ui/settings/android:java",
"//components/browser_ui/widget/android:java",
"//net/dns:secure_dns_mode_generated_enum",
"//third_party/android_deps:androidx_annotation_annotation_java",
"//third_party/android_deps:androidx_fragment_fragment_java",
"//third_party/android_deps:androidx_preference_preference_java",
"//third_party/android_deps:com_google_android_material_material_java",
]
srcjar_deps = [
"//chrome/browser/net:secure_dns_management_mode_generated_enum",
"//net/dns:secure_dns_mode_generated_enum",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
android_resources("java_resources") {
custom_package = "org.chromium.chrome.browser.privacy.secure_dns"
sources = [
"java/res/layout/secure_dns_provider_preference.xml",
"java/res/layout/secure_dns_provider_spinner_item.xml",
"java/res/xml/secure_dns_settings.xml",
]
deps = [
"//chrome/browser/ui/android/strings:ui_strings_grd",
"//components/browser_ui/strings/android:browser_ui_strings_grd",
"//components/browser_ui/styles/android:java_resources",
"//components/browser_ui/widget/android:java_resources",
"//third_party/android_deps:com_google_android_material_material_java",
]
}
generate_jni("jni_headers") {
visibility = [
":*",
"//chrome/android:jni_headers",
"//chrome/browser",
]
sources = [ "java/src/org/chromium/chrome/browser/privacy/secure_dns/SecureDnsBridge.java" ]
}
include_rules = [
"+components/browser_ui/styles/android",
]
per-file BUILD.gn=*
# For changes to Secure DNS
file://net/dns/OWNERS
bemasc@chromium.org
......@@ -12,7 +12,7 @@
android:title="@string/settings_secure_dns_title"
android:summary="@string/settings_secure_dns_description" />
<org.chromium.chrome.browser.privacy.settings.SecureDnsProviderPreference
<org.chromium.chrome.browser.privacy.secure_dns.SecureDnsProviderPreference
android:key="secure_dns_provider" />
</PreferenceScreen>
// 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.
package org.chromium.chrome.browser.privacy.secure_dns;
import androidx.annotation.NonNull;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.net.SecureDnsManagementMode;
import org.chromium.net.SecureDnsMode;
import java.util.ArrayList;
import java.util.List;
/**
* Reads and writes preferences related to Secure DNS.
*/
class SecureDnsBridge {
/**
* An Entry represents the subset of a net::DohProviderEntry that is relevant
* for display in the UI.
*/
static class Entry {
public final @NonNull String name; // Display name
public final @NonNull String template; // URI template, or "" for the custom entry.
public final @NonNull String privacy; // Privacy policy link
Entry(String name, String template, String privacy) {
this.name = name;
this.template = template;
this.privacy = privacy;
}
@Override
public String toString() {
return name;
}
}
/**
* @return Whether the DoH UI field trial is active on this instance.
*/
static boolean isUiEnabled() {
// Must match features::kDnsOverHttpsShowUiParam.
final String showUiParam = "ShowUi";
// Must match the default value for this param.
final boolean showUiParamDefault = false;
return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
ChromeFeatureList.DNS_OVER_HTTPS, showUiParam, showUiParamDefault);
}
/**
* @return The current Secure DNS mode (off, automatic, or secure).
*/
public static @SecureDnsMode int getMode() {
return SecureDnsBridgeJni.get().getMode();
}
/**
* Sets the current Secure DNS mode. Callers must successfully set a DoH template
* before changing the mode to "secure".
*
* @param mode The desired new Secure DNS mode.
*/
static void setMode(@SecureDnsMode int mode) {
SecureDnsBridgeJni.get().setMode(mode);
}
/**
* @return True if the Secure DNS mode is controlled by a policy.
*/
static boolean isModeManaged() {
return SecureDnsBridgeJni.get().isModeManaged();
}
/**
* @return The built-in DoH providers that should be displayed to the user.
*/
static List<Entry> getProviders() {
String[][] values = SecureDnsBridgeJni.get().getProviders();
ArrayList<Entry> entries = new ArrayList<>(values.length);
for (String[] v : values) {
entries.add(new Entry(v[0], v[1], v[2]));
}
return entries;
}
/**
* Get the raw preference value, which can represent multiple templates separated
* by whitespace. The raw value is needed in order to allow direct editing while
* preserving whitespace.
*
* @return The templates (separated by spaces) of the DoH server
* currently selected for use in "secure" mode, or "" if there is none.
*/
static String getTemplates() {
return SecureDnsBridgeJni.get().getTemplates();
}
/**
* Sets the templates to use for DoH in secure mode, if they are valid.
*
* @param templates The templates (separated by spaces) to store, or "" to clear
* the setting.
* @return True if the input was valid.
*/
static boolean setTemplates(String templates) {
return SecureDnsBridgeJni.get().setTemplates(templates);
}
/**
* @return The current Secure DNS management mode. Note that this is entirely
* independent of isDnsOverHttpsModeManaged.
*/
static @SecureDnsManagementMode int getManagementMode() {
return SecureDnsBridgeJni.get().getManagementMode();
}
/**
* Record a DoH selection action for statistical purposes.
* @param oldEntry The previous selection.
* @param newEntry The current selection.
*/
static void updateDropdownHistograms(Entry oldEntry, Entry newEntry) {
SecureDnsBridgeJni.get().updateDropdownHistograms(oldEntry.template, newEntry.template);
}
/**
* Record whether a custom template entered was valid for statistical purposes.
* @param valid True if the template was valid.
*/
static void updateValidationHistogram(boolean valid) {
SecureDnsBridgeJni.get().updateValidationHistogram(valid);
}
/**
* @param group A collection of DoH templates in textual format.
* @return All templates in the group, or an empty array if the group is not valid.
*/
static String[] splitTemplateGroup(String group) {
return SecureDnsBridgeJni.get().splitTemplateGroup(group);
}
/**
* Perform a probe to see if a server is working. This function blocks until the
* probe completes.
*
* @param template A valid DoH URI template.
* @return True if the server is reachable and functioning correctly.
*/
static boolean probeServer(String template) {
return SecureDnsBridgeJni.get().probeServer(template);
}
@NativeMethods
interface Natives {
@SecureDnsMode
int getMode();
void setMode(@SecureDnsMode int mode);
boolean isModeManaged();
String[][] getProviders();
String getTemplates();
boolean setTemplates(String templates);
@SecureDnsManagementMode
int getManagementMode();
void updateDropdownHistograms(String oldTemplate, String newTemplate);
void updateValidationHistogram(boolean valid);
String[] splitTemplateGroup(String group);
boolean probeServer(String dohTemplate);
}
}
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.privacy.settings;
package org.chromium.chrome.browser.privacy.secure_dns;
import android.content.Context;
import android.text.Editable;
......@@ -24,8 +24,7 @@ import androidx.preference.PreferenceViewHolder;
import com.google.android.material.textfield.TextInputLayout;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManager.DohEntry;
import org.chromium.chrome.browser.privacy.secure_dns.SecureDnsBridge.Entry;
import org.chromium.components.browser_ui.widget.RadioButtonWithDescription;
import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout;
......@@ -37,16 +36,16 @@ import java.util.List;
* SecureDnsProviderPreference is the user interface that is shown when Secure DNS is enabled.
* When Secure DNS is disabled, the SecureDnsProviderPreference is hidden.
*/
public class SecureDnsProviderPreference
extends Preference implements RadioGroup.OnCheckedChangeListener,
AdapterView.OnItemSelectedListener, TextWatcher {
class SecureDnsProviderPreference extends Preference implements RadioGroup.OnCheckedChangeListener,
AdapterView.OnItemSelectedListener,
TextWatcher {
// UI strings, loaded from the context.
private final String mPrivacyTemplate;
private final String mInvalidWarning;
private final String mProbeWarning;
// Server menu entries.
private final List<DohEntry> mOptions;
private final List<Entry> mOptions;
// UI elements. These fields are assigned only once, in onBindViewHolder.
private RadioButtonWithDescriptionLayout mGroup;
......@@ -130,14 +129,14 @@ public class SecureDnsProviderPreference
mOptions = makeOptions(context);
}
private static List<DohEntry> makeOptions(Context context) {
List<DohEntry> entries = PrivacyPreferencesManager.getInstance().getDohProviders();
private static List<Entry> makeOptions(Context context) {
List<Entry> entries = SecureDnsBridge.getProviders();
// The Spinner's options consist of an entry called "Custom", followed
// by the providers in random order.
List<DohEntry> options = new ArrayList<>(entries.size() + 1);
List<Entry> options = new ArrayList<>(entries.size() + 1);
String customEntryName = context.getString(R.string.settings_custom);
options.add(new DohEntry(customEntryName, "", ""));
options.add(new Entry(customEntryName, "", ""));
Collections.shuffle(entries);
options.addAll(entries);
......@@ -156,7 +155,7 @@ public class SecureDnsProviderPreference
mServerMenu = selectionContainer.findViewById(R.id.dropdown_spinner);
mServerMenu.setOnItemSelectedListener(this);
Context context = selectionContainer.getContext();
ArrayAdapter<DohEntry> adapter =
ArrayAdapter<Entry> adapter =
new ArrayAdapter<>(context, R.layout.secure_dns_provider_spinner_item, mOptions);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mServerMenu.setAdapter(adapter);
......@@ -171,14 +170,14 @@ public class SecureDnsProviderPreference
updateView();
}
public void setState(State state) {
void setState(State state) {
if (!state.equals(mState)) {
mState = state;
updateView();
}
}
public State getState() {
State getState() {
return mState;
}
......@@ -186,7 +185,7 @@ public class SecureDnsProviderPreference
// or 0 if none match (i.e. a custom template).
private int matchingDropdownIndex() {
for (int i = 1; i < mServerMenu.getCount(); ++i) {
DohEntry entry = (DohEntry) mServerMenu.getItemAtPosition(i);
Entry entry = (Entry) mServerMenu.getItemAtPosition(i);
if (entry.template.equals(mState.template)) {
return i;
}
......@@ -219,7 +218,7 @@ public class SecureDnsProviderPreference
// Position 0 is the custom server. Other positions are actual server entries.
if (position > 0) {
// Selected server mode.
DohEntry entry = (DohEntry) mServerMenu.getSelectedItem();
Entry entry = (Entry) mServerMenu.getSelectedItem();
String html = mPrivacyTemplate.replace("$1", entry.privacy);
mPrivacyPolicy.setText(Html.fromHtml(html));
......@@ -247,7 +246,7 @@ public class SecureDnsProviderPreference
mPrivacyPolicy.setVisibility(View.GONE);
}
PrivacyPreferencesManager.getInstance().updateDohValidationHistogram(mState.valid);
SecureDnsBridge.updateValidationHistogram(mState.valid);
}
private void startServerProbe() {
......@@ -255,13 +254,12 @@ public class SecureDnsProviderPreference
if (group.isEmpty() || !mState.valid || !mState.secure) {
return;
}
// probeDohServer() is a blocking network call that uses WaitableEvent, so it cannot run
// probeServer() is a blocking network call that uses WaitableEvent, so it cannot run
// on the UI thread, nor via the Java PostTask bindings, which do not expose
// base::WithBaseSyncPrimitives. Instead, it runs on a fresh Java thread.
new Thread(() -> {
PrivacyPreferencesManager manager = PrivacyPreferencesManager.getInstance();
for (String template : manager.splitDohTemplateGroup(group)) {
if (manager.probeDohServer(template)) {
for (String template : SecureDnsBridge.splitTemplateGroup(group)) {
if (SecureDnsBridge.probeServer(template)) {
return;
}
}
......@@ -291,11 +289,11 @@ public class SecureDnsProviderPreference
// attaching an adapter triggers a spurious onItemSelected event.
return;
}
DohEntry oldEntry = (DohEntry) parent.getItemAtPosition(oldPos);
DohEntry entry = (DohEntry) parent.getItemAtPosition(pos);
Entry oldEntry = (Entry) parent.getItemAtPosition(oldPos);
Entry entry = (Entry) parent.getItemAtPosition(pos);
tryUpdate(mState.withTemplate(entry.template));
PrivacyPreferencesManager.getInstance().updateDohDropdownHistograms(oldEntry, entry);
SecureDnsBridge.updateDropdownHistograms(oldEntry, entry);
}
@Override
......
......@@ -2,20 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.privacy.settings;
package org.chromium.chrome.browser.privacy.secure_dns;
import android.content.Context;
import android.os.Bundle;
import androidx.preference.PreferenceFragmentCompat;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.net.SecureDnsManagementMode;
import org.chromium.chrome.browser.privacy.settings.SecureDnsProviderPreference.State;
import org.chromium.chrome.browser.privacy.secure_dns.SecureDnsProviderPreference.State;
import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
import org.chromium.components.browser_ui.settings.SettingsUtils;
import org.chromium.net.SecureDnsMode;
import java.util.List;
/**
* Fragment to manage Secure DNS preference. It consists of a toggle switch and,
* if the switch is enabled, a SecureDnsControl.
......@@ -25,34 +27,58 @@ public class SecureDnsSettings extends PreferenceFragmentCompat {
private static final String PREF_SECURE_DNS_SWITCH = "secure_dns_switch";
private static final String PREF_SECURE_DNS_PROVIDER = "secure_dns_provider";
private PrivacyPreferencesManager mManager;
private ChromeSwitchPreference mSecureDnsSwitch;
private SecureDnsProviderPreference mSecureDnsProviderPreference;
public static boolean isUiEnabled() {
return SecureDnsBridge.isUiEnabled();
}
/** @return A summary for use in the Preference that opens this fragment. */
public static String getSummary(Context context) {
@SecureDnsMode
int mode = SecureDnsBridge.getMode();
if (mode == SecureDnsMode.OFF) {
return context.getString(R.string.text_off);
} else if (mode == SecureDnsMode.AUTOMATIC) {
return context.getString(R.string.settings_automatic_mode_summary);
} else {
String templateGroup = SecureDnsBridge.getTemplates();
List<SecureDnsBridge.Entry> providers = SecureDnsBridge.getProviders();
String serverName = templateGroup;
for (int i = 0; i < providers.size(); i++) {
SecureDnsBridge.Entry entry = providers.get(i);
if (entry.template.equals(templateGroup)) {
serverName = entry.name;
break;
}
}
return String.format("%s - %s", context.getString(R.string.text_on), serverName);
}
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
getActivity().setTitle(R.string.settings_secure_dns_title);
SettingsUtils.addPreferencesFromResource(this, R.xml.secure_dns_settings);
mManager = PrivacyPreferencesManager.getInstance();
// Set up preferences inside the activity.
mSecureDnsSwitch = (ChromeSwitchPreference) findPreference(PREF_SECURE_DNS_SWITCH);
mSecureDnsSwitch.setManagedPreferenceDelegate(
(ChromeManagedPreferenceDelegate) preference -> mManager.isSecureDnsModeManaged());
(ChromeManagedPreferenceDelegate) preference -> SecureDnsBridge.isModeManaged());
mSecureDnsSwitch.setOnPreferenceChangeListener((preference, enabled) -> {
storePreferenceState((boolean) enabled, mSecureDnsProviderPreference.getState());
loadPreferenceState();
return true;
});
if (!mManager.isSecureDnsModeManaged()) {
if (!SecureDnsBridge.isModeManaged()) {
// If the mode isn't managed directly, we still need to disable the controls
// if we detect a managed system configuration, or any parental control software.
// However, we don't want to show the managed setting icon in this case, because the
// setting is not directly controlled by a policy.
@SecureDnsManagementMode
int managementMode = mManager.getSecureDnsManagementMode();
int managementMode = SecureDnsBridge.getManagementMode();
if (managementMode != SecureDnsManagementMode.NO_OVERRIDE) {
mSecureDnsSwitch.setEnabled(false);
boolean parentalControls =
......@@ -87,32 +113,32 @@ public class SecureDnsSettings extends PreferenceFragmentCompat {
*/
private boolean storePreferenceState(boolean enabled, State controlState) {
if (!enabled) {
mManager.setSecureDnsMode(SecureDnsMode.OFF);
mManager.setDnsOverHttpsTemplates("");
SecureDnsBridge.setMode(SecureDnsMode.OFF);
SecureDnsBridge.setTemplates("");
} else if (!controlState.secure) {
mManager.setSecureDnsMode(SecureDnsMode.AUTOMATIC);
mManager.setDnsOverHttpsTemplates("");
SecureDnsBridge.setMode(SecureDnsMode.AUTOMATIC);
SecureDnsBridge.setTemplates("");
} else {
if (controlState.template.isEmpty()
|| !mManager.setDnsOverHttpsTemplates(controlState.template)) {
|| !SecureDnsBridge.setTemplates(controlState.template)) {
return false;
}
mManager.setSecureDnsMode(SecureDnsMode.SECURE);
SecureDnsBridge.setMode(SecureDnsMode.SECURE);
}
return true;
}
private void loadPreferenceState() {
@SecureDnsMode
int mode = mManager.getSecureDnsMode();
int mode = SecureDnsBridge.getMode();
boolean enabled = mode != SecureDnsMode.OFF;
boolean enforced = mManager.isSecureDnsModeManaged()
|| mManager.getSecureDnsManagementMode() != SecureDnsManagementMode.NO_OVERRIDE;
boolean enforced = SecureDnsBridge.isModeManaged()
|| SecureDnsBridge.getManagementMode() != SecureDnsManagementMode.NO_OVERRIDE;
mSecureDnsSwitch.setChecked(enabled);
mSecureDnsProviderPreference.setEnabled(enabled && !enforced);
boolean secure = mode == SecureDnsMode.SECURE;
String template = mManager.getDnsOverHttpsTemplates();
String template = SecureDnsBridge.getTemplates();
boolean valid = true; // States loaded from storage are presumed valid.
mSecureDnsProviderPreference.setState(new State(secure, template, valid));
}
......
// 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.
#include <jni.h>
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/dns_probe_runner.h"
#include "chrome/browser/net/secure_dns_config.h"
#include "chrome/browser/net/secure_dns_util.h"
#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/privacy/jni_headers/SecureDnsBridge_jni.h"
#include "chrome/common/pref_names.h"
#include "components/country_codes/country_codes.h"
#include "components/prefs/pref_service.h"
#include "net/dns/public/doh_provider_entry.h"
#include "net/dns/public/util.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;
using chrome_browser_net::DnsProbeRunner;
namespace secure_dns = chrome_browser_net::secure_dns;
namespace {
net::DohProviderEntry::List GetFilteredProviders() {
const auto local_providers = secure_dns::ProvidersForCountry(
net::DohProviderEntry::GetList(), country_codes::GetCurrentCountryID());
return secure_dns::RemoveDisabledProviders(
local_providers, secure_dns::GetDisabledProviders());
}
// Runs a DNS probe according to the configuration in |overrides|,
// asynchronously sets |success| to indicate the result, and signals
// |waiter| when the probe has completed. Must run on the UI thread.
void RunProbe(base::WaitableEvent* waiter,
bool* success,
net::DnsConfigOverrides overrides) {
auto* manager = g_browser_process->system_network_context_manager();
auto runner = std::make_unique<DnsProbeRunner>(
std::move(overrides),
base::BindRepeating(&SystemNetworkContextManager::GetContext,
base::Unretained(manager)));
runner->RunProbe(base::BindOnce(
[](base::WaitableEvent* waiter, bool* success,
std::unique_ptr<DnsProbeRunner> runner) {
*success = runner->result() == DnsProbeRunner::CORRECT;
waiter->Signal();
},
waiter, success, std::move(runner)));
}
} // namespace
static jint JNI_SecureDnsBridge_GetMode(JNIEnv* env) {
return static_cast<int>(
SystemNetworkContextManager::GetStubResolverConfigReader()
->GetSecureDnsConfiguration(
true /* force_check_parental_controls_for_automatic_mode */)
.mode());
}
static void JNI_SecureDnsBridge_SetMode(JNIEnv* env, jint mode) {
PrefService* local_state = g_browser_process->local_state();
local_state->SetString(prefs::kDnsOverHttpsMode,
SecureDnsConfig::ModeToString(
static_cast<net::DnsConfig::SecureDnsMode>(mode)));
}
static jboolean JNI_SecureDnsBridge_IsModeManaged(JNIEnv* env) {
PrefService* local_state = g_browser_process->local_state();
return local_state->IsManagedPreference(prefs::kDnsOverHttpsMode);
}
static ScopedJavaLocalRef<jobjectArray> JNI_SecureDnsBridge_GetProviders(
JNIEnv* env) {
net::DohProviderEntry::List providers = GetFilteredProviders();
std::vector<std::vector<base::string16>> ret;
ret.reserve(providers.size());
std::transform(providers.begin(), providers.end(), std::back_inserter(ret),
[](const auto* entry) {
return std::vector<base::string16>{
{base::UTF8ToUTF16(entry->ui_name),
base::UTF8ToUTF16(entry->dns_over_https_template),
base::UTF8ToUTF16(entry->privacy_policy)}};
});
return base::android::ToJavaArrayOfStringArray(env, ret);
}
static ScopedJavaLocalRef<jstring> JNI_SecureDnsBridge_GetTemplates(
JNIEnv* env) {
PrefService* local_state = g_browser_process->local_state();
return base::android::ConvertUTF8ToJavaString(
env, local_state->GetString(prefs::kDnsOverHttpsTemplates));
}
static jboolean JNI_SecureDnsBridge_SetTemplates(
JNIEnv* env,
const JavaParamRef<jstring>& jtemplates) {
PrefService* local_state = g_browser_process->local_state();
std::string templates = base::android::ConvertJavaStringToUTF8(jtemplates);
if (templates.empty()) {
local_state->ClearPref(prefs::kDnsOverHttpsTemplates);
return true;
}
if (secure_dns::IsValidGroup(templates)) {
local_state->SetString(prefs::kDnsOverHttpsTemplates, templates);
return true;
}
return false;
}
static jint JNI_SecureDnsBridge_GetManagementMode(JNIEnv* env) {
return static_cast<int>(
SystemNetworkContextManager::GetStubResolverConfigReader()
->GetSecureDnsConfiguration(
true /* force_check_parental_controls_for_automatic_mode */)
.management_mode());
}
static void JNI_SecureDnsBridge_UpdateDropdownHistograms(
JNIEnv* env,
const JavaParamRef<jstring>& old_template,
const JavaParamRef<jstring>& new_template) {
secure_dns::UpdateDropdownHistograms(
GetFilteredProviders(),
base::android::ConvertJavaStringToUTF8(old_template),
base::android::ConvertJavaStringToUTF8(new_template));
}
static void JNI_SecureDnsBridge_UpdateValidationHistogram(JNIEnv* env,
jboolean valid) {
secure_dns::UpdateValidationHistogram(valid);
}
static ScopedJavaLocalRef<jobjectArray> JNI_SecureDnsBridge_SplitTemplateGroup(
JNIEnv* env,
const JavaParamRef<jstring>& jgroup) {
std::string group = base::android::ConvertJavaStringToUTF8(jgroup);
std::vector<base::StringPiece> templates = secure_dns::SplitGroup(group);
std::vector<std::string> templates_copy(templates.begin(), templates.end());
return base::android::ToJavaArrayOfStrings(env, templates_copy);
}
static jboolean JNI_SecureDnsBridge_ProbeServer(
JNIEnv* env,
const JavaParamRef<jstring>& jtemplate) {
net::DnsConfigOverrides overrides;
overrides.search = std::vector<std::string>();
overrides.attempts = 1;
overrides.randomize_ports = false;
overrides.secure_dns_mode = net::DnsConfig::SecureDnsMode::SECURE;
secure_dns::ApplyTemplate(&overrides,
base::android::ConvertJavaStringToUTF8(jtemplate));
// Android recommends converting async functions to blocking when using JNI:
// https://developer.android.com/training/articles/perf-jni.
// This function converts the DnsProbeRunner, which can only be created and
// used on the UI thread, into a blocking function that can be called from an
// auxiliary Java thread.
// TODO: Use std::future if allowed in the future.
base::WaitableEvent waiter;
bool success;
bool posted = content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(RunProbe, &waiter, &success, std::move(overrides)));
DCHECK(posted);
waiter.Wait();
secure_dns::UpdateProbeHistogram(success);
return success;
}
......@@ -732,6 +732,8 @@ For example, some websites may respond to this request by showing you ads that a
<message name="IDS_CAN_MAKE_PAYMENT_TITLE" desc="Title for preference to allow websites to know whether you have payment methods available through PaymentRequest.CanMakePayment interface">
Access payment methods
</message>
<!-- Secure DNS Settings. Used by //chrome/browser/privacy. -->
<message name="IDS_SETTINGS_CUSTOM" desc="Label for a custom option in a dropdown menu.">
Custom
</message>
......@@ -771,6 +773,7 @@ For example, some websites may respond to this request by showing you ads that a
<message name="IDS_SETTINGS_SECURE_DNS_CUSTOM_CONNECTION_ERROR" desc="Error text for a custom secure DNS provider entry to which a probe connection fails">
Please verify that this is a valid provider or try again later
</message>
<message name="IDS_CLEAR_BROWSING_DATA_TITLE" desc="Title of the Clear Browsing Data screen. [CHAR-LIMIT=32]">
Clear browsing data
</message>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment