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. 4 5 #include "chrome/browser/net/chrome_extensions_network_delegate.h" 6 7 #include "net/base/net_errors.h" 8 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/extension_system.h" 19 #include "extensions/browser/info_map.h" 20 #include "extensions/browser/process_manager.h" 21 #include "net/url_request/url_request.h" 22 23 using content::BrowserThread; 24 using content::ResourceRequestInfo; 25 26 namespace { 27 28 enum RequestStatus { REQUEST_STARTED, REQUEST_DONE }; 29 30 // Notifies the extensions::ProcessManager that a request has started or stopped 31 // for a particular RenderFrame. 32 void NotifyEPMRequestStatus(RequestStatus status, 33 void* profile_id, 34 int process_id, 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)) 39 return; 40 41 extensions::ProcessManager* process_manager = 42 extensions::ExtensionSystem::Get(profile)->process_manager(); 43 // This may be NULL in unit tests. 44 if (!process_manager) 45 return; 46 47 // Will be NULL if the request was not issued on behalf of a renderer (e.g. a 48 // system-level request). 49 content::RenderFrameHost* render_frame_host = 50 content::RenderFrameHost::FromID(process_id, render_frame_id); 51 if (render_frame_host) { 52 if (status == REQUEST_STARTED) { 53 process_manager->OnNetworkRequestStarted(render_frame_host); 54 } else if (status == REQUEST_DONE) { 55 process_manager->OnNetworkRequestDone(render_frame_host); 56 } else { 57 NOTREACHED(); 58 } 59 } 60 } 61 62 void ForwardRequestStatus( 63 RequestStatus status, net::URLRequest* request, void* profile_id) { 64 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); 65 if (!info) 66 return; 67 68 if (status == REQUEST_STARTED && request->url_chain().size() > 1) { 69 // It's a redirect, this request has already been counted. 70 return; 71 } 72 73 int process_id, render_frame_id; 74 if (info->GetAssociatedRenderFrame(&process_id, &render_frame_id)) { 75 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 76 base::Bind(&NotifyEPMRequestStatus, 77 status, profile_id, process_id, render_frame_id)); 78 } 79 } 80 81 class ChromeExtensionsNetworkDelegateImpl 82 : public ChromeExtensionsNetworkDelegate { 83 public: 84 explicit ChromeExtensionsNetworkDelegateImpl( 85 extensions::EventRouterForwarder* event_router); 86 virtual ~ChromeExtensionsNetworkDelegateImpl(); 87 88 private: 89 // ChromeExtensionsNetworkDelegate implementation. 90 virtual void ForwardProxyErrors(net::URLRequest* request) OVERRIDE; 91 virtual void ForwardStartRequestStatus(net::URLRequest* request) OVERRIDE; 92 virtual void ForwardDoneRequestStatus(net::URLRequest* request) OVERRIDE; 93 virtual int OnBeforeURLRequest(net::URLRequest* request, 94 const net::CompletionCallback& callback, 95 GURL* new_url) OVERRIDE; 96 virtual int OnBeforeSendHeaders(net::URLRequest* request, 97 const net::CompletionCallback& callback, 98 net::HttpRequestHeaders* headers) OVERRIDE; 99 virtual void OnSendHeaders(net::URLRequest* request, 100 const net::HttpRequestHeaders& headers) OVERRIDE; 101 virtual 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 virtual void OnBeforeRedirect(net::URLRequest* request, 108 const GURL& new_location) OVERRIDE; 109 virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE; 110 virtual void OnCompleted(net::URLRequest* request, bool started) OVERRIDE; 111 virtual void OnURLRequestDestroyed(net::URLRequest* request) OVERRIDE; 112 virtual void OnPACScriptError(int line_number, 113 const base::string16& error) OVERRIDE; 114 virtual net::NetworkDelegate::AuthRequiredResponse OnAuthRequired( 115 net::URLRequest* request, 116 const net::AuthChallengeInfo& auth_info, 117 const AuthCallback& callback, 118 net::AuthCredentials* credentials) OVERRIDE; 119 120 scoped_refptr<extensions::EventRouterForwarder> event_router_; 121 122 DISALLOW_COPY_AND_ASSIGN(ChromeExtensionsNetworkDelegateImpl); 123 }; 124 125 ChromeExtensionsNetworkDelegateImpl::ChromeExtensionsNetworkDelegateImpl( 126 extensions::EventRouterForwarder* event_router) { 127 DCHECK(event_router); 128 event_router_ = event_router; 129 } 130 131 ChromeExtensionsNetworkDelegateImpl::~ChromeExtensionsNetworkDelegateImpl() {} 132 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()); 142 } 143 } 144 } 145 146 void ChromeExtensionsNetworkDelegateImpl::ForwardStartRequestStatus( 147 net::URLRequest* request) { 148 ForwardRequestStatus(REQUEST_STARTED, request, profile_); 149 } 150 151 void ChromeExtensionsNetworkDelegateImpl::ForwardDoneRequestStatus( 152 net::URLRequest* request) { 153 ForwardRequestStatus(REQUEST_DONE, request, profile_); 154 } 155 156 int ChromeExtensionsNetworkDelegateImpl::OnBeforeURLRequest( 157 net::URLRequest* request, 158 const net::CompletionCallback& callback, 159 GURL* new_url) { 160 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest( 161 profile_, extension_info_map_.get(), request, callback, new_url); 162 } 163 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); 170 } 171 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); 177 } 178 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( 186 profile_, 187 extension_info_map_.get(), 188 request, 189 callback, 190 original_response_headers, 191 override_response_headers, 192 allowed_unsafe_redirect_url); 193 } 194 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); 200 } 201 202 203 void ChromeExtensionsNetworkDelegateImpl::OnResponseStarted( 204 net::URLRequest* request) { 205 ExtensionWebRequestEventRouter::GetInstance()->OnResponseStarted( 206 profile_, extension_info_map_.get(), request); 207 ForwardProxyErrors(request); 208 } 209 210 void ChromeExtensionsNetworkDelegateImpl::OnCompleted( 211 net::URLRequest* request, 212 bool started) { 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()); 217 if (!is_redirect) { 218 ExtensionWebRequestEventRouter::GetInstance()->OnCompleted( 219 profile_, extension_info_map_.get(), request); 220 } 221 return; 222 } 223 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); 228 return; 229 } 230 231 NOTREACHED(); 232 } 233 234 void ChromeExtensionsNetworkDelegateImpl::OnURLRequestDestroyed( 235 net::URLRequest* request) { 236 ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestDestroyed( 237 profile_, request); 238 } 239 240 void ChromeExtensionsNetworkDelegateImpl::OnPACScriptError( 241 int line_number, 242 const base::string16& error) { 243 extensions::ProxyEventRouter::GetInstance()->OnPACScriptError( 244 event_router_.get(), profile_, line_number, error); 245 } 246 247 net::NetworkDelegate::AuthRequiredResponse 248 ChromeExtensionsNetworkDelegateImpl::OnAuthRequired( 249 net::URLRequest* request, 250 const net::AuthChallengeInfo& auth_info, 251 const AuthCallback& callback, 252 net::AuthCredentials* credentials) { 253 return ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired( 254 profile_, extension_info_map_.get(), request, auth_info, callback, 255 credentials); 256 } 257 258 } // namespace 259 260 #endif // defined(ENABLE_EXTENSIONS) 261 262 // static 263 ChromeExtensionsNetworkDelegate* ChromeExtensionsNetworkDelegate::Create( 264 extensions::EventRouterForwarder* event_router) { 265 #if defined(ENABLE_EXTENSIONS) 266 return new ChromeExtensionsNetworkDelegateImpl(event_router); 267 #else 268 return new ChromeExtensionsNetworkDelegate(); 269 #endif 270 } 271 272 ChromeExtensionsNetworkDelegate::ChromeExtensionsNetworkDelegate() 273 : profile_(NULL) { 274 } 275 276 ChromeExtensionsNetworkDelegate::~ChromeExtensionsNetworkDelegate() {} 277 278 void ChromeExtensionsNetworkDelegate::set_extension_info_map( 279 extensions::InfoMap* extension_info_map) { 280 #if defined(ENABLE_EXTENSIONS) 281 extension_info_map_ = extension_info_map; 282 #endif 283 } 284 285 void ChromeExtensionsNetworkDelegate::ForwardProxyErrors( 286 net::URLRequest* request) { 287 } 288 289 void ChromeExtensionsNetworkDelegate::ForwardStartRequestStatus( 290 net::URLRequest* request) { 291 } 292 293 void ChromeExtensionsNetworkDelegate::ForwardDoneRequestStatus( 294 net::URLRequest* request) { 295 } 296 297 int ChromeExtensionsNetworkDelegate::OnBeforeURLRequest( 298 net::URLRequest* request, 299 const net::CompletionCallback& callback, 300 GURL* new_url) { 301 return net::OK; 302 } 303 304 int ChromeExtensionsNetworkDelegate::OnBeforeSendHeaders( 305 net::URLRequest* request, 306 const net::CompletionCallback& callback, 307 net::HttpRequestHeaders* headers) { 308 return net::OK; 309 } 310 311 void ChromeExtensionsNetworkDelegate::OnSendHeaders( 312 net::URLRequest* request, 313 const net::HttpRequestHeaders& headers) { 314 } 315 316 int ChromeExtensionsNetworkDelegate::OnHeadersReceived( 317 net::URLRequest* request, 318 const net::CompletionCallback& callback, 319 const net::HttpResponseHeaders* original_response_headers, 320 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, 321 GURL* allowed_unsafe_redirect_url) { 322 return net::OK; 323 } 324 325 void ChromeExtensionsNetworkDelegate::OnBeforeRedirect( 326 net::URLRequest* request, 327 const GURL& new_location) { 328 } 329 330 331 void ChromeExtensionsNetworkDelegate::OnResponseStarted( 332 net::URLRequest* request) { 333 } 334 335 void ChromeExtensionsNetworkDelegate::OnCompleted( 336 net::URLRequest* request, 337 bool started) { 338 } 339 340 void ChromeExtensionsNetworkDelegate::OnURLRequestDestroyed( 341 net::URLRequest* request) { 342 } 343 344 void ChromeExtensionsNetworkDelegate::OnPACScriptError( 345 int line_number, 346 const base::string16& error) { 347 } 348 349 net::NetworkDelegate::AuthRequiredResponse 350 ChromeExtensionsNetworkDelegate::OnAuthRequired( 351 net::URLRequest* request, 352 const net::AuthChallengeInfo& auth_info, 353 const AuthCallback& callback, 354 net::AuthCredentials* credentials) { 355 return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION; 356 } 357