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