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/profile_impl_io_data.h" 6 7 #include "base/bind.h" 8 #include "base/command_line.h" 9 #include "base/logging.h" 10 #include "base/metrics/field_trial.h" 11 #include "base/prefs/pref_member.h" 12 #include "base/prefs/pref_service.h" 13 #include "base/sequenced_task_runner.h" 14 #include "base/stl_util.h" 15 #include "base/strings/string_util.h" 16 #include "base/threading/sequenced_worker_pool.h" 17 #include "base/threading/worker_pool.h" 18 #include "chrome/browser/chrome_notification_types.h" 19 #include "chrome/browser/chromeos/profiles/profile_helper.h" 20 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" 21 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" 22 #include "chrome/browser/extensions/extension_protocols.h" 23 #include "chrome/browser/io_thread.h" 24 #include "chrome/browser/net/chrome_net_log.h" 25 #include "chrome/browser/net/chrome_network_delegate.h" 26 #include "chrome/browser/net/connect_interceptor.h" 27 #include "chrome/browser/net/http_server_properties_manager.h" 28 #include "chrome/browser/net/predictor.h" 29 #include "chrome/browser/net/sqlite_server_bound_cert_store.h" 30 #include "chrome/browser/profiles/profile.h" 31 #include "chrome/common/chrome_constants.h" 32 #include "chrome/common/chrome_switches.h" 33 #include "chrome/common/pref_names.h" 34 #include "chrome/common/url_constants.h" 35 #include "components/webdata/encryptor/encryptor.h" 36 #include "content/public/browser/browser_thread.h" 37 #include "content/public/browser/cookie_crypto_delegate.h" 38 #include "content/public/browser/cookie_store_factory.h" 39 #include "content/public/browser/notification_service.h" 40 #include "content/public/browser/resource_context.h" 41 #include "content/public/browser/storage_partition.h" 42 #include "extensions/common/constants.h" 43 #include "net/base/cache_type.h" 44 #include "net/ftp/ftp_network_layer.h" 45 #include "net/http/http_cache.h" 46 #include "net/ssl/server_bound_cert_service.h" 47 #include "net/url_request/protocol_intercept_job_factory.h" 48 #include "net/url_request/url_request_job_factory_impl.h" 49 #include "webkit/browser/quota/special_storage_policy.h" 50 51 #if defined(OS_ANDROID) || defined(OS_IOS) 52 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_settings.h" 53 #endif 54 55 namespace { 56 57 // Use the operating system's mechanisms to encrypt cookies before writing 58 // them to persistent store. Currently this only is done with desktop OS's 59 // because ChromeOS and Android already protect the entire profile contents. 60 // 61 // TODO(bcwhite): Enable on MACOSX -- requires all Cookie tests to call 62 // Encryptor::UseMockKeychain or will hang waiting for user input. 63 #if defined(OS_WIN) || defined(OS_LINUX) // || defined(OS_MACOSX) 64 class CookieOSCryptoDelegate : public content::CookieCryptoDelegate { 65 public: 66 virtual bool EncryptString(const std::string& plaintext, 67 std::string* ciphertext) OVERRIDE; 68 virtual bool DecryptString(const std::string& ciphertext, 69 std::string* plaintext) OVERRIDE; 70 }; 71 72 bool CookieOSCryptoDelegate::EncryptString(const std::string& plaintext, 73 std::string* ciphertext) { 74 return Encryptor::EncryptString(plaintext, ciphertext); 75 } 76 77 bool CookieOSCryptoDelegate::DecryptString(const std::string& ciphertext, 78 std::string* plaintext) { 79 return Encryptor::DecryptString(ciphertext, plaintext); 80 } 81 82 scoped_ptr<content::CookieCryptoDelegate> CreateCookieCryptoIfUseful() { 83 return scoped_ptr<content::CookieCryptoDelegate>( 84 new CookieOSCryptoDelegate); 85 } 86 #else 87 scoped_ptr<content::CookieCryptoDelegate> CreateCookieCryptoIfUseful() { 88 return scoped_ptr<content::CookieCryptoDelegate>(); 89 } 90 #endif 91 92 93 net::BackendType ChooseCacheBackendType() { 94 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 95 if (command_line.HasSwitch(switches::kUseSimpleCacheBackend)) { 96 const std::string opt_value = 97 command_line.GetSwitchValueASCII(switches::kUseSimpleCacheBackend); 98 if (LowerCaseEqualsASCII(opt_value, "off")) 99 return net::CACHE_BACKEND_BLOCKFILE; 100 if (opt_value == "" || LowerCaseEqualsASCII(opt_value, "on")) 101 return net::CACHE_BACKEND_SIMPLE; 102 } 103 const std::string experiment_name = 104 base::FieldTrialList::FindFullName("SimpleCacheTrial"); 105 #if defined(OS_ANDROID) 106 if (experiment_name == "ExperimentNo" || 107 experiment_name == "ExperimentControl") { 108 return net::CACHE_BACKEND_BLOCKFILE; 109 } 110 return net::CACHE_BACKEND_SIMPLE; 111 #else 112 if (experiment_name == "ExperimentYes" || 113 experiment_name == "ExperimentYes2") { 114 return net::CACHE_BACKEND_SIMPLE; 115 } 116 return net::CACHE_BACKEND_BLOCKFILE; 117 #endif 118 } 119 120 } // namespace 121 122 using content::BrowserThread; 123 124 ProfileImplIOData::Handle::Handle(Profile* profile) 125 : io_data_(new ProfileImplIOData), 126 profile_(profile), 127 initialized_(false) { 128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 129 DCHECK(profile); 130 } 131 132 ProfileImplIOData::Handle::~Handle() { 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 134 if (io_data_->predictor_ != NULL) { 135 // io_data_->predictor_ might be NULL if Init() was never called 136 // (i.e. we shut down before ProfileImpl::DoFinalInit() got called). 137 bool save_prefs = true; 138 #if defined(OS_CHROMEOS) 139 save_prefs = !chromeos::ProfileHelper::IsSigninProfile(profile_); 140 #endif 141 if (save_prefs) { 142 io_data_->predictor_->SaveStateForNextStartupAndTrim( 143 profile_->GetPrefs()); 144 } 145 io_data_->predictor_->ShutdownOnUIThread(); 146 } 147 148 if (io_data_->http_server_properties_manager_) 149 io_data_->http_server_properties_manager_->ShutdownOnUIThread(); 150 io_data_->ShutdownOnUIThread(); 151 } 152 153 void ProfileImplIOData::Handle::Init( 154 const base::FilePath& cookie_path, 155 const base::FilePath& server_bound_cert_path, 156 const base::FilePath& cache_path, 157 int cache_max_size, 158 const base::FilePath& media_cache_path, 159 int media_cache_max_size, 160 const base::FilePath& extensions_cookie_path, 161 const base::FilePath& profile_path, 162 const base::FilePath& infinite_cache_path, 163 chrome_browser_net::Predictor* predictor, 164 bool restore_old_session_cookies, 165 quota::SpecialStoragePolicy* special_storage_policy) { 166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 167 DCHECK(!io_data_->lazy_params_); 168 DCHECK(predictor); 169 170 LazyParams* lazy_params = new LazyParams; 171 172 lazy_params->cookie_path = cookie_path; 173 lazy_params->server_bound_cert_path = server_bound_cert_path; 174 lazy_params->cache_path = cache_path; 175 lazy_params->cache_max_size = cache_max_size; 176 lazy_params->media_cache_path = media_cache_path; 177 lazy_params->media_cache_max_size = media_cache_max_size; 178 lazy_params->extensions_cookie_path = extensions_cookie_path; 179 lazy_params->infinite_cache_path = infinite_cache_path; 180 lazy_params->restore_old_session_cookies = restore_old_session_cookies; 181 lazy_params->special_storage_policy = special_storage_policy; 182 183 io_data_->lazy_params_.reset(lazy_params); 184 185 // Keep track of profile path and cache sizes separately so we can use them 186 // on demand when creating storage isolated URLRequestContextGetters. 187 io_data_->profile_path_ = profile_path; 188 io_data_->app_cache_max_size_ = cache_max_size; 189 io_data_->app_media_cache_max_size_ = media_cache_max_size; 190 191 io_data_->predictor_.reset(predictor); 192 193 io_data_->InitializeMetricsEnabledStateOnUIThread(); 194 } 195 196 content::ResourceContext* 197 ProfileImplIOData::Handle::GetResourceContext() const { 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 199 LazyInitialize(); 200 return GetResourceContextNoInit(); 201 } 202 203 content::ResourceContext* 204 ProfileImplIOData::Handle::GetResourceContextNoInit() const { 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 206 // Don't call LazyInitialize here, since the resource context is created at 207 // the beginning of initalization and is used by some members while they're 208 // being initialized (i.e. AppCacheService). 209 return io_data_->GetResourceContext(); 210 } 211 212 scoped_refptr<ChromeURLRequestContextGetter> 213 ProfileImplIOData::Handle::CreateMainRequestContextGetter( 214 content::ProtocolHandlerMap* protocol_handlers, 215 PrefService* local_state, 216 IOThread* io_thread) const { 217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 218 LazyInitialize(); 219 DCHECK(!main_request_context_getter_.get()); 220 main_request_context_getter_ = ChromeURLRequestContextGetter::Create( 221 profile_, io_data_, protocol_handlers); 222 223 io_data_->predictor_ 224 ->InitNetworkPredictor(profile_->GetPrefs(), 225 local_state, 226 io_thread, 227 main_request_context_getter_.get()); 228 229 content::NotificationService::current()->Notify( 230 chrome::NOTIFICATION_PROFILE_URL_REQUEST_CONTEXT_GETTER_INITIALIZED, 231 content::Source<Profile>(profile_), 232 content::NotificationService::NoDetails()); 233 return main_request_context_getter_; 234 } 235 236 scoped_refptr<ChromeURLRequestContextGetter> 237 ProfileImplIOData::Handle::GetMediaRequestContextGetter() const { 238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 239 LazyInitialize(); 240 if (!media_request_context_getter_.get()) { 241 media_request_context_getter_ = 242 ChromeURLRequestContextGetter::CreateForMedia(profile_, io_data_); 243 } 244 return media_request_context_getter_; 245 } 246 247 scoped_refptr<ChromeURLRequestContextGetter> 248 ProfileImplIOData::Handle::GetExtensionsRequestContextGetter() const { 249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 250 LazyInitialize(); 251 if (!extensions_request_context_getter_.get()) { 252 extensions_request_context_getter_ = 253 ChromeURLRequestContextGetter::CreateForExtensions(profile_, io_data_); 254 } 255 return extensions_request_context_getter_; 256 } 257 258 scoped_refptr<ChromeURLRequestContextGetter> 259 ProfileImplIOData::Handle::CreateIsolatedAppRequestContextGetter( 260 const base::FilePath& partition_path, 261 bool in_memory, 262 content::ProtocolHandlerMap* protocol_handlers) const { 263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 264 // Check that the partition_path is not the same as the base profile path. We 265 // expect isolated partition, which will never go to the default profile path. 266 CHECK(partition_path != profile_->GetPath()); 267 LazyInitialize(); 268 269 // Keep a map of request context getters, one per requested storage partition. 270 StoragePartitionDescriptor descriptor(partition_path, in_memory); 271 ChromeURLRequestContextGetterMap::iterator iter = 272 app_request_context_getter_map_.find(descriptor); 273 if (iter != app_request_context_getter_map_.end()) 274 return iter->second; 275 276 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> 277 protocol_handler_interceptor( 278 ProtocolHandlerRegistryFactory::GetForProfile(profile_)-> 279 CreateJobInterceptorFactory()); 280 ChromeURLRequestContextGetter* context = 281 ChromeURLRequestContextGetter::CreateForIsolatedApp( 282 profile_, io_data_, descriptor, 283 protocol_handler_interceptor.Pass(), 284 protocol_handlers); 285 app_request_context_getter_map_[descriptor] = context; 286 287 return context; 288 } 289 290 scoped_refptr<ChromeURLRequestContextGetter> 291 ProfileImplIOData::Handle::GetIsolatedMediaRequestContextGetter( 292 const base::FilePath& partition_path, 293 bool in_memory) const { 294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 295 // We must have a non-default path, or this will act like the default media 296 // context. 297 CHECK(partition_path != profile_->GetPath()); 298 LazyInitialize(); 299 300 // Keep a map of request context getters, one per requested storage partition. 301 StoragePartitionDescriptor descriptor(partition_path, in_memory); 302 ChromeURLRequestContextGetterMap::iterator iter = 303 isolated_media_request_context_getter_map_.find(descriptor); 304 if (iter != isolated_media_request_context_getter_map_.end()) 305 return iter->second; 306 307 // Get the app context as the starting point for the media context, so that 308 // it uses the app's cookie store. 309 ChromeURLRequestContextGetterMap::const_iterator app_iter = 310 app_request_context_getter_map_.find(descriptor); 311 DCHECK(app_iter != app_request_context_getter_map_.end()); 312 ChromeURLRequestContextGetter* app_context = app_iter->second.get(); 313 ChromeURLRequestContextGetter* context = 314 ChromeURLRequestContextGetter::CreateForIsolatedMedia( 315 profile_, app_context, io_data_, descriptor); 316 isolated_media_request_context_getter_map_[descriptor] = context; 317 318 return context; 319 } 320 321 void ProfileImplIOData::Handle::ClearNetworkingHistorySince( 322 base::Time time, 323 const base::Closure& completion) { 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 325 LazyInitialize(); 326 327 BrowserThread::PostTask( 328 BrowserThread::IO, FROM_HERE, 329 base::Bind( 330 &ProfileImplIOData::ClearNetworkingHistorySinceOnIOThread, 331 base::Unretained(io_data_), 332 time, 333 completion)); 334 } 335 336 void ProfileImplIOData::Handle::LazyInitialize() const { 337 if (initialized_) 338 return; 339 340 // Set initialized_ to true at the beginning in case any of the objects 341 // below try to get the ResourceContext pointer. 342 initialized_ = true; 343 PrefService* pref_service = profile_->GetPrefs(); 344 io_data_->http_server_properties_manager_ = 345 new chrome_browser_net::HttpServerPropertiesManager(pref_service); 346 io_data_->set_http_server_properties( 347 scoped_ptr<net::HttpServerProperties>( 348 io_data_->http_server_properties_manager_)); 349 io_data_->session_startup_pref()->Init( 350 prefs::kRestoreOnStartup, pref_service); 351 io_data_->session_startup_pref()->MoveToThread( 352 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); 353 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING) 354 io_data_->safe_browsing_enabled()->Init(prefs::kSafeBrowsingEnabled, 355 pref_service); 356 io_data_->safe_browsing_enabled()->MoveToThread( 357 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); 358 #endif 359 io_data_->InitializeOnUIThread(profile_); 360 } 361 362 ProfileImplIOData::LazyParams::LazyParams() 363 : cache_max_size(0), 364 media_cache_max_size(0), 365 restore_old_session_cookies(false) {} 366 367 ProfileImplIOData::LazyParams::~LazyParams() {} 368 369 ProfileImplIOData::ProfileImplIOData() 370 : ProfileIOData(false), 371 http_server_properties_manager_(NULL), 372 app_cache_max_size_(0), 373 app_media_cache_max_size_(0) {} 374 ProfileImplIOData::~ProfileImplIOData() { 375 DestroyResourceContext(); 376 377 if (media_request_context_) 378 media_request_context_->AssertNoURLRequests(); 379 } 380 381 void ProfileImplIOData::InitializeInternal( 382 ProfileParams* profile_params, 383 content::ProtocolHandlerMap* protocol_handlers) const { 384 ChromeURLRequestContext* main_context = main_request_context(); 385 386 IOThread* const io_thread = profile_params->io_thread; 387 IOThread::Globals* const io_thread_globals = io_thread->globals(); 388 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 389 bool record_mode = command_line.HasSwitch(switches::kRecordMode) && 390 chrome::kRecordModeEnabled; 391 bool playback_mode = command_line.HasSwitch(switches::kPlaybackMode); 392 393 network_delegate()->set_predictor(predictor_.get()); 394 395 // Initialize context members. 396 397 ApplyProfileParamsToContext(main_context); 398 399 if (http_server_properties_manager_) 400 http_server_properties_manager_->InitializeOnIOThread(); 401 402 main_context->set_transport_security_state(transport_security_state()); 403 404 main_context->set_net_log(io_thread->net_log()); 405 406 main_context->set_network_delegate(network_delegate()); 407 408 main_context->set_http_server_properties(http_server_properties()); 409 410 main_context->set_host_resolver( 411 io_thread_globals->host_resolver.get()); 412 main_context->set_cert_transparency_verifier( 413 io_thread_globals->cert_transparency_verifier.get()); 414 main_context->set_http_auth_handler_factory( 415 io_thread_globals->http_auth_handler_factory.get()); 416 417 main_context->set_fraudulent_certificate_reporter( 418 fraudulent_certificate_reporter()); 419 420 main_context->set_throttler_manager( 421 io_thread_globals->throttler_manager.get()); 422 423 main_context->set_proxy_service(proxy_service()); 424 425 scoped_refptr<net::CookieStore> cookie_store = NULL; 426 net::ServerBoundCertService* server_bound_cert_service = NULL; 427 if (record_mode || playback_mode) { 428 // Don't use existing cookies and use an in-memory store. 429 cookie_store = new net::CookieMonster( 430 NULL, profile_params->cookie_monster_delegate.get()); 431 // Don't use existing server-bound certs and use an in-memory store. 432 server_bound_cert_service = new net::ServerBoundCertService( 433 new net::DefaultServerBoundCertStore(NULL), 434 base::WorkerPool::GetTaskRunner(true)); 435 } 436 437 // setup cookie store 438 if (!cookie_store.get()) { 439 DCHECK(!lazy_params_->cookie_path.empty()); 440 441 cookie_store = content::CreatePersistentCookieStore( 442 lazy_params_->cookie_path, 443 lazy_params_->restore_old_session_cookies, 444 lazy_params_->special_storage_policy.get(), 445 profile_params->cookie_monster_delegate.get(), 446 CreateCookieCryptoIfUseful()); 447 cookie_store->GetCookieMonster()->SetPersistSessionCookies(true); 448 } 449 450 main_context->set_cookie_store(cookie_store.get()); 451 452 // Setup server bound cert service. 453 if (!server_bound_cert_service) { 454 DCHECK(!lazy_params_->server_bound_cert_path.empty()); 455 456 scoped_refptr<SQLiteServerBoundCertStore> server_bound_cert_db = 457 new SQLiteServerBoundCertStore( 458 lazy_params_->server_bound_cert_path, 459 BrowserThread::GetBlockingPool()->GetSequencedTaskRunner( 460 BrowserThread::GetBlockingPool()->GetSequenceToken()), 461 lazy_params_->special_storage_policy.get()); 462 server_bound_cert_service = new net::ServerBoundCertService( 463 new net::DefaultServerBoundCertStore(server_bound_cert_db.get()), 464 base::WorkerPool::GetTaskRunner(true)); 465 } 466 467 set_server_bound_cert_service(server_bound_cert_service); 468 main_context->set_server_bound_cert_service(server_bound_cert_service); 469 470 net::HttpCache::DefaultBackend* main_backend = 471 new net::HttpCache::DefaultBackend( 472 net::DISK_CACHE, 473 ChooseCacheBackendType(), 474 lazy_params_->cache_path, 475 lazy_params_->cache_max_size, 476 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE) 477 .get()); 478 net::HttpNetworkSession::Params network_session_params; 479 PopulateNetworkSessionParams(profile_params, &network_session_params); 480 net::HttpCache* main_cache = new net::HttpCache( 481 network_session_params, main_backend); 482 main_cache->InitializeInfiniteCache(lazy_params_->infinite_cache_path); 483 484 #if defined(OS_ANDROID) || defined(OS_IOS) 485 DataReductionProxySettings::InitDataReductionProxySession( 486 main_cache->GetSession()); 487 #endif 488 489 if (record_mode || playback_mode) { 490 main_cache->set_mode( 491 record_mode ? net::HttpCache::RECORD : net::HttpCache::PLAYBACK); 492 } 493 494 main_http_factory_.reset(main_cache); 495 main_context->set_http_transaction_factory(main_cache); 496 497 #if !defined(DISABLE_FTP_SUPPORT) 498 ftp_factory_.reset( 499 new net::FtpNetworkLayer(io_thread_globals->host_resolver.get())); 500 #endif // !defined(DISABLE_FTP_SUPPORT) 501 502 scoped_ptr<net::URLRequestJobFactoryImpl> main_job_factory( 503 new net::URLRequestJobFactoryImpl()); 504 InstallProtocolHandlers(main_job_factory.get(), protocol_handlers); 505 main_job_factory_ = SetUpJobFactoryDefaults( 506 main_job_factory.Pass(), 507 profile_params->protocol_handler_interceptor.Pass(), 508 network_delegate(), 509 ftp_factory_.get()); 510 main_context->set_job_factory(main_job_factory_.get()); 511 512 #if defined(ENABLE_EXTENSIONS) 513 InitializeExtensionsRequestContext(profile_params); 514 #endif 515 516 // Create a media request context based on the main context, but using a 517 // media cache. It shares the same job factory as the main context. 518 StoragePartitionDescriptor details(profile_path_, false); 519 media_request_context_.reset(InitializeMediaRequestContext(main_context, 520 details)); 521 522 lazy_params_.reset(); 523 } 524 525 void ProfileImplIOData:: 526 InitializeExtensionsRequestContext(ProfileParams* profile_params) const { 527 ChromeURLRequestContext* extensions_context = extensions_request_context(); 528 IOThread* const io_thread = profile_params->io_thread; 529 IOThread::Globals* const io_thread_globals = io_thread->globals(); 530 ApplyProfileParamsToContext(extensions_context); 531 532 extensions_context->set_transport_security_state(transport_security_state()); 533 534 extensions_context->set_net_log(io_thread->net_log()); 535 536 extensions_context->set_throttler_manager( 537 io_thread_globals->throttler_manager.get()); 538 539 net::CookieStore* extensions_cookie_store = 540 content::CreatePersistentCookieStore( 541 lazy_params_->extensions_cookie_path, 542 lazy_params_->restore_old_session_cookies, 543 NULL, 544 NULL, 545 CreateCookieCryptoIfUseful()); 546 // Enable cookies for devtools and extension URLs. 547 const char* schemes[] = {chrome::kChromeDevToolsScheme, 548 extensions::kExtensionScheme}; 549 extensions_cookie_store->GetCookieMonster()->SetCookieableSchemes(schemes, 2); 550 extensions_context->set_cookie_store(extensions_cookie_store); 551 552 scoped_ptr<net::URLRequestJobFactoryImpl> extensions_job_factory( 553 new net::URLRequestJobFactoryImpl()); 554 // TODO(shalev): The extensions_job_factory has a NULL NetworkDelegate. 555 // Without a network_delegate, this protocol handler will never 556 // handle file: requests, but as a side effect it makes 557 // job_factory::IsHandledProtocol return true, which prevents attempts to 558 // handle the protocol externally. We pass NULL in to 559 // SetUpJobFactory() to get this effect. 560 extensions_job_factory_ = SetUpJobFactoryDefaults( 561 extensions_job_factory.Pass(), 562 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>(), 563 NULL, 564 ftp_factory_.get()); 565 extensions_context->set_job_factory(extensions_job_factory_.get()); 566 } 567 568 ChromeURLRequestContext* 569 ProfileImplIOData::InitializeAppRequestContext( 570 ChromeURLRequestContext* main_context, 571 const StoragePartitionDescriptor& partition_descriptor, 572 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> 573 protocol_handler_interceptor, 574 content::ProtocolHandlerMap* protocol_handlers) const { 575 // Copy most state from the main context. 576 AppRequestContext* context = new AppRequestContext(load_time_stats()); 577 context->CopyFrom(main_context); 578 579 base::FilePath cookie_path = partition_descriptor.path.Append( 580 chrome::kCookieFilename); 581 base::FilePath cache_path = 582 partition_descriptor.path.Append(chrome::kCacheDirname); 583 584 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 585 bool record_mode = command_line.HasSwitch(switches::kRecordMode) && 586 chrome::kRecordModeEnabled; 587 bool playback_mode = command_line.HasSwitch(switches::kPlaybackMode); 588 589 // Use a separate HTTP disk cache for isolated apps. 590 net::HttpCache::BackendFactory* app_backend = NULL; 591 if (partition_descriptor.in_memory) { 592 app_backend = net::HttpCache::DefaultBackend::InMemory(0); 593 } else { 594 app_backend = new net::HttpCache::DefaultBackend( 595 net::DISK_CACHE, 596 ChooseCacheBackendType(), 597 cache_path, 598 app_cache_max_size_, 599 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE) 600 .get()); 601 } 602 net::HttpNetworkSession* main_network_session = 603 main_http_factory_->GetSession(); 604 net::HttpCache* app_http_cache = 605 new net::HttpCache(main_network_session, app_backend); 606 607 scoped_refptr<net::CookieStore> cookie_store = NULL; 608 if (partition_descriptor.in_memory) { 609 cookie_store = new net::CookieMonster(NULL, NULL); 610 } else if (record_mode || playback_mode) { 611 // Don't use existing cookies and use an in-memory store. 612 // TODO(creis): We should have a cookie delegate for notifying the cookie 613 // extensions API, but we need to update it to understand isolated apps 614 // first. 615 cookie_store = new net::CookieMonster(NULL, NULL); 616 app_http_cache->set_mode( 617 record_mode ? net::HttpCache::RECORD : net::HttpCache::PLAYBACK); 618 } 619 620 // Use an app-specific cookie store. 621 if (!cookie_store.get()) { 622 DCHECK(!cookie_path.empty()); 623 624 // TODO(creis): We should have a cookie delegate for notifying the cookie 625 // extensions API, but we need to update it to understand isolated apps 626 // first. 627 cookie_store = content::CreatePersistentCookieStore( 628 cookie_path, 629 false, 630 NULL, 631 NULL, 632 CreateCookieCryptoIfUseful()); 633 } 634 635 // Transfer ownership of the cookies and cache to AppRequestContext. 636 context->SetCookieStore(cookie_store.get()); 637 context->SetHttpTransactionFactory( 638 scoped_ptr<net::HttpTransactionFactory>(app_http_cache)); 639 640 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory( 641 new net::URLRequestJobFactoryImpl()); 642 InstallProtocolHandlers(job_factory.get(), protocol_handlers); 643 scoped_ptr<net::URLRequestJobFactory> top_job_factory( 644 SetUpJobFactoryDefaults( 645 job_factory.Pass(), protocol_handler_interceptor.Pass(), 646 network_delegate(), 647 ftp_factory_.get())); 648 context->SetJobFactory(top_job_factory.Pass()); 649 650 return context; 651 } 652 653 ChromeURLRequestContext* 654 ProfileImplIOData::InitializeMediaRequestContext( 655 ChromeURLRequestContext* original_context, 656 const StoragePartitionDescriptor& partition_descriptor) const { 657 // Copy most state from the original context. 658 MediaRequestContext* context = new MediaRequestContext(load_time_stats()); 659 context->CopyFrom(original_context); 660 661 // For in-memory context, return immediately after creating the new 662 // context before attaching a separate cache. It is important to return 663 // a new context rather than just reusing |original_context| because 664 // the caller expects to take ownership of the pointer. 665 if (partition_descriptor.in_memory) 666 return context; 667 668 using content::StoragePartition; 669 base::FilePath cache_path; 670 int cache_max_size = app_media_cache_max_size_; 671 if (partition_descriptor.path == profile_path_) { 672 // lazy_params_ is only valid for the default media context creation. 673 cache_path = lazy_params_->media_cache_path; 674 cache_max_size = lazy_params_->media_cache_max_size; 675 } else { 676 cache_path = partition_descriptor.path.Append(chrome::kMediaCacheDirname); 677 } 678 679 // Use a separate HTTP disk cache for isolated apps. 680 net::HttpCache::BackendFactory* media_backend = 681 new net::HttpCache::DefaultBackend( 682 net::MEDIA_CACHE, 683 ChooseCacheBackendType(), 684 cache_path, 685 cache_max_size, 686 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE) 687 .get()); 688 net::HttpNetworkSession* main_network_session = 689 main_http_factory_->GetSession(); 690 scoped_ptr<net::HttpTransactionFactory> media_http_cache( 691 new net::HttpCache(main_network_session, media_backend)); 692 693 // Transfer ownership of the cache to MediaRequestContext. 694 context->SetHttpTransactionFactory(media_http_cache.Pass()); 695 696 // Note that we do not create a new URLRequestJobFactory because 697 // the media context should behave exactly like its parent context 698 // in all respects except for cache behavior on media subresources. 699 // The CopyFrom() step above means that our media context will use 700 // the same URLRequestJobFactory instance that our parent context does. 701 702 return context; 703 } 704 705 ChromeURLRequestContext* 706 ProfileImplIOData::AcquireMediaRequestContext() const { 707 DCHECK(media_request_context_); 708 return media_request_context_.get(); 709 } 710 711 ChromeURLRequestContext* 712 ProfileImplIOData::AcquireIsolatedAppRequestContext( 713 ChromeURLRequestContext* main_context, 714 const StoragePartitionDescriptor& partition_descriptor, 715 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> 716 protocol_handler_interceptor, 717 content::ProtocolHandlerMap* protocol_handlers) const { 718 // We create per-app contexts on demand, unlike the others above. 719 ChromeURLRequestContext* app_request_context = 720 InitializeAppRequestContext(main_context, partition_descriptor, 721 protocol_handler_interceptor.Pass(), 722 protocol_handlers); 723 DCHECK(app_request_context); 724 return app_request_context; 725 } 726 727 ChromeURLRequestContext* 728 ProfileImplIOData::AcquireIsolatedMediaRequestContext( 729 ChromeURLRequestContext* app_context, 730 const StoragePartitionDescriptor& partition_descriptor) const { 731 // We create per-app media contexts on demand, unlike the others above. 732 ChromeURLRequestContext* media_request_context = 733 InitializeMediaRequestContext(app_context, partition_descriptor); 734 DCHECK(media_request_context); 735 return media_request_context; 736 } 737 738 chrome_browser_net::LoadTimeStats* ProfileImplIOData::GetLoadTimeStats( 739 IOThread::Globals* io_thread_globals) const { 740 return io_thread_globals->load_time_stats.get(); 741 } 742 743 void ProfileImplIOData::ClearNetworkingHistorySinceOnIOThread( 744 base::Time time, 745 const base::Closure& completion) { 746 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 747 DCHECK(initialized()); 748 749 DCHECK(transport_security_state()); 750 // Completes synchronously. 751 transport_security_state()->DeleteAllDynamicDataSince(time); 752 DCHECK(http_server_properties_manager_); 753 http_server_properties_manager_->Clear(completion); 754 } 755