Commit 2b8a914a authored by ttuttle@chromium.org's avatar ttuttle@chromium.org

Domain Reliability: Add wildcard domain support.

Add support for configs with domains *.foo.bar.  Given a domain foo.bar, it
will first look for a config with domain foo.bar, then *.foo.bar, then *.bar.

BUG=396139

Review URL: https://codereview.chromium.org/404363003

Cr-Commit-Position: refs/heads/master@{#288428}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288428 0039d316-1c4b-4281-b951-d872f2087c98
parent 9c765638
...@@ -176,7 +176,7 @@ TEST_F(DomainReliabilityContextTest, ReportUpload) { ...@@ -176,7 +176,7 @@ TEST_F(DomainReliabilityContextTest, ReportUpload) {
time_.Advance(max_delay()); time_.Advance(max_delay());
EXPECT_TRUE(upload_pending()); EXPECT_TRUE(upload_pending());
EXPECT_EQ(kExpectedReport, upload_report()); EXPECT_EQ(kExpectedReport, upload_report());
EXPECT_EQ(GURL("https://example/upload"), upload_url()); EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url());
CallUploadCallback(true); CallUploadCallback(true);
EXPECT_TRUE(CheckNoBeacons()); EXPECT_TRUE(CheckNoBeacons());
......
...@@ -196,13 +196,14 @@ void DomainReliabilityMonitor::OnRequestLegComplete( ...@@ -196,13 +196,14 @@ void DomainReliabilityMonitor::OnRequestLegComplete(
response_code = request.response_info.headers->response_code(); response_code = request.response_info.headers->response_code();
else else
response_code = -1; response_code = -1;
ContextMap::iterator context_it;
std::string beacon_status; std::string beacon_status;
int error_code = net::OK; int error_code = net::OK;
if (request.status.status() == net::URLRequestStatus::FAILED) if (request.status.status() == net::URLRequestStatus::FAILED)
error_code = request.status.error(); error_code = request.status.error();
DomainReliabilityContext* context = GetContextForHost(request.url.host());
// Ignore requests where: // Ignore requests where:
// 1. There is no context for the request host. // 1. There is no context for the request host.
// 2. The request did not access the network. // 2. The request did not access the network.
...@@ -211,7 +212,7 @@ void DomainReliabilityMonitor::OnRequestLegComplete( ...@@ -211,7 +212,7 @@ void DomainReliabilityMonitor::OnRequestLegComplete(
// 4. The request was itself a Domain Reliability upload (to avoid loops). // 4. The request was itself a Domain Reliability upload (to avoid loops).
// 5. There is no defined beacon status for the error or HTTP response code // 5. There is no defined beacon status for the error or HTTP response code
// (to avoid leaking network-local errors). // (to avoid leaking network-local errors).
if ((context_it = contexts_.find(request.url.host())) == contexts_.end() || if (!context ||
!request.AccessedNetwork() || !request.AccessedNetwork() ||
(request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) || (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) ||
request.is_upload || request.is_upload ||
...@@ -233,7 +234,36 @@ void DomainReliabilityMonitor::OnRequestLegComplete( ...@@ -233,7 +234,36 @@ void DomainReliabilityMonitor::OnRequestLegComplete(
beacon.http_response_code = response_code; beacon.http_response_code = response_code;
beacon.start_time = request.load_timing_info.request_start; beacon.start_time = request.load_timing_info.request_start;
beacon.elapsed = time_->NowTicks() - beacon.start_time; beacon.elapsed = time_->NowTicks() - beacon.start_time;
context_it->second->OnBeacon(request.url, beacon); context->OnBeacon(request.url, beacon);
}
// TODO(ttuttle): Keep a separate wildcard_contexts_ map to avoid having to
// prepend '*.' to domains.
DomainReliabilityContext* DomainReliabilityMonitor::GetContextForHost(
const std::string& host) const {
ContextMap::const_iterator context_it;
context_it = contexts_.find(host);
if (context_it != contexts_.end())
return context_it->second;
std::string host_with_asterisk = "*." + host;
context_it = contexts_.find(host_with_asterisk);
if (context_it != contexts_.end())
return context_it->second;
size_t dot_pos = host.find('.');
if (dot_pos == std::string::npos)
return NULL;
// TODO(ttuttle): Make sure parent is not in PSL before using.
std::string parent_with_asterisk = "*." + host.substr(dot_pos + 1);
context_it = contexts_.find(parent_with_asterisk);
if (context_it != contexts_.end())
return context_it->second;
return NULL;
} }
base::WeakPtr<DomainReliabilityMonitor> base::WeakPtr<DomainReliabilityMonitor>
......
...@@ -112,6 +112,8 @@ class DOMAIN_RELIABILITY_EXPORT DomainReliabilityMonitor { ...@@ -112,6 +112,8 @@ class DOMAIN_RELIABILITY_EXPORT DomainReliabilityMonitor {
void ClearContexts(); void ClearContexts();
void OnRequestLegComplete(const RequestInfo& info); void OnRequestLegComplete(const RequestInfo& info);
DomainReliabilityContext* GetContextForHost(const std::string& host) const;
base::WeakPtr<DomainReliabilityMonitor> MakeWeakPtr(); base::WeakPtr<DomainReliabilityMonitor> MakeWeakPtr();
scoped_ptr<base::ThreadChecker> thread_checker_; scoped_ptr<base::ThreadChecker> thread_checker_;
......
...@@ -87,13 +87,27 @@ class DomainReliabilityMonitorTest : public testing::Test { ...@@ -87,13 +87,27 @@ class DomainReliabilityMonitorTest : public testing::Test {
bool CheckRequestCounts(size_t index, bool CheckRequestCounts(size_t index,
uint32 expected_successful, uint32 expected_successful,
uint32 expected_failed) { uint32 expected_failed) {
return CheckRequestCounts(context_,
index,
expected_successful,
expected_failed);
}
bool CheckRequestCounts(DomainReliabilityContext* context,
size_t index,
uint32 expected_successful,
uint32 expected_failed) {
uint32 successful, failed; uint32 successful, failed;
context_->GetRequestCountsForTesting(index, &successful, &failed); context->GetRequestCountsForTesting(index, &successful, &failed);
EXPECT_EQ(expected_successful, successful); EXPECT_EQ(expected_successful, successful);
EXPECT_EQ(expected_failed, failed); EXPECT_EQ(expected_failed, failed);
return expected_successful == successful && expected_failed == failed; return expected_successful == successful && expected_failed == failed;
} }
DomainReliabilityContext* CreateAndAddContext(const std::string& domain) {
return monitor_.AddContextForTesting(MakeTestConfigWithDomain(domain));
}
scoped_refptr<base::TestSimpleTaskRunner> network_task_runner_; scoped_refptr<base::TestSimpleTaskRunner> network_task_runner_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
MockTime* time_; MockTime* time_;
...@@ -301,6 +315,70 @@ TEST_F(DomainReliabilityMonitorTest, IgnoreSuccessError) { ...@@ -301,6 +315,70 @@ TEST_F(DomainReliabilityMonitorTest, IgnoreSuccessError) {
EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u)); EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u));
} }
TEST_F(DomainReliabilityMonitorTest, WildcardMatchesSelf) {
DomainReliabilityContext* context = CreateAndAddContext("*.wildcard");
RequestInfo request = MakeRequestInfo();
request.url = GURL("http://wildcard/always_report");
OnRequestLegComplete(request);
EXPECT_TRUE(CheckRequestCounts(context, kAlwaysReportIndex, 1u, 0u));
}
TEST_F(DomainReliabilityMonitorTest, WildcardMatchesSubdomain) {
DomainReliabilityContext* context = CreateAndAddContext("*.wildcard");
RequestInfo request = MakeRequestInfo();
request.url = GURL("http://test.wildcard/always_report");
OnRequestLegComplete(request);
EXPECT_TRUE(CheckRequestCounts(context, kAlwaysReportIndex, 1u, 0u));
}
TEST_F(DomainReliabilityMonitorTest, WildcardDoesntMatchSubsubdomain) {
DomainReliabilityContext* context = CreateAndAddContext("*.wildcard");
RequestInfo request = MakeRequestInfo();
request.url = GURL("http://test.test.wildcard/always_report");
OnRequestLegComplete(request);
EXPECT_TRUE(CheckRequestCounts(context, kAlwaysReportIndex, 0u, 0u));
}
TEST_F(DomainReliabilityMonitorTest, WildcardPrefersSelfToSelfWildcard) {
DomainReliabilityContext* context1 = CreateAndAddContext("wildcard");
DomainReliabilityContext* context2 = CreateAndAddContext("*.wildcard");
RequestInfo request = MakeRequestInfo();
request.url = GURL("http://wildcard/always_report");
OnRequestLegComplete(request);
EXPECT_TRUE(CheckRequestCounts(context1, kAlwaysReportIndex, 1u, 0u));
EXPECT_TRUE(CheckRequestCounts(context2, kAlwaysReportIndex, 0u, 0u));
}
TEST_F(DomainReliabilityMonitorTest, WildcardPrefersSelfToParentWildcard) {
DomainReliabilityContext* context1 = CreateAndAddContext("test.wildcard");
DomainReliabilityContext* context2 = CreateAndAddContext("*.wildcard");
RequestInfo request = MakeRequestInfo();
request.url = GURL("http://test.wildcard/always_report");
OnRequestLegComplete(request);
EXPECT_TRUE(CheckRequestCounts(context1, kAlwaysReportIndex, 1u, 0u));
EXPECT_TRUE(CheckRequestCounts(context2, kAlwaysReportIndex, 0u, 0u));
}
TEST_F(DomainReliabilityMonitorTest,
WildcardPrefersSelfWildcardToParentWildcard) {
DomainReliabilityContext* context1 = CreateAndAddContext("*.test.wildcard");
DomainReliabilityContext* context2 = CreateAndAddContext("*.wildcard");
RequestInfo request = MakeRequestInfo();
request.url = GURL("http://test.wildcard/always_report");
OnRequestLegComplete(request);
EXPECT_TRUE(CheckRequestCounts(context1, kAlwaysReportIndex, 1u, 0u));
EXPECT_TRUE(CheckRequestCounts(context2, kAlwaysReportIndex, 0u, 0u));
}
} // namespace } // namespace
} // namespace domain_reliability } // namespace domain_reliability
...@@ -154,13 +154,18 @@ DomainReliabilityScheduler::Params MakeTestSchedulerParams() { ...@@ -154,13 +154,18 @@ DomainReliabilityScheduler::Params MakeTestSchedulerParams() {
} }
scoped_ptr<const DomainReliabilityConfig> MakeTestConfig() { scoped_ptr<const DomainReliabilityConfig> MakeTestConfig() {
return MakeTestConfigWithDomain("example");
}
scoped_ptr<const DomainReliabilityConfig> MakeTestConfigWithDomain(
const std::string& domain) {
DomainReliabilityConfig* config = new DomainReliabilityConfig(); DomainReliabilityConfig* config = new DomainReliabilityConfig();
DomainReliabilityConfig::Resource* resource; DomainReliabilityConfig::Resource* resource;
resource = new DomainReliabilityConfig::Resource(); resource = new DomainReliabilityConfig::Resource();
resource->name = "always_report"; resource->name = "always_report";
resource->url_patterns.push_back( resource->url_patterns.push_back(
new std::string("http://example/always_report")); new std::string("http://*/always_report"));
resource->success_sample_rate = 1.0; resource->success_sample_rate = 1.0;
resource->failure_sample_rate = 1.0; resource->failure_sample_rate = 1.0;
config->resources.push_back(resource); config->resources.push_back(resource);
...@@ -168,19 +173,19 @@ scoped_ptr<const DomainReliabilityConfig> MakeTestConfig() { ...@@ -168,19 +173,19 @@ scoped_ptr<const DomainReliabilityConfig> MakeTestConfig() {
resource = new DomainReliabilityConfig::Resource(); resource = new DomainReliabilityConfig::Resource();
resource->name = "never_report"; resource->name = "never_report";
resource->url_patterns.push_back( resource->url_patterns.push_back(
new std::string("http://example/never_report")); new std::string("http://*/never_report"));
resource->success_sample_rate = 0.0; resource->success_sample_rate = 0.0;
resource->failure_sample_rate = 0.0; resource->failure_sample_rate = 0.0;
config->resources.push_back(resource); config->resources.push_back(resource);
DomainReliabilityConfig::Collector* collector; DomainReliabilityConfig::Collector* collector;
collector = new DomainReliabilityConfig::Collector(); collector = new DomainReliabilityConfig::Collector();
collector->upload_url = GURL("https://example/upload"); collector->upload_url = GURL("https://exampleuploader/upload");
config->collectors.push_back(collector); config->collectors.push_back(collector);
config->version = "1"; config->version = "1";
config->valid_until = 1234567890.0; config->valid_until = 1234567890.0;
config->domain = "example"; config->domain = domain;
DCHECK(config->IsValid()); DCHECK(config->IsValid());
......
...@@ -115,6 +115,8 @@ class MockTime : public MockableTime { ...@@ -115,6 +115,8 @@ class MockTime : public MockableTime {
}; };
scoped_ptr<const DomainReliabilityConfig> MakeTestConfig(); scoped_ptr<const DomainReliabilityConfig> MakeTestConfig();
scoped_ptr<const DomainReliabilityConfig> MakeTestConfigWithDomain(
const std::string& domain);
DomainReliabilityScheduler::Params MakeTestSchedulerParams(); DomainReliabilityScheduler::Params MakeTestSchedulerParams();
} // namespace domain_reliability } // namespace domain_reliability
......
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