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