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
3 // found in the LICENSE file.
5 #ifndef NET_SSL_CHANNEL_ID_SERVICE_H_
6 #define NET_SSL_CHANNEL_ID_SERVICE_H_
12 #include "base/basictypes.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/threading/non_thread_safe.h"
16 #include "base/time/time.h"
17 #include "net/base/completion_callback.h"
18 #include "net/base/net_export.h"
19 #include "net/ssl/channel_id_store.h"
31 class ChannelIDServiceJob
;
32 class ChannelIDServiceWorker
;
34 // A class for creating and fetching Channel IDs.
36 // Inherits from NonThreadSafe in order to use the function
37 // |CalledOnValidThread|.
38 class NET_EXPORT ChannelIDService
39 : NON_EXPORTED_BASE(public base::NonThreadSafe
) {
41 class NET_EXPORT Request
{
46 // Cancel the request. Does nothing if the request finished or was already
50 bool is_active() const { return !callback_
.is_null(); }
53 friend class ChannelIDService
;
54 friend class ChannelIDServiceJob
;
56 void RequestStarted(ChannelIDService
* service
,
57 base::TimeTicks request_start
,
58 const CompletionCallback
& callback
,
59 scoped_ptr
<crypto::ECPrivateKey
>* key
,
60 ChannelIDServiceJob
* job
);
62 void Post(int error
, scoped_ptr
<crypto::ECPrivateKey
> key
);
64 ChannelIDService
* service_
;
65 base::TimeTicks request_start_
;
66 CompletionCallback callback_
;
67 scoped_ptr
<crypto::ECPrivateKey
>* key_
;
68 ChannelIDServiceJob
* job_
;
71 // Password used on EncryptedPrivateKeyInfo data stored in EC private_key
72 // values. (This is not used to provide any security, but to workaround NSS
73 // being unable to import unencrypted PrivateKeyInfo for EC keys.)
74 static const char kEPKIPassword
[];
76 // This object owns |channel_id_store|. |task_runner| will
77 // be used to post channel ID generation worker tasks. The tasks are
78 // safe for use with WorkerPool and SequencedWorkerPool::CONTINUE_ON_SHUTDOWN.
80 ChannelIDStore
* channel_id_store
,
81 const scoped_refptr
<base::TaskRunner
>& task_runner
);
85 // Returns the domain to be used for |host|. The domain is the
86 // "registry controlled domain", or the "ETLD + 1" where one exists, or
87 // the origin otherwise.
88 static std::string
GetDomainForHost(const std::string
& host
);
90 // Fetches the channel ID for the specified host if one exists and
91 // creates one otherwise. Returns OK if successful or an error code upon
94 // On successful completion, |key| holds the ECDSA keypair used for this
97 // |callback| must not be null. ERR_IO_PENDING is returned if the operation
98 // could not be completed immediately, in which case the result code will
99 // be passed to the callback when available.
101 // |*out_req| will be initialized with a handle to the async request.
102 int GetOrCreateChannelID(const std::string
& host
,
103 scoped_ptr
<crypto::ECPrivateKey
>* key
,
104 const CompletionCallback
& callback
,
107 // Fetches the channel ID for the specified host if one exists.
108 // Returns OK if successful, ERR_FILE_NOT_FOUND if none exists, or an error
109 // code upon failure.
111 // On successful completion, |key| holds the ECDSA keypair used for this
114 // |callback| must not be null. ERR_IO_PENDING is returned if the operation
115 // could not be completed immediately, in which case the result code will
116 // be passed to the callback when available. If an in-flight
117 // GetChannelID is pending, and a new GetOrCreateChannelID
118 // request arrives for the same domain, the GetChannelID request will
119 // not complete until a new channel ID is created.
121 // |*out_req| will be initialized with a handle to the async request.
122 int GetChannelID(const std::string
& host
,
123 scoped_ptr
<crypto::ECPrivateKey
>* key
,
124 const CompletionCallback
& callback
,
127 // Returns the backing ChannelIDStore.
128 ChannelIDStore
* GetChannelIDStore();
130 // Public only for unit testing.
131 int channel_id_count();
132 uint64
requests() const { return requests_
; }
133 uint64
key_store_hits() const { return key_store_hits_
; }
134 uint64
inflight_joins() const { return inflight_joins_
; }
135 uint64
workers_created() const { return workers_created_
; }
138 void GotChannelID(int err
,
139 const std::string
& server_identifier
,
140 scoped_ptr
<crypto::ECPrivateKey
> key
);
141 void GeneratedChannelID(
142 const std::string
& server_identifier
,
144 scoped_ptr
<ChannelIDStore::ChannelID
> channel_id
);
145 void HandleResult(int error
,
146 const std::string
& server_identifier
,
147 scoped_ptr
<crypto::ECPrivateKey
> key
);
149 // Searches for an in-flight request for the same domain. If found,
150 // attaches to the request and returns true. Returns false if no in-flight
152 bool JoinToInFlightRequest(const base::TimeTicks
& request_start
,
153 const std::string
& domain
,
154 scoped_ptr
<crypto::ECPrivateKey
>* key
,
155 bool create_if_missing
,
156 const CompletionCallback
& callback
,
159 // Looks for the channel ID for |domain| in this service's store.
160 // Returns OK if it can be found synchronously, ERR_IO_PENDING if the
161 // result cannot be obtained synchronously, or a network error code on
162 // failure (including failure to find a channel ID of |domain|).
163 int LookupChannelID(const base::TimeTicks
& request_start
,
164 const std::string
& domain
,
165 scoped_ptr
<crypto::ECPrivateKey
>* key
,
166 bool create_if_missing
,
167 const CompletionCallback
& callback
,
170 scoped_ptr
<ChannelIDStore
> channel_id_store_
;
171 scoped_refptr
<base::TaskRunner
> task_runner_
;
173 // inflight_ maps from a server to an active generation which is taking
175 std::map
<std::string
, ChannelIDServiceJob
*> inflight_
;
178 uint64 key_store_hits_
;
179 uint64 inflight_joins_
;
180 uint64 workers_created_
;
182 base::WeakPtrFactory
<ChannelIDService
> weak_ptr_factory_
;
184 DISALLOW_COPY_AND_ASSIGN(ChannelIDService
);
189 #endif // NET_SSL_CHANNEL_ID_SERVICE_H_