OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" | 5 #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/callback_helpers.h" | |
9 #include "base/values.h" | 10 #include "base/values.h" |
10 #include "chrome/browser/chromeos/platform_keys/platform_keys.h" | 11 #include "chrome/browser/chromeos/platform_keys/platform_keys.h" |
11 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
12 #include "extensions/browser/state_store.h" | 13 #include "extensions/browser/state_store.h" |
13 #include "net/cert/x509_certificate.h" | 14 #include "net/cert/x509_certificate.h" |
14 | 15 |
15 using content::BrowserThread; | 16 using content::BrowserThread; |
16 | 17 |
17 namespace chromeos { | 18 namespace chromeos { |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 const char kErrorKeyNotAllowedForSigning[] = | 22 const char kErrorKeyNotAllowedForSigning[] = |
22 "This key is not allowed for signing. Either it was used for signing " | 23 "This key is not allowed for signing. Either it was used for signing " |
23 "before or it was not correctly generated."; | 24 "before or it was not correctly generated."; |
24 const char kStateStorePlatformKeys[] = "PlatformKeys"; | 25 const char kStateStorePlatformKeys[] = "PlatformKeys"; |
25 | 26 |
26 scoped_ptr<base::StringValue> GetPublicKeyValue( | 27 scoped_ptr<base::StringValue> GetPublicKeyValue( |
27 const std::string& public_key_spki_der) { | 28 const std::string& public_key_spki_der) { |
28 std::string public_key_spki_der_b64; | 29 std::string public_key_spki_der_b64; |
29 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64); | 30 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64); |
30 return make_scoped_ptr(new base::StringValue(public_key_spki_der_b64)); | 31 return make_scoped_ptr(new base::StringValue(public_key_spki_der_b64)); |
31 } | 32 } |
32 | 33 |
33 void RunGenerateKeyCallback( | |
34 const PlatformKeysService::GenerateKeyCallback& callback, | |
35 const std::string& public_key_spki_der) { | |
36 callback.Run(public_key_spki_der, std::string() /* no error */); | |
37 } | |
38 | |
39 // Callback used by |PlatformKeysService::Sign|. | |
40 // Is called with the old validity of |public_key_spki_der| (or false if an | |
41 // error occurred during reading the StateStore). If allowed, starts the actual | |
42 // signing operation which will call back |callback|. If not allowed, calls | |
43 // |callback| with an error. | |
44 void CheckValidityAndSign(const std::string& token_id, | |
45 scoped_ptr<platform_keys::SignRSAParams> params, | |
46 const PlatformKeysService::SignCallback& callback, | |
47 content::BrowserContext* browser_context, | |
48 bool key_is_valid) { | |
49 if (!key_is_valid) { | |
50 callback.Run(std::string() /* no signature */, | |
51 kErrorKeyNotAllowedForSigning); | |
52 return; | |
53 } | |
54 platform_keys::subtle::SignRSA(token_id, params.Pass(), callback, | |
55 browser_context); | |
56 } | |
57 | |
58 } // namespace | 34 } // namespace |
59 | 35 |
36 class PlatformKeysService::Task { | |
37 public: | |
38 Task() {} | |
39 virtual ~Task() {} | |
40 virtual void Start() = 0; | |
41 virtual bool IsDone() = 0; | |
42 | |
43 private: | |
44 DISALLOW_ASSIGN(Task); | |
45 }; | |
46 | |
47 class PlatformKeysService::PermissionUpdateTask : public Task { | |
48 public: | |
49 enum class State { | |
50 NOT_STARTED, | |
51 READ_PLATFORM_KEYS, | |
52 WRITE_UPDATE, | |
kaliamoorthi
2015/02/09 10:44:01
Not sure if you need so many states. There is just
pneubeck (no reviews)
2015/02/09 14:02:38
dropped the NOT_STARTED state (which was meant to
| |
53 DONE, | |
54 }; | |
55 | |
56 PermissionUpdateTask(const bool new_permission_value, | |
57 const std::string& public_key_spki_der, | |
58 const std::string& extension_id, | |
59 base::Callback<void(Task*)> callback, | |
60 PlatformKeysService* service) | |
61 : new_permission_value_(new_permission_value), | |
62 public_key_spki_der_(public_key_spki_der), | |
63 extension_id_(extension_id), | |
64 callback_(callback), | |
65 service_(service), | |
66 weak_factory_(this) {} | |
67 | |
68 ~PermissionUpdateTask() override {} | |
69 | |
70 void Start() override { | |
71 CHECK(state_ == State::NOT_STARTED); | |
72 Step(); | |
73 } | |
74 bool IsDone() override { return state_ == State::DONE; } | |
75 bool old_permission_value() { return old_permission_value_; } | |
76 | |
77 private: | |
78 void Step() { | |
79 CHECK(state_ != State::DONE); | |
80 state_ = next_state_; | |
81 switch (state_) { | |
82 case State::NOT_STARTED: | |
83 NOTREACHED(); | |
84 return; | |
85 case State::READ_PLATFORM_KEYS: | |
86 next_state_ = State::WRITE_UPDATE; | |
87 ReadPlatformKeys(); | |
88 return; | |
89 case State::WRITE_UPDATE: | |
90 next_state_ = State::DONE; | |
91 WriteUpdate(); | |
92 return; | |
93 case State::DONE: | |
94 if (!callback_.is_null()) { | |
95 // Make a local copy of the callback to run as it might be deleted | |
96 // during the Run(). | |
97 base::ResetAndReturn(&callback_).Run(this); | |
98 // |this| might be invalid now. | |
99 } | |
100 return; | |
101 } | |
102 } | |
103 | |
104 // Reads the PlatformKeys value from the extension's state store and calls | |
105 // back to GotPlatformKeys(). | |
106 void ReadPlatformKeys() { | |
107 service_->GetPlatformKeysOfExtension( | |
108 extension_id_, base::Bind(&PermissionUpdateTask::GotPlatformKeys, | |
109 weak_factory_.GetWeakPtr())); | |
110 } | |
111 | |
112 void GotPlatformKeys(scoped_ptr<base::ListValue> platform_keys) { | |
113 platform_keys_ = platform_keys.Pass(); | |
114 Step(); | |
115 } | |
116 | |
117 // Returns whether the extension has permission to use the key for signing | |
118 // according to the PlatformKeys value read from the extensions state store. | |
119 // Invalidates the key if it was found to be valid. | |
120 void WriteUpdate() { | |
121 scoped_ptr<base::StringValue> key_value( | |
122 GetPublicKeyValue(public_key_spki_der_)); | |
123 | |
124 base::ListValue::const_iterator it = platform_keys_->Find(*key_value); | |
125 old_permission_value_ = it != platform_keys_->end(); | |
126 if (old_permission_value_ == new_permission_value_) | |
127 return; | |
128 | |
129 if (new_permission_value_) | |
130 platform_keys_->Append(key_value.release()); | |
131 else | |
132 platform_keys_->Remove(*key_value, nullptr); | |
133 | |
134 service_->SetPlatformKeysOfExtension(extension_id_, platform_keys_.Pass()); | |
135 Step(); | |
136 } | |
137 | |
138 State state_ = State::NOT_STARTED; | |
139 State next_state_ = State::READ_PLATFORM_KEYS; | |
140 scoped_ptr<base::ListValue> platform_keys_; | |
141 bool old_permission_value_ = false; | |
142 | |
143 const bool new_permission_value_; | |
144 const std::string public_key_spki_der_; | |
145 const std::string extension_id_; | |
146 base::Callback<void(Task*)> callback_; | |
147 PlatformKeysService* const service_; | |
148 base::WeakPtrFactory<PermissionUpdateTask> weak_factory_; | |
149 | |
150 DISALLOW_COPY_AND_ASSIGN(PermissionUpdateTask); | |
151 }; | |
152 | |
153 class PlatformKeysService::SignTask : public Task { | |
154 public: | |
155 enum class State { | |
156 NOT_STARTED, | |
157 UPDATE_PERMISSION, | |
158 SIGN_OR_ABORT, | |
159 DONE, | |
160 }; | |
161 | |
162 // This Task will check the permissions of the extension with |extension_id| | |
163 // for the key identified by |public_key_spki_der|, then updates the | |
164 // permission to prevent any future signing operation of that extension using | |
165 // that same key. If the permission check was positive, it will actually sign | |
166 // |data| with the key and pass the signature to |callback|. | |
167 // If an error occurs, an error message is passed to |callback| instead. | |
168 SignTask(const std::string& token_id, | |
169 scoped_ptr<platform_keys::SignRSAParams> params, | |
170 const std::string& extension_id, | |
171 const SignCallback& callback, | |
172 PlatformKeysService* service) | |
173 : token_id_(token_id), | |
174 params_(params.Pass()), | |
175 extension_id_(extension_id), | |
176 callback_(callback), | |
177 service_(service), | |
178 weak_factory_(this) {} | |
179 ~SignTask() override {} | |
180 | |
181 void Start() override { | |
182 CHECK(state_ == State::NOT_STARTED); | |
183 Step(); | |
184 } | |
185 bool IsDone() override { return state_ == State::DONE; } | |
186 | |
187 private: | |
188 void Step() { | |
189 CHECK(state_ != State::DONE); | |
190 state_ = next_state_; | |
191 switch (state_) { | |
192 case State::NOT_STARTED: | |
193 NOTREACHED(); | |
194 return; | |
195 case State::UPDATE_PERMISSION: | |
196 next_state_ = State::SIGN_OR_ABORT; | |
197 UpdatePermission(); | |
198 return; | |
199 case State::SIGN_OR_ABORT: | |
200 next_state_ = State::DONE; | |
201 if (!service_->permission_check_enabled_ || | |
202 permission_update_->old_permission_value()) { | |
203 Sign(); | |
204 } else { | |
205 callback_.Run(std::string() /* no signature */, | |
206 kErrorKeyNotAllowedForSigning); | |
207 Step(); | |
208 } | |
209 return; | |
210 case State::DONE: | |
211 service_->TaskFinished(this); | |
212 // |this| might be invalid now. | |
213 return; | |
214 } | |
215 } | |
216 | |
217 // Reads the current permission of the extension with |extension_id_| for key | |
218 // |params_->public_key| and updates the permission to disable further | |
219 // signing operations with that key. | |
220 void UpdatePermission() { | |
221 permission_update_.reset(new PermissionUpdateTask( | |
kaliamoorthi
2015/02/09 10:44:01
Combining SignTask with PermissionUpdateTask can r
pneubeck (no reviews)
2015/02/09 14:02:38
PermissionUpdate will also be used independent of
| |
222 false /* new permission value */, params_->public_key(), extension_id_, | |
223 base::Bind(&SignTask::DidUpdatePermission, weak_factory_.GetWeakPtr()), | |
224 service_)); | |
225 permission_update_->Start(); | |
226 } | |
227 | |
228 void DidUpdatePermission(Task* /* task */) { Step(); } | |
229 | |
230 // Starts the actual signing operation and afterwards passes the signature (or | |
231 // error) to |callback_|. | |
232 void Sign() { | |
233 platform_keys::subtle::SignRSA( | |
234 token_id_, params_.Pass(), | |
235 base::Bind(&SignTask::DidSign, weak_factory_.GetWeakPtr()), | |
236 service_->browser_context_); | |
237 } | |
238 | |
239 void DidSign(const std::string& signature, const std::string& error_message) { | |
240 callback_.Run(signature, error_message); | |
241 Step(); | |
242 } | |
243 | |
244 State state_ = State::NOT_STARTED; | |
245 State next_state_ = State::UPDATE_PERMISSION; | |
246 scoped_ptr<base::ListValue> platform_keys_; | |
247 scoped_ptr<PermissionUpdateTask> permission_update_; | |
248 | |
249 const std::string token_id_; | |
250 scoped_ptr<platform_keys::SignRSAParams> params_; | |
251 const std::string extension_id_; | |
252 const SignCallback callback_; | |
253 PlatformKeysService* const service_; | |
254 base::WeakPtrFactory<SignTask> weak_factory_; | |
255 | |
256 DISALLOW_COPY_AND_ASSIGN(SignTask); | |
257 }; | |
258 | |
60 PlatformKeysService::PlatformKeysService( | 259 PlatformKeysService::PlatformKeysService( |
61 content::BrowserContext* browser_context, | 260 content::BrowserContext* browser_context, |
62 extensions::StateStore* state_store) | 261 extensions::StateStore* state_store) |
63 : browser_context_(browser_context), | 262 : browser_context_(browser_context), |
64 state_store_(state_store), | 263 state_store_(state_store), |
65 weak_factory_(this) { | 264 weak_factory_(this) { |
66 DCHECK(state_store); | 265 DCHECK(state_store); |
67 } | 266 } |
68 | 267 |
69 PlatformKeysService::~PlatformKeysService() { | 268 PlatformKeysService::~PlatformKeysService() { |
70 } | 269 } |
71 | 270 |
72 void PlatformKeysService::DisablePermissionCheckForTesting() { | 271 void PlatformKeysService::DisablePermissionCheckForTesting() { |
73 permission_check_enabled_ = false; | 272 permission_check_enabled_ = false; |
74 } | 273 } |
75 | 274 |
76 void PlatformKeysService::GenerateRSAKey(const std::string& token_id, | 275 void PlatformKeysService::GenerateRSAKey(const std::string& token_id, |
77 unsigned int modulus_length, | 276 unsigned int modulus_length, |
78 const std::string& extension_id, | 277 const std::string& extension_id, |
79 const GenerateKeyCallback& callback) { | 278 const GenerateKeyCallback& callback) { |
80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 279 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
81 | 280 |
82 platform_keys::subtle::GenerateRSAKey( | 281 platform_keys::subtle::GenerateRSAKey( |
83 token_id, | 282 token_id, modulus_length, |
84 modulus_length, | 283 base::Bind(&PlatformKeysService::GeneratedKey, weak_factory_.GetWeakPtr(), |
85 base::Bind(&PlatformKeysService::GenerateRSAKeyCallback, | 284 extension_id, callback), |
86 weak_factory_.GetWeakPtr(), | |
87 extension_id, | |
88 callback), | |
89 browser_context_); | 285 browser_context_); |
90 } | 286 } |
91 | 287 |
92 void PlatformKeysService::SignRSA( | 288 void PlatformKeysService::SignRSA( |
93 const std::string& token_id, | 289 const std::string& token_id, |
94 scoped_ptr<platform_keys::SignRSAParams> params, | 290 scoped_ptr<platform_keys::SignRSAParams> params, |
95 const std::string& extension_id, | 291 const std::string& extension_id, |
96 const SignCallback& callback) { | 292 const SignCallback& callback) { |
97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
98 ReadValidityAndInvalidateKey( | 294 StartOrQueueTask(make_scoped_ptr( |
99 extension_id, params->public_key(), | 295 new SignTask(token_id, params.Pass(), extension_id, callback, this))); |
100 base::Bind(&CheckValidityAndSign, token_id, base::Passed(¶ms), | |
101 callback, browser_context_)); | |
102 } | 296 } |
103 | 297 |
104 void PlatformKeysService::SelectClientCertificates( | 298 void PlatformKeysService::SelectClientCertificates( |
105 const platform_keys::ClientCertificateRequest& request, | 299 const platform_keys::ClientCertificateRequest& request, |
106 const std::string& extension_id, | 300 const std::string& extension_id, |
107 const SelectCertificatesCallback& callback) { | 301 const SelectCertificatesCallback& callback) { |
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
109 | 303 |
110 platform_keys::subtle::SelectClientCertificates( | 304 platform_keys::subtle::SelectClientCertificates( |
111 request, | 305 request, |
112 base::Bind(&PlatformKeysService::SelectClientCertificatesCallback, | 306 base::Bind(&PlatformKeysService::SelectClientCertificatesCallback, |
113 weak_factory_.GetWeakPtr(), extension_id, callback), | 307 weak_factory_.GetWeakPtr(), extension_id, callback), |
114 browser_context_); | 308 browser_context_); |
115 } | 309 } |
116 | 310 |
117 void PlatformKeysService::RegisterPublicKey( | 311 void PlatformKeysService::StartOrQueueTask(scoped_ptr<Task> task) { |
118 const std::string& extension_id, | 312 tasks_.push(make_linked_ptr(task.release())); |
119 const std::string& public_key_spki_der, | 313 if (tasks_.size() == 1) |
120 const base::Closure& callback) { | 314 tasks_.front()->Start(); |
121 GetPlatformKeysOfExtension( | |
122 extension_id, | |
123 base::Bind(&PlatformKeysService::RegisterPublicKeyGotPlatformKeys, | |
124 weak_factory_.GetWeakPtr(), | |
125 extension_id, | |
126 public_key_spki_der, | |
127 callback)); | |
128 } | 315 } |
129 | 316 |
130 void PlatformKeysService::ReadValidityAndInvalidateKey( | 317 void PlatformKeysService::TaskFinished(Task* task) { |
131 const std::string& extension_id, | 318 DCHECK(!tasks_.empty()); |
132 const std::string& public_key_spki_der, | 319 DCHECK(task == tasks_.front().get()); |
133 const base::Callback<void(bool)>& callback) { | 320 while (!tasks_.empty() && tasks_.front()->IsDone()) |
134 GetPlatformKeysOfExtension(extension_id, | 321 tasks_.pop(); |
135 base::Bind(&PlatformKeysService::InvalidateKey, | 322 |
136 weak_factory_.GetWeakPtr(), | 323 if (!tasks_.empty()) |
137 extension_id, | 324 tasks_.front()->Start(); |
138 public_key_spki_der, | |
139 callback)); | |
140 } | 325 } |
141 | 326 |
142 void PlatformKeysService::GetPlatformKeysOfExtension( | 327 void PlatformKeysService::GetPlatformKeysOfExtension( |
143 const std::string& extension_id, | 328 const std::string& extension_id, |
144 const GetPlatformKeysCallback& callback) { | 329 const GetPlatformKeysCallback& callback) { |
145 state_store_->GetExtensionValue( | 330 state_store_->GetExtensionValue( |
146 extension_id, kStateStorePlatformKeys, | 331 extension_id, kStateStorePlatformKeys, |
147 base::Bind(&PlatformKeysService::GotPlatformKeysOfExtension, | 332 base::Bind(&PlatformKeysService::GotPlatformKeysOfExtension, |
148 weak_factory_.GetWeakPtr(), extension_id, callback)); | 333 weak_factory_.GetWeakPtr(), extension_id, callback)); |
149 } | 334 } |
150 | 335 |
151 void PlatformKeysService::SetPlatformKeysOfExtension( | 336 void PlatformKeysService::SetPlatformKeysOfExtension( |
152 const std::string& extension_id, | 337 const std::string& extension_id, |
153 scoped_ptr<base::ListValue> platform_keys) { | 338 scoped_ptr<base::ListValue> platform_keys) { |
154 state_store_->SetExtensionValue(extension_id, kStateStorePlatformKeys, | 339 state_store_->SetExtensionValue(extension_id, kStateStorePlatformKeys, |
155 platform_keys.Pass()); | 340 platform_keys.Pass()); |
156 } | 341 } |
157 | 342 |
158 void PlatformKeysService::GenerateRSAKeyCallback( | 343 void PlatformKeysService::GeneratedKey(const std::string& extension_id, |
159 const std::string& extension_id, | 344 const GenerateKeyCallback& callback, |
160 const GenerateKeyCallback& callback, | 345 const std::string& public_key_spki_der, |
161 const std::string& public_key_spki_der, | 346 const std::string& error_message) { |
162 const std::string& error_message) { | |
163 if (!error_message.empty()) { | 347 if (!error_message.empty()) { |
164 callback.Run(std::string() /* no public key */, error_message); | 348 callback.Run(std::string() /* no public key */, error_message); |
165 return; | 349 return; |
166 } | 350 } |
167 base::Closure wrapped_callback( | 351 |
168 base::Bind(&RunGenerateKeyCallback, callback, public_key_spki_der)); | 352 StartOrQueueTask(make_scoped_ptr(new PermissionUpdateTask( |
169 RegisterPublicKey(extension_id, public_key_spki_der, wrapped_callback); | 353 true /* new permission value */, public_key_spki_der, extension_id, |
354 base::Bind(&PlatformKeysService::DidRegisterGeneratedKey, | |
355 base::Unretained(this), callback, public_key_spki_der), | |
356 this))); | |
357 } | |
358 | |
359 void PlatformKeysService::DidRegisterGeneratedKey( | |
360 const GenerateKeyCallback& callback, | |
361 const std::string& public_key_spki_der, | |
362 Task* task) { | |
363 callback.Run(public_key_spki_der, std::string() /* no error */); | |
364 TaskFinished(task); | |
170 } | 365 } |
171 | 366 |
172 void PlatformKeysService::SelectClientCertificatesCallback( | 367 void PlatformKeysService::SelectClientCertificatesCallback( |
173 const std::string& extension_id, | 368 const std::string& extension_id, |
174 const SelectCertificatesCallback& callback, | 369 const SelectCertificatesCallback& callback, |
175 scoped_ptr<net::CertificateList> matches, | 370 scoped_ptr<net::CertificateList> matches, |
176 const std::string& error_message) { | 371 const std::string& error_message) { |
177 if (permission_check_enabled_) | 372 if (permission_check_enabled_) |
178 matches->clear(); | 373 matches->clear(); |
179 | 374 |
180 // TODO(pneubeck): Remove all certs that the extension doesn't have access to. | 375 // TODO(pneubeck): Remove all certs that the extension doesn't have access to. |
181 callback.Run(matches.Pass(), error_message); | 376 callback.Run(matches.Pass(), error_message); |
182 } | 377 } |
183 | 378 |
184 void PlatformKeysService::RegisterPublicKeyGotPlatformKeys( | |
185 const std::string& extension_id, | |
186 const std::string& public_key_spki_der, | |
187 const base::Closure& callback, | |
188 scoped_ptr<base::ListValue> platform_keys) { | |
189 scoped_ptr<base::StringValue> key_value( | |
190 GetPublicKeyValue(public_key_spki_der)); | |
191 | |
192 DCHECK(platform_keys->end() == platform_keys->Find(*key_value)) | |
193 << "Keys are assumed to be generated and not to be registered multiple " | |
194 "times."; | |
195 platform_keys->Append(key_value.release()); | |
196 SetPlatformKeysOfExtension(extension_id, platform_keys.Pass()); | |
197 callback.Run(); | |
198 } | |
199 | |
200 void PlatformKeysService::InvalidateKey( | |
201 const std::string& extension_id, | |
202 const std::string& public_key_spki_der, | |
203 const base::Callback<void(bool)>& callback, | |
204 scoped_ptr<base::ListValue> platform_keys) { | |
205 scoped_ptr<base::StringValue> key_value( | |
206 GetPublicKeyValue(public_key_spki_der)); | |
207 | |
208 size_t index = 0; | |
209 // If the key is found in |platform_keys|, it's valid for the extension to use | |
210 // it for signing. | |
211 bool key_was_valid = platform_keys->Remove(*key_value, &index); | |
212 | |
213 if (key_was_valid) { | |
214 // Persist that the key is now invalid. | |
215 SetPlatformKeysOfExtension(extension_id, platform_keys.Pass()); | |
216 } | |
217 | |
218 if (permission_check_enabled_) { | |
219 // If permission checks are enabled, pass back the key permission (before | |
220 // it was removed above). | |
221 callback.Run(key_was_valid); | |
222 } else { | |
223 // Otherwise just allow signing with the key (which is enabled for testing | |
224 // only). | |
225 callback.Run(true); | |
226 } | |
227 } | |
228 | |
229 void PlatformKeysService::GotPlatformKeysOfExtension( | 379 void PlatformKeysService::GotPlatformKeysOfExtension( |
230 const std::string& extension_id, | 380 const std::string& extension_id, |
231 const GetPlatformKeysCallback& callback, | 381 const GetPlatformKeysCallback& callback, |
232 scoped_ptr<base::Value> value) { | 382 scoped_ptr<base::Value> value) { |
233 if (!value) | 383 if (!value) |
234 value.reset(new base::ListValue); | 384 value.reset(new base::ListValue); |
235 | 385 |
236 base::ListValue* keys = NULL; | 386 base::ListValue* keys = NULL; |
237 if (!value->GetAsList(&keys)) { | 387 if (!value->GetAsList(&keys)) { |
238 LOG(ERROR) << "Found a value of wrong type."; | 388 LOG(ERROR) << "Found a value of wrong type."; |
239 | 389 |
240 keys = new base::ListValue; | 390 keys = new base::ListValue; |
241 value.reset(keys); | 391 value.reset(keys); |
242 } | 392 } |
243 | 393 |
244 ignore_result(value.release()); | 394 ignore_result(value.release()); |
245 callback.Run(make_scoped_ptr(keys)); | 395 callback.Run(make_scoped_ptr(keys)); |
246 } | 396 } |
247 | 397 |
248 } // namespace chromeos | 398 } // namespace chromeos |
OLD | NEW |