| // Copyright 2014 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. |
| |
| #ifndef NET_SSL_CHANNEL_ID_SERVICE_H_ |
| #define NET_SSL_CHANNEL_ID_SERVICE_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/task_runner.h" |
| #include "base/threading/thread_checker.h" |
| #include "net/base/completion_once_callback.h" |
| #include "net/base/net_export.h" |
| #include "net/ssl/channel_id_store.h" |
| #include "starboard/types.h" |
| |
| namespace crypto { |
| class ECPrivateKey; |
| } // namespace crypto |
| |
| namespace net { |
| |
| class ChannelIDServiceJob; |
| |
| // A class for creating and fetching Channel IDs. |
| class NET_EXPORT ChannelIDService { |
| public: |
| class NET_EXPORT Request { |
| public: |
| Request(); |
| ~Request(); |
| |
| // Cancel the request. Does nothing if the request finished or was already |
| // cancelled. |
| void Cancel(); |
| |
| bool is_active() const { return !callback_.is_null(); } |
| |
| private: |
| friend class ChannelIDService; |
| friend class ChannelIDServiceJob; |
| |
| void RequestStarted(ChannelIDService* service, |
| CompletionOnceCallback callback, |
| std::unique_ptr<crypto::ECPrivateKey>* key, |
| ChannelIDServiceJob* job); |
| |
| void Post(int error, std::unique_ptr<crypto::ECPrivateKey> key); |
| |
| ChannelIDService* service_; |
| CompletionOnceCallback callback_; |
| std::unique_ptr<crypto::ECPrivateKey>* key_; |
| ChannelIDServiceJob* job_; |
| }; |
| |
| // This object owns |channel_id_store|. |
| explicit ChannelIDService(ChannelIDStore* channel_id_store); |
| |
| ~ChannelIDService(); |
| |
| // Sets the TaskRunner to use for asynchronous operations. |
| void set_task_runner_for_testing( |
| scoped_refptr<base::TaskRunner> task_runner) { |
| task_runner_ = std::move(task_runner); |
| } |
| |
| // Returns the domain to be used for |host|. The domain is the |
| // "registry controlled domain", or the "ETLD + 1" where one exists, or |
| // the origin otherwise. |
| static std::string GetDomainForHost(const std::string& host); |
| |
| // Fetches the channel ID for the specified host if one exists and |
| // creates one otherwise. Returns OK if successful or an error code upon |
| // failure. |
| // |
| // On successful completion, |key| holds the ECDSA keypair used for this |
| // channel ID. |
| // |
| // |callback| must not be null. ERR_IO_PENDING is returned if the operation |
| // could not be completed immediately, in which case the result code will |
| // be passed to the callback when available. |
| // |
| // |*out_req| will be initialized with a handle to the async request. |
| int GetOrCreateChannelID(const std::string& host, |
| std::unique_ptr<crypto::ECPrivateKey>* key, |
| CompletionOnceCallback callback, |
| Request* out_req); |
| |
| // Fetches the channel ID for the specified host if one exists. |
| // Returns OK if successful, ERR_FILE_NOT_FOUND if none exists, or an error |
| // code upon failure. |
| // |
| // On successful completion, |key| holds the ECDSA keypair used for this |
| // channel ID. |
| // |
| // |callback| must not be null. ERR_IO_PENDING is returned if the operation |
| // could not be completed immediately, in which case the result code will |
| // be passed to the callback when available. If an in-flight |
| // GetChannelID is pending, and a new GetOrCreateChannelID |
| // request arrives for the same domain, the GetChannelID request will |
| // not complete until a new channel ID is created. |
| // |
| // |*out_req| will be initialized with a handle to the async request. |
| int GetChannelID(const std::string& host, |
| std::unique_ptr<crypto::ECPrivateKey>* key, |
| CompletionOnceCallback callback, |
| Request* out_req); |
| |
| // Returns the backing ChannelIDStore. |
| ChannelIDStore* GetChannelIDStore(); |
| |
| // Returns an ID that is unique across all instances of ChannelIDService in |
| // this process. TODO(nharper): remove this once crbug.com/548423 is resolved. |
| int GetUniqueID() const { return id_; } |
| |
| // Public only for unit testing. |
| int channel_id_count(); |
| uint64_t requests() const { return requests_; } |
| uint64_t key_store_hits() const { return key_store_hits_; } |
| uint64_t inflight_joins() const { return inflight_joins_; } |
| uint64_t workers_created() const { return workers_created_; } |
| |
| private: |
| void GotChannelID(int err, |
| const std::string& server_identifier, |
| std::unique_ptr<crypto::ECPrivateKey> key); |
| void GeneratedChannelID( |
| const std::string& server_identifier, |
| int error, |
| std::unique_ptr<ChannelIDStore::ChannelID> channel_id); |
| void HandleResult(int error, |
| const std::string& server_identifier, |
| std::unique_ptr<crypto::ECPrivateKey> key); |
| |
| // Searches for an in-flight request for the same domain. If found, attaches |
| // to the request, consumes |*callback|, and returns true. Otherwise does not |
| // consume |*callback| and returns false. |
| bool JoinToInFlightRequest(const std::string& domain, |
| std::unique_ptr<crypto::ECPrivateKey>* key, |
| bool create_if_missing, |
| CompletionOnceCallback* callback, |
| Request* out_req); |
| |
| // Looks for the channel ID for |domain| in this service's store. Returns OK |
| // if it can be found synchronously, ERR_IO_PENDING if the result cannot be |
| // obtained synchronously, or a different network error code on failure |
| // (including failure to find a channel ID of |domain|). Consumes |*callback| |
| // if and only if ERR_IO_PENDING is returned. |
| int LookupChannelID(const std::string& domain, |
| std::unique_ptr<crypto::ECPrivateKey>* key, |
| bool create_if_missing, |
| CompletionOnceCallback* callback, |
| Request* out_req); |
| |
| std::unique_ptr<ChannelIDStore> channel_id_store_; |
| scoped_refptr<base::TaskRunner> task_runner_; |
| const int id_; |
| |
| // inflight_ maps from a server to an active generation which is taking |
| // place. |
| std::map<std::string, std::unique_ptr<ChannelIDServiceJob>> inflight_; |
| |
| uint64_t requests_; |
| uint64_t key_store_hits_; |
| uint64_t inflight_joins_; |
| uint64_t workers_created_; |
| |
| THREAD_CHECKER(thread_checker_); |
| |
| base::WeakPtrFactory<ChannelIDService> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ChannelIDService); |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_SSL_CHANNEL_ID_SERVICE_H_ |