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 "storage/browser/fileapi/file_system_quota_client.h"
6
7#include <algorithm>
8#include <set>
9
10#include "base/bind.h"
11#include "base/files/file_path.h"
12#include "base/files/file_util.h"
13#include "base/location.h"
14#include "base/logging.h"
15#include "base/memory/scoped_ptr.h"
16#include "base/sequenced_task_runner.h"
17#include "base/single_thread_task_runner.h"
18#include "base/task_runner_util.h"
19#include "net/base/net_util.h"
20#include "storage/browser/fileapi/file_system_context.h"
21#include "storage/browser/fileapi/file_system_quota_util.h"
22#include "storage/browser/fileapi/file_system_usage_cache.h"
23#include "storage/browser/fileapi/sandbox_file_system_backend.h"
24#include "storage/common/fileapi/file_system_util.h"
25#include "url/gurl.h"
26
27using storage::StorageType;
28
29namespace storage {
30
31namespace {
32
33void GetOriginsForTypeOnFileTaskRunner(
34    FileSystemContext* context,
35    StorageType storage_type,
36    std::set<GURL>* origins_ptr) {
37  FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
38  DCHECK(type != kFileSystemTypeUnknown);
39
40  FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type);
41  if (!quota_util)
42    return;
43  quota_util->GetOriginsForTypeOnFileTaskRunner(type, origins_ptr);
44}
45
46void GetOriginsForHostOnFileTaskRunner(
47    FileSystemContext* context,
48    StorageType storage_type,
49    const std::string& host,
50    std::set<GURL>* origins_ptr) {
51  FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
52  DCHECK(type != kFileSystemTypeUnknown);
53
54  FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type);
55  if (!quota_util)
56    return;
57  quota_util->GetOriginsForHostOnFileTaskRunner(type, host, origins_ptr);
58}
59
60void DidGetOrigins(const storage::QuotaClient::GetOriginsCallback& callback,
61                   std::set<GURL>* origins_ptr) {
62  callback.Run(*origins_ptr);
63}
64
65storage::QuotaStatusCode DeleteOriginOnFileTaskRunner(
66    FileSystemContext* context,
67    const GURL& origin,
68    FileSystemType type) {
69  FileSystemBackend* provider = context->GetFileSystemBackend(type);
70  if (!provider || !provider->GetQuotaUtil())
71    return storage::kQuotaErrorNotSupported;
72  base::File::Error result =
73      provider->GetQuotaUtil()->DeleteOriginDataOnFileTaskRunner(
74          context, context->quota_manager_proxy(), origin, type);
75  if (result == base::File::FILE_OK)
76    return storage::kQuotaStatusOk;
77  return storage::kQuotaErrorInvalidModification;
78}
79
80}  // namespace
81
82FileSystemQuotaClient::FileSystemQuotaClient(
83    FileSystemContext* file_system_context,
84    bool is_incognito)
85    : file_system_context_(file_system_context),
86      is_incognito_(is_incognito) {
87}
88
89FileSystemQuotaClient::~FileSystemQuotaClient() {}
90
91storage::QuotaClient::ID FileSystemQuotaClient::id() const {
92  return storage::QuotaClient::kFileSystem;
93}
94
95void FileSystemQuotaClient::OnQuotaManagerDestroyed() {
96  delete this;
97}
98
99void FileSystemQuotaClient::GetOriginUsage(
100    const GURL& origin_url,
101    StorageType storage_type,
102    const GetUsageCallback& callback) {
103  DCHECK(!callback.is_null());
104
105  if (is_incognito_) {
106    // We don't support FileSystem in incognito mode yet.
107    callback.Run(0);
108    return;
109  }
110
111  FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
112  DCHECK(type != kFileSystemTypeUnknown);
113
114  FileSystemQuotaUtil* quota_util = file_system_context_->GetQuotaUtil(type);
115  if (!quota_util) {
116    callback.Run(0);
117    return;
118  }
119
120  base::PostTaskAndReplyWithResult(
121      file_task_runner(),
122      FROM_HERE,
123      // It is safe to pass Unretained(quota_util) since context owns it.
124      base::Bind(&FileSystemQuotaUtil::GetOriginUsageOnFileTaskRunner,
125                 base::Unretained(quota_util),
126                 file_system_context_,
127                 origin_url,
128                 type),
129      callback);
130}
131
132void FileSystemQuotaClient::GetOriginsForType(
133    StorageType storage_type,
134    const GetOriginsCallback& callback) {
135  DCHECK(!callback.is_null());
136
137  if (is_incognito_) {
138    // We don't support FileSystem in incognito mode yet.
139    std::set<GURL> origins;
140    callback.Run(origins);
141    return;
142  }
143
144  std::set<GURL>* origins_ptr = new std::set<GURL>();
145  file_task_runner()->PostTaskAndReply(
146      FROM_HERE,
147      base::Bind(&GetOriginsForTypeOnFileTaskRunner,
148                 file_system_context_,
149                 storage_type,
150                 base::Unretained(origins_ptr)),
151      base::Bind(&DidGetOrigins,
152                 callback,
153                 base::Owned(origins_ptr)));
154}
155
156void FileSystemQuotaClient::GetOriginsForHost(
157    StorageType storage_type,
158    const std::string& host,
159    const GetOriginsCallback& callback) {
160  DCHECK(!callback.is_null());
161
162  if (is_incognito_) {
163    // We don't support FileSystem in incognito mode yet.
164    std::set<GURL> origins;
165    callback.Run(origins);
166    return;
167  }
168
169  std::set<GURL>* origins_ptr = new std::set<GURL>();
170  file_task_runner()->PostTaskAndReply(
171      FROM_HERE,
172      base::Bind(&GetOriginsForHostOnFileTaskRunner,
173                 file_system_context_,
174                 storage_type,
175                 host,
176                 base::Unretained(origins_ptr)),
177      base::Bind(&DidGetOrigins,
178                 callback,
179                 base::Owned(origins_ptr)));
180}
181
182void FileSystemQuotaClient::DeleteOriginData(
183    const GURL& origin,
184    StorageType type,
185    const DeletionCallback& callback) {
186  FileSystemType fs_type = QuotaStorageTypeToFileSystemType(type);
187  DCHECK(fs_type != kFileSystemTypeUnknown);
188
189  base::PostTaskAndReplyWithResult(
190      file_task_runner(),
191      FROM_HERE,
192      base::Bind(&DeleteOriginOnFileTaskRunner,
193                 file_system_context_,
194                 origin,
195                 fs_type),
196      callback);
197}
198
199bool FileSystemQuotaClient::DoesSupport(
200    storage::StorageType storage_type) const {
201  FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
202  DCHECK(type != kFileSystemTypeUnknown);
203  return file_system_context_->IsSandboxFileSystem(type);
204}
205
206base::SequencedTaskRunner* FileSystemQuotaClient::file_task_runner() const {
207  return file_system_context_->default_file_task_runner();
208}
209
210}  // namespace storage
211