Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / net / chrome_network_delegate.cc
1 // Copyright (c) 2012 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 "chrome/browser/net/chrome_network_delegate.h"
6
7 #include <stdlib.h>
8
9 #include <vector>
10
11 #include "base/base_paths.h"
12 #include "base/debug/trace_event.h"
13 #include "base/logging.h"
14 #include "base/metrics/histogram.h"
15 #include "base/path_service.h"
16 #include "base/prefs/pref_member.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_split.h"
20 #include "base/time/time.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/content_settings/cookie_settings.h"
23 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
24 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
25 #include "chrome/browser/extensions/api/proxy/proxy_api.h"
26 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
27 #include "chrome/browser/extensions/event_router_forwarder.h"
28 #include "chrome/browser/google/google_util.h"
29 #include "chrome/browser/net/client_hints.h"
30 #include "chrome/browser/net/connect_interceptor.h"
31 #include "chrome/browser/performance_monitor/performance_monitor.h"
32 #include "chrome/browser/profiles/profile_manager.h"
33 #include "chrome/browser/task_manager/task_manager.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/common/url_constants.h"
36 #include "components/data_reduction_proxy/browser/data_reduction_proxy_metrics.h"
37 #include "components/domain_reliability/monitor.h"
38 #include "content/public/browser/browser_thread.h"
39 #include "content/public/browser/render_frame_host.h"
40 #include "content/public/browser/render_view_host.h"
41 #include "content/public/browser/resource_request_info.h"
42 #include "extensions/browser/extension_system.h"
43 #include "extensions/browser/info_map.h"
44 #include "extensions/browser/process_manager.h"
45 #include "extensions/common/constants.h"
46 #include "net/base/host_port_pair.h"
47 #include "net/base/net_errors.h"
48 #include "net/base/net_log.h"
49 #include "net/cookies/canonical_cookie.h"
50 #include "net/cookies/cookie_options.h"
51 #include "net/http/http_request_headers.h"
52 #include "net/http/http_response_headers.h"
53 #include "net/socket_stream/socket_stream.h"
54 #include "net/url_request/url_request.h"
55
56 #if defined(OS_CHROMEOS)
57 #include "base/command_line.h"
58 #include "base/sys_info.h"
59 #include "chrome/common/chrome_switches.h"
60 #endif
61
62 #if defined(ENABLE_CONFIGURATION_POLICY)
63 #include "components/policy/core/browser/url_blacklist_manager.h"
64 #endif
65
66 #if defined(OS_ANDROID)
67 #include "chrome/browser/io_thread.h"
68 #include "components/precache/content/precache_manager.h"
69 #include "components/precache/content/precache_manager_factory.h"
70 #endif
71
72 using content::BrowserThread;
73 using content::RenderViewHost;
74 using content::ResourceRequestInfo;
75
76 // By default we don't allow access to all file:// urls on ChromeOS and
77 // Android.
78 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
79 bool ChromeNetworkDelegate::g_allow_file_access_ = false;
80 #else
81 bool ChromeNetworkDelegate::g_allow_file_access_ = true;
82 #endif
83
84 // This remains false unless the --disable-extensions-http-throttling
85 // flag is passed to the browser.
86 bool ChromeNetworkDelegate::g_never_throttle_requests_ = false;
87
88 namespace {
89
90 const char kDNTHeader[] = "DNT";
91
92 // If the |request| failed due to problems with a proxy, forward the error to
93 // the proxy extension API.
94 void ForwardProxyErrors(net::URLRequest* request,
95                         extensions::EventRouterForwarder* event_router,
96                         void* profile) {
97   if (request->status().status() == net::URLRequestStatus::FAILED) {
98     switch (request->status().error()) {
99       case net::ERR_PROXY_AUTH_UNSUPPORTED:
100       case net::ERR_PROXY_CONNECTION_FAILED:
101       case net::ERR_TUNNEL_CONNECTION_FAILED:
102         extensions::ProxyEventRouter::GetInstance()->OnProxyError(
103             event_router, profile, request->status().error());
104     }
105   }
106 }
107
108 // Returns whether a URL parameter, |first_parameter| (e.g. foo=bar), has the
109 // same key as the the |second_parameter| (e.g. foo=baz). Both parameters
110 // must be in key=value form.
111 bool HasSameParameterKey(const std::string& first_parameter,
112                          const std::string& second_parameter) {
113   DCHECK(second_parameter.find("=") != std::string::npos);
114   // Prefix for "foo=bar" is "foo=".
115   std::string parameter_prefix = second_parameter.substr(
116       0, second_parameter.find("=") + 1);
117   return StartsWithASCII(first_parameter, parameter_prefix, false);
118 }
119
120 // Examines the query string containing parameters and adds the necessary ones
121 // so that SafeSearch is active. |query| is the string to examine and the
122 // return value is the |query| string modified such that SafeSearch is active.
123 std::string AddSafeSearchParameters(const std::string& query) {
124   std::vector<std::string> new_parameters;
125   std::string safe_parameter = chrome::kSafeSearchSafeParameter;
126   std::string ssui_parameter = chrome::kSafeSearchSsuiParameter;
127
128   std::vector<std::string> parameters;
129   base::SplitString(query, '&', &parameters);
130
131   std::vector<std::string>::iterator it;
132   for (it = parameters.begin(); it < parameters.end(); ++it) {
133     if (!HasSameParameterKey(*it, safe_parameter) &&
134         !HasSameParameterKey(*it, ssui_parameter)) {
135       new_parameters.push_back(*it);
136     }
137   }
138
139   new_parameters.push_back(safe_parameter);
140   new_parameters.push_back(ssui_parameter);
141   return JoinString(new_parameters, '&');
142 }
143
144 // If |request| is a request to Google Web Search the function
145 // enforces that the SafeSearch query parameters are set to active.
146 // Sets the query part of |new_url| with the new value of the parameters.
147 void ForceGoogleSafeSearch(net::URLRequest* request,
148                            GURL* new_url) {
149   if (!google_util::IsGoogleSearchUrl(request->url()) &&
150       !google_util::IsGoogleHomePageUrl(request->url()))
151     return;
152
153   std::string query = request->url().query();
154   std::string new_query = AddSafeSearchParameters(query);
155   if (query == new_query)
156     return;
157
158   GURL::Replacements replacements;
159   replacements.SetQueryStr(new_query);
160   *new_url = request->url().ReplaceComponents(replacements);
161 }
162
163 // Gets called when the extensions finish work on the URL. If the extensions
164 // did not do a redirect (so |new_url| is empty) then we enforce the
165 // SafeSearch parameters. Otherwise we will get called again after the
166 // redirect and we enforce SafeSearch then.
167 void ForceGoogleSafeSearchCallbackWrapper(
168     const net::CompletionCallback& callback,
169     net::URLRequest* request,
170     GURL* new_url,
171     int rv) {
172   if (rv == net::OK && new_url->is_empty())
173     ForceGoogleSafeSearch(request, new_url);
174   callback.Run(rv);
175 }
176
177 enum RequestStatus { REQUEST_STARTED, REQUEST_DONE };
178
179 // Notifies the extensions::ProcessManager that a request has started or stopped
180 // for a particular RenderFrame.
181 void NotifyEPMRequestStatus(RequestStatus status,
182                             void* profile_id,
183                             int process_id,
184                             int render_frame_id) {
185   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
186   Profile* profile = reinterpret_cast<Profile*>(profile_id);
187   if (!g_browser_process->profile_manager()->IsValidProfile(profile))
188     return;
189
190   extensions::ProcessManager* process_manager =
191       extensions::ExtensionSystem::Get(profile)->process_manager();
192   // This may be NULL in unit tests.
193   if (!process_manager)
194     return;
195
196   // Will be NULL if the request was not issued on behalf of a renderer (e.g. a
197   // system-level request).
198   content::RenderFrameHost* render_frame_host =
199       content::RenderFrameHost::FromID(process_id, render_frame_id);
200   if (render_frame_host) {
201     if (status == REQUEST_STARTED) {
202       process_manager->OnNetworkRequestStarted(render_frame_host);
203     } else if (status == REQUEST_DONE) {
204       process_manager->OnNetworkRequestDone(render_frame_host);
205     } else {
206       NOTREACHED();
207     }
208   }
209 }
210
211 void ForwardRequestStatus(
212     RequestStatus status, net::URLRequest* request, void* profile_id) {
213   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
214   if (!info)
215     return;
216
217   int process_id, render_frame_id;
218   if (info->GetAssociatedRenderFrame(&process_id, &render_frame_id)) {
219     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
220         base::Bind(&NotifyEPMRequestStatus,
221                    status, profile_id, process_id, render_frame_id));
222   }
223 }
224
225 void UpdateContentLengthPrefs(
226     int received_content_length,
227     int original_content_length,
228     data_reduction_proxy::DataReductionProxyRequestType request_type,
229     Profile* profile) {
230   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
231   DCHECK_GE(received_content_length, 0);
232   DCHECK_GE(original_content_length, 0);
233
234   // Can be NULL in a unit test.
235   if (!g_browser_process)
236     return;
237
238   PrefService* prefs = g_browser_process->local_state();
239   if (!prefs)
240     return;
241
242   // Ignore off-the-record data.
243   if (!g_browser_process->profile_manager()->IsValidProfile(profile) ||
244       profile->IsOffTheRecord()) {
245     return;
246   }
247 #if defined(OS_ANDROID)
248   // If Android ever goes multi profile, the profile should be passed so that
249   // the browser preference will be taken.
250   bool with_data_reduction_proxy_enabled =
251       ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
252           data_reduction_proxy::prefs::kDataReductionProxyEnabled);
253 #else
254   bool with_data_reduction_proxy_enabled = false;
255 #endif
256
257   data_reduction_proxy::UpdateContentLengthPrefs(received_content_length,
258                                          original_content_length,
259                                          with_data_reduction_proxy_enabled,
260                                          request_type, prefs);
261 }
262
263 void StoreAccumulatedContentLength(
264     int received_content_length,
265     int original_content_length,
266     data_reduction_proxy::DataReductionProxyRequestType request_type,
267     Profile* profile) {
268   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
269       base::Bind(&UpdateContentLengthPrefs,
270                  received_content_length, original_content_length,
271                  request_type, profile));
272 }
273
274 void RecordContentLengthHistograms(
275     int64 received_content_length,
276     int64 original_content_length,
277     const base::TimeDelta& freshness_lifetime) {
278   // Add the current resource to these histograms only when a valid
279   // X-Original-Content-Length header is present.
280   if (original_content_length >= 0) {
281     UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthWithValidOCL",
282                          received_content_length);
283     UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLengthWithValidOCL",
284                          original_content_length);
285     UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifferenceWithValidOCL",
286                          original_content_length - received_content_length);
287   } else {
288     // Presume the original content length is the same as the received content
289     // length if the X-Original-Content-Header is not present.
290     original_content_length = received_content_length;
291   }
292   UMA_HISTOGRAM_COUNTS("Net.HttpContentLength", received_content_length);
293   UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLength",
294                        original_content_length);
295   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifference",
296                        original_content_length - received_content_length);
297   UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpContentFreshnessLifetime",
298                               freshness_lifetime.InSeconds(),
299                               base::TimeDelta::FromHours(1).InSeconds(),
300                               base::TimeDelta::FromDays(30).InSeconds(),
301                               100);
302   if (freshness_lifetime.InSeconds() <= 0)
303     return;
304   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable",
305                        received_content_length);
306   if (freshness_lifetime.InHours() < 4)
307     return;
308   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable4Hours",
309                        received_content_length);
310
311   if (freshness_lifetime.InHours() < 24)
312     return;
313   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable24Hours",
314                        received_content_length);
315 }
316
317 #if defined(OS_ANDROID)
318 void RecordPrecacheStatsOnUIThread(const GURL& url,
319                                    const base::Time& fetch_time, int64 size,
320                                    bool was_cached, void* profile_id) {
321   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
322
323   Profile* profile = reinterpret_cast<Profile*>(profile_id);
324   if (!g_browser_process->profile_manager()->IsValidProfile(profile)) {
325     return;
326   }
327
328   precache::PrecacheManager* precache_manager =
329       precache::PrecacheManagerFactory::GetForBrowserContext(profile);
330   if (!precache_manager) {
331     // This could be NULL if the profile is off the record.
332     return;
333   }
334
335   precache_manager->RecordStatsForFetch(url, fetch_time, size, was_cached);
336 }
337
338 void RecordIOThreadToRequestStartOnUIThread(
339     const base::TimeTicks& request_start) {
340   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
341   base::TimeDelta request_lag = request_start -
342       g_browser_process->io_thread()->creation_time();
343   UMA_HISTOGRAM_TIMES("Net.IOThreadCreationToHTTPRequestStart", request_lag);
344 }
345 #endif  // defined(OS_ANDROID)
346
347 }  // namespace
348
349 ChromeNetworkDelegate::ChromeNetworkDelegate(
350     extensions::EventRouterForwarder* event_router,
351     BooleanPrefMember* enable_referrers)
352     : event_router_(event_router),
353       profile_(NULL),
354       enable_referrers_(enable_referrers),
355       enable_do_not_track_(NULL),
356       force_google_safe_search_(NULL),
357       url_blacklist_manager_(NULL),
358       domain_reliability_monitor_(NULL),
359       received_content_length_(0),
360       original_content_length_(0),
361       first_request_(true) {
362   DCHECK(event_router);
363   DCHECK(enable_referrers);
364 }
365
366 ChromeNetworkDelegate::~ChromeNetworkDelegate() {}
367
368 void ChromeNetworkDelegate::set_extension_info_map(
369     extensions::InfoMap* extension_info_map) {
370   extension_info_map_ = extension_info_map;
371 }
372
373 void ChromeNetworkDelegate::set_cookie_settings(
374     CookieSettings* cookie_settings) {
375   cookie_settings_ = cookie_settings;
376 }
377
378 void ChromeNetworkDelegate::set_predictor(
379     chrome_browser_net::Predictor* predictor) {
380   connect_interceptor_.reset(
381       new chrome_browser_net::ConnectInterceptor(predictor));
382 }
383
384 void ChromeNetworkDelegate::SetEnableClientHints() {
385   client_hints_.reset(new ClientHints());
386   client_hints_->Init();
387 }
388
389 // static
390 void ChromeNetworkDelegate::NeverThrottleRequests() {
391   g_never_throttle_requests_ = true;
392 }
393
394 // static
395 void ChromeNetworkDelegate::InitializePrefsOnUIThread(
396     BooleanPrefMember* enable_referrers,
397     BooleanPrefMember* enable_do_not_track,
398     BooleanPrefMember* force_google_safe_search,
399     PrefService* pref_service) {
400   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
401   enable_referrers->Init(prefs::kEnableReferrers, pref_service);
402   enable_referrers->MoveToThread(
403       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
404   if (enable_do_not_track) {
405     enable_do_not_track->Init(prefs::kEnableDoNotTrack, pref_service);
406     enable_do_not_track->MoveToThread(
407         BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
408   }
409   if (force_google_safe_search) {
410     force_google_safe_search->Init(prefs::kForceSafeSearch, pref_service);
411     force_google_safe_search->MoveToThread(
412         BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
413   }
414 }
415
416 // static
417 void ChromeNetworkDelegate::AllowAccessToAllFiles() {
418   g_allow_file_access_ = true;
419 }
420
421 // static
422 base::Value* ChromeNetworkDelegate::HistoricNetworkStatsInfoToValue() {
423   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
424   PrefService* prefs = g_browser_process->local_state();
425   int64 total_received = prefs->GetInt64(
426       data_reduction_proxy::prefs::kHttpReceivedContentLength);
427   int64 total_original = prefs->GetInt64(
428       data_reduction_proxy::prefs::kHttpOriginalContentLength);
429
430   base::DictionaryValue* dict = new base::DictionaryValue();
431   // Use strings to avoid overflow.  base::Value only supports 32-bit integers.
432   dict->SetString("historic_received_content_length",
433                   base::Int64ToString(total_received));
434   dict->SetString("historic_original_content_length",
435                   base::Int64ToString(total_original));
436   return dict;
437 }
438
439 base::Value* ChromeNetworkDelegate::SessionNetworkStatsInfoToValue() const {
440   base::DictionaryValue* dict = new base::DictionaryValue();
441   // Use strings to avoid overflow.  base::Value only supports 32-bit integers.
442   dict->SetString("session_received_content_length",
443                   base::Int64ToString(received_content_length_));
444   dict->SetString("session_original_content_length",
445                   base::Int64ToString(original_content_length_));
446   return dict;
447 }
448
449 int ChromeNetworkDelegate::OnBeforeURLRequest(
450     net::URLRequest* request,
451     const net::CompletionCallback& callback,
452     GURL* new_url) {
453 #if defined(OS_ANDROID)
454   // This UMA tracks the time to the first user-initiated request start, so
455   // only non-null profiles are considered.
456   if (first_request_ && profile_) {
457     bool record_timing = true;
458 #if defined(DATA_REDUCTION_PROXY_PROBE_URL)
459     record_timing = (request->url() != GURL(DATA_REDUCTION_PROXY_PROBE_URL));
460 #endif
461     if (record_timing) {
462       first_request_ = false;
463       net::LoadTimingInfo timing_info;
464       request->GetLoadTimingInfo(&timing_info);
465       BrowserThread::PostTask(
466           BrowserThread::UI, FROM_HERE,
467           base::Bind(&RecordIOThreadToRequestStartOnUIThread,
468                      timing_info.request_start));
469     }
470   }
471 #endif  // defined(OS_ANDROID)
472
473 #if defined(ENABLE_CONFIGURATION_POLICY)
474   // TODO(joaodasilva): This prevents extensions from seeing URLs that are
475   // blocked. However, an extension might redirect the request to another URL,
476   // which is not blocked.
477   int error = net::ERR_BLOCKED_BY_ADMINISTRATOR;
478   if (url_blacklist_manager_ &&
479       url_blacklist_manager_->IsRequestBlocked(*request, &error)) {
480     // URL access blocked by policy.
481     request->net_log().AddEvent(
482         net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST,
483         net::NetLog::StringCallback("url",
484                                     &request->url().possibly_invalid_spec()));
485     return error;
486   }
487 #endif
488
489   ForwardRequestStatus(REQUEST_STARTED, request, profile_);
490
491   if (!enable_referrers_->GetValue())
492     request->SetReferrer(std::string());
493   if (enable_do_not_track_ && enable_do_not_track_->GetValue())
494     request->SetExtraRequestHeaderByName(kDNTHeader, "1", true /* override */);
495
496   if (client_hints_) {
497     request->SetExtraRequestHeaderByName(
498         ClientHints::kDevicePixelRatioHeader,
499         client_hints_->GetDevicePixelRatioHeader(), true);
500   }
501
502   bool force_safe_search = force_google_safe_search_ &&
503                            force_google_safe_search_->GetValue();
504
505   net::CompletionCallback wrapped_callback = callback;
506   if (force_safe_search) {
507     wrapped_callback = base::Bind(&ForceGoogleSafeSearchCallbackWrapper,
508                                   callback,
509                                   base::Unretained(request),
510                                   base::Unretained(new_url));
511   }
512
513   int rv = ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
514       profile_, extension_info_map_.get(), request, wrapped_callback,
515       new_url);
516
517   if (force_safe_search && rv == net::OK && new_url->is_empty())
518     ForceGoogleSafeSearch(request, new_url);
519
520   if (connect_interceptor_)
521     connect_interceptor_->WitnessURLRequest(request);
522
523   return rv;
524 }
525
526 int ChromeNetworkDelegate::OnBeforeSendHeaders(
527     net::URLRequest* request,
528     const net::CompletionCallback& callback,
529     net::HttpRequestHeaders* headers) {
530   TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request, "SendRequest");
531   return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
532       profile_, extension_info_map_.get(), request, callback, headers);
533 }
534
535 void ChromeNetworkDelegate::OnSendHeaders(
536     net::URLRequest* request,
537     const net::HttpRequestHeaders& headers) {
538   ExtensionWebRequestEventRouter::GetInstance()->OnSendHeaders(
539       profile_, extension_info_map_.get(), request, headers);
540 }
541
542 int ChromeNetworkDelegate::OnHeadersReceived(
543     net::URLRequest* request,
544     const net::CompletionCallback& callback,
545     const net::HttpResponseHeaders* original_response_headers,
546     scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
547     GURL* allowed_unsafe_redirect_url) {
548   return ExtensionWebRequestEventRouter::GetInstance()->OnHeadersReceived(
549       profile_,
550       extension_info_map_.get(),
551       request,
552       callback,
553       original_response_headers,
554       override_response_headers,
555       allowed_unsafe_redirect_url);
556 }
557
558 void ChromeNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
559                                              const GURL& new_location) {
560   if (domain_reliability_monitor_)
561     domain_reliability_monitor_->OnBeforeRedirect(request);
562   ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRedirect(
563       profile_, extension_info_map_.get(), request, new_location);
564 }
565
566
567 void ChromeNetworkDelegate::OnResponseStarted(net::URLRequest* request) {
568   TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request, "ResponseStarted");
569   ExtensionWebRequestEventRouter::GetInstance()->OnResponseStarted(
570       profile_, extension_info_map_.get(), request);
571   ForwardProxyErrors(request, event_router_.get(), profile_);
572 }
573
574 void ChromeNetworkDelegate::OnRawBytesRead(const net::URLRequest& request,
575                                            int bytes_read) {
576   TRACE_EVENT_ASYNC_STEP_PAST1("net", "URLRequest", &request, "DidRead",
577                                "bytes_read", bytes_read);
578   performance_monitor::PerformanceMonitor::GetInstance()->BytesReadOnIOThread(
579       request, bytes_read);
580
581 #if defined(ENABLE_TASK_MANAGER)
582   // This is not completely accurate, but as a first approximation ignore
583   // requests that are served from the cache. See bug 330931 for more info.
584   if (!request.was_cached())
585     TaskManager::GetInstance()->model()->NotifyBytesRead(request, bytes_read);
586 #endif  // defined(ENABLE_TASK_MANAGER)
587 }
588
589 void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request,
590                                         bool started) {
591   TRACE_EVENT_ASYNC_END0("net", "URLRequest", request);
592   if (request->status().status() == net::URLRequestStatus::SUCCESS) {
593     // For better accuracy, we use the actual bytes read instead of the length
594     // specified with the Content-Length header, which may be inaccurate,
595     // or missing, as is the case with chunked encoding.
596     int64 received_content_length = request->received_response_content_length();
597
598 #if defined(OS_ANDROID)
599     if (precache::PrecacheManager::IsPrecachingEnabled()) {
600       // Record precache metrics when a fetch is completed successfully, if
601       // precaching is enabled.
602       BrowserThread::PostTask(
603           BrowserThread::UI, FROM_HERE,
604           base::Bind(&RecordPrecacheStatsOnUIThread, request->url(),
605                      base::Time::Now(), received_content_length,
606                      request->was_cached(), profile_));
607     }
608 #endif  // defined(OS_ANDROID)
609
610     // Only record for http or https urls.
611     bool is_http = request->url().SchemeIs("http");
612     bool is_https = request->url().SchemeIs("https");
613
614     if (!request->was_cached() &&         // Don't record cached content
615         received_content_length &&        // Zero-byte responses aren't useful.
616         (is_http || is_https)) {          // Only record for HTTP or HTTPS urls.
617       int64 original_content_length =
618           request->response_info().headers->GetInt64HeaderValue(
619               "x-original-content-length");
620       data_reduction_proxy::DataReductionProxyRequestType request_type =
621           data_reduction_proxy::GetDataReductionProxyRequestType(request);
622
623       base::TimeDelta freshness_lifetime =
624           request->response_info().headers->GetFreshnessLifetime(
625               request->response_info().response_time);
626       int64 adjusted_original_content_length =
627           data_reduction_proxy::GetAdjustedOriginalContentLength(
628               request_type, original_content_length,
629               received_content_length);
630       AccumulateContentLength(received_content_length,
631                               adjusted_original_content_length,
632                               request_type);
633       RecordContentLengthHistograms(received_content_length,
634                                     original_content_length,
635                                     freshness_lifetime);
636       DVLOG(2) << __FUNCTION__
637           << " received content length: " << received_content_length
638           << " original content length: " << original_content_length
639           << " url: " << request->url();
640     }
641
642     bool is_redirect = request->response_headers() &&
643         net::HttpResponseHeaders::IsRedirectResponseCode(
644             request->response_headers()->response_code());
645     if (!is_redirect) {
646       ExtensionWebRequestEventRouter::GetInstance()->OnCompleted(
647           profile_, extension_info_map_.get(), request);
648     }
649   } else if (request->status().status() == net::URLRequestStatus::FAILED ||
650              request->status().status() == net::URLRequestStatus::CANCELED) {
651     ExtensionWebRequestEventRouter::GetInstance()->OnErrorOccurred(
652             profile_, extension_info_map_.get(), request, started);
653   } else {
654     NOTREACHED();
655   }
656   if (domain_reliability_monitor_)
657     domain_reliability_monitor_->OnCompleted(request, started);
658   ForwardProxyErrors(request, event_router_.get(), profile_);
659
660   ForwardRequestStatus(REQUEST_DONE, request, profile_);
661 }
662
663 void ChromeNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {
664   ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestDestroyed(
665       profile_, request);
666 }
667
668 void ChromeNetworkDelegate::OnPACScriptError(int line_number,
669                                              const base::string16& error) {
670   extensions::ProxyEventRouter::GetInstance()->OnPACScriptError(
671       event_router_.get(), profile_, line_number, error);
672 }
673
674 net::NetworkDelegate::AuthRequiredResponse
675 ChromeNetworkDelegate::OnAuthRequired(
676     net::URLRequest* request,
677     const net::AuthChallengeInfo& auth_info,
678     const AuthCallback& callback,
679     net::AuthCredentials* credentials) {
680   return ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired(
681       profile_, extension_info_map_.get(), request, auth_info,
682       callback, credentials);
683 }
684
685 bool ChromeNetworkDelegate::OnCanGetCookies(
686     const net::URLRequest& request,
687     const net::CookieList& cookie_list) {
688   // NULL during tests, or when we're running in the system context.
689   if (!cookie_settings_.get())
690     return true;
691
692   bool allow = cookie_settings_->IsReadingCookieAllowed(
693       request.url(), request.first_party_for_cookies());
694
695   int render_process_id = -1;
696   int render_frame_id = -1;
697
698   // |is_for_blocking_resource| indicates whether the cookies read were for a
699   // blocking resource (eg script, css). It is only temporarily added for
700   // diagnostic purposes, per bug 353678. Will be removed again once data
701   // collection is finished.
702   bool is_for_blocking_resource = false;
703   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(&request);
704   if (info && ((!info->IsAsync()) ||
705                info->GetResourceType() == ResourceType::STYLESHEET ||
706                info->GetResourceType() == ResourceType::SCRIPT)) {
707     is_for_blocking_resource = true;
708   }
709
710   if (content::ResourceRequestInfo::GetRenderFrameForRequest(
711           &request, &render_process_id, &render_frame_id)) {
712     BrowserThread::PostTask(
713         BrowserThread::UI, FROM_HERE,
714         base::Bind(&TabSpecificContentSettings::CookiesRead,
715                    render_process_id, render_frame_id,
716                    request.url(), request.first_party_for_cookies(),
717                    cookie_list, !allow, is_for_blocking_resource));
718   }
719
720   return allow;
721 }
722
723 bool ChromeNetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
724                                            const std::string& cookie_line,
725                                            net::CookieOptions* options) {
726   // NULL during tests, or when we're running in the system context.
727   if (!cookie_settings_.get())
728     return true;
729
730   bool allow = cookie_settings_->IsSettingCookieAllowed(
731       request.url(), request.first_party_for_cookies());
732
733   int render_process_id = -1;
734   int render_frame_id = -1;
735   if (content::ResourceRequestInfo::GetRenderFrameForRequest(
736           &request, &render_process_id, &render_frame_id)) {
737     BrowserThread::PostTask(
738         BrowserThread::UI, FROM_HERE,
739         base::Bind(&TabSpecificContentSettings::CookieChanged,
740                    render_process_id, render_frame_id,
741                    request.url(), request.first_party_for_cookies(),
742                    cookie_line, *options, !allow));
743   }
744
745   return allow;
746 }
747
748 bool ChromeNetworkDelegate::OnCanAccessFile(const net::URLRequest& request,
749                                             const base::FilePath& path) const {
750   if (g_allow_file_access_)
751     return true;
752
753 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
754   return true;
755 #else
756 #if defined(OS_CHROMEOS)
757   // If we're running Chrome for ChromeOS on Linux, we want to allow file
758   // access.
759   if (!base::SysInfo::IsRunningOnChromeOS() ||
760       CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) {
761     return true;
762   }
763
764   // Use a whitelist to only allow access to files residing in the list of
765   // directories below.
766   static const char* const kLocalAccessWhiteList[] = {
767       "/home/chronos/user/Downloads",
768       "/home/chronos/user/log",
769       "/home/chronos/user/WebRTC Logs",
770       "/media",
771       "/opt/oem",
772       "/usr/share/chromeos-assets",
773       "/tmp",
774       "/var/log",
775   };
776
777   // The actual location of "/home/chronos/user/Downloads" is the Downloads
778   // directory under the profile path ("/home/chronos/user' is a hard link to
779   // current primary logged in profile.) For the support of multi-profile
780   // sessions, we are switching to use explicit "$PROFILE_PATH/Downloads" path
781   // and here whitelist such access.
782   if (!profile_path_.empty()) {
783     const base::FilePath downloads = profile_path_.AppendASCII("Downloads");
784     if (downloads == path.StripTrailingSeparators() || downloads.IsParent(path))
785       return true;
786   }
787 #elif defined(OS_ANDROID)
788   // Access to files in external storage is allowed.
789   base::FilePath external_storage_path;
790   PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE, &external_storage_path);
791   if (external_storage_path.IsParent(path))
792     return true;
793
794   // Whitelist of other allowed directories.
795   static const char* const kLocalAccessWhiteList[] = {
796       "/sdcard",
797       "/mnt/sdcard",
798   };
799 #endif
800
801   for (size_t i = 0; i < arraysize(kLocalAccessWhiteList); ++i) {
802     const base::FilePath white_listed_path(kLocalAccessWhiteList[i]);
803     // base::FilePath::operator== should probably handle trailing separators.
804     if (white_listed_path == path.StripTrailingSeparators() ||
805         white_listed_path.IsParent(path)) {
806       return true;
807     }
808   }
809
810   DVLOG(1) << "File access denied - " << path.value().c_str();
811   return false;
812 #endif  // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
813 }
814
815 bool ChromeNetworkDelegate::OnCanThrottleRequest(
816     const net::URLRequest& request) const {
817   if (g_never_throttle_requests_) {
818     return false;
819   }
820
821   return request.first_party_for_cookies().scheme() ==
822       extensions::kExtensionScheme;
823 }
824
825 bool ChromeNetworkDelegate::OnCanEnablePrivacyMode(
826     const GURL& url,
827     const GURL& first_party_for_cookies) const {
828   // NULL during tests, or when we're running in the system context.
829   if (!cookie_settings_.get())
830     return false;
831
832   bool reading_cookie_allowed = cookie_settings_->IsReadingCookieAllowed(
833       url, first_party_for_cookies);
834   bool setting_cookie_allowed = cookie_settings_->IsSettingCookieAllowed(
835       url, first_party_for_cookies);
836   bool privacy_mode = !(reading_cookie_allowed && setting_cookie_allowed);
837   return privacy_mode;
838 }
839
840 int ChromeNetworkDelegate::OnBeforeSocketStreamConnect(
841     net::SocketStream* socket,
842     const net::CompletionCallback& callback) {
843 #if defined(ENABLE_CONFIGURATION_POLICY)
844   if (url_blacklist_manager_ &&
845       url_blacklist_manager_->IsURLBlocked(socket->url())) {
846     // URL access blocked by policy.
847     socket->net_log()->AddEvent(
848         net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST,
849         net::NetLog::StringCallback("url",
850                                     &socket->url().possibly_invalid_spec()));
851     return net::ERR_BLOCKED_BY_ADMINISTRATOR;
852   }
853 #endif
854   return net::OK;
855 }
856
857 void ChromeNetworkDelegate::AccumulateContentLength(
858     int64 received_content_length,
859     int64 original_content_length,
860     data_reduction_proxy::DataReductionProxyRequestType request_type) {
861   DCHECK_GE(received_content_length, 0);
862   DCHECK_GE(original_content_length, 0);
863   StoreAccumulatedContentLength(received_content_length,
864                                 original_content_length,
865                                 request_type,
866                                 reinterpret_cast<Profile*>(profile_));
867   received_content_length_ += received_content_length;
868   original_content_length_ += original_content_length;
869 }