Commit 4e55899c authored by dalyk's avatar dalyk Committed by Commit Bot

Send test query for secure DNS setting custom text field entries.

This cl adds a new error message when the custom text field entry
passes the formatting check but a test DNS query fails.

Bug: 1040145
Change-Id: If25737013e942814d1f7bf0a0ac5d5c72c72e757
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2082357Reviewed-by: default avatarEric Orth <ericorth@chromium.org>
Reviewed-by: default avatarEsmael Elmoslimany <aee@chromium.org>
Commit-Queue: Katharine Daly <dalyk@google.com>
Cr-Commit-Position: refs/heads/master@{#748985}
parent 5da27796
......@@ -1748,10 +1748,10 @@
See this provider's <ph name="BEGIN_LINK">&lt;a target="_blank" href="$1<ex>https://google.com/</ex>"&gt;</ph>privacy policy<ph name="END_LINK">&lt;/a&gt;</ph>
</message>
<message name="IDS_SETTINGS_SECURE_DNS_DISABLED_FOR_MANAGED_ENVIRONMENT" desc="Substring of the secure DNS setting when secure DNS is disabled due to detection of a managed environment">
This setting is disabled on managed browsers.
This setting is disabled on managed browsers
</message>
<message name="IDS_SETTINGS_SECURE_DNS_DISABLED_FOR_PARENTAL_CONTROL" desc="Substring of the secure DNS setting when secure DNS is disabled due to detection of OS-level parental controls">
This setting is disabled because parental controls are on.
This setting is disabled because parental controls are on
</message>
<message name="IDS_SETTINGS_SECURE_DNS_CUSTOM_PLACEHOLDER" desc="Placeholder text for a textbox where users can enter a custom secure DNS provider">
Enter custom provider
......@@ -1759,6 +1759,9 @@
<message name="IDS_SETTINGS_SECURE_DNS_CUSTOM_FORMAT_ERROR" desc="Error text for an incorrectly formatted entry for the custom secure DNS provider">
Enter a correctly formatted URL
</message>
<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_SETTINGS_CONTENT_SETTINGS" desc="Text of the button that takes a user to settings page thats allows users to modify site settings. Also the title of that settings page.">
Content settings
</message>
......
......@@ -69,11 +69,18 @@ cr.define('settings', function() {
getSecureDnsSetting() {}
/**
* Determines whether the entry contains at least one valid URL template.
* Returns the first valid URL template, if any.
* @param {string} entry
* @return {!Promise<boolean>}
* @return {!Promise<string>}
*/
validateCustomDnsEntry(entry) {}
/**
* Returns whether a test query to the secure DNS template succeeded.
* @param {string} template
* @return {!Promise<boolean>}
*/
probeCustomDnsTemplate(template) {}
}
/**
......@@ -119,6 +126,11 @@ cr.define('settings', function() {
validateCustomDnsEntry(entry) {
return cr.sendWithPromise('validateCustomDnsEntry', entry);
}
/** @override */
probeCustomDnsTemplate(template) {
return cr.sendWithPromise('probeCustomDnsTemplate', template);
}
}
cr.addSingletonGetter(PrivacyPageBrowserProxyImpl);
......
......@@ -49,20 +49,31 @@ Polymer({
/**
* When the custom input field loses focus, validate the current value and
* trigger an event with the result. Show an error message if the validated
* value is still the most recent value, is invalid, and is non-empty.
* trigger an event with the result. If the value is valid, also attempt a
* test query. Show an error message if the tested value is still the most
* recent value, is non-empty, and was either invalid or failed the test
* query.
* @private
*/
validate: function() {
validate: async function() {
this.showError_ = false;
const valueToValidate = this.value;
this.browserProxy_.validateCustomDnsEntry(valueToValidate).then(valid => {
this.showError_ =
valueToValidate === this.value && !valid && valueToValidate !== '';
if (this.showError_) {
this.errorText_ = loadTimeData.getString('secureDnsCustomFormatError');
}
this.fire('value-update', {isValid: valid, text: valueToValidate});
});
const validTemplate =
await this.browserProxy_.validateCustomDnsEntry(valueToValidate);
const successfulProbe = validTemplate &&
await this.browserProxy_.probeCustomDnsTemplate(validTemplate);
// If there was no valid template or a valid template doesn't successfully
// answer a probe query, show an error as long as the input field value
// hasn't changed and is non-empty.
if (valueToValidate === this.value && this.value !== '' &&
!successfulProbe) {
this.errorText_ = loadTimeData.getString(
validTemplate ? 'secureDnsCustomConnectionError' :
'secureDnsCustomFormatError');
this.showError_ = true;
}
this.fire(
'value-update', {isValid: !!validTemplate, text: valueToValidate});
},
/**
......
......@@ -1094,6 +1094,8 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source,
IDS_SETTINGS_SECURE_DNS_CUSTOM_PLACEHOLDER},
{"secureDnsCustomFormatError",
IDS_SETTINGS_SECURE_DNS_CUSTOM_FORMAT_ERROR},
{"secureDnsCustomConnectionError",
IDS_SETTINGS_SECURE_DNS_CUSTOM_CONNECTION_ERROR},
{"contentSettings", IDS_SETTINGS_CONTENT_SETTINGS},
{"siteSettings", IDS_SETTINGS_SITE_SETTINGS},
{"siteSettingsDescription", IDS_SETTINGS_SITE_SETTINGS_DESCRIPTION},
......
......@@ -16,6 +16,9 @@
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/country_codes/country_codes.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "net/dns/public/doh_provider_list.h"
#include "net/dns/public/util.h"
......@@ -27,6 +30,8 @@ namespace settings {
namespace {
const char kProbeHostname[] = "google.com";
std::unique_ptr<base::DictionaryValue> CreateSecureDnsSettingDict() {
// Fetch the current host resolver configuration. It is not sufficient to read
// the secure DNS prefs directly since the host resolver configuration takes
......@@ -91,6 +96,11 @@ void SecureDnsHandler::RegisterMessages() {
"validateCustomDnsEntry",
base::BindRepeating(&SecureDnsHandler::HandleValidateCustomDnsEntry,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"probeCustomDnsTemplate",
base::BindRepeating(&SecureDnsHandler::HandleProbeCustomDnsTemplate,
base::Unretained(this)));
}
void SecureDnsHandler::OnJavascriptAllowed() {
......@@ -156,6 +166,11 @@ base::Value SecureDnsHandler::GetSecureDnsResolverListForCountry(
return resolvers;
}
void SecureDnsHandler::SetNetworkContextForTesting(
network::mojom::NetworkContext* network_context) {
network_context_for_testing_ = network_context;
}
void SecureDnsHandler::HandleGetSecureDnsResolverList(
const base::ListValue* args) {
AllowJavascript();
......@@ -188,14 +203,75 @@ void SecureDnsHandler::HandleValidateCustomDnsEntry(
SplitString(server_templates, " ", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY)) {
if (net::dns_util::IsValidDohTemplate(server_template, &server_method)) {
ResolveJavascriptCallback(*callback_id, base::Value(true));
ResolveJavascriptCallback(*callback_id, base::Value(server_template));
return;
}
}
ResolveJavascriptCallback(*callback_id, base::Value(false));
ResolveJavascriptCallback(*callback_id, base::Value(std::string()));
return;
}
void SecureDnsHandler::HandleProbeCustomDnsTemplate(
const base::ListValue* args) {
AllowJavascript();
receiver_.reset();
host_resolver_.reset();
std::string server_template;
CHECK(args->GetString(0, &probe_callback_id_));
CHECK(args->GetString(1, &server_template));
net::DnsConfigOverrides overrides;
overrides.search = std::vector<std::string>();
overrides.attempts = 1;
overrides.randomize_ports = false;
overrides.secure_dns_mode = net::DnsConfig::SecureDnsMode::SECURE;
std::string server_method;
// We only send probe queries to templates that have already passed a format
// validation check.
CHECK(net::dns_util::IsValidDohTemplate(server_template, &server_method));
overrides.dns_over_https_servers.emplace(
{net::DnsConfig::DnsOverHttpsServerConfig(server_template,
server_method == "POST")});
auto* network_context =
network_context_for_testing_
? network_context_for_testing_
: content::BrowserContext::GetDefaultStoragePartition(
web_ui()->GetWebContents()->GetBrowserContext())
->GetNetworkContext();
network_context->CreateHostResolver(
overrides, host_resolver_.BindNewPipeAndPassReceiver());
network::mojom::ResolveHostParametersPtr parameters =
network::mojom::ResolveHostParameters::New();
parameters->dns_query_type = net::DnsQueryType::A;
parameters->source = net::HostResolverSource::DNS;
parameters->cache_usage =
network::mojom::ResolveHostParameters::CacheUsage::DISALLOWED;
host_resolver_->ResolveHost(net::HostPortPair(kProbeHostname, 80),
net::NetworkIsolationKey::CreateTransient(),
std::move(parameters),
receiver_.BindNewPipeAndPassRemote());
receiver_.set_disconnect_handler(base::BindOnce(
&SecureDnsHandler::OnMojoConnectionError, base::Unretained(this)));
}
// network::ResolveHostClientBase impl:
void SecureDnsHandler::OnComplete(
int result,
const net::ResolveErrorInfo& resolve_error_info,
const base::Optional<net::AddressList>& resolved_addresses) {
receiver_.reset();
host_resolver_.reset();
ResolveJavascriptCallback(base::Value(probe_callback_id_),
base::Value(result == 0));
}
void SecureDnsHandler::OnMojoConnectionError() {
OnComplete(net::ERR_NAME_NOT_RESOLVED, net::ResolveErrorInfo(net::ERR_FAILED),
base::nullopt);
}
void SecureDnsHandler::SendSecureDnsSettingUpdatesToJavascript() {
FireWebUIListener("secure-dns-setting-changed",
*CreateSecureDnsSettingDict());
......
......@@ -9,12 +9,18 @@
#include "base/values.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
#include "components/prefs/pref_change_registrar.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/dns/public/doh_provider_list.h"
#include "services/network/public/cpp/resolve_host_client_base.h"
#include "services/network/public/mojom/host_resolver.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
namespace settings {
// Handler for the Secure DNS setting.
class SecureDnsHandler : public SettingsPageUIHandler {
class SecureDnsHandler : public SettingsPageUIHandler,
network::ResolveHostClientBase {
public:
SecureDnsHandler();
~SecureDnsHandler() override;
......@@ -32,6 +38,9 @@ class SecureDnsHandler : public SettingsPageUIHandler {
int country_id,
const std::vector<net::DohProviderEntry>& providers);
void SetNetworkContextForTesting(
network::mojom::NetworkContext* network_context);
protected:
// Retrieves all pre-approved secure resolvers and returns them to WebUI.
void HandleGetSecureDnsResolverList(const base::ListValue* args);
......@@ -42,11 +51,26 @@ class SecureDnsHandler : public SettingsPageUIHandler {
// Returns whether or not a custom entry is valid.
void HandleValidateCustomDnsEntry(const base::ListValue* args);
// Returns whether or not a test query to the resolver succeeds.
void HandleProbeCustomDnsTemplate(const base::ListValue* args);
// Retrieves the current host resolver configuration, computes the
// corresponding UI representation, and sends it to javascript.
void SendSecureDnsSettingUpdatesToJavascript();
private:
// network::ResolveHostClientBase impl:
void OnComplete(
int result,
const net::ResolveErrorInfo& resolve_error_info,
const base::Optional<net::AddressList>& resolved_addresses) override;
void OnMojoConnectionError();
network::mojom::NetworkContext* network_context_for_testing_ = nullptr;
mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this};
mojo::Remote<network::mojom::HostResolver> host_resolver_;
std::string probe_callback_id_;
PrefChangeRegistrar pref_registrar_;
DISALLOW_COPY_AND_ASSIGN(SecureDnsHandler);
......
......@@ -6,6 +6,7 @@
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/dns_probe_test_util.h"
#include "chrome/browser/net/dns_util.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
......@@ -16,6 +17,7 @@
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/test_web_ui.h"
#include "net/dns/public/resolve_error_info.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -33,6 +35,7 @@ namespace {
constexpr char kGetSecureDnsResolverList[] = "getSecureDnsResolverList";
constexpr char kValidateCustomDnsEntry[] = "validateCustomDnsEntry";
constexpr char kProbeCustomDnsTemplate[] = "probeCustomDnsTemplate";
constexpr char kWebUiFunctionName[] = "webUiCallbackName";
const std::vector<DohProviderEntry>& GetDohProviderListForTesting() {
......@@ -454,7 +457,8 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateValid) {
// The request should be successful.
ASSERT_TRUE(call_data.arg2()->GetBool());
// The template should be valid.
ASSERT_TRUE(call_data.arg3()->GetBool());
ASSERT_EQ("https://example.template/dns-query",
call_data.arg3()->GetString());
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateInvalid) {
......@@ -469,7 +473,7 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateInvalid) {
// The request should be successful.
ASSERT_TRUE(call_data.arg2()->GetBool());
// The template should be invalid.
ASSERT_FALSE(call_data.arg3()->GetBool());
ASSERT_EQ(std::string(), call_data.arg3()->GetString());
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, MultipleTemplates) {
......@@ -484,8 +488,9 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, MultipleTemplates) {
EXPECT_EQ(kWebUiFunctionName, call_data_valid.arg1()->GetString());
// The request should be successful.
ASSERT_TRUE(call_data_valid.arg2()->GetBool());
// The entry should be valid.
ASSERT_TRUE(call_data_valid.arg3()->GetBool());
// The second template should be valid.
ASSERT_EQ("https://example.template/dns-query",
call_data_valid.arg3()->GetString());
base::ListValue args_invalid;
args_invalid.AppendString(kWebUiFunctionName);
......@@ -498,7 +503,62 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, MultipleTemplates) {
// The request should be successful.
ASSERT_TRUE(call_data_invalid.arg2()->GetBool());
// The entry should be invalid.
ASSERT_FALSE(call_data_invalid.arg3()->GetBool());
ASSERT_EQ(std::string(), call_data_invalid.arg3()->GetString());
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateProbeSuccess) {
auto network_context_ =
std::make_unique<chrome_browser_net::FakeHostResolverNetworkContext>(
std::vector<chrome_browser_net::FakeHostResolver::SingleResult>(
{chrome_browser_net::FakeHostResolver::SingleResult(
net::OK, net::ResolveErrorInfo(net::OK),
chrome_browser_net::FakeHostResolver::
kOneAddressResponse)}) /* current_config_result_list */,
std::vector<chrome_browser_net::FakeHostResolver::
SingleResult>() /* google_config_result_list */);
handler_->SetNetworkContextForTesting(network_context_.get());
base::ListValue args_valid;
args_valid.AppendString(kWebUiFunctionName);
args_valid.AppendString("https://example.template/dns-query");
web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, &args_valid);
base::RunLoop().RunUntilIdle();
const content::TestWebUI::CallData& call_data_valid =
*web_ui_.call_data().back();
EXPECT_EQ("cr.webUIResponse", call_data_valid.function_name());
EXPECT_EQ(kWebUiFunctionName, call_data_valid.arg1()->GetString());
// The request should be successful.
ASSERT_TRUE(call_data_valid.arg2()->GetBool());
// The probe query should have succeeded.
ASSERT_TRUE(call_data_valid.arg3()->GetBool());
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateProbeFailure) {
auto network_context_ =
std::make_unique<chrome_browser_net::FakeHostResolverNetworkContext>(
std::vector<chrome_browser_net::FakeHostResolver::SingleResult>(
{chrome_browser_net::FakeHostResolver::SingleResult(
net::ERR_NAME_NOT_RESOLVED,
net::ResolveErrorInfo(net::ERR_DNS_MALFORMED_RESPONSE),
chrome_browser_net::FakeHostResolver::
kNoResponse)}) /* current_config_result_list */,
std::vector<chrome_browser_net::FakeHostResolver::
SingleResult>() /* google_config_result_list */);
handler_->SetNetworkContextForTesting(network_context_.get());
base::ListValue args_valid;
args_valid.AppendString(kWebUiFunctionName);
args_valid.AppendString("https://example.template/dns-query");
web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, &args_valid);
base::RunLoop().RunUntilIdle();
const content::TestWebUI::CallData& call_data_valid =
*web_ui_.call_data().back();
EXPECT_EQ("cr.webUIResponse", call_data_valid.function_name());
EXPECT_EQ(kWebUiFunctionName, call_data_valid.arg1()->GetString());
// The request should be successful.
ASSERT_TRUE(call_data_valid.arg2()->GetBool());
// The probe query should have failed.
ASSERT_FALSE(call_data_valid.arg3()->GetBool());
}
} // namespace settings
......@@ -65,6 +65,9 @@ suite('SettingsSecureDnsInteractive', function() {
},
];
const invalidEntry = 'invalid_template';
const validEntry = 'https://example.doh.server/dns-query';
suiteSetup(function() {
loadTimeData.overrideValues({showSecureDnsSetting: true});
});
......@@ -127,10 +130,13 @@ suite('SettingsSecureDnsInteractive', function() {
// click outside the text field. The mode pref should be updated to
// 'secure'.
secureDnsInput.focus();
secureDnsInput.value = 'https://example.doh.server/dns-query';
testBrowserProxy.setIsEntryValid(true);
secureDnsInput.value = validEntry;
testBrowserProxy.setValidEntry(validEntry);
secureDnsInput.blur();
await testBrowserProxy.whenCalled('validateCustomDnsEntry');
await Promise.all([
testBrowserProxy.whenCalled('validateCustomDnsEntry'),
testBrowserProxy.whenCalled('probeCustomDnsTemplate')
]);
assertEquals(
settings.SecureDnsMode.SECURE,
testElement.prefs.dns_over_https.mode.value);
......@@ -146,12 +152,15 @@ suite('SettingsSecureDnsInteractive', function() {
secureDnsToggle.click();
assertEquals(settings.SecureDnsMode.SECURE, secureDnsRadioGroup.selected);
assertTrue(secureDnsInput.matches(':focus-within'));
assertEquals('https://example.doh.server/dns-query', secureDnsInput.value);
assertEquals(validEntry, secureDnsInput.value);
assertEquals(
settings.SecureDnsMode.OFF,
testElement.prefs.dns_over_https.mode.value);
secureDnsInput.blur();
await testBrowserProxy.whenCalled('validateCustomDnsEntry');
await Promise.all([
testBrowserProxy.whenCalled('validateCustomDnsEntry'),
testBrowserProxy.whenCalled('probeCustomDnsTemplate')
]);
assertEquals(
settings.SecureDnsMode.SECURE,
testElement.prefs.dns_over_https.mode.value);
......@@ -323,8 +332,8 @@ suite('SettingsSecureDnsInteractive', function() {
// Make the template invalid and check that the mode pref changes to
// 'automatic'.
secureDnsInput.focus();
secureDnsInput.value = 'invalid_template';
testBrowserProxy.setIsEntryValid(false);
secureDnsInput.value = invalidEntry;
testBrowserProxy.setValidEntry('');
secureDnsInput.blur();
await testBrowserProxy.whenCalled('validateCustomDnsEntry');
assertFalse(secureDnsInput.matches(':focus-within'));
......@@ -347,17 +356,21 @@ suite('SettingsSecureDnsInteractive', function() {
assertFalse(secureDnsInput.hasAttribute('hidden'));
assertFalse(secureDnsInput.matches(':focus-within'));
assertTrue(secureDnsInput.isInvalid());
assertEquals('invalid_template', secureDnsInput.value);
assertEquals(invalidEntry, secureDnsInput.value);
assertEquals(
settings.SecureDnsMode.AUTOMATIC, secureDnsRadioGroup.selected);
// Make the template valid but don't change the radio button yet.
// Make the template valid, but don't change the radio button yet.
secureDnsInput.focus();
secureDnsInput.value =
'https://dns.ex/dns-query invalid https://dns.ex.another/dns-query';
testBrowserProxy.setIsEntryValid(true);
`${validEntry} ${invalidEntry} https://dns.ex.another/dns-query`;
testBrowserProxy.setValidEntry(validEntry);
testBrowserProxy.setProbeSuccess(true);
secureDnsInput.blur();
await testBrowserProxy.whenCalled('validateCustomDnsEntry');
await Promise.all([
testBrowserProxy.whenCalled('validateCustomDnsEntry'),
testBrowserProxy.whenCalled('probeCustomDnsTemplate')
]);
assertFalse(secureDnsInput.matches(':focus-within'));
assertFalse(secureDnsInput.isInvalid());
assertEquals(
......@@ -373,7 +386,10 @@ suite('SettingsSecureDnsInteractive', function() {
testElement.prefs.dns_over_https.mode.value);
assertEquals('', testElement.prefs.dns_over_https.templates.value);
secureDnsInput.blur();
await testBrowserProxy.whenCalled('validateCustomDnsEntry');
await Promise.all([
testBrowserProxy.whenCalled('validateCustomDnsEntry'),
testBrowserProxy.whenCalled('probeCustomDnsTemplate')
]);
assertFalse(secureDnsInput.matches(':focus-within'));
assertFalse(secureDnsInput.isInvalid());
assertEquals(settings.SecureDnsMode.SECURE, secureDnsRadioGroup.selected);
......@@ -381,7 +397,7 @@ suite('SettingsSecureDnsInteractive', function() {
settings.SecureDnsMode.SECURE,
testElement.prefs.dns_over_https.mode.value);
assertEquals(
'https://dns.ex/dns-query invalid https://dns.ex.another/dns-query',
`${validEntry} ${invalidEntry} https://dns.ex.another/dns-query`,
testElement.prefs.dns_over_https.templates.value);
// Make sure the input field updates with a change in the underlying
......
......@@ -14,12 +14,21 @@ suite('SettingsSecureDnsInput', function() {
/** @type {SecureDnsInputElement} */
let testElement;
/** @type {CrInputElement} */
let crInput;
// Possible error messages
const invalidFormat = 'invalid format description';
const probeFail = 'probe fail description';
const invalidEntry = 'invalid_entry';
const validFailEntry = 'https://example.server/dns-query';
const validSuccessEntry = 'https://example.server.another/dns-query';
suiteSetup(function() {
loadTimeData.overrideValues({
secureDnsCustomFormatError: invalidFormat,
secureDnsCustomConnectionError: probeFail,
});
});
......@@ -30,37 +39,66 @@ suite('SettingsSecureDnsInput', function() {
testElement = document.createElement('secure-dns-input');
document.body.appendChild(testElement);
Polymer.dom.flush();
crInput = testElement.$$('#input');
assertFalse(crInput.invalid);
assertEquals('', testElement.value);
});
teardown(function() {
testElement.remove();
});
test('SecureDnsInputError', async function() {
const crInput = testElement.$$('#input');
assertFalse(crInput.invalid);
assertEquals('', testElement.value);
test('SecureDnsInputEmpty', async function() {
// Trigger validation on an empty input.
testBrowserProxy.setIsEntryValid(false);
testBrowserProxy.setValidEntry('');
testElement.validate();
await testBrowserProxy.whenCalled('validateCustomDnsEntry');
assertEquals(
'', await testBrowserProxy.whenCalled('validateCustomDnsEntry'));
assertFalse(crInput.invalid);
assertFalse(testElement.isInvalid());
});
test('SecureDnsInputValidFormatAndProbeFail', async function() {
// Enter two valid servers but make the first one fail the test query.
testElement.value = `${validFailEntry} ${validSuccessEntry}`;
testBrowserProxy.setValidEntry(validFailEntry);
testBrowserProxy.setProbeSuccess(false);
testElement.validate();
assertEquals(
`${validFailEntry} ${validSuccessEntry}`,
await testBrowserProxy.whenCalled('validateCustomDnsEntry'));
assertEquals(
validFailEntry,
await testBrowserProxy.whenCalled('probeCustomDnsTemplate'));
assertTrue(crInput.invalid);
assertTrue(testElement.isInvalid());
assertEquals(probeFail, crInput.errorMessage);
});
// Enter a valid input and trigger validation.
testElement.value = 'https://example.server/dns-query';
testBrowserProxy.setIsEntryValid(true);
test('SecureDnsInputValidFormatAndProbeSuccess', async function() {
// Enter a valid input and make the test query succeed.
testElement.value = validSuccessEntry;
testBrowserProxy.setValidEntry(validSuccessEntry);
testBrowserProxy.setProbeSuccess(true);
testElement.validate();
await testBrowserProxy.whenCalled('validateCustomDnsEntry');
assertEquals(
validSuccessEntry,
await testBrowserProxy.whenCalled('validateCustomDnsEntry'));
assertEquals(
validSuccessEntry,
await testBrowserProxy.whenCalled('probeCustomDnsTemplate'));
assertFalse(crInput.invalid);
assertFalse(testElement.isInvalid());
});
test('SecureDnsInputInvalid', async function() {
// Enter an invalid input and trigger validation.
testElement.value = 'invalid_template';
testBrowserProxy.setIsEntryValid(false);
testElement.value = invalidEntry;
testBrowserProxy.setValidEntry('');
testElement.validate();
await testBrowserProxy.whenCalled('validateCustomDnsEntry');
assertEquals(
invalidEntry,
await testBrowserProxy.whenCalled('validateCustomDnsEntry'));
assertTrue(crInput.invalid);
assertTrue(testElement.isInvalid());
assertEquals(invalidFormat, crInput.errorMessage);
......@@ -69,7 +107,7 @@ suite('SettingsSecureDnsInput', function() {
crInput.fire('input');
assertFalse(crInput.invalid);
assertFalse(testElement.isInvalid());
assertEquals('invalid_template', testElement.value);
assertEquals(invalidEntry, testElement.value);
});
});
......
......@@ -14,6 +14,7 @@ class TestPrivacyPageBrowserProxy extends TestBrowserProxy {
'getSecureDnsResolverList',
'getSecureDnsSetting',
'validateCustomDnsEntry',
'probeCustomDnsTemplate',
]);
/** @type {!MetricsReporting} */
......@@ -94,15 +95,29 @@ class TestPrivacyPageBrowserProxy extends TestBrowserProxy {
/**
* Sets the return value for the next validateCustomDnsEntry call.
* @param {boolean} isEntryValid
* @param {string} validEntry
*/
setIsEntryValid(isEntryValid) {
this.isEntryValid_ = isEntryValid;
setValidEntry(validEntry) {
this.validEntry_ = validEntry;
}
/** @override */
validateCustomDnsEntry() {
this.methodCalled('validateCustomDnsEntry');
return Promise.resolve(this.isEntryValid_);
validateCustomDnsEntry(entry) {
this.methodCalled('validateCustomDnsEntry', entry);
return Promise.resolve(this.validEntry_);
}
/**
* Sets the return value for the next probeCustomDnsTemplate call.
* @param {boolean} success
*/
setProbeSuccess(success) {
this.probeSuccess_ = success;
}
/** @override */
probeCustomDnsTemplate(template) {
this.methodCalled('probeCustomDnsTemplate', template);
return Promise.resolve(this.probeSuccess_);
}
}
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