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/ui/webui/quota_internals/quota_internals_proxy.h"
6
7#include <set>
8#include <string>
9
10#include "base/bind.h"
11#include "chrome/browser/ui/webui/quota_internals/quota_internals_handler.h"
12#include "chrome/browser/ui/webui/quota_internals/quota_internals_types.h"
13#include "net/base/net_util.h"
14
15using content::BrowserThread;
16
17namespace quota_internals {
18
19QuotaInternalsProxy::QuotaInternalsProxy(QuotaInternalsHandler* handler)
20    : handler_(handler),
21      weak_factory_(this) {
22}
23
24void QuotaInternalsProxy::RequestInfo(
25    scoped_refptr<storage::QuotaManager> quota_manager) {
26  DCHECK(quota_manager.get());
27  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
28    BrowserThread::PostTask(
29        BrowserThread::IO, FROM_HERE,
30        base::Bind(&QuotaInternalsProxy::RequestInfo, this, quota_manager));
31    return;
32  }
33
34  quota_manager_ = quota_manager;
35  quota_manager_->GetAvailableSpace(
36      base::Bind(&QuotaInternalsProxy::DidGetAvailableSpace,
37                 weak_factory_.GetWeakPtr()));
38
39  quota_manager_->GetTemporaryGlobalQuota(
40      base::Bind(&QuotaInternalsProxy::DidGetGlobalQuota,
41                 weak_factory_.GetWeakPtr(),
42                 storage::kStorageTypeTemporary));
43
44  quota_manager_->GetGlobalUsage(
45      storage::kStorageTypeTemporary,
46      base::Bind(&QuotaInternalsProxy::DidGetGlobalUsage,
47                 weak_factory_.GetWeakPtr(),
48                 storage::kStorageTypeTemporary));
49
50  quota_manager_->GetGlobalUsage(
51      storage::kStorageTypePersistent,
52      base::Bind(&QuotaInternalsProxy::DidGetGlobalUsage,
53                 weak_factory_.GetWeakPtr(),
54                 storage::kStorageTypePersistent));
55
56  quota_manager_->GetGlobalUsage(
57      storage::kStorageTypeSyncable,
58      base::Bind(&QuotaInternalsProxy::DidGetGlobalUsage,
59                 weak_factory_.GetWeakPtr(),
60                 storage::kStorageTypeSyncable));
61
62  quota_manager_->DumpQuotaTable(
63      base::Bind(&QuotaInternalsProxy::DidDumpQuotaTable,
64                 weak_factory_.GetWeakPtr()));
65
66  quota_manager_->DumpOriginInfoTable(
67      base::Bind(&QuotaInternalsProxy::DidDumpOriginInfoTable,
68                 weak_factory_.GetWeakPtr()));
69
70  std::map<std::string, std::string> stats;
71  quota_manager_->GetStatistics(&stats);
72  ReportStatistics(stats);
73}
74
75QuotaInternalsProxy::~QuotaInternalsProxy() {}
76
77#define RELAY_TO_HANDLER(func, arg_t) \
78  void QuotaInternalsProxy::func(arg_t arg) {                 \
79    if (!handler_)                                            \
80      return;                                                 \
81    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {     \
82      BrowserThread::PostTask(                                \
83          BrowserThread::UI, FROM_HERE,                       \
84          base::Bind(&QuotaInternalsProxy::func, this, arg)); \
85      return;                                                 \
86    }                                                         \
87                                                              \
88    handler_->func(arg);                                      \
89  }
90
91RELAY_TO_HANDLER(ReportAvailableSpace, int64)
92RELAY_TO_HANDLER(ReportGlobalInfo, const GlobalStorageInfo&)
93RELAY_TO_HANDLER(ReportPerHostInfo, const std::vector<PerHostStorageInfo>&)
94RELAY_TO_HANDLER(ReportPerOriginInfo, const std::vector<PerOriginStorageInfo>&)
95RELAY_TO_HANDLER(ReportStatistics, const Statistics&)
96
97#undef RELAY_TO_HANDLER
98
99void QuotaInternalsProxy::DidGetAvailableSpace(storage::QuotaStatusCode status,
100                                               int64 space) {
101  if (status == storage::kQuotaStatusOk)
102    ReportAvailableSpace(space);
103}
104
105void QuotaInternalsProxy::DidGetGlobalQuota(storage::StorageType type,
106                                            storage::QuotaStatusCode status,
107                                            int64 quota) {
108  if (status == storage::kQuotaStatusOk) {
109    GlobalStorageInfo info(type);
110    info.set_quota(quota);
111    ReportGlobalInfo(info);
112  }
113}
114
115void QuotaInternalsProxy::DidGetGlobalUsage(storage::StorageType type,
116                                            int64 usage,
117                                            int64 unlimited_usage) {
118  GlobalStorageInfo info(type);
119  info.set_usage(usage);
120  info.set_unlimited_usage(unlimited_usage);
121
122  ReportGlobalInfo(info);
123  RequestPerOriginInfo(type);
124}
125
126void QuotaInternalsProxy::DidDumpQuotaTable(const QuotaTableEntries& entries) {
127  std::vector<PerHostStorageInfo> host_info;
128  host_info.reserve(entries.size());
129
130  typedef QuotaTableEntries::const_iterator iterator;
131  for (iterator itr(entries.begin()); itr != entries.end(); ++itr) {
132    PerHostStorageInfo info(itr->host, itr->type);
133    info.set_quota(itr->quota);
134    host_info.push_back(info);
135  }
136
137  ReportPerHostInfo(host_info);
138}
139
140void QuotaInternalsProxy::DidDumpOriginInfoTable(
141    const OriginInfoTableEntries& entries) {
142  std::vector<PerOriginStorageInfo> origin_info;
143  origin_info.reserve(entries.size());
144
145  typedef OriginInfoTableEntries::const_iterator iterator;
146  for (iterator itr(entries.begin()); itr != entries.end(); ++itr) {
147    PerOriginStorageInfo info(itr->origin, itr->type);
148    info.set_used_count(itr->used_count);
149    info.set_last_access_time(itr->last_access_time);
150    info.set_last_modified_time(itr->last_modified_time);
151
152    origin_info.push_back(info);
153  }
154
155  ReportPerOriginInfo(origin_info);
156}
157
158void QuotaInternalsProxy::DidGetHostUsage(const std::string& host,
159                                          storage::StorageType type,
160                                          int64 usage) {
161  DCHECK(type == storage::kStorageTypeTemporary ||
162         type == storage::kStorageTypePersistent ||
163         type == storage::kStorageTypeSyncable);
164
165  PerHostStorageInfo info(host, type);
166  info.set_usage(usage);
167
168  report_pending_.push_back(info);
169  hosts_pending_.erase(make_pair(host, type));
170  if (report_pending_.size() >= 10 || hosts_pending_.empty()) {
171    ReportPerHostInfo(report_pending_);
172    report_pending_.clear();
173  }
174
175  if (!hosts_pending_.empty())
176    GetHostUsage(hosts_pending_.begin()->first,
177                 hosts_pending_.begin()->second);
178}
179
180void QuotaInternalsProxy::RequestPerOriginInfo(storage::StorageType type) {
181  DCHECK(quota_manager_.get());
182
183  std::set<GURL> origins;
184  quota_manager_->GetCachedOrigins(type, &origins);
185
186  std::vector<PerOriginStorageInfo> origin_info;
187  origin_info.reserve(origins.size());
188
189  std::set<std::string> hosts;
190  std::vector<PerHostStorageInfo> host_info;
191
192  for (std::set<GURL>::iterator itr(origins.begin());
193       itr != origins.end(); ++itr) {
194    PerOriginStorageInfo info(*itr, type);
195    info.set_in_use(quota_manager_->IsOriginInUse(*itr));
196    origin_info.push_back(info);
197
198    std::string host(net::GetHostOrSpecFromURL(*itr));
199    if (hosts.insert(host).second) {
200      PerHostStorageInfo info(host, type);
201      host_info.push_back(info);
202      VisitHost(host, type);
203    }
204  }
205  ReportPerOriginInfo(origin_info);
206  ReportPerHostInfo(host_info);
207}
208
209void QuotaInternalsProxy::VisitHost(const std::string& host,
210                                    storage::StorageType type) {
211  if (hosts_visited_.insert(std::make_pair(host, type)).second) {
212    hosts_pending_.insert(std::make_pair(host, type));
213    if (hosts_pending_.size() == 1) {
214      GetHostUsage(host, type);
215    }
216  }
217}
218
219void QuotaInternalsProxy::GetHostUsage(const std::string& host,
220                                       storage::StorageType type) {
221  DCHECK(quota_manager_.get());
222  quota_manager_->GetHostUsage(host,
223                               type,
224                               base::Bind(&QuotaInternalsProxy::DidGetHostUsage,
225                                          weak_factory_.GetWeakPtr(),
226                                          host,
227                                          type));
228}
229
230}  // namespace quota_internals
231