blob: d60517b40b9223549ce946aba30bd11da6c7eb67 [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]9c8ae8c2012-03-09 13:13:359#include "chrome/browser/content_settings/cookie_settings.h"
10#include "chrome/browser/content_settings/tab_specific_content_settings.h"
[email protected]8523ba52011-05-22 19:00:5811#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
[email protected]6e672df2012-01-25 10:39:4712#include "chrome/browser/extensions/api/webrequest/webrequest_api.h"
[email protected]3ce02412011-03-01 12:01:1513#include "chrome/browser/extensions/extension_event_router_forwarder.h"
[email protected]c357acb42011-06-09 20:52:4214#include "chrome/browser/extensions/extension_info_map.h"
[email protected]6baff0b52012-03-06 01:30:1815#include "chrome/browser/extensions/extension_process_manager.h"
[email protected]8202d0c2011-02-23 08:31:1416#include "chrome/browser/extensions/extension_proxy_api.h"
[email protected]0a8db0d2011-04-13 15:15:4017#include "chrome/browser/prefs/pref_member.h"
[email protected]6baff0b52012-03-06 01:30:1818#include "chrome/browser/profiles/profile_manager.h"
[email protected]8523ba52011-05-22 19:00:5819#include "chrome/browser/task_manager/task_manager.h"
[email protected]0a8db0d2011-04-13 15:15:4020#include "chrome/common/pref_names.h"
[email protected]c38831a12011-10-28 12:44:4921#include "content/public/browser/browser_thread.h"
[email protected]9c1662b2012-03-06 15:44:3322#include "content/public/browser/render_view_host.h"
[email protected]9c8ae8c2012-03-09 13:13:3523#include "content/public/browser/resource_request_info.h"
24#include "net/base/cookie_monster.h"
[email protected]82b42302011-04-20 16:28:1625#include "net/base/host_port_pair.h"
[email protected]8202d0c2011-02-23 08:31:1426#include "net/base/net_errors.h"
[email protected]6a5f77c32011-09-04 19:19:5927#include "net/base/net_log.h"
[email protected]ac039522010-06-15 16:39:4428#include "net/http/http_request_headers.h"
[email protected]48944382011-04-23 13:28:1629#include "net/http/http_response_headers.h"
[email protected]d05ef99c2011-02-01 21:38:1630#include "net/url_request/url_request.h"
31
[email protected]3e598ff12011-09-06 11:22:3432#if defined(ENABLE_CONFIGURATION_POLICY)
33#include "chrome/browser/policy/url_blacklist_manager.h"
34#endif
35
[email protected]631bb742011-11-02 11:29:3936using content::BrowserThread;
[email protected]eaabba22012-03-07 15:02:1137using content::RenderViewHost;
[email protected]ea114722012-03-12 01:11:2538using content::ResourceRequestInfo;
[email protected]631bb742011-11-02 11:29:3939
[email protected]d05ef99c2011-02-01 21:38:1640namespace {
41
[email protected]8202d0c2011-02-23 08:31:1442// If the |request| failed due to problems with a proxy, forward the error to
43// the proxy extension API.
[email protected]0651b812011-02-24 00:22:5044void ForwardProxyErrors(net::URLRequest* request,
[email protected]3ce02412011-03-01 12:01:1545 ExtensionEventRouterForwarder* event_router,
[email protected]673514522011-07-13 18:17:1846 void* profile) {
[email protected]8202d0c2011-02-23 08:31:1447 if (request->status().status() == net::URLRequestStatus::FAILED) {
[email protected]d0cc35b2011-09-08 12:02:0548 switch (request->status().error()) {
[email protected]8202d0c2011-02-23 08:31:1449 case net::ERR_PROXY_AUTH_UNSUPPORTED:
50 case net::ERR_PROXY_CONNECTION_FAILED:
51 case net::ERR_TUNNEL_CONNECTION_FAILED:
52 ExtensionProxyEventRouter::GetInstance()->OnProxyError(
[email protected]d0cc35b2011-09-08 12:02:0553 event_router, profile, request->status().error());
[email protected]8202d0c2011-02-23 08:31:1454 }
55 }
56}
57
[email protected]6baff0b52012-03-06 01:30:1858enum RequestStatus { REQUEST_STARTED, REQUEST_DONE };
59
60// Notifies the ExtensionProcessManager that a request has started or stopped
61// for a particular RenderView.
62void NotifyEPMRequestStatus(RequestStatus status,
63 void* profile_id,
64 int process_id,
65 int render_view_id) {
66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
67 Profile* profile = reinterpret_cast<Profile*>(profile_id);
68 if (!g_browser_process->profile_manager()->IsValidProfile(profile))
69 return;
70
71 RenderViewHost* render_view_host =
72 RenderViewHost::FromID(process_id, render_view_id);
73 // Will be NULL if the request was not issued on behalf of a renderer (e.g. a
74 // system-level request).
75 if (render_view_host) {
76 if (status == REQUEST_STARTED) {
77 profile->GetExtensionProcessManager()->OnNetworkRequestStarted(
78 render_view_host);
79 } else if (status == REQUEST_DONE) {
80 profile->GetExtensionProcessManager()->OnNetworkRequestDone(
81 render_view_host);
82 } else {
83 NOTREACHED();
84 }
85 }
86}
87
88void ForwardRequestStatus(
89 RequestStatus status, net::URLRequest* request, void* profile_id) {
[email protected]ea114722012-03-12 01:11:2590 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
91 if (!info)
92 return;
93
[email protected]6baff0b52012-03-06 01:30:1894 int process_id, render_view_id;
[email protected]ea114722012-03-12 01:11:2595 if (info->GetAssociatedRenderView(&process_id, &render_view_id)) {
[email protected]6baff0b52012-03-06 01:30:1896 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
97 base::Bind(&NotifyEPMRequestStatus,
98 status, profile_id, process_id, render_view_id));
99 }
100}
101
[email protected]d05ef99c2011-02-01 21:38:16102} // namespace
[email protected]ac039522010-06-15 16:39:44103
[email protected]0651b812011-02-24 00:22:50104ChromeNetworkDelegate::ChromeNetworkDelegate(
[email protected]3ce02412011-03-01 12:01:15105 ExtensionEventRouterForwarder* event_router,
[email protected]c357acb42011-06-09 20:52:42106 ExtensionInfoMap* extension_info_map,
[email protected]6a5f77c32011-09-04 19:19:59107 const policy::URLBlacklistManager* url_blacklist_manager,
[email protected]673514522011-07-13 18:17:18108 void* profile,
[email protected]9c8ae8c2012-03-09 13:13:35109 CookieSettings* cookie_settings,
[email protected]a8c1e7452011-05-14 06:17:07110 BooleanPrefMember* enable_referrers)
[email protected]3ce02412011-03-01 12:01:15111 : event_router_(event_router),
[email protected]673514522011-07-13 18:17:18112 profile_(profile),
[email protected]9c8ae8c2012-03-09 13:13:35113 cookie_settings_(cookie_settings),
[email protected]c357acb42011-06-09 20:52:42114 extension_info_map_(extension_info_map),
[email protected]6a5f77c32011-09-04 19:19:59115 enable_referrers_(enable_referrers),
116 url_blacklist_manager_(url_blacklist_manager) {
[email protected]4b50cb52011-03-10 00:29:37117 DCHECK(event_router);
[email protected]0a8db0d2011-04-13 15:15:40118 DCHECK(enable_referrers);
[email protected]9c8ae8c2012-03-09 13:13:35119 DCHECK(!profile || cookie_settings);
[email protected]0651b812011-02-24 00:22:50120}
121
[email protected]ac039522010-06-15 16:39:44122ChromeNetworkDelegate::~ChromeNetworkDelegate() {}
123
[email protected]0a8db0d2011-04-13 15:15:40124// static
125void ChromeNetworkDelegate::InitializeReferrersEnabled(
126 BooleanPrefMember* enable_referrers,
127 PrefService* pref_service) {
128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
129 enable_referrers->Init(prefs::kEnableReferrers, pref_service, NULL);
130 enable_referrers->MoveToThread(BrowserThread::IO);
131}
132
[email protected]4875ba12011-03-30 22:31:51133int ChromeNetworkDelegate::OnBeforeURLRequest(
[email protected]4c76d7c2011-04-15 19:14:12134 net::URLRequest* request,
[email protected]084262c2011-12-01 21:12:47135 const net::CompletionCallback& callback,
[email protected]4c76d7c2011-04-15 19:14:12136 GURL* new_url) {
[email protected]3e598ff12011-09-06 11:22:34137#if defined(ENABLE_CONFIGURATION_POLICY)
[email protected]6a5f77c32011-09-04 19:19:59138 // TODO(joaodasilva): This prevents extensions from seeing URLs that are
139 // blocked. However, an extension might redirect the request to another URL,
140 // which is not blocked.
141 if (url_blacklist_manager_ &&
142 url_blacklist_manager_->IsURLBlocked(request->url())) {
143 // URL access blocked by policy.
144 scoped_refptr<net::NetLog::EventParameters> params;
145 params = new net::NetLogStringParameter("url", request->url().spec());
146 request->net_log().AddEvent(
147 net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST, params);
148 return net::ERR_NETWORK_ACCESS_DENIED;
149 }
[email protected]3e598ff12011-09-06 11:22:34150#endif
[email protected]6a5f77c32011-09-04 19:19:59151
[email protected]6baff0b52012-03-06 01:30:18152 ForwardRequestStatus(REQUEST_STARTED, request, profile_);
153
[email protected]0a8db0d2011-04-13 15:15:40154 if (!enable_referrers_->GetValue())
155 request->set_referrer(std::string());
[email protected]05cc4e72011-03-08 21:29:48156 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
[email protected]673514522011-07-13 18:17:18157 profile_, extension_info_map_.get(), request, callback, new_url);
[email protected]d05ef99c2011-02-01 21:38:16158}
159
[email protected]4875ba12011-03-30 22:31:51160int ChromeNetworkDelegate::OnBeforeSendHeaders(
[email protected]636eccd2011-06-28 12:28:01161 net::URLRequest* request,
[email protected]084262c2011-12-01 21:12:47162 const net::CompletionCallback& callback,
[email protected]4c76d7c2011-04-15 19:14:12163 net::HttpRequestHeaders* headers) {
[email protected]4875ba12011-03-30 22:31:51164 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
[email protected]673514522011-07-13 18:17:18165 profile_, extension_info_map_.get(), request, callback, headers);
[email protected]ac039522010-06-15 16:39:44166}
[email protected]8202d0c2011-02-23 08:31:14167
[email protected]5796dc942011-07-14 19:26:10168void ChromeNetworkDelegate::OnSendHeaders(
169 net::URLRequest* request,
[email protected]783573b2011-05-13 11:05:15170 const net::HttpRequestHeaders& headers) {
[email protected]5796dc942011-07-14 19:26:10171 ExtensionWebRequestEventRouter::GetInstance()->OnSendHeaders(
172 profile_, extension_info_map_.get(), request, headers);
[email protected]82b42302011-04-20 16:28:16173}
174
[email protected]ea8141e2011-10-05 13:12:51175int ChromeNetworkDelegate::OnHeadersReceived(
176 net::URLRequest* request,
[email protected]084262c2011-12-01 21:12:47177 const net::CompletionCallback& callback,
[email protected]ea8141e2011-10-05 13:12:51178 net::HttpResponseHeaders* original_response_headers,
179 scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
180 return ExtensionWebRequestEventRouter::GetInstance()->OnHeadersReceived(
181 profile_, extension_info_map_.get(), request, callback,
182 original_response_headers, override_response_headers);
183}
184
[email protected]31b2e5f2011-04-20 16:58:32185void ChromeNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
186 const GURL& new_location) {
187 ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRedirect(
[email protected]673514522011-07-13 18:17:18188 profile_, extension_info_map_.get(), request, new_location);
[email protected]31b2e5f2011-04-20 16:58:32189}
190
191
[email protected]8202d0c2011-02-23 08:31:14192void ChromeNetworkDelegate::OnResponseStarted(net::URLRequest* request) {
[email protected]62fecae2011-04-21 11:08:24193 ExtensionWebRequestEventRouter::GetInstance()->OnResponseStarted(
[email protected]673514522011-07-13 18:17:18194 profile_, extension_info_map_.get(), request);
195 ForwardProxyErrors(request, event_router_.get(), profile_);
[email protected]8202d0c2011-02-23 08:31:14196}
197
[email protected]8523ba52011-05-22 19:00:58198void ChromeNetworkDelegate::OnRawBytesRead(const net::URLRequest& request,
199 int bytes_read) {
200 TaskManager::GetInstance()->model()->NotifyBytesRead(request, bytes_read);
201}
202
[email protected]9045b8822012-01-13 20:35:35203void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request,
204 bool started) {
[email protected]a83dd332011-07-13 10:41:01205 if (request->status().status() == net::URLRequestStatus::SUCCESS ||
206 request->status().status() == net::URLRequestStatus::HANDLED_EXTERNALLY) {
[email protected]48944382011-04-23 13:28:16207 bool is_redirect = request->response_headers() &&
208 net::HttpResponseHeaders::IsRedirectResponseCode(
209 request->response_headers()->response_code());
210 if (!is_redirect) {
211 ExtensionWebRequestEventRouter::GetInstance()->OnCompleted(
[email protected]673514522011-07-13 18:17:18212 profile_, extension_info_map_.get(), request);
[email protected]48944382011-04-23 13:28:16213 }
[email protected]a83dd332011-07-13 10:41:01214 } else if (request->status().status() == net::URLRequestStatus::FAILED ||
215 request->status().status() == net::URLRequestStatus::CANCELED) {
[email protected]05b6ab42011-04-23 13:46:04216 ExtensionWebRequestEventRouter::GetInstance()->OnErrorOccurred(
[email protected]9045b8822012-01-13 20:35:35217 profile_, extension_info_map_.get(), request, started);
[email protected]a83dd332011-07-13 10:41:01218 } else {
219 NOTREACHED();
[email protected]48944382011-04-23 13:28:16220 }
[email protected]673514522011-07-13 18:17:18221 ForwardProxyErrors(request, event_router_.get(), profile_);
[email protected]6baff0b52012-03-06 01:30:18222
223 ForwardRequestStatus(REQUEST_DONE, request, profile_);
[email protected]8202d0c2011-02-23 08:31:14224}
[email protected]4b50cb52011-03-10 00:29:37225
[email protected]4875ba12011-03-30 22:31:51226void ChromeNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {
227 ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestDestroyed(
[email protected]673514522011-07-13 18:17:18228 profile_, request);
[email protected]4875ba12011-03-30 22:31:51229}
230
[email protected]82a37672011-05-03 12:02:41231void ChromeNetworkDelegate::OnPACScriptError(int line_number,
232 const string16& error) {
[email protected]3daf92302011-05-05 15:04:31233 ExtensionProxyEventRouter::GetInstance()->OnPACScriptError(
[email protected]673514522011-07-13 18:17:18234 event_router_.get(), profile_, line_number, error);
[email protected]82a37672011-05-03 12:02:41235}
[email protected]7efc582d2011-08-03 20:46:35236
[email protected]c2911d72011-10-03 22:16:36237net::NetworkDelegate::AuthRequiredResponse
238ChromeNetworkDelegate::OnAuthRequired(
[email protected]7efc582d2011-08-03 20:46:35239 net::URLRequest* request,
[email protected]c2911d72011-10-03 22:16:36240 const net::AuthChallengeInfo& auth_info,
241 const AuthCallback& callback,
242 net::AuthCredentials* credentials) {
[email protected]90449ab2011-10-11 15:36:45243 return ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired(
244 profile_, extension_info_map_.get(), request, auth_info,
245 callback, credentials);
[email protected]7efc582d2011-08-03 20:46:35246}
[email protected]9c8ae8c2012-03-09 13:13:35247
248bool ChromeNetworkDelegate::CanGetCookies(
249 const net::URLRequest* request,
250 const net::CookieList& cookie_list) {
251 // NULL during tests, or when we're running in the system context.
252 if (!cookie_settings_)
253 return true;
254
255 bool allow = cookie_settings_->IsReadingCookieAllowed(
256 request->url(), request->first_party_for_cookies());
257
258 int render_process_id = -1;
259 int render_view_id = -1;
260 if (content::ResourceRequestInfo::GetRenderViewForRequest(
261 request, &render_process_id, &render_view_id)) {
262 BrowserThread::PostTask(
263 BrowserThread::UI, FROM_HERE,
264 base::Bind(&TabSpecificContentSettings::CookiesRead,
265 render_process_id, render_view_id,
266 request->url(), cookie_list, !allow));
267 }
268
269 return allow;
270}
271
272bool ChromeNetworkDelegate::CanSetCookie(
273 const net::URLRequest* request,
274 const std::string& cookie_line,
275 net::CookieOptions* options) {
276 // NULL during tests, or when we're running in the system context.
277 if (!cookie_settings_)
278 return true;
279
280 bool allow = cookie_settings_->IsSettingCookieAllowed(
281 request->url(), request->first_party_for_cookies());
282
283 if (cookie_settings_->IsCookieSessionOnly(request->url()))
284 options->set_force_session();
285
286 int render_process_id = -1;
287 int render_view_id = -1;
288 if (content::ResourceRequestInfo::GetRenderViewForRequest(
289 request, &render_process_id, &render_view_id)) {
290 BrowserThread::PostTask(
291 BrowserThread::UI, FROM_HERE,
292 base::Bind(&TabSpecificContentSettings::CookieChanged,
293 render_process_id, render_view_id,
294 request->url(), cookie_line, *options, !allow));
295 }
296
297 return allow;
298}