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/logging.h"
     13 #include "base/metrics/histogram.h"
     14 #include "base/path_service.h"
     15 #include "base/prefs/pref_member.h"
     16 #include "base/prefs/pref_service.h"
     17 #include "base/strings/string_number_conversions.h"
     18 #include "base/strings/string_split.h"
     19 #include "chrome/browser/browser_process.h"
     20 #include "chrome/browser/content_settings/cookie_settings.h"
     21 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
     22 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
     23 #include "chrome/browser/extensions/api/proxy/proxy_api.h"
     24 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
     25 #include "chrome/browser/extensions/event_router_forwarder.h"
     26 #include "chrome/browser/extensions/extension_info_map.h"
     27 #include "chrome/browser/extensions/extension_process_manager.h"
     28 #include "chrome/browser/extensions/extension_system.h"
     29 #include "chrome/browser/google/google_util.h"
     30 #include "chrome/browser/net/connect_interceptor.h"
     31 #include "chrome/browser/net/load_time_stats.h"
     32 #include "chrome/browser/performance_monitor/performance_monitor.h"
     33 #include "chrome/browser/prefs/scoped_user_pref_update.h"
     34 #include "chrome/browser/profiles/profile_manager.h"
     35 #include "chrome/browser/task_manager/task_manager.h"
     36 #include "chrome/common/pref_names.h"
     37 #include "chrome/common/url_constants.h"
     38 #include "content/public/browser/browser_thread.h"
     39 #include "content/public/browser/render_view_host.h"
     40 #include "content/public/browser/resource_request_info.h"
     41 #include "extensions/common/constants.h"
     42 #include "net/base/host_port_pair.h"
     43 #include "net/base/net_errors.h"
     44 #include "net/base/net_log.h"
     45 #include "net/cookies/canonical_cookie.h"
     46 #include "net/cookies/cookie_options.h"
     47 #include "net/http/http_request_headers.h"
     48 #include "net/http/http_response_headers.h"
     49 #include "net/socket_stream/socket_stream.h"
     50 #include "net/url_request/url_request.h"
     51 
     52 #if defined(OS_CHROMEOS)
     53 #include "base/chromeos/chromeos_version.h"
     54 #include "base/command_line.h"
     55 #include "chrome/common/chrome_switches.h"
     56 #endif
     57 
     58 #if defined(ENABLE_CONFIGURATION_POLICY)
     59 #include "chrome/browser/policy/url_blacklist_manager.h"
     60 #endif
     61 
     62 using content::BrowserThread;
     63 using content::RenderViewHost;
     64 using content::ResourceRequestInfo;
     65 
     66 // By default we don't allow access to all file:// urls on ChromeOS and
     67 // Android.
     68 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
     69 bool ChromeNetworkDelegate::g_allow_file_access_ = false;
     70 #else
     71 bool ChromeNetworkDelegate::g_allow_file_access_ = true;
     72 #endif
     73 
     74 // This remains false unless the --disable-extensions-http-throttling
     75 // flag is passed to the browser.
     76 bool ChromeNetworkDelegate::g_never_throttle_requests_ = false;
     77 
     78 namespace {
     79 
     80 const char kDNTHeader[] = "DNT";
     81 
     82 // If the |request| failed due to problems with a proxy, forward the error to
     83 // the proxy extension API.
     84 void ForwardProxyErrors(net::URLRequest* request,
     85                         extensions::EventRouterForwarder* event_router,
     86                         void* profile) {
     87   if (request->status().status() == net::URLRequestStatus::FAILED) {
     88     switch (request->status().error()) {
     89       case net::ERR_PROXY_AUTH_UNSUPPORTED:
     90       case net::ERR_PROXY_CONNECTION_FAILED:
     91       case net::ERR_TUNNEL_CONNECTION_FAILED:
     92         extensions::ProxyEventRouter::GetInstance()->OnProxyError(
     93             event_router, profile, request->status().error());
     94     }
     95   }
     96 }
     97 
     98 // Returns whether a URL parameter, |first_parameter| (e.g. foo=bar), has the
     99 // same key as the the |second_parameter| (e.g. foo=baz). Both parameters
    100 // must be in key=value form.
    101 bool HasSameParameterKey(const std::string& first_parameter,
    102                          const std::string& second_parameter) {
    103   DCHECK(second_parameter.find("=") != std::string::npos);
    104   // Prefix for "foo=bar" is "foo=".
    105   std::string parameter_prefix = second_parameter.substr(
    106       0, second_parameter.find("=") + 1);
    107   return StartsWithASCII(first_parameter, parameter_prefix, false);
    108 }
    109 
    110 // Examines the query string containing parameters and adds the necessary ones
    111 // so that SafeSearch is active. |query| is the string to examine and the
    112 // return value is the |query| string modified such that SafeSearch is active.
    113 std::string AddSafeSearchParameters(const std::string& query) {
    114   std::vector<std::string> new_parameters;
    115   std::string safe_parameter = chrome::kSafeSearchSafeParameter;
    116   std::string ssui_parameter = chrome::kSafeSearchSsuiParameter;
    117 
    118   std::vector<std::string> parameters;
    119   base::SplitString(query, '&', &parameters);
    120 
    121   std::vector<std::string>::iterator it;
    122   for (it = parameters.begin(); it < parameters.end(); ++it) {
    123     if (!HasSameParameterKey(*it, safe_parameter) &&
    124         !HasSameParameterKey(*it, ssui_parameter)) {
    125       new_parameters.push_back(*it);
    126     }
    127   }
    128 
    129   new_parameters.push_back(safe_parameter);
    130   new_parameters.push_back(ssui_parameter);
    131   return JoinString(new_parameters, '&');
    132 }
    133 
    134 // If |request| is a request to Google Web Search the function
    135 // enforces that the SafeSearch query parameters are set to active.
    136 // Sets the query part of |new_url| with the new value of the parameters.
    137 void ForceGoogleSafeSearch(net::URLRequest* request,
    138                            GURL* new_url) {
    139   if (!google_util::IsGoogleSearchUrl(request->url()) &&
    140       !google_util::IsGoogleHomePageUrl(request->url()))
    141     return;
    142 
    143   std::string query = request->url().query();
    144   std::string new_query = AddSafeSearchParameters(query);
    145   if (query == new_query)
    146     return;
    147 
    148   GURL::Replacements replacements;
    149   replacements.SetQueryStr(new_query);
    150   *new_url = request->url().ReplaceComponents(replacements);
    151 }
    152 
    153 // Gets called when the extensions finish work on the URL. If the extensions
    154 // did not do a redirect (so |new_url| is empty) then we enforce the
    155 // SafeSearch parameters. Otherwise we will get called again after the
    156 // redirect and we enforce SafeSearch then.
    157 void ForceGoogleSafeSearchCallbackWrapper(
    158     const net::CompletionCallback& callback,
    159     net::URLRequest* request,
    160     GURL* new_url,
    161     int rv) {
    162   if (rv == net::OK && new_url->is_empty())
    163     ForceGoogleSafeSearch(request, new_url);
    164   callback.Run(rv);
    165 }
    166 
    167 enum RequestStatus { REQUEST_STARTED, REQUEST_DONE };
    168 
    169 // Notifies the ExtensionProcessManager that a request has started or stopped
    170 // for a particular RenderView.
    171 void NotifyEPMRequestStatus(RequestStatus status,
    172                             void* profile_id,
    173                             int process_id,
    174                             int render_view_id) {
    175   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    176   Profile* profile = reinterpret_cast<Profile*>(profile_id);
    177   if (!g_browser_process->profile_manager()->IsValidProfile(profile))
    178     return;
    179 
    180   ExtensionProcessManager* extension_process_manager =
    181       extensions::ExtensionSystem::Get(profile)->process_manager();
    182   // This may be NULL in unit tests.
    183   if (!extension_process_manager)
    184     return;
    185 
    186   // Will be NULL if the request was not issued on behalf of a renderer (e.g. a
    187   // system-level request).
    188   RenderViewHost* render_view_host =
    189       RenderViewHost::FromID(process_id, render_view_id);
    190   if (render_view_host) {
    191     if (status == REQUEST_STARTED) {
    192       extension_process_manager->OnNetworkRequestStarted(render_view_host);
    193     } else if (status == REQUEST_DONE) {
    194       extension_process_manager->OnNetworkRequestDone(render_view_host);
    195     } else {
    196       NOTREACHED();
    197     }
    198   }
    199 }
    200 
    201 void ForwardRequestStatus(
    202     RequestStatus status, net::URLRequest* request, void* profile_id) {
    203   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
    204   if (!info)
    205     return;
    206 
    207   int process_id, render_view_id;
    208   if (info->GetAssociatedRenderView(&process_id, &render_view_id)) {
    209     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    210         base::Bind(&NotifyEPMRequestStatus,
    211                    status, profile_id, process_id, render_view_id));
    212   }
    213 }
    214 
    215 #if defined(OS_ANDROID) || defined(OS_IOS)
    216 // Increments an int64, stored as a string, in a ListPref at the specified
    217 // index.  The value must already exist and be a string representation of a
    218 // number.
    219 void AddInt64ToListPref(size_t index, int64 length,
    220                         base::ListValue* list_update) {
    221   int64 value = 0;
    222   std::string old_string_value;
    223   bool rv = list_update->GetString(index, &old_string_value);
    224   DCHECK(rv);
    225   if (rv) {
    226     rv = base::StringToInt64(old_string_value, &value);
    227     DCHECK(rv);
    228   }
    229   value += length;
    230   list_update->Set(index, Value::CreateStringValue(base::Int64ToString(value)));
    231 }
    232 
    233 int64 ListPrefInt64Value(const base::ListValue& list_update, size_t index) {
    234   std::string string_value;
    235   if (!list_update.GetString(index, &string_value))
    236     return 0;
    237 
    238   int64 value = 0;
    239   bool rv = base::StringToInt64(string_value, &value);
    240   DCHECK(rv);
    241   return value;
    242 }
    243 
    244 void RecordDailyContentLengthHistograms(
    245     int64 original_length,
    246     int64 received_length,
    247     int64 length_with_data_reduction_enabled,
    248     int64 length_via_data_reduction_proxy) {
    249   // Record metrics in KB.
    250   UMA_HISTOGRAM_COUNTS(
    251       "Net.DailyHttpOriginalContentLength", original_length >> 10);
    252   UMA_HISTOGRAM_COUNTS(
    253       "Net.DailyHttpReceivedContentLength", received_length >> 10);
    254   UMA_HISTOGRAM_COUNTS(
    255       "Net.DailyHttpContentLengthWithDataReductionProxyEnabled",
    256       length_with_data_reduction_enabled >> 10);
    257   UMA_HISTOGRAM_COUNTS(
    258       "Net.DailyHttpContentLengthViaDataReductionProxy",
    259       length_via_data_reduction_proxy >> 10);
    260 
    261   if (original_length > 0 && received_length > 0) {
    262     int percent = (100 * (original_length - received_length)) / original_length;
    263     // UMA percentage cannot be negative.
    264     if (percent < 0)
    265       percent = 0;
    266     UMA_HISTOGRAM_PERCENTAGE("Net.DailyHttpContentSavings", percent);
    267     // If the data reduction proxy is enabled for some responses.
    268     if (length_with_data_reduction_enabled > 0) {
    269       UMA_HISTOGRAM_PERCENTAGE(
    270           "Net.DailyHttpContentSavings_DataReductionProxy", percent);
    271     }
    272   }
    273   if (received_length > 0 && length_with_data_reduction_enabled >= 0) {
    274     DCHECK_GE(received_length, length_with_data_reduction_enabled);
    275     UMA_HISTOGRAM_PERCENTAGE(
    276         "Net.DailyReceivedContentWithDataReductionProxyEnabled",
    277         (100 * length_with_data_reduction_enabled) / received_length);
    278   }
    279   if (received_length > 0 &&
    280       length_via_data_reduction_proxy >= 0) {
    281     DCHECK_GE(received_length, length_via_data_reduction_proxy);
    282     UMA_HISTOGRAM_PERCENTAGE(
    283         "Net.DailyReceivedContentViaDataReductionProxy",
    284         (100 * length_via_data_reduction_proxy) / received_length);
    285   }
    286 }
    287 
    288 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
    289 
    290 void UpdateContentLengthPrefs(int received_content_length,
    291                               int original_content_length,
    292                               bool data_reduction_proxy_was_used) {
    293   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    294   DCHECK_GE(received_content_length, 0);
    295   DCHECK_GE(original_content_length, 0);
    296 
    297   // Can be NULL in a unit test.
    298   if (!g_browser_process)
    299     return;
    300 
    301   PrefService* prefs = g_browser_process->local_state();
    302   if (!prefs)
    303     return;
    304 
    305   int64 total_received = prefs->GetInt64(prefs::kHttpReceivedContentLength);
    306   int64 total_original = prefs->GetInt64(prefs::kHttpOriginalContentLength);
    307   total_received += received_content_length;
    308   total_original += original_content_length;
    309   prefs->SetInt64(prefs::kHttpReceivedContentLength, total_received);
    310   prefs->SetInt64(prefs::kHttpOriginalContentLength, total_original);
    311 
    312 #if defined(OS_ANDROID) || defined(OS_IOS)
    313   base::Time now = base::Time::Now().LocalMidnight();
    314   const size_t kNumDaysInHistory = 60;
    315 
    316   // Each day, we calculate the total number of bytes received and the total
    317   // size of all corresponding resources before any data-reducing recompression
    318   // is applied. These values are used to compute the data savings realized
    319   // by applying our compression techniques. Totals for the last
    320   // |kNumDaysInHistory| days are maintained.
    321   ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength);
    322   ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength);
    323   ListPrefUpdate data_reduction_enabled_update(
    324       prefs,
    325       prefs::kDailyHttpReceivedContentLengthWithDataReductionProxyEnabled);
    326   ListPrefUpdate via_data_reduction_update(
    327       prefs, prefs::kDailyHttpReceivedContentLengthViaDataReductionProxy);
    328 
    329   // Determine how many days it has been since the last update.
    330   int64 then_internal = prefs->GetInt64(
    331       prefs::kDailyHttpContentLengthLastUpdateDate);
    332   base::Time then = base::Time::FromInternalValue(then_internal);
    333   int days_since_last_update = (now - then).InDays();
    334 
    335   if (days_since_last_update) {
    336     // Record the last update time.
    337     prefs->SetInt64(prefs::kDailyHttpContentLengthLastUpdateDate,
    338                     now.ToInternalValue());
    339 
    340     if (days_since_last_update == -1) {
    341       // The system may go backwards in time by up to a day for legitimate
    342       // reasons, such as with changes to the time zone. In such cases the
    343       // history is likely still valid. Shift backwards one day and retain all
    344       // values.
    345       original_update->Remove(kNumDaysInHistory - 1, NULL);
    346       received_update->Remove(kNumDaysInHistory - 1, NULL);
    347       data_reduction_enabled_update->Remove(kNumDaysInHistory - 1, NULL);
    348       via_data_reduction_update->Remove(kNumDaysInHistory - 1, NULL);
    349       original_update->Insert(0, new StringValue(base::Int64ToString(0)));
    350       received_update->Insert(0, new StringValue(base::Int64ToString(0)));
    351       data_reduction_enabled_update->Insert(
    352           0, new StringValue(base::Int64ToString(0)));
    353       via_data_reduction_update->Insert(
    354           0, new StringValue(base::Int64ToString(0)));
    355       days_since_last_update = 0;
    356 
    357     } else if (days_since_last_update < -1) {
    358       // Erase all entries if the system went backwards in time by more than
    359       // a day.
    360       original_update->Clear();
    361       received_update->Clear();
    362       data_reduction_enabled_update->Clear();
    363       via_data_reduction_update->Clear();
    364       days_since_last_update = kNumDaysInHistory;
    365     }
    366 
    367     // A new day. Report the previous day's data if exists. We'll lose usage
    368     // data if Chrome isn't run for a day. Here, we prefer collecting less data
    369     // but the collected data are associated with an accurate date.
    370     if (days_since_last_update == 1) {
    371       RecordDailyContentLengthHistograms(
    372           ListPrefInt64Value(*original_update, original_update->GetSize() - 1),
    373           ListPrefInt64Value(*received_update, received_update->GetSize() - 1),
    374           ListPrefInt64Value(*data_reduction_enabled_update,
    375                              data_reduction_enabled_update->GetSize() - 1),
    376           ListPrefInt64Value(*via_data_reduction_update,
    377                              via_data_reduction_update->GetSize() - 1));
    378     }
    379 
    380     // Add entries for days since last update.
    381     for (int i = 0;
    382          i < days_since_last_update && i < static_cast<int>(kNumDaysInHistory);
    383          ++i) {
    384       original_update->AppendString(base::Int64ToString(0));
    385       received_update->AppendString(base::Int64ToString(0));
    386       data_reduction_enabled_update->AppendString(base::Int64ToString(0));
    387       via_data_reduction_update->AppendString(base::Int64ToString(0));
    388     }
    389 
    390     // Maintain the invariant that there should never be more than
    391     // |kNumDaysInHistory| days in the histories.
    392     while (original_update->GetSize() > kNumDaysInHistory)
    393       original_update->Remove(0, NULL);
    394     while (received_update->GetSize() > kNumDaysInHistory)
    395       received_update->Remove(0, NULL);
    396     while (data_reduction_enabled_update->GetSize() > kNumDaysInHistory)
    397       data_reduction_enabled_update->Remove(0, NULL);
    398     while (via_data_reduction_update->GetSize() > kNumDaysInHistory)
    399       via_data_reduction_update->Remove(0, NULL);
    400   }
    401 
    402   DCHECK_EQ(kNumDaysInHistory, original_update->GetSize());
    403   DCHECK_EQ(kNumDaysInHistory, received_update->GetSize());
    404   DCHECK_EQ(kNumDaysInHistory, data_reduction_enabled_update->GetSize());
    405   DCHECK_EQ(kNumDaysInHistory, via_data_reduction_update->GetSize());
    406 
    407   // Update the counts for the current day.
    408   AddInt64ToListPref(kNumDaysInHistory - 1,
    409                      original_content_length, original_update.Get());
    410   AddInt64ToListPref(kNumDaysInHistory - 1,
    411                      received_content_length, received_update.Get());
    412 
    413   if (g_browser_process->profile_manager()->GetDefaultProfile()->
    414           GetPrefs()->GetBoolean(prefs::kSpdyProxyAuthEnabled)) {
    415     AddInt64ToListPref(kNumDaysInHistory - 1,
    416                        received_content_length,
    417                        data_reduction_enabled_update.Get());
    418   }
    419   if (data_reduction_proxy_was_used) {
    420     AddInt64ToListPref(kNumDaysInHistory - 1,
    421                        received_content_length,
    422                        via_data_reduction_update.Get());
    423   }
    424 #endif
    425 }
    426 
    427 void StoreAccumulatedContentLength(int received_content_length,
    428                                    int original_content_length,
    429                                    bool data_reduction_proxy_was_used) {
    430   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    431       base::Bind(&UpdateContentLengthPrefs,
    432                  received_content_length, original_content_length,
    433                  data_reduction_proxy_was_used));
    434 }
    435 
    436 void RecordContentLengthHistograms(
    437     int64 received_content_length,
    438     int64 original_content_length,
    439     const base::TimeDelta& freshness_lifetime) {
    440 #if defined(OS_ANDROID) || defined(OS_IOS)
    441   // Add the current resource to these histograms only when a valid
    442   // X-Original-Content-Length header is present.
    443   if (original_content_length >= 0) {
    444     UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthWithValidOCL",
    445                          received_content_length);
    446     UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLengthWithValidOCL",
    447                          original_content_length);
    448     UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifferenceWithValidOCL",
    449                          original_content_length - received_content_length);
    450   } else {
    451     // Presume the original content length is the same as the received content
    452     // length if the X-Original-Content-Header is not present.
    453     original_content_length = received_content_length;
    454   }
    455   UMA_HISTOGRAM_COUNTS("Net.HttpContentLength", received_content_length);
    456   UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLength",
    457                        original_content_length);
    458   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifference",
    459                        original_content_length - received_content_length);
    460   UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpContentFreshnessLifetime",
    461                               freshness_lifetime.InSeconds(),
    462                               base::TimeDelta::FromHours(1).InSeconds(),
    463                               base::TimeDelta::FromDays(30).InSeconds(),
    464                               100);
    465   if (freshness_lifetime.InSeconds() <= 0)
    466     return;
    467   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable",
    468                        received_content_length);
    469   if (freshness_lifetime.InHours() < 4)
    470     return;
    471   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable4Hours",
    472                        received_content_length);
    473 
    474   if (freshness_lifetime.InHours() < 24)
    475     return;
    476   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable24Hours",
    477                        received_content_length);
    478 #endif
    479 }
    480 
    481 }  // namespace
    482 
    483 ChromeNetworkDelegate::ChromeNetworkDelegate(
    484     extensions::EventRouterForwarder* event_router,
    485     BooleanPrefMember* enable_referrers)
    486     : event_router_(event_router),
    487       profile_(NULL),
    488       enable_referrers_(enable_referrers),
    489       enable_do_not_track_(NULL),
    490       force_google_safe_search_(NULL),
    491       url_blacklist_manager_(NULL),
    492       load_time_stats_(NULL),
    493       received_content_length_(0),
    494       original_content_length_(0) {
    495   DCHECK(event_router);
    496   DCHECK(enable_referrers);
    497 }
    498 
    499 ChromeNetworkDelegate::~ChromeNetworkDelegate() {}
    500 
    501 void ChromeNetworkDelegate::set_extension_info_map(
    502     ExtensionInfoMap* extension_info_map) {
    503   extension_info_map_ = extension_info_map;
    504 }
    505 
    506 void ChromeNetworkDelegate::set_cookie_settings(
    507     CookieSettings* cookie_settings) {
    508   cookie_settings_ = cookie_settings;
    509 }
    510 
    511 void ChromeNetworkDelegate::set_predictor(
    512     chrome_browser_net::Predictor* predictor) {
    513   connect_interceptor_.reset(
    514       new chrome_browser_net::ConnectInterceptor(predictor));
    515 }
    516 
    517 // static
    518 void ChromeNetworkDelegate::NeverThrottleRequests() {
    519   g_never_throttle_requests_ = true;
    520 }
    521 
    522 // static
    523 void ChromeNetworkDelegate::InitializePrefsOnUIThread(
    524     BooleanPrefMember* enable_referrers,
    525     BooleanPrefMember* enable_do_not_track,
    526     BooleanPrefMember* force_google_safe_search,
    527     PrefService* pref_service) {
    528   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    529   enable_referrers->Init(prefs::kEnableReferrers, pref_service);
    530   enable_referrers->MoveToThread(
    531       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
    532   if (enable_do_not_track) {
    533     enable_do_not_track->Init(prefs::kEnableDoNotTrack, pref_service);
    534     enable_do_not_track->MoveToThread(
    535         BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
    536   }
    537   if (force_google_safe_search) {
    538     force_google_safe_search->Init(prefs::kForceSafeSearch, pref_service);
    539     force_google_safe_search->MoveToThread(
    540         BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
    541   }
    542 }
    543 
    544 // static
    545 void ChromeNetworkDelegate::AllowAccessToAllFiles() {
    546   g_allow_file_access_ = true;
    547 }
    548 
    549 // static
    550 Value* ChromeNetworkDelegate::HistoricNetworkStatsInfoToValue() {
    551   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    552   PrefService* prefs = g_browser_process->local_state();
    553   int64 total_received = prefs->GetInt64(prefs::kHttpReceivedContentLength);
    554   int64 total_original = prefs->GetInt64(prefs::kHttpOriginalContentLength);
    555 
    556   DictionaryValue* dict = new DictionaryValue();
    557   // Use strings to avoid overflow.  base::Value only supports 32-bit integers.
    558   dict->SetString("historic_received_content_length",
    559                   base::Int64ToString(total_received));
    560   dict->SetString("historic_original_content_length",
    561                   base::Int64ToString(total_original));
    562   return dict;
    563 }
    564 
    565 Value* ChromeNetworkDelegate::SessionNetworkStatsInfoToValue() const {
    566   DictionaryValue* dict = new DictionaryValue();
    567   // Use strings to avoid overflow.  base::Value only supports 32-bit integers.
    568   dict->SetString("session_received_content_length",
    569                   base::Int64ToString(received_content_length_));
    570   dict->SetString("session_original_content_length",
    571                   base::Int64ToString(original_content_length_));
    572   return dict;
    573 }
    574 
    575 int ChromeNetworkDelegate::OnBeforeURLRequest(
    576     net::URLRequest* request,
    577     const net::CompletionCallback& callback,
    578     GURL* new_url) {
    579 #if defined(ENABLE_CONFIGURATION_POLICY)
    580   // TODO(joaodasilva): This prevents extensions from seeing URLs that are
    581   // blocked. However, an extension might redirect the request to another URL,
    582   // which is not blocked.
    583   if (url_blacklist_manager_ &&
    584       url_blacklist_manager_->IsRequestBlocked(*request)) {
    585     // URL access blocked by policy.
    586     request->net_log().AddEvent(
    587         net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST,
    588         net::NetLog::StringCallback("url",
    589                                     &request->url().possibly_invalid_spec()));
    590     return net::ERR_BLOCKED_BY_ADMINISTRATOR;
    591   }
    592 #endif
    593 
    594   ForwardRequestStatus(REQUEST_STARTED, request, profile_);
    595 
    596   if (!enable_referrers_->GetValue())
    597     request->SetReferrer(std::string());
    598   if (enable_do_not_track_ && enable_do_not_track_->GetValue())
    599     request->SetExtraRequestHeaderByName(kDNTHeader, "1", true /* override */);
    600 
    601   bool force_safe_search = force_google_safe_search_ &&
    602                            force_google_safe_search_->GetValue();
    603 
    604   net::CompletionCallback wrapped_callback = callback;
    605   if (force_safe_search) {
    606     wrapped_callback = base::Bind(&ForceGoogleSafeSearchCallbackWrapper,
    607                                   callback,
    608                                   base::Unretained(request),
    609                                   base::Unretained(new_url));
    610   }
    611 
    612   int rv = ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
    613       profile_, extension_info_map_.get(), request, wrapped_callback,
    614       new_url);
    615 
    616   if (force_safe_search && rv == net::OK && new_url->is_empty())
    617     ForceGoogleSafeSearch(request, new_url);
    618 
    619   if (connect_interceptor_)
    620     connect_interceptor_->WitnessURLRequest(request);
    621 
    622   return rv;
    623 }
    624 
    625 int ChromeNetworkDelegate::OnBeforeSendHeaders(
    626     net::URLRequest* request,
    627     const net::CompletionCallback& callback,
    628     net::HttpRequestHeaders* headers) {
    629   return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
    630       profile_, extension_info_map_.get(), request, callback, headers);
    631 }
    632 
    633 void ChromeNetworkDelegate::OnSendHeaders(
    634     net::URLRequest* request,
    635     const net::HttpRequestHeaders& headers) {
    636   ExtensionWebRequestEventRouter::GetInstance()->OnSendHeaders(
    637       profile_, extension_info_map_.get(), request, headers);
    638 }
    639 
    640 int ChromeNetworkDelegate::OnHeadersReceived(
    641     net::URLRequest* request,
    642     const net::CompletionCallback& callback,
    643     const net::HttpResponseHeaders* original_response_headers,
    644     scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
    645   return ExtensionWebRequestEventRouter::GetInstance()->OnHeadersReceived(
    646       profile_, extension_info_map_.get(), request, callback,
    647       original_response_headers, override_response_headers);
    648 }
    649 
    650 void ChromeNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
    651                                              const GURL& new_location) {
    652   ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRedirect(
    653       profile_, extension_info_map_.get(), request, new_location);
    654 }
    655 
    656 
    657 void ChromeNetworkDelegate::OnResponseStarted(net::URLRequest* request) {
    658   ExtensionWebRequestEventRouter::GetInstance()->OnResponseStarted(
    659       profile_, extension_info_map_.get(), request);
    660   ForwardProxyErrors(request, event_router_.get(), profile_);
    661 }
    662 
    663 void ChromeNetworkDelegate::OnRawBytesRead(const net::URLRequest& request,
    664                                            int bytes_read) {
    665   performance_monitor::PerformanceMonitor::GetInstance()->BytesReadOnIOThread(
    666       request, bytes_read);
    667 
    668 #if defined(ENABLE_TASK_MANAGER)
    669   TaskManager::GetInstance()->model()->NotifyBytesRead(request, bytes_read);
    670 #endif  // defined(ENABLE_TASK_MANAGER)
    671 }
    672 
    673 void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request,
    674                                         bool started) {
    675   if (request->status().status() == net::URLRequestStatus::SUCCESS) {
    676     // For better accuracy, we use the actual bytes read instead of the length
    677     // specified with the Content-Length header, which may be inaccurate,
    678     // or missing, as is the case with chunked encoding.
    679     int64 received_content_length = request->received_response_content_length();
    680 
    681     // Only record for http or https urls.
    682     bool is_http = request->url().SchemeIs("http");
    683     bool is_https = request->url().SchemeIs("https");
    684 
    685     if (!request->was_cached() &&         // Don't record cached content
    686         received_content_length &&        // Zero-byte responses aren't useful.
    687         (is_http || is_https)) {          // Only record for HTTP or HTTPS urls.
    688       int64 original_content_length =
    689           request->response_info().headers->GetInt64HeaderValue(
    690               "x-original-content-length");
    691       bool data_reduction_proxy_was_used =
    692           request->response_info().headers->HasHeaderValue(
    693               "via", "1.1 Chrome Compression Proxy");
    694 
    695       // Since there was no indication of the original content length, presume
    696       // it is no different from the number of bytes read.
    697       int64 adjusted_original_content_length = original_content_length;
    698       if (adjusted_original_content_length == -1)
    699         adjusted_original_content_length = received_content_length;
    700       base::TimeDelta freshness_lifetime =
    701           request->response_info().headers->GetFreshnessLifetime(
    702               request->response_info().response_time);
    703       AccumulateContentLength(received_content_length,
    704                               adjusted_original_content_length,
    705                               data_reduction_proxy_was_used);
    706       RecordContentLengthHistograms(received_content_length,
    707                                     original_content_length,
    708                                     freshness_lifetime);
    709       DVLOG(2) << __FUNCTION__
    710           << " received content length: " << received_content_length
    711           << " original content length: " << original_content_length
    712           << " url: " << request->url();
    713     }
    714 
    715     bool is_redirect = request->response_headers() &&
    716         net::HttpResponseHeaders::IsRedirectResponseCode(
    717             request->response_headers()->response_code());
    718     if (!is_redirect) {
    719       ExtensionWebRequestEventRouter::GetInstance()->OnCompleted(
    720           profile_, extension_info_map_.get(), request);
    721     }
    722   } else if (request->status().status() == net::URLRequestStatus::FAILED ||
    723              request->status().status() == net::URLRequestStatus::CANCELED) {
    724     ExtensionWebRequestEventRouter::GetInstance()->OnErrorOccurred(
    725             profile_, extension_info_map_.get(), request, started);
    726   } else {
    727     NOTREACHED();
    728   }
    729   ForwardProxyErrors(request, event_router_.get(), profile_);
    730 
    731   ForwardRequestStatus(REQUEST_DONE, request, profile_);
    732 }
    733 
    734 void ChromeNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {
    735   ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestDestroyed(
    736       profile_, request);
    737   if (load_time_stats_)
    738     load_time_stats_->OnURLRequestDestroyed(*request);
    739 }
    740 
    741 void ChromeNetworkDelegate::OnPACScriptError(int line_number,
    742                                              const string16& error) {
    743   extensions::ProxyEventRouter::GetInstance()->OnPACScriptError(
    744       event_router_.get(), profile_, line_number, error);
    745 }
    746 
    747 net::NetworkDelegate::AuthRequiredResponse
    748 ChromeNetworkDelegate::OnAuthRequired(
    749     net::URLRequest* request,
    750     const net::AuthChallengeInfo& auth_info,
    751     const AuthCallback& callback,
    752     net::AuthCredentials* credentials) {
    753   return ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired(
    754       profile_, extension_info_map_.get(), request, auth_info,
    755       callback, credentials);
    756 }
    757 
    758 bool ChromeNetworkDelegate::OnCanGetCookies(
    759     const net::URLRequest& request,
    760     const net::CookieList& cookie_list) {
    761   // NULL during tests, or when we're running in the system context.
    762   if (!cookie_settings_.get())
    763     return true;
    764 
    765   bool allow = cookie_settings_->IsReadingCookieAllowed(
    766       request.url(), request.first_party_for_cookies());
    767 
    768   int render_process_id = -1;
    769   int render_view_id = -1;
    770   if (content::ResourceRequestInfo::GetRenderViewForRequest(
    771           &request, &render_process_id, &render_view_id)) {
    772     BrowserThread::PostTask(
    773         BrowserThread::UI, FROM_HERE,
    774         base::Bind(&TabSpecificContentSettings::CookiesRead,
    775                    render_process_id, render_view_id,
    776                    request.url(), request.first_party_for_cookies(),
    777                    cookie_list, !allow));
    778   }
    779 
    780   return allow;
    781 }
    782 
    783 bool ChromeNetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
    784                                            const std::string& cookie_line,
    785                                            net::CookieOptions* options) {
    786   // NULL during tests, or when we're running in the system context.
    787   if (!cookie_settings_.get())
    788     return true;
    789 
    790   bool allow = cookie_settings_->IsSettingCookieAllowed(
    791       request.url(), request.first_party_for_cookies());
    792 
    793   int render_process_id = -1;
    794   int render_view_id = -1;
    795   if (content::ResourceRequestInfo::GetRenderViewForRequest(
    796           &request, &render_process_id, &render_view_id)) {
    797     BrowserThread::PostTask(
    798         BrowserThread::UI, FROM_HERE,
    799         base::Bind(&TabSpecificContentSettings::CookieChanged,
    800                    render_process_id, render_view_id,
    801                    request.url(), request.first_party_for_cookies(),
    802                    cookie_line, *options, !allow));
    803   }
    804 
    805   return allow;
    806 }
    807 
    808 bool ChromeNetworkDelegate::OnCanAccessFile(const net::URLRequest& request,
    809                                             const base::FilePath& path) const {
    810   if (g_allow_file_access_)
    811     return true;
    812 
    813 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
    814   return true;
    815 #else
    816 #if defined(OS_CHROMEOS)
    817   // If we're running Chrome for ChromeOS on Linux, we want to allow file
    818   // access.
    819   if (!base::chromeos::IsRunningOnChromeOS() ||
    820       CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) {
    821     return true;
    822   }
    823 
    824   // Use a whitelist to only allow access to files residing in the list of
    825   // directories below.
    826   static const char* const kLocalAccessWhiteList[] = {
    827       "/home/chronos/user/Downloads",
    828       "/home/chronos/user/log",
    829       "/media",
    830       "/opt/oem",
    831       "/usr/share/chromeos-assets",
    832       "/tmp",
    833       "/var/log",
    834   };
    835 #elif defined(OS_ANDROID)
    836   // Access to files in external storage is allowed.
    837   base::FilePath external_storage_path;
    838   PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE, &external_storage_path);
    839   if (external_storage_path.IsParent(path))
    840     return true;
    841 
    842   // Whitelist of other allowed directories.
    843   static const char* const kLocalAccessWhiteList[] = {
    844       "/sdcard",
    845       "/mnt/sdcard",
    846   };
    847 #endif
    848 
    849   for (size_t i = 0; i < arraysize(kLocalAccessWhiteList); ++i) {
    850     const base::FilePath white_listed_path(kLocalAccessWhiteList[i]);
    851     // base::FilePath::operator== should probably handle trailing separators.
    852     if (white_listed_path == path.StripTrailingSeparators() ||
    853         white_listed_path.IsParent(path)) {
    854       return true;
    855     }
    856   }
    857 
    858   DVLOG(1) << "File access denied - " << path.value().c_str();
    859   return false;
    860 #endif  // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
    861 }
    862 
    863 bool ChromeNetworkDelegate::OnCanThrottleRequest(
    864     const net::URLRequest& request) const {
    865   if (g_never_throttle_requests_) {
    866     return false;
    867   }
    868 
    869   return request.first_party_for_cookies().scheme() ==
    870       extensions::kExtensionScheme;
    871 }
    872 
    873 bool ChromeNetworkDelegate::OnCanEnablePrivacyMode(
    874     const GURL& url,
    875     const GURL& first_party_for_cookies) const {
    876   // NULL during tests, or when we're running in the system context.
    877   if (!cookie_settings_.get())
    878     return false;
    879 
    880   bool reading_cookie_allowed = cookie_settings_->IsReadingCookieAllowed(
    881       url, first_party_for_cookies);
    882   bool setting_cookie_allowed = cookie_settings_->IsSettingCookieAllowed(
    883       url, first_party_for_cookies);
    884   bool privacy_mode = !(reading_cookie_allowed && setting_cookie_allowed);
    885   return privacy_mode;
    886 }
    887 
    888 int ChromeNetworkDelegate::OnBeforeSocketStreamConnect(
    889     net::SocketStream* socket,
    890     const net::CompletionCallback& callback) {
    891 #if defined(ENABLE_CONFIGURATION_POLICY)
    892   if (url_blacklist_manager_ &&
    893       url_blacklist_manager_->IsURLBlocked(socket->url())) {
    894     // URL access blocked by policy.
    895     socket->net_log()->AddEvent(
    896         net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST,
    897         net::NetLog::StringCallback("url",
    898                                     &socket->url().possibly_invalid_spec()));
    899     return net::ERR_BLOCKED_BY_ADMINISTRATOR;
    900   }
    901 #endif
    902   return net::OK;
    903 }
    904 
    905 void ChromeNetworkDelegate::OnRequestWaitStateChange(
    906     const net::URLRequest& request,
    907     RequestWaitState state) {
    908   if (load_time_stats_)
    909     load_time_stats_->OnRequestWaitStateChange(request, state);
    910 }
    911 
    912 void ChromeNetworkDelegate::AccumulateContentLength(
    913     int64 received_content_length, int64 original_content_length,
    914     bool data_reduction_proxy_was_used) {
    915   DCHECK_GE(received_content_length, 0);
    916   DCHECK_GE(original_content_length, 0);
    917   StoreAccumulatedContentLength(received_content_length,
    918                                 original_content_length,
    919                                 data_reduction_proxy_was_used);
    920   received_content_length_ += received_content_length;
    921   original_content_length_ += original_content_length;
    922 }
    923