Update To 11.40.268.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/single_thread_task_runner.h"
10 #include "base/task_runner.h"
11 #include "base/time/time.h"
12 #include "components/domain_reliability/baked_in_configs.h"
13 #include "net/base/load_flags.h"
14 #include "net/http/http_response_headers.h"
15 #include "net/url_request/url_request.h"
16 #include "net/url_request/url_request_context.h"
17 #include "net/url_request/url_request_context_getter.h"
18
19 namespace domain_reliability {
20
21 DomainReliabilityMonitor::DomainReliabilityMonitor(
22     const std::string& upload_reporter_string,
23     scoped_refptr<base::SingleThreadTaskRunner> pref_thread,
24     scoped_refptr<base::SingleThreadTaskRunner> network_thread)
25     : time_(new ActualTime()),
26       upload_reporter_string_(upload_reporter_string),
27       scheduler_params_(
28           DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
29       dispatcher_(time_.get()),
30       pref_task_runner_(pref_thread),
31       network_task_runner_(network_thread),
32       moved_to_network_thread_(false),
33       discard_uploads_set_(false),
34       weak_factory_(this) {
35   DCHECK(OnPrefThread());
36   net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
37 }
38
39 DomainReliabilityMonitor::DomainReliabilityMonitor(
40     const std::string& upload_reporter_string,
41     scoped_refptr<base::SingleThreadTaskRunner> pref_thread,
42     scoped_refptr<base::SingleThreadTaskRunner> network_thread,
43     scoped_ptr<MockableTime> time)
44     : time_(time.Pass()),
45       upload_reporter_string_(upload_reporter_string),
46       scheduler_params_(
47           DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
48       dispatcher_(time_.get()),
49       pref_task_runner_(pref_thread),
50       network_task_runner_(network_thread),
51       moved_to_network_thread_(false),
52       discard_uploads_set_(false),
53       weak_factory_(this) {
54   DCHECK(OnPrefThread());
55   net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
56 }
57
58 DomainReliabilityMonitor::~DomainReliabilityMonitor() {
59   if (moved_to_network_thread_)
60     DCHECK(OnNetworkThread());
61   else
62     DCHECK(OnPrefThread());
63
64   ClearContexts();
65   net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
66 }
67
68 void DomainReliabilityMonitor::MoveToNetworkThread() {
69   DCHECK(OnPrefThread());
70   DCHECK(!moved_to_network_thread_);
71
72   moved_to_network_thread_ = true;
73 }
74
75 void DomainReliabilityMonitor::InitURLRequestContext(
76     net::URLRequestContext* url_request_context) {
77   DCHECK(OnNetworkThread());
78   DCHECK(moved_to_network_thread_);
79
80   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
81       new net::TrivialURLRequestContextGetter(url_request_context,
82                                               network_task_runner_);
83   InitURLRequestContext(url_request_context_getter);
84 }
85
86 void DomainReliabilityMonitor::InitURLRequestContext(
87     scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
88   DCHECK(OnNetworkThread());
89   DCHECK(moved_to_network_thread_);
90
91   // Make sure the URLRequestContext actually lives on what was declared to be
92   // the network thread.
93   DCHECK(url_request_context_getter->GetNetworkTaskRunner()->
94          RunsTasksOnCurrentThread());
95
96   uploader_ = DomainReliabilityUploader::Create(url_request_context_getter);
97 }
98
99 void DomainReliabilityMonitor::AddBakedInConfigs() {
100   DCHECK(OnNetworkThread());
101   DCHECK(moved_to_network_thread_);
102
103   base::Time now = base::Time::Now();
104   for (size_t i = 0; kBakedInJsonConfigs[i]; ++i) {
105     std::string json(kBakedInJsonConfigs[i]);
106     scoped_ptr<const DomainReliabilityConfig> config =
107         DomainReliabilityConfig::FromJSON(json);
108     if (config && config->IsExpired(now)) {
109       LOG(WARNING) << "Baked-in Domain Reliability config for "
110                    << config->domain << " is expired.";
111       continue;
112     }
113     AddContext(config.Pass());
114   }
115 }
116
117 void DomainReliabilityMonitor::SetDiscardUploads(bool discard_uploads) {
118   DCHECK(OnNetworkThread());
119   DCHECK(moved_to_network_thread_);
120   DCHECK(uploader_);
121
122   uploader_->set_discard_uploads(discard_uploads);
123   discard_uploads_set_ = true;
124 }
125
126 void DomainReliabilityMonitor::OnBeforeRedirect(net::URLRequest* request) {
127   DCHECK(OnNetworkThread());
128   DCHECK(discard_uploads_set_);
129
130   // Record the redirect itself in addition to the final request.
131   OnRequestLegComplete(RequestInfo(*request));
132 }
133
134 void DomainReliabilityMonitor::OnCompleted(net::URLRequest* request,
135                                            bool started) {
136   DCHECK(OnNetworkThread());
137   DCHECK(discard_uploads_set_);
138
139   if (!started)
140     return;
141   RequestInfo request_info(*request);
142   if (request_info.AccessedNetwork()) {
143     OnRequestLegComplete(request_info);
144     // A request was just using the network, so now is a good time to run any
145     // pending and eligible uploads.
146     dispatcher_.RunEligibleTasks();
147   }
148 }
149
150 void DomainReliabilityMonitor::OnNetworkChanged(
151     net::NetworkChangeNotifier::ConnectionType type) {
152   last_network_change_time_ = time_->NowTicks();
153 }
154
155 void DomainReliabilityMonitor::ClearBrowsingData(
156    DomainReliabilityClearMode mode) {
157   DCHECK(OnNetworkThread());
158
159   switch (mode) {
160     case CLEAR_BEACONS: {
161       ContextMap::const_iterator it;
162       for (it = contexts_.begin(); it != contexts_.end(); ++it)
163         it->second->ClearBeacons();
164       break;
165     };
166     case CLEAR_CONTEXTS:
167       ClearContexts();
168       break;
169     case MAX_CLEAR_MODE:
170       NOTREACHED();
171   }
172 }
173
174 scoped_ptr<base::Value> DomainReliabilityMonitor::GetWebUIData() const {
175   DCHECK(OnNetworkThread());
176
177   base::ListValue* contexts_value = new base::ListValue();
178   for (ContextMap::const_iterator it = contexts_.begin();
179        it != contexts_.end();
180        ++it) {
181     contexts_value->Append(it->second->GetWebUIData().release());
182   }
183
184   base::DictionaryValue* data_value = new base::DictionaryValue();
185   data_value->Set("contexts", contexts_value);
186
187   return scoped_ptr<base::Value>(data_value);
188 }
189
190 DomainReliabilityContext* DomainReliabilityMonitor::AddContextForTesting(
191     scoped_ptr<const DomainReliabilityConfig> config) {
192   DCHECK(OnNetworkThread());
193
194   return AddContext(config.Pass());
195 }
196
197 DomainReliabilityMonitor::RequestInfo::RequestInfo() {}
198
199 DomainReliabilityMonitor::RequestInfo::RequestInfo(
200     const net::URLRequest& request)
201     : url(request.url()),
202       status(request.status()),
203       response_info(request.response_info()),
204       load_flags(request.load_flags()),
205       is_upload(DomainReliabilityUploader::URLRequestIsUpload(request)) {
206   request.GetLoadTimingInfo(&load_timing_info);
207 }
208
209 DomainReliabilityMonitor::RequestInfo::~RequestInfo() {}
210
211 bool DomainReliabilityMonitor::RequestInfo::AccessedNetwork() const {
212   return status.status() != net::URLRequestStatus::CANCELED &&
213      response_info.network_accessed;
214 }
215
216 DomainReliabilityContext* DomainReliabilityMonitor::AddContext(
217     scoped_ptr<const DomainReliabilityConfig> config) {
218   DCHECK(OnNetworkThread());
219   DCHECK(config);
220   DCHECK(config->IsValid());
221
222   // Grab a copy of the domain before transferring ownership of |config|.
223   std::string domain = config->domain;
224
225   DomainReliabilityContext* context =
226       new DomainReliabilityContext(time_.get(),
227                                    scheduler_params_,
228                                    upload_reporter_string_,
229                                    &last_network_change_time_,
230                                    &dispatcher_,
231                                    uploader_.get(),
232                                    config.Pass());
233
234   std::pair<ContextMap::iterator, bool> map_it =
235       contexts_.insert(make_pair(domain, context));
236   // Make sure the domain wasn't already in the map.
237   DCHECK(map_it.second);
238
239   return map_it.first->second;
240 }
241
242 void DomainReliabilityMonitor::ClearContexts() {
243   STLDeleteContainerPairSecondPointers(
244       contexts_.begin(), contexts_.end());
245   contexts_.clear();
246 }
247
248 void DomainReliabilityMonitor::OnRequestLegComplete(
249     const RequestInfo& request) {
250   // Check these again because unit tests call this directly.
251   DCHECK(OnNetworkThread());
252   DCHECK(discard_uploads_set_);
253
254   int response_code;
255   if (request.response_info.headers.get())
256     response_code = request.response_info.headers->response_code();
257   else
258     response_code = -1;
259   std::string beacon_status;
260
261   int error_code = net::OK;
262   if (request.status.status() == net::URLRequestStatus::FAILED)
263     error_code = request.status.error();
264
265   DomainReliabilityContext* context = GetContextForHost(request.url.host());
266
267   // Ignore requests where:
268   // 1. There is no context for the request host.
269   // 2. The request did not access the network.
270   // 3. The request is not supposed to send cookies (to avoid associating the
271   //    request with any potentially unique data in the config).
272   // 4. The request was itself a Domain Reliability upload (to avoid loops).
273   // 5. There is no defined beacon status for the error or HTTP response code
274   //    (to avoid leaking network-local errors).
275   if (!context ||
276       !request.AccessedNetwork() ||
277       (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) ||
278       request.is_upload ||
279       !GetDomainReliabilityBeaconStatus(
280           error_code, response_code, &beacon_status)) {
281     return;
282   }
283
284   DomainReliabilityBeacon beacon;
285   beacon.status = beacon_status;
286   beacon.chrome_error = error_code;
287   if (!request.response_info.was_fetched_via_proxy)
288     beacon.server_ip = request.response_info.socket_address.host();
289   else
290     beacon.server_ip.clear();
291   beacon.protocol = GetDomainReliabilityProtocol(
292       request.response_info.connection_info,
293       request.response_info.ssl_info.is_valid());
294   beacon.http_response_code = response_code;
295   beacon.start_time = request.load_timing_info.request_start;
296   beacon.elapsed = time_->NowTicks() - beacon.start_time;
297   beacon.domain = request.url.host();
298   context->OnBeacon(request.url, beacon);
299 }
300
301 // TODO(ttuttle): Keep a separate wildcard_contexts_ map to avoid having to
302 // prepend '*.' to domains.
303 DomainReliabilityContext* DomainReliabilityMonitor::GetContextForHost(
304     const std::string& host) const {
305   DCHECK(OnNetworkThread());
306
307   ContextMap::const_iterator context_it;
308
309   context_it = contexts_.find(host);
310   if (context_it != contexts_.end())
311     return context_it->second;
312
313   std::string host_with_asterisk = "*." + host;
314   context_it = contexts_.find(host_with_asterisk);
315   if (context_it != contexts_.end())
316     return context_it->second;
317
318   size_t dot_pos = host.find('.');
319   if (dot_pos == std::string::npos)
320     return NULL;
321
322   // TODO(ttuttle): Make sure parent is not in PSL before using.
323
324   std::string parent_with_asterisk = "*." + host.substr(dot_pos + 1);
325   context_it = contexts_.find(parent_with_asterisk);
326   if (context_it != contexts_.end())
327     return context_it->second;
328
329   return NULL;
330 }
331
332 base::WeakPtr<DomainReliabilityMonitor>
333 DomainReliabilityMonitor::MakeWeakPtr() {
334   return weak_factory_.GetWeakPtr();
335 }
336
337 }  // namespace domain_reliability