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
;
27 enum RequestStatus
{ REQUEST_STARTED
, REQUEST_DONE
};
29 // Notifies the extensions::ProcessManager that a request has started or stopped
30 // for a particular RenderFrame.
31 void NotifyEPMRequestStatus(RequestStatus status
,
35 int render_frame_id
) {
36 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
37 Profile
* profile
= reinterpret_cast<Profile
*>(profile_id
);
38 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
))
41 extensions::ProcessManager
* process_manager
=
42 extensions::ProcessManager::Get(profile
);
43 DCHECK(process_manager
);
45 // Will be NULL if the request was not issued on behalf of a renderer (e.g. a
46 // system-level request).
47 content::RenderFrameHost
* render_frame_host
=
48 content::RenderFrameHost::FromID(process_id
, render_frame_id
);
49 if (render_frame_host
) {
50 if (status
== REQUEST_STARTED
) {
51 process_manager
->OnNetworkRequestStarted(render_frame_host
, request_id
);
52 } else if (status
== REQUEST_DONE
) {
53 process_manager
->OnNetworkRequestDone(render_frame_host
, request_id
);
60 void ForwardRequestStatus(
61 RequestStatus status
, net::URLRequest
* request
, void* profile_id
) {
62 const ResourceRequestInfo
* info
= ResourceRequestInfo::ForRequest(request
);
66 if (status
== REQUEST_STARTED
&& request
->url_chain().size() > 1) {
67 // It's a redirect, this request has already been counted.
71 int process_id
, render_frame_id
;
72 if (info
->GetAssociatedRenderFrame(&process_id
, &render_frame_id
)) {
73 BrowserThread::PostTask(
74 BrowserThread::UI
, FROM_HERE
,
75 base::Bind(&NotifyEPMRequestStatus
, status
, profile_id
,
76 request
->identifier(), process_id
, render_frame_id
));
80 class ChromeExtensionsNetworkDelegateImpl
81 : public ChromeExtensionsNetworkDelegate
{
83 explicit ChromeExtensionsNetworkDelegateImpl(
84 extensions::EventRouterForwarder
* event_router
);
85 ~ChromeExtensionsNetworkDelegateImpl() override
;
88 // ChromeExtensionsNetworkDelegate implementation.
89 void ForwardProxyErrors(net::URLRequest
* request
) override
;
90 void ForwardStartRequestStatus(net::URLRequest
* request
) override
;
91 void ForwardDoneRequestStatus(net::URLRequest
* request
) override
;
92 int OnBeforeURLRequest(net::URLRequest
* request
,
93 const net::CompletionCallback
& callback
,
94 GURL
* new_url
) override
;
95 int OnBeforeSendHeaders(net::URLRequest
* request
,
96 const net::CompletionCallback
& callback
,
97 net::HttpRequestHeaders
* headers
) override
;
98 void OnSendHeaders(net::URLRequest
* request
,
99 const net::HttpRequestHeaders
& headers
) override
;
100 int OnHeadersReceived(
101 net::URLRequest
* request
,
102 const net::CompletionCallback
& callback
,
103 const net::HttpResponseHeaders
* original_response_headers
,
104 scoped_refptr
<net::HttpResponseHeaders
>* override_response_headers
,
105 GURL
* allowed_unsafe_redirect_url
) override
;
106 void OnBeforeRedirect(net::URLRequest
* request
,
107 const GURL
& new_location
) override
;
108 void OnResponseStarted(net::URLRequest
* request
) override
;
109 void OnCompleted(net::URLRequest
* request
, bool started
) override
;
110 void OnURLRequestDestroyed(net::URLRequest
* request
) override
;
111 void OnPACScriptError(int line_number
, const base::string16
& error
) override
;
112 net::NetworkDelegate::AuthRequiredResponse
OnAuthRequired(
113 net::URLRequest
* request
,
114 const net::AuthChallengeInfo
& auth_info
,
115 const AuthCallback
& callback
,
116 net::AuthCredentials
* credentials
) override
;
118 scoped_refptr
<extensions::EventRouterForwarder
> event_router_
;
120 DISALLOW_COPY_AND_ASSIGN(ChromeExtensionsNetworkDelegateImpl
);
123 ChromeExtensionsNetworkDelegateImpl::ChromeExtensionsNetworkDelegateImpl(
124 extensions::EventRouterForwarder
* event_router
) {
125 DCHECK(event_router
);
126 event_router_
= event_router
;
129 ChromeExtensionsNetworkDelegateImpl::~ChromeExtensionsNetworkDelegateImpl() {}
131 void ChromeExtensionsNetworkDelegateImpl::ForwardProxyErrors(
132 net::URLRequest
* request
) {
133 if (request
->status().status() == net::URLRequestStatus::FAILED
) {
134 switch (request
->status().error()) {
135 case net::ERR_PROXY_AUTH_UNSUPPORTED
:
136 case net::ERR_PROXY_CONNECTION_FAILED
:
137 case net::ERR_TUNNEL_CONNECTION_FAILED
:
138 extensions::ProxyEventRouter::GetInstance()->OnProxyError(
139 event_router_
.get(), profile_
, request
->status().error());
144 void ChromeExtensionsNetworkDelegateImpl::ForwardStartRequestStatus(
145 net::URLRequest
* request
) {
146 ForwardRequestStatus(REQUEST_STARTED
, request
, profile_
);
149 void ChromeExtensionsNetworkDelegateImpl::ForwardDoneRequestStatus(
150 net::URLRequest
* request
) {
151 ForwardRequestStatus(REQUEST_DONE
, request
, profile_
);
154 int ChromeExtensionsNetworkDelegateImpl::OnBeforeURLRequest(
155 net::URLRequest
* request
,
156 const net::CompletionCallback
& callback
,
158 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
159 profile_
, extension_info_map_
.get(), request
, callback
, new_url
);
162 int ChromeExtensionsNetworkDelegateImpl::OnBeforeSendHeaders(
163 net::URLRequest
* request
,
164 const net::CompletionCallback
& callback
,
165 net::HttpRequestHeaders
* headers
) {
166 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
167 profile_
, extension_info_map_
.get(), request
, callback
, headers
);
170 void ChromeExtensionsNetworkDelegateImpl::OnSendHeaders(
171 net::URLRequest
* request
,
172 const net::HttpRequestHeaders
& headers
) {
173 ExtensionWebRequestEventRouter::GetInstance()->OnSendHeaders(
174 profile_
, extension_info_map_
.get(), request
, headers
);
177 int ChromeExtensionsNetworkDelegateImpl::OnHeadersReceived(
178 net::URLRequest
* request
,
179 const net::CompletionCallback
& callback
,
180 const net::HttpResponseHeaders
* original_response_headers
,
181 scoped_refptr
<net::HttpResponseHeaders
>* override_response_headers
,
182 GURL
* allowed_unsafe_redirect_url
) {
183 return ExtensionWebRequestEventRouter::GetInstance()->OnHeadersReceived(
185 extension_info_map_
.get(),
188 original_response_headers
,
189 override_response_headers
,
190 allowed_unsafe_redirect_url
);
193 void ChromeExtensionsNetworkDelegateImpl::OnBeforeRedirect(
194 net::URLRequest
* request
,
195 const GURL
& new_location
) {
196 ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRedirect(
197 profile_
, extension_info_map_
.get(), request
, new_location
);
201 void ChromeExtensionsNetworkDelegateImpl::OnResponseStarted(
202 net::URLRequest
* request
) {
203 ExtensionWebRequestEventRouter::GetInstance()->OnResponseStarted(
204 profile_
, extension_info_map_
.get(), request
);
205 ForwardProxyErrors(request
);
208 void ChromeExtensionsNetworkDelegateImpl::OnCompleted(
209 net::URLRequest
* request
,
211 if (request
->status().status() == net::URLRequestStatus::SUCCESS
) {
212 bool is_redirect
= request
->response_headers() &&
213 net::HttpResponseHeaders::IsRedirectResponseCode(
214 request
->response_headers()->response_code());
216 ExtensionWebRequestEventRouter::GetInstance()->OnCompleted(
217 profile_
, extension_info_map_
.get(), request
);
222 if (request
->status().status() == net::URLRequestStatus::FAILED
||
223 request
->status().status() == net::URLRequestStatus::CANCELED
) {
224 ExtensionWebRequestEventRouter::GetInstance()->OnErrorOccurred(
225 profile_
, extension_info_map_
.get(), request
, started
);
232 void ChromeExtensionsNetworkDelegateImpl::OnURLRequestDestroyed(
233 net::URLRequest
* request
) {
234 ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestDestroyed(
238 void ChromeExtensionsNetworkDelegateImpl::OnPACScriptError(
240 const base::string16
& error
) {
241 extensions::ProxyEventRouter::GetInstance()->OnPACScriptError(
242 event_router_
.get(), profile_
, line_number
, error
);
245 net::NetworkDelegate::AuthRequiredResponse
246 ChromeExtensionsNetworkDelegateImpl::OnAuthRequired(
247 net::URLRequest
* request
,
248 const net::AuthChallengeInfo
& auth_info
,
249 const AuthCallback
& callback
,
250 net::AuthCredentials
* credentials
) {
251 return ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired(
252 profile_
, extension_info_map_
.get(), request
, auth_info
, callback
,
258 #endif // defined(ENABLE_EXTENSIONS)
261 ChromeExtensionsNetworkDelegate
* ChromeExtensionsNetworkDelegate::Create(
262 extensions::EventRouterForwarder
* event_router
) {
263 #if defined(ENABLE_EXTENSIONS)
264 return new ChromeExtensionsNetworkDelegateImpl(event_router
);
266 return new ChromeExtensionsNetworkDelegate();
270 ChromeExtensionsNetworkDelegate::ChromeExtensionsNetworkDelegate()
274 ChromeExtensionsNetworkDelegate::~ChromeExtensionsNetworkDelegate() {}
276 void ChromeExtensionsNetworkDelegate::set_extension_info_map(
277 extensions::InfoMap
* extension_info_map
) {
278 #if defined(ENABLE_EXTENSIONS)
279 extension_info_map_
= extension_info_map
;
283 void ChromeExtensionsNetworkDelegate::ForwardProxyErrors(
284 net::URLRequest
* request
) {
287 void ChromeExtensionsNetworkDelegate::ForwardStartRequestStatus(
288 net::URLRequest
* request
) {
291 void ChromeExtensionsNetworkDelegate::ForwardDoneRequestStatus(
292 net::URLRequest
* request
) {
295 int ChromeExtensionsNetworkDelegate::OnBeforeURLRequest(
296 net::URLRequest
* request
,
297 const net::CompletionCallback
& callback
,
302 int ChromeExtensionsNetworkDelegate::OnBeforeSendHeaders(
303 net::URLRequest
* request
,
304 const net::CompletionCallback
& callback
,
305 net::HttpRequestHeaders
* headers
) {
309 void ChromeExtensionsNetworkDelegate::OnSendHeaders(
310 net::URLRequest
* request
,
311 const net::HttpRequestHeaders
& headers
) {
314 int ChromeExtensionsNetworkDelegate::OnHeadersReceived(
315 net::URLRequest
* request
,
316 const net::CompletionCallback
& callback
,
317 const net::HttpResponseHeaders
* original_response_headers
,
318 scoped_refptr
<net::HttpResponseHeaders
>* override_response_headers
,
319 GURL
* allowed_unsafe_redirect_url
) {
323 void ChromeExtensionsNetworkDelegate::OnBeforeRedirect(
324 net::URLRequest
* request
,
325 const GURL
& new_location
) {
329 void ChromeExtensionsNetworkDelegate::OnResponseStarted(
330 net::URLRequest
* request
) {
333 void ChromeExtensionsNetworkDelegate::OnCompleted(
334 net::URLRequest
* request
,
338 void ChromeExtensionsNetworkDelegate::OnURLRequestDestroyed(
339 net::URLRequest
* request
) {
342 void ChromeExtensionsNetworkDelegate::OnPACScriptError(
344 const base::string16
& error
) {
347 net::NetworkDelegate::AuthRequiredResponse
348 ChromeExtensionsNetworkDelegate::OnAuthRequired(
349 net::URLRequest
* request
,
350 const net::AuthChallengeInfo
& auth_info
,
351 const AuthCallback
& callback
,
352 net::AuthCredentials
* credentials
) {
353 return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION
;