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/profiles/off_the_record_profile_io_data.h" 6 7 #include "base/bind.h" 8 #include "base/command_line.h" 9 #include "base/logging.h" 10 #include "base/prefs/pref_service.h" 11 #include "base/stl_util.h" 12 #include "base/threading/worker_pool.h" 13 #include "build/build_config.h" 14 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" 16 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" 17 #include "chrome/browser/io_thread.h" 18 #include "chrome/browser/net/about_protocol_handler.h" 19 #include "chrome/browser/net/chrome_net_log.h" 20 #include "chrome/browser/net/chrome_network_delegate.h" 21 #include "chrome/browser/net/chrome_url_request_context.h" 22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/common/chrome_switches.h" 24 #include "chrome/common/extensions/extension.h" 25 #include "chrome/common/pref_names.h" 26 #include "chrome/common/url_constants.h" 27 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/resource_context.h" 29 #include "extensions/common/constants.h" 30 #include "net/ftp/ftp_network_layer.h" 31 #include "net/http/http_cache.h" 32 #include "net/http/http_network_session.h" 33 #include "net/http/http_server_properties_impl.h" 34 #include "net/ssl/default_server_bound_cert_store.h" 35 #include "net/ssl/server_bound_cert_service.h" 36 #include "net/url_request/protocol_intercept_job_factory.h" 37 #include "net/url_request/url_request_job_factory_impl.h" 38 #include "webkit/browser/database/database_tracker.h" 39 40 using content::BrowserThread; 41 42 OffTheRecordProfileIOData::Handle::Handle(Profile* profile) 43 : io_data_(new OffTheRecordProfileIOData), 44 profile_(profile), 45 initialized_(false) { 46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 47 DCHECK(profile); 48 } 49 50 OffTheRecordProfileIOData::Handle::~Handle() { 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 52 io_data_->ShutdownOnUIThread(); 53 } 54 55 content::ResourceContext* 56 OffTheRecordProfileIOData::Handle::GetResourceContext() const { 57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 58 LazyInitialize(); 59 return GetResourceContextNoInit(); 60 } 61 62 content::ResourceContext* 63 OffTheRecordProfileIOData::Handle::GetResourceContextNoInit() const { 64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 65 // Don't call LazyInitialize here, since the resource context is created at 66 // the beginning of initalization and is used by some members while they're 67 // being initialized (i.e. AppCacheService). 68 return io_data_->GetResourceContext(); 69 } 70 71 scoped_refptr<ChromeURLRequestContextGetter> 72 OffTheRecordProfileIOData::Handle::CreateMainRequestContextGetter( 73 content::ProtocolHandlerMap* protocol_handlers) const { 74 // TODO(oshima): Re-enable when ChromeOS only accesses the profile on the UI 75 // thread. 76 #if !defined(OS_CHROMEOS) 77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 78 #endif // defined(OS_CHROMEOS) 79 LazyInitialize(); 80 DCHECK(!main_request_context_getter_.get()); 81 main_request_context_getter_ = 82 ChromeURLRequestContextGetter::CreateOffTheRecord( 83 profile_, io_data_, protocol_handlers); 84 return main_request_context_getter_; 85 } 86 87 scoped_refptr<ChromeURLRequestContextGetter> 88 OffTheRecordProfileIOData::Handle::GetExtensionsRequestContextGetter() const { 89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 90 LazyInitialize(); 91 if (!extensions_request_context_getter_.get()) { 92 extensions_request_context_getter_ = 93 ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions( 94 profile_, io_data_); 95 } 96 return extensions_request_context_getter_; 97 } 98 99 scoped_refptr<ChromeURLRequestContextGetter> 100 OffTheRecordProfileIOData::Handle::GetIsolatedAppRequestContextGetter( 101 const base::FilePath& partition_path, 102 bool in_memory) const { 103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 104 DCHECK(!partition_path.empty()); 105 LazyInitialize(); 106 107 // Keep a map of request context getters, one per requested app ID. 108 StoragePartitionDescriptor descriptor(partition_path, in_memory); 109 ChromeURLRequestContextGetterMap::iterator iter = 110 app_request_context_getter_map_.find(descriptor); 111 CHECK(iter != app_request_context_getter_map_.end()); 112 return iter->second; 113 } 114 115 scoped_refptr<ChromeURLRequestContextGetter> 116 OffTheRecordProfileIOData::Handle::CreateIsolatedAppRequestContextGetter( 117 const base::FilePath& partition_path, 118 bool in_memory, 119 content::ProtocolHandlerMap* protocol_handlers) const { 120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 121 DCHECK(!partition_path.empty()); 122 LazyInitialize(); 123 124 // Keep a map of request context getters, one per requested app ID. 125 StoragePartitionDescriptor descriptor(partition_path, in_memory); 126 DCHECK_EQ(app_request_context_getter_map_.count(descriptor), 0u); 127 128 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> 129 protocol_handler_interceptor( 130 ProtocolHandlerRegistryFactory::GetForProfile(profile_)-> 131 CreateJobInterceptorFactory()); 132 ChromeURLRequestContextGetter* context = 133 ChromeURLRequestContextGetter::CreateOffTheRecordForIsolatedApp( 134 profile_, io_data_, descriptor, protocol_handler_interceptor.Pass(), 135 protocol_handlers); 136 app_request_context_getter_map_[descriptor] = context; 137 138 return context; 139 } 140 141 void OffTheRecordProfileIOData::Handle::LazyInitialize() const { 142 if (initialized_) 143 return; 144 145 // Set initialized_ to true at the beginning in case any of the objects 146 // below try to get the ResourceContext pointer. 147 initialized_ = true; 148 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING) 149 io_data_->safe_browsing_enabled()->Init(prefs::kSafeBrowsingEnabled, 150 profile_->GetPrefs()); 151 io_data_->safe_browsing_enabled()->MoveToThread( 152 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); 153 #endif 154 io_data_->InitializeOnUIThread(profile_); 155 } 156 157 OffTheRecordProfileIOData::OffTheRecordProfileIOData() 158 : ProfileIOData(true) {} 159 OffTheRecordProfileIOData::~OffTheRecordProfileIOData() { 160 DestroyResourceContext(); 161 } 162 163 void OffTheRecordProfileIOData::InitializeInternal( 164 ProfileParams* profile_params, 165 content::ProtocolHandlerMap* protocol_handlers) const { 166 ChromeURLRequestContext* main_context = main_request_context(); 167 168 IOThread* const io_thread = profile_params->io_thread; 169 IOThread::Globals* const io_thread_globals = io_thread->globals(); 170 171 ApplyProfileParamsToContext(main_context); 172 173 main_context->set_transport_security_state(transport_security_state()); 174 175 main_context->set_net_log(io_thread->net_log()); 176 177 main_context->set_network_delegate(network_delegate()); 178 179 main_context->set_host_resolver( 180 io_thread_globals->host_resolver.get()); 181 main_context->set_cert_verifier( 182 io_thread_globals->cert_verifier.get()); 183 main_context->set_http_auth_handler_factory( 184 io_thread_globals->http_auth_handler_factory.get()); 185 main_context->set_fraudulent_certificate_reporter( 186 fraudulent_certificate_reporter()); 187 main_context->set_proxy_service(proxy_service()); 188 189 main_context->set_throttler_manager( 190 io_thread_globals->throttler_manager.get()); 191 192 // For incognito, we use the default non-persistent HttpServerPropertiesImpl. 193 set_http_server_properties( 194 scoped_ptr<net::HttpServerProperties>( 195 new net::HttpServerPropertiesImpl())); 196 main_context->set_http_server_properties(http_server_properties()); 197 198 // For incognito, we use a non-persistent server bound cert store. 199 net::ServerBoundCertService* server_bound_cert_service = 200 new net::ServerBoundCertService( 201 new net::DefaultServerBoundCertStore(NULL), 202 base::WorkerPool::GetTaskRunner(true)); 203 set_server_bound_cert_service(server_bound_cert_service); 204 main_context->set_server_bound_cert_service(server_bound_cert_service); 205 206 main_context->set_cookie_store(new net::CookieMonster( 207 NULL, profile_params->cookie_monster_delegate.get())); 208 209 net::HttpCache::BackendFactory* main_backend = 210 net::HttpCache::DefaultBackend::InMemory(0); 211 net::HttpNetworkSession::Params network_session_params; 212 PopulateNetworkSessionParams(profile_params, &network_session_params); 213 net::HttpCache* cache = new net::HttpCache( 214 network_session_params, main_backend); 215 216 main_http_factory_.reset(cache); 217 main_context->set_http_transaction_factory(cache); 218 #if !defined(DISABLE_FTP_SUPPORT) 219 ftp_factory_.reset( 220 new net::FtpNetworkLayer(main_context->host_resolver())); 221 #endif // !defined(DISABLE_FTP_SUPPORT) 222 223 scoped_ptr<net::URLRequestJobFactoryImpl> main_job_factory( 224 new net::URLRequestJobFactoryImpl()); 225 226 InstallProtocolHandlers(main_job_factory.get(), protocol_handlers); 227 main_job_factory_ = SetUpJobFactoryDefaults( 228 main_job_factory.Pass(), 229 profile_params->protocol_handler_interceptor.Pass(), 230 network_delegate(), 231 ftp_factory_.get()); 232 main_context->set_job_factory(main_job_factory_.get()); 233 234 #if defined(ENABLE_EXTENSIONS) 235 InitializeExtensionsRequestContext(profile_params); 236 #endif 237 } 238 239 void OffTheRecordProfileIOData:: 240 InitializeExtensionsRequestContext(ProfileParams* profile_params) const { 241 ChromeURLRequestContext* extensions_context = extensions_request_context(); 242 243 IOThread* const io_thread = profile_params->io_thread; 244 IOThread::Globals* const io_thread_globals = io_thread->globals(); 245 246 ApplyProfileParamsToContext(extensions_context); 247 248 extensions_context->set_transport_security_state(transport_security_state()); 249 250 extensions_context->set_net_log(io_thread->net_log()); 251 252 extensions_context->set_throttler_manager( 253 io_thread_globals->throttler_manager.get()); 254 255 // All we care about for extensions is the cookie store. For incognito, we 256 // use a non-persistent cookie store. 257 net::CookieMonster* extensions_cookie_store = 258 new net::CookieMonster(NULL, NULL); 259 // Enable cookies for devtools and extension URLs. 260 const char* schemes[] = {chrome::kChromeDevToolsScheme, 261 extensions::kExtensionScheme}; 262 extensions_cookie_store->SetCookieableSchemes(schemes, 2); 263 extensions_context->set_cookie_store(extensions_cookie_store); 264 265 scoped_ptr<net::URLRequestJobFactoryImpl> extensions_job_factory( 266 new net::URLRequestJobFactoryImpl()); 267 // TODO(shalev): The extensions_job_factory has a NULL NetworkDelegate. 268 // Without a network_delegate, this protocol handler will never 269 // handle file: requests, but as a side effect it makes 270 // job_factory::IsHandledProtocol return true, which prevents attempts to 271 // handle the protocol externally. We pass NULL in to 272 // SetUpJobFactoryDefaults() to get this effect. 273 extensions_job_factory_ = SetUpJobFactoryDefaults( 274 extensions_job_factory.Pass(), 275 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>(), 276 NULL, 277 ftp_factory_.get()); 278 extensions_context->set_job_factory(extensions_job_factory_.get()); 279 } 280 281 ChromeURLRequestContext* 282 OffTheRecordProfileIOData::InitializeAppRequestContext( 283 ChromeURLRequestContext* main_context, 284 const StoragePartitionDescriptor& partition_descriptor, 285 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> 286 protocol_handler_interceptor, 287 content::ProtocolHandlerMap* protocol_handlers) const { 288 AppRequestContext* context = new AppRequestContext(load_time_stats()); 289 290 // Copy most state from the main context. 291 context->CopyFrom(main_context); 292 293 // Use a separate in-memory cookie store for the app. 294 // TODO(creis): We should have a cookie delegate for notifying the cookie 295 // extensions API, but we need to update it to understand isolated apps first. 296 context->SetCookieStore(new net::CookieMonster(NULL, NULL)); 297 298 // Use a separate in-memory cache for the app. 299 net::HttpCache::BackendFactory* app_backend = 300 net::HttpCache::DefaultBackend::InMemory(0); 301 net::HttpNetworkSession* main_network_session = 302 main_http_factory_->GetSession(); 303 scoped_ptr<net::HttpTransactionFactory> app_http_cache( 304 new net::HttpCache(main_network_session, app_backend)); 305 306 context->SetHttpTransactionFactory(app_http_cache.Pass()); 307 308 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory( 309 new net::URLRequestJobFactoryImpl()); 310 InstallProtocolHandlers(job_factory.get(), protocol_handlers); 311 scoped_ptr<net::URLRequestJobFactory> top_job_factory; 312 top_job_factory = SetUpJobFactoryDefaults(job_factory.Pass(), 313 protocol_handler_interceptor.Pass(), 314 network_delegate(), 315 ftp_factory_.get()); 316 context->SetJobFactory(top_job_factory.Pass()); 317 return context; 318 } 319 320 ChromeURLRequestContext* 321 OffTheRecordProfileIOData::InitializeMediaRequestContext( 322 ChromeURLRequestContext* original_context, 323 const StoragePartitionDescriptor& partition_descriptor) const { 324 NOTREACHED(); 325 return NULL; 326 } 327 328 ChromeURLRequestContext* 329 OffTheRecordProfileIOData::AcquireMediaRequestContext() const { 330 NOTREACHED(); 331 return NULL; 332 } 333 334 ChromeURLRequestContext* 335 OffTheRecordProfileIOData::AcquireIsolatedAppRequestContext( 336 ChromeURLRequestContext* main_context, 337 const StoragePartitionDescriptor& partition_descriptor, 338 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> 339 protocol_handler_interceptor, 340 content::ProtocolHandlerMap* protocol_handlers) const { 341 // We create per-app contexts on demand, unlike the others above. 342 ChromeURLRequestContext* app_request_context = 343 InitializeAppRequestContext(main_context, partition_descriptor, 344 protocol_handler_interceptor.Pass(), 345 protocol_handlers); 346 DCHECK(app_request_context); 347 return app_request_context; 348 } 349 350 ChromeURLRequestContext* 351 OffTheRecordProfileIOData::AcquireIsolatedMediaRequestContext( 352 ChromeURLRequestContext* app_context, 353 const StoragePartitionDescriptor& partition_descriptor) const { 354 NOTREACHED(); 355 return NULL; 356 } 357 358 chrome_browser_net::LoadTimeStats* OffTheRecordProfileIOData::GetLoadTimeStats( 359 IOThread::Globals* io_thread_globals) const { 360 return NULL; 361 } 362