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_url_request_context_getter.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/compiler_specific.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/message_loop/message_loop_proxy.h"
     11 #include "chrome/browser/browser_process.h"
     12 #include "chrome/browser/io_thread.h"
     13 #include "chrome/browser/profiles/profile.h"
     14 #include "chrome/browser/profiles/profile_io_data.h"
     15 #include "chrome/browser/profiles/storage_partition_descriptor.h"
     16 #include "content/public/browser/browser_thread.h"
     17 #include "net/cookies/cookie_store.h"
     18 
     19 using content::BrowserThread;
     20 
     21 class ChromeURLRequestContextFactory {
     22  public:
     23   ChromeURLRequestContextFactory() {}
     24   virtual ~ChromeURLRequestContextFactory() {}
     25 
     26   // Called to create a new instance (will only be called once).
     27   virtual net::URLRequestContext* Create() = 0;
     28 
     29  protected:
     30   DISALLOW_COPY_AND_ASSIGN(ChromeURLRequestContextFactory);
     31 };
     32 
     33 namespace {
     34 
     35 // ----------------------------------------------------------------------------
     36 // Helper factories
     37 // ----------------------------------------------------------------------------
     38 
     39 // Factory that creates the main URLRequestContext.
     40 class FactoryForMain : public ChromeURLRequestContextFactory {
     41  public:
     42   FactoryForMain(
     43       const ProfileIOData* profile_io_data,
     44       content::ProtocolHandlerMap* protocol_handlers,
     45       content::URLRequestInterceptorScopedVector request_interceptors)
     46       : profile_io_data_(profile_io_data),
     47         request_interceptors_(request_interceptors.Pass()) {
     48     std::swap(protocol_handlers_, *protocol_handlers);
     49   }
     50 
     51   virtual net::URLRequestContext* Create() OVERRIDE {
     52     profile_io_data_->Init(&protocol_handlers_, request_interceptors_.Pass());
     53     return profile_io_data_->GetMainRequestContext();
     54   }
     55 
     56  private:
     57   const ProfileIOData* const profile_io_data_;
     58   content::ProtocolHandlerMap protocol_handlers_;
     59   content::URLRequestInterceptorScopedVector request_interceptors_;
     60 };
     61 
     62 // Factory that creates the URLRequestContext for extensions.
     63 class FactoryForExtensions : public ChromeURLRequestContextFactory {
     64  public:
     65   explicit FactoryForExtensions(const ProfileIOData* profile_io_data)
     66       : profile_io_data_(profile_io_data) {}
     67 
     68   virtual net::URLRequestContext* Create() OVERRIDE {
     69     return profile_io_data_->GetExtensionsRequestContext();
     70   }
     71 
     72  private:
     73   const ProfileIOData* const profile_io_data_;
     74 };
     75 
     76 // Factory that creates the URLRequestContext for a given isolated app.
     77 class FactoryForIsolatedApp : public ChromeURLRequestContextFactory {
     78  public:
     79   FactoryForIsolatedApp(
     80       const ProfileIOData* profile_io_data,
     81       const StoragePartitionDescriptor& partition_descriptor,
     82       ChromeURLRequestContextGetter* main_context,
     83       scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
     84           protocol_handler_interceptor,
     85       content::ProtocolHandlerMap* protocol_handlers,
     86       content::URLRequestInterceptorScopedVector request_interceptors)
     87       : profile_io_data_(profile_io_data),
     88         partition_descriptor_(partition_descriptor),
     89         main_request_context_getter_(main_context),
     90         protocol_handler_interceptor_(protocol_handler_interceptor.Pass()),
     91         request_interceptors_(request_interceptors.Pass()) {
     92     std::swap(protocol_handlers_, *protocol_handlers);
     93   }
     94 
     95   virtual net::URLRequestContext* Create() OVERRIDE {
     96     // We will copy most of the state from the main request context.
     97     //
     98     // Note that this factory is one-shot.  After Create() is called once, the
     99     // factory is actually destroyed. Thus it is safe to destructively pass
    100     // state onwards.
    101     return profile_io_data_->GetIsolatedAppRequestContext(
    102         main_request_context_getter_->GetURLRequestContext(),
    103         partition_descriptor_,
    104         protocol_handler_interceptor_.Pass(),
    105         &protocol_handlers_,
    106         request_interceptors_.Pass());
    107   }
    108 
    109  private:
    110   const ProfileIOData* const profile_io_data_;
    111   const StoragePartitionDescriptor partition_descriptor_;
    112   scoped_refptr<ChromeURLRequestContextGetter>
    113       main_request_context_getter_;
    114   scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
    115       protocol_handler_interceptor_;
    116   content::ProtocolHandlerMap protocol_handlers_;
    117   content::URLRequestInterceptorScopedVector request_interceptors_;
    118 };
    119 
    120 // Factory that creates the media URLRequestContext for a given isolated
    121 // app.  The media context is based on the corresponding isolated app's context.
    122 class FactoryForIsolatedMedia : public ChromeURLRequestContextFactory {
    123  public:
    124   FactoryForIsolatedMedia(
    125       const ProfileIOData* profile_io_data,
    126       const StoragePartitionDescriptor& partition_descriptor,
    127       ChromeURLRequestContextGetter* app_context)
    128     : profile_io_data_(profile_io_data),
    129       partition_descriptor_(partition_descriptor),
    130       app_context_getter_(app_context) {}
    131 
    132   virtual net::URLRequestContext* Create() OVERRIDE {
    133     // We will copy most of the state from the corresopnding app's
    134     // request context. We expect to have the same lifetime as
    135     // the associated |app_context_getter_| so we can just reuse
    136     // all its backing objects, including the
    137     // |protocol_handler_interceptor|.  This is why the API
    138     // looks different from FactoryForIsolatedApp's.
    139     return profile_io_data_->GetIsolatedMediaRequestContext(
    140         app_context_getter_->GetURLRequestContext(), partition_descriptor_);
    141   }
    142 
    143  private:
    144   const ProfileIOData* const profile_io_data_;
    145   const StoragePartitionDescriptor partition_descriptor_;
    146   scoped_refptr<ChromeURLRequestContextGetter> app_context_getter_;
    147 };
    148 
    149 // Factory that creates the URLRequestContext for media.
    150 class FactoryForMedia : public ChromeURLRequestContextFactory {
    151  public:
    152   explicit FactoryForMedia(const ProfileIOData* profile_io_data)
    153       : profile_io_data_(profile_io_data) {
    154   }
    155 
    156   virtual net::URLRequestContext* Create() OVERRIDE {
    157     return profile_io_data_->GetMediaRequestContext();
    158   }
    159 
    160  private:
    161   const ProfileIOData* const profile_io_data_;
    162 };
    163 
    164 }  // namespace
    165 
    166 // ----------------------------------------------------------------------------
    167 // ChromeURLRequestContextGetter
    168 // ----------------------------------------------------------------------------
    169 
    170 ChromeURLRequestContextGetter::ChromeURLRequestContextGetter(
    171     ChromeURLRequestContextFactory* factory)
    172     : factory_(factory),
    173       url_request_context_(NULL) {
    174   DCHECK(factory);
    175 }
    176 
    177 ChromeURLRequestContextGetter::~ChromeURLRequestContextGetter() {}
    178 
    179 // Lazily create a URLRequestContext using our factory.
    180 net::URLRequestContext*
    181 ChromeURLRequestContextGetter::GetURLRequestContext() {
    182   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    183 
    184   if (factory_.get()) {
    185     DCHECK(!url_request_context_);
    186     url_request_context_ = factory_->Create();
    187     factory_.reset();
    188   }
    189 
    190   // Context reference is valid, unless we're trying to use the
    191   // URLRequestContextGetter after the Profile has already been deleted.
    192   CHECK(url_request_context_);
    193 
    194   return url_request_context_;
    195 }
    196 
    197 void ChromeURLRequestContextGetter::Invalidate() {
    198   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    199   factory_.reset();
    200   url_request_context_ = NULL;
    201 }
    202 
    203 scoped_refptr<base::SingleThreadTaskRunner>
    204 ChromeURLRequestContextGetter::GetNetworkTaskRunner() const {
    205   return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
    206 }
    207 
    208 // static
    209 ChromeURLRequestContextGetter* ChromeURLRequestContextGetter::Create(
    210     Profile* profile,
    211     const ProfileIOData* profile_io_data,
    212     content::ProtocolHandlerMap* protocol_handlers,
    213     content::URLRequestInterceptorScopedVector request_interceptors) {
    214   return new ChromeURLRequestContextGetter(new FactoryForMain(
    215       profile_io_data, protocol_handlers, request_interceptors.Pass()));
    216 }
    217 
    218 // static
    219 ChromeURLRequestContextGetter*
    220 ChromeURLRequestContextGetter::CreateForMedia(
    221     Profile* profile, const ProfileIOData* profile_io_data) {
    222   return new ChromeURLRequestContextGetter(
    223       new FactoryForMedia(profile_io_data));
    224 }
    225 
    226 // static
    227 ChromeURLRequestContextGetter*
    228 ChromeURLRequestContextGetter::CreateForExtensions(
    229     Profile* profile, const ProfileIOData* profile_io_data) {
    230   return new ChromeURLRequestContextGetter(
    231       new FactoryForExtensions(profile_io_data));
    232 }
    233 
    234 // static
    235 ChromeURLRequestContextGetter*
    236 ChromeURLRequestContextGetter::CreateForIsolatedApp(
    237     Profile* profile,
    238     const ProfileIOData* profile_io_data,
    239     const StoragePartitionDescriptor& partition_descriptor,
    240     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
    241         protocol_handler_interceptor,
    242     content::ProtocolHandlerMap* protocol_handlers,
    243     content::URLRequestInterceptorScopedVector request_interceptors) {
    244   ChromeURLRequestContextGetter* main_context =
    245       static_cast<ChromeURLRequestContextGetter*>(profile->GetRequestContext());
    246   return new ChromeURLRequestContextGetter(
    247       new FactoryForIsolatedApp(profile_io_data,
    248                                 partition_descriptor,
    249                                 main_context,
    250                                 protocol_handler_interceptor.Pass(),
    251                                 protocol_handlers,
    252                                 request_interceptors.Pass()));
    253 }
    254 
    255 // static
    256 ChromeURLRequestContextGetter*
    257 ChromeURLRequestContextGetter::CreateForIsolatedMedia(
    258     Profile* profile,
    259     ChromeURLRequestContextGetter* app_context,
    260     const ProfileIOData* profile_io_data,
    261     const StoragePartitionDescriptor& partition_descriptor) {
    262   return new ChromeURLRequestContextGetter(
    263       new FactoryForIsolatedMedia(
    264           profile_io_data, partition_descriptor, app_context));
    265 }
    266