Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / extensions / api / platform_keys / verify_trust_api.cc
blob3a2b5540b1a6851fcd0a0ed2b94ce725f9f61e76
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/extensions/api/platform_keys/verify_trust_api.h"
7 #include <algorithm>
9 #include "base/lazy_instance.h"
10 #include "base/macros.h"
11 #include "base/memory/linked_ptr.h"
12 #include "base/memory/ref_counted.h"
13 #include "chrome/browser/extensions/api/platform_keys/platform_keys_api.h"
14 #include "chrome/common/extensions/api/platform_keys_internal.h"
15 #include "extensions/browser/extension_registry_factory.h"
16 #include "net/base/net_errors.h"
17 #include "net/cert/cert_verifier.h"
18 #include "net/cert/cert_verify_result.h"
19 #include "net/cert/x509_certificate.h"
20 #include "net/log/net_log.h"
21 #include "net/ssl/ssl_config_service.h"
23 namespace extensions {
25 namespace {
27 base::LazyInstance<BrowserContextKeyedAPIFactory<VerifyTrustAPI>>::Leaky
28 g_factory = LAZY_INSTANCE_INITIALIZER;
30 const char kErrorEmptyCertificateChain[] =
31 "Server certificate chain must not be empty.";
33 } // namespace
35 // This class bundles IO data and functions of the VerifyTrustAPI that are to be
36 // used on the IO thread only.
37 // It is created on the UI thread and afterwards lives on the IO thread.
38 class VerifyTrustAPI::IOPart {
39 public:
40 ~IOPart();
42 // Verifies the certificate as stated by |params| and calls back |callback|
43 // with the result (see the declaration of VerifyCallback).
44 // Will not call back after this object is destructed or the verifier for this
45 // extension is deleted (see OnExtensionUnloaded).
46 void Verify(scoped_ptr<Params> params,
47 const std::string& extension_id,
48 const VerifyCallback& callback);
50 // Must be called when the extension with id |extension_id| is unloaded.
51 // Deletes the verifier for |extension_id| and cancels all pending
52 // verifications of this verifier.
53 void OnExtensionUnloaded(const std::string& extension_id);
55 private:
56 struct RequestState {
57 RequestState() {}
59 scoped_ptr<net::CertVerifier::Request> request;
61 private:
62 DISALLOW_COPY_AND_ASSIGN(RequestState);
65 // Calls back |callback| with the result and no error.
66 void CallBackWithResult(const VerifyCallback& callback,
67 scoped_ptr<net::CertVerifyResult> verify_result,
68 RequestState* request_state,
69 int return_value);
71 // One CertVerifier per extension to verify trust. Each verifier is created on
72 // first usage and deleted when this IOPart is destructed or the respective
73 // extension is unloaded.
74 std::map<std::string, linked_ptr<net::CertVerifier>> extension_to_verifier_;
77 // static
78 BrowserContextKeyedAPIFactory<VerifyTrustAPI>*
79 VerifyTrustAPI::GetFactoryInstance() {
80 return g_factory.Pointer();
83 template <>
84 void BrowserContextKeyedAPIFactory<
85 VerifyTrustAPI>::DeclareFactoryDependencies() {
86 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
87 DependsOn(ExtensionRegistryFactory::GetInstance());
90 VerifyTrustAPI::VerifyTrustAPI(content::BrowserContext* context)
91 : io_part_(new IOPart), registry_observer_(this), weak_factory_(this) {
92 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
93 registry_observer_.Add(ExtensionRegistry::Get(context));
96 VerifyTrustAPI::~VerifyTrustAPI() {
97 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
100 void VerifyTrustAPI::Verify(scoped_ptr<Params> params,
101 const std::string& extension_id,
102 const VerifyCallback& ui_callback) {
103 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
105 // Call back through the VerifyTrustAPI object on the UIThread. Because of the
106 // WeakPtr usage, this will ensure that |ui_callback| is not called after the
107 // API is destroyed.
108 VerifyCallback finish_callback(base::Bind(
109 &CallBackOnUI, base::Bind(&VerifyTrustAPI::FinishedVerificationOnUI,
110 weak_factory_.GetWeakPtr(), ui_callback)));
112 content::BrowserThread::PostTask(
113 content::BrowserThread::IO, FROM_HERE,
114 base::Bind(&IOPart::Verify, base::Unretained(io_part_.get()),
115 base::Passed(&params), extension_id, finish_callback));
118 void VerifyTrustAPI::OnExtensionUnloaded(
119 content::BrowserContext* browser_context,
120 const Extension* extension,
121 UnloadedExtensionInfo::Reason reason) {
122 content::BrowserThread::PostTask(
123 content::BrowserThread::IO, FROM_HERE,
124 base::Bind(&IOPart::OnExtensionUnloaded, base::Unretained(io_part_.get()),
125 extension->id()));
128 void VerifyTrustAPI::FinishedVerificationOnUI(const VerifyCallback& ui_callback,
129 const std::string& error,
130 int return_value,
131 int cert_status) {
132 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
134 ui_callback.Run(error, return_value, cert_status);
137 // static
138 void VerifyTrustAPI::CallBackOnUI(const VerifyCallback& ui_callback,
139 const std::string& error,
140 int return_value,
141 int cert_status) {
142 content::BrowserThread::PostTask(
143 content::BrowserThread::UI, FROM_HERE,
144 base::Bind(ui_callback, error, return_value, cert_status));
147 VerifyTrustAPI::IOPart::~IOPart() {
148 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
151 void VerifyTrustAPI::IOPart::Verify(scoped_ptr<Params> params,
152 const std::string& extension_id,
153 const VerifyCallback& callback) {
154 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
156 const api::platform_keys::VerificationDetails& details = params->details;
158 if (details.server_certificate_chain.empty()) {
159 callback.Run(kErrorEmptyCertificateChain, 0, 0);
160 return;
163 std::vector<base::StringPiece> der_cert_chain;
164 for (const std::vector<char>& cert_der : details.server_certificate_chain) {
165 if (cert_der.empty()) {
166 callback.Run(platform_keys::kErrorInvalidX509Cert, 0, 0);
167 return;
169 der_cert_chain.push_back(base::StringPiece(
170 reinterpret_cast<const char*>(vector_as_array(&cert_der)),
171 cert_der.size()));
173 scoped_refptr<net::X509Certificate> cert_chain(
174 net::X509Certificate::CreateFromDERCertChain(der_cert_chain));
175 if (!cert_chain) {
176 callback.Run(platform_keys::kErrorInvalidX509Cert, 0, 0);
177 return;
180 net::CertVerifier* verifier = nullptr;
181 if (ContainsKey(extension_to_verifier_, extension_id)) {
182 verifier = extension_to_verifier_[extension_id].get();
183 } else {
184 verifier = net::CertVerifier::CreateDefault();
185 extension_to_verifier_[extension_id] = make_linked_ptr(verifier);
188 scoped_ptr<net::CertVerifyResult> verify_result(new net::CertVerifyResult);
189 scoped_ptr<net::BoundNetLog> net_log(new net::BoundNetLog);
190 const int flags = 0;
192 std::string ocsp_response;
193 net::CertVerifyResult* const verify_result_ptr = verify_result.get();
195 RequestState* request_state = new RequestState();
196 base::Callback<void(int)> bound_callback(
197 base::Bind(&IOPart::CallBackWithResult, base::Unretained(this), callback,
198 base::Passed(&verify_result), base::Owned(request_state)));
200 const int return_value = verifier->Verify(
201 cert_chain.get(), details.hostname, ocsp_response, flags,
202 net::SSLConfigService::GetCRLSet().get(), verify_result_ptr,
203 bound_callback, &request_state->request, *net_log);
205 if (return_value != net::ERR_IO_PENDING) {
206 bound_callback.Run(return_value);
207 return;
211 void VerifyTrustAPI::IOPart::OnExtensionUnloaded(
212 const std::string& extension_id) {
213 extension_to_verifier_.erase(extension_id);
216 void VerifyTrustAPI::IOPart::CallBackWithResult(
217 const VerifyCallback& callback,
218 scoped_ptr<net::CertVerifyResult> verify_result,
219 RequestState* request_state,
220 int return_value) {
221 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
223 callback.Run(std::string() /* no error message */, return_value,
224 verify_result->cert_status);
227 } // namespace extensions