Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / components / domain_reliability / monitor.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/domain_reliability/monitor.h"
6
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/task_runner.h"
12 #include "base/threading/thread_checker.h"
13 #include "base/time/time.h"
14 #include "components/domain_reliability/baked_in_configs.h"
15 #include "net/base/load_flags.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/url_request/url_request.h"
18 #include "net/url_request/url_request_context.h"
19 #include "net/url_request/url_request_context_getter.h"
20
21 namespace domain_reliability {
22
23 DomainReliabilityMonitor::DomainReliabilityMonitor(
24     const std::string& upload_reporter_string)
25     : time_(new ActualTime()),
26       upload_reporter_string_(upload_reporter_string),
27       scheduler_params_(
28           DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
29       dispatcher_(time_.get()),
30       weak_factory_(this) {}
31
32 DomainReliabilityMonitor::DomainReliabilityMonitor(
33     const std::string& upload_reporter_string,
34     scoped_ptr<MockableTime> time)
35     : time_(time.Pass()),
36       upload_reporter_string_(upload_reporter_string),
37       scheduler_params_(
38           DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
39       dispatcher_(time_.get()),
40       weak_factory_(this) {}
41
42 DomainReliabilityMonitor::~DomainReliabilityMonitor() {
43   ClearContexts();
44 }
45
46 void DomainReliabilityMonitor::Init(
47     net::URLRequestContext* url_request_context,
48     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
49   DCHECK(!thread_checker_);
50
51   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
52       new net::TrivialURLRequestContextGetter(url_request_context,
53                                               task_runner);
54   Init(url_request_context_getter);
55 }
56
57 void DomainReliabilityMonitor::Init(
58     scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
59   DCHECK(!thread_checker_);
60
61   DCHECK(url_request_context_getter->GetNetworkTaskRunner()->
62          RunsTasksOnCurrentThread());
63
64   uploader_ = DomainReliabilityUploader::Create(url_request_context_getter);
65   thread_checker_.reset(new base::ThreadChecker());
66 }
67
68 void DomainReliabilityMonitor::AddBakedInConfigs() {
69   DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread());
70   base::Time now = base::Time::Now();
71   for (size_t i = 0; kBakedInJsonConfigs[i]; ++i) {
72     std::string json(kBakedInJsonConfigs[i]);
73     scoped_ptr<const DomainReliabilityConfig> config =
74         DomainReliabilityConfig::FromJSON(json);
75     if (config && config->IsExpired(now)) {
76       LOG(WARNING) << "Baked-in Domain Reliability config for "
77                    << config->domain << " is expired.";
78       continue;
79     }
80     AddContext(config.Pass());
81   }
82 }
83
84 void DomainReliabilityMonitor::OnBeforeRedirect(net::URLRequest* request) {
85   DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread());
86   // Record the redirect itself in addition to the final request.
87   OnRequestLegComplete(RequestInfo(*request));
88 }
89
90 void DomainReliabilityMonitor::OnCompleted(net::URLRequest* request,
91                                            bool started) {
92   DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread());
93   if (!started)
94     return;
95   RequestInfo request_info(*request);
96   if (request_info.AccessedNetwork()) {
97     OnRequestLegComplete(request_info);
98     // A request was just using the network, so now is a good time to run any
99     // pending and eligible uploads.
100     dispatcher_.RunEligibleTasks();
101   }
102 }
103
104 void DomainReliabilityMonitor::ClearBrowsingData(
105    DomainReliabilityClearMode mode) {
106   DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread());
107
108   switch (mode) {
109     case CLEAR_BEACONS: {
110       ContextMap::const_iterator it;
111       for (it = contexts_.begin(); it != contexts_.end(); ++it)
112         it->second->ClearBeacons();
113       break;
114     };
115     case CLEAR_CONTEXTS:
116       ClearContexts();
117       break;
118     case MAX_CLEAR_MODE:
119       NOTREACHED();
120   }
121 }
122
123 scoped_ptr<base::Value> DomainReliabilityMonitor::GetWebUIData() const {
124   base::ListValue* contexts_value = new base::ListValue();
125   for (ContextMap::const_iterator it = contexts_.begin();
126        it != contexts_.end();
127        ++it) {
128     contexts_value->Append(it->second->GetWebUIData().release());
129   }
130
131   base::DictionaryValue* data_value = new base::DictionaryValue();
132   data_value->Set("contexts", contexts_value);
133
134   return scoped_ptr<base::Value>(data_value);
135 }
136
137 DomainReliabilityContext* DomainReliabilityMonitor::AddContextForTesting(
138     scoped_ptr<const DomainReliabilityConfig> config) {
139   DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread());
140   return AddContext(config.Pass());
141 }
142
143 DomainReliabilityMonitor::RequestInfo::RequestInfo() {}
144
145 DomainReliabilityMonitor::RequestInfo::RequestInfo(
146     const net::URLRequest& request)
147     : url(request.url()),
148       status(request.status()),
149       response_info(request.response_info()),
150       load_flags(request.load_flags()),
151       is_upload(DomainReliabilityUploader::URLRequestIsUpload(request)) {
152   request.GetLoadTimingInfo(&load_timing_info);
153 }
154
155 DomainReliabilityMonitor::RequestInfo::~RequestInfo() {}
156
157 bool DomainReliabilityMonitor::RequestInfo::AccessedNetwork() const {
158   return status.status() != net::URLRequestStatus::CANCELED &&
159      response_info.network_accessed;
160 }
161
162 DomainReliabilityContext* DomainReliabilityMonitor::AddContext(
163     scoped_ptr<const DomainReliabilityConfig> config) {
164   DCHECK(config);
165   DCHECK(config->IsValid());
166
167   // Grab a copy of the domain before transferring ownership of |config|.
168   std::string domain = config->domain;
169
170   DomainReliabilityContext* context =
171       new DomainReliabilityContext(time_.get(),
172                                    scheduler_params_,
173                                    upload_reporter_string_,
174                                    &dispatcher_,
175                                    uploader_.get(),
176                                    config.Pass());
177
178   std::pair<ContextMap::iterator, bool> map_it =
179       contexts_.insert(make_pair(domain, context));
180   // Make sure the domain wasn't already in the map.
181   DCHECK(map_it.second);
182
183   return map_it.first->second;
184 }
185
186 void DomainReliabilityMonitor::ClearContexts() {
187   STLDeleteContainerPairSecondPointers(
188       contexts_.begin(), contexts_.end());
189   contexts_.clear();
190 }
191
192 void DomainReliabilityMonitor::OnRequestLegComplete(
193     const RequestInfo& request) {
194   int response_code;
195   if (request.response_info.headers)
196     response_code = request.response_info.headers->response_code();
197   else
198     response_code = -1;
199   std::string beacon_status;
200
201   int error_code = net::OK;
202   if (request.status.status() == net::URLRequestStatus::FAILED)
203     error_code = request.status.error();
204
205   DomainReliabilityContext* context = GetContextForHost(request.url.host());
206
207   // Ignore requests where:
208   // 1. There is no context for the request host.
209   // 2. The request did not access the network.
210   // 3. The request is not supposed to send cookies (to avoid associating the
211   //    request with any potentially unique data in the config).
212   // 4. The request was itself a Domain Reliability upload (to avoid loops).
213   // 5. There is no defined beacon status for the error or HTTP response code
214   //    (to avoid leaking network-local errors).
215   if (!context ||
216       !request.AccessedNetwork() ||
217       (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) ||
218       request.is_upload ||
219       !GetDomainReliabilityBeaconStatus(
220           error_code, response_code, &beacon_status)) {
221     return;
222   }
223
224   DomainReliabilityBeacon beacon;
225   beacon.status = beacon_status;
226   beacon.chrome_error = error_code;
227   if (!request.response_info.was_fetched_via_proxy)
228     beacon.server_ip = request.response_info.socket_address.host();
229   else
230     beacon.server_ip.clear();
231   beacon.protocol = GetDomainReliabilityProtocol(
232       request.response_info.connection_info,
233       request.response_info.ssl_info.is_valid());
234   beacon.http_response_code = response_code;
235   beacon.start_time = request.load_timing_info.request_start;
236   beacon.elapsed = time_->NowTicks() - beacon.start_time;
237   context->OnBeacon(request.url, beacon);
238 }
239
240 // TODO(ttuttle): Keep a separate wildcard_contexts_ map to avoid having to
241 // prepend '*.' to domains.
242 DomainReliabilityContext* DomainReliabilityMonitor::GetContextForHost(
243     const std::string& host) const {
244   ContextMap::const_iterator context_it;
245
246   context_it = contexts_.find(host);
247   if (context_it != contexts_.end())
248     return context_it->second;
249
250   std::string host_with_asterisk = "*." + host;
251   context_it = contexts_.find(host_with_asterisk);
252   if (context_it != contexts_.end())
253     return context_it->second;
254
255   size_t dot_pos = host.find('.');
256   if (dot_pos == std::string::npos)
257     return NULL;
258
259   // TODO(ttuttle): Make sure parent is not in PSL before using.
260
261   std::string parent_with_asterisk = "*." + host.substr(dot_pos + 1);
262   context_it = contexts_.find(parent_with_asterisk);
263   if (context_it != contexts_.end())
264     return context_it->second;
265
266   return NULL;
267 }
268
269 base::WeakPtr<DomainReliabilityMonitor>
270 DomainReliabilityMonitor::MakeWeakPtr() {
271   return weak_factory_.GetWeakPtr();
272 }
273
274 }  // namespace domain_reliability