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 19using content::BrowserThread; 20 21class 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 33namespace { 34 35// ---------------------------------------------------------------------------- 36// Helper factories 37// ---------------------------------------------------------------------------- 38 39// Factory that creates the main URLRequestContext. 40class 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. 63class 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. 77class 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. 122class 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. 150class 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 170ChromeURLRequestContextGetter::ChromeURLRequestContextGetter( 171 ChromeURLRequestContextFactory* factory) 172 : factory_(factory), 173 url_request_context_(NULL) { 174 DCHECK(factory); 175} 176 177ChromeURLRequestContextGetter::~ChromeURLRequestContextGetter() {} 178 179// Lazily create a URLRequestContext using our factory. 180net::URLRequestContext* 181ChromeURLRequestContextGetter::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 197void ChromeURLRequestContextGetter::Invalidate() { 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 199 factory_.reset(); 200 url_request_context_ = NULL; 201} 202 203scoped_refptr<base::SingleThreadTaskRunner> 204ChromeURLRequestContextGetter::GetNetworkTaskRunner() const { 205 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 206} 207 208// static 209ChromeURLRequestContextGetter* 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 219ChromeURLRequestContextGetter* 220ChromeURLRequestContextGetter::CreateForMedia( 221 Profile* profile, const ProfileIOData* profile_io_data) { 222 return new ChromeURLRequestContextGetter( 223 new FactoryForMedia(profile_io_data)); 224} 225 226// static 227ChromeURLRequestContextGetter* 228ChromeURLRequestContextGetter::CreateForExtensions( 229 Profile* profile, const ProfileIOData* profile_io_data) { 230 return new ChromeURLRequestContextGetter( 231 new FactoryForExtensions(profile_io_data)); 232} 233 234// static 235ChromeURLRequestContextGetter* 236ChromeURLRequestContextGetter::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 256ChromeURLRequestContextGetter* 257ChromeURLRequestContextGetter::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