fc25dd77c914a0df96a58534ec03328cd3fbbae0
[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       was_cleared_(false),
31       cleared_mode_(MAX_CLEAR_MODE),
32       weak_factory_(this) {}
33
34 DomainReliabilityMonitor::DomainReliabilityMonitor(
35     const std::string& upload_reporter_string,
36     scoped_ptr<MockableTime> time)
37     : time_(time.Pass()),
38       upload_reporter_string_(upload_reporter_string),
39       scheduler_params_(
40           DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
41       dispatcher_(time_.get()),
42       was_cleared_(false),
43       cleared_mode_(MAX_CLEAR_MODE),
44       weak_factory_(this) {}
45
46 DomainReliabilityMonitor::~DomainReliabilityMonitor() {
47   ClearContexts();
48 }
49
50 void DomainReliabilityMonitor::Init(
51     net::URLRequestContext* url_request_context,
52     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
53   DCHECK(!thread_checker_);
54
55   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
56       new net::TrivialURLRequestContextGetter(url_request_context,
57                                               task_runner);
58   Init(url_request_context_getter);
59 }
60
61 void DomainReliabilityMonitor::Init(
62     scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
63   DCHECK(!thread_checker_);
64
65   DCHECK(url_request_context_getter->GetNetworkTaskRunner()->
66          RunsTasksOnCurrentThread());
67
68   uploader_ = DomainReliabilityUploader::Create(url_request_context_getter);
69   thread_checker_.reset(new base::ThreadChecker());
70 }
71
72 void DomainReliabilityMonitor::AddBakedInConfigs() {
73   DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread());
74   base::Time now = base::Time::Now();
75   for (size_t i = 0; kBakedInJsonConfigs[i]; ++i) {
76     std::string json(kBakedInJsonConfigs[i]);
77     scoped_ptr<const DomainReliabilityConfig> config =
78         DomainReliabilityConfig::FromJSON(json);
79     if (config && config->IsExpired(now)) {
80       LOG(WARNING) << "Baked-in Domain Reliability config for "
81                    << config->domain << " is expired.";
82       continue;
83     }
84     AddContext(config.Pass());
85   }
86 }
87
88 void DomainReliabilityMonitor::OnBeforeRedirect(net::URLRequest* request) {
89   DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread());
90   // Record the redirect itself in addition to the final request.
91   OnRequestLegComplete(RequestInfo(*request));
92 }
93
94 void DomainReliabilityMonitor::OnCompleted(net::URLRequest* request,
95                                            bool started) {
96   DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread());
97   if (!started)
98     return;
99   RequestInfo request_info(*request);
100   if (request_info.AccessedNetwork()) {
101     OnRequestLegComplete(request_info);
102     // A request was just using the network, so now is a good time to run any
103     // pending and eligible uploads.
104     dispatcher_.RunEligibleTasks();
105   }
106 }
107
108 void DomainReliabilityMonitor::ClearBrowsingData(
109    DomainReliabilityClearMode mode) {
110   DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread());
111
112   was_cleared_ = true;
113   cleared_mode_ = mode;
114
115   switch (mode) {
116     case CLEAR_BEACONS: {
117       ContextMap::const_iterator it;
118       for (it = contexts_.begin(); it != contexts_.end(); ++it)
119         it->second->ClearBeacons();
120       break;
121     };
122     case CLEAR_CONTEXTS:
123       ClearContexts();
124       break;
125     case MAX_CLEAR_MODE:
126       NOTREACHED();
127   }
128 }
129
130 DomainReliabilityContext* DomainReliabilityMonitor::AddContextForTesting(
131     scoped_ptr<const DomainReliabilityConfig> config) {
132   DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread());
133   return AddContext(config.Pass());
134 }
135
136 DomainReliabilityMonitor::RequestInfo::RequestInfo() {}
137
138 DomainReliabilityMonitor::RequestInfo::RequestInfo(
139     const net::URLRequest& request)
140     : url(request.url()),
141       status(request.status()),
142       response_info(request.response_info()),
143       load_flags(request.load_flags()),
144       is_upload(DomainReliabilityUploader::URLRequestIsUpload(request)) {
145   request.GetLoadTimingInfo(&load_timing_info);
146 }
147
148 DomainReliabilityMonitor::RequestInfo::~RequestInfo() {}
149
150 bool DomainReliabilityMonitor::RequestInfo::AccessedNetwork() const {
151   return status.status() != net::URLRequestStatus::CANCELED &&
152      response_info.network_accessed;
153 }
154
155 DomainReliabilityContext* DomainReliabilityMonitor::AddContext(
156     scoped_ptr<const DomainReliabilityConfig> config) {
157   DCHECK(config);
158   DCHECK(config->IsValid());
159
160   // Grab a copy of the domain before transferring ownership of |config|.
161   std::string domain = config->domain;
162
163   DomainReliabilityContext* context =
164       new DomainReliabilityContext(time_.get(),
165                                    scheduler_params_,
166                                    upload_reporter_string_,
167                                    &dispatcher_,
168                                    uploader_.get(),
169                                    config.Pass());
170
171   std::pair<ContextMap::iterator, bool> map_it =
172       contexts_.insert(make_pair(domain, context));
173   // Make sure the domain wasn't already in the map.
174   DCHECK(map_it.second);
175
176   return map_it.first->second;
177 }
178
179 void DomainReliabilityMonitor::ClearContexts() {
180   STLDeleteContainerPairSecondPointers(
181       contexts_.begin(), contexts_.end());
182   contexts_.clear();
183 }
184
185 void DomainReliabilityMonitor::OnRequestLegComplete(
186     const RequestInfo& request) {
187   int response_code;
188   if (request.response_info.headers)
189     response_code = request.response_info.headers->response_code();
190   else
191     response_code = -1;
192   ContextMap::iterator context_it;
193   std::string beacon_status;
194
195   int error_code = net::OK;
196   if (request.status.status() == net::URLRequestStatus::FAILED)
197     error_code = request.status.error();
198
199   // Ignore requests where:
200   // 1. There is no context for the request host.
201   // 2. The request did not access the network.
202   // 3. The request is not supposed to send cookies (to avoid associating the
203   //    request with any potentially unique data in the config).
204   // 4. The request was itself a Domain Reliability upload (to avoid loops).
205   // 5. There is no defined beacon status for the error or HTTP response code
206   //    (to avoid leaking network-local errors).
207   if ((context_it = contexts_.find(request.url.host())) == contexts_.end() ||
208       !request.AccessedNetwork() ||
209       (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) ||
210       request.is_upload ||
211       !GetDomainReliabilityBeaconStatus(
212           error_code, response_code, &beacon_status)) {
213     return;
214   }
215
216   DomainReliabilityBeacon beacon;
217   beacon.status = beacon_status;
218   beacon.chrome_error = error_code;
219   if (!request.response_info.was_fetched_via_proxy)
220     beacon.server_ip = request.response_info.socket_address.host();
221   else
222     beacon.server_ip.clear();
223   beacon.http_response_code = response_code;
224   beacon.start_time = request.load_timing_info.request_start;
225   beacon.elapsed = time_->NowTicks() - beacon.start_time;
226   context_it->second->OnBeacon(request.url, beacon);
227 }
228
229 base::WeakPtr<DomainReliabilityMonitor>
230 DomainReliabilityMonitor::MakeWeakPtr() {
231   return weak_factory_.GetWeakPtr();
232 }
233
234 }  // namespace domain_reliability