Home | History | Annotate | Download | only in browsing_data
      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