| Index: chrome/browser/profiles/profile_io_data.cc
|
| diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
|
| index 46129e6f7cb12110364cf6a76e5d25c6078f6636..e50779ce5fb9da6df15836c34fc522493e7cec96 100644
|
| --- a/chrome/browser/profiles/profile_io_data.cc
|
| +++ b/chrome/browser/profiles/profile_io_data.cc
|
| @@ -89,11 +89,17 @@
|
|
|
| #if defined(OS_CHROMEOS)
|
| #include "chrome/browser/chromeos/drive/drive_protocol_handler.h"
|
| +#include "chrome/browser/chromeos/login/user.h"
|
| +#include "chrome/browser/chromeos/login/user_manager.h"
|
| #include "chrome/browser/chromeos/policy/policy_cert_service.h"
|
| #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
|
| #include "chrome/browser/chromeos/policy/policy_cert_verifier.h"
|
| #include "chrome/browser/chromeos/settings/cros_settings.h"
|
| +#include "chromeos/dbus/cryptohome_client.h"
|
| +#include "chromeos/dbus/dbus_thread_manager.h"
|
| #include "chromeos/settings/cros_settings_names.h"
|
| +#include "crypto/nss_util.h"
|
| +#include "crypto/nss_util_internal.h"
|
| #endif // defined(OS_CHROMEOS)
|
|
|
| #if defined(USE_NSS)
|
| @@ -228,6 +234,112 @@ class DebugDevToolsInterceptor
|
| };
|
| #endif // defined(DEBUG_DEVTOOLS)
|
|
|
| +#if defined(OS_CHROMEOS)
|
| +// The following four functions are responsible for initializing NSS for each
|
| +// profile on ChromeOS, which has a separate NSS database and TPM slot
|
| +// per-profile.
|
| +//
|
| +// Initialization basically follows these steps:
|
| +// 1) Get some info from chromeos::UserManager about the User for this profile.
|
| +// 2) Tell nss_util to initialize the software slot for this profile.
|
| +// 3) Wait for the TPM module to be loaded by nss_util if it isn't already.
|
| +// 4) Ask CryptohomeClient which TPM slot id corresponds to this profile.
|
| +// 5) Tell nss_util to use that slot id on the TPM module.
|
| +//
|
| +// Some of these steps must happen on the UI thread, others must happen on the
|
| +// IO thread:
|
| +// UI thread IO Thread
|
| +//
|
| +// ProfileIOData::InitializeOnUIThread
|
| +// |
|
| +// chromeos::UserManager::GetUserByProfile
|
| +// \---------------------------------------v
|
| +// StartNSSInitOnIOThread
|
| +// |
|
| +// crypto::InitializeNSSForChromeOSUser
|
| +// |
|
| +// crypto::IsTPMTokenReady
|
| +// |
|
| +// StartTPMSlotInitializationOnIOThread
|
| +// v---------------------------------------/
|
| +// GetTPMInfoForUserOnUIThread
|
| +// |
|
| +// CryptohomeClient::Pkcs11GetTpmTokenInfoForUser
|
| +// |
|
| +// DidGetTPMInfoForUserOnUIThread
|
| +// \---------------------------------------v
|
| +// crypto::InitializeTPMForChromeOSUser
|
| +
|
| +void DidGetTPMInfoForUserOnUIThread(const std::string& username_hash,
|
| + chromeos::DBusMethodCallStatus call_status,
|
| + const std::string& label,
|
| + const std::string& user_pin,
|
| + int slot_id) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + if (call_status == chromeos::DBUS_METHOD_CALL_FAILURE) {
|
| + NOTREACHED() << "dbus error getting TPM info for " << username_hash;
|
| + return;
|
| + }
|
| + DVLOG(1) << "Got TPM slot for " << username_hash << ": " << slot_id;
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &crypto::InitializeTPMForChromeOSUser, username_hash, slot_id));
|
| +}
|
| +
|
| +void GetTPMInfoForUserOnUIThread(const std::string& username,
|
| + const std::string& username_hash) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + DVLOG(1) << "Getting TPM info from cryptohome for "
|
| + << " " << username << " " << username_hash;
|
| + chromeos::DBusThreadManager::Get()
|
| + ->GetCryptohomeClient()
|
| + ->Pkcs11GetTpmTokenInfoForUser(
|
| + username,
|
| + base::Bind(&DidGetTPMInfoForUserOnUIThread, username_hash));
|
| +}
|
| +
|
| +void StartTPMSlotInitializationOnIOThread(const std::string& username,
|
| + const std::string& username_hash) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI,
|
| + FROM_HERE,
|
| + base::Bind(&GetTPMInfoForUserOnUIThread, username, username_hash));
|
| +}
|
| +
|
| +void StartNSSInitOnIOThread(const std::string& username,
|
| + const std::string& username_hash,
|
| + const base::FilePath& path,
|
| + bool is_primary_user) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DVLOG(1) << "Starting NSS init for " << username
|
| + << " hash:" << username_hash
|
| + << " is_primary_user:" << is_primary_user;
|
| +
|
| + if (!crypto::InitializeNSSForChromeOSUser(
|
| + username, username_hash, is_primary_user, path)) {
|
| + // If the user already exists in nss_util's map, it is already initialized
|
| + // or in the process of being initialized. In either case, there's no need
|
| + // to do anything.
|
| + return;
|
| + }
|
| +
|
| + if (crypto::IsTPMTokenEnabledForNSS()) {
|
| + if (crypto::IsTPMTokenReady(base::Bind(
|
| + &StartTPMSlotInitializationOnIOThread, username, username_hash))) {
|
| + StartTPMSlotInitializationOnIOThread(username, username_hash);
|
| + } else {
|
| + DVLOG(1) << "Waiting for tpm ready ...";
|
| + }
|
| + } else {
|
| + crypto::InitializePrivateSoftwareSlotForChromeOSUser(username_hash);
|
| + }
|
| +}
|
| +#endif // defined(OS_CHROMEOS)
|
| +
|
| } // namespace
|
|
|
| void ProfileIOData::InitializeOnUIThread(Profile* profile) {
|
| @@ -278,6 +390,25 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) {
|
| params->managed_mode_url_filter =
|
| managed_user_service->GetURLFilterForIOThread();
|
| #endif
|
| +#if defined(OS_CHROMEOS)
|
| + chromeos::UserManager* user_manager = chromeos::UserManager::Get();
|
| + if (user_manager) {
|
| + chromeos::User* user = user_manager->GetUserByProfile(profile);
|
| + if (user) {
|
| + params->username_hash = user->username_hash();
|
| + bool is_primary_user = (user_manager->GetPrimaryUser() == user);
|
| + BrowserThread::PostTask(BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&StartNSSInitOnIOThread,
|
| + user->email(),
|
| + user->username_hash(),
|
| + profile->GetPath(),
|
| + is_primary_user));
|
| + }
|
| + }
|
| + if (params->username_hash.empty())
|
| + LOG(WARNING) << "no username_hash";
|
| +#endif
|
|
|
| params->profile = profile;
|
| profile_params_.reset(params.release());
|
| @@ -833,6 +964,7 @@ void ProfileIOData::Init(content::ProtocolHandlerMap* protocol_handlers) const {
|
| main_request_context_->set_cert_verifier(
|
| io_thread_globals->cert_verifier.get());
|
| }
|
| + username_hash_ = profile_params_->username_hash;
|
| #else
|
| main_request_context_->set_cert_verifier(
|
| io_thread_globals->cert_verifier.get());
|
|
|