Chromium Code Reviews| Index: chrome/browser/chromeos/cros/cert_library.cc |
| diff --git a/chrome/browser/chromeos/cros/cert_library.cc b/chrome/browser/chromeos/cros/cert_library.cc |
| index c096157758eb697ce42ee9ce375f3e941379c23f..7085bfd49928ece66ec3c7d8f8436aca4f9c80f4 100644 |
| --- a/chrome/browser/chromeos/cros/cert_library.cc |
| +++ b/chrome/browser/chromeos/cros/cert_library.cc |
| @@ -29,8 +29,6 @@ |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/l10n/l10n_util_collator.h" |
| -using content::BrowserThread; |
| - |
| namespace chromeos { |
| namespace { |
| @@ -38,9 +36,6 @@ namespace { |
| // Root CA certificates that are built into Chrome use this token name. |
| const char kRootCertificateTokenName[] = "Builtin Object Token"; |
| -// Delay between certificate requests while waiting for TPM/PKCS#11 init. |
| -const int kRequestDelayMs = 500; |
| - |
| string16 GetDisplayString(net::X509Certificate* cert, bool hardware_backed) { |
| std::string org; |
| if (!cert->subject().organization_names.empty()) |
| @@ -69,477 +64,115 @@ string16 GetDisplayString(net::X509Certificate* cert, bool hardware_backed) { |
| } // namespace |
| -////////////////////////////////////////////////////////////////////////////// |
| - |
| -// base::Unretained(this) in the class is safe. By the time this object is |
| -// deleted as part of CrosLibrary, the DB thread and the UI message loop |
| -// are already terminated. |
| -class CertLibraryImpl |
| - : public CertLibrary, |
| - public net::CertDatabase::Observer { |
| +class CertNameComparator { |
| public: |
| - typedef ObserverListThreadSafe<CertLibrary::Observer> CertLibraryObserverList; |
| - |
| - CertLibraryImpl() : |
| - observer_list_(new CertLibraryObserverList), |
| - tpm_token_ready_(false), |
| - user_logged_in_(false), |
| - certificates_requested_(false), |
| - certificates_loaded_(false), |
| - key_store_loaded_(false), |
| - ALLOW_THIS_IN_INITIALIZER_LIST(certs_(this)), |
| - ALLOW_THIS_IN_INITIALIZER_LIST(user_certs_(this)), |
| - ALLOW_THIS_IN_INITIALIZER_LIST(server_certs_(this)), |
| - ALLOW_THIS_IN_INITIALIZER_LIST(server_ca_certs_(this)), |
| - ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - net::CertDatabase::GetInstance()->AddObserver(this); |
| - } |
| - |
| - virtual ~CertLibraryImpl() { |
| - DCHECK(request_task_.is_null()); |
| - net::CertDatabase::GetInstance()->RemoveObserver(this); |
| - } |
| - |
| - // CertLibrary implementation. |
| - virtual void AddObserver(CertLibrary::Observer* observer) OVERRIDE { |
| - observer_list_->AddObserver(observer); |
| - } |
| - |
| - virtual void RemoveObserver(CertLibrary::Observer* observer) OVERRIDE { |
| - observer_list_->RemoveObserver(observer); |
| - } |
| - |
| - virtual void LoadKeyStore() OVERRIDE { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - if (key_store_loaded_) |
| - return; |
| - |
| - // Ensure we've opened the real user's key/certificate database. |
| - crypto::OpenPersistentNSSDB(); |
| - |
| - if (base::chromeos::IsRunningOnChromeOS() || |
| - CommandLine::ForCurrentProcess()->HasSwitch( |
| - switches::kLoadOpencryptoki)) { |
| - crypto::EnableTPMTokenForNSS(); |
| - // Note: this calls crypto::EnsureTPMTokenReady() |
| - RequestCertificates(); |
| - } |
| - key_store_loaded_ = true; |
| - } |
| - |
| - virtual bool CertificatesLoading() const OVERRIDE { |
| - return certificates_requested_ && !certificates_loaded_; |
| - } |
| - |
| - virtual bool CertificatesLoaded() const OVERRIDE { |
| - return certificates_loaded_; |
| - } |
| - |
| - virtual bool IsHardwareBacked() const OVERRIDE { |
| - return !tpm_token_name_.empty(); |
| - } |
| - |
| - virtual const CertList& GetCertificates() const OVERRIDE { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - return certs_; |
| - } |
| - |
| - virtual const CertList& GetUserCertificates() const OVERRIDE { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - return user_certs_; |
| - } |
| - |
| - virtual const CertList& GetServerCertificates() const OVERRIDE { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - return server_certs_; |
| - } |
| - |
| - virtual const CertList& GetCACertificates() const OVERRIDE { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - return server_ca_certs_; |
| - } |
| - |
| - // net::CertDatabase::Observer implementation. Observer added on UI thread. |
| - virtual void OnCertTrustChanged(const net::X509Certificate* cert) OVERRIDE { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - } |
| - |
| - virtual void OnCertAdded(const net::X509Certificate* cert) OVERRIDE { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - // Only load certificates if we have completed an initial request. |
| - if (certificates_loaded_) { |
| - BrowserThread::PostTask( |
| - BrowserThread::DB, FROM_HERE, |
| - base::Bind(&CertLibraryImpl::LoadCertificates, |
| - base::Unretained(this))); |
| - } |
| + explicit CertNameComparator(icu::Collator* collator) |
| + : collator_(collator) { |
| } |
| - virtual void OnCertRemoved(const net::X509Certificate* cert) OVERRIDE { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - // Only load certificates if we have completed an initial request. |
| - if (certificates_loaded_) { |
| - BrowserThread::PostTask( |
| - BrowserThread::DB, FROM_HERE, |
| - base::Bind(&CertLibraryImpl::LoadCertificates, |
| - base::Unretained(this))); |
| - } |
| - } |
| - |
| - virtual const std::string& GetTpmTokenName() const OVERRIDE { |
| - return tpm_token_name_; |
| + bool operator()(const scoped_refptr<net::X509Certificate>& lhs, |
| + const scoped_refptr<net::X509Certificate>& rhs) const { |
| + string16 lhs_name = GetDisplayString(lhs.get(), false); |
| + string16 rhs_name = GetDisplayString(rhs.get(), false); |
| + if (collator_ == NULL) |
| + return lhs_name < rhs_name; |
| + return base::i18n::CompareString16WithCollator( |
| + collator_, lhs_name, rhs_name) == UCOL_LESS; |
| } |
| private: |
| - void LoadCertificates() { |
| - VLOG(1) << " Loading Certificates."; |
| - // Certificate fetch occurs on the DB thread. |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| - net::CertificateList* cert_list = new net::CertificateList(); |
| - net::NSSCertDatabase::GetInstance()->ListCerts(cert_list); |
| - // Pass the list to the UI thread to safely update the local lists. |
| - BrowserThread::PostTask( |
| - BrowserThread::UI, FROM_HERE, |
| - base::Bind(&CertLibraryImpl::UpdateCertificates, |
| - base::Unretained(this), cert_list)); |
| - } |
| - |
| - // Comparison functor for locale-sensitive sorting of certificates by name. |
| - class CertNameComparator { |
| - public: |
| - explicit CertNameComparator(icu::Collator* collator) |
| - : collator_(collator) { } |
| - |
| - bool operator()(const scoped_refptr<net::X509Certificate>& lhs, |
| - const scoped_refptr<net::X509Certificate>& rhs) const { |
| - string16 lhs_name = GetDisplayString(lhs.get(), false); |
| - string16 rhs_name = GetDisplayString(rhs.get(), false); |
| - if (collator_ == NULL) |
| - return lhs_name < rhs_name; |
| - return base::i18n::CompareString16WithCollator( |
| - collator_, lhs_name, rhs_name) == UCOL_LESS; |
| - } |
| - private: |
| - icu::Collator* collator_; |
| - }; |
| - |
| - void NotifyCertificatesLoaded(bool initial_load) { |
| - observer_list_->Notify( |
| - &CertLibrary::Observer::OnCertificatesLoaded, initial_load); |
| - } |
| - |
| - // |cert_list| is allocated in LoadCertificates() and must be deleted here. |
| - void UpdateCertificates(net::CertificateList* cert_list) { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - DCHECK(cert_list); |
| - |
| - // Clear any existing certificates. |
| - certs_.Clear(); |
| - server_ca_certs_.Clear(); |
| - user_certs_.Clear(); |
| - server_certs_.Clear(); |
| - |
| - // Add certificates to the appropriate list. |
| - for (net::CertificateList::const_iterator iter = cert_list->begin(); |
| - iter != cert_list->end(); ++iter) { |
| - certs_.Append(iter->get()); |
| - net::X509Certificate::OSCertHandle cert_handle = |
| - iter->get()->os_cert_handle(); |
| - net::CertType type = x509_certificate_model::GetType(cert_handle); |
| - switch (type) { |
| - case net::USER_CERT: |
| - user_certs_.Append(iter->get()); |
| - break; |
| - case net::SERVER_CERT: |
| - server_certs_.Append(iter->get()); |
| - break; |
| - case net::CA_CERT: { |
| - // Exclude root CA certificates that are built into Chrome. |
| - std::string token_name = |
| - x509_certificate_model::GetTokenName(cert_handle); |
| - if (token_name != kRootCertificateTokenName) |
| - server_ca_certs_.Append(iter->get()); |
| - break; |
| - } |
| - default: |
| - break; |
| - } |
| - } |
| - |
| - // Perform locale-sensitive sorting by certificate name. |
| - scoped_ptr<icu::Collator> collator; |
| - UErrorCode error = U_ZERO_ERROR; |
| - collator.reset( |
| - icu::Collator::createInstance( |
| - icu::Locale(g_browser_process->GetApplicationLocale().c_str()), |
| - error)); |
| - if (U_FAILURE(error)) |
| - collator.reset(NULL); |
| - CertNameComparator cert_name_comparator(collator.get()); |
| - std::sort(user_certs_.list().begin(), user_certs_.list().end(), |
| - cert_name_comparator); |
| - std::sort(server_certs_.list().begin(), server_certs_.list().end(), |
| - cert_name_comparator); |
| - std::sort(server_ca_certs_.list().begin(), server_ca_certs_.list().end(), |
| - cert_name_comparator); |
| - |
| - // cert_list is allocated in LoadCertificates(), then released here. |
| - delete cert_list; |
| - |
| - // Set loaded state and notify observers. |
| - if (!certificates_loaded_) { |
| - certificates_loaded_ = true; |
| - NotifyCertificatesLoaded(true); |
| - } else { |
| - NotifyCertificatesLoaded(false); |
| - } |
| - } |
| - |
| - // Call this to start the certificate list initialization process. |
| - // Must be called from the UI thread. |
| - void RequestCertificates() { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - |
| - certificates_requested_ = true; |
| - |
| - if (!LoginState::Get()->IsUserLoggedIn()) { |
| - // If we are not logged in, we cannot load any certificates. |
| - // Set 'loaded' to true for the UI, since we are not waiting on loading. |
| - LOG(WARNING) << "Requesting certificates before login."; |
| - certificates_loaded_ = true; |
| - return; |
| - } |
| - |
| - if (!user_logged_in_) { |
| - user_logged_in_ = true; |
| - certificates_loaded_ = false; |
| - } |
| - |
| - VLOG(1) << "Requesting Certificates."; |
| - DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled( |
| - base::Bind(&CertLibraryImpl::OnTpmIsEnabled, |
| - weak_ptr_factory_.GetWeakPtr())); |
| - } |
| - |
| - // This method is used to implement RequestCertificates. |
| - void OnTpmIsEnabled(DBusMethodCallStatus call_status, bool tpm_is_enabled) { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - if (call_status != DBUS_METHOD_CALL_SUCCESS || !tpm_is_enabled) { |
| - // TPM is not enabled, so proceed with empty tpm token name. |
| - VLOG(1) << "TPM not available."; |
| - BrowserThread::PostTask( |
| - BrowserThread::DB, FROM_HERE, |
| - base::Bind(&CertLibraryImpl::LoadCertificates, |
| - base::Unretained(this))); |
| - } else if (tpm_token_ready_) { |
| - InitializeTPMToken(); |
| - } else { |
| - DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11IsTpmTokenReady( |
| - base::Bind(&CertLibraryImpl::OnPkcs11IsTpmTokenReady, |
| - weak_ptr_factory_.GetWeakPtr())); |
| - } |
| - } |
| - |
| - // This method is used to implement RequestCertificates. |
| - void OnPkcs11IsTpmTokenReady(DBusMethodCallStatus call_status, |
| - bool is_tpm_token_ready) { |
| - if (call_status != DBUS_METHOD_CALL_SUCCESS || !is_tpm_token_ready) { |
| - MaybeRetryRequestCertificates(); |
| - return; |
| - } |
| - |
| - // Retrieve token_name_ and user_pin_ here since they will never change |
| - // and CryptohomeClient calls are not thread safe. |
| - DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11GetTpmTokenInfo( |
| - base::Bind(&CertLibraryImpl::OnPkcs11GetTpmTokenInfo, |
| - weak_ptr_factory_.GetWeakPtr())); |
| - } |
| - |
| - // This method is used to implement RequestCertificates. |
| - void OnPkcs11GetTpmTokenInfo(DBusMethodCallStatus call_status, |
| - const std::string& token_name, |
| - const std::string& user_pin) { |
| - if (call_status != DBUS_METHOD_CALL_SUCCESS) { |
| - MaybeRetryRequestCertificates(); |
| - return; |
| - } |
| - tpm_token_name_ = token_name; |
| - tpm_user_pin_ = user_pin; |
| - tpm_token_ready_ = true; |
| - |
| - InitializeTPMToken(); |
| - } |
| - |
| - // This method is used to implement RequestCertificates. |
| - void InitializeTPMToken() { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - if (!crypto::InitializeTPMToken(tpm_token_name_, tpm_user_pin_)) { |
| - MaybeRetryRequestCertificates(); |
| - return; |
| - } |
| - |
| - // tpm_token_name_ is set, load the certificates on the DB thread. |
| - BrowserThread::PostTask( |
| - BrowserThread::DB, FROM_HERE, |
| - base::Bind(&CertLibraryImpl::LoadCertificates, base::Unretained(this))); |
| - } |
| - |
| - void MaybeRetryRequestCertificates() { |
| - if (!request_task_.is_null()) |
| - return; |
| - // Cryptohome does not notify us when the token is ready, so call |
| - // this again after a delay. |
| - request_task_ = base::Bind(&CertLibraryImpl::RequestCertificatesTask, |
| - weak_ptr_factory_.GetWeakPtr()); |
| - BrowserThread::PostDelayedTask( |
| - BrowserThread::UI, FROM_HERE, request_task_, |
| - base::TimeDelta::FromMilliseconds(kRequestDelayMs)); |
| - } |
| - |
| - void RequestCertificatesTask() { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - // Reset the task to the initial state so is_null() returns true. |
| - request_task_ = base::Closure(); |
| - RequestCertificates(); |
| - } |
| - |
| - // Observers. |
| - const scoped_refptr<CertLibraryObserverList> observer_list_; |
| - |
| - // Active request task for re-requests while waiting for TPM init. |
| - base::Closure request_task_; |
| - |
| - bool tpm_token_ready_; |
| - |
| - // Cached TPM token name. |
| - std::string tpm_token_name_; |
| - |
| - // Cached TPM user pin. |
| - std::string tpm_user_pin_; |
| - |
| - // Local state. |
| - bool user_logged_in_; |
| - bool certificates_requested_; |
| - bool certificates_loaded_; |
| - // The key store for the current user has been loaded. This flag is needed to |
| - // ensure that the key store will not be loaded twice in the policy recovery |
| - // "safe-mode". |
| - bool key_store_loaded_; |
| - |
| - // Certificates. |
| - CertList certs_; |
| - CertList user_certs_; |
| - CertList server_certs_; |
| - CertList server_ca_certs_; |
| - |
| - base::WeakPtrFactory<CertLibraryImpl> weak_ptr_factory_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(CertLibraryImpl); |
| + icu::Collator* collator_; |
| }; |
| -////////////////////////////////////////////////////////////////////////////// |
| +static CertLibrary* g_cert_library = NULL; |
| -class CertLibraryImplStub : public CertLibrary { |
| - public: |
| - CertLibraryImplStub() |
| - : token_name_("StubToken"), |
| - ALLOW_THIS_IN_INITIALIZER_LIST(cert_list_(this)) { |
| - } |
| - virtual ~CertLibraryImplStub() {} |
| +// static |
| +void CertLibrary::Initialize() { |
| + CHECK(!g_cert_library); |
| + g_cert_library = new CertLibrary(); |
| +} |
| - virtual void AddObserver(Observer* observer) {} |
| - virtual void RemoveObserver(Observer* observer) {} |
| - virtual void LoadKeyStore() {} |
| - virtual bool CertificatesLoading() const { |
| - return false; |
| - } |
| - virtual bool CertificatesLoaded() const { |
| - return true; |
| - } |
| - virtual bool IsHardwareBacked() const { |
| - return false; |
| - } |
| - virtual const std::string& GetTpmTokenName() const { |
| - return token_name_; |
| - } |
| - virtual const CertList& GetCertificates() const { |
| - return cert_list_; |
| - } |
| - virtual const CertList& GetUserCertificates() const { |
| - return cert_list_; |
| - } |
| - virtual const CertList& GetServerCertificates() const { |
| - return cert_list_; |
| - } |
| - virtual const CertList& GetCACertificates() const { |
| - return cert_list_; |
| - } |
| +// static |
| +void CertLibrary::Shutdown() { |
| + CHECK(g_cert_library); |
| + delete g_cert_library; |
| + g_cert_library = NULL; |
| +} |
| - private: |
| - std::string token_name_; |
| - CertList cert_list_; |
| +// static |
| +CertLibrary* CertLibrary::Get() { |
| + CHECK(g_cert_library) << "CertLibrary::Get() called before Initialize()"; |
| + return g_cert_library; |
| +} |
| - DISALLOW_COPY_AND_ASSIGN(CertLibraryImplStub); |
| -}; |
| +// static |
| +bool CertLibrary::IsInitialized() { |
| + return g_cert_library; |
| +} |
| -////////////////////////////////////////////////////////////////////////////// |
| +CertLibrary::CertLibrary() { |
| + CertLoader::Get()->AddObserver(this); |
| +} |
| CertLibrary::~CertLibrary() { |
| + CertLoader::Get()->RemoveObserver(this); |
| } |
| -// static |
| -CertLibrary* CertLibrary::GetImpl(bool stub) { |
| - // TODO(stevenjb): Disassociate CertLibrary from CrosLibrary entirely. |
| - // crbug.com/133752 |
| - if (stub) |
| - return new CertLibraryImplStub(); |
| - return new CertLibraryImpl(); |
| +void CertLibrary::AddObserver(CertLibrary::Observer* observer) { |
| + observer_list_.AddObserver(observer); |
| } |
| -////////////////////////////////////////////////////////////////////////////// |
| +void CertLibrary::RemoveObserver(CertLibrary::Observer* observer) { |
| + observer_list_.RemoveObserver(observer); |
| +} |
| -CertLibrary::CertList::CertList(CertLibrary* library) |
| - : cert_library_(library) { |
| +bool CertLibrary::CertificatesLoading() const { |
| + return CertLoader::Get()->CertificatesLoading(); |
| } |
| -CertLibrary::CertList::~CertList() {} |
| +bool CertLibrary::CertificatesLoaded() const { |
| + return CertLoader::Get()->certificates_loaded(); |
| +} |
| -net::X509Certificate* CertLibrary::CertList::GetCertificateAt(int index) const { |
| - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - DCHECK_GE(index, 0); |
| - DCHECK_LT(index, static_cast<int>(list_.size())); |
| - return list_[index].get(); |
| +bool CertLibrary::IsHardwareBacked() const { |
| + return CertLoader::Get()->IsHardwareBacked(); |
| } |
| -string16 CertLibrary::CertList::GetDisplayStringAt(int index) const { |
| - net::X509Certificate* cert = GetCertificateAt(index); |
| +int CertLibrary::NumCertificates(CertType type) const { |
| + const net::CertificateList& cert_list = GetCertificateListForType(type); |
| + return static_cast<int>(cert_list.size()); |
| +} |
| + |
| +string16 CertLibrary::GetCertDisplayStringAt(CertType type, int index) const { |
| + net::X509Certificate* cert = GetCertificateAt(type, index); |
| bool hardware_backed = |
| - !cert_library_->GetTpmTokenName().empty() && IsHardwareBackedAt(index); |
| + CertLoader::Get()->IsHardwareBacked() && |
| + IsCertHardwareBackedAt(type, index); |
| return GetDisplayString(cert, hardware_backed); |
| } |
| -std::string CertLibrary::CertList::GetNicknameAt(int index) const { |
| - net::X509Certificate* cert = GetCertificateAt(index); |
| +std::string CertLibrary::GetCertNicknameAt(CertType type, int index) const { |
| + net::X509Certificate* cert = GetCertificateAt(type, index); |
| return x509_certificate_model::GetNickname(cert->os_cert_handle()); |
| } |
| -std::string CertLibrary::CertList::GetPkcs11IdAt(int index) const { |
| - net::X509Certificate* cert = GetCertificateAt(index); |
| +std::string CertLibrary::GetCertPkcs11IdAt(CertType type, int index) const { |
| + net::X509Certificate* cert = GetCertificateAt(type, index); |
| return x509_certificate_model::GetPkcs11Id(cert->os_cert_handle()); |
| } |
| -bool CertLibrary::CertList::IsHardwareBackedAt(int index) const { |
| - net::X509Certificate* cert = GetCertificateAt(index); |
| +bool CertLibrary::IsCertHardwareBackedAt(CertType type, int index) const { |
| + net::X509Certificate* cert = GetCertificateAt(type, index); |
| std::string cert_token_name = |
| x509_certificate_model::GetTokenName(cert->os_cert_handle()); |
| - return cert_token_name == cert_library_->GetTpmTokenName(); |
| + return cert_token_name == CertLoader::Get()->tpm_token_name(); |
| } |
| -int CertLibrary::CertList::FindCertByNickname( |
| - const std::string& nickname) const { |
| - for (int index = 0; index < Size(); ++index) { |
| - net::X509Certificate* cert = GetCertificateAt(index); |
| +int CertLibrary::GetCertIndexByNickname(CertType type, |
| + const std::string& nickname) const { |
| + int num_certs = NumCertificates(type); |
| + for (int index = 0; index < num_certs; ++index) { |
| + net::X509Certificate* cert = GetCertificateAt(type, index); |
| net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle(); |
| std::string nick = x509_certificate_model::GetNickname(cert_handle); |
| if (nick == nickname) |
| @@ -548,10 +181,11 @@ int CertLibrary::CertList::FindCertByNickname( |
| return -1; // Not found. |
| } |
| -int CertLibrary::CertList::FindCertByPkcs11Id( |
| - const std::string& pkcs11_id) const { |
| - for (int index = 0; index < Size(); ++index) { |
| - net::X509Certificate* cert = GetCertificateAt(index); |
| +int CertLibrary::GetCertIndexByPkcs11Id(CertType type, |
| + const std::string& pkcs11_id) const { |
| + int num_certs = NumCertificates(type); |
| + for (int index = 0; index < num_certs; ++index) { |
| + net::X509Certificate* cert = GetCertificateAt(type, index); |
| net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle(); |
| std::string id = x509_certificate_model::GetPkcs11Id(cert_handle); |
| if (id == pkcs11_id) |
| @@ -560,4 +194,82 @@ int CertLibrary::CertList::FindCertByPkcs11Id( |
| return -1; // Not found. |
| } |
| +void CertLibrary::OnCertificatesLoaded(const net::CertificateList& cert_list, |
| + bool initial_load) { |
| + VLOG(1) << "CertLibrary::OnCertificatesLoaded: " << cert_list.size(); |
| + certs_.clear(); |
| + user_certs_.clear(); |
| + server_certs_.clear(); |
| + server_ca_certs_.clear(); |
| + |
| + // Add certificates to the appropriate list. |
| + for (net::CertificateList::const_iterator iter = cert_list.begin(); |
| + iter != cert_list.end(); ++iter) { |
| + certs_.push_back(iter->get()); |
| + net::X509Certificate::OSCertHandle cert_handle = |
| + iter->get()->os_cert_handle(); |
| + net::CertType type = x509_certificate_model::GetType(cert_handle); |
| + switch (type) { |
| + case net::USER_CERT: |
| + user_certs_.push_back(iter->get()); |
| + break; |
| + case net::SERVER_CERT: |
| + server_certs_.push_back(iter->get()); |
| + break; |
| + case net::CA_CERT: { |
| + // Exclude root CA certificates that are built into Chrome. |
| + std::string token_name = |
| + x509_certificate_model::GetTokenName(cert_handle); |
| + if (token_name != kRootCertificateTokenName) |
| + server_ca_certs_.push_back(iter->get()); |
| + break; |
| + } |
| + default: |
| + break; |
| + } |
| + } |
| + |
| + // Perform locale-sensitive sorting by certificate name. |
| + scoped_ptr<icu::Collator> collator; |
| + UErrorCode error = U_ZERO_ERROR; |
| + collator.reset(icu::Collator::createInstance( |
| + icu::Locale(g_browser_process->GetApplicationLocale().c_str()), error)); |
|
Ryan Sleevi
2013/05/01 18:16:18
FYI, http://crbug.com/225830
stevenjb
2013/05/01 20:47:59
Yep. That's one of several issues preventing this
|
| + if (U_FAILURE(error)) |
| + collator.reset(NULL); |
| + CertNameComparator cert_name_comparator(collator.get()); |
| + std::sort(certs_.begin(), certs_.end(), cert_name_comparator); |
| + std::sort(user_certs_.begin(), user_certs_.end(), cert_name_comparator); |
| + std::sort(server_certs_.begin(), server_certs_.end(), cert_name_comparator); |
| + std::sort(server_ca_certs_.begin(), server_ca_certs_.end(), |
| + cert_name_comparator); |
| + |
| + VLOG(1) << "certs_: " << certs_.size(); |
| + VLOG(1) << "user_certs_: " << user_certs_.size(); |
| + VLOG(1) << "server_certs_: " << server_certs_.size(); |
| + VLOG(1) << "server_ca_certs_: " << server_ca_certs_.size(); |
| + |
| + FOR_EACH_OBSERVER(CertLibrary::Observer, observer_list_, |
| + OnCertificatesLoaded(initial_load)); |
| +} |
| + |
| +net::X509Certificate* CertLibrary::GetCertificateAt(CertType type, |
| + int index) const { |
| + const net::CertificateList& cert_list = GetCertificateListForType(type); |
| + DCHECK_GE(index, 0); |
| + DCHECK_LT(index, static_cast<int>(cert_list.size())); |
| + return cert_list[index].get(); |
| +} |
| + |
| +const net::CertificateList& CertLibrary::GetCertificateListForType( |
| + CertType type) const { |
| + if (type == CERT_TYPE_USER) |
| + return user_certs_; |
| + if (type == CERT_TYPE_SERVER) |
| + return server_certs_; |
| + if (type == CERT_TYPE_SERVER_CA) |
| + return server_ca_certs_; |
| + DCHECK(type == CERT_TYPE_DEFAULT); |
| + return certs_; |
| +} |
| + |
| } // chromeos |