1 // Copyright 2015 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/certificate_provider/certificate_requests.h"
10 #include "base/callback.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/time/time.h"
15 #include "base/timer/timer.h"
18 namespace certificate_provider
{
21 const int kGetCertificatesTimeoutInMinutes
= 5;
24 // Holds state for a single certificate request.
25 struct CertificateRequests::CertificateRequestState
{
26 CertificateRequestState() : timeout(false, false) {}
28 ~CertificateRequestState() {}
30 // Extensions that are too slow are eventually dropped from a request.
33 // Extensions that this request is still waiting for.
34 std::set
<std::string
> pending_extensions
;
36 // For every extension that replied to this request, there is one entry from
37 // extension id to the reported certificates.
38 std::map
<std::string
, CertificateInfoList
> extension_to_certificates
;
40 // The callback that must be run with the final list of certificates.
41 base::Callback
<void(const net::CertificateList
&)> callback
;
44 CertificateRequests::CertificateRequests() {}
46 CertificateRequests::~CertificateRequests() {}
48 int CertificateRequests::AddRequest(
49 const std::vector
<std::string
>& extension_ids
,
50 const base::Callback
<void(const net::CertificateList
&)>& callback
,
51 const base::Callback
<void(int)>& timeout_callback
) {
52 scoped_ptr
<CertificateRequestState
> state(new CertificateRequestState
);
53 state
->callback
= callback
;
54 state
->pending_extensions
.insert(extension_ids
.begin(), extension_ids
.end());
56 const int request_id
= next_free_request_id_
++;
58 FROM_HERE
, base::TimeDelta::FromMinutes(kGetCertificatesTimeoutInMinutes
),
59 base::Bind(timeout_callback
, request_id
));
61 const auto insert_result
= requests_
.insert(request_id
, state
.Pass());
62 DCHECK(insert_result
.second
) << "request id already in use.";
66 bool CertificateRequests::SetCertificates(
67 const std::string
& extension_id
,
69 const CertificateInfoList
& certificate_infos
,
72 const auto it
= requests_
.find(request_id
);
73 if (it
== requests_
.end())
76 CertificateRequestState
& state
= *it
->second
;
77 if (state
.pending_extensions
.erase(extension_id
) == 0)
80 state
.extension_to_certificates
[extension_id
] = certificate_infos
;
81 *completed
= state
.pending_extensions
.empty();
85 bool CertificateRequests::RemoveRequest(
87 std::map
<std::string
, CertificateInfoList
>* certificates
,
88 base::Callback
<void(const net::CertificateList
&)>* callback
) {
89 const auto it
= requests_
.find(request_id
);
90 if (it
== requests_
.end())
93 CertificateRequestState
& state
= *it
->second
;
94 *certificates
= state
.extension_to_certificates
;
95 *callback
= state
.callback
;
97 DVLOG(2) << "Completed certificate request " << request_id
;
101 std::vector
<int> CertificateRequests::DropExtension(
102 const std::string
& extension_id
) {
103 std::vector
<int> completed_requests
;
104 for (auto& entry
: requests_
) {
105 DVLOG(2) << "Remove extension " << extension_id
106 << " from certificate request " << entry
.first
;
108 CertificateRequestState
& state
= *entry
.second
;
109 state
.pending_extensions
.erase(extension_id
);
110 if (state
.pending_extensions
.empty())
111 completed_requests
.push_back(entry
.first
);
113 return completed_requests
;
116 } // namespace certificate_provider
117 } // namespace chromeos