Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / chromeos / platform_keys / platform_keys_service.cc
blob7ba138c69202d7817d7b3ea4e940fde0b9810338
1 // Copyright 2014 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/platform_keys/platform_keys_service.h"
7 #include "base/base64.h"
8 #include "base/callback.h"
9 #include "base/values.h"
10 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "extensions/browser/state_store.h"
14 using content::BrowserThread;
16 namespace chromeos {
18 namespace {
20 const char kErrorInternal[] = "Internal Error.";
21 const char kErrorKeyNotAllowedForSigning[] =
22 "This key is not allowed for signing. Either it was used for signing "
23 "before or it was not correctly generated.";
24 const char kStateStorePlatformKeys[] = "PlatformKeys";
26 scoped_ptr<base::StringValue> GetPublicKeyValue(
27 const std::string& public_key_spki_der) {
28 std::string public_key_spki_der_b64;
29 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
30 return make_scoped_ptr(new base::StringValue(public_key_spki_der_b64));
33 // Wraps |callback| into a void(bool) callback which forwards
34 // |public_key_spki_der| if |true| is passed to it.
35 void WrapGenerateKeyCallback(
36 const PlatformKeysService::GenerateKeyCallback& callback,
37 const std::string& public_key_spki_der,
38 bool success) {
39 if (success)
40 callback.Run(public_key_spki_der, std::string() /* no error */);
41 else
42 callback.Run(std::string() /* no public key */, kErrorInternal);
45 // Callback used by |PlatformKeysService::Sign|.
46 // Is called with the old validity of |public_key_spki_der| (or false if an
47 // error occurred during reading the StateStore). If allowed, starts the actual
48 // signing operation which will call back |callback|. If not allowed, calls
49 // |callback| with an error.
50 void CheckValidityAndSign(const std::string& token_id,
51 const std::string& public_key_spki_der,
52 platform_keys::HashAlgorithm hash_algorithm,
53 const std::string& data,
54 const PlatformKeysService::SignCallback& callback,
55 content::BrowserContext* browser_context,
56 bool key_is_valid) {
57 if (!key_is_valid) {
58 callback.Run(std::string() /* no signature */,
59 kErrorKeyNotAllowedForSigning);
60 return;
62 platform_keys::subtle::Sign(token_id,
63 public_key_spki_der,
64 hash_algorithm,
65 data,
66 callback,
67 browser_context);
70 } // namespace
72 PlatformKeysService::PlatformKeysService(
73 content::BrowserContext* browser_context,
74 extensions::StateStore* state_store)
75 : browser_context_(browser_context),
76 state_store_(state_store),
77 weak_factory_(this) {
78 DCHECK(state_store);
81 PlatformKeysService::~PlatformKeysService() {
84 void PlatformKeysService::GenerateRSAKey(const std::string& token_id,
85 unsigned int modulus_length,
86 const std::string& extension_id,
87 const GenerateKeyCallback& callback) {
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
90 platform_keys::subtle::GenerateRSAKey(
91 token_id,
92 modulus_length,
93 base::Bind(&PlatformKeysService::GenerateRSAKeyCallback,
94 weak_factory_.GetWeakPtr(),
95 extension_id,
96 callback),
97 browser_context_);
100 void PlatformKeysService::Sign(const std::string& token_id,
101 const std::string& public_key_spki_der,
102 platform_keys::HashAlgorithm hash_algorithm,
103 const std::string& data,
104 const std::string& extension_id,
105 const SignCallback& callback) {
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
107 ReadValidityAndInvalidateKey(extension_id,
108 public_key_spki_der,
109 base::Bind(&CheckValidityAndSign,
110 token_id,
111 public_key_spki_der,
112 hash_algorithm,
113 data,
114 callback,
115 browser_context_));
118 void PlatformKeysService::RegisterPublicKey(
119 const std::string& extension_id,
120 const std::string& public_key_spki_der,
121 const base::Callback<void(bool)>& callback) {
122 GetPlatformKeysOfExtension(
123 extension_id,
124 base::Bind(&PlatformKeysService::RegisterPublicKeyGotPlatformKeys,
125 weak_factory_.GetWeakPtr(),
126 extension_id,
127 public_key_spki_der,
128 callback));
131 void PlatformKeysService::ReadValidityAndInvalidateKey(
132 const std::string& extension_id,
133 const std::string& public_key_spki_der,
134 const base::Callback<void(bool)>& callback) {
135 GetPlatformKeysOfExtension(extension_id,
136 base::Bind(&PlatformKeysService::InvalidateKey,
137 weak_factory_.GetWeakPtr(),
138 extension_id,
139 public_key_spki_der,
140 callback));
143 void PlatformKeysService::GetPlatformKeysOfExtension(
144 const std::string& extension_id,
145 const GetPlatformKeysCallback& callback) {
146 state_store_->GetExtensionValue(
147 extension_id,
148 kStateStorePlatformKeys,
149 base::Bind(&PlatformKeysService::GotPlatformKeysOfExtension,
150 weak_factory_.GetWeakPtr(),
151 extension_id,
152 callback));
155 void PlatformKeysService::GenerateRSAKeyCallback(
156 const std::string& extension_id,
157 const GenerateKeyCallback& callback,
158 const std::string& public_key_spki_der,
159 const std::string& error_message) {
160 if (!error_message.empty()) {
161 callback.Run(std::string() /* no public key */, error_message);
162 return;
164 base::Callback<void(bool)> wrapped_callback(
165 base::Bind(&WrapGenerateKeyCallback, callback, public_key_spki_der));
166 RegisterPublicKey(extension_id, public_key_spki_der, wrapped_callback);
169 void PlatformKeysService::RegisterPublicKeyGotPlatformKeys(
170 const std::string& extension_id,
171 const std::string& public_key_spki_der,
172 const base::Callback<void(bool)>& callback,
173 scoped_ptr<base::ListValue> platform_keys) {
174 if (!platform_keys) {
175 LOG(ERROR) << "Error while reading the platform keys.";
176 callback.Run(false);
177 return;
180 scoped_ptr<base::StringValue> key_value(
181 GetPublicKeyValue(public_key_spki_der));
183 DCHECK(platform_keys->end() == platform_keys->Find(*key_value))
184 << "Keys are assumed to be generated and not to be registered multiple "
185 "times.";
186 platform_keys->Append(key_value.release());
188 state_store_->SetExtensionValue(
189 extension_id, kStateStorePlatformKeys, platform_keys.Pass());
190 callback.Run(true);
193 void PlatformKeysService::InvalidateKey(
194 const std::string& extension_id,
195 const std::string& public_key_spki_der,
196 const base::Callback<void(bool)>& callback,
197 scoped_ptr<base::ListValue> platform_keys) {
198 scoped_ptr<base::StringValue> key_value(
199 GetPublicKeyValue(public_key_spki_der));
201 size_t index = 0;
202 if (!platform_keys->Remove(*key_value, &index)) {
203 // The key is not found, so it's not valid to use it for signing.
204 callback.Run(false);
205 return;
208 state_store_->SetExtensionValue(
209 extension_id, kStateStorePlatformKeys, platform_keys.Pass());
210 callback.Run(true);
213 void PlatformKeysService::GotPlatformKeysOfExtension(
214 const std::string& extension_id,
215 const GetPlatformKeysCallback& callback,
216 scoped_ptr<base::Value> value) {
217 if (!value)
218 value.reset(new base::ListValue);
220 base::ListValue* keys = NULL;
221 if (!value->GetAsList(&keys)) {
222 LOG(ERROR) << "Found a value of wrong type.";
223 value.reset();
225 ignore_result(value.release());
226 callback.Run(make_scoped_ptr(keys));
229 } // namespace chromeos