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