profile_io_data.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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_io_data.h"
6
7#include <string>
8
9#include "base/basictypes.h"
10#include "base/bind.h"
11#include "base/bind_helpers.h"
12#include "base/callback.h"
13#include "base/command_line.h"
14#include "base/compiler_specific.h"
15#include "base/debug/alias.h"
16#include "base/logging.h"
17#include "base/path_service.h"
18#include "base/prefs/pref_service.h"
19#include "base/stl_util.h"
20#include "base/strings/string_number_conversions.h"
21#include "base/strings/string_util.h"
22#include "base/strings/stringprintf.h"
23#include "base/threading/sequenced_worker_pool.h"
24#include "chrome/browser/browser_process.h"
25#include "chrome/browser/chrome_notification_types.h"
26#include "chrome/browser/content_settings/cookie_settings.h"
27#include "chrome/browser/content_settings/host_content_settings_map.h"
28#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
29#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
30#include "chrome/browser/devtools/devtools_network_controller.h"
31#include "chrome/browser/devtools/devtools_network_transaction_factory.h"
32#include "chrome/browser/download/download_service.h"
33#include "chrome/browser/download/download_service_factory.h"
34#include "chrome/browser/io_thread.h"
35#include "chrome/browser/media/media_device_id_salt.h"
36#include "chrome/browser/net/about_protocol_handler.h"
37#include "chrome/browser/net/chrome_fraudulent_certificate_reporter.h"
38#include "chrome/browser/net/chrome_http_user_agent_settings.h"
39#include "chrome/browser/net/chrome_net_log.h"
40#include "chrome/browser/net/chrome_network_delegate.h"
41#include "chrome/browser/net/chrome_url_request_context_getter.h"
42#include "chrome/browser/net/cookie_store_util.h"
43#include "chrome/browser/net/proxy_service_factory.h"
44#include "chrome/browser/net/resource_prefetch_predictor_observer.h"
45#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_configurator.h"
46#include "chrome/browser/predictors/resource_prefetch_predictor.h"
47#include "chrome/browser/predictors/resource_prefetch_predictor_factory.h"
48#include "chrome/browser/profiles/profile.h"
49#include "chrome/browser/profiles/profile_manager.h"
50#include "chrome/browser/signin/signin_names_io_thread.h"
51#include "chrome/common/chrome_paths.h"
52#include "chrome/common/chrome_switches.h"
53#include "chrome/common/pref_names.h"
54#include "chrome/common/url_constants.h"
55#include "components/content_settings/core/browser/content_settings_provider.h"
56#include "components/data_reduction_proxy/browser/data_reduction_proxy_config_service.h"
57#include "components/data_reduction_proxy/browser/data_reduction_proxy_configurator.h"
58#include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"
59#include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h"
60#include "components/dom_distiller/core/url_constants.h"
61#include "components/startup_metric_utils/startup_metric_utils.h"
62#include "components/sync_driver/pref_names.h"
63#include "components/url_fixer/url_fixer.h"
64#include "content/public/browser/browser_thread.h"
65#include "content/public/browser/host_zoom_map.h"
66#include "content/public/browser/notification_service.h"
67#include "content/public/browser/resource_context.h"
68#include "net/base/keygen_handler.h"
69#include "net/cookies/canonical_cookie.h"
70#include "net/http/http_transaction_factory.h"
71#include "net/http/http_util.h"
72#include "net/http/transport_security_persister.h"
73#include "net/proxy/proxy_config_service_fixed.h"
74#include "net/proxy/proxy_script_fetcher_impl.h"
75#include "net/proxy/proxy_service.h"
76#include "net/ssl/channel_id_service.h"
77#include "net/ssl/client_cert_store.h"
78#include "net/url_request/data_protocol_handler.h"
79#include "net/url_request/file_protocol_handler.h"
80#include "net/url_request/ftp_protocol_handler.h"
81#include "net/url_request/url_request.h"
82#include "net/url_request/url_request_context.h"
83#include "net/url_request/url_request_file_job.h"
84#include "net/url_request/url_request_intercepting_job_factory.h"
85#include "net/url_request/url_request_interceptor.h"
86#include "net/url_request/url_request_job_factory_impl.h"
87
88#if defined(ENABLE_CONFIGURATION_POLICY)
89#include "chrome/browser/policy/cloud/policy_header_service_factory.h"
90#include "chrome/browser/policy/policy_helpers.h"
91#include "components/policy/core/browser/url_blacklist_manager.h"
92#include "components/policy/core/common/cloud/policy_header_io_helper.h"
93#include "components/policy/core/common/cloud/policy_header_service.h"
94#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
95#endif
96
97#if defined(ENABLE_EXTENSIONS)
98#include "chrome/browser/extensions/extension_resource_protocols.h"
99#include "extensions/browser/extension_protocols.h"
100#include "extensions/browser/extension_system.h"
101#include "extensions/browser/info_map.h"
102#include "extensions/common/constants.h"
103#endif
104
105#if defined(ENABLE_MANAGED_USERS)
106#include "chrome/browser/supervised_user/supervised_user_service.h"
107#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
108#include "chrome/browser/supervised_user/supervised_user_url_filter.h"
109#endif
110
111#if defined(OS_ANDROID)
112#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
113#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
114#include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h"
115#endif  // defined(OS_ANDROID)
116
117#if defined(OS_CHROMEOS)
118#include "chrome/browser/chromeos/fileapi/external_file_protocol_handler.h"
119#include "chrome/browser/chromeos/login/startup_utils.h"
120#include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
121#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
122#include "chrome/browser/chromeos/policy/policy_cert_service.h"
123#include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
124#include "chrome/browser/chromeos/policy/policy_cert_verifier.h"
125#include "chrome/browser/chromeos/profiles/profile_helper.h"
126#include "chrome/browser/chromeos/settings/cros_settings.h"
127#include "chrome/browser/net/nss_context.h"
128#include "chromeos/dbus/cryptohome_client.h"
129#include "chromeos/dbus/dbus_thread_manager.h"
130#include "chromeos/settings/cros_settings_names.h"
131#include "components/user_manager/user.h"
132#include "components/user_manager/user_manager.h"
133#include "crypto/nss_util.h"
134#include "crypto/nss_util_internal.h"
135#include "net/cert/cert_verifier.h"
136#include "net/cert/multi_threaded_cert_verifier.h"
137#include "net/ssl/client_cert_store_chromeos.h"
138#endif  // defined(OS_CHROMEOS)
139
140#if defined(USE_NSS)
141#include "chrome/browser/ui/crypto_module_delegate_nss.h"
142#include "net/ssl/client_cert_store_nss.h"
143#endif
144
145#if defined(OS_WIN)
146#include "net/ssl/client_cert_store_win.h"
147#endif
148
149#if defined(OS_MACOSX)
150#include "net/ssl/client_cert_store_mac.h"
151#endif
152
153using content::BrowserContext;
154using content::BrowserThread;
155using content::ResourceContext;
156
157namespace {
158
159#if defined(DEBUG_DEVTOOLS)
160bool IsSupportedDevToolsURL(const GURL& url, base::FilePath* path) {
161  std::string bundled_path_prefix(chrome::kChromeUIDevToolsBundledPath);
162  bundled_path_prefix = "/" + bundled_path_prefix + "/";
163
164  if (!url.SchemeIs(content::kChromeDevToolsScheme) ||
165      url.host() != chrome::kChromeUIDevToolsHost ||
166      !StartsWithASCII(url.path(), bundled_path_prefix, false)) {
167    return false;
168  }
169
170  if (!url.is_valid()) {
171    NOTREACHED();
172    return false;
173  }
174
175  // Remove Query and Ref from URL.
176  GURL stripped_url;
177  GURL::Replacements replacements;
178  replacements.ClearQuery();
179  replacements.ClearRef();
180  stripped_url = url.ReplaceComponents(replacements);
181
182  std::string relative_path;
183  const std::string& spec = stripped_url.possibly_invalid_spec();
184  const url::Parsed& parsed = stripped_url.parsed_for_possibly_invalid_spec();
185  int offset = parsed.CountCharactersBefore(url::Parsed::PATH, false);
186  if (offset < static_cast<int>(spec.size()))
187    relative_path.assign(spec.substr(offset + bundled_path_prefix.length()));
188
189  // Check that |relative_path| is not an absolute path (otherwise
190  // AppendASCII() will DCHECK).  The awkward use of StringType is because on
191  // some systems FilePath expects a std::string, but on others a std::wstring.
192  base::FilePath p(
193      base::FilePath::StringType(relative_path.begin(), relative_path.end()));
194  if (p.IsAbsolute())
195    return false;
196
197  base::FilePath inspector_dir;
198  if (!PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir))
199    return false;
200
201  if (inspector_dir.empty())
202    return false;
203
204  *path = inspector_dir.AppendASCII(relative_path);
205  return true;
206}
207
208class DebugDevToolsInterceptor : public net::URLRequestInterceptor {
209 public:
210  DebugDevToolsInterceptor() {}
211  virtual ~DebugDevToolsInterceptor() {}
212
213  // net::URLRequestInterceptor implementation.
214  virtual net::URLRequestJob* MaybeInterceptRequest(
215      net::URLRequest* request,
216      net::NetworkDelegate* network_delegate) const OVERRIDE {
217    base::FilePath path;
218    if (IsSupportedDevToolsURL(request->url(), &path))
219      return new net::URLRequestFileJob(
220          request, network_delegate, path,
221          content::BrowserThread::GetBlockingPool()->
222              GetTaskRunnerWithShutdownBehavior(
223                  base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
224
225    return NULL;
226  }
227};
228#endif  // defined(DEBUG_DEVTOOLS)
229
230#if defined(OS_CHROMEOS)
231// The following four functions are responsible for initializing NSS for each
232// profile on ChromeOS, which has a separate NSS database and TPM slot
233// per-profile.
234//
235// Initialization basically follows these steps:
236// 1) Get some info from user_manager::UserManager about the User for this
237// profile.
238// 2) Tell nss_util to initialize the software slot for this profile.
239// 3) Wait for the TPM module to be loaded by nss_util if it isn't already.
240// 4) Ask CryptohomeClient which TPM slot id corresponds to this profile.
241// 5) Tell nss_util to use that slot id on the TPM module.
242//
243// Some of these steps must happen on the UI thread, others must happen on the
244// IO thread:
245//               UI thread                              IO Thread
246//
247//  ProfileIOData::InitializeOnUIThread
248//                   |
249//  ProfileHelper::Get()->GetUserByProfile()
250//                   \---------------------------------------v
251//                                                 StartNSSInitOnIOThread
252//                                                           |
253//                                          crypto::InitializeNSSForChromeOSUser
254//                                                           |
255//                                                crypto::IsTPMTokenReady
256//                                                           |
257//                                          StartTPMSlotInitializationOnIOThread
258//                   v---------------------------------------/
259//     GetTPMInfoForUserOnUIThread
260//                   |
261// CryptohomeClient::Pkcs11GetTpmTokenInfoForUser
262//                   |
263//     DidGetTPMInfoForUserOnUIThread
264//                   \---------------------------------------v
265//                                          crypto::InitializeTPMForChromeOSUser
266
267void DidGetTPMInfoForUserOnUIThread(const std::string& username_hash,
268                                    chromeos::DBusMethodCallStatus call_status,
269                                    const std::string& label,
270                                    const std::string& user_pin,
271                                    int slot_id) {
272  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
273  if (call_status == chromeos::DBUS_METHOD_CALL_FAILURE) {
274    NOTREACHED() << "dbus error getting TPM info for " << username_hash;
275    return;
276  }
277  DVLOG(1) << "Got TPM slot for " << username_hash << ": " << slot_id;
278  BrowserThread::PostTask(
279      BrowserThread::IO,
280      FROM_HERE,
281      base::Bind(
282          &crypto::InitializeTPMForChromeOSUser, username_hash, slot_id));
283}
284
285void GetTPMInfoForUserOnUIThread(const std::string& username,
286                                 const std::string& username_hash) {
287  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
288  DVLOG(1) << "Getting TPM info from cryptohome for "
289           << " " << username << " " << username_hash;
290  chromeos::DBusThreadManager::Get()
291      ->GetCryptohomeClient()
292      ->Pkcs11GetTpmTokenInfoForUser(
293            username,
294            base::Bind(&DidGetTPMInfoForUserOnUIThread, username_hash));
295}
296
297void StartTPMSlotInitializationOnIOThread(const std::string& username,
298                                          const std::string& username_hash) {
299  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
300
301  BrowserThread::PostTask(
302      BrowserThread::UI,
303      FROM_HERE,
304      base::Bind(&GetTPMInfoForUserOnUIThread, username, username_hash));
305}
306
307void StartNSSInitOnIOThread(const std::string& username,
308                            const std::string& username_hash,
309                            const base::FilePath& path) {
310  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
311  DVLOG(1) << "Starting NSS init for " << username
312           << "  hash:" << username_hash;
313
314  // Make sure NSS is initialized for the user.
315  crypto::InitializeNSSForChromeOSUser(username_hash, path);
316
317  // Check if it's OK to initialize TPM for the user before continuing. This
318  // may not be the case if the TPM slot initialization was previously
319  // requested for the same user.
320  if (!crypto::ShouldInitializeTPMForChromeOSUser(username_hash))
321    return;
322
323  crypto::WillInitializeTPMForChromeOSUser(username_hash);
324
325  if (crypto::IsTPMTokenEnabledForNSS()) {
326    if (crypto::IsTPMTokenReady(base::Bind(
327            &StartTPMSlotInitializationOnIOThread, username, username_hash))) {
328      StartTPMSlotInitializationOnIOThread(username, username_hash);
329    } else {
330      DVLOG(1) << "Waiting for tpm ready ...";
331    }
332  } else {
333    crypto::InitializePrivateSoftwareSlotForChromeOSUser(username_hash);
334  }
335}
336#endif  // defined(OS_CHROMEOS)
337
338void InvalidateContextGettersOnIO(
339    scoped_ptr<ProfileIOData::ChromeURLRequestContextGetterVector> getters) {
340  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
341  ProfileIOData::ChromeURLRequestContextGetterVector::iterator iter;
342  for (iter = getters->begin(); iter != getters->end(); ++iter)
343    (*iter)->Invalidate();
344}
345
346}  // namespace
347
348void ProfileIOData::InitializeOnUIThread(Profile* profile) {
349  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
350  PrefService* pref_service = profile->GetPrefs();
351  PrefService* local_state_pref_service = g_browser_process->local_state();
352
353  scoped_ptr<ProfileParams> params(new ProfileParams);
354  params->path = profile->GetPath();
355
356  params->io_thread = g_browser_process->io_thread();
357
358  params->cookie_settings = CookieSettings::Factory::GetForProfile(profile);
359  params->host_content_settings_map = profile->GetHostContentSettingsMap();
360  params->ssl_config_service = profile->GetSSLConfigService();
361  params->cookie_monster_delegate =
362      chrome_browser_net::CreateCookieDelegate(profile);
363#if defined(ENABLE_EXTENSIONS)
364  params->extension_info_map =
365      extensions::ExtensionSystem::Get(profile)->info_map();
366#endif
367
368  if (predictors::ResourcePrefetchPredictor* predictor =
369          predictors::ResourcePrefetchPredictorFactory::GetForProfile(
370              profile)) {
371    resource_prefetch_predictor_observer_.reset(
372        new chrome_browser_net::ResourcePrefetchPredictorObserver(predictor));
373  }
374
375  ProtocolHandlerRegistry* protocol_handler_registry =
376      ProtocolHandlerRegistryFactory::GetForBrowserContext(profile);
377  DCHECK(protocol_handler_registry);
378
379  // The profile instance is only available here in the InitializeOnUIThread
380  // method, so we create the url job factory here, then save it for
381  // later delivery to the job factory in Init().
382  params->protocol_handler_interceptor =
383      protocol_handler_registry->CreateJobInterceptorFactory();
384
385  params->proxy_config_service
386      .reset(ProxyServiceFactory::CreateProxyConfigService(
387           profile->GetProxyConfigTracker()));
388#if defined(ENABLE_MANAGED_USERS)
389  SupervisedUserService* supervised_user_service =
390      SupervisedUserServiceFactory::GetForProfile(profile);
391  params->supervised_user_url_filter =
392      supervised_user_service->GetURLFilterForIOThread();
393#endif
394#if defined(OS_CHROMEOS)
395  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
396  if (user_manager) {
397    user_manager::User* user =
398        chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
399    // No need to initialize NSS for users with empty username hash:
400    // Getters for a user's NSS slots always return NULL slot if the user's
401    // username hash is empty, even when the NSS is not initialized for the
402    // user.
403    if (user && !user->username_hash().empty()) {
404      params->username_hash = user->username_hash();
405      DCHECK(!params->username_hash.empty());
406      BrowserThread::PostTask(BrowserThread::IO,
407                              FROM_HERE,
408                              base::Bind(&StartNSSInitOnIOThread,
409                                         user->email(),
410                                         user->username_hash(),
411                                         profile->GetPath()));
412
413      // Use the device-wide system key slot only if the user is of the same
414      // domain as the device is registered to.
415      policy::BrowserPolicyConnectorChromeOS* connector =
416          g_browser_process->platform_part()
417              ->browser_policy_connector_chromeos();
418      params->use_system_key_slot =
419          connector->GetUserAffiliation(user->email()) ==
420          policy::USER_AFFILIATION_MANAGED;
421    }
422  }
423#endif
424
425  params->profile = profile;
426  params->prerender_tracker = g_browser_process->prerender_tracker();
427  profile_params_.reset(params.release());
428
429  ChromeNetworkDelegate::InitializePrefsOnUIThread(
430      &enable_referrers_,
431      &enable_do_not_track_,
432      &force_safesearch_,
433      pref_service);
434
435  scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy =
436      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
437#if defined(ENABLE_PRINTING)
438  printing_enabled_.Init(prefs::kPrintingEnabled, pref_service);
439  printing_enabled_.MoveToThread(io_message_loop_proxy);
440#endif
441
442  chrome_http_user_agent_settings_.reset(
443      new ChromeHttpUserAgentSettings(pref_service));
444
445  // These members are used only for one click sign in, which is not enabled
446  // in incognito mode.  So no need to initialize them.
447  if (!IsOffTheRecord()) {
448    signin_names_.reset(new SigninNamesOnIOThread());
449
450    google_services_user_account_id_.Init(
451        prefs::kGoogleServicesUserAccountId, pref_service);
452    google_services_user_account_id_.MoveToThread(io_message_loop_proxy);
453
454    google_services_username_.Init(
455        prefs::kGoogleServicesUsername, pref_service);
456    google_services_username_.MoveToThread(io_message_loop_proxy);
457
458    google_services_username_pattern_.Init(
459        prefs::kGoogleServicesUsernamePattern, local_state_pref_service);
460    google_services_username_pattern_.MoveToThread(io_message_loop_proxy);
461
462    reverse_autologin_enabled_.Init(
463        prefs::kReverseAutologinEnabled, pref_service);
464    reverse_autologin_enabled_.MoveToThread(io_message_loop_proxy);
465
466    one_click_signin_rejected_email_list_.Init(
467        prefs::kReverseAutologinRejectedEmailList, pref_service);
468    one_click_signin_rejected_email_list_.MoveToThread(io_message_loop_proxy);
469
470    sync_disabled_.Init(sync_driver::prefs::kSyncManaged, pref_service);
471    sync_disabled_.MoveToThread(io_message_loop_proxy);
472
473    signin_allowed_.Init(prefs::kSigninAllowed, pref_service);
474    signin_allowed_.MoveToThread(io_message_loop_proxy);
475  }
476
477  quick_check_enabled_.Init(prefs::kQuickCheckEnabled,
478                            local_state_pref_service);
479  quick_check_enabled_.MoveToThread(io_message_loop_proxy);
480
481  media_device_id_salt_ = new MediaDeviceIDSalt(pref_service, IsOffTheRecord());
482
483  network_prediction_options_.Init(prefs::kNetworkPredictionOptions,
484                                   pref_service);
485
486  network_prediction_options_.MoveToThread(io_message_loop_proxy);
487
488#if defined(OS_CHROMEOS)
489  scoped_ptr<policy::PolicyCertVerifier> verifier =
490      policy::PolicyCertServiceFactory::CreateForProfile(profile);
491  policy_cert_verifier_ = verifier.get();
492  cert_verifier_ = verifier.Pass();
493#endif
494  // The URLBlacklistManager has to be created on the UI thread to register
495  // observers of |pref_service|, and it also has to clean up on
496  // ShutdownOnUIThread to release these observers on the right thread.
497  // Don't pass it in |profile_params_| to make sure it is correctly cleaned up,
498  // in particular when this ProfileIOData isn't |initialized_| during deletion.
499#if defined(ENABLE_CONFIGURATION_POLICY)
500  policy::URLBlacklist::SegmentURLCallback callback =
501      static_cast<policy::URLBlacklist::SegmentURLCallback>(
502          url_fixer::SegmentURL);
503  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
504  scoped_refptr<base::SequencedTaskRunner> background_task_runner =
505      pool->GetSequencedTaskRunner(pool->GetSequenceToken());
506  url_blacklist_manager_.reset(
507      new policy::URLBlacklistManager(
508          pref_service,
509          background_task_runner,
510          io_message_loop_proxy,
511          callback,
512          base::Bind(policy::OverrideBlacklistForURL)));
513
514  if (!IsOffTheRecord()) {
515    // Add policy headers for non-incognito requests.
516    policy::PolicyHeaderService* policy_header_service =
517        policy::PolicyHeaderServiceFactory::GetForBrowserContext(profile);
518    if (policy_header_service) {
519      policy_header_helper_ = policy_header_service->CreatePolicyHeaderIOHelper(
520          io_message_loop_proxy);
521    }
522  }
523#endif
524
525  incognito_availibility_pref_.Init(
526      prefs::kIncognitoModeAvailability, pref_service);
527  incognito_availibility_pref_.MoveToThread(io_message_loop_proxy);
528
529  initialized_on_UI_thread_ = true;
530
531  // We need to make sure that content initializes its own data structures that
532  // are associated with each ResourceContext because we might post this
533  // object to the IO thread after this function.
534  BrowserContext::EnsureResourceContextInitialized(profile);
535}
536
537ProfileIOData::MediaRequestContext::MediaRequestContext() {
538}
539
540void ProfileIOData::MediaRequestContext::SetHttpTransactionFactory(
541    scoped_ptr<net::HttpTransactionFactory> http_factory) {
542  http_factory_ = http_factory.Pass();
543  set_http_transaction_factory(http_factory_.get());
544}
545
546ProfileIOData::MediaRequestContext::~MediaRequestContext() {
547  AssertNoURLRequests();
548}
549
550ProfileIOData::AppRequestContext::AppRequestContext() {
551}
552
553void ProfileIOData::AppRequestContext::SetCookieStore(
554    net::CookieStore* cookie_store) {
555  cookie_store_ = cookie_store;
556  set_cookie_store(cookie_store);
557}
558
559void ProfileIOData::AppRequestContext::SetHttpTransactionFactory(
560    scoped_ptr<net::HttpTransactionFactory> http_factory) {
561  http_factory_ = http_factory.Pass();
562  set_http_transaction_factory(http_factory_.get());
563}
564
565void ProfileIOData::AppRequestContext::SetJobFactory(
566    scoped_ptr<net::URLRequestJobFactory> job_factory) {
567  job_factory_ = job_factory.Pass();
568  set_job_factory(job_factory_.get());
569}
570
571ProfileIOData::AppRequestContext::~AppRequestContext() {
572  AssertNoURLRequests();
573}
574
575ProfileIOData::ProfileParams::ProfileParams()
576    : io_thread(NULL),
577#if defined(OS_CHROMEOS)
578      use_system_key_slot(false),
579#endif
580      profile(NULL) {
581}
582
583ProfileIOData::ProfileParams::~ProfileParams() {}
584
585ProfileIOData::ProfileIOData(Profile::ProfileType profile_type)
586    : initialized_(false),
587#if defined(OS_CHROMEOS)
588      policy_cert_verifier_(NULL),
589      use_system_key_slot_(false),
590#endif
591      resource_context_(new ResourceContext(this)),
592      initialized_on_UI_thread_(false),
593      profile_type_(profile_type) {
594  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
595}
596
597ProfileIOData::~ProfileIOData() {
598  if (BrowserThread::IsMessageLoopValid(BrowserThread::IO))
599    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
600
601  // Pull the contents of the request context maps onto the stack for sanity
602  // checking of values in a minidump. http://crbug.com/260425
603  size_t num_app_contexts = app_request_context_map_.size();
604  size_t num_media_contexts = isolated_media_request_context_map_.size();
605  size_t current_context = 0;
606  static const size_t kMaxCachedContexts = 20;
607  net::URLRequestContext* app_context_cache[kMaxCachedContexts] = {0};
608  void* app_context_vtable_cache[kMaxCachedContexts] = {0};
609  net::URLRequestContext* media_context_cache[kMaxCachedContexts] = {0};
610  void* media_context_vtable_cache[kMaxCachedContexts] = {0};
611  void* tmp_vtable = NULL;
612  base::debug::Alias(&num_app_contexts);
613  base::debug::Alias(&num_media_contexts);
614  base::debug::Alias(&current_context);
615  base::debug::Alias(app_context_cache);
616  base::debug::Alias(app_context_vtable_cache);
617  base::debug::Alias(media_context_cache);
618  base::debug::Alias(media_context_vtable_cache);
619  base::debug::Alias(&tmp_vtable);
620
621  current_context = 0;
622  for (URLRequestContextMap::const_iterator it =
623           app_request_context_map_.begin();
624       current_context < kMaxCachedContexts &&
625           it != app_request_context_map_.end();
626       ++it, ++current_context) {
627    app_context_cache[current_context] = it->second;
628    memcpy(&app_context_vtable_cache[current_context],
629           static_cast<void*>(it->second), sizeof(void*));
630  }
631
632  current_context = 0;
633  for (URLRequestContextMap::const_iterator it =
634           isolated_media_request_context_map_.begin();
635       current_context < kMaxCachedContexts &&
636           it != isolated_media_request_context_map_.end();
637       ++it, ++current_context) {
638    media_context_cache[current_context] = it->second;
639    memcpy(&media_context_vtable_cache[current_context],
640           static_cast<void*>(it->second), sizeof(void*));
641  }
642
643  // TODO(ajwong): These AssertNoURLRequests() calls are unnecessary since they
644  // are already done in the URLRequestContext destructor.
645  if (main_request_context_)
646    main_request_context_->AssertNoURLRequests();
647  if (extensions_request_context_)
648    extensions_request_context_->AssertNoURLRequests();
649
650  current_context = 0;
651  for (URLRequestContextMap::iterator it = app_request_context_map_.begin();
652       it != app_request_context_map_.end(); ++it) {
653    if (current_context < kMaxCachedContexts) {
654      CHECK_EQ(app_context_cache[current_context], it->second);
655      memcpy(&tmp_vtable, static_cast<void*>(it->second), sizeof(void*));
656      CHECK_EQ(app_context_vtable_cache[current_context], tmp_vtable);
657    }
658    it->second->AssertNoURLRequests();
659    delete it->second;
660    current_context++;
661  }
662
663  current_context = 0;
664  for (URLRequestContextMap::iterator it =
665           isolated_media_request_context_map_.begin();
666       it != isolated_media_request_context_map_.end(); ++it) {
667    if (current_context < kMaxCachedContexts) {
668      CHECK_EQ(media_context_cache[current_context], it->second);
669      memcpy(&tmp_vtable, static_cast<void*>(it->second), sizeof(void*));
670      CHECK_EQ(media_context_vtable_cache[current_context], tmp_vtable);
671    }
672    it->second->AssertNoURLRequests();
673    delete it->second;
674    current_context++;
675  }
676}
677
678// static
679ProfileIOData* ProfileIOData::FromResourceContext(
680    content::ResourceContext* rc) {
681  return (static_cast<ResourceContext*>(rc))->io_data_;
682}
683
684// static
685bool ProfileIOData::IsHandledProtocol(const std::string& scheme) {
686  DCHECK_EQ(scheme, base::StringToLowerASCII(scheme));
687  static const char* const kProtocolList[] = {
688    url::kFileScheme,
689    content::kChromeDevToolsScheme,
690    dom_distiller::kDomDistillerScheme,
691#if defined(ENABLE_EXTENSIONS)
692    extensions::kExtensionScheme,
693    extensions::kExtensionResourceScheme,
694#endif
695    content::kChromeUIScheme,
696    url::kDataScheme,
697#if defined(OS_CHROMEOS)
698    chrome::kExternalFileScheme,
699#endif  // defined(OS_CHROMEOS)
700    url::kAboutScheme,
701#if !defined(DISABLE_FTP_SUPPORT)
702    url::kFtpScheme,
703#endif  // !defined(DISABLE_FTP_SUPPORT)
704    url::kBlobScheme,
705    url::kFileSystemScheme,
706    chrome::kChromeSearchScheme,
707  };
708  for (size_t i = 0; i < arraysize(kProtocolList); ++i) {
709    if (scheme == kProtocolList[i])
710      return true;
711  }
712  return net::URLRequest::IsHandledProtocol(scheme);
713}
714
715// static
716bool ProfileIOData::IsHandledURL(const GURL& url) {
717  if (!url.is_valid()) {
718    // We handle error cases.
719    return true;
720  }
721
722  return IsHandledProtocol(url.scheme());
723}
724
725// static
726void ProfileIOData::InstallProtocolHandlers(
727    net::URLRequestJobFactoryImpl* job_factory,
728    content::ProtocolHandlerMap* protocol_handlers) {
729  for (content::ProtocolHandlerMap::iterator it =
730           protocol_handlers->begin();
731       it != protocol_handlers->end();
732       ++it) {
733    bool set_protocol = job_factory->SetProtocolHandler(
734        it->first, it->second.release());
735    DCHECK(set_protocol);
736  }
737  protocol_handlers->clear();
738}
739
740content::ResourceContext* ProfileIOData::GetResourceContext() const {
741  return resource_context_.get();
742}
743
744net::URLRequestContext* ProfileIOData::GetMainRequestContext() const {
745  DCHECK(initialized_);
746  return main_request_context_.get();
747}
748
749net::URLRequestContext* ProfileIOData::GetMediaRequestContext() const {
750  DCHECK(initialized_);
751  net::URLRequestContext* context = AcquireMediaRequestContext();
752  DCHECK(context);
753  return context;
754}
755
756net::URLRequestContext* ProfileIOData::GetExtensionsRequestContext() const {
757  DCHECK(initialized_);
758  return extensions_request_context_.get();
759}
760
761net::URLRequestContext* ProfileIOData::GetIsolatedAppRequestContext(
762    net::URLRequestContext* main_context,
763    const StoragePartitionDescriptor& partition_descriptor,
764    scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
765        protocol_handler_interceptor,
766    content::ProtocolHandlerMap* protocol_handlers,
767    content::URLRequestInterceptorScopedVector request_interceptors) const {
768  DCHECK(initialized_);
769  net::URLRequestContext* context = NULL;
770  if (ContainsKey(app_request_context_map_, partition_descriptor)) {
771    context = app_request_context_map_[partition_descriptor];
772  } else {
773    context =
774        AcquireIsolatedAppRequestContext(main_context,
775                                         partition_descriptor,
776                                         protocol_handler_interceptor.Pass(),
777                                         protocol_handlers,
778                                         request_interceptors.Pass());
779    app_request_context_map_[partition_descriptor] = context;
780  }
781  DCHECK(context);
782  return context;
783}
784
785net::URLRequestContext* ProfileIOData::GetIsolatedMediaRequestContext(
786    net::URLRequestContext* app_context,
787    const StoragePartitionDescriptor& partition_descriptor) const {
788  DCHECK(initialized_);
789  net::URLRequestContext* context = NULL;
790  if (ContainsKey(isolated_media_request_context_map_, partition_descriptor)) {
791    context = isolated_media_request_context_map_[partition_descriptor];
792  } else {
793    context = AcquireIsolatedMediaRequestContext(app_context,
794                                                 partition_descriptor);
795    isolated_media_request_context_map_[partition_descriptor] = context;
796  }
797  DCHECK(context);
798  return context;
799}
800
801extensions::InfoMap* ProfileIOData::GetExtensionInfoMap() const {
802  DCHECK(initialized_) << "ExtensionSystem not initialized";
803#if defined(ENABLE_EXTENSIONS)
804  return extension_info_map_.get();
805#else
806  return NULL;
807#endif
808}
809
810CookieSettings* ProfileIOData::GetCookieSettings() const {
811  // Allow either Init() or SetCookieSettingsForTesting() to initialize.
812  DCHECK(initialized_ || cookie_settings_.get());
813  return cookie_settings_.get();
814}
815
816HostContentSettingsMap* ProfileIOData::GetHostContentSettingsMap() const {
817  DCHECK(initialized_);
818  return host_content_settings_map_.get();
819}
820
821ResourceContext::SaltCallback ProfileIOData::GetMediaDeviceIDSalt() const {
822  return base::Bind(&MediaDeviceIDSalt::GetSalt, media_device_id_salt_);
823}
824
825bool ProfileIOData::IsOffTheRecord() const {
826  return profile_type() == Profile::INCOGNITO_PROFILE
827      || profile_type() == Profile::GUEST_PROFILE;
828}
829
830void ProfileIOData::InitializeMetricsEnabledStateOnUIThread() {
831  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
832#if defined(OS_CHROMEOS)
833  // Just fetch the value from ChromeOS' settings while we're on the UI thread.
834  // TODO(stevet): For now, this value is only set on profile initialization.
835  // We will want to do something similar to the PrefMember method below in the
836  // future to more accurately capture this state.
837  chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
838                                            &enable_metrics_);
839#elif defined(OS_ANDROID)
840  // TODO(dwkang): rename or unify the pref for UMA once we have conclusion
841  // in crbugs.com/246495.
842  // Android has it's own preferences for metrics / crash uploading.
843  enable_metrics_.Init(prefs::kCrashReportingEnabled,
844                       g_browser_process->local_state());
845  enable_metrics_.MoveToThread(
846      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
847#else
848  // Prep the PrefMember and send it to the IO thread, since this value will be
849  // read from there.
850  enable_metrics_.Init(prefs::kMetricsReportingEnabled,
851                       g_browser_process->local_state());
852  enable_metrics_.MoveToThread(
853      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
854#endif  // defined(OS_CHROMEOS)
855}
856
857bool ProfileIOData::GetMetricsEnabledStateOnIOThread() const {
858  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
859#if defined(OS_CHROMEOS)
860  return enable_metrics_;
861#else
862  return enable_metrics_.GetValue();
863#endif  // defined(OS_CHROMEOS)
864}
865
866bool ProfileIOData::IsDataReductionProxyEnabled() const {
867  return data_reduction_proxy_enabled_.GetValue() ||
868         CommandLine::ForCurrentProcess()->HasSwitch(
869            data_reduction_proxy::switches::kEnableDataReductionProxy);
870}
871
872base::WeakPtr<net::HttpServerProperties>
873ProfileIOData::http_server_properties() const {
874  return http_server_properties_->GetWeakPtr();
875}
876
877void ProfileIOData::set_http_server_properties(
878    scoped_ptr<net::HttpServerProperties> http_server_properties) const {
879  http_server_properties_ = http_server_properties.Pass();
880}
881
882ProfileIOData::ResourceContext::ResourceContext(ProfileIOData* io_data)
883    : io_data_(io_data),
884      host_resolver_(NULL),
885      request_context_(NULL) {
886  DCHECK(io_data);
887}
888
889ProfileIOData::ResourceContext::~ResourceContext() {}
890
891net::HostResolver* ProfileIOData::ResourceContext::GetHostResolver()  {
892  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
893  DCHECK(io_data_->initialized_);
894  return host_resolver_;
895}
896
897net::URLRequestContext* ProfileIOData::ResourceContext::GetRequestContext()  {
898  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
899  DCHECK(io_data_->initialized_);
900  return request_context_;
901}
902
903scoped_ptr<net::ClientCertStore>
904ProfileIOData::ResourceContext::CreateClientCertStore() {
905  if (!io_data_->client_cert_store_factory_.is_null())
906    return io_data_->client_cert_store_factory_.Run();
907#if defined(OS_CHROMEOS)
908  return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreChromeOS(
909      io_data_->use_system_key_slot(),
910      io_data_->username_hash(),
911      base::Bind(&CreateCryptoModuleBlockingPasswordDelegate,
912                 chrome::kCryptoModulePasswordClientAuth)));
913#elif defined(USE_NSS)
914  return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(
915      base::Bind(&CreateCryptoModuleBlockingPasswordDelegate,
916                 chrome::kCryptoModulePasswordClientAuth)));
917#elif defined(OS_WIN)
918  return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
919#elif defined(OS_MACOSX)
920  return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
921#elif defined(USE_OPENSSL)
922  // OpenSSL does not use the ClientCertStore infrastructure. On Android client
923  // cert matching is done by the OS as part of the call to show the cert
924  // selection dialog.
925  return scoped_ptr<net::ClientCertStore>();
926#else
927#error Unknown platform.
928#endif
929}
930
931void ProfileIOData::ResourceContext::CreateKeygenHandler(
932    uint32 key_size_in_bits,
933    const std::string& challenge_string,
934    const GURL& url,
935    const base::Callback<void(scoped_ptr<net::KeygenHandler>)>& callback) {
936  DCHECK(!callback.is_null());
937#if defined(USE_NSS)
938  scoped_ptr<net::KeygenHandler> keygen_handler(
939      new net::KeygenHandler(key_size_in_bits, challenge_string, url));
940
941  scoped_ptr<ChromeNSSCryptoModuleDelegate> delegate(
942      new ChromeNSSCryptoModuleDelegate(chrome::kCryptoModulePasswordKeygen,
943                                        net::HostPortPair::FromURL(url)));
944  ChromeNSSCryptoModuleDelegate* delegate_ptr = delegate.get();
945  keygen_handler->set_crypto_module_delegate(
946      delegate.PassAs<crypto::NSSCryptoModuleDelegate>());
947
948  base::Closure bound_callback =
949      base::Bind(callback, base::Passed(&keygen_handler));
950  if (delegate_ptr->InitializeSlot(this, bound_callback)) {
951    // Initialization complete, run the callback synchronously.
952    bound_callback.Run();
953    return;
954  }
955  // Otherwise, the InitializeSlot will run the callback asynchronously.
956#else
957  callback.Run(make_scoped_ptr(
958      new net::KeygenHandler(key_size_in_bits, challenge_string, url)));
959#endif
960}
961
962ResourceContext::SaltCallback
963ProfileIOData::ResourceContext::GetMediaDeviceIDSalt() {
964  return io_data_->GetMediaDeviceIDSalt();
965}
966
967// static
968std::string ProfileIOData::GetSSLSessionCacheShard() {
969  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
970  // The SSL session cache is partitioned by setting a string. This returns a
971  // unique string to partition the SSL session cache. Each time we create a
972  // new profile, we'll get a fresh SSL session cache which is separate from
973  // the other profiles.
974  static unsigned ssl_session_cache_instance = 0;
975  return base::StringPrintf("profile/%u", ssl_session_cache_instance++);
976}
977
978void ProfileIOData::Init(
979    content::ProtocolHandlerMap* protocol_handlers,
980    content::URLRequestInterceptorScopedVector request_interceptors) const {
981  // The basic logic is implemented here. The specific initialization
982  // is done in InitializeInternal(), implemented by subtypes. Static helper
983  // functions have been provided to assist in common operations.
984  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
985  DCHECK(!initialized_);
986
987  startup_metric_utils::ScopedSlowStartupUMA
988      scoped_timer("Startup.SlowStartupProfileIODataInit");
989
990  // TODO(jhawkins): Remove once crbug.com/102004 is fixed.
991  CHECK(initialized_on_UI_thread_);
992
993  // TODO(jhawkins): Return to DCHECK once crbug.com/102004 is fixed.
994  CHECK(profile_params_.get());
995
996  IOThread* const io_thread = profile_params_->io_thread;
997  IOThread::Globals* const io_thread_globals = io_thread->globals();
998  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
999
1000  // Create the common request contexts.
1001  main_request_context_.reset(new net::URLRequestContext());
1002  extensions_request_context_.reset(new net::URLRequestContext());
1003
1004  ChromeNetworkDelegate* network_delegate =
1005      new ChromeNetworkDelegate(
1006#if defined(ENABLE_EXTENSIONS)
1007          io_thread_globals->extension_event_router_forwarder.get(),
1008#else
1009          NULL,
1010#endif
1011          &enable_referrers_);
1012  if (command_line.HasSwitch(switches::kEnableClientHints))
1013    network_delegate->SetEnableClientHints();
1014#if defined(ENABLE_EXTENSIONS)
1015  network_delegate->set_extension_info_map(
1016      profile_params_->extension_info_map.get());
1017#endif
1018#if defined(ENABLE_CONFIGURATION_POLICY)
1019  network_delegate->set_url_blacklist_manager(url_blacklist_manager_.get());
1020#endif
1021  network_delegate->set_profile(profile_params_->profile);
1022  network_delegate->set_profile_path(profile_params_->path);
1023  network_delegate->set_cookie_settings(profile_params_->cookie_settings.get());
1024  network_delegate->set_enable_do_not_track(&enable_do_not_track_);
1025  network_delegate->set_force_google_safe_search(&force_safesearch_);
1026  network_delegate->set_data_reduction_proxy_enabled_pref(
1027      &data_reduction_proxy_enabled_);
1028  network_delegate->set_prerender_tracker(profile_params_->prerender_tracker);
1029  network_delegate_.reset(network_delegate);
1030
1031  fraudulent_certificate_reporter_.reset(
1032      new chrome_browser_net::ChromeFraudulentCertificateReporter(
1033          main_request_context_.get()));
1034
1035  // NOTE: Proxy service uses the default io thread network delegate, not the
1036  // delegate just created.
1037  proxy_service_.reset(
1038      ProxyServiceFactory::CreateProxyService(
1039          io_thread->net_log(),
1040          io_thread_globals->proxy_script_fetcher_context.get(),
1041          io_thread_globals->system_network_delegate.get(),
1042          profile_params_->proxy_config_service.release(),
1043          command_line,
1044          quick_check_enabled_.GetValue()));
1045  transport_security_state_.reset(new net::TransportSecurityState());
1046  transport_security_persister_.reset(
1047      new net::TransportSecurityPersister(
1048          transport_security_state_.get(),
1049          profile_params_->path,
1050          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
1051          IsOffTheRecord()));
1052
1053  // Take ownership over these parameters.
1054  cookie_settings_ = profile_params_->cookie_settings;
1055  host_content_settings_map_ = profile_params_->host_content_settings_map;
1056#if defined(ENABLE_EXTENSIONS)
1057  extension_info_map_ = profile_params_->extension_info_map;
1058#endif
1059
1060  resource_context_->host_resolver_ = io_thread_globals->host_resolver.get();
1061  resource_context_->request_context_ = main_request_context_.get();
1062
1063  if (profile_params_->resource_prefetch_predictor_observer_) {
1064    resource_prefetch_predictor_observer_.reset(
1065        profile_params_->resource_prefetch_predictor_observer_.release());
1066  }
1067
1068#if defined(ENABLE_MANAGED_USERS)
1069  supervised_user_url_filter_ = profile_params_->supervised_user_url_filter;
1070#endif
1071
1072#if defined(OS_CHROMEOS)
1073  username_hash_ = profile_params_->username_hash;
1074  use_system_key_slot_ = profile_params_->use_system_key_slot;
1075  if (use_system_key_slot_)
1076    EnableNSSSystemKeySlotForResourceContext(resource_context_.get());
1077
1078  crypto::ScopedPK11Slot public_slot =
1079      crypto::GetPublicSlotForChromeOSUser(username_hash_);
1080  // The private slot won't be ready by this point. It shouldn't be necessary
1081  // for cert trust purposes anyway.
1082  scoped_refptr<net::CertVerifyProc> verify_proc(
1083      new chromeos::CertVerifyProcChromeOS(public_slot.Pass()));
1084  if (policy_cert_verifier_) {
1085    DCHECK_EQ(policy_cert_verifier_, cert_verifier_.get());
1086    policy_cert_verifier_->InitializeOnIOThread(verify_proc);
1087  } else {
1088    cert_verifier_.reset(new net::MultiThreadedCertVerifier(verify_proc.get()));
1089  }
1090  main_request_context_->set_cert_verifier(cert_verifier_.get());
1091#else
1092  main_request_context_->set_cert_verifier(
1093      io_thread_globals->cert_verifier.get());
1094#endif
1095
1096  InitializeInternal(
1097      profile_params_.get(), protocol_handlers, request_interceptors.Pass());
1098
1099  profile_params_.reset();
1100  initialized_ = true;
1101}
1102
1103void ProfileIOData::ApplyProfileParamsToContext(
1104    net::URLRequestContext* context) const {
1105  context->set_http_user_agent_settings(
1106      chrome_http_user_agent_settings_.get());
1107  context->set_ssl_config_service(profile_params_->ssl_config_service.get());
1108}
1109
1110scoped_ptr<net::URLRequestJobFactory> ProfileIOData::SetUpJobFactoryDefaults(
1111    scoped_ptr<net::URLRequestJobFactoryImpl> job_factory,
1112    content::URLRequestInterceptorScopedVector request_interceptors,
1113    scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
1114        protocol_handler_interceptor,
1115    net::NetworkDelegate* network_delegate,
1116    net::FtpTransactionFactory* ftp_transaction_factory) const {
1117  // NOTE(willchan): Keep these protocol handlers in sync with
1118  // ProfileIOData::IsHandledProtocol().
1119  bool set_protocol = job_factory->SetProtocolHandler(
1120      url::kFileScheme,
1121      new net::FileProtocolHandler(
1122          content::BrowserThread::GetBlockingPool()->
1123              GetTaskRunnerWithShutdownBehavior(
1124                  base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
1125  DCHECK(set_protocol);
1126
1127#if defined(ENABLE_EXTENSIONS)
1128  DCHECK(extension_info_map_.get());
1129  // Check only for incognito (and not Chrome OS guest mode GUEST_PROFILE).
1130  bool is_incognito = profile_type() == Profile::INCOGNITO_PROFILE;
1131  set_protocol = job_factory->SetProtocolHandler(
1132      extensions::kExtensionScheme,
1133      extensions::CreateExtensionProtocolHandler(is_incognito,
1134                                                 extension_info_map_.get()));
1135  DCHECK(set_protocol);
1136  set_protocol = job_factory->SetProtocolHandler(
1137      extensions::kExtensionResourceScheme,
1138      CreateExtensionResourceProtocolHandler());
1139  DCHECK(set_protocol);
1140#endif
1141  set_protocol = job_factory->SetProtocolHandler(
1142      url::kDataScheme, new net::DataProtocolHandler());
1143  DCHECK(set_protocol);
1144#if defined(OS_CHROMEOS)
1145  if (profile_params_) {
1146    set_protocol = job_factory->SetProtocolHandler(
1147        chrome::kExternalFileScheme,
1148        new chromeos::ExternalFileProtocolHandler(profile_params_->profile));
1149    DCHECK(set_protocol);
1150  }
1151#endif  // defined(OS_CHROMEOS)
1152
1153  job_factory->SetProtocolHandler(
1154      url::kAboutScheme, new chrome_browser_net::AboutProtocolHandler());
1155#if !defined(DISABLE_FTP_SUPPORT)
1156  DCHECK(ftp_transaction_factory);
1157  job_factory->SetProtocolHandler(
1158      url::kFtpScheme,
1159      new net::FtpProtocolHandler(ftp_transaction_factory));
1160#endif  // !defined(DISABLE_FTP_SUPPORT)
1161
1162#if defined(DEBUG_DEVTOOLS)
1163  request_interceptors.push_back(new DebugDevToolsInterceptor);
1164#endif
1165
1166  // Set up interceptors in the reverse order.
1167  scoped_ptr<net::URLRequestJobFactory> top_job_factory =
1168      job_factory.PassAs<net::URLRequestJobFactory>();
1169  for (content::URLRequestInterceptorScopedVector::reverse_iterator i =
1170           request_interceptors.rbegin();
1171       i != request_interceptors.rend();
1172       ++i) {
1173    top_job_factory.reset(new net::URLRequestInterceptingJobFactory(
1174        top_job_factory.Pass(), make_scoped_ptr(*i)));
1175  }
1176  request_interceptors.weak_clear();
1177
1178  if (protocol_handler_interceptor) {
1179    protocol_handler_interceptor->Chain(top_job_factory.Pass());
1180    return protocol_handler_interceptor.PassAs<net::URLRequestJobFactory>();
1181  } else {
1182    return top_job_factory.Pass();
1183  }
1184}
1185
1186void ProfileIOData::ShutdownOnUIThread(
1187    scoped_ptr<ChromeURLRequestContextGetterVector> context_getters) {
1188  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1189
1190  if (signin_names_)
1191    signin_names_->ReleaseResourcesOnUIThread();
1192
1193  google_services_user_account_id_.Destroy();
1194  google_services_username_.Destroy();
1195  google_services_username_pattern_.Destroy();
1196  reverse_autologin_enabled_.Destroy();
1197  one_click_signin_rejected_email_list_.Destroy();
1198  enable_referrers_.Destroy();
1199  enable_do_not_track_.Destroy();
1200  force_safesearch_.Destroy();
1201#if !defined(OS_CHROMEOS)
1202  enable_metrics_.Destroy();
1203#endif
1204  safe_browsing_enabled_.Destroy();
1205  data_reduction_proxy_enabled_.Destroy();
1206  printing_enabled_.Destroy();
1207  sync_disabled_.Destroy();
1208  signin_allowed_.Destroy();
1209  network_prediction_options_.Destroy();
1210  quick_check_enabled_.Destroy();
1211  if (media_device_id_salt_.get())
1212    media_device_id_salt_->ShutdownOnUIThread();
1213  session_startup_pref_.Destroy();
1214#if defined(ENABLE_CONFIGURATION_POLICY)
1215  if (url_blacklist_manager_)
1216    url_blacklist_manager_->ShutdownOnUIThread();
1217#endif
1218  if (chrome_http_user_agent_settings_)
1219    chrome_http_user_agent_settings_->CleanupOnUIThread();
1220  incognito_availibility_pref_.Destroy();
1221
1222  if (!context_getters->empty()) {
1223    if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
1224      BrowserThread::PostTask(
1225          BrowserThread::IO, FROM_HERE,
1226          base::Bind(&InvalidateContextGettersOnIO,
1227              base::Passed(&context_getters)));
1228    }
1229  }
1230
1231  bool posted = BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, this);
1232  if (!posted)
1233    delete this;
1234}
1235
1236void ProfileIOData::set_channel_id_service(
1237    net::ChannelIDService* channel_id_service) const {
1238  channel_id_service_.reset(channel_id_service);
1239}
1240
1241void ProfileIOData::DestroyResourceContext() {
1242  resource_context_.reset();
1243}
1244
1245scoped_ptr<net::HttpCache> ProfileIOData::CreateMainHttpFactory(
1246    const ProfileParams* profile_params,
1247    net::HttpCache::BackendFactory* main_backend) const {
1248  net::HttpNetworkSession::Params params;
1249  net::URLRequestContext* context = main_request_context();
1250
1251  IOThread* const io_thread = profile_params->io_thread;
1252
1253  io_thread->InitializeNetworkSessionParams(&params);
1254
1255  params.host_resolver = context->host_resolver();
1256  params.cert_verifier = context->cert_verifier();
1257  params.channel_id_service = context->channel_id_service();
1258  params.transport_security_state = context->transport_security_state();
1259  params.cert_transparency_verifier = context->cert_transparency_verifier();
1260  params.proxy_service = context->proxy_service();
1261  params.ssl_session_cache_shard = GetSSLSessionCacheShard();
1262  params.ssl_config_service = context->ssl_config_service();
1263  params.http_auth_handler_factory = context->http_auth_handler_factory();
1264  params.network_delegate = network_delegate();
1265  params.http_server_properties = context->http_server_properties();
1266  params.net_log = context->net_log();
1267
1268  network_controller_.reset(new DevToolsNetworkController());
1269
1270  net::HttpNetworkSession* session = new net::HttpNetworkSession(params);
1271  return scoped_ptr<net::HttpCache>(new net::HttpCache(
1272      new DevToolsNetworkTransactionFactory(network_controller_.get(), session),
1273      context->net_log(), main_backend));
1274}
1275
1276scoped_ptr<net::HttpCache> ProfileIOData::CreateHttpFactory(
1277    net::HttpNetworkSession* shared_session,
1278    net::HttpCache::BackendFactory* backend) const {
1279  return scoped_ptr<net::HttpCache>(new net::HttpCache(
1280      new DevToolsNetworkTransactionFactory(
1281          network_controller_.get(), shared_session),
1282      shared_session->net_log(), backend));
1283}
1284
1285void ProfileIOData::SetCookieSettingsForTesting(
1286    CookieSettings* cookie_settings) {
1287  DCHECK(!cookie_settings_.get());
1288  cookie_settings_ = cookie_settings;
1289}
1290
1291void ProfileIOData::set_signin_names_for_testing(
1292    SigninNamesOnIOThread* signin_names) {
1293  signin_names_.reset(signin_names);
1294}
1295