blob: 043f7898f5522e5eb4db11e2f96737a55d3efc38 [file] [log] [blame]
[email protected]9045b8822012-01-13 20:35:351// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ac039522010-06-15 16:39:442// 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 "base/logging.h"
[email protected]6baff0b52012-03-06 01:30:188#include "chrome/browser/browser_process.h"
[email protected]8523ba52011-05-22 19:00:589#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
[email protected]6e672df2012-01-25 10:39:4710#include "chrome/browser/extensions/api/webrequest/webrequest_api.h"
[email protected]3ce02412011-03-01 12:01:1511#include "chrome/browser/extensions/extension_event_router_forwarder.h"
[email protected]c357acb42011-06-09 20:52:4212#include "chrome/browser/extensions/extension_info_map.h"
[email protected]6baff0b52012-03-06 01:30:1813#include "chrome/browser/extensions/extension_process_manager.h"
[email protected]8202d0c2011-02-23 08:31:1414#include "chrome/browser/extensions/extension_proxy_api.h"
[email protected]0a8db0d2011-04-13 15:15:4015#include "chrome/browser/prefs/pref_member.h"
[email protected]6baff0b52012-03-06 01:30:1816#include "chrome/browser/profiles/profile_manager.h"
[email protected]8523ba52011-05-22 19:00:5817#include "chrome/browser/task_manager/task_manager.h"
[email protected]0a8db0d2011-04-13 15:15:4018#include "chrome/common/pref_names.h"
[email protected]6baff0b52012-03-06 01:30:1819#include "content/browser/renderer_host/render_view_host.h"
20#include "content/browser/renderer_host/resource_dispatcher_host.h"
[email protected]c38831a12011-10-28 12:44:4921#include "content/public/browser/browser_thread.h"
[email protected]82b42302011-04-20 16:28:1622#include "net/base/host_port_pair.h"
[email protected]8202d0c2011-02-23 08:31:1423#include "net/base/net_errors.h"
[email protected]6a5f77c32011-09-04 19:19:5924#include "net/base/net_log.h"
[email protected]ac039522010-06-15 16:39:4425#include "net/http/http_request_headers.h"
[email protected]48944382011-04-23 13:28:1626#include "net/http/http_response_headers.h"
[email protected]d05ef99c2011-02-01 21:38:1627#include "net/url_request/url_request.h"
28
[email protected]3e598ff12011-09-06 11:22:3429#if defined(ENABLE_CONFIGURATION_POLICY)
30#include "chrome/browser/policy/url_blacklist_manager.h"
31#endif
32
[email protected]631bb742011-11-02 11:29:3933using content::BrowserThread;
34
[email protected]d05ef99c2011-02-01 21:38:1635namespace {
36
[email protected]8202d0c2011-02-23 08:31:1437// If the |request| failed due to problems with a proxy, forward the error to
38// the proxy extension API.
[email protected]0651b812011-02-24 00:22:5039void ForwardProxyErrors(net::URLRequest* request,
[email protected]3ce02412011-03-01 12:01:1540 ExtensionEventRouterForwarder* event_router,
[email protected]673514522011-07-13 18:17:1841 void* profile) {
[email protected]8202d0c2011-02-23 08:31:1442 if (request->status().status() == net::URLRequestStatus::FAILED) {
[email protected]d0cc35b2011-09-08 12:02:0543 switch (request->status().error()) {
[email protected]8202d0c2011-02-23 08:31:1444 case net::ERR_PROXY_AUTH_UNSUPPORTED:
45 case net::ERR_PROXY_CONNECTION_FAILED:
46 case net::ERR_TUNNEL_CONNECTION_FAILED:
47 ExtensionProxyEventRouter::GetInstance()->OnProxyError(
[email protected]d0cc35b2011-09-08 12:02:0548 event_router, profile, request->status().error());
[email protected]8202d0c2011-02-23 08:31:1449 }
50 }
51}
52
[email protected]6baff0b52012-03-06 01:30:1853enum RequestStatus { REQUEST_STARTED, REQUEST_DONE };
54
55// Notifies the ExtensionProcessManager that a request has started or stopped
56// for a particular RenderView.
57void NotifyEPMRequestStatus(RequestStatus status,
58 void* profile_id,
59 int process_id,
60 int render_view_id) {
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
62 Profile* profile = reinterpret_cast<Profile*>(profile_id);
63 if (!g_browser_process->profile_manager()->IsValidProfile(profile))
64 return;
65
66 RenderViewHost* render_view_host =
67 RenderViewHost::FromID(process_id, render_view_id);
68 // Will be NULL if the request was not issued on behalf of a renderer (e.g. a
69 // system-level request).
70 if (render_view_host) {
71 if (status == REQUEST_STARTED) {
72 profile->GetExtensionProcessManager()->OnNetworkRequestStarted(
73 render_view_host);
74 } else if (status == REQUEST_DONE) {
75 profile->GetExtensionProcessManager()->OnNetworkRequestDone(
76 render_view_host);
77 } else {
78 NOTREACHED();
79 }
80 }
81}
82
83void ForwardRequestStatus(
84 RequestStatus status, net::URLRequest* request, void* profile_id) {
85 int process_id, render_view_id;
86 if (ResourceDispatcherHost::RenderViewForRequest(
87 request, &process_id, &render_view_id)) {
88 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
89 base::Bind(&NotifyEPMRequestStatus,
90 status, profile_id, process_id, render_view_id));
91 }
92}
93
[email protected]d05ef99c2011-02-01 21:38:1694} // namespace
[email protected]ac039522010-06-15 16:39:4495
[email protected]0651b812011-02-24 00:22:5096ChromeNetworkDelegate::ChromeNetworkDelegate(
[email protected]3ce02412011-03-01 12:01:1597 ExtensionEventRouterForwarder* event_router,
[email protected]c357acb42011-06-09 20:52:4298 ExtensionInfoMap* extension_info_map,
[email protected]6a5f77c32011-09-04 19:19:5999 const policy::URLBlacklistManager* url_blacklist_manager,
[email protected]673514522011-07-13 18:17:18100 void* profile,
[email protected]a8c1e7452011-05-14 06:17:07101 BooleanPrefMember* enable_referrers)
[email protected]3ce02412011-03-01 12:01:15102 : event_router_(event_router),
[email protected]673514522011-07-13 18:17:18103 profile_(profile),
[email protected]c357acb42011-06-09 20:52:42104 extension_info_map_(extension_info_map),
[email protected]6a5f77c32011-09-04 19:19:59105 enable_referrers_(enable_referrers),
106 url_blacklist_manager_(url_blacklist_manager) {
[email protected]4b50cb52011-03-10 00:29:37107 DCHECK(event_router);
[email protected]0a8db0d2011-04-13 15:15:40108 DCHECK(enable_referrers);
[email protected]0651b812011-02-24 00:22:50109}
110
[email protected]ac039522010-06-15 16:39:44111ChromeNetworkDelegate::~ChromeNetworkDelegate() {}
112
[email protected]0a8db0d2011-04-13 15:15:40113// static
114void ChromeNetworkDelegate::InitializeReferrersEnabled(
115 BooleanPrefMember* enable_referrers,
116 PrefService* pref_service) {
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
118 enable_referrers->Init(prefs::kEnableReferrers, pref_service, NULL);
119 enable_referrers->MoveToThread(BrowserThread::IO);
120}
121
[email protected]4875ba12011-03-30 22:31:51122int ChromeNetworkDelegate::OnBeforeURLRequest(
[email protected]4c76d7c2011-04-15 19:14:12123 net::URLRequest* request,
[email protected]084262c2011-12-01 21:12:47124 const net::CompletionCallback& callback,
[email protected]4c76d7c2011-04-15 19:14:12125 GURL* new_url) {
[email protected]3e598ff12011-09-06 11:22:34126#if defined(ENABLE_CONFIGURATION_POLICY)
[email protected]6a5f77c32011-09-04 19:19:59127 // TODO(joaodasilva): This prevents extensions from seeing URLs that are
128 // blocked. However, an extension might redirect the request to another URL,
129 // which is not blocked.
130 if (url_blacklist_manager_ &&
131 url_blacklist_manager_->IsURLBlocked(request->url())) {
132 // URL access blocked by policy.
133 scoped_refptr<net::NetLog::EventParameters> params;
134 params = new net::NetLogStringParameter("url", request->url().spec());
135 request->net_log().AddEvent(
136 net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST, params);
137 return net::ERR_NETWORK_ACCESS_DENIED;
138 }
[email protected]3e598ff12011-09-06 11:22:34139#endif
[email protected]6a5f77c32011-09-04 19:19:59140
[email protected]6baff0b52012-03-06 01:30:18141 ForwardRequestStatus(REQUEST_STARTED, request, profile_);
142
[email protected]0a8db0d2011-04-13 15:15:40143 if (!enable_referrers_->GetValue())
144 request->set_referrer(std::string());
[email protected]05cc4e72011-03-08 21:29:48145 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
[email protected]673514522011-07-13 18:17:18146 profile_, extension_info_map_.get(), request, callback, new_url);
[email protected]d05ef99c2011-02-01 21:38:16147}
148
[email protected]4875ba12011-03-30 22:31:51149int ChromeNetworkDelegate::OnBeforeSendHeaders(
[email protected]636eccd2011-06-28 12:28:01150 net::URLRequest* request,
[email protected]084262c2011-12-01 21:12:47151 const net::CompletionCallback& callback,
[email protected]4c76d7c2011-04-15 19:14:12152 net::HttpRequestHeaders* headers) {
[email protected]4875ba12011-03-30 22:31:51153 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
[email protected]673514522011-07-13 18:17:18154 profile_, extension_info_map_.get(), request, callback, headers);
[email protected]ac039522010-06-15 16:39:44155}
[email protected]8202d0c2011-02-23 08:31:14156
[email protected]5796dc942011-07-14 19:26:10157void ChromeNetworkDelegate::OnSendHeaders(
158 net::URLRequest* request,
[email protected]783573b2011-05-13 11:05:15159 const net::HttpRequestHeaders& headers) {
[email protected]5796dc942011-07-14 19:26:10160 ExtensionWebRequestEventRouter::GetInstance()->OnSendHeaders(
161 profile_, extension_info_map_.get(), request, headers);
[email protected]82b42302011-04-20 16:28:16162}
163
[email protected]ea8141e2011-10-05 13:12:51164int ChromeNetworkDelegate::OnHeadersReceived(
165 net::URLRequest* request,
[email protected]084262c2011-12-01 21:12:47166 const net::CompletionCallback& callback,
[email protected]ea8141e2011-10-05 13:12:51167 net::HttpResponseHeaders* original_response_headers,
168 scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
169 return ExtensionWebRequestEventRouter::GetInstance()->OnHeadersReceived(
170 profile_, extension_info_map_.get(), request, callback,
171 original_response_headers, override_response_headers);
172}
173
[email protected]31b2e5f2011-04-20 16:58:32174void ChromeNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
175 const GURL& new_location) {
176 ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRedirect(
[email protected]673514522011-07-13 18:17:18177 profile_, extension_info_map_.get(), request, new_location);
[email protected]31b2e5f2011-04-20 16:58:32178}
179
180
[email protected]8202d0c2011-02-23 08:31:14181void ChromeNetworkDelegate::OnResponseStarted(net::URLRequest* request) {
[email protected]62fecae2011-04-21 11:08:24182 ExtensionWebRequestEventRouter::GetInstance()->OnResponseStarted(
[email protected]673514522011-07-13 18:17:18183 profile_, extension_info_map_.get(), request);
184 ForwardProxyErrors(request, event_router_.get(), profile_);
[email protected]8202d0c2011-02-23 08:31:14185}
186
[email protected]8523ba52011-05-22 19:00:58187void ChromeNetworkDelegate::OnRawBytesRead(const net::URLRequest& request,
188 int bytes_read) {
189 TaskManager::GetInstance()->model()->NotifyBytesRead(request, bytes_read);
190}
191
[email protected]9045b8822012-01-13 20:35:35192void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request,
193 bool started) {
[email protected]a83dd332011-07-13 10:41:01194 if (request->status().status() == net::URLRequestStatus::SUCCESS ||
195 request->status().status() == net::URLRequestStatus::HANDLED_EXTERNALLY) {
[email protected]48944382011-04-23 13:28:16196 bool is_redirect = request->response_headers() &&
197 net::HttpResponseHeaders::IsRedirectResponseCode(
198 request->response_headers()->response_code());
199 if (!is_redirect) {
200 ExtensionWebRequestEventRouter::GetInstance()->OnCompleted(
[email protected]673514522011-07-13 18:17:18201 profile_, extension_info_map_.get(), request);
[email protected]48944382011-04-23 13:28:16202 }
[email protected]a83dd332011-07-13 10:41:01203 } else if (request->status().status() == net::URLRequestStatus::FAILED ||
204 request->status().status() == net::URLRequestStatus::CANCELED) {
[email protected]05b6ab42011-04-23 13:46:04205 ExtensionWebRequestEventRouter::GetInstance()->OnErrorOccurred(
[email protected]9045b8822012-01-13 20:35:35206 profile_, extension_info_map_.get(), request, started);
[email protected]a83dd332011-07-13 10:41:01207 } else {
208 NOTREACHED();
[email protected]48944382011-04-23 13:28:16209 }
[email protected]673514522011-07-13 18:17:18210 ForwardProxyErrors(request, event_router_.get(), profile_);
[email protected]6baff0b52012-03-06 01:30:18211
212 ForwardRequestStatus(REQUEST_DONE, request, profile_);
[email protected]8202d0c2011-02-23 08:31:14213}
[email protected]4b50cb52011-03-10 00:29:37214
[email protected]4875ba12011-03-30 22:31:51215void ChromeNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {
216 ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestDestroyed(
[email protected]673514522011-07-13 18:17:18217 profile_, request);
[email protected]4875ba12011-03-30 22:31:51218}
219
[email protected]82a37672011-05-03 12:02:41220void ChromeNetworkDelegate::OnPACScriptError(int line_number,
221 const string16& error) {
[email protected]3daf92302011-05-05 15:04:31222 ExtensionProxyEventRouter::GetInstance()->OnPACScriptError(
[email protected]673514522011-07-13 18:17:18223 event_router_.get(), profile_, line_number, error);
[email protected]82a37672011-05-03 12:02:41224}
[email protected]7efc582d2011-08-03 20:46:35225
[email protected]c2911d72011-10-03 22:16:36226net::NetworkDelegate::AuthRequiredResponse
227ChromeNetworkDelegate::OnAuthRequired(
[email protected]7efc582d2011-08-03 20:46:35228 net::URLRequest* request,
[email protected]c2911d72011-10-03 22:16:36229 const net::AuthChallengeInfo& auth_info,
230 const AuthCallback& callback,
231 net::AuthCredentials* credentials) {
[email protected]90449ab2011-10-11 15:36:45232 return ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired(
233 profile_, extension_info_map_.get(), request, auth_info,
234 callback, credentials);
[email protected]7efc582d2011-08-03 20:46:35235}