// Copyright (c) 2011 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 "webkit/quota/mock_storage_client.h" #include "base/atomic_sequence_num.h" #include "base/basictypes.h" #include "base/bind.h" #include "base/memory/scoped_ptr.h" #include "base/memory/singleton.h" #include "base/message_loop_proxy.h" #include "base/stl_util.h" #include "net/base/net_util.h" #include "webkit/quota/quota_manager.h" using base::AtomicSequenceNumber; namespace quota { namespace { using std::make_pair; class MockStorageClientIDSequencer { public: static MockStorageClientIDSequencer* GetInstance() { return Singleton::get(); } QuotaClient::ID NextMockID() { return static_cast( QuotaClient::kMockStart + seq_.GetNext()); } private: MockStorageClientIDSequencer() { } friend struct DefaultSingletonTraits; AtomicSequenceNumber seq_; DISALLOW_COPY_AND_ASSIGN(MockStorageClientIDSequencer); }; } // anonymous namespace MockStorageClient::MockStorageClient( QuotaManagerProxy* quota_manager_proxy, const MockOriginData* mock_data, size_t mock_data_size) : quota_manager_proxy_(quota_manager_proxy), id_(MockStorageClientIDSequencer::GetInstance()->NextMockID()), mock_time_counter_(0), ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { for (size_t i = 0; i < mock_data_size; ++i) { origin_data_[make_pair(GURL(mock_data[i].origin), mock_data[i].type)] = mock_data[i].usage; } } MockStorageClient::~MockStorageClient() {} void MockStorageClient::AddOriginAndNotify( const GURL& origin_url, StorageType type, int64 size) { DCHECK(origin_data_.find(make_pair(origin_url, type)) == origin_data_.end()); DCHECK_GE(size, 0); origin_data_[make_pair(origin_url, type)] = size; quota_manager_proxy_->quota_manager()->NotifyStorageModifiedInternal( id(), origin_url, type, size, IncrementMockTime()); } void MockStorageClient::ModifyOriginAndNotify( const GURL& origin_url, StorageType type, int64 delta) { OriginDataMap::iterator find = origin_data_.find(make_pair(origin_url, type)); DCHECK(find != origin_data_.end()); find->second += delta; DCHECK_GE(find->second, 0); // TODO(tzik): Check quota to prevent usage exceed quota_manager_proxy_->quota_manager()->NotifyStorageModifiedInternal( id(), origin_url, type, delta, IncrementMockTime()); } void MockStorageClient::TouchAllOriginsAndNotify() { for (OriginDataMap::const_iterator itr = origin_data_.begin(); itr != origin_data_.end(); ++itr) { quota_manager_proxy_->quota_manager()->NotifyStorageModifiedInternal( id(), itr->first.first, itr->first.second, 0, IncrementMockTime()); } } void MockStorageClient::AddOriginToErrorSet( const GURL& origin_url, StorageType type) { error_origins_.insert(make_pair(origin_url, type)); } base::Time MockStorageClient::IncrementMockTime() { ++mock_time_counter_; return base::Time::FromDoubleT(mock_time_counter_ * 10.0); } QuotaClient::ID MockStorageClient::id() const { return id_; } void MockStorageClient::OnQuotaManagerDestroyed() { delete this; } void MockStorageClient::GetOriginUsage(const GURL& origin_url, StorageType type, const GetUsageCallback& callback) { base::MessageLoopProxy::current()->PostTask( FROM_HERE, base::Bind(&MockStorageClient::RunGetOriginUsage, weak_factory_.GetWeakPtr(), origin_url, type, callback)); } void MockStorageClient::GetOriginsForType( StorageType type, const GetOriginsCallback& callback) { base::MessageLoopProxy::current()->PostTask( FROM_HERE, base::Bind(&MockStorageClient::RunGetOriginsForType, weak_factory_.GetWeakPtr(), type, callback)); } void MockStorageClient::GetOriginsForHost( StorageType type, const std::string& host, const GetOriginsCallback& callback) { base::MessageLoopProxy::current()->PostTask( FROM_HERE, base::Bind(&MockStorageClient::RunGetOriginsForHost, weak_factory_.GetWeakPtr(), type, host, callback)); } void MockStorageClient::DeleteOriginData( const GURL& origin, StorageType type, const DeletionCallback& callback) { base::MessageLoopProxy::current()->PostTask( FROM_HERE, base::Bind(&MockStorageClient::RunDeleteOriginData, weak_factory_.GetWeakPtr(), origin, type, callback)); } void MockStorageClient::RunGetOriginUsage( const GURL& origin_url, StorageType type, const GetUsageCallback& callback) { OriginDataMap::iterator find = origin_data_.find(make_pair(origin_url, type)); if (find == origin_data_.end()) { callback.Run(0); } else { callback.Run(find->second); } } void MockStorageClient::RunGetOriginsForType( StorageType type, const GetOriginsCallback& callback) { std::set origins; for (OriginDataMap::iterator iter = origin_data_.begin(); iter != origin_data_.end(); ++iter) { if (type == iter->first.second) origins.insert(iter->first.first); } callback.Run(origins, type); } void MockStorageClient::RunGetOriginsForHost( StorageType type, const std::string& host, const GetOriginsCallback& callback) { std::set origins; for (OriginDataMap::iterator iter = origin_data_.begin(); iter != origin_data_.end(); ++iter) { std::string host_or_spec = net::GetHostOrSpecFromURL(iter->first.first); if (type == iter->first.second && host == host_or_spec) origins.insert(iter->first.first); } callback.Run(origins, type); } void MockStorageClient::RunDeleteOriginData( const GURL& origin_url, StorageType type, const DeletionCallback& callback) { ErrorOriginSet::iterator itr_error = error_origins_.find(make_pair(origin_url, type)); if (itr_error != error_origins_.end()) { callback.Run(kQuotaErrorInvalidModification); return; } OriginDataMap::iterator itr = origin_data_.find(make_pair(origin_url, type)); if (itr != origin_data_.end()) { int64 delta = itr->second; quota_manager_proxy_-> NotifyStorageModified(id(), origin_url, type, -delta); origin_data_.erase(itr); } callback.Run(kQuotaStatusOk); } } // namespace quota