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::Create(
    197     Profile* profile,
    198     const ProfileIOData* profile_io_data,
    199     content::ProtocolHandlerMap* protocol_handlers) {
    200   return new ChromeURLRequestContextGetter(
    201       new FactoryForMain(profile_io_data, protocol_handlers));
    202 }
    203 
    204 // static
    205 ChromeURLRequestContextGetter*
    206 ChromeURLRequestContextGetter::CreateForMedia(
    207     Profile* profile, const ProfileIOData* profile_io_data) {
    208   return new ChromeURLRequestContextGetter(
    209       new FactoryForMedia(profile_io_data));
    210 }
    211 
    212 // static
    213 ChromeURLRequestContextGetter*
    214 ChromeURLRequestContextGetter::CreateForExtensions(
    215     Profile* profile, const ProfileIOData* profile_io_data) {
    216   return new ChromeURLRequestContextGetter(
    217       new FactoryForExtensions(profile_io_data));
    218 }
    219 
    220 // static
    221 ChromeURLRequestContextGetter*
    222 ChromeURLRequestContextGetter::CreateForIsolatedApp(
    223     Profile* profile,
    224     const ProfileIOData* profile_io_data,
    225     const StoragePartitionDescriptor& partition_descriptor,
    226     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
    227         protocol_handler_interceptor,
    228     content::ProtocolHandlerMap* protocol_handlers) {
    229   ChromeURLRequestContextGetter* main_context =
    230       static_cast<ChromeURLRequestContextGetter*>(profile->GetRequestContext());
    231   return new ChromeURLRequestContextGetter(
    232       new FactoryForIsolatedApp(profile_io_data, partition_descriptor,
    233                                 main_context,
    234                                 protocol_handler_interceptor.Pass(),
    235                                 protocol_handlers));
    236 }
    237 
    238 // static
    239 ChromeURLRequestContextGetter*
    240 ChromeURLRequestContextGetter::CreateForIsolatedMedia(
    241     Profile* profile,
    242     ChromeURLRequestContextGetter* app_context,
    243     const ProfileIOData* profile_io_data,
    244     const StoragePartitionDescriptor& partition_descriptor) {
    245   return new ChromeURLRequestContextGetter(
    246       new FactoryForIsolatedMedia(
    247           profile_io_data, partition_descriptor, app_context));
    248 }
    249 
    250 // ----------------------------------------------------------------------------
    251 // ChromeURLRequestContext
    252 // ----------------------------------------------------------------------------
    253 
    254 ChromeURLRequestContext::ChromeURLRequestContext(
    255     ContextType type,
    256     chrome_browser_net::LoadTimeStats* load_time_stats)
    257     : weak_factory_(this),
    258       load_time_stats_(load_time_stats) {
    259   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    260   if (load_time_stats_)
    261     load_time_stats_->RegisterURLRequestContext(this, type);
    262 }
    263 
    264 ChromeURLRequestContext::~ChromeURLRequestContext() {
    265   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    266   if (load_time_stats_)
    267     load_time_stats_->UnregisterURLRequestContext(this);
    268 }
    269 
    270 void ChromeURLRequestContext::CopyFrom(ChromeURLRequestContext* other) {
    271   URLRequestContext::CopyFrom(other);
    272 
    273   // Copy ChromeURLRequestContext parameters.
    274 }
    275