Home | History | Annotate | Download | only in net
      1 // Copyright (c) 2012 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.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/net/load_time_stats.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/profiles/profile_io_data.h"
     16 #include "chrome/browser/profiles/storage_partition_descriptor.h"
     17 #include "content/public/browser/browser_thread.h"
     18 #include "net/cookies/cookie_store.h"
     19 
     20 using content::BrowserThread;
     21 
     22 class ChromeURLRequestContextFactory {
     23  public:
     24   ChromeURLRequestContextFactory() {}
     25   virtual ~ChromeURLRequestContextFactory() {}
     26 
     27   // Called to create a new instance (will only be called once).
     28   virtual ChromeURLRequestContext* Create() = 0;
     29 
     30  protected:
     31   DISALLOW_COPY_AND_ASSIGN(ChromeURLRequestContextFactory);
     32 };
     33 
     34 namespace {
     35 
     36 // ----------------------------------------------------------------------------
     37 // Helper factories
     38 // ----------------------------------------------------------------------------
     39 
     40 // Factory that creates the main ChromeURLRequestContext.
     41 class FactoryForMain : public ChromeURLRequestContextFactory {
     42  public:
     43   FactoryForMain(
     44       const ProfileIOData* profile_io_data,
     45       content::ProtocolHandlerMap* protocol_handlers)
     46       : profile_io_data_(profile_io_data) {
     47     std::swap(protocol_handlers_, *protocol_handlers);
     48   }
     49 
     50   virtual ChromeURLRequestContext* Create() OVERRIDE {
     51     profile_io_data_->Init(&protocol_handlers_);
     52     return profile_io_data_->GetMainRequestContext();
     53   }
     54 
     55  private:
     56   const ProfileIOData* const profile_io_data_;
     57   content::ProtocolHandlerMap protocol_handlers_;
     58 };
     59 
     60 // Factory that creates the ChromeURLRequestContext for extensions.
     61 class FactoryForExtensions : public ChromeURLRequestContextFactory {
     62  public:
     63   explicit FactoryForExtensions(const ProfileIOData* profile_io_data)
     64       : profile_io_data_(profile_io_data) {}
     65 
     66   virtual ChromeURLRequestContext* Create() OVERRIDE {
     67     return profile_io_data_->GetExtensionsRequestContext();
     68   }
     69 
     70  private:
     71   const ProfileIOData* const profile_io_data_;
     72 };
     73 
     74 // Factory that creates the ChromeURLRequestContext for a given isolated app.
     75 class FactoryForIsolatedApp : public ChromeURLRequestContextFactory {
     76  public:
     77   FactoryForIsolatedApp(
     78       const ProfileIOData* profile_io_data,
     79       const StoragePartitionDescriptor& partition_descriptor,
     80       ChromeURLRequestContextGetter* main_context,
     81       scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
     82           protocol_handler_interceptor,
     83       content::ProtocolHandlerMap* protocol_handlers)
     84       : profile_io_data_(profile_io_data),
     85         partition_descriptor_(partition_descriptor),
     86         main_request_context_getter_(main_context),
     87         protocol_handler_interceptor_(protocol_handler_interceptor.Pass()) {
     88     std::swap(protocol_handlers_, *protocol_handlers);
     89   }
     90 
     91   virtual ChromeURLRequestContext* Create() OVERRIDE {
     92     // We will copy most of the state from the main request context.
     93     //
     94     // Note that this factory is one-shot.  After Create() is called once, the
     95     // factory is actually destroyed. Thus it is safe to destructively pass
     96     // state onwards.
     97     return profile_io_data_->GetIsolatedAppRequestContext(
     98         main_request_context_getter_->GetURLRequestContext(),
     99         partition_descriptor_,
    100         protocol_handler_interceptor_.Pass(),
    101         &protocol_handlers_);
    102   }
    103 
    104  private:
    105   const ProfileIOData* const profile_io_data_;
    106   const StoragePartitionDescriptor partition_descriptor_;
    107   scoped_refptr<ChromeURLRequestContextGetter>
    108       main_request_context_getter_;
    109   scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
    110       protocol_handler_interceptor_;
    111   content::ProtocolHandlerMap protocol_handlers_;
    112 };
    113 
    114 // Factory that creates the media ChromeURLRequestContext for a given isolated
    115 // app.  The media context is based on the corresponding isolated app's context.
    116 class FactoryForIsolatedMedia : public ChromeURLRequestContextFactory {
    117  public:
    118   FactoryForIsolatedMedia(
    119       const ProfileIOData* profile_io_data,
    120       const StoragePartitionDescriptor& partition_descriptor,
    121       ChromeURLRequestContextGetter* app_context)
    122     : profile_io_data_(profile_io_data),
    123       partition_descriptor_(partition_descriptor),
    124       app_context_getter_(app_context) {}
    125 
    126   virtual ChromeURLRequestContext* Create() OVERRIDE {
    127     // We will copy most of the state from the corresopnding app's
    128     // request context. We expect to have the same lifetime as
    129     // the associated |app_context_getter_| so we can just reuse
    130     // all its backing objects, including the
    131     // |protocol_handler_interceptor|.  This is why the API
    132     // looks different from FactoryForIsolatedApp's.
    133     return profile_io_data_->GetIsolatedMediaRequestContext(
    134         app_context_getter_->GetURLRequestContext(), partition_descriptor_);
    135   }
    136 
    137  private:
    138   const ProfileIOData* const profile_io_data_;
    139   const StoragePartitionDescriptor partition_descriptor_;
    140   scoped_refptr<ChromeURLRequestContextGetter> app_context_getter_;
    141 };
    142 
    143 // Factory that creates the ChromeURLRequestContext for media.
    144 class FactoryForMedia : public ChromeURLRequestContextFactory {
    145  public:
    146   explicit FactoryForMedia(const ProfileIOData* profile_io_data)
    147       : profile_io_data_(profile_io_data) {
    148   }
    149 
    150   virtual ChromeURLRequestContext* Create() OVERRIDE {
    151     return profile_io_data_->GetMediaRequestContext();
    152   }
    153 
    154  private:
    155   const ProfileIOData* const profile_io_data_;
    156 };
    157 
    158 }  // namespace
    159 
    160 // ----------------------------------------------------------------------------
    161 // ChromeURLRequestContextGetter
    162 // ----------------------------------------------------------------------------
    163 
    164 ChromeURLRequestContextGetter::ChromeURLRequestContextGetter(
    165     ChromeURLRequestContextFactory* factory)
    166     : factory_(factory) {
    167   DCHECK(factory);
    168 }
    169 
    170 ChromeURLRequestContextGetter::~ChromeURLRequestContextGetter() {}
    171 
    172 // Lazily create a ChromeURLRequestContext using our factory.
    173 ChromeURLRequestContext*
    174 ChromeURLRequestContextGetter::GetURLRequestContext() {
    175   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    176 
    177   if (!url_request_context_.get()) {
    178     DCHECK(factory_.get());
    179     url_request_context_ = factory_->Create()->GetWeakPtr();
    180     factory_.reset();
    181   }
    182 
    183   // Should not be NULL, unless we're trying to use the URLRequestContextGetter
    184   // after the Profile has already been deleted.
    185   CHECK(url_request_context_.get());
    186 
    187   return url_request_context_.get();
    188 }
    189 
    190 scoped_refptr<base::SingleThreadTaskRunner>
    191 ChromeURLRequestContextGetter::GetNetworkTaskRunner() const {
    192   return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
    193 }
    194 
    195 // static
    196 ChromeURLRequestContextGetter* ChromeURLRequestContextGetter::CreateOriginal(
    197     Profile* profile,
    198     const ProfileIOData* profile_io_data,
    199     content::ProtocolHandlerMap* protocol_handlers) {
    200   DCHECK(!profile->IsOffTheRecord());
    201   return new ChromeURLRequestContextGetter(
    202       new FactoryForMain(profile_io_data, protocol_handlers));
    203 }
    204 
    205 // static
    206 ChromeURLRequestContextGetter*
    207 ChromeURLRequestContextGetter::CreateOriginalForMedia(
    208     Profile* profile, const ProfileIOData* profile_io_data) {
    209   DCHECK(!profile->IsOffTheRecord());
    210   return new ChromeURLRequestContextGetter(
    211       new FactoryForMedia(profile_io_data));
    212 }
    213 
    214 // static
    215 ChromeURLRequestContextGetter*
    216 ChromeURLRequestContextGetter::CreateOriginalForExtensions(
    217     Profile* profile, const ProfileIOData* profile_io_data) {
    218   DCHECK(!profile->IsOffTheRecord());
    219   return new ChromeURLRequestContextGetter(
    220       new FactoryForExtensions(profile_io_data));
    221 }
    222 
    223 // static
    224 ChromeURLRequestContextGetter*
    225 ChromeURLRequestContextGetter::CreateOriginalForIsolatedApp(
    226     Profile* profile,
    227     const ProfileIOData* profile_io_data,
    228     const StoragePartitionDescriptor& partition_descriptor,
    229     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
    230         protocol_handler_interceptor,
    231     content::ProtocolHandlerMap* protocol_handlers) {
    232   DCHECK(!profile->IsOffTheRecord());
    233   ChromeURLRequestContextGetter* main_context =
    234       static_cast<ChromeURLRequestContextGetter*>(profile->GetRequestContext());
    235   return new ChromeURLRequestContextGetter(
    236       new FactoryForIsolatedApp(profile_io_data, partition_descriptor,
    237                                 main_context,
    238                                 protocol_handler_interceptor.Pass(),
    239                                 protocol_handlers));
    240 }
    241 
    242 // static
    243 ChromeURLRequestContextGetter*
    244 ChromeURLRequestContextGetter::CreateOriginalForIsolatedMedia(
    245     Profile* profile,
    246     ChromeURLRequestContextGetter* app_context,
    247     const ProfileIOData* profile_io_data,
    248     const StoragePartitionDescriptor& partition_descriptor) {
    249   DCHECK(!profile->IsOffTheRecord());
    250   return new ChromeURLRequestContextGetter(
    251       new FactoryForIsolatedMedia(
    252           profile_io_data, partition_descriptor, app_context));
    253 }
    254 
    255 // static
    256 ChromeURLRequestContextGetter*
    257 ChromeURLRequestContextGetter::CreateOffTheRecord(
    258     Profile* profile,
    259     const ProfileIOData* profile_io_data,
    260     content::ProtocolHandlerMap* protocol_handlers) {
    261   DCHECK(profile->IsOffTheRecord());
    262   return new ChromeURLRequestContextGetter(
    263       new FactoryForMain(profile_io_data, protocol_handlers));
    264 }
    265 
    266 // static
    267 ChromeURLRequestContextGetter*
    268 ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions(
    269     Profile* profile, const ProfileIOData* profile_io_data) {
    270   DCHECK(profile->IsOffTheRecord());
    271   return new ChromeURLRequestContextGetter(
    272       new FactoryForExtensions(profile_io_data));
    273 }
    274 
    275 // static
    276 ChromeURLRequestContextGetter*
    277 ChromeURLRequestContextGetter::CreateOffTheRecordForIsolatedApp(
    278     Profile* profile,
    279     const ProfileIOData* profile_io_data,
    280     const StoragePartitionDescriptor& partition_descriptor,
    281     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
    282         protocol_handler_interceptor,
    283     content::ProtocolHandlerMap* protocol_handlers) {
    284   DCHECK(profile->IsOffTheRecord());
    285   ChromeURLRequestContextGetter* main_context =
    286       static_cast<ChromeURLRequestContextGetter*>(profile->GetRequestContext());
    287   return new ChromeURLRequestContextGetter(
    288       new FactoryForIsolatedApp(profile_io_data, partition_descriptor,
    289                                 main_context,
    290                                 protocol_handler_interceptor.Pass(),
    291                                 protocol_handlers));
    292 }
    293 
    294 // ----------------------------------------------------------------------------
    295 // ChromeURLRequestContext
    296 // ----------------------------------------------------------------------------
    297 
    298 ChromeURLRequestContext::ChromeURLRequestContext(
    299     ContextType type,
    300     chrome_browser_net::LoadTimeStats* load_time_stats)
    301     : weak_factory_(this),
    302       load_time_stats_(load_time_stats) {
    303   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    304   if (load_time_stats_)
    305     load_time_stats_->RegisterURLRequestContext(this, type);
    306 }
    307 
    308 ChromeURLRequestContext::~ChromeURLRequestContext() {
    309   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    310   if (load_time_stats_)
    311     load_time_stats_->UnregisterURLRequestContext(this);
    312 }
    313 
    314 void ChromeURLRequestContext::CopyFrom(ChromeURLRequestContext* other) {
    315   URLRequestContext::CopyFrom(other);
    316 
    317   // Copy ChromeURLRequestContext parameters.
    318 }
    319