Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / profiles / profile_impl_io_data.cc
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/io_thread.h"
23 #include "chrome/browser/net/chrome_net_log.h"
24 #include "chrome/browser/net/chrome_network_delegate.h"
25 #include "chrome/browser/net/chrome_sdch_policy.h"
26 #include "chrome/browser/net/connect_interceptor.h"
27 #include "chrome/browser/net/cookie_store_util.h"
28 #include "chrome/browser/net/http_server_properties_manager_factory.h"
29 #include "chrome/browser/net/predictor.h"
30 #include "chrome/browser/net/quota_policy_channel_id_store.h"
31 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_configurator.h"
32 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
33 #include "chrome/browser/profiles/profile.h"
34 #include "chrome/common/chrome_constants.h"
35 #include "chrome/common/chrome_switches.h"
36 #include "chrome/common/pref_names.h"
37 #include "chrome/common/url_constants.h"
38 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h"
39 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.h"
40 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol.h"
41 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h"
42 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h"
43 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
44 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
45 #include "components/domain_reliability/monitor.h"
46 #include "content/public/browser/browser_thread.h"
47 #include "content/public/browser/cookie_store_factory.h"
48 #include "content/public/browser/notification_service.h"
49 #include "content/public/browser/resource_context.h"
50 #include "content/public/browser/storage_partition.h"
51 #include "extensions/browser/extension_protocols.h"
52 #include "extensions/common/constants.h"
53 #include "net/base/cache_type.h"
54 #include "net/base/sdch_manager.h"
55 #include "net/ftp/ftp_network_layer.h"
56 #include "net/http/http_cache.h"
57 #include "net/http/http_server_properties_manager.h"
58 #include "net/ssl/channel_id_service.h"
59 #include "net/url_request/url_request_intercepting_job_factory.h"
60 #include "net/url_request/url_request_job_factory_impl.h"
61 #include "storage/browser/quota/special_storage_policy.h"
62
63 namespace {
64
65 net::BackendType ChooseCacheBackendType() {
66 #if defined(OS_ANDROID)
67   return net::CACHE_BACKEND_SIMPLE;
68 #else
69   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
70   if (command_line.HasSwitch(switches::kUseSimpleCacheBackend)) {
71     const std::string opt_value =
72         command_line.GetSwitchValueASCII(switches::kUseSimpleCacheBackend);
73     if (LowerCaseEqualsASCII(opt_value, "off"))
74       return net::CACHE_BACKEND_BLOCKFILE;
75     if (opt_value == "" || LowerCaseEqualsASCII(opt_value, "on"))
76       return net::CACHE_BACKEND_SIMPLE;
77   }
78   const std::string experiment_name =
79       base::FieldTrialList::FindFullName("SimpleCacheTrial");
80   if (experiment_name == "ExperimentYes" ||
81       experiment_name == "ExperimentYes2") {
82     return net::CACHE_BACKEND_SIMPLE;
83   }
84   return net::CACHE_BACKEND_BLOCKFILE;
85 #endif
86 }
87
88 }  // namespace
89
90 using content::BrowserThread;
91 using data_reduction_proxy::DataReductionProxyParams;
92
93 ProfileImplIOData::Handle::Handle(Profile* profile)
94     : io_data_(new ProfileImplIOData),
95       profile_(profile),
96       initialized_(false) {
97   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
98   DCHECK(profile);
99 }
100
101 ProfileImplIOData::Handle::~Handle() {
102   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
103   io_data_->data_reduction_proxy_statistics_prefs()->WritePrefs();
104
105   if (io_data_->predictor_ != NULL) {
106     // io_data_->predictor_ might be NULL if Init() was never called
107     // (i.e. we shut down before ProfileImpl::DoFinalInit() got called).
108     bool save_prefs = true;
109 #if defined(OS_CHROMEOS)
110     save_prefs = !chromeos::ProfileHelper::IsSigninProfile(profile_);
111 #endif
112     if (save_prefs)
113       io_data_->predictor_->SaveStateForNextStartupAndTrim();
114     io_data_->predictor_->ShutdownOnUIThread();
115   }
116
117   if (io_data_->http_server_properties_manager_)
118     io_data_->http_server_properties_manager_->ShutdownOnPrefThread();
119
120   io_data_->data_reduction_proxy_enabled()->Destroy();
121   io_data_->ShutdownOnUIThread(GetAllContextGetters().Pass());
122 }
123
124 void ProfileImplIOData::Handle::Init(
125     const base::FilePath& cookie_path,
126     const base::FilePath& channel_id_path,
127     const base::FilePath& cache_path,
128     int cache_max_size,
129     const base::FilePath& media_cache_path,
130     int media_cache_max_size,
131     const base::FilePath& extensions_cookie_path,
132     const base::FilePath& profile_path,
133     const base::FilePath& infinite_cache_path,
134     chrome_browser_net::Predictor* predictor,
135     content::CookieStoreConfig::SessionCookieMode session_cookie_mode,
136     storage::SpecialStoragePolicy* special_storage_policy,
137     scoped_ptr<domain_reliability::DomainReliabilityMonitor>
138         domain_reliability_monitor,
139     const base::Callback<void(bool)>& data_reduction_proxy_unavailable,
140     scoped_ptr<DataReductionProxyChromeConfigurator>
141         data_reduction_proxy_chrome_configurator,
142     scoped_ptr<data_reduction_proxy::DataReductionProxyParams>
143         data_reduction_proxy_params,
144     scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs>
145         data_reduction_proxy_statistics_prefs) {
146   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
147   DCHECK(!io_data_->lazy_params_);
148   DCHECK(predictor);
149
150   LazyParams* lazy_params = new LazyParams();
151
152   lazy_params->cookie_path = cookie_path;
153   lazy_params->channel_id_path = channel_id_path;
154   lazy_params->cache_path = cache_path;
155   lazy_params->cache_max_size = cache_max_size;
156   lazy_params->media_cache_path = media_cache_path;
157   lazy_params->media_cache_max_size = media_cache_max_size;
158   lazy_params->extensions_cookie_path = extensions_cookie_path;
159   lazy_params->infinite_cache_path = infinite_cache_path;
160   lazy_params->session_cookie_mode = session_cookie_mode;
161   lazy_params->special_storage_policy = special_storage_policy;
162
163   io_data_->lazy_params_.reset(lazy_params);
164
165   // Keep track of profile path and cache sizes separately so we can use them
166   // on demand when creating storage isolated URLRequestContextGetters.
167   io_data_->profile_path_ = profile_path;
168   io_data_->app_cache_max_size_ = cache_max_size;
169   io_data_->app_media_cache_max_size_ = media_cache_max_size;
170
171   io_data_->predictor_.reset(predictor);
172   io_data_->domain_reliability_monitor_ = domain_reliability_monitor.Pass();
173
174   io_data_->InitializeMetricsEnabledStateOnUIThread();
175   if (io_data_->domain_reliability_monitor_)
176     io_data_->domain_reliability_monitor_->MoveToNetworkThread();
177
178   io_data_->set_data_reduction_proxy_unavailable_callback(
179       data_reduction_proxy_unavailable);
180   io_data_->set_data_reduction_proxy_chrome_configurator(
181       data_reduction_proxy_chrome_configurator.Pass());
182   io_data_->set_data_reduction_proxy_params(data_reduction_proxy_params.Pass());
183   io_data_->set_data_reduction_proxy_statistics_prefs(
184       data_reduction_proxy_statistics_prefs.Pass());
185 }
186
187 content::ResourceContext*
188     ProfileImplIOData::Handle::GetResourceContext() const {
189   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
190   LazyInitialize();
191   return GetResourceContextNoInit();
192 }
193
194 content::ResourceContext*
195 ProfileImplIOData::Handle::GetResourceContextNoInit() const {
196   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
197   // Don't call LazyInitialize here, since the resource context is created at
198   // the beginning of initalization and is used by some members while they're
199   // being initialized (i.e. AppCacheService).
200   return io_data_->GetResourceContext();
201 }
202
203 scoped_refptr<ChromeURLRequestContextGetter>
204 ProfileImplIOData::Handle::CreateMainRequestContextGetter(
205     content::ProtocolHandlerMap* protocol_handlers,
206     content::URLRequestInterceptorScopedVector request_interceptors,
207     PrefService* local_state,
208     IOThread* io_thread) const {
209   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
210   LazyInitialize();
211   DCHECK(!main_request_context_getter_.get());
212   main_request_context_getter_ = ChromeURLRequestContextGetter::Create(
213       profile_, io_data_, protocol_handlers, request_interceptors.Pass());
214
215   io_data_->predictor_
216       ->InitNetworkPredictor(profile_->GetPrefs(),
217                              local_state,
218                              io_thread,
219                              main_request_context_getter_.get(),
220                              io_data_);
221
222   content::NotificationService::current()->Notify(
223       chrome::NOTIFICATION_PROFILE_URL_REQUEST_CONTEXT_GETTER_INITIALIZED,
224       content::Source<Profile>(profile_),
225       content::NotificationService::NoDetails());
226   return main_request_context_getter_;
227 }
228
229 scoped_refptr<ChromeURLRequestContextGetter>
230 ProfileImplIOData::Handle::GetMediaRequestContextGetter() const {
231   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
232   LazyInitialize();
233   if (!media_request_context_getter_.get()) {
234     media_request_context_getter_ =
235         ChromeURLRequestContextGetter::CreateForMedia(profile_, io_data_);
236   }
237   return media_request_context_getter_;
238 }
239
240 scoped_refptr<ChromeURLRequestContextGetter>
241 ProfileImplIOData::Handle::GetExtensionsRequestContextGetter() const {
242   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
243   LazyInitialize();
244   if (!extensions_request_context_getter_.get()) {
245     extensions_request_context_getter_ =
246         ChromeURLRequestContextGetter::CreateForExtensions(profile_, io_data_);
247   }
248   return extensions_request_context_getter_;
249 }
250
251 scoped_refptr<ChromeURLRequestContextGetter>
252 ProfileImplIOData::Handle::CreateIsolatedAppRequestContextGetter(
253     const base::FilePath& partition_path,
254     bool in_memory,
255     content::ProtocolHandlerMap* protocol_handlers,
256     content::URLRequestInterceptorScopedVector request_interceptors) const {
257   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
258   // Check that the partition_path is not the same as the base profile path. We
259   // expect isolated partition, which will never go to the default profile path.
260   CHECK(partition_path != profile_->GetPath());
261   LazyInitialize();
262
263   // Keep a map of request context getters, one per requested storage partition.
264   StoragePartitionDescriptor descriptor(partition_path, in_memory);
265   ChromeURLRequestContextGetterMap::iterator iter =
266       app_request_context_getter_map_.find(descriptor);
267   if (iter != app_request_context_getter_map_.end())
268     return iter->second;
269
270   scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
271       protocol_handler_interceptor(
272           ProtocolHandlerRegistryFactory::GetForBrowserContext(profile_)->
273               CreateJobInterceptorFactory());
274   ChromeURLRequestContextGetter* context =
275       ChromeURLRequestContextGetter::CreateForIsolatedApp(
276           profile_,
277           io_data_,
278           descriptor,
279           protocol_handler_interceptor.Pass(),
280           protocol_handlers,
281           request_interceptors.Pass());
282   app_request_context_getter_map_[descriptor] = context;
283
284   return context;
285 }
286
287 scoped_refptr<ChromeURLRequestContextGetter>
288 ProfileImplIOData::Handle::GetIsolatedMediaRequestContextGetter(
289     const base::FilePath& partition_path,
290     bool in_memory) const {
291   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
292   // We must have a non-default path, or this will act like the default media
293   // context.
294   CHECK(partition_path != profile_->GetPath());
295   LazyInitialize();
296
297   // Keep a map of request context getters, one per requested storage partition.
298   StoragePartitionDescriptor descriptor(partition_path, in_memory);
299   ChromeURLRequestContextGetterMap::iterator iter =
300       isolated_media_request_context_getter_map_.find(descriptor);
301   if (iter != isolated_media_request_context_getter_map_.end())
302     return iter->second;
303
304   // Get the app context as the starting point for the media context, so that
305   // it uses the app's cookie store.
306   ChromeURLRequestContextGetterMap::const_iterator app_iter =
307       app_request_context_getter_map_.find(descriptor);
308   DCHECK(app_iter != app_request_context_getter_map_.end());
309   ChromeURLRequestContextGetter* app_context = app_iter->second.get();
310   ChromeURLRequestContextGetter* context =
311       ChromeURLRequestContextGetter::CreateForIsolatedMedia(
312           profile_, app_context, io_data_, descriptor);
313   isolated_media_request_context_getter_map_[descriptor] = context;
314
315   return context;
316 }
317
318 DevToolsNetworkController*
319 ProfileImplIOData::Handle::GetDevToolsNetworkController() const {
320   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
321   return io_data_->network_controller();
322 }
323
324 void ProfileImplIOData::Handle::ClearNetworkingHistorySince(
325     base::Time time,
326     const base::Closure& completion) {
327   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
328   LazyInitialize();
329
330   BrowserThread::PostTask(
331       BrowserThread::IO, FROM_HERE,
332       base::Bind(
333           &ProfileImplIOData::ClearNetworkingHistorySinceOnIOThread,
334           base::Unretained(io_data_),
335           time,
336           completion));
337 }
338
339 void ProfileImplIOData::Handle::LazyInitialize() const {
340   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
341   if (initialized_)
342     return;
343
344   // Set initialized_ to true at the beginning in case any of the objects
345   // below try to get the ResourceContext pointer.
346   initialized_ = true;
347   PrefService* pref_service = profile_->GetPrefs();
348   io_data_->http_server_properties_manager_ =
349       chrome_browser_net::HttpServerPropertiesManagerFactory::CreateManager(
350           pref_service);
351   io_data_->set_http_server_properties(
352       scoped_ptr<net::HttpServerProperties>(
353           io_data_->http_server_properties_manager_));
354   io_data_->session_startup_pref()->Init(
355       prefs::kRestoreOnStartup, pref_service);
356   io_data_->session_startup_pref()->MoveToThread(
357       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
358 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING)
359   io_data_->safe_browsing_enabled()->Init(prefs::kSafeBrowsingEnabled,
360       pref_service);
361   io_data_->safe_browsing_enabled()->MoveToThread(
362       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
363 #endif
364   io_data_->data_reduction_proxy_enabled()->Init(
365       data_reduction_proxy::prefs::kDataReductionProxyEnabled, pref_service);
366   io_data_->data_reduction_proxy_enabled()->MoveToThread(
367       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
368   io_data_->InitializeOnUIThread(profile_);
369 }
370
371 scoped_ptr<ProfileIOData::ChromeURLRequestContextGetterVector>
372 ProfileImplIOData::Handle::GetAllContextGetters() {
373   ChromeURLRequestContextGetterMap::iterator iter;
374   scoped_ptr<ChromeURLRequestContextGetterVector> context_getters(
375       new ChromeURLRequestContextGetterVector());
376
377   iter = isolated_media_request_context_getter_map_.begin();
378   for (; iter != isolated_media_request_context_getter_map_.end(); ++iter)
379     context_getters->push_back(iter->second);
380
381   iter = app_request_context_getter_map_.begin();
382   for (; iter != app_request_context_getter_map_.end(); ++iter)
383     context_getters->push_back(iter->second);
384
385   if (extensions_request_context_getter_.get())
386     context_getters->push_back(extensions_request_context_getter_);
387
388   if (media_request_context_getter_.get())
389     context_getters->push_back(media_request_context_getter_);
390
391   if (main_request_context_getter_.get())
392     context_getters->push_back(main_request_context_getter_);
393
394   return context_getters.Pass();
395 }
396
397 ProfileImplIOData::LazyParams::LazyParams()
398     : cache_max_size(0),
399       media_cache_max_size(0),
400       session_cookie_mode(
401           content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES) {}
402
403 ProfileImplIOData::LazyParams::~LazyParams() {}
404
405 ProfileImplIOData::ProfileImplIOData()
406     : ProfileIOData(Profile::REGULAR_PROFILE),
407       http_server_properties_manager_(NULL),
408       app_cache_max_size_(0),
409       app_media_cache_max_size_(0) {
410 }
411
412 ProfileImplIOData::~ProfileImplIOData() {
413   if (initialized())
414     network_delegate()->set_domain_reliability_monitor(NULL);
415
416   DestroyResourceContext();
417
418   if (media_request_context_)
419     media_request_context_->AssertNoURLRequests();
420 }
421
422 void ProfileImplIOData::InitializeInternal(
423     ProfileParams* profile_params,
424     content::ProtocolHandlerMap* protocol_handlers,
425     content::URLRequestInterceptorScopedVector request_interceptors) const {
426   net::URLRequestContext* main_context = main_request_context();
427
428   IOThread* const io_thread = profile_params->io_thread;
429   IOThread::Globals* const io_thread_globals = io_thread->globals();
430
431   set_data_reduction_proxy_auth_request_handler(
432       scoped_ptr<data_reduction_proxy::DataReductionProxyAuthRequestHandler>
433           (new data_reduction_proxy::DataReductionProxyAuthRequestHandler(
434               DataReductionProxyChromeSettings::GetClient(),
435               data_reduction_proxy_params(),
436               BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))));
437   set_data_reduction_proxy_usage_stats(
438       scoped_ptr<data_reduction_proxy::DataReductionProxyUsageStats>
439           (new data_reduction_proxy::DataReductionProxyUsageStats(
440               data_reduction_proxy_params(),
441               BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)
442                   .get())));
443   data_reduction_proxy_usage_stats()->set_unavailable_callback(
444       data_reduction_proxy_unavailable_callback());
445
446   network_delegate()->set_data_reduction_proxy_enabled_pref(
447       &data_reduction_proxy_enabled_);
448   network_delegate()->set_data_reduction_proxy_params(
449       data_reduction_proxy_params());
450   network_delegate()->set_data_reduction_proxy_usage_stats(
451       data_reduction_proxy_usage_stats());
452   network_delegate()->set_data_reduction_proxy_auth_request_handler(
453       data_reduction_proxy_auth_request_handler());
454   network_delegate()->set_data_reduction_proxy_statistics_prefs(
455       data_reduction_proxy_statistics_prefs());
456   network_delegate()->set_on_resolve_proxy_handler(
457       base::Bind(data_reduction_proxy::OnResolveProxyHandler));
458   network_delegate()->set_proxy_config_getter(
459       base::Bind(
460           &DataReductionProxyChromeConfigurator::GetProxyConfigOnIO,
461           base::Unretained(data_reduction_proxy_chrome_configurator())));
462   network_delegate()->set_predictor(predictor_.get());
463
464   // Initialize context members.
465
466   ApplyProfileParamsToContext(main_context);
467
468   if (http_server_properties_manager_)
469     http_server_properties_manager_->InitializeOnNetworkThread();
470
471   main_context->set_transport_security_state(transport_security_state());
472
473   main_context->set_net_log(io_thread->net_log());
474
475   main_context->set_network_delegate(network_delegate());
476
477   main_context->set_http_server_properties(http_server_properties());
478
479   main_context->set_host_resolver(
480       io_thread_globals->host_resolver.get());
481   main_context->set_cert_transparency_verifier(
482       io_thread_globals->cert_transparency_verifier.get());
483   main_context->set_http_auth_handler_factory(
484       io_thread_globals->http_auth_handler_factory.get());
485
486   main_context->set_fraudulent_certificate_reporter(
487       fraudulent_certificate_reporter());
488
489   main_context->set_throttler_manager(
490       io_thread_globals->throttler_manager.get());
491
492   main_context->set_proxy_service(proxy_service());
493
494   scoped_refptr<net::CookieStore> cookie_store = NULL;
495   net::ChannelIDService* channel_id_service = NULL;
496   if (chrome_browser_net::ShouldUseInMemoryCookiesAndCache()) {
497     // Don't use existing cookies and use an in-memory store.
498     using content::CookieStoreConfig;
499     cookie_store = content::CreateCookieStore(CookieStoreConfig(
500         base::FilePath(),
501         CookieStoreConfig::EPHEMERAL_SESSION_COOKIES,
502         NULL,
503         profile_params->cookie_monster_delegate.get()));
504     // Don't use existing channel ids and use an in-memory store.
505     channel_id_service = new net::ChannelIDService(
506         new net::DefaultChannelIDStore(NULL),
507         base::WorkerPool::GetTaskRunner(true));
508   }
509
510
511   // setup cookie store
512   if (!cookie_store.get()) {
513     DCHECK(!lazy_params_->cookie_path.empty());
514
515     content::CookieStoreConfig cookie_config(
516         lazy_params_->cookie_path,
517         lazy_params_->session_cookie_mode,
518         lazy_params_->special_storage_policy.get(),
519         profile_params->cookie_monster_delegate.get());
520     cookie_config.crypto_delegate =
521       chrome_browser_net::GetCookieCryptoDelegate();
522     cookie_store = content::CreateCookieStore(cookie_config);
523   }
524
525   main_context->set_cookie_store(cookie_store.get());
526
527   // Setup server bound cert service.
528   if (!channel_id_service) {
529     DCHECK(!lazy_params_->channel_id_path.empty());
530
531     scoped_refptr<QuotaPolicyChannelIDStore> channel_id_db =
532         new QuotaPolicyChannelIDStore(
533             lazy_params_->channel_id_path,
534             BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
535                 BrowserThread::GetBlockingPool()->GetSequenceToken()),
536             lazy_params_->special_storage_policy.get());
537     channel_id_service = new net::ChannelIDService(
538         new net::DefaultChannelIDStore(channel_id_db.get()),
539         base::WorkerPool::GetTaskRunner(true));
540   }
541
542   set_channel_id_service(channel_id_service);
543   main_context->set_channel_id_service(channel_id_service);
544
545   net::HttpCache::DefaultBackend* main_backend =
546       new net::HttpCache::DefaultBackend(
547           net::DISK_CACHE,
548           ChooseCacheBackendType(),
549           lazy_params_->cache_path,
550           lazy_params_->cache_max_size,
551           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE));
552   scoped_ptr<net::HttpCache> main_cache = CreateMainHttpFactory(
553       profile_params, main_backend);
554   main_cache->InitializeInfiniteCache(lazy_params_->infinite_cache_path);
555
556   if (chrome_browser_net::ShouldUseInMemoryCookiesAndCache()) {
557     main_cache->set_mode(
558         chrome_browser_net::IsCookieRecordMode() ?
559         net::HttpCache::RECORD : net::HttpCache::PLAYBACK);
560   }
561
562   main_http_factory_.reset(main_cache.release());
563   main_context->set_http_transaction_factory(main_http_factory_.get());
564
565 #if !defined(DISABLE_FTP_SUPPORT)
566   ftp_factory_.reset(
567       new net::FtpNetworkLayer(io_thread_globals->host_resolver.get()));
568 #endif  // !defined(DISABLE_FTP_SUPPORT)
569
570   scoped_ptr<net::URLRequestJobFactoryImpl> main_job_factory(
571       new net::URLRequestJobFactoryImpl());
572   InstallProtocolHandlers(main_job_factory.get(), protocol_handlers);
573   // The data reduction proxy interceptor should be as close to the network
574   // as possible.
575   request_interceptors.insert(
576       request_interceptors.begin(),
577       new data_reduction_proxy::DataReductionProxyInterceptor(
578           data_reduction_proxy_params(),
579           data_reduction_proxy_usage_stats()));
580   main_job_factory_ = SetUpJobFactoryDefaults(
581       main_job_factory.Pass(),
582       request_interceptors.Pass(),
583       profile_params->protocol_handler_interceptor.Pass(),
584       network_delegate(),
585       ftp_factory_.get());
586   main_context->set_job_factory(main_job_factory_.get());
587
588 #if defined(ENABLE_EXTENSIONS)
589   InitializeExtensionsRequestContext(profile_params);
590 #endif
591
592   // Setup SDCH for this profile.
593   sdch_manager_.reset(new net::SdchManager);
594   sdch_policy_.reset(new ChromeSdchPolicy(sdch_manager_.get(), main_context));
595   main_context->set_sdch_manager(sdch_manager_.get());
596
597   // Create a media request context based on the main context, but using a
598   // media cache.  It shares the same job factory as the main context.
599   StoragePartitionDescriptor details(profile_path_, false);
600   media_request_context_.reset(InitializeMediaRequestContext(main_context,
601                                                              details));
602
603   if (domain_reliability_monitor_) {
604     domain_reliability::DomainReliabilityMonitor* monitor =
605         domain_reliability_monitor_.get();
606     monitor->InitURLRequestContext(main_context);
607     monitor->AddBakedInConfigs();
608     monitor->SetDiscardUploads(!GetMetricsEnabledStateOnIOThread());
609     network_delegate()->set_domain_reliability_monitor(monitor);
610   }
611
612   lazy_params_.reset();
613 }
614
615 void ProfileImplIOData::
616     InitializeExtensionsRequestContext(ProfileParams* profile_params) const {
617   net::URLRequestContext* extensions_context = extensions_request_context();
618   IOThread* const io_thread = profile_params->io_thread;
619   IOThread::Globals* const io_thread_globals = io_thread->globals();
620   ApplyProfileParamsToContext(extensions_context);
621
622   extensions_context->set_transport_security_state(transport_security_state());
623
624   extensions_context->set_net_log(io_thread->net_log());
625
626   extensions_context->set_throttler_manager(
627       io_thread_globals->throttler_manager.get());
628
629   content::CookieStoreConfig cookie_config(
630       lazy_params_->extensions_cookie_path,
631       lazy_params_->session_cookie_mode,
632       NULL, NULL);
633   cookie_config.crypto_delegate =
634       chrome_browser_net::GetCookieCryptoDelegate();
635   net::CookieStore* extensions_cookie_store =
636       content::CreateCookieStore(cookie_config);
637   // Enable cookies for devtools and extension URLs.
638   const char* const schemes[] = {
639       content::kChromeDevToolsScheme,
640       extensions::kExtensionScheme
641   };
642   extensions_cookie_store->GetCookieMonster()->SetCookieableSchemes(
643       schemes, arraysize(schemes));
644   extensions_context->set_cookie_store(extensions_cookie_store);
645
646   scoped_ptr<net::URLRequestJobFactoryImpl> extensions_job_factory(
647       new net::URLRequestJobFactoryImpl());
648   // TODO(shalev): The extensions_job_factory has a NULL NetworkDelegate.
649   // Without a network_delegate, this protocol handler will never
650   // handle file: requests, but as a side effect it makes
651   // job_factory::IsHandledProtocol return true, which prevents attempts to
652   // handle the protocol externally. We pass NULL in to
653   // SetUpJobFactory() to get this effect.
654   extensions_job_factory_ = SetUpJobFactoryDefaults(
655       extensions_job_factory.Pass(),
656       content::URLRequestInterceptorScopedVector(),
657       scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>(),
658       NULL,
659       ftp_factory_.get());
660   extensions_context->set_job_factory(extensions_job_factory_.get());
661 }
662
663 net::URLRequestContext* ProfileImplIOData::InitializeAppRequestContext(
664     net::URLRequestContext* main_context,
665     const StoragePartitionDescriptor& partition_descriptor,
666     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
667         protocol_handler_interceptor,
668     content::ProtocolHandlerMap* protocol_handlers,
669     content::URLRequestInterceptorScopedVector request_interceptors) const {
670   // Copy most state from the main context.
671   AppRequestContext* context = new AppRequestContext();
672   context->CopyFrom(main_context);
673
674   base::FilePath cookie_path = partition_descriptor.path.Append(
675       chrome::kCookieFilename);
676   base::FilePath cache_path =
677       partition_descriptor.path.Append(chrome::kCacheDirname);
678
679   // Use a separate HTTP disk cache for isolated apps.
680   net::HttpCache::BackendFactory* app_backend = NULL;
681   if (partition_descriptor.in_memory) {
682     app_backend = net::HttpCache::DefaultBackend::InMemory(0);
683   } else {
684     app_backend = new net::HttpCache::DefaultBackend(
685         net::DISK_CACHE,
686         ChooseCacheBackendType(),
687         cache_path,
688         app_cache_max_size_,
689         BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE));
690   }
691   net::HttpNetworkSession* main_network_session =
692       main_http_factory_->GetSession();
693   scoped_ptr<net::HttpCache> app_http_cache =
694       CreateHttpFactory(main_network_session, app_backend);
695
696   scoped_refptr<net::CookieStore> cookie_store = NULL;
697   if (partition_descriptor.in_memory) {
698     cookie_store = content::CreateCookieStore(content::CookieStoreConfig());
699   } else if (chrome_browser_net::ShouldUseInMemoryCookiesAndCache()) {
700     // Don't use existing cookies and use an in-memory store.
701     // TODO(creis): We should have a cookie delegate for notifying the cookie
702     // extensions API, but we need to update it to understand isolated apps
703     // first.
704     cookie_store = content::CreateCookieStore(content::CookieStoreConfig());
705     app_http_cache->set_mode(
706         chrome_browser_net::IsCookieRecordMode() ?
707         net::HttpCache::RECORD : net::HttpCache::PLAYBACK);
708   }
709
710   // Use an app-specific cookie store.
711   if (!cookie_store.get()) {
712     DCHECK(!cookie_path.empty());
713
714     // TODO(creis): We should have a cookie delegate for notifying the cookie
715     // extensions API, but we need to update it to understand isolated apps
716     // first.
717     content::CookieStoreConfig cookie_config(
718         cookie_path,
719         content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES,
720         NULL, NULL);
721     cookie_config.crypto_delegate =
722       chrome_browser_net::GetCookieCryptoDelegate();
723     cookie_store = content::CreateCookieStore(cookie_config);
724   }
725
726   // Transfer ownership of the cookies and cache to AppRequestContext.
727   context->SetCookieStore(cookie_store.get());
728   context->SetHttpTransactionFactory(app_http_cache.Pass());
729
730   scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
731       new net::URLRequestJobFactoryImpl());
732   InstallProtocolHandlers(job_factory.get(), protocol_handlers);
733   // The data reduction proxy interceptor should be as close to the network
734   // as possible.
735   request_interceptors.insert(
736       request_interceptors.begin(),
737       new data_reduction_proxy::DataReductionProxyInterceptor(
738           data_reduction_proxy_params(),
739           data_reduction_proxy_usage_stats()));
740   scoped_ptr<net::URLRequestJobFactory> top_job_factory(
741       SetUpJobFactoryDefaults(job_factory.Pass(),
742                               request_interceptors.Pass(),
743                               protocol_handler_interceptor.Pass(),
744                               network_delegate(),
745                               ftp_factory_.get()));
746   context->SetJobFactory(top_job_factory.Pass());
747
748   return context;
749 }
750
751 net::URLRequestContext*
752 ProfileImplIOData::InitializeMediaRequestContext(
753     net::URLRequestContext* original_context,
754     const StoragePartitionDescriptor& partition_descriptor) const {
755   // Copy most state from the original context.
756   MediaRequestContext* context = new MediaRequestContext();
757   context->CopyFrom(original_context);
758
759   // For in-memory context, return immediately after creating the new
760   // context before attaching a separate cache. It is important to return
761   // a new context rather than just reusing |original_context| because
762   // the caller expects to take ownership of the pointer.
763   if (partition_descriptor.in_memory)
764     return context;
765
766   using content::StoragePartition;
767   base::FilePath cache_path;
768   int cache_max_size = app_media_cache_max_size_;
769   if (partition_descriptor.path == profile_path_) {
770     // lazy_params_ is only valid for the default media context creation.
771     cache_path = lazy_params_->media_cache_path;
772     cache_max_size = lazy_params_->media_cache_max_size;
773   } else {
774     cache_path = partition_descriptor.path.Append(chrome::kMediaCacheDirname);
775   }
776
777   // Use a separate HTTP disk cache for isolated apps.
778   net::HttpCache::BackendFactory* media_backend =
779       new net::HttpCache::DefaultBackend(
780           net::MEDIA_CACHE,
781           ChooseCacheBackendType(),
782           cache_path,
783           cache_max_size,
784           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE));
785   net::HttpNetworkSession* main_network_session =
786       main_http_factory_->GetSession();
787   scoped_ptr<net::HttpCache> media_http_cache =
788       CreateHttpFactory(main_network_session, media_backend);
789
790   // Transfer ownership of the cache to MediaRequestContext.
791   context->SetHttpTransactionFactory(media_http_cache.Pass());
792
793   // Note that we do not create a new URLRequestJobFactory because
794   // the media context should behave exactly like its parent context
795   // in all respects except for cache behavior on media subresources.
796   // The CopyFrom() step above means that our media context will use
797   // the same URLRequestJobFactory instance that our parent context does.
798
799   return context;
800 }
801
802 net::URLRequestContext*
803 ProfileImplIOData::AcquireMediaRequestContext() const {
804   DCHECK(media_request_context_);
805   return media_request_context_.get();
806 }
807
808 net::URLRequestContext* ProfileImplIOData::AcquireIsolatedAppRequestContext(
809     net::URLRequestContext* main_context,
810     const StoragePartitionDescriptor& partition_descriptor,
811     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
812         protocol_handler_interceptor,
813     content::ProtocolHandlerMap* protocol_handlers,
814     content::URLRequestInterceptorScopedVector request_interceptors) const {
815   // We create per-app contexts on demand, unlike the others above.
816   net::URLRequestContext* app_request_context =
817       InitializeAppRequestContext(main_context,
818                                   partition_descriptor,
819                                   protocol_handler_interceptor.Pass(),
820                                   protocol_handlers,
821                                   request_interceptors.Pass());
822   DCHECK(app_request_context);
823   return app_request_context;
824 }
825
826 net::URLRequestContext*
827 ProfileImplIOData::AcquireIsolatedMediaRequestContext(
828     net::URLRequestContext* app_context,
829     const StoragePartitionDescriptor& partition_descriptor) const {
830   // We create per-app media contexts on demand, unlike the others above.
831   net::URLRequestContext* media_request_context =
832       InitializeMediaRequestContext(app_context, partition_descriptor);
833   DCHECK(media_request_context);
834   return media_request_context;
835 }
836
837 void ProfileImplIOData::ClearNetworkingHistorySinceOnIOThread(
838     base::Time time,
839     const base::Closure& completion) {
840   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
841   DCHECK(initialized());
842
843   DCHECK(transport_security_state());
844   // Completes synchronously.
845   transport_security_state()->DeleteAllDynamicDataSince(time);
846   DCHECK(http_server_properties_manager_);
847   http_server_properties_manager_->Clear(completion);
848 }
849
850 bool ProfileImplIOData::IsDataReductionProxyEnabled() const {
851   return data_reduction_proxy_enabled_.GetValue() ||
852          CommandLine::ForCurrentProcess()->HasSwitch(
853             data_reduction_proxy::switches::kEnableDataReductionProxy);
854 }