1 // Copyright 2015 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.
5 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.h"
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/memory/singleton.h"
14 #include "base/values.h"
15 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service.h"
16 #include "chrome/browser/chromeos/profiles/profile_helper.h"
17 #include "chrome/browser/profiles/incognito_helpers.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/extensions/api/certificate_provider.h"
20 #include "components/keyed_service/content/browser_context_dependency_manager.h"
21 #include "extensions/browser/event_listener_map.h"
22 #include "extensions/browser/event_router.h"
23 #include "extensions/browser/event_router_factory.h"
24 #include "extensions/browser/extension_event_histogram_value.h"
25 #include "extensions/browser/extension_registry.h"
26 #include "extensions/browser/extension_registry_factory.h"
27 #include "extensions/browser/extension_registry_observer.h"
28 #include "extensions/common/extension.h"
29 #include "net/cert/x509_certificate.h"
30 #include "net/ssl/ssl_private_key.h"
36 namespace api_cp
= extensions::api::certificate_provider
;
38 class DefaultDelegate
: public CertificateProviderService::Delegate
,
39 public extensions::ExtensionRegistryObserver
{
41 DefaultDelegate(CertificateProviderService
* service
,
42 extensions::ExtensionRegistry
* registry
,
43 extensions::EventRouter
* event_router
);
44 ~DefaultDelegate() override
;
46 // CertificateProviderService::Delegate:
47 std::vector
<std::string
> CertificateProviderExtensions() override
;
48 void BroadcastCertificateRequest(int request_id
) override
;
49 bool DispatchSignRequestToExtension(
50 const std::string
& extension_id
,
52 net::SSLPrivateKey::Hash hash
,
53 const scoped_refptr
<net::X509Certificate
>& certificate
,
54 const std::string
& digest
) override
;
56 // extensions::ExtensionRegistryObserver:
57 void OnExtensionUnloaded(
58 content::BrowserContext
* browser_context
,
59 const extensions::Extension
* extension
,
60 extensions::UnloadedExtensionInfo::Reason reason
) override
;
63 CertificateProviderService
* const service_
;
64 extensions::ExtensionRegistry
* const registry_
;
65 extensions::EventRouter
* const event_router_
;
67 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate
);
70 DefaultDelegate::DefaultDelegate(CertificateProviderService
* service
,
71 extensions::ExtensionRegistry
* registry
,
72 extensions::EventRouter
* event_router
)
73 : service_(service
), registry_(registry
), event_router_(event_router
) {
75 DCHECK(event_router_
);
76 registry_
->AddObserver(this);
79 DefaultDelegate::~DefaultDelegate() {
80 registry_
->RemoveObserver(this);
83 std::vector
<std::string
> DefaultDelegate::CertificateProviderExtensions() {
84 const std::string
event_name(api_cp::OnCertificatesRequested::kEventName
);
85 std::vector
<std::string
> ids
;
86 for (const auto& listener
:
87 event_router_
->listeners().GetEventListenersByName(event_name
)) {
88 ids
.push_back(listener
->extension_id());
93 void DefaultDelegate::BroadcastCertificateRequest(int request_id
) {
94 const std::string
event_name(api_cp::OnCertificatesRequested::kEventName
);
95 scoped_ptr
<base::ListValue
> internal_args(new base::ListValue
);
96 internal_args
->AppendInteger(request_id
);
97 scoped_ptr
<extensions::Event
> event(new extensions::Event(
98 extensions::events::CERTIFICATEPROVIDER_ON_CERTIFICATES_REQUESTED
,
99 event_name
, internal_args
.Pass()));
100 event_router_
->BroadcastEvent(event
.Pass());
103 bool DefaultDelegate::DispatchSignRequestToExtension(
104 const std::string
& extension_id
,
106 net::SSLPrivateKey::Hash hash
,
107 const scoped_refptr
<net::X509Certificate
>& certificate
,
108 const std::string
& digest
) {
109 const std::string
event_name(api_cp::OnSignDigestRequested::kEventName
);
110 if (!event_router_
->ExtensionHasEventListener(extension_id
, event_name
))
113 api_cp::SignRequest request
;
115 case net::SSLPrivateKey::Hash::MD5_SHA1
:
116 request
.hash
= api_cp::HASH_MD5_SHA1
;
118 case net::SSLPrivateKey::Hash::SHA1
:
119 request
.hash
= api_cp::HASH_SHA1
;
121 case net::SSLPrivateKey::Hash::SHA256
:
122 request
.hash
= api_cp::HASH_SHA256
;
124 case net::SSLPrivateKey::Hash::SHA384
:
125 request
.hash
= api_cp::HASH_SHA384
;
127 case net::SSLPrivateKey::Hash::SHA512
:
128 request
.hash
= api_cp::HASH_SHA512
;
131 request
.digest
.assign(digest
.begin(), digest
.end());
132 std::string cert_der
;
133 if (!net::X509Certificate::GetDEREncoded(certificate
->os_cert_handle(),
135 LOG(ERROR
) << "Could not DER encode the certificate.";
136 return false; // Behave as if the extension wasn't registered anymore.
138 request
.certificate
.assign(cert_der
.begin(), cert_der
.end());
140 scoped_ptr
<base::ListValue
> internal_args(new base::ListValue
);
141 internal_args
->AppendInteger(request_id
);
142 internal_args
->Append(request
.ToValue().Pass());
144 event_router_
->DispatchEventToExtension(
146 make_scoped_ptr(new extensions::Event(
147 extensions::events::CERTIFICATEPROVIDER_ON_SIGN_DIGEST_REQUESTED
,
148 event_name
, internal_args
.Pass())));
152 void DefaultDelegate::OnExtensionUnloaded(
153 content::BrowserContext
* browser_context
,
154 const extensions::Extension
* extension
,
155 extensions::UnloadedExtensionInfo::Reason reason
) {
156 service_
->OnExtensionUnloaded(extension
->id());
162 CertificateProviderService
*
163 CertificateProviderServiceFactory::GetForBrowserContext(
164 content::BrowserContext
* context
) {
165 return static_cast<CertificateProviderService
*>(
166 GetInstance()->GetServiceForBrowserContext(context
, true));
170 CertificateProviderServiceFactory
*
171 CertificateProviderServiceFactory::GetInstance() {
172 return base::Singleton
<CertificateProviderServiceFactory
>::get();
175 CertificateProviderServiceFactory::CertificateProviderServiceFactory()
176 : BrowserContextKeyedServiceFactory(
177 "CertificateProviderService",
178 BrowserContextDependencyManager::GetInstance()) {
179 DependsOn(extensions::EventRouterFactory::GetInstance());
180 DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
183 content::BrowserContext
*
184 CertificateProviderServiceFactory::GetBrowserContextToUse(
185 content::BrowserContext
* context
) const {
186 return chrome::GetBrowserContextRedirectedInIncognito(context
);
189 bool CertificateProviderServiceFactory::ServiceIsNULLWhileTesting() const {
193 KeyedService
* CertificateProviderServiceFactory::BuildServiceInstanceFor(
194 content::BrowserContext
* context
) const {
195 if (chromeos::ProfileHelper::IsSigninProfile(
196 Profile::FromBrowserContext(context
))) {
199 CertificateProviderService
* const service
= new CertificateProviderService();
200 service
->SetDelegate(make_scoped_ptr(new DefaultDelegate(
202 extensions::ExtensionRegistryFactory::GetForBrowserContext(context
),
203 extensions::EventRouterFactory::GetForBrowserContext(context
))));
207 } // namespace chromeos