#include "components/domain_reliability/monitor.h"
#include "base/command_line.h"
+#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
+#include "components/domain_reliability/baked_in_configs.h"
#include "content/public/browser/browser_thread.h"
+#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
: context_(context),
main_task_runner_(main_task_runner) {}
- // net::URLRequestContextGEtter implementation:
+ // net::URLRequestContextGetter implementation:
virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
return context_;
}
namespace domain_reliability {
DomainReliabilityMonitor::DomainReliabilityMonitor(
- net::URLRequestContext* url_request_context)
+ net::URLRequestContext* url_request_context,
+ const std::string& upload_reporter_string)
: time_(new ActualTime()),
url_request_context_getter_(scoped_refptr<net::URLRequestContextGetter>(
new TrivialURLRequestContextGetter(
url_request_context,
content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::IO)))),
+ upload_reporter_string_(upload_reporter_string),
scheduler_params_(
DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
dispatcher_(time_.get()),
DomainReliabilityMonitor::DomainReliabilityMonitor(
net::URLRequestContext* url_request_context,
+ const std::string& upload_reporter_string,
scoped_ptr<MockableTime> time)
: time_(time.Pass()),
url_request_context_getter_(scoped_refptr<net::URLRequestContextGetter>(
url_request_context,
content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::IO)))),
+ upload_reporter_string_(upload_reporter_string),
scheduler_params_(
DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
dispatcher_(time_.get()),
DomainReliabilityMonitor::~DomainReliabilityMonitor() {
DCHECK(OnIOThread());
- STLDeleteContainerPairSecondPointers(
- contexts_.begin(), contexts_.end());
+ STLDeleteContainerPairSecondPointers(contexts_.begin(), contexts_.end());
+}
+
+void DomainReliabilityMonitor::AddBakedInConfigs() {
+ base::Time now = base::Time::Now();
+ for (size_t i = 0; kBakedInJsonConfigs[i]; ++i) {
+ std::string json(kBakedInJsonConfigs[i]);
+ scoped_ptr<const DomainReliabilityConfig> config =
+ DomainReliabilityConfig::FromJSON(json);
+ if (config && config->IsExpired(now)) {
+ LOG(WARNING) << "Baked-in Domain Reliability config for "
+ << config->domain << " is expired.";
+ continue;
+ }
+ AddContext(config.Pass());
+ }
}
void DomainReliabilityMonitor::OnBeforeRedirect(net::URLRequest* request) {
DCHECK(OnIOThread());
- RequestInfo request_info(*request);
// Record the redirect itself in addition to the final request.
- OnRequestLegComplete(request_info);
+ OnRequestLegComplete(RequestInfo(*request));
}
void DomainReliabilityMonitor::OnCompleted(net::URLRequest* request,
if (!started)
return;
RequestInfo request_info(*request);
- OnRequestLegComplete(request_info);
+ if (request_info.DefinitelyReachedNetwork()) {
+ OnRequestLegComplete(request_info);
+ // A request was just using the network, so now is a good time to run any
+ // pending and eligible uploads.
+ dispatcher_.RunEligibleTasks();
+ }
}
DomainReliabilityContext* DomainReliabilityMonitor::AddContextForTesting(
scoped_ptr<const DomainReliabilityConfig> config) {
- DomainReliabilityContext*& context_ref = contexts_[config->domain];
- DCHECK(!context_ref);
- context_ref = new DomainReliabilityContext(
- time_.get(),
- scheduler_params_,
- &dispatcher_,
- uploader_.get(),
- config.Pass());
- return context_ref;
+ return AddContext(config.Pass());
}
DomainReliabilityMonitor::RequestInfo::RequestInfo() {}
status(request.status()),
response_code(-1),
socket_address(request.GetSocketAddress()),
- was_cached(request.was_cached()) {
+ was_cached(request.was_cached()),
+ load_flags(request.load_flags()),
+ is_upload(DomainReliabilityUploader::URLRequestIsUpload(request)) {
request.GetLoadTimingInfo(&load_timing_info);
// Can't get response code of a canceled request -- there's no transaction.
if (status.status() != net::URLRequestStatus::CANCELED)
DomainReliabilityMonitor::RequestInfo::~RequestInfo() {}
+bool DomainReliabilityMonitor::RequestInfo::DefinitelyReachedNetwork() const {
+ return status.status() != net::URLRequestStatus::CANCELED && !was_cached;
+}
+
+DomainReliabilityContext* DomainReliabilityMonitor::AddContext(
+ scoped_ptr<const DomainReliabilityConfig> config) {
+ DCHECK(config);
+ DCHECK(config->IsValid());
+
+ // Grab a copy of the domain before transferring ownership of |config|.
+ std::string domain = config->domain;
+
+ DomainReliabilityContext* context =
+ new DomainReliabilityContext(time_.get(),
+ scheduler_params_,
+ upload_reporter_string_,
+ &dispatcher_,
+ uploader_.get(),
+ config.Pass());
+
+ std::pair<ContextMap::iterator, bool> map_it =
+ contexts_.insert(make_pair(domain, context));
+ // Make sure the domain wasn't already in the map.
+ DCHECK(map_it.second);
+
+ return map_it.first->second;
+}
+
void DomainReliabilityMonitor::OnRequestLegComplete(
const RequestInfo& request) {
- if (request.was_cached ||
- request.status.status() == net::URLRequestStatus::CANCELED) {
+ if (!request.DefinitelyReachedNetwork())
+ return;
+
+ // Don't monitor requests that are not sending cookies, since sending a beacon
+ // for such requests may allow the server to correlate that request with the
+ // user (by correlating a particular config).
+ if (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES)
+ return;
+
+ // Don't monitor requests that were, themselves, Domain Reliability uploads,
+ // to avoid infinite chains of uploads.
+ if (request.is_upload)
return;
- }
- std::map<std::string, DomainReliabilityContext*>::iterator it =
- contexts_.find(request.url.host());
+ ContextMap::iterator it = contexts_.find(request.url.host());
if (it == contexts_.end())
return;
DomainReliabilityContext* context = it->second;
std::string beacon_status;
- bool got_status = DomainReliabilityUtil::GetBeaconStatus(
+ bool got_status = GetDomainReliabilityBeaconStatus(
request.status.error(),
request.response_code,
&beacon_status);
beacon.server_ip = request.socket_address.host();
beacon.http_response_code = request.response_code;
beacon.start_time = request.load_timing_info.request_start;
- beacon.elapsed = time_->Now() - beacon.start_time;
- context->AddBeacon(beacon, request.url);
+ beacon.elapsed = time_->NowTicks() - beacon.start_time;
+ context->OnBeacon(request.url, beacon);
}
} // namespace domain_reliability