// 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. #include "chrome/browser/browsing_data/browsing_data_channel_id_helper.h" #include "base/bind.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "content/public/browser/browser_thread.h" #include "net/ssl/channel_id_service.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" using content::BrowserThread; namespace { class BrowsingDataChannelIDHelperImpl : public BrowsingDataChannelIDHelper { public: explicit BrowsingDataChannelIDHelperImpl( net::URLRequestContextGetter* request_context); // BrowsingDataChannelIDHelper methods. virtual void StartFetching(const FetchResultCallback& callback) OVERRIDE; virtual void DeleteChannelID(const std::string& server_id) OVERRIDE; private: virtual ~BrowsingDataChannelIDHelperImpl(); // Fetch the certs. This must be called in the IO thread. void FetchOnIOThread(); void OnFetchComplete( const net::ChannelIDStore::ChannelIDList& channel_id_list); // Notifies the completion callback. This must be called in the UI thread. void NotifyInUIThread( const net::ChannelIDStore::ChannelIDList& channel_id_list); // Delete a single cert. This must be called in IO thread. void DeleteOnIOThread(const std::string& server_id); // Called when deletion is done. void DeleteCallback(); // Indicates whether or not we're currently fetching information: // it's true when StartFetching() is called in the UI thread, and it's reset // after we notify the callback in the UI thread. // This member is only mutated on the UI thread. bool is_fetching_; scoped_refptr request_context_getter_; // This member is only mutated on the UI thread. FetchResultCallback completion_callback_; DISALLOW_COPY_AND_ASSIGN(BrowsingDataChannelIDHelperImpl); }; BrowsingDataChannelIDHelperImpl::BrowsingDataChannelIDHelperImpl( net::URLRequestContextGetter* request_context) : is_fetching_(false), request_context_getter_(request_context) { DCHECK_CURRENTLY_ON(BrowserThread::UI); } BrowsingDataChannelIDHelperImpl:: ~BrowsingDataChannelIDHelperImpl() { } void BrowsingDataChannelIDHelperImpl::StartFetching( const FetchResultCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!is_fetching_); DCHECK(!callback.is_null()); DCHECK(completion_callback_.is_null()); is_fetching_ = true; completion_callback_ = callback; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&BrowsingDataChannelIDHelperImpl::FetchOnIOThread, this)); } void BrowsingDataChannelIDHelperImpl::DeleteChannelID( const std::string& server_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind( &BrowsingDataChannelIDHelperImpl::DeleteOnIOThread, this, server_id)); } void BrowsingDataChannelIDHelperImpl::FetchOnIOThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); net::ChannelIDStore* cert_store = request_context_getter_->GetURLRequestContext()-> channel_id_service()->GetChannelIDStore(); if (cert_store) { cert_store->GetAllChannelIDs(base::Bind( &BrowsingDataChannelIDHelperImpl::OnFetchComplete, this)); } else { OnFetchComplete(net::ChannelIDStore::ChannelIDList()); } } void BrowsingDataChannelIDHelperImpl::OnFetchComplete( const net::ChannelIDStore::ChannelIDList& channel_id_list) { DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&BrowsingDataChannelIDHelperImpl::NotifyInUIThread, this, channel_id_list)); } void BrowsingDataChannelIDHelperImpl::NotifyInUIThread( const net::ChannelIDStore::ChannelIDList& channel_id_list) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(is_fetching_); is_fetching_ = false; completion_callback_.Run(channel_id_list); completion_callback_.Reset(); } void BrowsingDataChannelIDHelperImpl::DeleteOnIOThread( const std::string& server_id) { DCHECK_CURRENTLY_ON(BrowserThread::IO); net::ChannelIDStore* cert_store = request_context_getter_->GetURLRequestContext()-> channel_id_service()->GetChannelIDStore(); if (cert_store) { cert_store->DeleteChannelID( server_id, base::Bind(&BrowsingDataChannelIDHelperImpl::DeleteCallback, this)); } } void BrowsingDataChannelIDHelperImpl::DeleteCallback() { DCHECK_CURRENTLY_ON(BrowserThread::IO); // Need to close open SSL connections which may be using the channel ids we // are deleting. // TODO(mattm): http://crbug.com/166069 Make the server bound cert // service/store have observers that can notify relevant things directly. request_context_getter_->GetURLRequestContext()->ssl_config_service()-> NotifySSLConfigChange(); } } // namespace // static BrowsingDataChannelIDHelper* BrowsingDataChannelIDHelper::Create( net::URLRequestContextGetter* request_context) { return new BrowsingDataChannelIDHelperImpl(request_context); } CannedBrowsingDataChannelIDHelper:: CannedBrowsingDataChannelIDHelper() {} CannedBrowsingDataChannelIDHelper:: ~CannedBrowsingDataChannelIDHelper() {} CannedBrowsingDataChannelIDHelper* CannedBrowsingDataChannelIDHelper::Clone() { DCHECK_CURRENTLY_ON(BrowserThread::UI); CannedBrowsingDataChannelIDHelper* clone = new CannedBrowsingDataChannelIDHelper(); clone->channel_id_map_ = channel_id_map_; return clone; } void CannedBrowsingDataChannelIDHelper::AddChannelID( const net::ChannelIDStore::ChannelID& channel_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); channel_id_map_[channel_id.server_identifier()] = channel_id; } void CannedBrowsingDataChannelIDHelper::Reset() { channel_id_map_.clear(); } bool CannedBrowsingDataChannelIDHelper::empty() const { return channel_id_map_.empty(); } size_t CannedBrowsingDataChannelIDHelper::GetChannelIDCount() const { DCHECK_CURRENTLY_ON(BrowserThread::UI); return channel_id_map_.size(); } void CannedBrowsingDataChannelIDHelper::StartFetching( const FetchResultCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (callback.is_null()) return; // We post a task to emulate async fetching behavior. completion_callback_ = callback; base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&CannedBrowsingDataChannelIDHelper::FinishFetching, this)); } void CannedBrowsingDataChannelIDHelper::FinishFetching() { DCHECK_CURRENTLY_ON(BrowserThread::UI); net::ChannelIDStore::ChannelIDList channel_id_list; for (ChannelIDMap::iterator i = channel_id_map_.begin(); i != channel_id_map_.end(); ++i) channel_id_list.push_back(i->second); completion_callback_.Run(channel_id_list); } void CannedBrowsingDataChannelIDHelper::DeleteChannelID( const std::string& server_id) { NOTREACHED(); }