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