Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(875)

Unified Diff: net/cert/internal/cert_issuer_source_collection.cc

Issue 2126803004: WIP: NSS trust store integration for path builder. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cert-command-line-path-builder-add_certpathbuilder
Patch Set: . Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/cert/internal/cert_issuer_source_collection.cc
diff --git a/net/cert/internal/cert_issuer_source_collection.cc b/net/cert/internal/cert_issuer_source_collection.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6be9856bd32abbfbd64e8beab349a0e6ca26bde2
--- /dev/null
+++ b/net/cert/internal/cert_issuer_source_collection.cc
@@ -0,0 +1,145 @@
+// Copyright 2016 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 "net/cert/internal/cert_issuer_source_collection.h"
+
+#include <unordered_map>
+
+#include "base/bind.h"
+#include "net/cert/internal/parsed_certificate.h"
+
+namespace net {
+
+namespace {
+
+using RequestSet =
+ std::unordered_map<CertIssuerSource::Request*,
+ std::unique_ptr<CertIssuerSource::Request>>;
+
+class CollectionRequest : public CertIssuerSource::Request {
+ public:
+ explicit CollectionRequest(
+ const CertIssuerSource::IssuerCallback& issuers_callback);
+ ~CollectionRequest() override;
+
+ // CertIssuerSource::Request implementation.
+ CompletionStatus GetNext(scoped_refptr<ParsedCertificate>* out_cert) override;
+
+ void MakeRequest(scoped_refptr<ParsedCertificate> cert,
+ CertIssuerSource* source);
+ bool has_requests() const {
+ return !pending_requests_.empty() || !ready_requests_.empty();
+ }
+
+ private:
+ void OnAsyncGetIssuersOf(CertIssuerSource::Request* req);
+
+ CertIssuerSource::IssuerCallback issuers_callback_;
+
+ RequestSet pending_requests_;
+ RequestSet ready_requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(CollectionRequest);
+};
+
+CollectionRequest::CollectionRequest(
+ const CertIssuerSource::IssuerCallback& issuers_callback)
+ : issuers_callback_(issuers_callback) {}
+
+CollectionRequest::~CollectionRequest() = default;
+
+CompletionStatus CollectionRequest::GetNext(
+ scoped_refptr<ParsedCertificate>* out_cert) {
+ while (!ready_requests_.empty()) {
+ auto it = ready_requests_.begin();
+ CompletionStatus status = it->second->GetNext(out_cert);
+ if (status == CompletionStatus::ASYNC) {
+ // This Request has no more results ready, but isn't done yet. Move it
+ // back to the pending list.
+ pending_requests_[it->first] = std::move(it->second);
+ ready_requests_.erase(it);
+ } else if (!*out_cert) {
+ // This Request is done, remove it.
+ ready_requests_.erase(it);
+ } else {
+ // This Request returned a result, pass it on.
+ return CompletionStatus::SYNC;
+ }
+ // No result from that Request, loop around try another.
+ }
+
+ *out_cert = nullptr;
+ if (!pending_requests_.empty()) {
+ // No results available at the moment, but there are still pending Requests.
+ return CompletionStatus::ASYNC;
+ }
+
+ // All Requests are complete.
+ return CompletionStatus::SYNC;
+}
+
+void CollectionRequest::MakeRequest(scoped_refptr<ParsedCertificate> cert,
+ CertIssuerSource* source) {
+ std::unique_ptr<CertIssuerSource::Request> req;
+ source->AsyncGetIssuersOf(std::move(cert),
+ base::Bind(&CollectionRequest::OnAsyncGetIssuersOf,
+ base::Unretained(this)),
+ &req);
+ if (req) {
+ CertIssuerSource::Request* req_ptr = req.get();
+ pending_requests_[req_ptr] = std::move(req);
+ }
+}
+
+void CollectionRequest::OnAsyncGetIssuersOf(CertIssuerSource::Request* req) {
+ bool client_waiting_for_callback = ready_requests_.empty();
+ // Find the request which just returned some results and move it to the ready
+ // list, if it isn't there already.
+ auto it = pending_requests_.find(req);
+ if (it != pending_requests_.end()) {
+ ready_requests_[it->first] = std::move(it->second);
+ pending_requests_.erase(it);
+ // Notify the client that results are now available.
+ if (client_waiting_for_callback)
+ issuers_callback_.Run(this);
+ } else {
+ // If it wasn't in the pending requests, it must already be in the ready
+ // requests.
+ DCHECK(ready_requests_.count(req));
+ }
+}
+
+} // namespace
+
+CertIssuerSourceCollection::CertIssuerSourceCollection() = default;
+CertIssuerSourceCollection::~CertIssuerSourceCollection() = default;
+
+void CertIssuerSourceCollection::AddSource(CertIssuerSource* source) {
+ sources_.push_back(source);
+}
+
+void CertIssuerSourceCollection::SyncGetIssuersOf(
+ const ParsedCertificate* cert,
+ ParsedCertificateList* issuers) {
+ for (CertIssuerSource* source : sources_)
+ source->SyncGetIssuersOf(cert, issuers);
+}
+
+void CertIssuerSourceCollection::AsyncGetIssuersOf(
+ scoped_refptr<ParsedCertificate> cert,
+ const IssuerCallback& issuers_callback,
+ std::unique_ptr<Request>* out_req) {
+ std::unique_ptr<CollectionRequest> req(
+ new CollectionRequest(issuers_callback));
+
+ for (CertIssuerSource* source : sources_)
+ req->MakeRequest(cert, source);
+
+ if (req->has_requests())
+ *out_req = std::move(req);
+ else
+ out_req->reset();
+}
+
+} // namespace net
« no previous file with comments | « net/cert/internal/cert_issuer_source_collection.h ('k') | net/cert/internal/cert_issuer_source_collection_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698