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.
5 #include "chrome/browser/profiles/off_the_record_profile_io_data.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"
40 using content::BrowserThread;
42 OffTheRecordProfileIOData::Handle::Handle(Profile* profile)
43 : io_data_(new OffTheRecordProfileIOData),
46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
50 OffTheRecordProfileIOData::Handle::~Handle() {
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
52 io_data_->ShutdownOnUIThread();
55 content::ResourceContext*
56 OffTheRecordProfileIOData::Handle::GetResourceContext() const {
57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
59 return GetResourceContextNoInit();
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();
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
76 #if !defined(OS_CHROMEOS)
77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
78 #endif // defined(OS_CHROMEOS)
80 DCHECK(!main_request_context_getter_.get());
81 main_request_context_getter_ =
82 ChromeURLRequestContextGetter::Create(
83 profile_, io_data_, protocol_handlers);
84 return main_request_context_getter_;
87 scoped_refptr<ChromeURLRequestContextGetter>
88 OffTheRecordProfileIOData::Handle::GetExtensionsRequestContextGetter() const {
89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
91 if (!extensions_request_context_getter_.get()) {
92 extensions_request_context_getter_ =
93 ChromeURLRequestContextGetter::CreateForExtensions(profile_, io_data_);
95 return extensions_request_context_getter_;
98 scoped_refptr<ChromeURLRequestContextGetter>
99 OffTheRecordProfileIOData::Handle::GetIsolatedAppRequestContextGetter(
100 const base::FilePath& partition_path,
101 bool in_memory) const {
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
103 DCHECK(!partition_path.empty());
106 // Keep a map of request context getters, one per requested app ID.
107 StoragePartitionDescriptor descriptor(partition_path, in_memory);
108 ChromeURLRequestContextGetterMap::iterator iter =
109 app_request_context_getter_map_.find(descriptor);
110 CHECK(iter != app_request_context_getter_map_.end());
114 scoped_refptr<ChromeURLRequestContextGetter>
115 OffTheRecordProfileIOData::Handle::CreateIsolatedAppRequestContextGetter(
116 const base::FilePath& partition_path,
118 content::ProtocolHandlerMap* protocol_handlers) const {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
120 DCHECK(!partition_path.empty());
123 // Keep a map of request context getters, one per requested app ID.
124 StoragePartitionDescriptor descriptor(partition_path, in_memory);
125 DCHECK_EQ(app_request_context_getter_map_.count(descriptor), 0u);
127 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
128 protocol_handler_interceptor(
129 ProtocolHandlerRegistryFactory::GetForProfile(profile_)->
130 CreateJobInterceptorFactory());
131 ChromeURLRequestContextGetter* context =
132 ChromeURLRequestContextGetter::CreateForIsolatedApp(
133 profile_, io_data_, descriptor, protocol_handler_interceptor.Pass(),
135 app_request_context_getter_map_[descriptor] = context;
140 void OffTheRecordProfileIOData::Handle::LazyInitialize() const {
144 // Set initialized_ to true at the beginning in case any of the objects
145 // below try to get the ResourceContext pointer.
147 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING)
148 io_data_->safe_browsing_enabled()->Init(prefs::kSafeBrowsingEnabled,
149 profile_->GetPrefs());
150 io_data_->safe_browsing_enabled()->MoveToThread(
151 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
153 io_data_->InitializeOnUIThread(profile_);
156 OffTheRecordProfileIOData::OffTheRecordProfileIOData()
157 : ProfileIOData(true) {}
158 OffTheRecordProfileIOData::~OffTheRecordProfileIOData() {
159 DestroyResourceContext();
162 void OffTheRecordProfileIOData::InitializeInternal(
163 ProfileParams* profile_params,
164 content::ProtocolHandlerMap* protocol_handlers) const {
165 ChromeURLRequestContext* main_context = main_request_context();
167 IOThread* const io_thread = profile_params->io_thread;
168 IOThread::Globals* const io_thread_globals = io_thread->globals();
170 ApplyProfileParamsToContext(main_context);
172 main_context->set_transport_security_state(transport_security_state());
174 main_context->set_net_log(io_thread->net_log());
176 main_context->set_network_delegate(network_delegate());
178 main_context->set_host_resolver(
179 io_thread_globals->host_resolver.get());
180 main_context->set_cert_verifier(
181 io_thread_globals->cert_verifier.get());
182 main_context->set_http_auth_handler_factory(
183 io_thread_globals->http_auth_handler_factory.get());
184 main_context->set_fraudulent_certificate_reporter(
185 fraudulent_certificate_reporter());
186 main_context->set_proxy_service(proxy_service());
188 main_context->set_throttler_manager(
189 io_thread_globals->throttler_manager.get());
191 // For incognito, we use the default non-persistent HttpServerPropertiesImpl.
192 set_http_server_properties(
193 scoped_ptr<net::HttpServerProperties>(
194 new net::HttpServerPropertiesImpl()));
195 main_context->set_http_server_properties(http_server_properties());
197 // For incognito, we use a non-persistent server bound cert store.
198 net::ServerBoundCertService* server_bound_cert_service =
199 new net::ServerBoundCertService(
200 new net::DefaultServerBoundCertStore(NULL),
201 base::WorkerPool::GetTaskRunner(true));
202 set_server_bound_cert_service(server_bound_cert_service);
203 main_context->set_server_bound_cert_service(server_bound_cert_service);
205 main_context->set_cookie_store(new net::CookieMonster(
206 NULL, profile_params->cookie_monster_delegate.get()));
208 net::HttpCache::BackendFactory* main_backend =
209 net::HttpCache::DefaultBackend::InMemory(0);
210 net::HttpNetworkSession::Params network_session_params;
211 PopulateNetworkSessionParams(profile_params, &network_session_params);
212 net::HttpCache* cache = new net::HttpCache(
213 network_session_params, main_backend);
215 main_http_factory_.reset(cache);
216 main_context->set_http_transaction_factory(cache);
217 #if !defined(DISABLE_FTP_SUPPORT)
219 new net::FtpNetworkLayer(main_context->host_resolver()));
220 #endif // !defined(DISABLE_FTP_SUPPORT)
222 scoped_ptr<net::URLRequestJobFactoryImpl> main_job_factory(
223 new net::URLRequestJobFactoryImpl());
225 InstallProtocolHandlers(main_job_factory.get(), protocol_handlers);
226 main_job_factory_ = SetUpJobFactoryDefaults(
227 main_job_factory.Pass(),
228 profile_params->protocol_handler_interceptor.Pass(),
231 main_context->set_job_factory(main_job_factory_.get());
233 #if defined(ENABLE_EXTENSIONS)
234 InitializeExtensionsRequestContext(profile_params);
238 void OffTheRecordProfileIOData::
239 InitializeExtensionsRequestContext(ProfileParams* profile_params) const {
240 ChromeURLRequestContext* extensions_context = extensions_request_context();
242 IOThread* const io_thread = profile_params->io_thread;
243 IOThread::Globals* const io_thread_globals = io_thread->globals();
245 ApplyProfileParamsToContext(extensions_context);
247 extensions_context->set_transport_security_state(transport_security_state());
249 extensions_context->set_net_log(io_thread->net_log());
251 extensions_context->set_throttler_manager(
252 io_thread_globals->throttler_manager.get());
254 // All we care about for extensions is the cookie store. For incognito, we
255 // use a non-persistent cookie store.
256 net::CookieMonster* extensions_cookie_store =
257 new net::CookieMonster(NULL, NULL);
258 // Enable cookies for devtools and extension URLs.
259 const char* schemes[] = {chrome::kChromeDevToolsScheme,
260 extensions::kExtensionScheme};
261 extensions_cookie_store->SetCookieableSchemes(schemes, 2);
262 extensions_context->set_cookie_store(extensions_cookie_store);
264 scoped_ptr<net::URLRequestJobFactoryImpl> extensions_job_factory(
265 new net::URLRequestJobFactoryImpl());
266 // TODO(shalev): The extensions_job_factory has a NULL NetworkDelegate.
267 // Without a network_delegate, this protocol handler will never
268 // handle file: requests, but as a side effect it makes
269 // job_factory::IsHandledProtocol return true, which prevents attempts to
270 // handle the protocol externally. We pass NULL in to
271 // SetUpJobFactoryDefaults() to get this effect.
272 extensions_job_factory_ = SetUpJobFactoryDefaults(
273 extensions_job_factory.Pass(),
274 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>(),
277 extensions_context->set_job_factory(extensions_job_factory_.get());
280 ChromeURLRequestContext*
281 OffTheRecordProfileIOData::InitializeAppRequestContext(
282 ChromeURLRequestContext* main_context,
283 const StoragePartitionDescriptor& partition_descriptor,
284 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
285 protocol_handler_interceptor,
286 content::ProtocolHandlerMap* protocol_handlers) const {
287 AppRequestContext* context = new AppRequestContext(load_time_stats());
289 // Copy most state from the main context.
290 context->CopyFrom(main_context);
292 // Use a separate in-memory cookie store for the app.
293 // TODO(creis): We should have a cookie delegate for notifying the cookie
294 // extensions API, but we need to update it to understand isolated apps first.
295 context->SetCookieStore(new net::CookieMonster(NULL, NULL));
297 // Use a separate in-memory cache for the app.
298 net::HttpCache::BackendFactory* app_backend =
299 net::HttpCache::DefaultBackend::InMemory(0);
300 net::HttpNetworkSession* main_network_session =
301 main_http_factory_->GetSession();
302 scoped_ptr<net::HttpTransactionFactory> app_http_cache(
303 new net::HttpCache(main_network_session, app_backend));
305 context->SetHttpTransactionFactory(app_http_cache.Pass());
307 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
308 new net::URLRequestJobFactoryImpl());
309 InstallProtocolHandlers(job_factory.get(), protocol_handlers);
310 scoped_ptr<net::URLRequestJobFactory> top_job_factory;
311 top_job_factory = SetUpJobFactoryDefaults(job_factory.Pass(),
312 protocol_handler_interceptor.Pass(),
315 context->SetJobFactory(top_job_factory.Pass());
319 ChromeURLRequestContext*
320 OffTheRecordProfileIOData::InitializeMediaRequestContext(
321 ChromeURLRequestContext* original_context,
322 const StoragePartitionDescriptor& partition_descriptor) const {
327 ChromeURLRequestContext*
328 OffTheRecordProfileIOData::AcquireMediaRequestContext() const {
333 ChromeURLRequestContext*
334 OffTheRecordProfileIOData::AcquireIsolatedAppRequestContext(
335 ChromeURLRequestContext* main_context,
336 const StoragePartitionDescriptor& partition_descriptor,
337 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
338 protocol_handler_interceptor,
339 content::ProtocolHandlerMap* protocol_handlers) const {
340 // We create per-app contexts on demand, unlike the others above.
341 ChromeURLRequestContext* app_request_context =
342 InitializeAppRequestContext(main_context, partition_descriptor,
343 protocol_handler_interceptor.Pass(),
345 DCHECK(app_request_context);
346 return app_request_context;
349 ChromeURLRequestContext*
350 OffTheRecordProfileIOData::AcquireIsolatedMediaRequestContext(
351 ChromeURLRequestContext* app_context,
352 const StoragePartitionDescriptor& partition_descriptor) const {
357 chrome_browser_net::LoadTimeStats* OffTheRecordProfileIOData::GetLoadTimeStats(
358 IOThread::Globals* io_thread_globals) const {