Home | History | Annotate | Download | only in net
      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