1 // Copyright (c) 2011 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/logging.h" 8 #include "base/stl_util-inl.h" 9 #include "build/build_config.h" 10 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/io_thread.h" 12 #include "chrome/browser/net/chrome_net_log.h" 13 #include "chrome/browser/net/chrome_network_delegate.h" 14 #include "chrome/browser/net/chrome_url_request_context.h" 15 #include "chrome/common/extensions/extension.h" 16 #include "chrome/common/url_constants.h" 17 #include "content/browser/browser_thread.h" 18 #include "content/browser/resource_context.h" 19 #include "net/ftp/ftp_network_layer.h" 20 #include "net/http/http_cache.h" 21 #include "webkit/database/database_tracker.h" 22 23 OffTheRecordProfileIOData::Handle::Handle(Profile* profile) 24 : io_data_(new OffTheRecordProfileIOData), 25 profile_(profile), 26 initialized_(false) { 27 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 28 DCHECK(profile); 29 } 30 31 OffTheRecordProfileIOData::Handle::~Handle() { 32 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 33 if (main_request_context_getter_) 34 main_request_context_getter_->CleanupOnUIThread(); 35 if (extensions_request_context_getter_) 36 extensions_request_context_getter_->CleanupOnUIThread(); 37 38 // Clean up all isolated app request contexts. 39 for (ChromeURLRequestContextGetterMap::iterator iter = 40 app_request_context_getter_map_.begin(); 41 iter != app_request_context_getter_map_.end(); 42 ++iter) { 43 iter->second->CleanupOnUIThread(); 44 } 45 46 io_data_->ShutdownOnUIThread(); 47 } 48 49 const content::ResourceContext& 50 OffTheRecordProfileIOData::Handle::GetResourceContext() const { 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 52 LazyInitialize(); 53 return io_data_->GetResourceContext(); 54 } 55 56 scoped_refptr<ChromeURLRequestContextGetter> 57 OffTheRecordProfileIOData::Handle::GetMainRequestContextGetter() const { 58 // TODO(oshima): Re-enable when ChromeOS only accesses the profile on the UI 59 // thread. 60 #if !defined(OS_CHROMEOS) 61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 62 #endif // defined(OS_CHROMEOS) 63 LazyInitialize(); 64 if (!main_request_context_getter_) { 65 main_request_context_getter_ = 66 ChromeURLRequestContextGetter::CreateOffTheRecord(profile_, io_data_); 67 } 68 return main_request_context_getter_; 69 } 70 71 scoped_refptr<ChromeURLRequestContextGetter> 72 OffTheRecordProfileIOData::Handle::GetExtensionsRequestContextGetter() const { 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 74 LazyInitialize(); 75 if (!extensions_request_context_getter_) { 76 extensions_request_context_getter_ = 77 ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions( 78 profile_, io_data_); 79 } 80 return extensions_request_context_getter_; 81 } 82 83 scoped_refptr<ChromeURLRequestContextGetter> 84 OffTheRecordProfileIOData::Handle::GetIsolatedAppRequestContextGetter( 85 const std::string& app_id) const { 86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 87 DCHECK(!app_id.empty()); 88 LazyInitialize(); 89 90 // Keep a map of request context getters, one per requested app ID. 91 ChromeURLRequestContextGetterMap::iterator iter = 92 app_request_context_getter_map_.find(app_id); 93 if (iter != app_request_context_getter_map_.end()) 94 return iter->second; 95 96 ChromeURLRequestContextGetter* context = 97 ChromeURLRequestContextGetter::CreateOffTheRecordForIsolatedApp( 98 profile_, io_data_, app_id); 99 app_request_context_getter_map_[app_id] = context; 100 101 return context; 102 } 103 104 void OffTheRecordProfileIOData::Handle::LazyInitialize() const { 105 if (!initialized_) { 106 io_data_->InitializeProfileParams(profile_); 107 ChromeNetworkDelegate::InitializeReferrersEnabled( 108 io_data_->enable_referrers(), profile_->GetPrefs()); 109 initialized_ = true; 110 } 111 } 112 113 OffTheRecordProfileIOData::OffTheRecordProfileIOData() 114 : ProfileIOData(true) {} 115 OffTheRecordProfileIOData::~OffTheRecordProfileIOData() { 116 STLDeleteValues(&app_http_factory_map_); 117 } 118 119 void OffTheRecordProfileIOData::LazyInitializeInternal( 120 ProfileParams* profile_params) const { 121 ChromeURLRequestContext* main_context = main_request_context(); 122 ChromeURLRequestContext* extensions_context = extensions_request_context(); 123 124 IOThread* const io_thread = profile_params->io_thread; 125 IOThread::Globals* const io_thread_globals = io_thread->globals(); 126 127 ApplyProfileParamsToContext(main_context); 128 ApplyProfileParamsToContext(extensions_context); 129 130 main_context->set_cookie_policy(cookie_policy()); 131 extensions_context->set_cookie_policy(cookie_policy()); 132 133 main_context->set_net_log(io_thread->net_log()); 134 extensions_context->set_net_log(io_thread->net_log()); 135 136 main_context->set_network_delegate(network_delegate()); 137 138 main_context->set_host_resolver( 139 io_thread_globals->host_resolver.get()); 140 main_context->set_cert_verifier( 141 io_thread_globals->cert_verifier.get()); 142 main_context->set_dnsrr_resolver( 143 io_thread_globals->dnsrr_resolver.get()); 144 main_context->set_http_auth_handler_factory( 145 io_thread_globals->http_auth_handler_factory.get()); 146 main_context->set_dns_cert_checker(dns_cert_checker()); 147 main_context->set_proxy_service(proxy_service()); 148 149 main_context->set_cookie_store( 150 new net::CookieMonster(NULL, profile_params->cookie_monster_delegate)); 151 // All we care about for extensions is the cookie store. For incognito, we 152 // use a non-persistent cookie store. 153 154 net::CookieMonster* extensions_cookie_store = 155 new net::CookieMonster(NULL, NULL); 156 // Enable cookies for devtools and extension URLs. 157 const char* schemes[] = {chrome::kChromeDevToolsScheme, 158 chrome::kExtensionScheme}; 159 extensions_cookie_store->SetCookieableSchemes(schemes, 2); 160 161 extensions_context->set_cookie_store( 162 new net::CookieMonster(NULL, NULL)); 163 164 net::HttpCache::BackendFactory* main_backend = 165 net::HttpCache::DefaultBackend::InMemory(0); 166 net::HttpCache* cache = 167 new net::HttpCache(main_context->host_resolver(), 168 main_context->cert_verifier(), 169 main_context->dnsrr_resolver(), 170 main_context->dns_cert_checker(), 171 main_context->proxy_service(), 172 main_context->ssl_config_service(), 173 main_context->http_auth_handler_factory(), 174 main_context->network_delegate(), 175 main_context->net_log(), 176 main_backend); 177 178 main_http_factory_.reset(cache); 179 main_context->set_http_transaction_factory(cache); 180 main_context->set_ftp_transaction_factory( 181 new net::FtpNetworkLayer(main_context->host_resolver())); 182 } 183 184 scoped_refptr<ProfileIOData::RequestContext> 185 OffTheRecordProfileIOData::InitializeAppRequestContext( 186 scoped_refptr<ChromeURLRequestContext> main_context, 187 const std::string& app_id) const { 188 scoped_refptr<ProfileIOData::RequestContext> context = new RequestContext; 189 190 // Copy most state from the main context. 191 context->CopyFrom(main_context); 192 193 // Use a separate in-memory cookie store for the app. 194 // TODO(creis): We should have a cookie delegate for notifying the cookie 195 // extensions API, but we need to update it to understand isolated apps first. 196 context->set_cookie_store( 197 new net::CookieMonster(NULL, NULL)); 198 199 // Use a separate in-memory cache for the app. 200 net::HttpCache::BackendFactory* app_backend = 201 net::HttpCache::DefaultBackend::InMemory(0); 202 net::HttpNetworkSession* main_network_session = 203 main_http_factory_->GetSession(); 204 net::HttpCache* app_http_cache = 205 new net::HttpCache(main_network_session, app_backend); 206 207 // Keep track of app_http_cache to delete it when we go away. 208 DCHECK(!app_http_factory_map_[app_id]); 209 app_http_factory_map_[app_id] = app_http_cache; 210 context->set_http_transaction_factory(app_http_cache); 211 212 return context; 213 } 214 215 scoped_refptr<ChromeURLRequestContext> 216 OffTheRecordProfileIOData::AcquireMediaRequestContext() const { 217 NOTREACHED(); 218 return NULL; 219 } 220 221 scoped_refptr<ChromeURLRequestContext> 222 OffTheRecordProfileIOData::AcquireIsolatedAppRequestContext( 223 scoped_refptr<ChromeURLRequestContext> main_context, 224 const std::string& app_id) const { 225 // We create per-app contexts on demand, unlike the others above. 226 scoped_refptr<RequestContext> app_request_context = 227 InitializeAppRequestContext(main_context, app_id); 228 DCHECK(app_request_context); 229 app_request_context->set_profile_io_data(this); 230 return app_request_context; 231 } 232