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 "content/browser/indexed_db/indexed_db_quota_client.h"
6
7#include <vector>
8
9#include "base/logging.h"
10#include "content/browser/indexed_db/indexed_db_context_impl.h"
11#include "content/public/browser/browser_thread.h"
12#include "net/base/net_util.h"
13#include "storage/browser/database/database_util.h"
14
15using storage::QuotaClient;
16using storage::DatabaseUtil;
17
18namespace content {
19namespace {
20
21storage::QuotaStatusCode DeleteOriginDataOnIndexedDBThread(
22    IndexedDBContextImpl* context,
23    const GURL& origin) {
24  context->DeleteForOrigin(origin);
25  return storage::kQuotaStatusOk;
26}
27
28int64 GetOriginUsageOnIndexedDBThread(IndexedDBContextImpl* context,
29                                      const GURL& origin) {
30  DCHECK(context->TaskRunner()->RunsTasksOnCurrentThread());
31  return context->GetOriginDiskUsage(origin);
32}
33
34void GetAllOriginsOnIndexedDBThread(IndexedDBContextImpl* context,
35                                    std::set<GURL>* origins_to_return) {
36  DCHECK(context->TaskRunner()->RunsTasksOnCurrentThread());
37  std::vector<GURL> all_origins = context->GetAllOrigins();
38  origins_to_return->insert(all_origins.begin(), all_origins.end());
39}
40
41void DidGetOrigins(const IndexedDBQuotaClient::GetOriginsCallback& callback,
42                   const std::set<GURL>* origins) {
43  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
44  callback.Run(*origins);
45}
46
47void GetOriginsForHostOnIndexedDBThread(IndexedDBContextImpl* context,
48                                        const std::string& host,
49                                        std::set<GURL>* origins_to_return) {
50  DCHECK(context->TaskRunner()->RunsTasksOnCurrentThread());
51  std::vector<GURL> all_origins = context->GetAllOrigins();
52  for (std::vector<GURL>::const_iterator iter = all_origins.begin();
53       iter != all_origins.end();
54       ++iter) {
55    if (host == net::GetHostOrSpecFromURL(*iter))
56      origins_to_return->insert(*iter);
57  }
58}
59
60}  // namespace
61
62// IndexedDBQuotaClient --------------------------------------------------------
63
64IndexedDBQuotaClient::IndexedDBQuotaClient(
65    IndexedDBContextImpl* indexed_db_context)
66    : indexed_db_context_(indexed_db_context) {}
67
68IndexedDBQuotaClient::~IndexedDBQuotaClient() {}
69
70QuotaClient::ID IndexedDBQuotaClient::id() const { return kIndexedDatabase; }
71
72void IndexedDBQuotaClient::OnQuotaManagerDestroyed() { delete this; }
73
74void IndexedDBQuotaClient::GetOriginUsage(const GURL& origin_url,
75                                          storage::StorageType type,
76                                          const GetUsageCallback& callback) {
77  DCHECK(!callback.is_null());
78  DCHECK(indexed_db_context_.get());
79
80  // IndexedDB is in the temp namespace for now.
81  if (type != storage::kStorageTypeTemporary) {
82    callback.Run(0);
83    return;
84  }
85
86  // No task runner means unit test; no cleanup necessary.
87  if (!indexed_db_context_->TaskRunner()) {
88    callback.Run(0);
89    return;
90  }
91
92  base::PostTaskAndReplyWithResult(
93      indexed_db_context_->TaskRunner(),
94      FROM_HERE,
95      base::Bind(
96          &GetOriginUsageOnIndexedDBThread, indexed_db_context_, origin_url),
97      callback);
98}
99
100void IndexedDBQuotaClient::GetOriginsForType(
101    storage::StorageType type,
102    const GetOriginsCallback& callback) {
103  DCHECK(!callback.is_null());
104  DCHECK(indexed_db_context_.get());
105
106  // All databases are in the temp namespace for now.
107  if (type != storage::kStorageTypeTemporary) {
108    callback.Run(std::set<GURL>());
109    return;
110  }
111
112  // No task runner means unit test; no cleanup necessary.
113  if (!indexed_db_context_->TaskRunner()) {
114    callback.Run(std::set<GURL>());
115    return;
116  }
117
118  std::set<GURL>* origins_to_return = new std::set<GURL>();
119  indexed_db_context_->TaskRunner()->PostTaskAndReply(
120      FROM_HERE,
121      base::Bind(&GetAllOriginsOnIndexedDBThread,
122                 indexed_db_context_,
123                 base::Unretained(origins_to_return)),
124      base::Bind(&DidGetOrigins, callback, base::Owned(origins_to_return)));
125}
126
127void IndexedDBQuotaClient::GetOriginsForHost(
128    storage::StorageType type,
129    const std::string& host,
130    const GetOriginsCallback& callback) {
131  DCHECK(!callback.is_null());
132  DCHECK(indexed_db_context_.get());
133
134  // All databases are in the temp namespace for now.
135  if (type != storage::kStorageTypeTemporary) {
136    callback.Run(std::set<GURL>());
137    return;
138  }
139
140  // No task runner means unit test; no cleanup necessary.
141  if (!indexed_db_context_->TaskRunner()) {
142    callback.Run(std::set<GURL>());
143    return;
144  }
145
146  std::set<GURL>* origins_to_return = new std::set<GURL>();
147  indexed_db_context_->TaskRunner()->PostTaskAndReply(
148      FROM_HERE,
149      base::Bind(&GetOriginsForHostOnIndexedDBThread,
150                 indexed_db_context_,
151                 host,
152                 base::Unretained(origins_to_return)),
153      base::Bind(&DidGetOrigins, callback, base::Owned(origins_to_return)));
154}
155
156void IndexedDBQuotaClient::DeleteOriginData(const GURL& origin,
157                                            storage::StorageType type,
158                                            const DeletionCallback& callback) {
159  if (type != storage::kStorageTypeTemporary) {
160    callback.Run(storage::kQuotaErrorNotSupported);
161    return;
162  }
163
164  // No task runner means unit test; no cleanup necessary.
165  if (!indexed_db_context_->TaskRunner()) {
166    callback.Run(storage::kQuotaStatusOk);
167    return;
168  }
169
170  base::PostTaskAndReplyWithResult(
171      indexed_db_context_->TaskRunner(),
172      FROM_HERE,
173      base::Bind(
174          &DeleteOriginDataOnIndexedDBThread, indexed_db_context_, origin),
175      callback);
176}
177
178bool IndexedDBQuotaClient::DoesSupport(storage::StorageType type) const {
179  return type == storage::kStorageTypeTemporary;
180}
181
182}  // namespace content
183