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