15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef NET_SSL_CHANNEL_ID_SERVICE_H_ 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define NET_SSL_CHANNEL_ID_SERVICE_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/weak_ptr.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/non_thread_safe.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_export.h" 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/ssl/channel_id_store.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TaskRunner; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ChannelIDServiceJob; 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ChannelIDServiceRequest; 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ChannelIDServiceWorker; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// A class for creating and fetching domain bound certs. They are used 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// to identify users' machines; their public keys are used as channel IDs in 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// http://tools.ietf.org/html/draft-balfanz-tls-channelid-00. 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// As a result although certs are set to be invalid after one year, we don't 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// actually expire them. Once generated, certs are valid as long as the users 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// want. Users can delete existing certs, and new certs will be generated 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// automatically. 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Inherits from NonThreadSafe in order to use the function 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |CalledOnValidThread|. 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class NET_EXPORT ChannelIDService 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : NON_EXPORTED_BASE(public base::NonThreadSafe) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) class NET_EXPORT RequestHandle { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestHandle(); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~RequestHandle(); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Cancel the request. Does nothing if the request finished or was already 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // cancelled. 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Cancel(); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_active() const { return request_ != NULL; } 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) friend class ChannelIDService; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void RequestStarted(ChannelIDService* service, 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ChannelIDServiceRequest* request, 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void OnRequestComplete(int result); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ChannelIDService* service_; 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ChannelIDServiceRequest* request_; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CompletionCallback callback_; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Password used on EncryptedPrivateKeyInfo data stored in EC private_key 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // values. (This is not used to provide any security, but to workaround NSS 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // being unable to import unencrypted PrivateKeyInfo for EC keys.) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kEPKIPassword[]; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This object owns |channel_id_store|. |task_runner| will 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be used to post certificate generation worker tasks. The tasks are 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // safe for use with WorkerPool and SequencedWorkerPool::CONTINUE_ON_SHUTDOWN. 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ChannelIDService( 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ChannelIDStore* channel_id_store, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<base::TaskRunner>& task_runner); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ~ChannelIDService(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the domain to be used for |host|. The domain is the 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "registry controlled domain", or the "ETLD + 1" where one exists, or 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the origin otherwise. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string GetDomainForHost(const std::string& host); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tests whether the system time is within the supported range for 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // certificate generation. This value is cached when ChannelIDService 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is created, so if the system time is changed by a huge amount, this may no 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // longer hold. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsSystemTimeValid() const { return is_system_time_valid_; } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 94bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Fetches the domain bound cert for the specified host if one exists and 95bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // creates one otherwise. Returns OK if successful or an error code upon 96bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // failure. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On successful completion, |private_key| stores a DER-encoded 99bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate. 100bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // The PrivateKeyInfo is always an ECDSA private key. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |callback| must not be null. ERR_IO_PENDING is returned if the operation 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could not be completed immediately, in which case the result code will 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be passed to the callback when available. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |*out_req| will be initialized with a handle to the async request. This 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // RequestHandle object must be cancelled or destroyed before the 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // ChannelIDService is destroyed. 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int GetOrCreateChannelID( 1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& host, 1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string* private_key, 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string* cert, 1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const CompletionCallback& callback, 1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RequestHandle* out_req); 1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Fetches the domain bound cert for the specified host if one exists. 1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Returns OK if successful, ERR_FILE_NOT_FOUND if none exists, or an error 1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // code upon failure. 1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // On successful completion, |private_key| stores a DER-encoded 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate. 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The PrivateKeyInfo is always an ECDSA private key. 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // |callback| must not be null. ERR_IO_PENDING is returned if the operation 1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // could not be completed immediately, in which case the result code will 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // be passed to the callback when available. If an in-flight 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // GetChannelID is pending, and a new GetOrCreateDomainBoundCert 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // request arrives for the same domain, the GetChannelID request will 1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // not complete until a new cert is created. 1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // 1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // |*out_req| will be initialized with a handle to the async request. This 1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // RequestHandle object must be cancelled or destroyed before the 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // ChannelIDService is destroyed. 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int GetChannelID( 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& host, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* private_key, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* cert, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestHandle* out_req); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Returns the backing ChannelIDStore. 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ChannelIDStore* GetChannelIDStore(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Public only for unit testing. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cert_count(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 requests() const { return requests_; } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 cert_store_hits() const { return cert_store_hits_; } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 inflight_joins() const { return inflight_joins_; } 149bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch uint64 workers_created() const { return workers_created_; } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Cancels the specified request. |req| is the handle stored by 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // GetChannelID(). After a request is canceled, its completion 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // callback will not be called. 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void CancelRequest(ChannelIDServiceRequest* req); 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void GotChannelID(int err, 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& server_identifier, 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Time expiration_time, 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& key, 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& cert); 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void GeneratedChannelID( 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& server_identifier, 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int error, 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<ChannelIDStore::ChannelID> channel_id); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void HandleResult(int error, 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& server_identifier, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& private_key, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& cert); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Searches for an in-flight request for the same domain. If found, 1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // attaches to the request and returns true. Returns false if no in-flight 1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // request is found. 1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool JoinToInFlightRequest(const base::TimeTicks& request_start, 1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& domain, 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string* private_key, 1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string* cert, 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool create_if_missing, 1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const CompletionCallback& callback, 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RequestHandle* out_req); 1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Looks for the domain bound cert for |domain| in this service's store. 1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Returns OK if it can be found synchronously, ERR_IO_PENDING if the 1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // result cannot be obtained synchronously, or a network error code on 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // failure (including failure to find a domain-bound cert of |domain|). 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int LookupChannelID(const base::TimeTicks& request_start, 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& domain, 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string* private_key, 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string* cert, 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool create_if_missing, 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const CompletionCallback& callback, 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RequestHandle* out_req); 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<ChannelIDStore> channel_id_store_; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::TaskRunner> task_runner_; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // inflight_ maps from a server to an active generation which is taking 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // place. 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::map<std::string, ChannelIDServiceJob*> inflight_; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 requests_; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 cert_store_hits_; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 inflight_joins_; 204bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch uint64 workers_created_; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_system_time_valid_; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::WeakPtrFactory<ChannelIDService> weak_ptr_factory_; 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ChannelIDService); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif // NET_SSL_CHANNEL_ID_SERVICE_H_ 216