1 // Copyright 2014 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.
5 #include "chrome/browser/net/chrome_extensions_network_delegate.h"
7 #include "net/base/net_errors.h"
9 #if defined(ENABLE_EXTENSIONS)
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/extensions/api/proxy/proxy_api.h"
12 #include "chrome/browser/extensions/event_router_forwarder.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/browser/render_frame_host.h"
16 #include "content/public/browser/resource_request_info.h"
17 #include "extensions/browser/api/web_request/web_request_api.h"
18 #include "extensions/browser/info_map.h"
19 #include "extensions/browser/process_manager.h"
20 #include "net/url_request/url_request.h"
22 using content::BrowserThread
;
23 using content::ResourceRequestInfo
;
24 using extensions::ExtensionWebRequestEventRouter
;
28 enum RequestStatus
{ REQUEST_STARTED
, REQUEST_DONE
};
30 // Notifies the extensions::ProcessManager that a request has started or stopped
31 // for a particular RenderFrame.
32 void NotifyEPMRequestStatus(RequestStatus status
,
36 int render_frame_id
) {
37 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
38 Profile
* profile
= reinterpret_cast<Profile
*>(profile_id
);
39 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
))
42 extensions::ProcessManager
* process_manager
=
43 extensions::ProcessManager::Get(profile
);
44 DCHECK(process_manager
);
46 // Will be NULL if the request was not issued on behalf of a renderer (e.g. a
47 // system-level request).
48 content::RenderFrameHost
* render_frame_host
=
49 content::RenderFrameHost::FromID(process_id
, render_frame_id
);
50 if (render_frame_host
) {
51 if (status
== REQUEST_STARTED
) {
52 process_manager
->OnNetworkRequestStarted(render_frame_host
, request_id
);
53 } else if (status
== REQUEST_DONE
) {
54 process_manager
->OnNetworkRequestDone(render_frame_host
, request_id
);
61 void ForwardRequestStatus(
62 RequestStatus status
, net::URLRequest
* request
, void* profile_id
) {
63 const ResourceRequestInfo
* info
= ResourceRequestInfo::ForRequest(request
);
67 if (status
== REQUEST_STARTED
&& request
->url_chain().size() > 1) {
68 // It's a redirect, this request has already been counted.
72 int process_id
, render_frame_id
;
73 if (info
->GetAssociatedRenderFrame(&process_id
, &render_frame_id
)) {
74 BrowserThread::PostTask(
75 BrowserThread::UI
, FROM_HERE
,
76 base::Bind(&NotifyEPMRequestStatus
, status
, profile_id
,
77 request
->identifier(), process_id
, render_frame_id
));
81 class ChromeExtensionsNetworkDelegateImpl
82 : public ChromeExtensionsNetworkDelegate
{
84 explicit ChromeExtensionsNetworkDelegateImpl(
85 extensions::EventRouterForwarder
* event_router
);
86 ~ChromeExtensionsNetworkDelegateImpl() override
;
89 // ChromeExtensionsNetworkDelegate implementation.
90 void ForwardProxyErrors(net::URLRequest
* request
) override
;
91 void ForwardStartRequestStatus(net::URLRequest
* request
) override
;
92 void ForwardDoneRequestStatus(net::URLRequest
* request
) override
;
93 int OnBeforeURLRequest(net::URLRequest
* request
,
94 const net::CompletionCallback
& callback
,
95 GURL
* new_url
) override
;
96 int OnBeforeSendHeaders(net::URLRequest
* request
,
97 const net::CompletionCallback
& callback
,
98 net::HttpRequestHeaders
* headers
) override
;
99 void OnSendHeaders(net::URLRequest
* request
,
100 const net::HttpRequestHeaders
& headers
) override
;
101 int OnHeadersReceived(
102 net::URLRequest
* request
,
103 const net::CompletionCallback
& callback
,
104 const net::HttpResponseHeaders
* original_response_headers
,
105 scoped_refptr
<net::HttpResponseHeaders
>* override_response_headers
,
106 GURL
* allowed_unsafe_redirect_url
) override
;
107 void OnBeforeRedirect(net::URLRequest
* request
,
108 const GURL
& new_location
) override
;
109 void OnResponseStarted(net::URLRequest
* request
) override
;
110 void OnCompleted(net::URLRequest
* request
, bool started
) override
;
111 void OnURLRequestDestroyed(net::URLRequest
* request
) override
;
112 void OnURLRequestJobOrphaned(net::URLRequest
* request
) override
;
113 void OnPACScriptError(int line_number
, const base::string16
& error
) override
;
114 net::NetworkDelegate::AuthRequiredResponse
OnAuthRequired(
115 net::URLRequest
* request
,
116 const net::AuthChallengeInfo
& auth_info
,
117 const AuthCallback
& callback
,
118 net::AuthCredentials
* credentials
) override
;
120 scoped_refptr
<extensions::EventRouterForwarder
> event_router_
;
122 DISALLOW_COPY_AND_ASSIGN(ChromeExtensionsNetworkDelegateImpl
);
125 ChromeExtensionsNetworkDelegateImpl::ChromeExtensionsNetworkDelegateImpl(
126 extensions::EventRouterForwarder
* event_router
) {
127 DCHECK(event_router
);
128 event_router_
= event_router
;
131 ChromeExtensionsNetworkDelegateImpl::~ChromeExtensionsNetworkDelegateImpl() {}
133 void ChromeExtensionsNetworkDelegateImpl::ForwardProxyErrors(
134 net::URLRequest
* request
) {
135 if (request
->status().status() == net::URLRequestStatus::FAILED
) {
136 switch (request
->status().error()) {
137 case net::ERR_PROXY_AUTH_UNSUPPORTED
:
138 case net::ERR_PROXY_CONNECTION_FAILED
:
139 case net::ERR_TUNNEL_CONNECTION_FAILED
:
140 extensions::ProxyEventRouter::GetInstance()->OnProxyError(
141 event_router_
.get(), profile_
, request
->status().error());
146 void ChromeExtensionsNetworkDelegateImpl::ForwardStartRequestStatus(
147 net::URLRequest
* request
) {
148 ForwardRequestStatus(REQUEST_STARTED
, request
, profile_
);
151 void ChromeExtensionsNetworkDelegateImpl::ForwardDoneRequestStatus(
152 net::URLRequest
* request
) {
153 ForwardRequestStatus(REQUEST_DONE
, request
, profile_
);
156 int ChromeExtensionsNetworkDelegateImpl::OnBeforeURLRequest(
157 net::URLRequest
* request
,
158 const net::CompletionCallback
& callback
,
160 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
161 profile_
, extension_info_map_
.get(), request
, callback
, new_url
);
164 int ChromeExtensionsNetworkDelegateImpl::OnBeforeSendHeaders(
165 net::URLRequest
* request
,
166 const net::CompletionCallback
& callback
,
167 net::HttpRequestHeaders
* headers
) {
168 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
169 profile_
, extension_info_map_
.get(), request
, callback
, headers
);
172 void ChromeExtensionsNetworkDelegateImpl::OnSendHeaders(
173 net::URLRequest
* request
,
174 const net::HttpRequestHeaders
& headers
) {
175 ExtensionWebRequestEventRouter::GetInstance()->OnSendHeaders(
176 profile_
, extension_info_map_
.get(), request
, headers
);
179 int ChromeExtensionsNetworkDelegateImpl::OnHeadersReceived(
180 net::URLRequest
* request
,
181 const net::CompletionCallback
& callback
,
182 const net::HttpResponseHeaders
* original_response_headers
,
183 scoped_refptr
<net::HttpResponseHeaders
>* override_response_headers
,
184 GURL
* allowed_unsafe_redirect_url
) {
185 return ExtensionWebRequestEventRouter::GetInstance()->OnHeadersReceived(
187 extension_info_map_
.get(),
190 original_response_headers
,
191 override_response_headers
,
192 allowed_unsafe_redirect_url
);
195 void ChromeExtensionsNetworkDelegateImpl::OnBeforeRedirect(
196 net::URLRequest
* request
,
197 const GURL
& new_location
) {
198 ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRedirect(
199 profile_
, extension_info_map_
.get(), request
, new_location
);
203 void ChromeExtensionsNetworkDelegateImpl::OnResponseStarted(
204 net::URLRequest
* request
) {
205 ExtensionWebRequestEventRouter::GetInstance()->OnResponseStarted(
206 profile_
, extension_info_map_
.get(), request
);
207 ForwardProxyErrors(request
);
210 void ChromeExtensionsNetworkDelegateImpl::OnCompleted(
211 net::URLRequest
* request
,
213 if (request
->status().status() == net::URLRequestStatus::SUCCESS
) {
214 bool is_redirect
= request
->response_headers() &&
215 net::HttpResponseHeaders::IsRedirectResponseCode(
216 request
->response_headers()->response_code());
218 ExtensionWebRequestEventRouter::GetInstance()->OnCompleted(
219 profile_
, extension_info_map_
.get(), request
);
224 if (request
->status().status() == net::URLRequestStatus::FAILED
||
225 request
->status().status() == net::URLRequestStatus::CANCELED
) {
226 ExtensionWebRequestEventRouter::GetInstance()->OnErrorOccurred(
227 profile_
, extension_info_map_
.get(), request
, started
);
234 void ChromeExtensionsNetworkDelegateImpl::OnURLRequestDestroyed(
235 net::URLRequest
* request
) {
236 ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestDestroyed(
240 void ChromeExtensionsNetworkDelegateImpl::OnURLRequestJobOrphaned(
241 net::URLRequest
* request
) {
242 ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestJobOrphaned(
246 void ChromeExtensionsNetworkDelegateImpl::OnPACScriptError(
248 const base::string16
& error
) {
249 extensions::ProxyEventRouter::GetInstance()->OnPACScriptError(
250 event_router_
.get(), profile_
, line_number
, error
);
253 net::NetworkDelegate::AuthRequiredResponse
254 ChromeExtensionsNetworkDelegateImpl::OnAuthRequired(
255 net::URLRequest
* request
,
256 const net::AuthChallengeInfo
& auth_info
,
257 const AuthCallback
& callback
,
258 net::AuthCredentials
* credentials
) {
259 return ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired(
260 profile_
, extension_info_map_
.get(), request
, auth_info
, callback
,
266 #endif // defined(ENABLE_EXTENSIONS)
269 ChromeExtensionsNetworkDelegate
* ChromeExtensionsNetworkDelegate::Create(
270 extensions::EventRouterForwarder
* event_router
) {
271 #if defined(ENABLE_EXTENSIONS)
272 return new ChromeExtensionsNetworkDelegateImpl(event_router
);
274 return new ChromeExtensionsNetworkDelegate();
278 ChromeExtensionsNetworkDelegate::ChromeExtensionsNetworkDelegate()
282 ChromeExtensionsNetworkDelegate::~ChromeExtensionsNetworkDelegate() {}
284 void ChromeExtensionsNetworkDelegate::set_extension_info_map(
285 extensions::InfoMap
* extension_info_map
) {
286 #if defined(ENABLE_EXTENSIONS)
287 extension_info_map_
= extension_info_map
;
291 void ChromeExtensionsNetworkDelegate::ForwardProxyErrors(
292 net::URLRequest
* request
) {
295 void ChromeExtensionsNetworkDelegate::ForwardStartRequestStatus(
296 net::URLRequest
* request
) {
299 void ChromeExtensionsNetworkDelegate::ForwardDoneRequestStatus(
300 net::URLRequest
* request
) {
303 int ChromeExtensionsNetworkDelegate::OnBeforeURLRequest(
304 net::URLRequest
* request
,
305 const net::CompletionCallback
& callback
,
310 int ChromeExtensionsNetworkDelegate::OnBeforeSendHeaders(
311 net::URLRequest
* request
,
312 const net::CompletionCallback
& callback
,
313 net::HttpRequestHeaders
* headers
) {
317 void ChromeExtensionsNetworkDelegate::OnSendHeaders(
318 net::URLRequest
* request
,
319 const net::HttpRequestHeaders
& headers
) {
322 int ChromeExtensionsNetworkDelegate::OnHeadersReceived(
323 net::URLRequest
* request
,
324 const net::CompletionCallback
& callback
,
325 const net::HttpResponseHeaders
* original_response_headers
,
326 scoped_refptr
<net::HttpResponseHeaders
>* override_response_headers
,
327 GURL
* allowed_unsafe_redirect_url
) {
331 void ChromeExtensionsNetworkDelegate::OnBeforeRedirect(
332 net::URLRequest
* request
,
333 const GURL
& new_location
) {
337 void ChromeExtensionsNetworkDelegate::OnResponseStarted(
338 net::URLRequest
* request
) {
341 void ChromeExtensionsNetworkDelegate::OnCompleted(
342 net::URLRequest
* request
,
346 void ChromeExtensionsNetworkDelegate::OnURLRequestDestroyed(
347 net::URLRequest
* request
) {
350 void ChromeExtensionsNetworkDelegate::OnURLRequestJobOrphaned(
351 net::URLRequest
* request
) {
354 void ChromeExtensionsNetworkDelegate::OnPACScriptError(
356 const base::string16
& error
) {
359 net::NetworkDelegate::AuthRequiredResponse
360 ChromeExtensionsNetworkDelegate::OnAuthRequired(
361 net::URLRequest
* request
,
362 const net::AuthChallengeInfo
& auth_info
,
363 const AuthCallback
& callback
,
364 net::AuthCredentials
* credentials
) {
365 return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION
;