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. 4 5 #include "chrome/browser/browsing_data/browsing_data_channel_id_helper.h" 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/message_loop/message_loop.h" 11 #include "content/public/browser/browser_thread.h" 12 #include "net/ssl/channel_id_service.h" 13 #include "net/url_request/url_request_context.h" 14 #include "net/url_request/url_request_context_getter.h" 15 16 using content::BrowserThread; 17 18 namespace { 19 20 class BrowsingDataChannelIDHelperImpl 21 : public BrowsingDataChannelIDHelper { 22 public: 23 explicit BrowsingDataChannelIDHelperImpl( 24 net::URLRequestContextGetter* request_context); 25 26 // BrowsingDataChannelIDHelper methods. 27 virtual void StartFetching(const FetchResultCallback& callback) OVERRIDE; 28 virtual void DeleteChannelID(const std::string& server_id) OVERRIDE; 29 30 private: 31 virtual ~BrowsingDataChannelIDHelperImpl(); 32 33 // Fetch the certs. This must be called in the IO thread. 34 void FetchOnIOThread(); 35 36 void OnFetchComplete( 37 const net::ChannelIDStore::ChannelIDList& channel_id_list); 38 39 // Notifies the completion callback. This must be called in the UI thread. 40 void NotifyInUIThread( 41 const net::ChannelIDStore::ChannelIDList& channel_id_list); 42 43 // Delete a single cert. This must be called in IO thread. 44 void DeleteOnIOThread(const std::string& server_id); 45 46 // Called when deletion is done. 47 void DeleteCallback(); 48 49 // Indicates whether or not we're currently fetching information: 50 // it's true when StartFetching() is called in the UI thread, and it's reset 51 // after we notify the callback in the UI thread. 52 // This member is only mutated on the UI thread. 53 bool is_fetching_; 54 55 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; 56 57 // This member is only mutated on the UI thread. 58 FetchResultCallback completion_callback_; 59 60 DISALLOW_COPY_AND_ASSIGN(BrowsingDataChannelIDHelperImpl); 61 }; 62 63 BrowsingDataChannelIDHelperImpl::BrowsingDataChannelIDHelperImpl( 64 net::URLRequestContextGetter* request_context) 65 : is_fetching_(false), request_context_getter_(request_context) { 66 DCHECK_CURRENTLY_ON(BrowserThread::UI); 67 } 68 69 BrowsingDataChannelIDHelperImpl:: 70 ~BrowsingDataChannelIDHelperImpl() { 71 } 72 73 void BrowsingDataChannelIDHelperImpl::StartFetching( 74 const FetchResultCallback& callback) { 75 DCHECK_CURRENTLY_ON(BrowserThread::UI); 76 DCHECK(!is_fetching_); 77 DCHECK(!callback.is_null()); 78 DCHECK(completion_callback_.is_null()); 79 is_fetching_ = true; 80 completion_callback_ = callback; 81 BrowserThread::PostTask( 82 BrowserThread::IO, 83 FROM_HERE, 84 base::Bind(&BrowsingDataChannelIDHelperImpl::FetchOnIOThread, this)); 85 } 86 87 void BrowsingDataChannelIDHelperImpl::DeleteChannelID( 88 const std::string& server_id) { 89 DCHECK_CURRENTLY_ON(BrowserThread::UI); 90 BrowserThread::PostTask( 91 BrowserThread::IO, 92 FROM_HERE, 93 base::Bind( 94 &BrowsingDataChannelIDHelperImpl::DeleteOnIOThread, this, server_id)); 95 } 96 97 void BrowsingDataChannelIDHelperImpl::FetchOnIOThread() { 98 DCHECK_CURRENTLY_ON(BrowserThread::IO); 99 net::ChannelIDStore* cert_store = 100 request_context_getter_->GetURLRequestContext()-> 101 channel_id_service()->GetChannelIDStore(); 102 if (cert_store) { 103 cert_store->GetAllChannelIDs(base::Bind( 104 &BrowsingDataChannelIDHelperImpl::OnFetchComplete, this)); 105 } else { 106 OnFetchComplete(net::ChannelIDStore::ChannelIDList()); 107 } 108 } 109 110 void BrowsingDataChannelIDHelperImpl::OnFetchComplete( 111 const net::ChannelIDStore::ChannelIDList& channel_id_list) { 112 DCHECK_CURRENTLY_ON(BrowserThread::IO); 113 BrowserThread::PostTask( 114 BrowserThread::UI, 115 FROM_HERE, 116 base::Bind(&BrowsingDataChannelIDHelperImpl::NotifyInUIThread, 117 this, 118 channel_id_list)); 119 } 120 121 void BrowsingDataChannelIDHelperImpl::NotifyInUIThread( 122 const net::ChannelIDStore::ChannelIDList& channel_id_list) { 123 DCHECK_CURRENTLY_ON(BrowserThread::UI); 124 DCHECK(is_fetching_); 125 is_fetching_ = false; 126 completion_callback_.Run(channel_id_list); 127 completion_callback_.Reset(); 128 } 129 130 void BrowsingDataChannelIDHelperImpl::DeleteOnIOThread( 131 const std::string& server_id) { 132 DCHECK_CURRENTLY_ON(BrowserThread::IO); 133 net::ChannelIDStore* cert_store = 134 request_context_getter_->GetURLRequestContext()-> 135 channel_id_service()->GetChannelIDStore(); 136 if (cert_store) { 137 cert_store->DeleteChannelID( 138 server_id, 139 base::Bind(&BrowsingDataChannelIDHelperImpl::DeleteCallback, 140 this)); 141 } 142 } 143 144 void BrowsingDataChannelIDHelperImpl::DeleteCallback() { 145 DCHECK_CURRENTLY_ON(BrowserThread::IO); 146 // Need to close open SSL connections which may be using the channel ids we 147 // are deleting. 148 // TODO(mattm): http://crbug.com/166069 Make the server bound cert 149 // service/store have observers that can notify relevant things directly. 150 request_context_getter_->GetURLRequestContext()->ssl_config_service()-> 151 NotifySSLConfigChange(); 152 } 153 154 } // namespace 155 156 // static 157 BrowsingDataChannelIDHelper* BrowsingDataChannelIDHelper::Create( 158 net::URLRequestContextGetter* request_context) { 159 return new BrowsingDataChannelIDHelperImpl(request_context); 160 } 161 162 CannedBrowsingDataChannelIDHelper:: 163 CannedBrowsingDataChannelIDHelper() {} 164 165 CannedBrowsingDataChannelIDHelper:: 166 ~CannedBrowsingDataChannelIDHelper() {} 167 168 void CannedBrowsingDataChannelIDHelper::AddChannelID( 169 const net::ChannelIDStore::ChannelID& channel_id) { 170 DCHECK_CURRENTLY_ON(BrowserThread::UI); 171 channel_id_map_[channel_id.server_identifier()] = 172 channel_id; 173 } 174 175 void CannedBrowsingDataChannelIDHelper::Reset() { 176 channel_id_map_.clear(); 177 } 178 179 bool CannedBrowsingDataChannelIDHelper::empty() const { 180 return channel_id_map_.empty(); 181 } 182 183 size_t CannedBrowsingDataChannelIDHelper::GetChannelIDCount() const { 184 DCHECK_CURRENTLY_ON(BrowserThread::UI); 185 return channel_id_map_.size(); 186 } 187 188 void CannedBrowsingDataChannelIDHelper::StartFetching( 189 const FetchResultCallback& callback) { 190 DCHECK_CURRENTLY_ON(BrowserThread::UI); 191 if (callback.is_null()) 192 return; 193 // We post a task to emulate async fetching behavior. 194 completion_callback_ = callback; 195 base::MessageLoop::current()->PostTask( 196 FROM_HERE, 197 base::Bind(&CannedBrowsingDataChannelIDHelper::FinishFetching, 198 this)); 199 } 200 201 void CannedBrowsingDataChannelIDHelper::FinishFetching() { 202 DCHECK_CURRENTLY_ON(BrowserThread::UI); 203 net::ChannelIDStore::ChannelIDList channel_id_list; 204 for (ChannelIDMap::iterator i = channel_id_map_.begin(); 205 i != channel_id_map_.end(); ++i) 206 channel_id_list.push_back(i->second); 207 completion_callback_.Run(channel_id_list); 208 } 209 210 void CannedBrowsingDataChannelIDHelper::DeleteChannelID( 211 const std::string& server_id) { 212 NOTREACHED(); 213 } 214