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/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 ChromeURLRequestContext* 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 ChromeURLRequestContext. 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 ChromeURLRequestContext* 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 ChromeURLRequestContext 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 ChromeURLRequestContext* 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 ChromeURLRequestContext 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 ChromeURLRequestContext* 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 ChromeURLRequestContext 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 ChromeURLRequestContext* 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 ChromeURLRequestContext 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 ChromeURLRequestContext* 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 DCHECK(factory); 174 } 175 176 ChromeURLRequestContextGetter::~ChromeURLRequestContextGetter() {} 177 178 // Lazily create a ChromeURLRequestContext using our factory. 179 ChromeURLRequestContext* 180 ChromeURLRequestContextGetter::GetURLRequestContext() { 181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 182 183 if (!url_request_context_.get()) { 184 DCHECK(factory_.get()); 185 url_request_context_ = factory_->Create()->GetWeakPtr(); 186 factory_.reset(); 187 } 188 189 // Should not be NULL, unless we're trying to use the URLRequestContextGetter 190 // after the Profile has already been deleted. 191 CHECK(url_request_context_.get()); 192 193 return url_request_context_.get(); 194 } 195 196 scoped_refptr<base::SingleThreadTaskRunner> 197 ChromeURLRequestContextGetter::GetNetworkTaskRunner() const { 198 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 199 } 200 201 // static 202 ChromeURLRequestContextGetter* ChromeURLRequestContextGetter::Create( 203 Profile* profile, 204 const ProfileIOData* profile_io_data, 205 content::ProtocolHandlerMap* protocol_handlers, 206 content::URLRequestInterceptorScopedVector request_interceptors) { 207 return new ChromeURLRequestContextGetter(new FactoryForMain( 208 profile_io_data, protocol_handlers, request_interceptors.Pass())); 209 } 210 211 // static 212 ChromeURLRequestContextGetter* 213 ChromeURLRequestContextGetter::CreateForMedia( 214 Profile* profile, const ProfileIOData* profile_io_data) { 215 return new ChromeURLRequestContextGetter( 216 new FactoryForMedia(profile_io_data)); 217 } 218 219 // static 220 ChromeURLRequestContextGetter* 221 ChromeURLRequestContextGetter::CreateForExtensions( 222 Profile* profile, const ProfileIOData* profile_io_data) { 223 return new ChromeURLRequestContextGetter( 224 new FactoryForExtensions(profile_io_data)); 225 } 226 227 // static 228 ChromeURLRequestContextGetter* 229 ChromeURLRequestContextGetter::CreateForIsolatedApp( 230 Profile* profile, 231 const ProfileIOData* profile_io_data, 232 const StoragePartitionDescriptor& partition_descriptor, 233 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> 234 protocol_handler_interceptor, 235 content::ProtocolHandlerMap* protocol_handlers, 236 content::URLRequestInterceptorScopedVector request_interceptors) { 237 ChromeURLRequestContextGetter* main_context = 238 static_cast<ChromeURLRequestContextGetter*>(profile->GetRequestContext()); 239 return new ChromeURLRequestContextGetter( 240 new FactoryForIsolatedApp(profile_io_data, 241 partition_descriptor, 242 main_context, 243 protocol_handler_interceptor.Pass(), 244 protocol_handlers, 245 request_interceptors.Pass())); 246 } 247 248 // static 249 ChromeURLRequestContextGetter* 250 ChromeURLRequestContextGetter::CreateForIsolatedMedia( 251 Profile* profile, 252 ChromeURLRequestContextGetter* app_context, 253 const ProfileIOData* profile_io_data, 254 const StoragePartitionDescriptor& partition_descriptor) { 255 return new ChromeURLRequestContextGetter( 256 new FactoryForIsolatedMedia( 257 profile_io_data, partition_descriptor, app_context)); 258 } 259 260 // ---------------------------------------------------------------------------- 261 // ChromeURLRequestContext 262 // ---------------------------------------------------------------------------- 263 264 ChromeURLRequestContext::ChromeURLRequestContext() 265 : weak_factory_(this) { 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 267 } 268 269 ChromeURLRequestContext::~ChromeURLRequestContext() { 270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 271 } 272 273 void ChromeURLRequestContext::CopyFrom(ChromeURLRequestContext* other) { 274 URLRequestContext::CopyFrom(other); 275 276 // Copy ChromeURLRequestContext parameters. 277 } 278