[M94 Dev] Remove *.pyc files from git repositories
[platform/framework/web/chromium-efl.git] / chrome / browser / certificate_manager_model.cc
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/certificate_manager_model.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/i18n/time_formatting.h"
12 #include "base/logging.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/scoped_observation.h"
15 #include "base/sequence_checker.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "build/build_config.h"
18 #include "build/chromeos_buildflags.h"
19 #include "chrome/browser/net/nss_context.h"
20 #include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
21 #include "chrome/common/net/x509_certificate_model_nss.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "content/public/browser/browser_context.h"
24 #include "content/public/browser/browser_task_traits.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/resource_context.h"
27 #include "crypto/nss_util.h"
28 #include "net/base/net_errors.h"
29 #include "net/cert/cert_database.h"
30 #include "net/cert/x509_certificate.h"
31 #include "net/cert/x509_util_nss.h"
32 #include "ui/base/l10n/l10n_util.h"
33
34 #if BUILDFLAG(IS_CHROMEOS_ASH)
35 #include "chrome/browser/ash/certificate_provider/certificate_provider.h"
36 #include "chrome/browser/ash/certificate_provider/certificate_provider_service.h"
37 #include "chrome/browser/ash/certificate_provider/certificate_provider_service_factory.h"
38 #include "chrome/browser/ash/policy/networking/user_network_configuration_updater.h"
39 #include "chrome/browser/ash/policy/networking/user_network_configuration_updater_factory.h"
40 #include "chromeos/network/onc/certificate_scope.h"
41 #include "chromeos/network/policy_certificate_provider.h"
42 #endif
43
44 using content::BrowserThread;
45
46 // CertificateManagerModel is created on the UI thread. It needs a
47 // NSSCertDatabase handle (and on ChromeOS it needs to get the TPM status) which
48 // needs to be done on the IO thread.
49 //
50 // The initialization flow is roughly:
51 //
52 //               UI thread                              IO Thread
53 //
54 //   CertificateManagerModel::Create
55 //                  \--------------------------------------v
56 //                                CertificateManagerModel::GetCertDBOnIOThread
57 //                                                         |
58 //                                               NssCertDatabaseGetter
59 //                                                         |
60 //                               CertificateManagerModel::DidGetCertDBOnIOThread
61 //                                                         |
62 //                                       crypto::IsTPMTokenEnabledForNSS
63 //                  v--------------------------------------/
64 // CertificateManagerModel::DidGetCertDBOnUIThread
65 //                  |
66 //     new CertificateManagerModel
67 //                  |
68 //               callback
69
70 namespace {
71
72 std::string GetCertificateOrg(CERTCertificate* cert) {
73   std::string org =
74       x509_certificate_model::GetSubjectOrgName(cert, std::string());
75   if (org.empty())
76     org = x509_certificate_model::GetSubjectDisplayName(cert);
77
78   return org;
79 }
80
81 #if BUILDFLAG(IS_CHROMEOS_ASH)
82 // Log message for an operation that can not be performed on a certificate of a
83 // given source.
84 constexpr char kOperationNotPermitted[] =
85     "Operation not permitted on a certificate. Source: ";
86 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
87
88 }  // namespace
89
90 // A source of certificates that should be displayed on the certificate manager
91 // UI. Currently, a CertsSource yields CertInfo objects. Each CertInfo contains
92 // a NSS ScopedCERTCertificate.
93 class CertificateManagerModel::CertsSource {
94  public:
95   // |certs_source_updated_callback| will be invoked when the list of
96   // certificates provided by this CertsSource changes.
97   explicit CertsSource(base::RepeatingClosure certs_source_updated_callback)
98       : certs_source_updated_callback_(certs_source_updated_callback) {}
99   virtual ~CertsSource() = default;
100
101   // Returns the CertInfos provided by this CertsSource.
102   const std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>>&
103   cert_infos() const {
104     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
105     return cert_infos_;
106   }
107
108   // Returns true if |cert| is in this CertsSource's certificate list.
109   bool HasCert(CERTCertificate* cert) const {
110     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
111     for (const auto& cert_info : cert_infos_) {
112       if (cert_info->cert() == cert)
113         return true;
114     }
115     return false;
116   }
117
118   // Triggers a refresh of this CertsSource. When done, the
119   // |certs_source_updated_callback| passed to the constructor will be invoked.
120   virtual void Refresh() = 0;
121
122   // If any CertsSource's |IsHoldBackUpdates| is returning true, the
123   // CertificateManagerModel will not notify its Observer about updates.
124   bool IsHoldBackUpdates() const { return hold_back_updates_; }
125
126   // Set trust values for certificate.
127   // |trust_bits| should be a bit field of TRUST* values from NSSCertDatabase.
128   // Returns true on success or false on failure.
129   virtual bool SetCertTrust(CERTCertificate* cert,
130                             net::CertType type,
131                             net::NSSCertDatabase::TrustBits trust_bits) = 0;
132
133   // Delete the cert. Returns true on success. |cert| is still valid when this
134   // function returns.
135   virtual bool Delete(CERTCertificate* cert) = 0;
136
137  protected:
138   // To be called by subclasses to set the CertInfo list provided by this
139   // CertsSource. If this CertsSource is signalling that updates should be held
140   // back (|SetHoldBackUpdates(true)|, this will be set to false. The
141   // |certs_source_updated_callback| passed to the constructor will be invoked.
142   void SetCertInfos(
143       std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>>
144           cert_infos) {
145     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
146     cert_infos_.swap(cert_infos);
147     SetHoldBackUpdates(false);
148     certs_source_updated_callback_.Run();
149   }
150
151   // Signal to |CertificateManagerModel| that updates to its Observer should be
152   // held back. This will be automatically taken back on |SetCertInfos|.
153   // This should only be used by |CertsSource|s that provide their list of
154   // certificates asynchronously but expect their certificate listing to be
155   // fast.
156   void SetHoldBackUpdates(bool hold_back_updates) {
157     hold_back_updates_ = hold_back_updates;
158   }
159
160   // Used to verify that the constructor, and accessing |cert_infos_| are
161   // performed on the same sequence. Offered to subclasses so they can also
162   // check that they're being called on a valid sequence.
163   SEQUENCE_CHECKER(sequence_checker_);
164
165  private:
166   // Cached CertInfos provided by this CertsSource.
167   std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>> cert_infos_;
168
169   // Invoked when the list of certificates provided by this CertsSource has
170   // changed.
171   base::RepeatingClosure certs_source_updated_callback_;
172
173   // If true, the CertificateManagerModel should be holding back update
174   // notifications.
175   bool hold_back_updates_ = false;
176
177   DISALLOW_COPY_AND_ASSIGN(CertsSource);
178 };
179
180 namespace {
181 // Provides certificates enumerable from a NSSCertDatabase.
182 class CertsSourcePlatformNSS : public CertificateManagerModel::CertsSource,
183                                net::CertDatabase::Observer {
184  public:
185   CertsSourcePlatformNSS(base::RepeatingClosure certs_source_updated_callback,
186                          net::NSSCertDatabase* nss_cert_database)
187       : CertsSource(certs_source_updated_callback),
188         cert_db_(nss_cert_database) {
189     // Observe CertDatabase changes to refresh when it's updated.
190     cert_database_observation_.Observe(net::CertDatabase::GetInstance());
191   }
192   ~CertsSourcePlatformNSS() override = default;
193
194   // net::CertDatabase::Observer
195   void OnCertDBChanged() override {
196     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
197     Refresh();
198   }
199
200   void Refresh() override {
201     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
202     SetHoldBackUpdates(true);
203     DVLOG(1) << "refresh started";
204     std::vector<crypto::ScopedPK11Slot> modules;
205     cert_db_->ListModules(&modules, false);
206     DVLOG(1) << "refresh waiting for unlocking...";
207     chrome::UnlockSlotsIfNecessary(
208         std::move(modules), kCryptoModulePasswordListCerts,
209         net::HostPortPair(),  // unused.
210         nullptr,              // TODO(mattm): supply parent window.
211         base::BindOnce(&CertsSourcePlatformNSS::RefreshSlotsUnlocked,
212                        weak_ptr_factory_.GetWeakPtr()));
213   }
214
215   bool SetCertTrust(CERTCertificate* cert,
216                     net::CertType type,
217                     net::NSSCertDatabase::TrustBits trust_bits) override {
218     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
219     return cert_db_->SetCertTrust(cert, type, trust_bits);
220   }
221
222   bool Delete(CERTCertificate* cert) override {
223     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
224     return cert_db_->DeleteCertAndKey(cert);
225   }
226
227  private:
228   void RefreshSlotsUnlocked() {
229     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
230     DVLOG(1) << "refresh listing certs...";
231     cert_db_->ListCertsInfo(base::BindOnce(&CertsSourcePlatformNSS::DidGetCerts,
232                                            weak_ptr_factory_.GetWeakPtr()));
233   }
234
235   void DidGetCerts(net::NSSCertDatabase::CertInfoList cert_info_list) {
236     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
237     DVLOG(1) << "refresh finished for platform provided certificates";
238
239     std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>> cert_infos;
240     cert_infos.reserve(cert_info_list.size());
241
242     for (auto& cert_info : cert_info_list) {
243       net::CertType type =
244           x509_certificate_model::GetType(cert_info.cert.get());
245       bool can_be_deleted = !cert_info.on_read_only_slot;
246       bool hardware_backed = cert_info.hardware_backed;
247       std::u16string name = GetName(cert_info.cert.get(), hardware_backed);
248
249       cert_infos.push_back(std::make_unique<CertificateManagerModel::CertInfo>(
250           /*cert=*/std::move(cert_info.cert), type, name, can_be_deleted,
251           /*untrusted=*/cert_info.untrusted,
252           /*source=*/CertificateManagerModel::CertInfo::Source::kPlatform,
253           /*web_trust_anchor=*/cert_info.web_trust_anchor, hardware_backed,
254           /*device_wide=*/cert_info.device_wide));
255     }
256
257     SetCertInfos(std::move(cert_infos));
258   }
259
260   static std::u16string GetName(CERTCertificate* cert,
261                                 bool is_hardware_backed) {
262     std::u16string name =
263         base::UTF8ToUTF16(x509_certificate_model::GetCertNameOrNickname(cert));
264     if (is_hardware_backed) {
265       name = l10n_util::GetStringFUTF16(
266           IDS_CERT_MANAGER_HARDWARE_BACKED_KEY_FORMAT, name,
267           l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED));
268     }
269     return name;
270   }
271
272   // The source NSSCertDatabase used for listing certificates.
273   net::NSSCertDatabase* cert_db_;
274
275   // ScopedObservation to keep track of the observer for net::CertDatabase.
276   base::ScopedObservation<net::CertDatabase, net::CertDatabase::Observer>
277       cert_database_observation_{this};
278
279   base::WeakPtrFactory<CertsSourcePlatformNSS> weak_ptr_factory_{this};
280
281   DISALLOW_COPY_AND_ASSIGN(CertsSourcePlatformNSS);
282 };
283
284 #if BUILDFLAG(IS_CHROMEOS_ASH)
285 // Provides certificates installed through enterprise policy.
286 class CertsSourcePolicy : public CertificateManagerModel::CertsSource,
287                           chromeos::PolicyCertificateProvider::Observer {
288  public:
289   // Defines which policy-provided certificates this CertsSourcePolicy instance
290   // should yield.
291   enum class Mode {
292     // Only certificates which are installed by enterprise policy, but not Web
293     // trusted.
294     kPolicyCertsWithoutWebTrust,
295     // Only certificates which are installed by enterprise policy and Web
296     // trusted.
297     kPolicyCertsWithWebTrust
298   };
299
300   CertsSourcePolicy(base::RepeatingClosure certs_source_updated_callback,
301                     chromeos::PolicyCertificateProvider* policy_certs_provider,
302                     Mode mode)
303       : CertsSource(certs_source_updated_callback),
304         policy_certs_provider_(policy_certs_provider),
305         mode_(mode) {
306     policy_certs_provider_->AddPolicyProvidedCertsObserver(this);
307   }
308
309   ~CertsSourcePolicy() override {
310     policy_certs_provider_->RemovePolicyProvidedCertsObserver(this);
311   }
312
313   // chromeos::PolicyCertificateProvider::Observer
314   void OnPolicyProvidedCertsChanged() override {
315     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
316     Refresh();
317   }
318
319   void Refresh() override {
320     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
321     switch (mode_) {
322       case Mode::kPolicyCertsWithoutWebTrust:
323         RefreshImpl(policy_certs_provider_->GetCertificatesWithoutWebTrust(
324                         chromeos::onc::CertificateScope::Default()),
325                     false /* policy_web_trusted */);
326         break;
327       case Mode::kPolicyCertsWithWebTrust:
328         RefreshImpl(policy_certs_provider_->GetWebTrustedCertificates(
329                         chromeos::onc::CertificateScope::Default()),
330                     true /* policy_web_trusted */);
331         break;
332       default:
333         NOTREACHED();
334     }
335   }
336
337   bool SetCertTrust(CERTCertificate* cert,
338                     net::CertType type,
339                     net::NSSCertDatabase::TrustBits trust_bits) override {
340     // Trust of policy-provided certificates can not be changed.
341     LOG(WARNING) << kOperationNotPermitted << "Policy";
342     return false;
343   }
344
345   bool Delete(CERTCertificate* cert) override {
346     // Policy-provided certificates can not be deleted.
347     LOG(WARNING) << kOperationNotPermitted << "Policy";
348     return false;
349   }
350
351  private:
352   void RefreshImpl(const net::CertificateList& certificates,
353                    bool policy_web_trusted) {
354     std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>> cert_infos;
355     cert_infos.reserve(certificates.size());
356
357     for (const auto& policy_cert : certificates) {
358       net::ScopedCERTCertificate nss_cert(
359           net::x509_util::CreateCERTCertificateFromX509Certificate(
360               policy_cert.get()));
361       if (!nss_cert)
362         continue;
363
364       net::CertType type = x509_certificate_model::GetType(nss_cert.get());
365       std::u16string cert_name = base::UTF8ToUTF16(
366           x509_certificate_model::GetCertNameOrNickname(nss_cert.get()));
367       cert_infos.push_back(std::make_unique<CertificateManagerModel::CertInfo>(
368           std::move(nss_cert), type, std::move(cert_name),
369           false /* can_be_deleted */, false /* untrusted */,
370           CertificateManagerModel::CertInfo::Source::kPolicy,
371           policy_web_trusted /* web_trust_anchor */,
372           false /* hardware_backed */, false /* device_wide */));
373     }
374
375     SetCertInfos(std::move(cert_infos));
376   }
377
378   chromeos::PolicyCertificateProvider* policy_certs_provider_;
379   Mode mode_;
380
381   DISALLOW_COPY_AND_ASSIGN(CertsSourcePolicy);
382 };
383
384 // Provides certificates made available by extensions through the
385 // chrome.certificateProvider API.
386 class CertsSourceExtensions : public CertificateManagerModel::CertsSource {
387  public:
388   CertsSourceExtensions(base::RepeatingClosure certs_source_updated_callback,
389                         std::unique_ptr<chromeos::CertificateProvider>
390                             certificate_provider_service)
391       : CertsSource(certs_source_updated_callback),
392         certificate_provider_service_(std::move(certificate_provider_service)) {
393   }
394
395   void Refresh() override {
396     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
397     certificate_provider_service_->GetCertificates(base::BindOnce(
398         &CertsSourceExtensions::DidGetCerts, weak_ptr_factory_.GetWeakPtr()));
399   }
400
401   bool SetCertTrust(CERTCertificate* cert,
402                     net::CertType type,
403                     net::NSSCertDatabase::TrustBits trust_bits) override {
404     // Extension-provided certificates are user certificates; changing trust
405     // does not make sense here.
406     LOG(WARNING) << kOperationNotPermitted << "Extension";
407     return false;
408   }
409
410   bool Delete(CERTCertificate* cert) override {
411     // Extension-provided certificates can not be deleted.
412     LOG(WARNING) << kOperationNotPermitted << "Extension";
413     return false;
414   }
415
416  private:
417   void DidGetCerts(net::ClientCertIdentityList cert_identities) {
418     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
419     std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>> cert_infos;
420
421     cert_infos.reserve(cert_identities.size());
422     for (const auto& identity : cert_identities) {
423       net::ScopedCERTCertificate nss_cert(
424           net::x509_util::CreateCERTCertificateFromX509Certificate(
425               identity->certificate()));
426       if (!nss_cert)
427         continue;
428
429       std::u16string cert_name = base::UTF8ToUTF16(
430           x509_certificate_model::GetCertNameOrNickname(nss_cert.get()));
431       std::u16string display_name = l10n_util::GetStringFUTF16(
432           IDS_CERT_MANAGER_EXTENSION_PROVIDED_FORMAT, std::move(cert_name));
433
434       cert_infos.push_back(std::make_unique<CertificateManagerModel::CertInfo>(
435           std::move(nss_cert), net::CertType::USER_CERT /* type */,
436           display_name, false /* can_be_deleted */, false /* untrusted */,
437           CertificateManagerModel::CertInfo::Source::kExtension,
438           false /* web_trust_anchor */, false /* hardware_backed */,
439           false /* device_wide */));
440     }
441
442     SetCertInfos(std::move(cert_infos));
443   }
444
445   std::unique_ptr<chromeos::CertificateProvider> certificate_provider_service_;
446
447   base::WeakPtrFactory<CertsSourceExtensions> weak_ptr_factory_{this};
448
449   DISALLOW_COPY_AND_ASSIGN(CertsSourceExtensions);
450 };
451
452 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
453
454 }  // namespace
455
456 CertificateManagerModel::CertInfo::CertInfo(net::ScopedCERTCertificate cert,
457                                             net::CertType type,
458                                             std::u16string name,
459                                             bool can_be_deleted,
460                                             bool untrusted,
461                                             Source source,
462                                             bool web_trust_anchor,
463                                             bool hardware_backed,
464                                             bool device_wide)
465     : cert_(std::move(cert)),
466       type_(type),
467       name_(std::move(name)),
468       can_be_deleted_(can_be_deleted),
469       untrusted_(untrusted),
470       source_(source),
471       web_trust_anchor_(web_trust_anchor),
472       hardware_backed_(hardware_backed),
473       device_wide_(device_wide) {}
474
475 CertificateManagerModel::CertInfo::~CertInfo() {}
476
477 // static
478 std::unique_ptr<CertificateManagerModel::CertInfo>
479 CertificateManagerModel::CertInfo::Clone(const CertInfo* cert_info) {
480   return std::make_unique<CertInfo>(
481       net::x509_util::DupCERTCertificate(cert_info->cert()), cert_info->type(),
482       cert_info->name(), cert_info->can_be_deleted(), cert_info->untrusted(),
483       cert_info->source(), cert_info->web_trust_anchor(),
484       cert_info->hardware_backed(), cert_info->device_wide());
485 }
486
487 CertificateManagerModel::Params::Params() = default;
488 CertificateManagerModel::Params::~Params() = default;
489 CertificateManagerModel::Params::Params(Params&& other) = default;
490
491 // static
492 void CertificateManagerModel::Create(
493     content::BrowserContext* browser_context,
494     CertificateManagerModel::Observer* observer,
495     CreationCallback callback) {
496   DCHECK_CURRENTLY_ON(BrowserThread::UI);
497
498   std::unique_ptr<Params> params = std::make_unique<Params>();
499 #if BUILDFLAG(IS_CHROMEOS_ASH)
500   policy::UserNetworkConfigurationUpdater* user_network_configuration_updater =
501       policy::UserNetworkConfigurationUpdaterFactory::GetForBrowserContext(
502           browser_context);
503   params->policy_certs_provider = user_network_configuration_updater;
504
505   chromeos::CertificateProviderService* certificate_provider_service =
506       chromeos::CertificateProviderServiceFactory::GetForBrowserContext(
507           browser_context);
508   params->extension_certificate_provider =
509       certificate_provider_service->CreateCertificateProvider();
510 #endif
511
512   content::GetIOThreadTaskRunner({})->PostTask(
513       FROM_HERE, base::BindOnce(&CertificateManagerModel::GetCertDBOnIOThread,
514                                 std::move(params),
515                                 CreateNSSCertDatabaseGetter(browser_context),
516                                 observer, std::move(callback)));
517 }
518
519 CertificateManagerModel::CertificateManagerModel(
520     std::unique_ptr<Params> params,
521     Observer* observer,
522     net::NSSCertDatabase* nss_cert_database,
523     bool is_user_db_available,
524     bool is_tpm_available)
525     : cert_db_(nss_cert_database),
526       is_user_db_available_(is_user_db_available),
527       is_tpm_available_(is_tpm_available),
528       observer_(observer) {
529   DCHECK_CURRENTLY_ON(BrowserThread::UI);
530
531   // Fill |certs_sources_|. Note that the order matters. Higher priority
532   // CertsSources must come first.
533
534   base::RepeatingClosure certs_source_updated_callback = base::BindRepeating(
535       &CertificateManagerModel::OnCertsSourceUpdated, base::Unretained(this));
536
537 #if BUILDFLAG(IS_CHROMEOS_ASH)
538   // Certificates installed and web trusted by enterprise policy is the highest
539   // priority CertsSource.
540   // UserNetworkConfigurationUpdater is only available for the primary user's
541   // profile.
542   if (params->policy_certs_provider) {
543     certs_sources_.push_back(std::make_unique<CertsSourcePolicy>(
544         certs_source_updated_callback, params->policy_certs_provider,
545         CertsSourcePolicy::Mode::kPolicyCertsWithWebTrust));
546   }
547 #endif
548
549   // Add the main NSS DB based CertsSource.
550   certs_sources_.push_back(std::make_unique<CertsSourcePlatformNSS>(
551       certs_source_updated_callback, nss_cert_database));
552
553 #if BUILDFLAG(IS_CHROMEOS_ASH)
554   // Certificates installed by enterprise policy without web trust are lower
555   // priority than the main NSS DB based CertsSource.
556   // Rationale: The user should be able to add trust to policy-provided
557   // certificates by re-importing them and modifying their trust settings.
558   if (params->policy_certs_provider) {
559     certs_sources_.push_back(std::make_unique<CertsSourcePolicy>(
560         certs_source_updated_callback, params->policy_certs_provider,
561         CertsSourcePolicy::Mode::kPolicyCertsWithoutWebTrust));
562   }
563
564   // Extensions is the lowest priority CertsSource.
565   if (params->extension_certificate_provider) {
566     certs_sources_.push_back(std::make_unique<CertsSourceExtensions>(
567         certs_source_updated_callback,
568         std::move(params->extension_certificate_provider)));
569   }
570 #endif
571 }
572
573 CertificateManagerModel::~CertificateManagerModel() {}
574
575 void CertificateManagerModel::OnCertsSourceUpdated() {
576   if (hold_back_updates_)
577     return;
578   for (const auto& certs_source : certs_sources_) {
579     if (certs_source->IsHoldBackUpdates()) {
580       return;
581     }
582   }
583
584   observer_->CertificatesRefreshed();
585 }
586
587 CertificateManagerModel::CertsSource*
588 CertificateManagerModel::FindCertsSourceForCert(CERTCertificate* cert) {
589   for (auto& certs_source : certs_sources_) {
590     if (certs_source->HasCert(cert))
591       return certs_source.get();
592   }
593   return nullptr;
594 }
595
596 void CertificateManagerModel::Refresh() {
597   hold_back_updates_ = true;
598
599   for (auto& certs_source : certs_sources_)
600     certs_source->Refresh();
601
602   hold_back_updates_ = false;
603   OnCertsSourceUpdated();
604 }
605
606 void CertificateManagerModel::FilterAndBuildOrgGroupingMap(
607     net::CertType filter_type,
608     CertificateManagerModel::OrgGroupingMap* out_org_grouping_map) const {
609   std::map<CERTCertificate*, std::unique_ptr<CertInfo>> cert_info_map;
610   for (const auto& certs_source : certs_sources_) {
611     for (const auto& cert_info : certs_source->cert_infos()) {
612       if (cert_info->type() != filter_type)
613         continue;
614
615       if (cert_info_map.find(cert_info->cert()) == cert_info_map.end())
616         cert_info_map[cert_info->cert()] = CertInfo::Clone(cert_info.get());
617     }
618   }
619
620   for (auto& cert_info_kv : cert_info_map) {
621     std::string org = GetCertificateOrg(cert_info_kv.second->cert());
622     (*out_org_grouping_map)[org].push_back(std::move(cert_info_kv.second));
623   }
624 }
625
626 int CertificateManagerModel::ImportFromPKCS12(PK11SlotInfo* slot_info,
627                                               const std::string& data,
628                                               const std::u16string& password,
629                                               bool is_extractable) {
630   return cert_db_->ImportFromPKCS12(slot_info, data, password, is_extractable,
631                                     nullptr);
632 }
633
634 int CertificateManagerModel::ImportUserCert(const std::string& data) {
635   return cert_db_->ImportUserCert(data);
636 }
637
638 bool CertificateManagerModel::ImportCACerts(
639     const net::ScopedCERTCertificateList& certificates,
640     net::NSSCertDatabase::TrustBits trust_bits,
641     net::NSSCertDatabase::ImportCertFailureList* not_imported) {
642   return cert_db_->ImportCACerts(certificates, trust_bits, not_imported);
643 }
644
645 bool CertificateManagerModel::ImportServerCert(
646     const net::ScopedCERTCertificateList& certificates,
647     net::NSSCertDatabase::TrustBits trust_bits,
648     net::NSSCertDatabase::ImportCertFailureList* not_imported) {
649   const size_t num_certs = certificates.size();
650   bool result =
651       cert_db_->ImportServerCert(certificates, trust_bits, not_imported);
652   if (result && not_imported->size() != num_certs)
653     Refresh();
654   return result;
655 }
656
657 bool CertificateManagerModel::SetCertTrust(
658     CERTCertificate* cert,
659     net::CertType type,
660     net::NSSCertDatabase::TrustBits trust_bits) {
661   CertsSource* certs_source = FindCertsSourceForCert(cert);
662   if (!certs_source)
663     return false;
664   return certs_source->SetCertTrust(cert, type, trust_bits);
665 }
666
667 bool CertificateManagerModel::Delete(CERTCertificate* cert) {
668   CertsSource* certs_source = FindCertsSourceForCert(cert);
669   if (!certs_source)
670     return false;
671   return certs_source->Delete(cert);
672 }
673
674 // static
675 void CertificateManagerModel::DidGetCertDBOnUIThread(
676     std::unique_ptr<Params> params,
677     CertificateManagerModel::Observer* observer,
678     CreationCallback callback,
679     net::NSSCertDatabase* cert_db,
680     bool is_user_db_available,
681     bool is_tpm_available) {
682   DCHECK_CURRENTLY_ON(BrowserThread::UI);
683
684   std::unique_ptr<CertificateManagerModel> model =
685       std::make_unique<CertificateManagerModel>(std::move(params), observer,
686                                                 cert_db, is_user_db_available,
687                                                 is_tpm_available);
688   std::move(callback).Run(std::move(model));
689 }
690
691 // static
692 void CertificateManagerModel::DidGetCertDBOnIOThread(
693     std::unique_ptr<Params> params,
694     CertificateManagerModel::Observer* observer,
695     CreationCallback callback,
696     net::NSSCertDatabase* cert_db) {
697   DCHECK_CURRENTLY_ON(BrowserThread::IO);
698
699   bool is_user_db_available = !!cert_db->GetPublicSlot();
700   bool is_tpm_available = false;
701 #if BUILDFLAG(IS_CHROMEOS_ASH)
702   is_tpm_available = crypto::IsTPMTokenEnabledForNSS();
703 #endif
704   content::GetUIThreadTaskRunner({})->PostTask(
705       FROM_HERE,
706       base::BindOnce(&CertificateManagerModel::DidGetCertDBOnUIThread,
707                      std::move(params), observer, std::move(callback), cert_db,
708                      is_user_db_available, is_tpm_available));
709 }
710
711 // static
712 void CertificateManagerModel::GetCertDBOnIOThread(
713     std::unique_ptr<Params> params,
714     NssCertDatabaseGetter database_getter,
715     CertificateManagerModel::Observer* observer,
716     CreationCallback callback) {
717   DCHECK_CURRENTLY_ON(BrowserThread::IO);
718
719   auto split_callback = base::SplitOnceCallback(
720       base::BindOnce(&CertificateManagerModel::DidGetCertDBOnIOThread,
721                      std::move(params), observer, std::move(callback)));
722
723   net::NSSCertDatabase* cert_db =
724       std::move(database_getter).Run(std::move(split_callback.first));
725   // If the NSS database was already available, |cert_db| is non-null and
726   // |did_get_cert_db_callback| has not been called. Call it explicitly.
727   if (cert_db)
728     std::move(split_callback.second).Run(cert_db);
729 }