1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "webkit/browser/fileapi/quota/quota_backend_impl.h"
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <string>
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/bind.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/callback.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/sequenced_task_runner.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_usage_cache.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "webkit/browser/quota/quota_client.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "webkit/browser/quota/quota_manager.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "webkit/common/fileapi/file_system_util.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace fileapi {
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)QuotaBackendImpl::QuotaBackendImpl(
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::SequencedTaskRunner* file_task_runner,
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ObfuscatedFileUtil* obfuscated_file_util,
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    FileSystemUsageCache* file_system_usage_cache,
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    quota::QuotaManagerProxy* quota_manager_proxy)
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : file_task_runner_(file_task_runner),
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      obfuscated_file_util_(obfuscated_file_util),
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      file_system_usage_cache_(file_system_usage_cache),
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      quota_manager_proxy_(quota_manager_proxy),
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      weak_ptr_factory_(this) {
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)QuotaBackendImpl::~QuotaBackendImpl() {
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void QuotaBackendImpl::ReserveQuota(const GURL& origin,
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    FileSystemType type,
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    int64 delta,
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    const ReserveQuotaCallback& callback) {
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(origin.is_valid());
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!delta) {
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    callback.Run(base::PLATFORM_FILE_OK);
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(quota_manager_proxy_);
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  quota_manager_proxy_->GetUsageAndQuota(
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      file_task_runner_, origin, FileSystemTypeToQuotaStorageType(type),
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota,
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 QuotaReservationInfo(origin, type, delta), callback));
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void QuotaBackendImpl::ReleaseReservedQuota(const GURL& origin,
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            FileSystemType type,
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            int64 size) {
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(origin.is_valid());
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_LE(0, size);
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!size)
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ReserveQuotaInternal(QuotaReservationInfo(origin, type, -size));
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void QuotaBackendImpl::CommitQuotaUsage(const GURL& origin,
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        FileSystemType type,
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        int64 delta) {
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(origin.is_valid());
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!delta)
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ReserveQuotaInternal(QuotaReservationInfo(origin, type, delta));
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::FilePath path;
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (GetUsageCachePath(origin, type, &path) != base::PLATFORM_FILE_OK)
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool result = file_system_usage_cache_->AtomicUpdateUsageByDelta(path, delta);
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(result);
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void QuotaBackendImpl::IncrementDirtyCount(const GURL& origin,
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                           FileSystemType type) {
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(origin.is_valid());
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::FilePath path;
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (GetUsageCachePath(origin, type, &path) != base::PLATFORM_FILE_OK)
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(file_system_usage_cache_);
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  file_system_usage_cache_->IncrementDirty(path);
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void QuotaBackendImpl::DecrementDirtyCount(const GURL& origin,
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                           FileSystemType type) {
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(origin.is_valid());
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::FilePath path;
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (GetUsageCachePath(origin, type, &path) != base::PLATFORM_FILE_OK)
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(file_system_usage_cache_);
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  file_system_usage_cache_->DecrementDirty(path);
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota(
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const QuotaReservationInfo& info,
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const ReserveQuotaCallback& callback,
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    quota::QuotaStatusCode status, int64 usage, int64 quota) {
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(info.origin.is_valid());
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (status != quota::kQuotaStatusOk) {
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    callback.Run(base::PLATFORM_FILE_ERROR_FAILED);
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (quota < usage + info.delta) {
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    callback.Run(base::PLATFORM_FILE_ERROR_NO_SPACE);
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ReserveQuotaInternal(info);
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (callback.Run(base::PLATFORM_FILE_OK))
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The requester could not accept the reserved quota. Revert it.
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ReserveQuotaInternal(
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      QuotaReservationInfo(info.origin, info.type, -info.delta));
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) {
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(info.origin.is_valid());
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(quota_manager_proxy_);
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  quota_manager_proxy_->NotifyStorageModified(
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      quota::QuotaClient::kFileSystem, info.origin,
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FileSystemTypeToQuotaStorageType(info.type), info.delta);
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)base::PlatformFileError QuotaBackendImpl::GetUsageCachePath(
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const GURL& origin,
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    FileSystemType type,
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::FilePath* usage_file_path) {
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(origin.is_valid());
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(usage_file_path);
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::PlatformFileError error = base::PLATFORM_FILE_OK;
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  *usage_file_path =
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType(
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          obfuscated_file_util_, origin, type, &error);
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return error;
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)QuotaBackendImpl::QuotaReservationInfo::QuotaReservationInfo(
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const GURL& origin, FileSystemType type, int64 delta)
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : origin(origin), type(type), delta(delta) {
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)QuotaBackendImpl::QuotaReservationInfo::~QuotaReservationInfo() {
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace fileapi
157