1// Copyright (c) 2012 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_quota_helper_impl.h" 6 7#include <map> 8#include <set> 9 10#include "base/bind.h" 11#include "base/logging.h" 12#include "chrome/browser/browsing_data/browsing_data_helper.h" 13#include "chrome/browser/profiles/profile.h" 14#include "chrome/common/url_constants.h" 15#include "content/public/browser/browser_context.h" 16#include "content/public/browser/browser_thread.h" 17#include "content/public/browser/storage_partition.h" 18#include "storage/browser/quota/quota_manager.h" 19 20using content::BrowserThread; 21using content::BrowserContext; 22 23// static 24BrowsingDataQuotaHelper* BrowsingDataQuotaHelper::Create(Profile* profile) { 25 return new BrowsingDataQuotaHelperImpl( 26 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI).get(), 27 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(), 28 BrowserContext::GetDefaultStoragePartition(profile)->GetQuotaManager()); 29} 30 31void BrowsingDataQuotaHelperImpl::StartFetching( 32 const FetchResultCallback& callback) { 33 DCHECK(!callback.is_null()); 34 DCHECK(callback_.is_null()); 35 DCHECK(!is_fetching_); 36 callback_ = callback; 37 quota_info_.clear(); 38 is_fetching_ = true; 39 40 FetchQuotaInfo(); 41} 42 43void BrowsingDataQuotaHelperImpl::RevokeHostQuota(const std::string& host) { 44 if (!io_thread_->BelongsToCurrentThread()) { 45 io_thread_->PostTask( 46 FROM_HERE, 47 base::Bind(&BrowsingDataQuotaHelperImpl::RevokeHostQuota, this, host)); 48 return; 49 } 50 51 quota_manager_->SetPersistentHostQuota( 52 host, 0, 53 base::Bind(&BrowsingDataQuotaHelperImpl::DidRevokeHostQuota, 54 weak_factory_.GetWeakPtr())); 55} 56 57BrowsingDataQuotaHelperImpl::BrowsingDataQuotaHelperImpl( 58 base::MessageLoopProxy* ui_thread, 59 base::MessageLoopProxy* io_thread, 60 storage::QuotaManager* quota_manager) 61 : BrowsingDataQuotaHelper(io_thread), 62 quota_manager_(quota_manager), 63 is_fetching_(false), 64 ui_thread_(ui_thread), 65 io_thread_(io_thread), 66 weak_factory_(this) { 67 DCHECK(quota_manager); 68} 69 70BrowsingDataQuotaHelperImpl::~BrowsingDataQuotaHelperImpl() {} 71 72void BrowsingDataQuotaHelperImpl::FetchQuotaInfo() { 73 if (!io_thread_->BelongsToCurrentThread()) { 74 io_thread_->PostTask( 75 FROM_HERE, 76 base::Bind(&BrowsingDataQuotaHelperImpl::FetchQuotaInfo, this)); 77 return; 78 } 79 80 quota_manager_->GetOriginsModifiedSince( 81 storage::kStorageTypeTemporary, 82 base::Time(), 83 base::Bind(&BrowsingDataQuotaHelperImpl::GotOrigins, 84 weak_factory_.GetWeakPtr())); 85} 86 87void BrowsingDataQuotaHelperImpl::GotOrigins(const std::set<GURL>& origins, 88 storage::StorageType type) { 89 for (std::set<GURL>::const_iterator itr = origins.begin(); 90 itr != origins.end(); 91 ++itr) 92 if (BrowsingDataHelper::HasWebScheme(*itr)) 93 pending_hosts_.insert(std::make_pair(itr->host(), type)); 94 95 DCHECK(type == storage::kStorageTypeTemporary || 96 type == storage::kStorageTypePersistent || 97 type == storage::kStorageTypeSyncable); 98 99 // Calling GetOriginsModifiedSince() for all types by chaining callbacks. 100 if (type == storage::kStorageTypeTemporary) { 101 quota_manager_->GetOriginsModifiedSince( 102 storage::kStorageTypePersistent, 103 base::Time(), 104 base::Bind(&BrowsingDataQuotaHelperImpl::GotOrigins, 105 weak_factory_.GetWeakPtr())); 106 } else if (type == storage::kStorageTypePersistent) { 107 quota_manager_->GetOriginsModifiedSince( 108 storage::kStorageTypeSyncable, 109 base::Time(), 110 base::Bind(&BrowsingDataQuotaHelperImpl::GotOrigins, 111 weak_factory_.GetWeakPtr())); 112 } else { 113 DCHECK(type == storage::kStorageTypeSyncable); 114 ProcessPendingHosts(); 115 } 116} 117 118void BrowsingDataQuotaHelperImpl::ProcessPendingHosts() { 119 if (pending_hosts_.empty()) { 120 OnComplete(); 121 return; 122 } 123 124 PendingHosts::iterator itr = pending_hosts_.begin(); 125 std::string host = itr->first; 126 storage::StorageType type = itr->second; 127 pending_hosts_.erase(itr); 128 GetHostUsage(host, type); 129} 130 131void BrowsingDataQuotaHelperImpl::GetHostUsage(const std::string& host, 132 storage::StorageType type) { 133 DCHECK(quota_manager_.get()); 134 quota_manager_->GetHostUsage( 135 host, type, 136 base::Bind(&BrowsingDataQuotaHelperImpl::GotHostUsage, 137 weak_factory_.GetWeakPtr(), host, type)); 138} 139 140void BrowsingDataQuotaHelperImpl::GotHostUsage(const std::string& host, 141 storage::StorageType type, 142 int64 usage) { 143 switch (type) { 144 case storage::kStorageTypeTemporary: 145 quota_info_[host].temporary_usage = usage; 146 break; 147 case storage::kStorageTypePersistent: 148 quota_info_[host].persistent_usage = usage; 149 break; 150 case storage::kStorageTypeSyncable: 151 quota_info_[host].syncable_usage = usage; 152 break; 153 default: 154 NOTREACHED(); 155 } 156 ProcessPendingHosts(); 157} 158 159void BrowsingDataQuotaHelperImpl::OnComplete() { 160 if (!ui_thread_->BelongsToCurrentThread()) { 161 ui_thread_->PostTask( 162 FROM_HERE, 163 base::Bind(&BrowsingDataQuotaHelperImpl::OnComplete, this)); 164 return; 165 } 166 167 is_fetching_ = false; 168 169 QuotaInfoArray result; 170 171 for (std::map<std::string, QuotaInfo>::iterator itr = quota_info_.begin(); 172 itr != quota_info_.end(); 173 ++itr) { 174 QuotaInfo* info = &itr->second; 175 // Skip unused entries 176 if (info->temporary_usage <= 0 && 177 info->persistent_usage <= 0 && 178 info->syncable_usage <= 0) 179 continue; 180 181 info->host = itr->first; 182 result.push_back(*info); 183 } 184 185 callback_.Run(result); 186 callback_.Reset(); 187} 188 189void BrowsingDataQuotaHelperImpl::DidRevokeHostQuota( 190 storage::QuotaStatusCode status_unused, 191 int64 quota_unused) { 192} 193