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