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