Upstream version 10.38.220.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / net / chrome_network_delegate.cc
index ffb7959..110edde 100644 (file)
 #include "base/prefs/pref_member.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
 #include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/cookie_settings.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
-#include "chrome/browser/extensions/api/proxy/proxy_api.h"
-#include "chrome/browser/extensions/api/web_request/web_request_api.h"
-#include "chrome/browser/extensions/event_router_forwarder.h"
-#include "chrome/browser/extensions/extension_info_map.h"
-#include "chrome/browser/extensions/extension_process_manager.h"
-#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/net/chrome_network_data_saving_metrics.h"
+#include "chrome/browser/net/chrome_extensions_network_delegate.h"
 #include "chrome/browser/net/client_hints.h"
 #include "chrome/browser/net/connect_interceptor.h"
-#include "chrome/browser/net/load_time_stats.h"
+#include "chrome/browser/net/safe_search_util.h"
 #include "chrome/browser/performance_monitor/performance_monitor.h"
+#include "chrome/browser/prerender/prerender_tracker.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/task_manager/task_manager.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
+#include "components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.h"
+#include "components/data_reduction_proxy/browser/data_reduction_proxy_metrics.h"
+#include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h"
+#include "components/data_reduction_proxy/browser/data_reduction_proxy_protocol.h"
+#include "components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.h"
+#include "components/domain_reliability/monitor.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/resource_request_info.h"
-#include "extensions/common/constants.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_log.h"
 #include "net/cookies/cookie_options.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
+#include "net/proxy/proxy_config.h"
+#include "net/proxy/proxy_info.h"
+#include "net/proxy/proxy_retry_info.h"
+#include "net/proxy/proxy_server.h"
 #include "net/socket_stream/socket_stream.h"
 #include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+
+#if defined(OS_ANDROID)
+#include "chrome/browser/io_thread.h"
+#include "components/precache/content/precache_manager.h"
+#include "components/precache/content/precache_manager_factory.h"
+#endif
 
 #if defined(OS_CHROMEOS)
 #include "base/command_line.h"
 #endif
 
 #if defined(ENABLE_CONFIGURATION_POLICY)
-#include "chrome/browser/policy/url_blacklist_manager.h"
+#include "components/policy/core/browser/url_blacklist_manager.h"
+#endif
+
+#if defined(ENABLE_EXTENSIONS)
+#include "extensions/common/constants.h"
 #endif
 
 using content::BrowserThread;
 using content::RenderViewHost;
 using content::ResourceRequestInfo;
+using content::ResourceType;
 
 // By default we don't allow access to all file:// urls on ChromeOS and
 // Android.
@@ -74,85 +88,16 @@ bool ChromeNetworkDelegate::g_allow_file_access_ = false;
 bool ChromeNetworkDelegate::g_allow_file_access_ = true;
 #endif
 
+#if defined(ENABLE_EXTENSIONS)
 // This remains false unless the --disable-extensions-http-throttling
 // flag is passed to the browser.
 bool ChromeNetworkDelegate::g_never_throttle_requests_ = false;
+#endif
 
 namespace {
 
 const char kDNTHeader[] = "DNT";
 
-// If the |request| failed due to problems with a proxy, forward the error to
-// the proxy extension API.
-void ForwardProxyErrors(net::URLRequest* request,
-                        extensions::EventRouterForwarder* event_router,
-                        void* profile) {
-  if (request->status().status() == net::URLRequestStatus::FAILED) {
-    switch (request->status().error()) {
-      case net::ERR_PROXY_AUTH_UNSUPPORTED:
-      case net::ERR_PROXY_CONNECTION_FAILED:
-      case net::ERR_TUNNEL_CONNECTION_FAILED:
-        extensions::ProxyEventRouter::GetInstance()->OnProxyError(
-            event_router, profile, request->status().error());
-    }
-  }
-}
-
-// Returns whether a URL parameter, |first_parameter| (e.g. foo=bar), has the
-// same key as the the |second_parameter| (e.g. foo=baz). Both parameters
-// must be in key=value form.
-bool HasSameParameterKey(const std::string& first_parameter,
-                         const std::string& second_parameter) {
-  DCHECK(second_parameter.find("=") != std::string::npos);
-  // Prefix for "foo=bar" is "foo=".
-  std::string parameter_prefix = second_parameter.substr(
-      0, second_parameter.find("=") + 1);
-  return StartsWithASCII(first_parameter, parameter_prefix, false);
-}
-
-// Examines the query string containing parameters and adds the necessary ones
-// so that SafeSearch is active. |query| is the string to examine and the
-// return value is the |query| string modified such that SafeSearch is active.
-std::string AddSafeSearchParameters(const std::string& query) {
-  std::vector<std::string> new_parameters;
-  std::string safe_parameter = chrome::kSafeSearchSafeParameter;
-  std::string ssui_parameter = chrome::kSafeSearchSsuiParameter;
-
-  std::vector<std::string> parameters;
-  base::SplitString(query, '&', &parameters);
-
-  std::vector<std::string>::iterator it;
-  for (it = parameters.begin(); it < parameters.end(); ++it) {
-    if (!HasSameParameterKey(*it, safe_parameter) &&
-        !HasSameParameterKey(*it, ssui_parameter)) {
-      new_parameters.push_back(*it);
-    }
-  }
-
-  new_parameters.push_back(safe_parameter);
-  new_parameters.push_back(ssui_parameter);
-  return JoinString(new_parameters, '&');
-}
-
-// If |request| is a request to Google Web Search the function
-// enforces that the SafeSearch query parameters are set to active.
-// Sets the query part of |new_url| with the new value of the parameters.
-void ForceGoogleSafeSearch(net::URLRequest* request,
-                           GURL* new_url) {
-  if (!google_util::IsGoogleSearchUrl(request->url()) &&
-      !google_util::IsGoogleHomePageUrl(request->url()))
-    return;
-
-  std::string query = request->url().query();
-  std::string new_query = AddSafeSearchParameters(query);
-  if (query == new_query)
-    return;
-
-  GURL::Replacements replacements;
-  replacements.SetQueryStr(new_query);
-  *new_url = request->url().ReplaceComponents(replacements);
-}
-
 // Gets called when the extensions finish work on the URL. If the extensions
 // did not do a redirect (so |new_url| is empty) then we enforce the
 // SafeSearch parameters. Otherwise we will get called again after the
@@ -163,61 +108,15 @@ void ForceGoogleSafeSearchCallbackWrapper(
     GURL* new_url,
     int rv) {
   if (rv == net::OK && new_url->is_empty())
-    ForceGoogleSafeSearch(request, new_url);
+    safe_search_util::ForceGoogleSafeSearch(request, new_url);
   callback.Run(rv);
 }
 
-enum RequestStatus { REQUEST_STARTED, REQUEST_DONE };
-
-// Notifies the ExtensionProcessManager that a request has started or stopped
-// for a particular RenderView.
-void NotifyEPMRequestStatus(RequestStatus status,
-                            void* profile_id,
-                            int process_id,
-                            int render_view_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  Profile* profile = reinterpret_cast<Profile*>(profile_id);
-  if (!g_browser_process->profile_manager()->IsValidProfile(profile))
-    return;
-
-  ExtensionProcessManager* extension_process_manager =
-      extensions::ExtensionSystem::Get(profile)->process_manager();
-  // This may be NULL in unit tests.
-  if (!extension_process_manager)
-    return;
-
-  // Will be NULL if the request was not issued on behalf of a renderer (e.g. a
-  // system-level request).
-  RenderViewHost* render_view_host =
-      RenderViewHost::FromID(process_id, render_view_id);
-  if (render_view_host) {
-    if (status == REQUEST_STARTED) {
-      extension_process_manager->OnNetworkRequestStarted(render_view_host);
-    } else if (status == REQUEST_DONE) {
-      extension_process_manager->OnNetworkRequestDone(render_view_host);
-    } else {
-      NOTREACHED();
-    }
-  }
-}
-
-void ForwardRequestStatus(
-    RequestStatus status, net::URLRequest* request, void* profile_id) {
-  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
-  if (!info)
-    return;
-
-  int process_id, render_view_id;
-  if (info->GetAssociatedRenderView(&process_id, &render_view_id)) {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-        base::Bind(&NotifyEPMRequestStatus,
-                   status, profile_id, process_id, render_view_id));
-  }
-}
-
-void UpdateContentLengthPrefs(int received_content_length,
-                              int original_content_length,
-                              bool via_data_reduction_proxy) {
+void UpdateContentLengthPrefs(
+    int received_content_length,
+    int original_content_length,
+    data_reduction_proxy::DataReductionProxyRequestType request_type,
+    Profile* profile) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK_GE(received_content_length, 0);
   DCHECK_GE(original_content_length, 0);
@@ -230,35 +129,42 @@ void UpdateContentLengthPrefs(int received_content_length,
   if (!prefs)
     return;
 
-#if defined(OS_ANDROID)
+  // Ignore off-the-record data.
+  if (!g_browser_process->profile_manager()->IsValidProfile(profile) ||
+      profile->IsOffTheRecord()) {
+    return;
+  }
+#if defined(OS_ANDROID) && defined(SPDY_PROXY_AUTH_ORIGIN)
+  // If Android ever goes multi profile, the profile should be passed so that
+  // the browser preference will be taken.
   bool with_data_reduction_proxy_enabled =
-      g_browser_process->profile_manager()->GetDefaultProfile()->
-      GetPrefs()->GetBoolean(prefs::kSpdyProxyAuthEnabled);
+      ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
+          data_reduction_proxy::prefs::kDataReductionProxyEnabled);
 #else
   bool with_data_reduction_proxy_enabled = false;
 #endif
 
-  chrome_browser_net::UpdateContentLengthPrefs(
-      received_content_length,
-      original_content_length,
-      with_data_reduction_proxy_enabled,
-      via_data_reduction_proxy, prefs);
+  data_reduction_proxy::UpdateContentLengthPrefs(received_content_length,
+                                         original_content_length,
+                                         with_data_reduction_proxy_enabled,
+                                         request_type, prefs);
 }
 
-void StoreAccumulatedContentLength(int received_content_length,
-                                   int original_content_length,
-                                   bool data_reduction_proxy_was_used) {
+void StoreAccumulatedContentLength(
+    int received_content_length,
+    int original_content_length,
+    data_reduction_proxy::DataReductionProxyRequestType request_type,
+    Profile* profile) {
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
       base::Bind(&UpdateContentLengthPrefs,
                  received_content_length, original_content_length,
-                 data_reduction_proxy_was_used));
+                 request_type, profile));
 }
 
 void RecordContentLengthHistograms(
     int64 received_content_length,
     int64 original_content_length,
     const base::TimeDelta& freshness_lifetime) {
-#if defined(OS_ANDROID)
   // Add the current resource to these histograms only when a valid
   // X-Original-Content-Length header is present.
   if (original_content_length >= 0) {
@@ -296,32 +202,74 @@ void RecordContentLengthHistograms(
     return;
   UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable24Hours",
                        received_content_length);
-#endif  // defined(OS_ANDROID)
 }
 
+#if defined(OS_ANDROID)
+void RecordPrecacheStatsOnUIThread(const GURL& url,
+                                   const base::Time& fetch_time, int64 size,
+                                   bool was_cached, void* profile_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  Profile* profile = reinterpret_cast<Profile*>(profile_id);
+  if (!g_browser_process->profile_manager()->IsValidProfile(profile)) {
+    return;
+  }
+
+  precache::PrecacheManager* precache_manager =
+      precache::PrecacheManagerFactory::GetForBrowserContext(profile);
+  if (!precache_manager) {
+    // This could be NULL if the profile is off the record.
+    return;
+  }
+
+  precache_manager->RecordStatsForFetch(url, fetch_time, size, was_cached);
+}
+
+void RecordIOThreadToRequestStartOnUIThread(
+    const base::TimeTicks& request_start) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  base::TimeDelta request_lag = request_start -
+      g_browser_process->io_thread()->creation_time();
+  UMA_HISTOGRAM_TIMES("Net.IOThreadCreationToHTTPRequestStart", request_lag);
+}
+#endif  // defined(OS_ANDROID)
+
 }  // namespace
 
 ChromeNetworkDelegate::ChromeNetworkDelegate(
     extensions::EventRouterForwarder* event_router,
     BooleanPrefMember* enable_referrers)
-    : event_router_(event_router),
-      profile_(NULL),
+    : profile_(NULL),
       enable_referrers_(enable_referrers),
       enable_do_not_track_(NULL),
       force_google_safe_search_(NULL),
+      data_reduction_proxy_enabled_(NULL),
+#if defined(ENABLE_CONFIGURATION_POLICY)
       url_blacklist_manager_(NULL),
-      load_time_stats_(NULL),
+#endif
+      domain_reliability_monitor_(NULL),
       received_content_length_(0),
-      original_content_length_(0) {
-  DCHECK(event_router);
+      original_content_length_(0),
+      first_request_(true),
+      prerender_tracker_(NULL),
+      data_reduction_proxy_params_(NULL),
+      data_reduction_proxy_usage_stats_(NULL),
+      data_reduction_proxy_auth_request_handler_(NULL) {
   DCHECK(enable_referrers);
+  extensions_delegate_.reset(
+      ChromeExtensionsNetworkDelegate::Create(event_router));
 }
 
 ChromeNetworkDelegate::~ChromeNetworkDelegate() {}
 
 void ChromeNetworkDelegate::set_extension_info_map(
-    ExtensionInfoMap* extension_info_map) {
-  extension_info_map_ = extension_info_map;
+    extensions::InfoMap* extension_info_map) {
+  extensions_delegate_->set_extension_info_map(extension_info_map);
+}
+
+void ChromeNetworkDelegate::set_profile(void* profile) {
+  profile_ = profile;
+  extensions_delegate_->set_profile(profile);
 }
 
 void ChromeNetworkDelegate::set_cookie_settings(
@@ -341,9 +289,11 @@ void ChromeNetworkDelegate::SetEnableClientHints() {
 }
 
 // static
+#if defined(ENABLE_EXTENSIONS)
 void ChromeNetworkDelegate::NeverThrottleRequests() {
   g_never_throttle_requests_ = true;
 }
+#endif
 
 // static
 void ChromeNetworkDelegate::InitializePrefsOnUIThread(
@@ -373,13 +323,15 @@ void ChromeNetworkDelegate::AllowAccessToAllFiles() {
 }
 
 // static
-Value* ChromeNetworkDelegate::HistoricNetworkStatsInfoToValue() {
+base::Value* ChromeNetworkDelegate::HistoricNetworkStatsInfoToValue() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   PrefService* prefs = g_browser_process->local_state();
-  int64 total_received = prefs->GetInt64(prefs::kHttpReceivedContentLength);
-  int64 total_original = prefs->GetInt64(prefs::kHttpOriginalContentLength);
+  int64 total_received = prefs->GetInt64(
+      data_reduction_proxy::prefs::kHttpReceivedContentLength);
+  int64 total_original = prefs->GetInt64(
+      data_reduction_proxy::prefs::kHttpOriginalContentLength);
 
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   // Use strings to avoid overflow.  base::Value only supports 32-bit integers.
   dict->SetString("historic_received_content_length",
                   base::Int64ToString(total_received));
@@ -388,8 +340,8 @@ Value* ChromeNetworkDelegate::HistoricNetworkStatsInfoToValue() {
   return dict;
 }
 
-Value* ChromeNetworkDelegate::SessionNetworkStatsInfoToValue() const {
-  DictionaryValue* dict = new DictionaryValue();
+base::Value* ChromeNetworkDelegate::SessionNetworkStatsInfoToValue() const {
+  base::DictionaryValue* dict = new base::DictionaryValue();
   // Use strings to avoid overflow.  base::Value only supports 32-bit integers.
   dict->SetString("session_received_content_length",
                   base::Int64ToString(received_content_length_));
@@ -402,22 +354,45 @@ int ChromeNetworkDelegate::OnBeforeURLRequest(
     net::URLRequest* request,
     const net::CompletionCallback& callback,
     GURL* new_url) {
+#if defined(OS_ANDROID)
+  // This UMA tracks the time to the first user-initiated request start, so
+  // only non-null profiles are considered.
+  if (first_request_ && profile_) {
+    bool record_timing = true;
+    if (data_reduction_proxy_params_) {
+      record_timing =
+          (request->url() != data_reduction_proxy_params_->probe_url()) &&
+          (request->url() != data_reduction_proxy_params_->warmup_url());
+    }
+    if (record_timing) {
+      first_request_ = false;
+      net::LoadTimingInfo timing_info;
+      request->GetLoadTimingInfo(&timing_info);
+      BrowserThread::PostTask(
+          BrowserThread::UI, FROM_HERE,
+          base::Bind(&RecordIOThreadToRequestStartOnUIThread,
+                     timing_info.request_start));
+    }
+  }
+#endif  // defined(OS_ANDROID)
+
 #if defined(ENABLE_CONFIGURATION_POLICY)
   // TODO(joaodasilva): This prevents extensions from seeing URLs that are
   // blocked. However, an extension might redirect the request to another URL,
   // which is not blocked.
+  int error = net::ERR_BLOCKED_BY_ADMINISTRATOR;
   if (url_blacklist_manager_ &&
-      url_blacklist_manager_->IsRequestBlocked(*request)) {
+      url_blacklist_manager_->IsRequestBlocked(*request, &error)) {
     // URL access blocked by policy.
     request->net_log().AddEvent(
         net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST,
         net::NetLog::StringCallback("url",
                                     &request->url().possibly_invalid_spec()));
-    return net::ERR_BLOCKED_BY_ADMINISTRATOR;
+    return error;
   }
 #endif
 
-  ForwardRequestStatus(REQUEST_STARTED, request, profile_);
+  extensions_delegate_->ForwardStartRequestStatus(request);
 
   if (!enable_referrers_->GetValue())
     request->SetReferrer(std::string());
@@ -441,12 +416,11 @@ int ChromeNetworkDelegate::OnBeforeURLRequest(
                                   base::Unretained(new_url));
   }
 
-  int rv = ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
-      profile_, extension_info_map_.get(), request, wrapped_callback,
-      new_url);
+  int rv = extensions_delegate_->OnBeforeURLRequest(
+      request, wrapped_callback, new_url);
 
   if (force_safe_search && rv == net::OK && new_url->is_empty())
-    ForceGoogleSafeSearch(request, new_url);
+    safe_search_util::ForceGoogleSafeSearch(request, new_url);
 
   if (connect_interceptor_)
     connect_interceptor_->WitnessURLRequest(request);
@@ -454,44 +428,94 @@ int ChromeNetworkDelegate::OnBeforeURLRequest(
   return rv;
 }
 
+void ChromeNetworkDelegate::OnResolveProxy(
+    const GURL& url,
+    int load_flags,
+    const net::ProxyService& proxy_service,
+    net::ProxyInfo* result) {
+  if (!on_resolve_proxy_handler_.is_null() &&
+      !proxy_config_getter_.is_null()) {
+    on_resolve_proxy_handler_.Run(url, load_flags,
+                                  proxy_config_getter_.Run(),
+                                  proxy_service.proxy_retry_info(),
+                                  data_reduction_proxy_params_, result);
+  }
+}
+
+void ChromeNetworkDelegate::OnProxyFallback(const net::ProxyServer& bad_proxy,
+                                            int net_error) {
+  if (data_reduction_proxy_usage_stats_) {
+    data_reduction_proxy_usage_stats_->OnProxyFallback(
+        bad_proxy, net_error);
+  }
+}
+
 int ChromeNetworkDelegate::OnBeforeSendHeaders(
     net::URLRequest* request,
     const net::CompletionCallback& callback,
     net::HttpRequestHeaders* headers) {
+  bool force_safe_search = force_google_safe_search_ &&
+                           force_google_safe_search_->GetValue();
+  if (force_safe_search)
+    safe_search_util::ForceYouTubeSafetyMode(request, headers);
+
   TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request, "SendRequest");
-  return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
-      profile_, extension_info_map_.get(), request, callback, headers);
+  return extensions_delegate_->OnBeforeSendHeaders(request, callback, headers);
+}
+
+void ChromeNetworkDelegate::OnBeforeSendProxyHeaders(
+    net::URLRequest* request,
+    const net::ProxyInfo& proxy_info,
+    net::HttpRequestHeaders* headers) {
+  if (data_reduction_proxy_auth_request_handler_) {
+    data_reduction_proxy_auth_request_handler_->MaybeAddRequestHeader(
+        request, proxy_info.proxy_server(), headers);
+  }
 }
 
 void ChromeNetworkDelegate::OnSendHeaders(
     net::URLRequest* request,
     const net::HttpRequestHeaders& headers) {
-  ExtensionWebRequestEventRouter::GetInstance()->OnSendHeaders(
-      profile_, extension_info_map_.get(), request, headers);
+  extensions_delegate_->OnSendHeaders(request, headers);
 }
 
 int ChromeNetworkDelegate::OnHeadersReceived(
     net::URLRequest* request,
     const net::CompletionCallback& callback,
     const net::HttpResponseHeaders* original_response_headers,
-    scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
-  return ExtensionWebRequestEventRouter::GetInstance()->OnHeadersReceived(
-      profile_, extension_info_map_.get(), request, callback,
-      original_response_headers, override_response_headers);
+    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
+  data_reduction_proxy::DataReductionProxyBypassType bypass_type;
+  if (data_reduction_proxy::MaybeBypassProxyAndPrepareToRetry(
+      data_reduction_proxy_params_,
+      request,
+      original_response_headers,
+      override_response_headers,
+      &bypass_type)) {
+    if (data_reduction_proxy_usage_stats_)
+      data_reduction_proxy_usage_stats_->SetBypassType(bypass_type);
+    return net::OK;
+  }
+
+  return extensions_delegate_->OnHeadersReceived(
+      request,
+      callback,
+      original_response_headers,
+      override_response_headers,
+      allowed_unsafe_redirect_url);
 }
 
 void ChromeNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
                                              const GURL& new_location) {
-  ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRedirect(
-      profile_, extension_info_map_.get(), request, new_location);
+  if (domain_reliability_monitor_)
+    domain_reliability_monitor_->OnBeforeRedirect(request);
+  extensions_delegate_->OnBeforeRedirect(request, new_location);
 }
 
 
 void ChromeNetworkDelegate::OnResponseStarted(net::URLRequest* request) {
   TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request, "ResponseStarted");
-  ExtensionWebRequestEventRouter::GetInstance()->OnResponseStarted(
-      profile_, extension_info_map_.get(), request);
-  ForwardProxyErrors(request, event_router_.get(), profile_);
+  extensions_delegate_->OnResponseStarted(request);
 }
 
 void ChromeNetworkDelegate::OnRawBytesRead(const net::URLRequest& request,
@@ -502,12 +526,18 @@ void ChromeNetworkDelegate::OnRawBytesRead(const net::URLRequest& request,
       request, bytes_read);
 
 #if defined(ENABLE_TASK_MANAGER)
-  TaskManager::GetInstance()->model()->NotifyBytesRead(request, bytes_read);
+  // This is not completely accurate, but as a first approximation ignore
+  // requests that are served from the cache. See bug 330931 for more info.
+  if (!request.was_cached())
+    TaskManager::GetInstance()->model()->NotifyBytesRead(request, bytes_read);
 #endif  // defined(ENABLE_TASK_MANAGER)
 }
 
 void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request,
                                         bool started) {
+  if (data_reduction_proxy_usage_stats_)
+    data_reduction_proxy_usage_stats_->OnUrlRequestCompleted(request, started);
+
   TRACE_EVENT_ASYNC_END0("net", "URLRequest", request);
   if (request->status().status() == net::URLRequestStatus::SUCCESS) {
     // For better accuracy, we use the actual bytes read instead of the length
@@ -515,6 +545,18 @@ void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request,
     // or missing, as is the case with chunked encoding.
     int64 received_content_length = request->received_response_content_length();
 
+#if defined(OS_ANDROID)
+    if (precache::PrecacheManager::IsPrecachingEnabled()) {
+      // Record precache metrics when a fetch is completed successfully, if
+      // precaching is enabled.
+      BrowserThread::PostTask(
+          BrowserThread::UI, FROM_HERE,
+          base::Bind(&RecordPrecacheStatsOnUIThread, request->url(),
+                     base::Time::Now(), received_content_length,
+                     request->was_cached(), profile_));
+    }
+#endif  // defined(OS_ANDROID)
+
     // Only record for http or https urls.
     bool is_http = request->url().SchemeIs("http");
     bool is_https = request->url().SchemeIs("https");
@@ -525,60 +567,56 @@ void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request,
       int64 original_content_length =
           request->response_info().headers->GetInt64HeaderValue(
               "x-original-content-length");
-      bool via_data_reduction_proxy =
-          request->response_info().headers->HasHeaderValue(
-              "via", "1.1 Chrome Compression Proxy");
-
-      // Since there was no indication of the original content length, presume
-      // it is no different from the number of bytes read.
-      int64 adjusted_original_content_length = original_content_length;
-      if (adjusted_original_content_length == -1)
-        adjusted_original_content_length = received_content_length;
+      data_reduction_proxy::DataReductionProxyRequestType request_type =
+          data_reduction_proxy::GetDataReductionProxyRequestType(request);
+
       base::TimeDelta freshness_lifetime =
           request->response_info().headers->GetFreshnessLifetime(
               request->response_info().response_time);
+      int64 adjusted_original_content_length =
+          data_reduction_proxy::GetAdjustedOriginalContentLength(
+              request_type, original_content_length,
+              received_content_length);
       AccumulateContentLength(received_content_length,
                               adjusted_original_content_length,
-                              via_data_reduction_proxy);
+                              request_type);
       RecordContentLengthHistograms(received_content_length,
                                     original_content_length,
                                     freshness_lifetime);
+      if (data_reduction_proxy_enabled_ &&
+          data_reduction_proxy_usage_stats_ &&
+          !proxy_config_getter_.is_null()) {
+        data_reduction_proxy_usage_stats_->RecordBypassedBytesHistograms(
+            *request,
+            *data_reduction_proxy_enabled_,
+            proxy_config_getter_.Run());
+      }
       DVLOG(2) << __FUNCTION__
           << " received content length: " << received_content_length
           << " original content length: " << original_content_length
           << " url: " << request->url();
     }
 
-    bool is_redirect = request->response_headers() &&
-        net::HttpResponseHeaders::IsRedirectResponseCode(
-            request->response_headers()->response_code());
-    if (!is_redirect) {
-      ExtensionWebRequestEventRouter::GetInstance()->OnCompleted(
-          profile_, extension_info_map_.get(), request);
-    }
+    extensions_delegate_->OnCompleted(request, started);
   } else if (request->status().status() == net::URLRequestStatus::FAILED ||
              request->status().status() == net::URLRequestStatus::CANCELED) {
-    ExtensionWebRequestEventRouter::GetInstance()->OnErrorOccurred(
-            profile_, extension_info_map_.get(), request, started);
+    extensions_delegate_->OnCompleted(request, started);
   } else {
     NOTREACHED();
   }
-  ForwardProxyErrors(request, event_router_.get(), profile_);
-
-  ForwardRequestStatus(REQUEST_DONE, request, profile_);
+  if (domain_reliability_monitor_)
+    domain_reliability_monitor_->OnCompleted(request, started);
+  extensions_delegate_->ForwardProxyErrors(request);
+  extensions_delegate_->ForwardDoneRequestStatus(request);
 }
 
 void ChromeNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {
-  ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestDestroyed(
-      profile_, request);
-  if (load_time_stats_)
-    load_time_stats_->OnURLRequestDestroyed(*request);
+  extensions_delegate_->OnURLRequestDestroyed(request);
 }
 
 void ChromeNetworkDelegate::OnPACScriptError(int line_number,
-                                             const string16& error) {
-  extensions::ProxyEventRouter::GetInstance()->OnPACScriptError(
-      event_router_.get(), profile_, line_number, error);
+                                             const base::string16& error) {
+  extensions_delegate_->OnPACScriptError(line_number, error);
 }
 
 net::NetworkDelegate::AuthRequiredResponse
@@ -587,9 +625,8 @@ ChromeNetworkDelegate::OnAuthRequired(
     const net::AuthChallengeInfo& auth_info,
     const AuthCallback& callback,
     net::AuthCredentials* credentials) {
-  return ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired(
-      profile_, extension_info_map_.get(), request, auth_info,
-      callback, credentials);
+  return extensions_delegate_->OnAuthRequired(
+      request, auth_info, callback, credentials);
 }
 
 bool ChromeNetworkDelegate::OnCanGetCookies(
@@ -603,15 +640,28 @@ bool ChromeNetworkDelegate::OnCanGetCookies(
       request.url(), request.first_party_for_cookies());
 
   int render_process_id = -1;
-  int render_view_id = -1;
-  if (content::ResourceRequestInfo::GetRenderViewForRequest(
-          &request, &render_process_id, &render_view_id)) {
+  int render_frame_id = -1;
+
+  // |is_for_blocking_resource| indicates whether the cookies read were for a
+  // blocking resource (eg script, css). It is only temporarily added for
+  // diagnostic purposes, per bug 353678. Will be removed again once data
+  // collection is finished.
+  bool is_for_blocking_resource = false;
+  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(&request);
+  if (info && ((!info->IsAsync()) ||
+               info->GetResourceType() == content::RESOURCE_TYPE_STYLESHEET ||
+               info->GetResourceType() == content::RESOURCE_TYPE_SCRIPT)) {
+    is_for_blocking_resource = true;
+  }
+
+  if (content::ResourceRequestInfo::GetRenderFrameForRequest(
+          &request, &render_process_id, &render_frame_id)) {
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
         base::Bind(&TabSpecificContentSettings::CookiesRead,
-                   render_process_id, render_view_id,
+                   render_process_id, render_frame_id,
                    request.url(), request.first_party_for_cookies(),
-                   cookie_list, !allow));
+                   cookie_list, !allow, is_for_blocking_resource));
   }
 
   return allow;
@@ -628,17 +678,24 @@ bool ChromeNetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
       request.url(), request.first_party_for_cookies());
 
   int render_process_id = -1;
-  int render_view_id = -1;
-  if (content::ResourceRequestInfo::GetRenderViewForRequest(
-          &request, &render_process_id, &render_view_id)) {
+  int render_frame_id = -1;
+  if (content::ResourceRequestInfo::GetRenderFrameForRequest(
+          &request, &render_process_id, &render_frame_id)) {
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
         base::Bind(&TabSpecificContentSettings::CookieChanged,
-                   render_process_id, render_view_id,
+                   render_process_id, render_frame_id,
                    request.url(), request.first_party_for_cookies(),
                    cookie_line, *options, !allow));
   }
 
+  if (prerender_tracker_) {
+    prerender_tracker_->OnCookieChangedForURL(
+        render_process_id,
+        request.context()->cookie_store()->GetCookieMonster(),
+        request.url());
+  }
+
   return allow;
 }
 
@@ -663,6 +720,7 @@ bool ChromeNetworkDelegate::OnCanAccessFile(const net::URLRequest& request,
   static const char* const kLocalAccessWhiteList[] = {
       "/home/chronos/user/Downloads",
       "/home/chronos/user/log",
+      "/home/chronos/user/WebRTC Logs",
       "/media",
       "/opt/oem",
       "/usr/share/chromeos-assets",
@@ -670,15 +728,20 @@ bool ChromeNetworkDelegate::OnCanAccessFile(const net::URLRequest& request,
       "/var/log",
   };
 
-  // The actual location of "/home/chronos/user/Downloads" is the Downloads
-  // directory under the profile path ("/home/chronos/user' is a hard link to
-  // current primary logged in profile.) For the support of multi-profile
-  // sessions, we are switching to use explicit "$PROFILE_PATH/Downloads" path
-  // and here whitelist such access.
+  // The actual location of "/home/chronos/user/Xyz" is the Xyz directory under
+  // the profile path ("/home/chronos/user' is a hard link to current primary
+  // logged in profile.) For the support of multi-profile sessions, we are
+  // switching to use explicit "$PROFILE_PATH/Xyz" path and here whitelist such
+  // access.
   if (!profile_path_.empty()) {
     const base::FilePath downloads = profile_path_.AppendASCII("Downloads");
     if (downloads == path.StripTrailingSeparators() || downloads.IsParent(path))
       return true;
+    const base::FilePath webrtc_logs = profile_path_.AppendASCII("WebRTC Logs");
+    if (webrtc_logs == path.StripTrailingSeparators() ||
+        webrtc_logs.IsParent(path)) {
+      return true;
+    }
   }
 #elif defined(OS_ANDROID)
   // Access to files in external storage is allowed.
@@ -710,12 +773,14 @@ bool ChromeNetworkDelegate::OnCanAccessFile(const net::URLRequest& request,
 
 bool ChromeNetworkDelegate::OnCanThrottleRequest(
     const net::URLRequest& request) const {
-  if (g_never_throttle_requests_) {
+#if defined(ENABLE_EXTENSIONS)
+  if (g_never_throttle_requests_)
     return false;
-  }
-
   return request.first_party_for_cookies().scheme() ==
       extensions::kExtensionScheme;
+#else
+  return false;
+#endif
 }
 
 bool ChromeNetworkDelegate::OnCanEnablePrivacyMode(
@@ -750,21 +815,16 @@ int ChromeNetworkDelegate::OnBeforeSocketStreamConnect(
   return net::OK;
 }
 
-void ChromeNetworkDelegate::OnRequestWaitStateChange(
-    const net::URLRequest& request,
-    RequestWaitState state) {
-  if (load_time_stats_)
-    load_time_stats_->OnRequestWaitStateChange(request, state);
-}
-
 void ChromeNetworkDelegate::AccumulateContentLength(
-    int64 received_content_length, int64 original_content_length,
-    bool via_data_reduction_proxy) {
+    int64 received_content_length,
+    int64 original_content_length,
+    data_reduction_proxy::DataReductionProxyRequestType request_type) {
   DCHECK_GE(received_content_length, 0);
   DCHECK_GE(original_content_length, 0);
   StoreAccumulatedContentLength(received_content_length,
                                 original_content_length,
-                                via_data_reduction_proxy);
+                                request_type,
+                                reinterpret_cast<Profile*>(profile_));
   received_content_length_ += received_content_length;
   original_content_length_ += original_content_length;
 }