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