| Index: chrome/browser/chromeos/platform_keys/platform_keys_service.cc
|
| diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_service.cc b/chrome/browser/chromeos/platform_keys/platform_keys_service.cc
|
| index 4f9eb1761d888a5fcf95cfc08cecab7a476c01ba..01abc1ae0661865d7d969651ad9cd91812623cc2 100644
|
| --- a/chrome/browser/chromeos/platform_keys/platform_keys_service.cc
|
| +++ b/chrome/browser/chromeos/platform_keys/platform_keys_service.cc
|
| @@ -17,18 +17,125 @@ using content::BrowserThread;
|
|
|
| namespace chromeos {
|
|
|
| +struct PlatformKeysService::KeyEntry {
|
| + // The base64-encoded DER of a X.509 Subject Public Key Info.
|
| + std::string spki_b64;
|
| +
|
| + // True if the key can be used once for singing.
|
| + // This permission is granted if an extension generated a key using the
|
| + // enterprise.platformKeys API, so that it can build a certification request..
|
| + // After the first signing operation this permission will be revoked.
|
| + bool sign_once = false;
|
| +
|
| + // True if the key can be used for signing an unlimited number of times.
|
| + // This permission is granted by the user or by policy to allow the extension
|
| + // to use the key for signing through the enterprise.platformKeys or
|
| + // platformKeys API.
|
| + // This permission is granted until revoked by the user or the policy.
|
| + bool sign_unlimited = false;
|
| +};
|
| +
|
| namespace {
|
|
|
| const char kErrorKeyNotAllowedForSigning[] =
|
| "This key is not allowed for signing. Either it was used for signing "
|
| "before or it was not correctly generated.";
|
| +
|
| +// The key at which platform key specific data is stored in each extension's
|
| +// state store.
|
| +// From older versions of ChromeOS, this key can hold a list of base64 and
|
| +// DER-encoded SPKIs. A key can be used for signing at most once if it is part
|
| +// of that list
|
| +// and removed from that list afterwards.
|
| +//
|
| +// The current format of data that is written to the PlatformKeys field is a
|
| +// list of serialized KeyEntry objects:
|
| +// { 'SPKI': string,
|
| +// 'signOnce': bool, // if not present, defaults to false
|
| +// 'signUnlimited': bool // if not present, defaults to false
|
| +// }
|
| +//
|
| +// Do not change this constant as clients will lose their existing state.
|
| const char kStateStorePlatformKeys[] = "PlatformKeys";
|
| +const char kStateStoreSPKI[] = "SPKI";
|
| +const char kStateStoreSignOnce[] = "signOnce";
|
| +const char kStateStoreSignUnlimited[] = "signUnlimited";
|
| +
|
| +scoped_ptr<PlatformKeysService::KeyEntries> KeyEntriesFromState(
|
| + const base::Value& state) {
|
| + scoped_ptr<PlatformKeysService::KeyEntries> new_entries(
|
| + new PlatformKeysService::KeyEntries);
|
| +
|
| + const base::ListValue* entries = nullptr;
|
| + if (!state.GetAsList(&entries)) {
|
| + LOG(ERROR) << "Found a state store of wrong type.";
|
| + return new_entries.Pass();
|
| + }
|
| + for (const base::Value* entry : *entries) {
|
| + if (!entry) {
|
| + LOG(ERROR) << "Found invalid NULL entry in PlatformKeys state store.";
|
| + continue;
|
| + }
|
| +
|
| + PlatformKeysService::KeyEntry new_entry;
|
| + const base::DictionaryValue* dict_entry = nullptr;
|
| + if (entry->GetAsString(&new_entry.spki_b64)) {
|
| + // This handles the case that the store contained a plain list of base64
|
| + // and DER-encoded SPKIs from an older version of ChromeOS.
|
| + new_entry.sign_once = true;
|
| + } else if (entry->GetAsDictionary(&dict_entry)) {
|
| + dict_entry->GetStringWithoutPathExpansion(kStateStoreSPKI,
|
| + &new_entry.spki_b64);
|
| + dict_entry->GetBooleanWithoutPathExpansion(kStateStoreSignOnce,
|
| + &new_entry.sign_once);
|
| + dict_entry->GetBooleanWithoutPathExpansion(kStateStoreSignUnlimited,
|
| + &new_entry.sign_unlimited);
|
| + } else {
|
| + LOG(ERROR) << "Found invalid entry of type " << entry->GetType()
|
| + << " in PlatformKeys state store.";
|
| + continue;
|
| + }
|
| + new_entries->push_back(new_entry);
|
| + }
|
| + return new_entries.Pass();
|
| +}
|
| +
|
| +scoped_ptr<base::ListValue> KeyEntriesToState(
|
| + const PlatformKeysService::KeyEntries& entries) {
|
| + scoped_ptr<base::ListValue> new_state(new base::ListValue);
|
| + for (const PlatformKeysService::KeyEntry& entry : entries) {
|
| + // Drop entries that the extension doesn't have any permissions for anymore.
|
| + if (!entry.sign_once && !entry.sign_unlimited)
|
| + continue;
|
| +
|
| + scoped_ptr<base::DictionaryValue> new_entry(new base::DictionaryValue);
|
| + new_entry->SetStringWithoutPathExpansion(kStateStoreSPKI, entry.spki_b64);
|
| + // Omit writing default values, namely |false|.
|
| + if (entry.sign_once) {
|
| + new_entry->SetBooleanWithoutPathExpansion(kStateStoreSignOnce,
|
| + entry.sign_once);
|
| + }
|
| + if (entry.sign_unlimited) {
|
| + new_entry->SetBooleanWithoutPathExpansion(kStateStoreSignUnlimited,
|
| + entry.sign_unlimited);
|
| + }
|
| + new_state->Append(new_entry.release());
|
| + }
|
| + return new_state.Pass();
|
| +}
|
|
|
| -scoped_ptr<base::StringValue> GetPublicKeyValue(
|
| - const std::string& public_key_spki_der) {
|
| - std::string public_key_spki_der_b64;
|
| - base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
|
| - return make_scoped_ptr(new base::StringValue(public_key_spki_der_b64));
|
| +// Searches |platform_keys| for an entry for |public_key_spki_der_b64|. If found
|
| +// returns a pointer to it, otherwise returns null.
|
| +PlatformKeysService::KeyEntry* GetMatchingEntry(
|
| + const std::string& public_key_spki_der_b64,
|
| + PlatformKeysService::KeyEntries* platform_keys) {
|
| + for (PlatformKeysService::KeyEntry& entry : *platform_keys) {
|
| + // For every ASN.1 value there is exactly one DER encoding, so it is fine to
|
| + // compare the DER (or its base64 encoding).
|
| + if (entry.spki_b64 == public_key_spki_der_b64)
|
| + return &entry;
|
| + }
|
| + return nullptr;
|
| }
|
|
|
| } // namespace
|
| @@ -55,14 +162,16 @@ class PlatformKeysService::PermissionUpdateTask : public Task {
|
| // Creates a task that reads the current permission for an extension to access
|
| // a certain key. Afterwards it updates and persists the permission to the new
|
| // value |new_permission_value|. |callback| will be run after the permission
|
| - // was persisted. The old permission value is then accessible through
|
| - // old_permission_value().
|
| - PermissionUpdateTask(const bool new_permission_value,
|
| + // was persisted. The old permission values are then available through
|
| + // old_key_entry().
|
| + PermissionUpdateTask(const SignPermission permission,
|
| + const bool new_permission_value,
|
| const std::string& public_key_spki_der,
|
| const std::string& extension_id,
|
| base::Callback<void(Task*)> callback,
|
| PlatformKeysService* service)
|
| - : new_permission_value_(new_permission_value),
|
| + : permission_(permission),
|
| + new_permission_value_(new_permission_value),
|
| public_key_spki_der_(public_key_spki_der),
|
| extension_id_(extension_id),
|
| callback_(callback),
|
| @@ -78,9 +187,9 @@ class PlatformKeysService::PermissionUpdateTask : public Task {
|
|
|
| bool IsDone() override { return next_step_ == Step::DONE; }
|
|
|
| - // The original permission value before setting the new value
|
| - // |new_permission_value|.
|
| - bool old_permission_value() { return old_permission_value_; }
|
| + // The old key entry with the old permissions before setting |permission| to
|
| + // the new value |new_permission_value|.
|
| + const KeyEntry& old_key_entry() { return old_key_entry_; }
|
|
|
| private:
|
| void DoStep() {
|
| @@ -113,38 +222,59 @@ class PlatformKeysService::PermissionUpdateTask : public Task {
|
| weak_factory_.GetWeakPtr()));
|
| }
|
|
|
| - void GotPlatformKeys(scoped_ptr<base::ListValue> platform_keys) {
|
| + void GotPlatformKeys(scoped_ptr<KeyEntries> platform_keys) {
|
| platform_keys_ = platform_keys.Pass();
|
| DoStep();
|
| }
|
|
|
| - // Returns whether the extension has permission to use the key for signing
|
| - // according to the PlatformKeys value read from the extensions state store.
|
| - // Invalidates the key if it was found to be valid.
|
| + // Persists the existing KeyEntry in |old_key_entry_|, updates the entry with
|
| + // the new permission and persists it to the extension's state store if it was
|
| + // changed.
|
| void WriteUpdate() {
|
| - scoped_ptr<base::StringValue> key_value(
|
| - GetPublicKeyValue(public_key_spki_der_));
|
| -
|
| - base::ListValue::const_iterator it = platform_keys_->Find(*key_value);
|
| - old_permission_value_ = it != platform_keys_->end();
|
| - if (old_permission_value_ == new_permission_value_)
|
| - return;
|
| -
|
| - if (new_permission_value_)
|
| - platform_keys_->Append(key_value.release());
|
| - else
|
| - platform_keys_->Remove(*key_value, nullptr);
|
| + DCHECK(platform_keys_);
|
| +
|
| + std::string public_key_spki_der_b64;
|
| + base::Base64Encode(public_key_spki_der_, &public_key_spki_der_b64);
|
| +
|
| + KeyEntry* matching_entry =
|
| + GetMatchingEntry(public_key_spki_der_b64, platform_keys_.get());
|
| +
|
| + if (!matching_entry) {
|
| + platform_keys_->push_back(KeyEntry());
|
| + matching_entry = &platform_keys_->back();
|
| + matching_entry->spki_b64 = public_key_spki_der_b64;
|
| + } else if (permission_ == SignPermission::ONCE && new_permission_value_) {
|
| + // The one-time sign permission is supposed to be granted once per key
|
| + // during generation. Generated keys should be unique and thus this case
|
| + // should never occur.
|
| + NOTREACHED() << "Requested one-time sign permission on existing key.";
|
| + }
|
| + old_key_entry_ = *matching_entry;
|
| +
|
| + bool* permission_value = nullptr;
|
| + switch (permission_) {
|
| + case SignPermission::ONCE:
|
| + permission_value = &matching_entry->sign_once;
|
| + break;
|
| + case SignPermission::UNLIMITED:
|
| + permission_value = &matching_entry->sign_unlimited;
|
| + break;
|
| + }
|
|
|
| - service_->SetPlatformKeysOfExtension(extension_id_, platform_keys_.Pass());
|
| + if (*permission_value != new_permission_value_) {
|
| + *permission_value = new_permission_value_;
|
| + service_->SetPlatformKeysOfExtension(extension_id_, *platform_keys_);
|
| + }
|
| }
|
|
|
| Step next_step_ = Step::READ_PLATFORM_KEYS;
|
| - scoped_ptr<base::ListValue> platform_keys_;
|
| - bool old_permission_value_ = false;
|
| + KeyEntry old_key_entry_;
|
|
|
| + const SignPermission permission_;
|
| const bool new_permission_value_;
|
| const std::string public_key_spki_der_;
|
| const std::string extension_id_;
|
| + scoped_ptr<KeyEntries> platform_keys_;
|
| base::Callback<void(Task*)> callback_;
|
| PlatformKeysService* const service_;
|
| base::WeakPtrFactory<PermissionUpdateTask> weak_factory_;
|
| @@ -198,17 +328,21 @@ class PlatformKeysService::SignTask : public Task {
|
| next_step_ = Step::SIGN_OR_ABORT;
|
| UpdatePermission();
|
| return;
|
| - case Step::SIGN_OR_ABORT:
|
| + case Step::SIGN_OR_ABORT: {
|
| next_step_ = Step::DONE;
|
| - if (!service_->permission_check_enabled_ ||
|
| - permission_update_->old_permission_value()) {
|
| + bool sign_granted = permission_update_->old_key_entry().sign_once ||
|
| + permission_update_->old_key_entry().sign_unlimited;
|
| + if (sign_granted) {
|
| Sign();
|
| } else {
|
| - callback_.Run(std::string() /* no signature */,
|
| - kErrorKeyNotAllowedForSigning);
|
| + if (!callback_.is_null()) {
|
| + callback_.Run(std::string() /* no signature */,
|
| + kErrorKeyNotAllowedForSigning);
|
| + }
|
| DoStep();
|
| }
|
| return;
|
| + }
|
| case Step::DONE:
|
| service_->TaskFinished(this);
|
| // |this| might be invalid now.
|
| @@ -221,7 +355,8 @@ class PlatformKeysService::SignTask : public Task {
|
| // signing operations with that key.
|
| void UpdatePermission() {
|
| permission_update_.reset(new PermissionUpdateTask(
|
| - false /* new permission value */, public_key_, extension_id_,
|
| + SignPermission::ONCE, false /* new permission value */, public_key_,
|
| + extension_id_,
|
| base::Bind(&SignTask::DidUpdatePermission, weak_factory_.GetWeakPtr()),
|
| service_));
|
| permission_update_->Start();
|
| @@ -251,7 +386,7 @@ class PlatformKeysService::SignTask : public Task {
|
| }
|
|
|
| Step next_step_ = Step::UPDATE_PERMISSION;
|
| - scoped_ptr<base::ListValue> platform_keys_;
|
| + scoped_ptr<KeyEntries> platform_keys_;
|
| scoped_ptr<PermissionUpdateTask> permission_update_;
|
|
|
| const std::string token_id_;
|
| @@ -271,6 +406,213 @@ class PlatformKeysService::SignTask : public Task {
|
| DISALLOW_COPY_AND_ASSIGN(SignTask);
|
| };
|
|
|
| +class PlatformKeysService::SelectTask : public Task {
|
| + public:
|
| + enum class Step {
|
| + GET_MATCHING_CERTS,
|
| + SELECT_CERTS,
|
| + READ_PLATFORM_KEYS,
|
| + UPDATE_PERMISSION,
|
| + FILTER_BY_PERMISSIONS,
|
| + DONE,
|
| + };
|
| +
|
| + // This task determines all known client certs matching |request|. If
|
| + // |interactive| is true, calls |service->select_delegate_->Select()| to
|
| + // select a cert from all matches. The extension with |extension_id| will be
|
| + // granted unlimited sign permission for the selected cert.
|
| + // Finally, either the selection or, if |interactive| is false, matching certs
|
| + // that the extension has permission for are passed to |callback|.
|
| + SelectTask(const platform_keys::ClientCertificateRequest& request,
|
| + bool interactive,
|
| + const std::string& extension_id,
|
| + const SelectCertificatesCallback& callback,
|
| + PlatformKeysService* service)
|
| + : request_(request),
|
| + interactive_(interactive),
|
| + extension_id_(extension_id),
|
| + callback_(callback),
|
| + service_(service),
|
| + weak_factory_(this) {}
|
| + ~SelectTask() override {}
|
| +
|
| + void Start() override {
|
| + CHECK(next_step_ == Step::GET_MATCHING_CERTS);
|
| + DoStep();
|
| + }
|
| + bool IsDone() override { return next_step_ == Step::DONE; }
|
| +
|
| + private:
|
| + void DoStep() {
|
| + switch (next_step_) {
|
| + case Step::GET_MATCHING_CERTS:
|
| + if (interactive_)
|
| + next_step_ = Step::SELECT_CERTS;
|
| + else // Skip SelectCerts and UpdatePermission if not interactive.
|
| + next_step_ = Step::READ_PLATFORM_KEYS;
|
| + GetMatchingCerts();
|
| + return;
|
| + case Step::SELECT_CERTS:
|
| + next_step_ = Step::UPDATE_PERMISSION;
|
| + SelectCerts();
|
| + return;
|
| + case Step::UPDATE_PERMISSION:
|
| + next_step_ = Step::READ_PLATFORM_KEYS;
|
| + UpdatePermission();
|
| + return;
|
| + case Step::READ_PLATFORM_KEYS:
|
| + next_step_ = Step::FILTER_BY_PERMISSIONS;
|
| + ReadPlatformKeys();
|
| + return;
|
| + case Step::FILTER_BY_PERMISSIONS:
|
| + next_step_ = Step::DONE;
|
| + FilterSelectionByPermission();
|
| + return;
|
| + case Step::DONE:
|
| + service_->TaskFinished(this);
|
| + // |this| might be invalid now.
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // Retrieves all certificates matching |request_|. Will call back to
|
| + // |GotMatchingCerts()|.
|
| + void GetMatchingCerts() {
|
| + platform_keys::subtle::SelectClientCertificates(
|
| + request_,
|
| + base::Bind(&SelectTask::GotMatchingCerts, weak_factory_.GetWeakPtr()),
|
| + service_->browser_context_);
|
| + }
|
| +
|
| + // If the certificate request could be processed successfully, |matches| will
|
| + // contain the list of matching certificates (maybe empty) and |error_message|
|
| + // will be empty. If an error occurred, |matches| will be null and
|
| + // |error_message| contain an error message.
|
| + void GotMatchingCerts(scoped_ptr<net::CertificateList> matches,
|
| + const std::string& error_message) {
|
| + if (!error_message.empty()) {
|
| + next_step_ = Step::DONE;
|
| + callback_.Run(nullptr /* no certificates */, error_message);
|
| + DoStep();
|
| + return;
|
| + }
|
| + matches_.swap(*matches);
|
| + DoStep();
|
| + }
|
| +
|
| + // Calls |service_->select_delegate_->Select()| to select a cert from
|
| + // |matches_|, which will be stored in |selected_cert_|.
|
| + // Will call back to |GotSelection()|.
|
| + void SelectCerts() {
|
| + CHECK(interactive_);
|
| + if (matches_.empty()) {
|
| + // Don't show a select dialog if no certificate is matching.
|
| + DoStep();
|
| + return;
|
| + }
|
| + service_->select_delegate_->Select(
|
| + extension_id_, matches_,
|
| + base::Bind(&SelectTask::GotSelection, base::Unretained(this)));
|
| + }
|
| +
|
| + // Will be called by |SelectCerts()| with the selected cert or null if no cert
|
| + // was selected.
|
| + void GotSelection(scoped_refptr<net::X509Certificate> selected_cert) {
|
| + selected_cert_ = selected_cert;
|
| + DoStep();
|
| + }
|
| +
|
| + // Updates the extension's state store about unlimited sign permission for the
|
| + // selected cert. Does nothing if no cert was selected.
|
| + // Will call back to |DidUpdatePermission()|.
|
| + void UpdatePermission() {
|
| + CHECK(interactive_);
|
| + if (!selected_cert_) {
|
| + DoStep();
|
| + return;
|
| + }
|
| + const std::string public_key_spki_der(
|
| + platform_keys::GetSubjectPublicKeyInfo(selected_cert_));
|
| + permission_update_.reset(new PermissionUpdateTask(
|
| + SignPermission::UNLIMITED, true /* new permission value */,
|
| + public_key_spki_der, extension_id_,
|
| + base::Bind(&SelectTask::DidUpdatePermission, base::Unretained(this)),
|
| + service_));
|
| + permission_update_->Start();
|
| + }
|
| +
|
| + void DidUpdatePermission(Task* /* task */) { DoStep(); }
|
| +
|
| + // Reads the PlatformKeys value from the extension's state store and calls
|
| + // back to GotPlatformKeys().
|
| + void ReadPlatformKeys() {
|
| + service_->GetPlatformKeysOfExtension(
|
| + extension_id_,
|
| + base::Bind(&SelectTask::GotPlatformKeys, weak_factory_.GetWeakPtr()));
|
| + }
|
| +
|
| + void GotPlatformKeys(scoped_ptr<KeyEntries> platform_keys) {
|
| + platform_keys_ = platform_keys.Pass();
|
| + DoStep();
|
| + }
|
| +
|
| + // Filters from all matches (if not interactive) or from the selection (if
|
| + // interactive), the certificates that the extension has unlimited sign
|
| + // permission for. Passes the filtered certs to |callback_|.
|
| + void FilterSelectionByPermission() {
|
| + scoped_ptr<net::CertificateList> selection(new net::CertificateList);
|
| + if (interactive_) {
|
| + if (selected_cert_)
|
| + selection->push_back(selected_cert_);
|
| + } else {
|
| + selection->assign(matches_.begin(), matches_.end());
|
| + }
|
| +
|
| + scoped_ptr<net::CertificateList> filtered_certs(new net::CertificateList);
|
| + for (scoped_refptr<net::X509Certificate> selected_cert : *selection) {
|
| + const std::string public_key_spki_der(
|
| + platform_keys::GetSubjectPublicKeyInfo(selected_cert));
|
| + std::string public_key_spki_der_b64;
|
| + base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
|
| +
|
| + KeyEntry* matching_entry =
|
| + GetMatchingEntry(public_key_spki_der_b64, platform_keys_.get());
|
| + if (!matching_entry || !matching_entry->sign_unlimited)
|
| + continue;
|
| +
|
| + filtered_certs->push_back(selected_cert);
|
| + }
|
| + // Note: In the interactive case this should have filtered exactly the
|
| + // one selected cert. Checking the permissions again is not striclty
|
| + // necessary but this ensures that the permissions were updated correctly.
|
| + CHECK(!selected_cert_ || (filtered_certs->size() == 1 &&
|
| + filtered_certs->front() == selected_cert_));
|
| + callback_.Run(filtered_certs.Pass(), std::string() /* no error */);
|
| + DoStep();
|
| + }
|
| +
|
| + Step next_step_ = Step::GET_MATCHING_CERTS;
|
| + scoped_ptr<KeyEntries> platform_keys_;
|
| + scoped_ptr<PermissionUpdateTask> permission_update_;
|
| +
|
| + net::CertificateList matches_;
|
| + scoped_refptr<net::X509Certificate> selected_cert_;
|
| + platform_keys::ClientCertificateRequest request_;
|
| + const bool interactive_;
|
| + const std::string extension_id_;
|
| + const SelectCertificatesCallback callback_;
|
| + PlatformKeysService* const service_;
|
| + base::WeakPtrFactory<SelectTask> weak_factory_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SelectTask);
|
| +};
|
| +
|
| +PlatformKeysService::SelectDelegate::SelectDelegate() {
|
| +}
|
| +
|
| +PlatformKeysService::SelectDelegate::~SelectDelegate() {
|
| +}
|
| +
|
| PlatformKeysService::PlatformKeysService(
|
| content::BrowserContext* browser_context,
|
| extensions::StateStore* state_store)
|
| @@ -283,8 +625,22 @@ PlatformKeysService::PlatformKeysService(
|
| PlatformKeysService::~PlatformKeysService() {
|
| }
|
|
|
| -void PlatformKeysService::DisablePermissionCheckForTesting() {
|
| - permission_check_enabled_ = false;
|
| +void PlatformKeysService::SetSelectDelegate(
|
| + scoped_ptr<SelectDelegate> delegate) {
|
| + select_delegate_ = delegate.Pass();
|
| +}
|
| +
|
| +void PlatformKeysService::GrantUnlimitedSignPermission(
|
| + const std::string& extension_id,
|
| + scoped_refptr<net::X509Certificate> cert) {
|
| + const std::string public_key_spki_der(
|
| + platform_keys::GetSubjectPublicKeyInfo(cert));
|
| +
|
| + StartOrQueueTask(make_scoped_ptr(new PermissionUpdateTask(
|
| + SignPermission::UNLIMITED, true /* new permission value */,
|
| + public_key_spki_der, extension_id,
|
| + base::Bind(&PlatformKeysService::TaskFinished, base::Unretained(this)),
|
| + this)));
|
| }
|
|
|
| void PlatformKeysService::GenerateRSAKey(const std::string& token_id,
|
| @@ -326,15 +682,12 @@ void PlatformKeysService::SignRSAPKCS1Raw(const std::string& token_id,
|
|
|
| void PlatformKeysService::SelectClientCertificates(
|
| const platform_keys::ClientCertificateRequest& request,
|
| + bool interactive,
|
| const std::string& extension_id,
|
| const SelectCertificatesCallback& callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - platform_keys::subtle::SelectClientCertificates(
|
| - request,
|
| - base::Bind(&PlatformKeysService::SelectClientCertificatesCallback,
|
| - weak_factory_.GetWeakPtr(), extension_id, callback),
|
| - browser_context_);
|
| + StartOrQueueTask(make_scoped_ptr(
|
| + new SelectTask(request, interactive, extension_id, callback, this)));
|
| }
|
|
|
| void PlatformKeysService::StartOrQueueTask(scoped_ptr<Task> task) {
|
| @@ -367,9 +720,9 @@ void PlatformKeysService::GetPlatformKeysOfExtension(
|
|
|
| void PlatformKeysService::SetPlatformKeysOfExtension(
|
| const std::string& extension_id,
|
| - scoped_ptr<base::ListValue> platform_keys) {
|
| + const KeyEntries& platform_keys) {
|
| state_store_->SetExtensionValue(extension_id, kStateStorePlatformKeys,
|
| - platform_keys.Pass());
|
| + KeyEntriesToState(platform_keys));
|
| }
|
|
|
| void PlatformKeysService::GeneratedKey(const std::string& extension_id,
|
| @@ -382,7 +735,8 @@ void PlatformKeysService::GeneratedKey(const std::string& extension_id,
|
| }
|
|
|
| StartOrQueueTask(make_scoped_ptr(new PermissionUpdateTask(
|
| - true /* new permission value */, public_key_spki_der, extension_id,
|
| + SignPermission::ONCE, true /* new permission value */,
|
| + public_key_spki_der, extension_id,
|
| base::Bind(&PlatformKeysService::RegisteredGeneratedKey,
|
| base::Unretained(this), callback, public_key_spki_der),
|
| this)));
|
| @@ -396,35 +750,16 @@ void PlatformKeysService::RegisteredGeneratedKey(
|
| TaskFinished(task);
|
| }
|
|
|
| -void PlatformKeysService::SelectClientCertificatesCallback(
|
| - const std::string& extension_id,
|
| - const SelectCertificatesCallback& callback,
|
| - scoped_ptr<net::CertificateList> matches,
|
| - const std::string& error_message) {
|
| - if (permission_check_enabled_)
|
| - matches->clear();
|
| -
|
| - // TODO(pneubeck): Remove all certs that the extension doesn't have access to.
|
| - callback.Run(matches.Pass(), error_message);
|
| -}
|
|
|
| void PlatformKeysService::GotPlatformKeysOfExtension(
|
| const std::string& extension_id,
|
| const GetPlatformKeysCallback& callback,
|
| scoped_ptr<base::Value> value) {
|
| - if (!value)
|
| - value.reset(new base::ListValue);
|
| -
|
| - base::ListValue* keys = NULL;
|
| - if (!value->GetAsList(&keys)) {
|
| - LOG(ERROR) << "Found a value of wrong type.";
|
| -
|
| - keys = new base::ListValue;
|
| - value.reset(keys);
|
| - }
|
| + scoped_ptr<KeyEntries> key_entries(new KeyEntries);
|
| + if (value)
|
| + key_entries = KeyEntriesFromState(*value);
|
|
|
| - ignore_result(value.release());
|
| - callback.Run(make_scoped_ptr(keys));
|
| + callback.Run(key_entries.Pass());
|
| }
|
|
|
| } // namespace chromeos
|
|
|