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 "content/public/test/mock_storage_client.h"
6
7#include "base/basictypes.h"
8#include "base/bind.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/memory/singleton.h"
11#include "base/message_loop/message_loop_proxy.h"
12#include "base/stl_util.h"
13#include "net/base/net_util.h"
14#include "storage/browser/quota/quota_manager_proxy.h"
15
16using storage::kQuotaErrorInvalidModification;
17using storage::kQuotaStatusOk;
18
19namespace content {
20
21using std::make_pair;
22
23MockStorageClient::MockStorageClient(
24    QuotaManagerProxy* quota_manager_proxy,
25    const MockOriginData* mock_data, QuotaClient::ID id, size_t mock_data_size)
26    : quota_manager_proxy_(quota_manager_proxy),
27      id_(id),
28      mock_time_counter_(0),
29      weak_factory_(this) {
30  Populate(mock_data, mock_data_size);
31}
32
33void MockStorageClient::Populate(
34    const MockOriginData* mock_data,
35    size_t mock_data_size) {
36  for (size_t i = 0; i < mock_data_size; ++i) {
37    origin_data_[make_pair(GURL(mock_data[i].origin), mock_data[i].type)] =
38        mock_data[i].usage;
39  }
40}
41
42MockStorageClient::~MockStorageClient() {}
43
44void MockStorageClient::AddOriginAndNotify(
45    const GURL& origin_url, StorageType type, int64 size) {
46  DCHECK(origin_data_.find(make_pair(origin_url, type)) == origin_data_.end());
47  DCHECK_GE(size, 0);
48  origin_data_[make_pair(origin_url, type)] = size;
49  quota_manager_proxy_->quota_manager()->NotifyStorageModifiedInternal(
50      id(), origin_url, type, size, IncrementMockTime());
51}
52
53void MockStorageClient::ModifyOriginAndNotify(
54    const GURL& origin_url, StorageType type, int64 delta) {
55  OriginDataMap::iterator find = origin_data_.find(make_pair(origin_url, type));
56  DCHECK(find != origin_data_.end());
57  find->second += delta;
58  DCHECK_GE(find->second, 0);
59
60  // TODO(tzik): Check quota to prevent usage exceed
61  quota_manager_proxy_->quota_manager()->NotifyStorageModifiedInternal(
62      id(), origin_url, type, delta, IncrementMockTime());
63}
64
65void MockStorageClient::TouchAllOriginsAndNotify() {
66  for (OriginDataMap::const_iterator itr = origin_data_.begin();
67       itr != origin_data_.end();
68       ++itr) {
69    quota_manager_proxy_->quota_manager()->NotifyStorageModifiedInternal(
70        id(), itr->first.first, itr->first.second, 0, IncrementMockTime());
71  }
72}
73
74void MockStorageClient::AddOriginToErrorSet(
75    const GURL& origin_url, StorageType type) {
76  error_origins_.insert(make_pair(origin_url, type));
77}
78
79base::Time MockStorageClient::IncrementMockTime() {
80  ++mock_time_counter_;
81  return base::Time::FromDoubleT(mock_time_counter_ * 10.0);
82}
83
84QuotaClient::ID MockStorageClient::id() const {
85  return id_;
86}
87
88void MockStorageClient::OnQuotaManagerDestroyed() {
89  delete this;
90}
91
92void MockStorageClient::GetOriginUsage(const GURL& origin_url,
93                                       StorageType type,
94                                       const GetUsageCallback& callback) {
95  base::MessageLoopProxy::current()->PostTask(
96      FROM_HERE,
97      base::Bind(&MockStorageClient::RunGetOriginUsage,
98                 weak_factory_.GetWeakPtr(), origin_url, type, callback));
99}
100
101void MockStorageClient::GetOriginsForType(
102    StorageType type, const GetOriginsCallback& callback) {
103  base::MessageLoopProxy::current()->PostTask(
104      FROM_HERE,
105      base::Bind(&MockStorageClient::RunGetOriginsForType,
106                 weak_factory_.GetWeakPtr(), type, callback));
107}
108
109void MockStorageClient::GetOriginsForHost(
110    StorageType type, const std::string& host,
111    const GetOriginsCallback& callback) {
112  base::MessageLoopProxy::current()->PostTask(
113      FROM_HERE,
114      base::Bind(&MockStorageClient::RunGetOriginsForHost,
115                 weak_factory_.GetWeakPtr(), type, host, callback));
116}
117
118void MockStorageClient::DeleteOriginData(
119    const GURL& origin, StorageType type,
120    const DeletionCallback& callback) {
121  base::MessageLoopProxy::current()->PostTask(
122      FROM_HERE,
123      base::Bind(&MockStorageClient::RunDeleteOriginData,
124                 weak_factory_.GetWeakPtr(), origin, type, callback));
125}
126
127bool MockStorageClient::DoesSupport(storage::StorageType type) const {
128  return true;
129}
130
131void MockStorageClient::RunGetOriginUsage(
132    const GURL& origin_url, StorageType type,
133    const GetUsageCallback& callback) {
134  OriginDataMap::iterator find = origin_data_.find(make_pair(origin_url, type));
135  if (find == origin_data_.end()) {
136    callback.Run(0);
137  } else {
138    callback.Run(find->second);
139  }
140}
141
142void MockStorageClient::RunGetOriginsForType(
143    StorageType type, const GetOriginsCallback& callback) {
144  std::set<GURL> origins;
145  for (OriginDataMap::iterator iter = origin_data_.begin();
146       iter != origin_data_.end(); ++iter) {
147    if (type == iter->first.second)
148      origins.insert(iter->first.first);
149  }
150  callback.Run(origins);
151}
152
153void MockStorageClient::RunGetOriginsForHost(
154    StorageType type, const std::string& host,
155    const GetOriginsCallback& callback) {
156  std::set<GURL> origins;
157  for (OriginDataMap::iterator iter = origin_data_.begin();
158       iter != origin_data_.end(); ++iter) {
159    std::string host_or_spec = net::GetHostOrSpecFromURL(iter->first.first);
160    if (type == iter->first.second && host == host_or_spec)
161      origins.insert(iter->first.first);
162  }
163  callback.Run(origins);
164}
165
166void MockStorageClient::RunDeleteOriginData(
167    const GURL& origin_url,
168    StorageType type,
169    const DeletionCallback& callback) {
170  ErrorOriginSet::iterator itr_error =
171      error_origins_.find(make_pair(origin_url, type));
172  if (itr_error != error_origins_.end()) {
173    callback.Run(kQuotaErrorInvalidModification);
174    return;
175  }
176
177  OriginDataMap::iterator itr =
178      origin_data_.find(make_pair(origin_url, type));
179  if (itr != origin_data_.end()) {
180    int64 delta = itr->second;
181    quota_manager_proxy_->
182        NotifyStorageModified(id(), origin_url, type, -delta);
183    origin_data_.erase(itr);
184  }
185
186  callback.Run(kQuotaStatusOk);
187}
188
189}  // namespace content
190