OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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. |
| 4 |
| 5 #include "net/cert/internal/cert_issuer_source_collection.h" |
| 6 |
| 7 #include <unordered_map> |
| 8 |
| 9 #include "base/bind.h" |
| 10 #include "net/cert/internal/parsed_certificate.h" |
| 11 |
| 12 namespace net { |
| 13 |
| 14 namespace { |
| 15 |
| 16 using RequestSet = |
| 17 std::unordered_map<CertIssuerSource::Request*, |
| 18 std::unique_ptr<CertIssuerSource::Request>>; |
| 19 |
| 20 class CollectionRequest : public CertIssuerSource::Request { |
| 21 public: |
| 22 explicit CollectionRequest( |
| 23 const CertIssuerSource::IssuerCallback& issuers_callback); |
| 24 ~CollectionRequest() override; |
| 25 |
| 26 // CertIssuerSource::Request implementation. |
| 27 CompletionStatus GetNext(scoped_refptr<ParsedCertificate>* out_cert) override; |
| 28 |
| 29 void MakeRequest(scoped_refptr<ParsedCertificate> cert, |
| 30 CertIssuerSource* source); |
| 31 bool has_requests() const { |
| 32 return !pending_requests_.empty() || !ready_requests_.empty(); |
| 33 } |
| 34 |
| 35 private: |
| 36 void OnAsyncGetIssuersOf(CertIssuerSource::Request* req); |
| 37 |
| 38 CertIssuerSource::IssuerCallback issuers_callback_; |
| 39 |
| 40 RequestSet pending_requests_; |
| 41 RequestSet ready_requests_; |
| 42 |
| 43 DISALLOW_COPY_AND_ASSIGN(CollectionRequest); |
| 44 }; |
| 45 |
| 46 CollectionRequest::CollectionRequest( |
| 47 const CertIssuerSource::IssuerCallback& issuers_callback) |
| 48 : issuers_callback_(issuers_callback) {} |
| 49 |
| 50 CollectionRequest::~CollectionRequest() = default; |
| 51 |
| 52 CompletionStatus CollectionRequest::GetNext( |
| 53 scoped_refptr<ParsedCertificate>* out_cert) { |
| 54 while (!ready_requests_.empty()) { |
| 55 auto it = ready_requests_.begin(); |
| 56 CompletionStatus status = it->second->GetNext(out_cert); |
| 57 if (status == CompletionStatus::ASYNC) { |
| 58 // This Request has no more results ready, but isn't done yet. Move it |
| 59 // back to the pending list. |
| 60 pending_requests_[it->first] = std::move(it->second); |
| 61 ready_requests_.erase(it); |
| 62 } else if (!*out_cert) { |
| 63 // This Request is done, remove it. |
| 64 ready_requests_.erase(it); |
| 65 } else { |
| 66 // This Request returned a result, pass it on. |
| 67 return CompletionStatus::SYNC; |
| 68 } |
| 69 // No result from that Request, loop around try another. |
| 70 } |
| 71 |
| 72 *out_cert = nullptr; |
| 73 if (!pending_requests_.empty()) { |
| 74 // No results available at the moment, but there are still pending Requests. |
| 75 return CompletionStatus::ASYNC; |
| 76 } |
| 77 |
| 78 // All Requests are complete. |
| 79 return CompletionStatus::SYNC; |
| 80 } |
| 81 |
| 82 void CollectionRequest::MakeRequest(scoped_refptr<ParsedCertificate> cert, |
| 83 CertIssuerSource* source) { |
| 84 std::unique_ptr<CertIssuerSource::Request> req; |
| 85 source->AsyncGetIssuersOf(std::move(cert), |
| 86 base::Bind(&CollectionRequest::OnAsyncGetIssuersOf, |
| 87 base::Unretained(this)), |
| 88 &req); |
| 89 if (req) { |
| 90 CertIssuerSource::Request* req_ptr = req.get(); |
| 91 pending_requests_[req_ptr] = std::move(req); |
| 92 } |
| 93 } |
| 94 |
| 95 void CollectionRequest::OnAsyncGetIssuersOf(CertIssuerSource::Request* req) { |
| 96 bool client_waiting_for_callback = ready_requests_.empty(); |
| 97 // Find the request which just returned some results and move it to the ready |
| 98 // list, if it isn't there already. |
| 99 auto it = pending_requests_.find(req); |
| 100 if (it != pending_requests_.end()) { |
| 101 ready_requests_[it->first] = std::move(it->second); |
| 102 pending_requests_.erase(it); |
| 103 // Notify the client that results are now available. |
| 104 if (client_waiting_for_callback) |
| 105 issuers_callback_.Run(this); |
| 106 } else { |
| 107 // If it wasn't in the pending requests, it must already be in the ready |
| 108 // requests. |
| 109 DCHECK(ready_requests_.count(req)); |
| 110 } |
| 111 } |
| 112 |
| 113 } // namespace |
| 114 |
| 115 CertIssuerSourceCollection::CertIssuerSourceCollection() = default; |
| 116 CertIssuerSourceCollection::~CertIssuerSourceCollection() = default; |
| 117 |
| 118 void CertIssuerSourceCollection::AddSource(CertIssuerSource* source) { |
| 119 sources_.push_back(source); |
| 120 } |
| 121 |
| 122 void CertIssuerSourceCollection::SyncGetIssuersOf( |
| 123 const ParsedCertificate* cert, |
| 124 ParsedCertificateList* issuers) { |
| 125 for (CertIssuerSource* source : sources_) |
| 126 source->SyncGetIssuersOf(cert, issuers); |
| 127 } |
| 128 |
| 129 void CertIssuerSourceCollection::AsyncGetIssuersOf( |
| 130 scoped_refptr<ParsedCertificate> cert, |
| 131 const IssuerCallback& issuers_callback, |
| 132 std::unique_ptr<Request>* out_req) { |
| 133 std::unique_ptr<CollectionRequest> req( |
| 134 new CollectionRequest(issuers_callback)); |
| 135 |
| 136 for (CertIssuerSource* source : sources_) |
| 137 req->MakeRequest(cert, source); |
| 138 |
| 139 if (req->has_requests()) |
| 140 *out_req = std::move(req); |
| 141 else |
| 142 out_req->reset(); |
| 143 } |
| 144 |
| 145 } // namespace net |
OLD | NEW |