Index: chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.cc |
diff --git a/chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.cc b/chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d61468b43ccd914112a7ae1ded3365c647a1ab3e |
--- /dev/null |
+++ b/chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.cc |
@@ -0,0 +1,207 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.h" |
+ |
+#include <string> |
+#include <vector> |
+ |
+#include "base/logging.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/memory/singleton.h" |
+#include "base/values.h" |
+#include "chrome/browser/chromeos/certificate_provider/certificate_provider_service.h" |
+#include "chrome/browser/chromeos/profiles/profile_helper.h" |
+#include "chrome/browser/profiles/incognito_helpers.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/common/extensions/api/certificate_provider.h" |
+#include "components/keyed_service/content/browser_context_dependency_manager.h" |
+#include "extensions/browser/event_listener_map.h" |
+#include "extensions/browser/event_router.h" |
+#include "extensions/browser/event_router_factory.h" |
+#include "extensions/browser/extension_event_histogram_value.h" |
+#include "extensions/browser/extension_registry.h" |
+#include "extensions/browser/extension_registry_factory.h" |
+#include "extensions/browser/extension_registry_observer.h" |
+#include "extensions/common/extension.h" |
+#include "net/cert/x509_certificate.h" |
+#include "net/ssl/ssl_private_key.h" |
+ |
+namespace chromeos { |
+ |
+namespace { |
+ |
+namespace api_cp = extensions::api::certificate_provider; |
+ |
+class DefaultDelegate : public CertificateProviderService::Delegate, |
+ public extensions::ExtensionRegistryObserver { |
+ public: |
+ DefaultDelegate(CertificateProviderService* service, |
+ extensions::ExtensionRegistry* registry, |
+ extensions::EventRouter* event_router); |
+ ~DefaultDelegate() override; |
+ |
+ // CertificateProviderService::Delegate: |
+ std::vector<std::string> CertificateProviderExtensions() override; |
+ void BroadcastCertificateRequest(int request_id) override; |
+ bool DispatchSignRequestToExtension( |
+ const std::string& extension_id, |
+ int request_id, |
+ net::SSLPrivateKey::Hash hash, |
+ const scoped_refptr<net::X509Certificate>& certificate, |
+ const std::string& digest) override; |
+ |
+ // extensions::ExtensionRegistryObserver: |
+ void OnExtensionUnloaded( |
+ content::BrowserContext* browser_context, |
+ const extensions::Extension* extension, |
+ extensions::UnloadedExtensionInfo::Reason reason) override; |
+ |
+ private: |
+ CertificateProviderService* const service_; |
+ extensions::ExtensionRegistry* const registry_; |
+ extensions::EventRouter* const event_router_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); |
+}; |
+ |
+DefaultDelegate::DefaultDelegate(CertificateProviderService* service, |
+ extensions::ExtensionRegistry* registry, |
+ extensions::EventRouter* event_router) |
+ : service_(service), registry_(registry), event_router_(event_router) { |
+ DCHECK(service_); |
+ DCHECK(event_router_); |
+ registry_->AddObserver(this); |
+} |
+ |
+DefaultDelegate::~DefaultDelegate() { |
+ registry_->RemoveObserver(this); |
+} |
+ |
+std::vector<std::string> DefaultDelegate::CertificateProviderExtensions() { |
+ const std::string event_name(api_cp::OnCertificatesRequested::kEventName); |
+ std::vector<std::string> ids; |
+ for (const auto& listener : |
+ event_router_->listeners().GetEventListenersByName(event_name)) { |
+ ids.push_back(listener->extension_id()); |
+ } |
+ return ids; |
+} |
+ |
+void DefaultDelegate::BroadcastCertificateRequest(int request_id) { |
+ const std::string event_name(api_cp::OnCertificatesRequested::kEventName); |
+ scoped_ptr<base::ListValue> internal_args(new base::ListValue); |
+ internal_args->AppendInteger(request_id); |
+ scoped_ptr<extensions::Event> event(new extensions::Event( |
+ extensions::events::CERTIFICATEPROVIDER_ON_CERTIFICATES_REQUESTED, |
+ event_name, internal_args.Pass())); |
+ event_router_->BroadcastEvent(event.Pass()); |
+} |
+ |
+bool DefaultDelegate::DispatchSignRequestToExtension( |
+ const std::string& extension_id, |
+ int request_id, |
+ net::SSLPrivateKey::Hash hash, |
+ const scoped_refptr<net::X509Certificate>& certificate, |
+ const std::string& digest) { |
+ const std::string event_name(api_cp::OnSignDigestRequested::kEventName); |
+ if (!event_router_->ExtensionHasEventListener(extension_id, event_name)) |
+ return false; |
+ |
+ api_cp::SignRequest request; |
+ switch (hash) { |
+ case net::SSLPrivateKey::Hash::MD5_SHA1: |
+ request.hash = api_cp::HASH_MD5_SHA1; |
+ break; |
+ case net::SSLPrivateKey::Hash::SHA1: |
+ request.hash = api_cp::HASH_SHA1; |
+ break; |
+ case net::SSLPrivateKey::Hash::SHA256: |
+ request.hash = api_cp::HASH_SHA256; |
+ break; |
+ case net::SSLPrivateKey::Hash::SHA384: |
+ request.hash = api_cp::HASH_SHA384; |
+ break; |
+ case net::SSLPrivateKey::Hash::SHA512: |
+ request.hash = api_cp::HASH_SHA512; |
+ break; |
+ } |
+ request.digest.assign(digest.begin(), digest.end()); |
+ std::string cert_der; |
+ if (!net::X509Certificate::GetDEREncoded(certificate->os_cert_handle(), |
+ &cert_der)) { |
+ LOG(ERROR) << "Could not DER encode the certificate."; |
+ return false; // Behave as if the extension wasn't registered anymore. |
+ } |
+ request.certificate.assign(cert_der.begin(), cert_der.end()); |
+ |
+ scoped_ptr<base::ListValue> internal_args(new base::ListValue); |
+ internal_args->AppendInteger(request_id); |
+ internal_args->Append(request.ToValue().Pass()); |
+ |
+ event_router_->DispatchEventToExtension( |
+ extension_id, |
+ make_scoped_ptr(new extensions::Event( |
+ extensions::events::CERTIFICATEPROVIDER_ON_SIGN_DIGEST_REQUESTED, |
+ event_name, internal_args.Pass()))); |
+ return true; |
+} |
+ |
+void DefaultDelegate::OnExtensionUnloaded( |
+ content::BrowserContext* browser_context, |
+ const extensions::Extension* extension, |
+ extensions::UnloadedExtensionInfo::Reason reason) { |
+ service_->OnExtensionUnloaded(extension->id()); |
+} |
+ |
+} // namespace |
+ |
+// static |
+CertificateProviderService* |
+CertificateProviderServiceFactory::GetForBrowserContext( |
+ content::BrowserContext* context) { |
+ return static_cast<CertificateProviderService*>( |
+ GetInstance()->GetServiceForBrowserContext(context, true)); |
+} |
+ |
+// static |
+CertificateProviderServiceFactory* |
+CertificateProviderServiceFactory::GetInstance() { |
+ return Singleton<CertificateProviderServiceFactory>::get(); |
+} |
+ |
+CertificateProviderServiceFactory::CertificateProviderServiceFactory() |
+ : BrowserContextKeyedServiceFactory( |
+ "CertificateProviderService", |
+ BrowserContextDependencyManager::GetInstance()) { |
+ DependsOn(extensions::EventRouterFactory::GetInstance()); |
+ DependsOn(extensions::ExtensionRegistryFactory::GetInstance()); |
+} |
+ |
+content::BrowserContext* |
+CertificateProviderServiceFactory::GetBrowserContextToUse( |
+ content::BrowserContext* context) const { |
+ return chrome::GetBrowserContextRedirectedInIncognito(context); |
+} |
+ |
+bool CertificateProviderServiceFactory::ServiceIsNULLWhileTesting() const { |
+ return true; |
+} |
+ |
+KeyedService* CertificateProviderServiceFactory::BuildServiceInstanceFor( |
+ content::BrowserContext* context) const { |
+ if (chromeos::ProfileHelper::IsSigninProfile( |
+ Profile::FromBrowserContext(context))) { |
+ return nullptr; |
+ } |
+ CertificateProviderService* const service = new CertificateProviderService(); |
+ service->SetDelegate(make_scoped_ptr(new DefaultDelegate( |
+ service, |
+ extensions::ExtensionRegistryFactory::GetForBrowserContext(context), |
+ extensions::EventRouterFactory::GetForBrowserContext(context)))); |
+ return service; |
+} |
+ |
+} // namespace chromeos |