summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-09 06:29:59 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-09 06:29:59 +0000
commitc62983a7fcbd13cb5aade8da6d4f27c44dd5c069 (patch)
tree7532ffa1f81bbf1eed6dbf5c9009c4c4ecd89f4e
parentd36f941bbea3e9fa6d13829626a1911008b37f17 (diff)
downloadchromium_src-c62983a7fcbd13cb5aade8da6d4f27c44dd5c069.zip
chromium_src-c62983a7fcbd13cb5aade8da6d4f27c44dd5c069.tar.gz
chromium_src-c62983a7fcbd13cb5aade8da6d4f27c44dd5c069.tar.bz2
Implement SandboxQuotaClient for Quota support in sandboxed filesystem
- Refactored FileSystemUsageTracker as a SandboxQuotaClient - Added a few more tests BUG=61676 TEST=SandboxQuotaClientTest.* Review URL: http://codereview.chromium.org/6883002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84604 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_service_unittest.cc9
-rw-r--r--chrome/browser/profiles/profile.cc37
-rw-r--r--chrome/browser/profiles/profile_impl.cc37
-rw-r--r--chrome/browser/profiles/profile_impl.h2
-rw-r--r--content/browser/file_system/browser_file_system_helper.cc5
-rw-r--r--content/browser/file_system/browser_file_system_helper.h6
-rw-r--r--webkit/fileapi/file_system_context.cc37
-rw-r--r--webkit/fileapi/file_system_context.h14
-rw-r--r--webkit/fileapi/file_system_context_unittest.cc2
-rw-r--r--webkit/fileapi/file_system_dir_url_request_job_unittest.cc2
-rw-r--r--webkit/fileapi/file_system_operation_write_unittest.cc2
-rw-r--r--webkit/fileapi/file_system_url_request_job_unittest.cc2
-rw-r--r--webkit/fileapi/file_system_usage_tracker.cc183
-rw-r--r--webkit/fileapi/file_system_usage_tracker.h70
-rw-r--r--webkit/fileapi/file_system_usage_tracker_unittest.cc279
-rw-r--r--webkit/fileapi/file_system_util.cc23
-rw-r--r--webkit/fileapi/file_system_util.h6
-rw-r--r--webkit/fileapi/file_writer_delegate_unittest.cc4
-rw-r--r--webkit/fileapi/local_file_system_file_util_unittest.cc2
-rw-r--r--webkit/fileapi/quota_file_util_unittest.cc2
-rw-r--r--webkit/fileapi/sandbox_mount_point_provider.cc104
-rw-r--r--webkit/fileapi/sandbox_mount_point_provider.h63
-rw-r--r--webkit/fileapi/sandbox_mount_point_provider_unittest.cc61
-rw-r--r--webkit/fileapi/sandbox_quota_client.cc292
-rw-r--r--webkit/fileapi/sandbox_quota_client.h93
-rw-r--r--webkit/fileapi/sandbox_quota_client_unittest.cc431
-rw-r--r--webkit/fileapi/webkit_fileapi.gypi13
-rw-r--r--webkit/quota/mock_storage_client.cc18
-rw-r--r--webkit/quota/mock_storage_client.h13
-rw-r--r--webkit/quota/quota_client.h3
-rw-r--r--webkit/quota/quota_manager.cc83
-rw-r--r--webkit/quota/quota_manager.h68
-rw-r--r--webkit/quota/quota_manager_unittest.cc6
-rw-r--r--webkit/quota/quota_types.h76
-rw-r--r--webkit/quota/usage_tracker.cc8
-rw-r--r--webkit/tools/test_shell/simple_file_system.cc1
-rw-r--r--webkit/tools/test_shell/test_shell.gypi5
37 files changed, 1294 insertions, 768 deletions
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index aa55653..11b050c 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -66,6 +66,7 @@
#include "testing/platform_test.h"
#include "webkit/database/database_tracker.h"
#include "webkit/database/database_util.h"
+#include "webkit/quota/quota_manager.h"
namespace keys = extension_manifest_keys;
@@ -361,9 +362,13 @@ class ExtensionTestingProfile : public TestingProfile {
}
virtual fileapi::FileSystemContext* GetFileSystemContext() {
- if (!file_system_context_)
+ if (!file_system_context_) {
+ quota::QuotaManager* quota_manager = GetQuotaManager();
file_system_context_ = CreateFileSystemContext(
- GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy());
+ GetPath(), IsOffTheRecord(),
+ GetExtensionSpecialStoragePolicy(),
+ quota_manager ? quota_manager->proxy() : NULL);
+ }
return file_system_context_;
}
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc
index a2c0d6f..bcb812a 100644
--- a/chrome/browser/profiles/profile.cc
+++ b/chrome/browser/profiles/profile.cc
@@ -435,10 +435,7 @@ class OffTheRecordProfileImpl : public Profile,
}
virtual fileapi::FileSystemContext* GetFileSystemContext() {
- if (!file_system_context_)
- file_system_context_ = CreateFileSystemContext(
- GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy());
- DCHECK(file_system_context_.get());
+ CreateQuotaManagerAndClients();
return file_system_context_.get();
}
@@ -447,13 +444,7 @@ class OffTheRecordProfileImpl : public Profile,
}
virtual quota::QuotaManager* GetQuotaManager() {
- if (!quota_manager_.get()) {
- quota_manager_ = new quota::QuotaManager(
- IsOffTheRecord(),
- GetPath(),
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB));
- }
+ CreateQuotaManagerAndClients();
return quota_manager_.get();
}
@@ -705,6 +696,30 @@ class OffTheRecordProfileImpl : public Profile,
}
private:
+ void CreateQuotaManagerAndClients() {
+ if (quota_manager_.get()) {
+ DCHECK(file_system_context_.get());
+ return;
+ }
+
+ // All of the clients have to be created and registered with the
+ // QuotaManager prior to the QuotaManger being used. So we do them
+ // all together here prior to handing out a reference to anything
+ // that utlizes the QuotaManager.
+ quota_manager_ = new quota::QuotaManager(
+ IsOffTheRecord(),
+ GetPath(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB));
+
+ // Each consumer is responsible for registering its QuotaClient during
+ // its construction.
+ file_system_context_ = CreateFileSystemContext(
+ GetPath(), IsOffTheRecord(),
+ GetExtensionSpecialStoragePolicy(),
+ quota_manager_->proxy());
+ }
+
NotificationRegistrar registrar_;
// The real underlying profile.
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 216eed9..ae2a519 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -1170,21 +1170,12 @@ PersonalDataManager* ProfileImpl::GetPersonalDataManager() {
}
fileapi::FileSystemContext* ProfileImpl::GetFileSystemContext() {
- if (!file_system_context_.get())
- file_system_context_ = CreateFileSystemContext(
- GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy());
- DCHECK(file_system_context_.get());
+ CreateQuotaManagerAndClients();
return file_system_context_.get();
}
quota::QuotaManager* ProfileImpl::GetQuotaManager() {
- if (!quota_manager_.get()) {
- quota_manager_ = new quota::QuotaManager(
- IsOffTheRecord(),
- GetPath(),
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB));
- }
+ CreateQuotaManagerAndClients();
return quota_manager_.get();
}
@@ -1279,6 +1270,30 @@ ExtensionPrefValueMap* ProfileImpl::GetExtensionPrefValueMap() {
return extension_pref_value_map_.get();
}
+void ProfileImpl::CreateQuotaManagerAndClients() {
+ if (quota_manager_.get()) {
+ DCHECK(file_system_context_.get());
+ return;
+ }
+
+ // All of the clients have to be created and registered with the
+ // QuotaManager prior to the QuotaManger being used. So we do them
+ // all together here prior to handing out a reference to anything
+ // that utlizes the QuotaManager.
+ quota_manager_ = new quota::QuotaManager(
+ IsOffTheRecord(),
+ GetPath(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB));
+
+ // Each consumer is responsible for registering its QuotaClient during
+ // its construction.
+ file_system_context_ = CreateFileSystemContext(
+ GetPath(), IsOffTheRecord(),
+ GetExtensionSpecialStoragePolicy(),
+ quota_manager_->proxy());
+}
+
WebKitContext* ProfileImpl::GetWebKitContext() {
if (!webkit_context_.get()) {
webkit_context_ = new WebKitContext(
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 5450bb6c..0809482 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -179,6 +179,8 @@ class ProfileImpl : public Profile,
ExtensionPrefValueMap* GetExtensionPrefValueMap();
+ void CreateQuotaManagerAndClients();
+
NotificationRegistrar registrar_;
PrefChangeRegistrar pref_change_registrar_;
diff --git a/content/browser/file_system/browser_file_system_helper.cc b/content/browser/file_system/browser_file_system_helper.cc
index db4bf3f..5515ebc 100644
--- a/content/browser/file_system/browser_file_system_helper.cc
+++ b/content/browser/file_system/browser_file_system_helper.cc
@@ -8,14 +8,17 @@
#include "base/command_line.h"
#include "content/common/content_switches.h"
#include "content/browser/browser_thread.h"
+#include "webkit/quota/quota_manager.h"
scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext(
const FilePath& profile_path, bool is_incognito,
- quota::SpecialStoragePolicy* special_storage_policy) {
+ quota::SpecialStoragePolicy* special_storage_policy,
+ quota::QuotaManagerProxy* quota_manager_proxy) {
return new fileapi::FileSystemContext(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
special_storage_policy,
+ quota_manager_proxy,
profile_path,
is_incognito,
CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/content/browser/file_system/browser_file_system_helper.h b/content/browser/file_system/browser_file_system_helper.h
index 072a8a1..9af8031 100644
--- a/content/browser/file_system/browser_file_system_helper.h
+++ b/content/browser/file_system/browser_file_system_helper.h
@@ -16,7 +16,9 @@ class SpecialStoragePolicy;
// Helper method that returns FileSystemContext constructed for
// the browser process.
scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext(
- const FilePath& profile_path, bool is_incognito,
- quota::SpecialStoragePolicy* special_storage_policy);
+ const FilePath& profile_path,
+ bool is_incognito,
+ quota::SpecialStoragePolicy* special_storage_policy,
+ quota::QuotaManagerProxy* quota_manager_proxy);
#endif // CONTENT_BROWSER_FILE_SYSTEM_BROWSER_FILE_SYSTEM_HELPER_H_
diff --git a/webkit/fileapi/file_system_context.cc b/webkit/fileapi/file_system_context.cc
index 7e0d62e..d27b87d 100644
--- a/webkit/fileapi/file_system_context.cc
+++ b/webkit/fileapi/file_system_context.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -8,15 +8,32 @@
#include "base/message_loop_proxy.h"
#include "googleurl/src/gurl.h"
#include "webkit/fileapi/file_system_path_manager.h"
-#include "webkit/fileapi/file_system_usage_tracker.h"
#include "webkit/fileapi/sandbox_mount_point_provider.h"
+#include "webkit/fileapi/sandbox_quota_client.h"
+#include "webkit/quota/quota_manager.h"
+
+using quota::QuotaClient;
namespace fileapi {
+namespace {
+QuotaClient* CreateQuotaClient(
+ scoped_refptr<base::MessageLoopProxy> file_message_loop,
+ FileSystemContext* context,
+ bool is_incognito) {
+ // TODO(kinuko): For now we assume only sandbox filesystem uses
+ // the quota feature. If we want to support multiple filesystem types
+ // that require different quota we'll need to add more QuotaClientID
+ // and more factory-like code around QuotaClient.
+ return new SandboxQuotaClient(file_message_loop, context, is_incognito);
+}
+} // anonymous namespace
+
FileSystemContext::FileSystemContext(
scoped_refptr<base::MessageLoopProxy> file_message_loop,
scoped_refptr<base::MessageLoopProxy> io_message_loop,
scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,
+ quota::QuotaManagerProxy* quota_manager_proxy,
const FilePath& profile_path,
bool is_incognito,
bool allow_file_access,
@@ -25,16 +42,19 @@ FileSystemContext::FileSystemContext(
: file_message_loop_(file_message_loop),
io_message_loop_(io_message_loop),
special_storage_policy_(special_storage_policy),
+ quota_manager_proxy_(quota_manager_proxy),
allow_file_access_from_files_(allow_file_access),
unlimited_quota_(unlimited_quota),
- path_manager_(path_manager),
- usage_tracker_(new FileSystemUsageTracker(
- file_message_loop, profile_path, is_incognito)) {
+ path_manager_(path_manager) {
if (!path_manager) {
path_manager_.reset(new FileSystemPathManager(
file_message_loop, profile_path, special_storage_policy,
is_incognito, allow_file_access));
}
+ if (quota_manager_proxy) {
+ quota_manager_proxy->RegisterClient(CreateQuotaClient(
+ file_message_loop, this, is_incognito));
+ }
}
FileSystemContext::~FileSystemContext() {
@@ -55,11 +75,8 @@ void FileSystemContext::DeleteDataForOriginOnFileThread(
DCHECK(path_manager_.get());
DCHECK(file_message_loop_->BelongsToCurrentThread());
- std::string origin_identifier =
- SandboxMountPointProvider::GetOriginIdentifierFromURL(origin_url);
- FilePath path_for_origin = sandbox_provider()->base_path().AppendASCII(
- origin_identifier);
-
+ FilePath path_for_origin =
+ sandbox_provider()->GetBaseDirectoryForOrigin(origin_url);
file_util::Delete(path_for_origin, true /* recursive */);
}
diff --git a/webkit/fileapi/file_system_context.h b/webkit/fileapi/file_system_context.h
index aa1804a..f80e5f0 100644
--- a/webkit/fileapi/file_system_context.h
+++ b/webkit/fileapi/file_system_context.h
@@ -16,6 +16,11 @@ namespace base {
class MessageLoopProxy;
}
+namespace quota {
+class QuotaClient;
+class QuotaManagerProxy;
+}
+
namespace fileapi {
class FileSystemContext;
@@ -34,6 +39,7 @@ class FileSystemContext
scoped_refptr<base::MessageLoopProxy> file_message_loop,
scoped_refptr<base::MessageLoopProxy> io_message_loop,
scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,
+ quota::QuotaManagerProxy* quota_manager_proxy,
const FilePath& profile_path,
bool is_incognito,
bool allow_file_access_from_files,
@@ -46,8 +52,10 @@ class FileSystemContext
void DeleteDataForOriginOnFileThread(const GURL& origin_url);
- FileSystemPathManager* path_manager() { return path_manager_.get(); }
- FileSystemUsageTracker* usage_tracker() { return usage_tracker_.get(); }
+ FileSystemPathManager* path_manager() const { return path_manager_.get(); }
+ quota::QuotaManagerProxy* quota_manager_proxy() const {
+ return quota_manager_proxy_.get();
+ }
private:
friend struct DefaultContextDeleter;
@@ -58,11 +66,11 @@ class FileSystemContext
scoped_refptr<base::MessageLoopProxy> io_message_loop_;
scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
const bool allow_file_access_from_files_;
const bool unlimited_quota_;
scoped_ptr<FileSystemPathManager> path_manager_;
- scoped_ptr<FileSystemUsageTracker> usage_tracker_;
DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemContext);
};
diff --git a/webkit/fileapi/file_system_context_unittest.cc b/webkit/fileapi/file_system_context_unittest.cc
index 30ec54e..025b7f3 100644
--- a/webkit/fileapi/file_system_context_unittest.cc
+++ b/webkit/fileapi/file_system_context_unittest.cc
@@ -12,6 +12,7 @@
#include "base/string_number_conversions.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/quota/quota_manager.h"
using namespace fileapi;
@@ -46,6 +47,7 @@ scoped_refptr<FileSystemContext> NewFileSystemContext(
return new FileSystemContext(base::MessageLoopProxy::CreateForCurrentThread(),
base::MessageLoopProxy::CreateForCurrentThread(),
special_storage_policy,
+ NULL /* quota manager */,
FilePath(), false /* is_incognito */,
allow_file_access, unlimited_quota, NULL);
}
diff --git a/webkit/fileapi/file_system_dir_url_request_job_unittest.cc b/webkit/fileapi/file_system_dir_url_request_job_unittest.cc
index 6b2882b..888121b 100644
--- a/webkit/fileapi/file_system_dir_url_request_job_unittest.cc
+++ b/webkit/fileapi/file_system_dir_url_request_job_unittest.cc
@@ -68,7 +68,7 @@ class FileSystemDirURLRequestJobTest : public testing::Test {
new FileSystemContext(
base::MessageLoopProxy::CreateForCurrentThread(),
base::MessageLoopProxy::CreateForCurrentThread(),
- special_storage_policy_,
+ special_storage_policy_, NULL,
FilePath(), false /* is_incognito */,
false, true,
new FileSystemPathManager(
diff --git a/webkit/fileapi/file_system_operation_write_unittest.cc b/webkit/fileapi/file_system_operation_write_unittest.cc
index 2f996ab..053cc68 100644
--- a/webkit/fileapi/file_system_operation_write_unittest.cc
+++ b/webkit/fileapi/file_system_operation_write_unittest.cc
@@ -188,7 +188,7 @@ FileSystemOperation* FileSystemOperationWriteTest::operation() {
base::MessageLoopProxy::CreateForCurrentThread(),
new FileSystemContext(base::MessageLoopProxy::CreateForCurrentThread(),
base::MessageLoopProxy::CreateForCurrentThread(),
- NULL, FilePath(), false /* is_incognito */,
+ NULL, NULL, FilePath(), false /* is_incognito */,
true, true,
new MockFileSystemPathManager(filesystem_dir_)),
LocalFileSystemFileUtil::GetInstance());
diff --git a/webkit/fileapi/file_system_url_request_job_unittest.cc b/webkit/fileapi/file_system_url_request_job_unittest.cc
index 62e6d8f..c0e60a1 100644
--- a/webkit/fileapi/file_system_url_request_job_unittest.cc
+++ b/webkit/fileapi/file_system_url_request_job_unittest.cc
@@ -88,7 +88,7 @@ class FileSystemURLRequestJobTest : public testing::Test {
new FileSystemContext(
base::MessageLoopProxy::CreateForCurrentThread(),
base::MessageLoopProxy::CreateForCurrentThread(),
- special_storage_policy_,
+ special_storage_policy_, NULL,
FilePath(), false /* is_incognito */,
false, true,
new FileSystemPathManager(
diff --git a/webkit/fileapi/file_system_usage_tracker.cc b/webkit/fileapi/file_system_usage_tracker.cc
deleted file mode 100644
index 687884f..0000000
--- a/webkit/fileapi/file_system_usage_tracker.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/fileapi/file_system_usage_tracker.h"
-
-#include <algorithm>
-
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop_proxy.h"
-#include "base/task.h"
-#include "googleurl/src/gurl.h"
-#include "webkit/fileapi/file_system_path_manager.h"
-#include "webkit/fileapi/file_system_usage_cache.h"
-#include "webkit/fileapi/sandbox_mount_point_provider.h"
-
-namespace fileapi {
-
-class FileSystemUsageTracker::GetUsageTask
- : public base::RefCountedThreadSafe<GetUsageTask> {
- public:
- GetUsageTask(
- FileSystemUsageTracker* tracker,
- scoped_refptr<base::MessageLoopProxy> file_message_loop,
- std::string fs_identifier,
- const FilePath& origin_base_path)
- : tracker_(tracker),
- file_message_loop_(file_message_loop),
- original_message_loop_(
- base::MessageLoopProxy::CreateForCurrentThread()),
- fs_identifier_(fs_identifier),
- fs_usage_(0),
- origin_base_path_(origin_base_path) {
- }
-
- virtual ~GetUsageTask() {}
-
- void Start() {
- DCHECK(tracker_);
- tracker_->RegisterUsageTask(this);
- file_message_loop_->PostTask(
- FROM_HERE, NewRunnableMethod(this, &GetUsageTask::RunOnFileThread));
- }
-
- void Cancel() {
- DCHECK(original_message_loop_->BelongsToCurrentThread());
- tracker_ = NULL;
- }
-
- private:
- void RunOnFileThread() {
- DCHECK(file_message_loop_->BelongsToCurrentThread());
-
- if (!file_util::DirectoryExists(origin_base_path_))
- fs_usage_ = 0;
- else {
- FilePath usage_file_path = origin_base_path_.AppendASCII(
- FileSystemUsageCache::kUsageFileName);
-
- if (FileSystemUsageCache::GetDirty(usage_file_path) != 0) {
- FilePath content_file_path = origin_base_path_;
- if (FileSystemUsageCache::Exists(usage_file_path))
- FileSystemUsageCache::Delete(usage_file_path);
- fs_usage_ = file_util::ComputeDirectorySize(content_file_path);
- // fs_usage_ will include the size of .usage.
- // The result of ComputeDirectorySize does not include it.
- fs_usage_ += FileSystemUsageCache::kUsageFileSize;
- FileSystemUsageCache::UpdateUsage(usage_file_path, fs_usage_);
- } else {
- fs_usage_ = FileSystemUsageCache::GetUsage(usage_file_path);
- }
- }
-
- original_message_loop_->PostTask(
- FROM_HERE, NewRunnableMethod(this, &GetUsageTask::Completed));
- }
-
- void Completed() {
- DCHECK(original_message_loop_->BelongsToCurrentThread());
- if (tracker_) {
- tracker_->UnregisterUsageTask(this);
- tracker_->DidGetOriginUsage(fs_identifier_, fs_usage_);
- }
- }
-
- FileSystemUsageTracker* tracker_;
- scoped_refptr<base::MessageLoopProxy> file_message_loop_;
- scoped_refptr<base::MessageLoopProxy> original_message_loop_;
- std::string fs_identifier_;
- int64 fs_usage_;
- FilePath origin_base_path_;
-};
-
-FileSystemUsageTracker::FileSystemUsageTracker(
- scoped_refptr<base::MessageLoopProxy> file_message_loop,
- const FilePath& profile_path,
- bool is_incognito)
- : file_message_loop_(file_message_loop),
- base_path_(profile_path.Append(
- SandboxMountPointProvider::kFileSystemDirectory)),
- is_incognito_(is_incognito) {
- DCHECK(file_message_loop);
-}
-
-FileSystemUsageTracker::~FileSystemUsageTracker() {
- std::for_each(running_usage_tasks_.begin(),
- running_usage_tasks_.end(),
- std::mem_fun(&GetUsageTask::Cancel));
-}
-
-void FileSystemUsageTracker::GetOriginUsage(
- const GURL& origin_url,
- fileapi::FileSystemType type,
- GetUsageCallback* callback_ptr) {
- DCHECK(callback_ptr);
- scoped_ptr<GetUsageCallback> callback(callback_ptr);
-
- if (is_incognito_) {
- // We don't support FileSystem in incognito mode yet.
- callback->Run(0);
- return;
- }
-
- std::string origin_identifier =
- SandboxMountPointProvider::GetOriginIdentifierFromURL(origin_url);
- std::string type_string =
- FileSystemPathManager::GetFileSystemTypeString(type);
- std::string fs_identifier = origin_identifier + ":" + type_string;
-
- if (pending_usage_callbacks_.find(fs_identifier) !=
- pending_usage_callbacks_.end()) {
- // Another get usage task is running. Add the callback to
- // the pending queue and return.
- pending_usage_callbacks_[fs_identifier].push_back(callback.release());
- return;
- }
-
- // Get the filesystem base path (i.e. "FileSystem/<origin>/<type>",
- // without unique part).
- FilePath origin_base_path =
- SandboxMountPointProvider::GetFileSystemBaseDirectoryForOriginAndType(
- base_path_, origin_identifier, type);
- if (origin_base_path.empty()) {
- // The directory does not exist.
- callback->Run(0);
- return;
- }
-
- pending_usage_callbacks_[fs_identifier].push_back(callback.release());
- scoped_refptr<GetUsageTask> task(
- new GetUsageTask(this, file_message_loop_, fs_identifier,
- origin_base_path));
- task->Start();
-}
-
-void FileSystemUsageTracker::RegisterUsageTask(GetUsageTask* task) {
- running_usage_tasks_.push_back(task);
-}
-
-void FileSystemUsageTracker::UnregisterUsageTask(GetUsageTask* task) {
- DCHECK(running_usage_tasks_.front() == task);
- running_usage_tasks_.pop_front();
-}
-
-void FileSystemUsageTracker::DidGetOriginUsage(
- const std::string& fs_identifier, int64 usage) {
- PendingUsageCallbackMap::iterator cb_list_iter =
- pending_usage_callbacks_.find(fs_identifier);
- DCHECK(cb_list_iter != pending_usage_callbacks_.end());
- PendingCallbackList cb_list = cb_list_iter->second;
- for (PendingCallbackList::iterator cb_iter = cb_list.begin();
- cb_iter != cb_list.end();
- ++cb_iter) {
- scoped_ptr<GetUsageCallback> callback(*cb_iter);
- callback->Run(usage);
- }
- pending_usage_callbacks_.erase(cb_list_iter);
-}
-
-} // namespace fileapi
diff --git a/webkit/fileapi/file_system_usage_tracker.h b/webkit/fileapi/file_system_usage_tracker.h
deleted file mode 100644
index 6328693..0000000
--- a/webkit/fileapi/file_system_usage_tracker.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef WEBKIT_FILEAPI_FILE_SYSTEM_USAGE_TRACKER_H_
-#define WEBKIT_FILEAPI_FILE_SYSTEM_USAGE_TRACKER_H_
-
-#include <deque>
-#include <list>
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "webkit/fileapi/file_system_types.h"
-
-class GURL;
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace fileapi {
-
-// Owned by the FileSystemContext, which is a per-profile instance, and has the
-// same lifetime as the FileSystemContext. It's going to be created and
-// destroyed on the IO thread in chrome. (The destruction on the same thread
-// where it is created was guaranteed by its owner, FileSystemContext.)
-class FileSystemUsageTracker {
- public:
- FileSystemUsageTracker(
- scoped_refptr<base::MessageLoopProxy> file_message_loop,
- const FilePath& profile_path,
- bool is_incognito);
- ~FileSystemUsageTracker();
-
- // Get the amount of data stored in the filesystem specified by
- // |origin_url| and |type|.
- typedef Callback1<int64 /* usage */>::Type GetUsageCallback;
- void GetOriginUsage(const GURL& origin_url,
- fileapi::FileSystemType type,
- GetUsageCallback* callback);
-
- private:
- class GetUsageTask;
-
- void RegisterUsageTask(GetUsageTask* task);
- void UnregisterUsageTask(GetUsageTask* task);
-
- void DidGetOriginUsage(const std::string& fs_name, int64 usage);
-
- scoped_refptr<base::MessageLoopProxy> file_message_loop_;
- FilePath base_path_;
- bool is_incognito_;
-
- typedef std::deque<GetUsageTask*> UsageTaskQueue;
- UsageTaskQueue running_usage_tasks_;
-
- typedef std::list<GetUsageCallback*> PendingCallbackList;
- typedef std::map<std::string, PendingCallbackList> PendingUsageCallbackMap;
- PendingUsageCallbackMap pending_usage_callbacks_;
-
- DISALLOW_COPY_AND_ASSIGN(FileSystemUsageTracker);
-};
-
-} // namespace fileapi
-
-#endif // WEBKIT_FILEAPI_FILE_SYSTEM_USAGE_TRACKER_H_
diff --git a/webkit/fileapi/file_system_usage_tracker_unittest.cc b/webkit/fileapi/file_system_usage_tracker_unittest.cc
deleted file mode 100644
index e198363..0000000
--- a/webkit/fileapi/file_system_usage_tracker_unittest.cc
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/fileapi/file_system_usage_tracker.h"
-
-#include "base/basictypes.h"
-#include "base/file_util.h"
-#include "base/memory/scoped_callback_factory.h"
-#include "base/memory/scoped_temp_dir.h"
-#include "base/message_loop.h"
-#include "base/message_loop_proxy.h"
-#include "base/platform_file.h"
-#include "googleurl/src/gurl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/fileapi/file_system_types.h"
-#include "webkit/fileapi/file_system_usage_cache.h"
-#include "webkit/fileapi/sandbox_mount_point_provider.h"
-
-using namespace fileapi;
-
-namespace {
-
-static const GURL kDummyURL1("http://www.dummy.org");
-static const GURL kDummyURL2("http://www.example.com");
-
-// Declared to shorten the variable names.
-static const fileapi::FileSystemType kTemporary =
- fileapi::kFileSystemTypeTemporary;
-static const fileapi::FileSystemType kPersistent =
- fileapi::kFileSystemTypePersistent;
-static const int kUsageFileSize = FileSystemUsageCache::kUsageFileSize;
-
-}
-
-class FileSystemUsageTrackerTest : public testing::Test {
- public:
- FileSystemUsageTrackerTest()
- : callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
- }
-
- void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- }
-
- struct TestFile {
- bool isDirectory;
- const char* name;
- int64 size;
- GURL origin_url;
- fileapi::FileSystemType type;
- };
-
- protected:
- FileSystemUsageTracker* NewUsageTracker(bool is_incognito) {
- return new FileSystemUsageTracker(
- base::MessageLoopProxy::CreateForCurrentThread(),
- data_dir_.path(), is_incognito);
- }
-
- int64 GetOriginUsage(FileSystemUsageTracker* tracker,
- const GURL& origin_url,
- fileapi::FileSystemType type) {
- tracker->GetOriginUsage(origin_url, type,
- callback_factory_.NewCallback(
- &FileSystemUsageTrackerTest::OnGetUsage));
- MessageLoop::current()->RunAllPending();
- return usage_;
- }
-
- FilePath GetOriginBasePath(const GURL& origin_url,
- fileapi::FileSystemType type) {
- return
- SandboxMountPointProvider::GetFileSystemBaseDirectoryForOriginAndType(
- data_dir_.path().Append(
- SandboxMountPointProvider::kFileSystemDirectory),
- SandboxMountPointProvider::GetOriginIdentifierFromURL(origin_url),
- type);
- }
-
- bool CreateFileSystemDirectory(const char* dir_name,
- const GURL& origin_url,
- fileapi::FileSystemType type) {
- FilePath origin_base_path = GetOriginBasePath(origin_url, type);
- FilePath dir_path;
- if (dir_name != NULL)
- dir_path = origin_base_path.AppendASCII(dir_name);
- else
- dir_path = origin_base_path;
- if (dir_path.empty())
- return false;
-
- return file_util::CreateDirectory(dir_path);
- }
-
- bool CreateFileSystemFile(const char* file_name,
- int64 file_size,
- const GURL& origin_url,
- fileapi::FileSystemType type) {
- FilePath origin_base_path = GetOriginBasePath(origin_url, type);
- FilePath file_path = origin_base_path.AppendASCII(file_name);
-
- if (file_path.empty())
- return false;
-
- int file_flags = base::PLATFORM_FILE_CREATE_ALWAYS |
- base::PLATFORM_FILE_WRITE;
- base::PlatformFileError error_code;
- base::PlatformFile file =
- base::CreatePlatformFile(file_path, file_flags, NULL, &error_code);
- if (error_code != base::PLATFORM_FILE_OK)
- return false;
-
- bool succeeded;
- succeeded = base::TruncatePlatformFile(file, file_size);
- succeeded = succeeded && base::ClosePlatformFile(file);
- return succeeded;
- }
-
- void CreateFiles(const TestFile* files, int num_files) {
- for (int i = 0; i < num_files; i++) {
- if (files[i].isDirectory) {
- ASSERT_TRUE(CreateFileSystemDirectory(
- files[i].name, files[i].origin_url, files[i].type));
- } else {
- ASSERT_TRUE(CreateFileSystemFile(
- files[i].name, files[i].size, files[i].origin_url, files[i].type));
- }
- }
- }
-
- private:
- void OnGetUsage(int64 usage) {
- usage_ = usage;
- }
-
- ScopedTempDir data_dir_;
- base::ScopedCallbackFactory<FileSystemUsageTrackerTest> callback_factory_;
- int64 usage_;
-
- DISALLOW_COPY_AND_ASSIGN(FileSystemUsageTrackerTest);
-};
-
-TEST_F(FileSystemUsageTrackerTest, NoFileSystemTest) {
- scoped_ptr<FileSystemUsageTracker> tracker(NewUsageTracker(false));
-
- EXPECT_EQ(0,
- GetOriginUsage(tracker.get(), kDummyURL1, kTemporary));
-}
-
-TEST_F(FileSystemUsageTrackerTest, NoFileTest) {
- scoped_ptr<FileSystemUsageTracker> tracker(NewUsageTracker(false));
- TestFile files[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- };
- CreateFiles(files, ARRAYSIZE_UNSAFE(files));
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL1, kTemporary));
- }
-}
-
-TEST_F(FileSystemUsageTrackerTest, OneFileTest) {
- scoped_ptr<FileSystemUsageTracker> tracker(NewUsageTracker(false));
- TestFile files[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {false, "foo", 4921, kDummyURL1, kTemporary},
- };
- CreateFiles(files, ARRAYSIZE_UNSAFE(files));
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(4921 + kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL1, kTemporary));
- }
-}
-
-TEST_F(FileSystemUsageTrackerTest, TwoFilesTest) {
- scoped_ptr<FileSystemUsageTracker> tracker(NewUsageTracker(false));
- TestFile files[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {false, "foo", 10310, kDummyURL1, kTemporary},
- {false, "bar", 41, kDummyURL1, kTemporary},
- };
- CreateFiles(files, ARRAYSIZE_UNSAFE(files));
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(10310 + 41 + kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL1, kTemporary));
- }
-}
-
-TEST_F(FileSystemUsageTrackerTest, EmptyFilesTest) {
- scoped_ptr<FileSystemUsageTracker> tracker(NewUsageTracker(false));
- TestFile files[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {false, "foo", 0, kDummyURL1, kTemporary},
- {false, "bar", 0, kDummyURL1, kTemporary},
- {false, "baz", 0, kDummyURL1, kTemporary},
- };
- CreateFiles(files, ARRAYSIZE_UNSAFE(files));
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL1, kTemporary));
- }
-}
-
-TEST_F(FileSystemUsageTrackerTest, SubDirectoryTest) {
- scoped_ptr<FileSystemUsageTracker> tracker(NewUsageTracker(false));
- TestFile files[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {true, "dirtest", 0, kDummyURL1, kTemporary},
- {false, "dirtest/foo", 11921, kDummyURL1, kTemporary},
- {false, "bar", 4814, kDummyURL1, kTemporary},
- };
- CreateFiles(files, ARRAYSIZE_UNSAFE(files));
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(11921 + 4814 + kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL1, kTemporary));
- }
-}
-
-TEST_F(FileSystemUsageTrackerTest, MultiTypeTest) {
- scoped_ptr<FileSystemUsageTracker> tracker(NewUsageTracker(false));
- TestFile files[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {true, "dirtest", 0, kDummyURL1, kTemporary},
- {false, "dirtest/foo", 133, kDummyURL1, kTemporary},
- {false, "bar", 14, kDummyURL1, kTemporary},
- {true, NULL, 0, kDummyURL1, kPersistent},
- {true, "dirtest", 0, kDummyURL1, kPersistent},
- {false, "dirtest/foo", 193, kDummyURL1, kPersistent},
- {false, "bar", 9, kDummyURL1, kPersistent},
- };
- CreateFiles(files, ARRAYSIZE_UNSAFE(files));
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(133 + 14 + kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL1, kTemporary));
- EXPECT_EQ(193 + 9 + kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL1, kPersistent));
- }
-}
-
-TEST_F(FileSystemUsageTrackerTest, MultiDomainTest) {
- scoped_ptr<FileSystemUsageTracker> tracker(NewUsageTracker(false));
- TestFile files[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {true, "dir1", 0, kDummyURL1, kTemporary},
- {false, "dir1/foo", 1331, kDummyURL1, kTemporary},
- {false, "bar", 134, kDummyURL1, kTemporary},
- {true, NULL, 0, kDummyURL1, kPersistent},
- {true, "dir2", 0, kDummyURL1, kPersistent},
- {false, "dir2/foo", 1903, kDummyURL1, kPersistent},
- {false, "bar", 19, kDummyURL1, kPersistent},
- {true, NULL, 0, kDummyURL2, kTemporary},
- {true, "dom", 0, kDummyURL2, kTemporary},
- {false, "dom/fan", 1319, kDummyURL2, kTemporary},
- {false, "bar", 113, kDummyURL2, kTemporary},
- {true, NULL, 0, kDummyURL2, kPersistent},
- {true, "dom", 0, kDummyURL2, kPersistent},
- {false, "dom/fan", 2013, kDummyURL2, kPersistent},
- {false, "baz", 18, kDummyURL2, kPersistent},
- };
- CreateFiles(files, ARRAYSIZE_UNSAFE(files));
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(1331 + 134 + kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL1, kTemporary));
- EXPECT_EQ(1903 + 19 + kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL1, kPersistent));
- EXPECT_EQ(1319 + 113 + kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL2, kTemporary));
- EXPECT_EQ(2013 + 18 + kUsageFileSize,
- GetOriginUsage(tracker.get(), kDummyURL2, kPersistent));
- }
-}
diff --git a/webkit/fileapi/file_system_util.cc b/webkit/fileapi/file_system_util.cc
index f3e6278..5aa3cf2 100644
--- a/webkit/fileapi/file_system_util.cc
+++ b/webkit/fileapi/file_system_util.cc
@@ -128,4 +128,27 @@ GURL GetFileSystemRootURI(
return GURL(path);
}
+FileSystemType QuotaStorageTypeToFileSystemType(
+ quota::StorageType storage_type) {
+ switch (storage_type) {
+ case quota::kStorageTypeTemporary:
+ return kFileSystemTypeTemporary;
+ case quota::kStorageTypePersistent:
+ return kFileSystemTypePersistent;
+ default:
+ return kFileSystemTypeUnknown;
+ }
+}
+
+quota::StorageType FileSystemTypeToQuotaStorageType(FileSystemType type) {
+ switch (type) {
+ case kFileSystemTypeTemporary:
+ return quota::kStorageTypeTemporary;
+ case kFileSystemTypePersistent:
+ return quota::kStorageTypePersistent;
+ default:
+ return quota::kStorageTypeUnknown;
+ }
+}
+
} // namespace fileapi
diff --git a/webkit/fileapi/file_system_util.h b/webkit/fileapi/file_system_util.h
index 272e432..6f3bdca 100644
--- a/webkit/fileapi/file_system_util.h
+++ b/webkit/fileapi/file_system_util.h
@@ -7,6 +7,7 @@
#pragma once
#include "webkit/fileapi/file_system_types.h"
+#include "webkit/quota/quota_types.h"
class FilePath;
class GURL;
@@ -27,6 +28,11 @@ bool CrackFileSystemURL(const GURL& url, GURL* origin_url, FileSystemType* type,
GURL GetFileSystemRootURI(const GURL& origin_url, fileapi::FileSystemType type);
+FileSystemType QuotaStorageTypeToFileSystemType(
+ quota::StorageType storage_type);
+
+quota::StorageType FileSystemTypeToQuotaStorageType(FileSystemType type);
+
} // namespace fileapi
#endif // WEBKIT_FILEAPI_FILE_SYSTEM_UTIL_H_
diff --git a/webkit/fileapi/file_writer_delegate_unittest.cc b/webkit/fileapi/file_writer_delegate_unittest.cc
index c25a69f..d56c7ae 100644
--- a/webkit/fileapi/file_writer_delegate_unittest.cc
+++ b/webkit/fileapi/file_writer_delegate_unittest.cc
@@ -208,7 +208,7 @@ void FileWriterDelegateTest::SetUp() {
context_.reset(new FileSystemOperationContext(
new FileSystemContext(base::MessageLoopProxy::CreateForCurrentThread(),
base::MessageLoopProxy::CreateForCurrentThread(),
- NULL, FilePath(), false /* is_incognito */,
+ NULL, NULL, FilePath(), false /* is_incognito */,
true, true,
new MockFileSystemPathManager(filesystem_dir_)),
NULL));
@@ -345,7 +345,7 @@ TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimitConcurrent) {
context2.reset(new FileSystemOperationContext(
new FileSystemContext(base::MessageLoopProxy::CreateForCurrentThread(),
base::MessageLoopProxy::CreateForCurrentThread(),
- NULL, FilePath(), false /* is_incognito */,
+ NULL, NULL, FilePath(), false /* is_incognito */,
true, true,
new MockFileSystemPathManager(filesystem_dir_)),
NULL));
diff --git a/webkit/fileapi/local_file_system_file_util_unittest.cc b/webkit/fileapi/local_file_system_file_util_unittest.cc
index c60d6c8..26ba04d 100644
--- a/webkit/fileapi/local_file_system_file_util_unittest.cc
+++ b/webkit/fileapi/local_file_system_file_util_unittest.cc
@@ -74,7 +74,7 @@ class LocalFileSystemFileUtilTest : public testing::Test {
return new FileSystemOperationContext(
new FileSystemContext(base::MessageLoopProxy::CreateForCurrentThread(),
base::MessageLoopProxy::CreateForCurrentThread(),
- NULL, FilePath(), false /* is_incognito */,
+ NULL, NULL, FilePath(), false /* is_incognito */,
true, true,
new MockFileSystemPathManager(filesystem_dir_)),
FileUtil());
diff --git a/webkit/fileapi/quota_file_util_unittest.cc b/webkit/fileapi/quota_file_util_unittest.cc
index b01a178..bb76f65 100644
--- a/webkit/fileapi/quota_file_util_unittest.cc
+++ b/webkit/fileapi/quota_file_util_unittest.cc
@@ -62,7 +62,7 @@ class QuotaFileUtilTest : public testing::Test {
FileSystemOperationContext *context = new FileSystemOperationContext(
new FileSystemContext(base::MessageLoopProxy::CreateForCurrentThread(),
base::MessageLoopProxy::CreateForCurrentThread(),
- NULL, FilePath(), false,
+ NULL, NULL, FilePath(), false,
true, true,
new MockFileSystemPathManager(filesystem_dir_)),
QuotaFileUtil::GetInstance());
diff --git a/webkit/fileapi/sandbox_mount_point_provider.cc b/webkit/fileapi/sandbox_mount_point_provider.cc
index 51954ce..ad46f3b 100644
--- a/webkit/fileapi/sandbox_mount_point_provider.cc
+++ b/webkit/fileapi/sandbox_mount_point_provider.cc
@@ -19,6 +19,7 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
#include "webkit/fileapi/file_system_path_manager.h"
#include "webkit/fileapi/file_system_util.h"
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
#include "webkit/glue/webkit_glue.h"
namespace {
@@ -51,6 +52,28 @@ inline std::string FilePathStringToASCII(
#endif
}
+// TODO(kinuko): Merge these two methods (conversion methods between
+// origin url <==> identifier) with the ones in the database module.
+std::string GetOriginIdentifierFromURL(const GURL& url) {
+ WebKit::WebSecurityOrigin web_security_origin =
+ WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
+ return web_security_origin.databaseIdentifier().utf8();
+}
+
+GURL GetOriginURLFromIdentifier(const std::string& origin_identifier) {
+ WebKit::WebSecurityOrigin web_security_origin =
+ WebKit::WebSecurityOrigin::createFromDatabaseIdentifier(
+ UTF8ToUTF16(origin_identifier));
+ GURL origin_url(web_security_origin.toString());
+
+ // We need this work-around for file:/// URIs as
+ // createFromDatabaseIdentifier returns empty origin_url for them.
+ if (origin_url.spec().empty() &&
+ origin_identifier.find("file__") == 0)
+ return GURL("file:///");
+ return origin_url;
+}
+
FilePath::StringType CreateUniqueDirectoryName(const GURL& origin_url) {
// This can be anything but need to be unpredictable.
static const FilePath::CharType letters[] = FILE_PATH_LITERAL(
@@ -104,6 +127,36 @@ FilePath GetFileSystemRootPathOnFileThreadHelper(
return root;
}
+class SandboxOriginEnumerator
+ : public fileapi::SandboxMountPointProvider::OriginEnumerator {
+ public:
+ explicit SandboxOriginEnumerator(const FilePath& base_path)
+ : enumerator_(base_path, false /* recursive */,
+ file_util::FileEnumerator::DIRECTORIES) {}
+ virtual ~SandboxOriginEnumerator() {}
+
+ virtual GURL Next() OVERRIDE {
+ current_ = enumerator_.Next();
+ if (current_.empty())
+ return GURL();
+ return GetOriginURLFromIdentifier(
+ FilePathStringToASCII(current_.BaseName().value()));
+ }
+
+ virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE {
+ if (current_.empty())
+ return false;
+ std::string directory =
+ fileapi::FileSystemPathManager::GetFileSystemTypeString(type);
+ DCHECK(!directory.empty());
+ return file_util::DirectoryExists(current_.AppendASCII(directory));
+ }
+
+ private:
+ file_util::FileEnumerator enumerator_;
+ FilePath current_;
+};
+
} // anonymous namespace
namespace fileapi {
@@ -220,6 +273,11 @@ std::vector<FilePath> SandboxMountPointProvider::GetRootDirectories() const {
return std::vector<FilePath>();
}
+SandboxMountPointProvider::OriginEnumerator*
+SandboxMountPointProvider::CreateOriginEnumerator() const {
+ return new SandboxOriginEnumerator(base_path_);
+}
+
void SandboxMountPointProvider::ValidateFileSystemRootAndGetURL(
const GURL& origin_url, fileapi::FileSystemType type,
bool create, FileSystemPathManager::GetRootPathCallback* callback_ptr) {
@@ -251,49 +309,20 @@ SandboxMountPointProvider::ValidateFileSystemRootAndGetPathOnFileThread(
origin_url, origin_base_path, create);
}
-// static
-std::string SandboxMountPointProvider::GetOriginIdentifierFromURL(
- const GURL& url) {
- WebKit::WebSecurityOrigin web_security_origin =
- WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
- return web_security_origin.databaseIdentifier().utf8();
+FilePath SandboxMountPointProvider::GetBaseDirectoryForOrigin(
+ const GURL& origin_url) const {
+ return base_path_.AppendASCII(GetOriginIdentifierFromURL(origin_url));
}
-// static
-FilePath SandboxMountPointProvider::GetFileSystemBaseDirectoryForOriginAndType(
- const FilePath& base_path, const std::string& origin_identifier,
- fileapi::FileSystemType type) {
- if (origin_identifier.empty())
- return FilePath();
+FilePath SandboxMountPointProvider::GetBaseDirectoryForOriginAndType(
+ const GURL& origin_url, fileapi::FileSystemType type) const {
std::string type_string =
FileSystemPathManager::GetFileSystemTypeString(type);
if (type_string.empty()) {
LOG(WARNING) << "Unknown filesystem type is requested:" << type;
return FilePath();
}
- return base_path.AppendASCII(origin_identifier)
- .AppendASCII(type_string);
-}
-
-SandboxMountPointProvider::OriginEnumerator::OriginEnumerator(
- const FilePath& base_path)
- : enumerator_(base_path, false /* recursive */,
- file_util::FileEnumerator::DIRECTORIES) {
-}
-
-std::string SandboxMountPointProvider::OriginEnumerator::Next() {
- current_ = enumerator_.Next();
- return FilePathStringToASCII(current_.BaseName().value());
-}
-
-bool SandboxMountPointProvider::OriginEnumerator::HasTemporary() {
- return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII(
- fileapi::kTemporaryName));
-}
-
-bool SandboxMountPointProvider::OriginEnumerator::HasPersistent() {
- return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII(
- fileapi::kPersistentName));
+ return GetBaseDirectoryForOrigin(origin_url).AppendASCII(type_string);
}
bool SandboxMountPointProvider::GetOriginBasePathAndName(
@@ -309,12 +338,11 @@ bool SandboxMountPointProvider::GetOriginBasePathAndName(
if (!path_manager_->IsAllowedScheme(origin_url))
return false;
- std::string origin_identifier = GetOriginIdentifierFromURL(origin_url);
- *origin_base_path = GetFileSystemBaseDirectoryForOriginAndType(
- base_path(), origin_identifier, type);
+ *origin_base_path = GetBaseDirectoryForOriginAndType(origin_url, type);
if (origin_base_path->empty())
return false;
+ std::string origin_identifier = GetOriginIdentifierFromURL(origin_url);
std::string type_string =
FileSystemPathManager::GetFileSystemTypeString(type);
DCHECK(!type_string.empty());
diff --git a/webkit/fileapi/sandbox_mount_point_provider.h b/webkit/fileapi/sandbox_mount_point_provider.h
index 6f8cff8..748ced8 100644
--- a/webkit/fileapi/sandbox_mount_point_provider.h
+++ b/webkit/fileapi/sandbox_mount_point_provider.h
@@ -12,8 +12,6 @@
#include "googleurl/src/gurl.h"
#include "webkit/fileapi/file_system_mount_point_provider.h"
-class GURL;
-
namespace base {
class MessageLoopProxy;
}
@@ -22,6 +20,18 @@ namespace fileapi {
class SandboxMountPointProvider : public FileSystemMountPointProvider {
public:
+ // Origin enumerator interface.
+ // An instance of this interface is assumed to be called on the file thread.
+ class OriginEnumerator {
+ public:
+ virtual ~OriginEnumerator() {}
+
+ // Returns the next origin. Returns empty if there are no more origins.
+ virtual GURL Next() = 0;
+
+ // Returns the current origin's information.
+ virtual bool HasFileSystemType(FileSystemType type) const = 0;
+ };
SandboxMountPointProvider(
FileSystemPathManager* path_manager,
@@ -63,40 +73,26 @@ class SandboxMountPointProvider : public FileSystemMountPointProvider {
virtual std::vector<FilePath> GetRootDirectories() const;
- // Returns the origin identifier string, which is used as a part of the
- // sandboxed path component, for the given |url|.
- static std::string GetOriginIdentifierFromURL(const GURL& url);
+ // Returns an origin enumerator of this provider.
+ // This method is supposed to be called on the file thread.
+ OriginEnumerator* CreateOriginEnumerator() const;
// Gets a base directory path of the sandboxed filesystem that is
- // specified by |origin_identifier| and |type|.
- // |base_path| must be pointing the FileSystem's data directory
- // under the profile directory, i.e. <profile_dir>/kFileSystemDirectory.
- // Returns an empty path if any of the given parameters are invalid.
- // Returned directory path does not contain 'unique' part, therefore
- // it is not an actual root path for the filesystem.
- static FilePath GetFileSystemBaseDirectoryForOriginAndType(
- const FilePath& base_path,
- const std::string& origin_identifier,
- fileapi::FileSystemType type);
-
- // Enumerates origins under the given |base_path|.
- // This must be used on the FILE thread.
- class OriginEnumerator {
- public:
- explicit OriginEnumerator(const FilePath& base_path);
-
- // Returns the next origin identifier. Returns empty if there are no
- // more origins.
- std::string Next();
+ // specified by |origin_url|.
+ // (The path is similar to the origin's root path but doesn't contain
+ // the 'unique' and 'type' part.)
+ // This method is portable and can be called on any threads.
+ FilePath GetBaseDirectoryForOrigin(const GURL& origin_url) const;
- bool HasTemporary();
- bool HasPersistent();
- const FilePath& path() { return current_; }
-
- private:
- file_util::FileEnumerator enumerator_;
- FilePath current_;
- };
+ // Gets a base directory path of the sandboxed filesystem that is
+ // specified by |origin_url| and |type|.
+ // (The path is similar to the origin's root path but doesn't contain
+ // the 'unique' part.)
+ // Returns an empty path if the given type is invalid.
+ // This method is portable and can be called on any threads.
+ FilePath GetBaseDirectoryForOriginAndType(
+ const GURL& origin_url,
+ fileapi::FileSystemType type) const;
private:
bool GetOriginBasePathAndName(
@@ -121,4 +117,3 @@ class SandboxMountPointProvider : public FileSystemMountPointProvider {
} // namespace fileapi
#endif // WEBKIT_FILEAPI_SANDBOX_MOUNT_POINT_PROVIDER_H_
-
diff --git a/webkit/fileapi/sandbox_mount_point_provider_unittest.cc b/webkit/fileapi/sandbox_mount_point_provider_unittest.cc
index 767f0ef..54f6865 100644
--- a/webkit/fileapi/sandbox_mount_point_provider_unittest.cc
+++ b/webkit/fileapi/sandbox_mount_point_provider_unittest.cc
@@ -22,12 +22,20 @@
using namespace fileapi;
+class MockFileSystemPathManager : public FileSystemPathManager {
+ public:
+ MockFileSystemPathManager(const FilePath& filesystem_path)
+ : FileSystemPathManager(base::MessageLoopProxy::CreateForCurrentThread(),
+ filesystem_path, NULL, false, true) {}
+};
+
class SandboxMountPointProviderOriginEnumeratorTest : public testing::Test {
public:
void SetUp() {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- enumerator_.reset(new SandboxMountPointProvider::OriginEnumerator(
- data_dir_.path()));
+ path_manager_.reset(new MockFileSystemPathManager(data_dir_.path()));
+ enumerator_.reset(
+ path_manager_->sandbox_provider()->CreateOriginEnumerator());
}
SandboxMountPointProvider::OriginEnumerator* enumerator() const {
@@ -35,61 +43,60 @@ class SandboxMountPointProviderOriginEnumeratorTest : public testing::Test {
}
protected:
- void CreateOriginTypeDirectory(const std::string& origin_identifier,
+ void CreateOriginTypeDirectory(const GURL& origin,
fileapi::FileSystemType type) {
- std::string type_string =
- FileSystemPathManager::GetFileSystemTypeString(type);
- ASSERT_TRUE(!type_string.empty());
- FilePath target = data_dir_.path().AppendASCII(origin_identifier)
- .AppendASCII(type_string);
+ FilePath target = path_manager_->sandbox_provider()->
+ GetBaseDirectoryForOriginAndType(origin, type);
file_util::CreateDirectory(target);
ASSERT_TRUE(file_util::DirectoryExists(target));
}
ScopedTempDir data_dir_;
+ scoped_ptr<FileSystemPathManager> path_manager_;
scoped_ptr<SandboxMountPointProvider::OriginEnumerator> enumerator_;
};
TEST_F(SandboxMountPointProviderOriginEnumeratorTest, Empty) {
- ASSERT_TRUE(enumerator()->Next().empty());
+ ASSERT_TRUE(enumerator()->Next().is_empty());
}
TEST_F(SandboxMountPointProviderOriginEnumeratorTest, EnumerateOrigins) {
const char* temporary_origins[] = {
- "http_www.bar.com_0",
- "http_www.foo.com_0",
- "http_www.foo.com_80",
- "http_www.example.com_8080",
- "http_www.google.com_80",
+ "http://www.bar.com/",
+ "http://www.foo.com/",
+ "http://www.foo.com:1/",
+ "http://www.example.com:8080/",
+ "http://www.google.com:80/",
};
const char* persistent_origins[] = {
- "http_www.bar.com_0",
- "http_www.foo.com_8080",
- "http_www.foo.com_80",
+ "http://www.bar.com/",
+ "http://www.foo.com:8080/",
+ "http://www.foo.com:80/",
};
size_t temporary_size = ARRAYSIZE_UNSAFE(temporary_origins);
size_t persistent_size = ARRAYSIZE_UNSAFE(persistent_origins);
- std::set<std::string> temporary_set, persistent_set;
+ std::set<GURL> temporary_set, persistent_set;
for (size_t i = 0; i < temporary_size; ++i) {
- CreateOriginTypeDirectory(temporary_origins[i],
+ CreateOriginTypeDirectory(GURL(temporary_origins[i]),
fileapi::kFileSystemTypeTemporary);
- temporary_set.insert(temporary_origins[i]);
+ temporary_set.insert(GURL(temporary_origins[i]));
}
for (size_t i = 0; i < persistent_size; ++i) {
- CreateOriginTypeDirectory(persistent_origins[i], kFileSystemTypePersistent);
- persistent_set.insert(persistent_origins[i]);
+ CreateOriginTypeDirectory(GURL(persistent_origins[i]),
+ kFileSystemTypePersistent);
+ persistent_set.insert(GURL(persistent_origins[i]));
}
size_t temporary_actual_size = 0;
size_t persistent_actual_size = 0;
- std::string current;
- while (!(current = enumerator()->Next()).empty()) {
- SCOPED_TRACE(testing::Message() << "EnumerateOrigin " << current);
- if (enumerator()->HasTemporary()) {
+ GURL current;
+ while (!(current = enumerator()->Next()).is_empty()) {
+ SCOPED_TRACE(testing::Message() << "EnumerateOrigin " << current.spec());
+ if (enumerator()->HasFileSystemType(kFileSystemTypeTemporary)) {
ASSERT_TRUE(temporary_set.find(current) != temporary_set.end());
++temporary_actual_size;
}
- if (enumerator()->HasPersistent()) {
+ if (enumerator()->HasFileSystemType(kFileSystemTypePersistent)) {
ASSERT_TRUE(persistent_set.find(current) != persistent_set.end());
++persistent_actual_size;
}
diff --git a/webkit/fileapi/sandbox_quota_client.cc b/webkit/fileapi/sandbox_quota_client.cc
new file mode 100644
index 0000000..b35e7ba
--- /dev/null
+++ b/webkit/fileapi/sandbox_quota_client.cc
@@ -0,0 +1,292 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/fileapi/sandbox_quota_client.h"
+
+#include <algorithm>
+#include <set>
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop_proxy.h"
+#include "base/task.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_util.h"
+#include "webkit/fileapi/file_system_context.h"
+#include "webkit/fileapi/file_system_path_manager.h"
+#include "webkit/fileapi/file_system_usage_cache.h"
+#include "webkit/fileapi/file_system_util.h"
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
+
+using namespace std;
+
+using base::MessageLoopProxy;
+using quota::QuotaThreadTask;
+using quota::StorageType;
+
+namespace fileapi {
+
+class SandboxQuotaClient::GetOriginUsageTask : public QuotaThreadTask {
+ public:
+ GetOriginUsageTask(
+ SandboxQuotaClient* quota_client,
+ scoped_refptr<MessageLoopProxy> file_message_loop,
+ const GURL& origin_url,
+ FileSystemType type)
+ : QuotaThreadTask(quota_client, file_message_loop),
+ quota_client_(quota_client),
+ origin_url_(origin_url),
+ type_(type),
+ fs_usage_(0) {
+ DCHECK(quota_client_);
+ file_system_context_ = quota_client_->file_system_context_;
+ visited_ = (quota_client_->visited_origins_.find(origin_url) !=
+ quota_client_->visited_origins_.end());
+ }
+
+ virtual ~GetOriginUsageTask() {}
+
+ protected:
+ virtual void RunOnTargetThread() OVERRIDE {
+ FilePath base_path =
+ file_system_context_->path_manager()->sandbox_provider()->
+ GetBaseDirectoryForOriginAndType(origin_url_, type_);
+ if (!file_util::DirectoryExists(base_path)) {
+ fs_usage_ = 0;
+ } else {
+ FilePath usage_file_path = base_path.AppendASCII(
+ FileSystemUsageCache::kUsageFileName);
+ int32 dirty_status = FileSystemUsageCache::GetDirty(usage_file_path);
+ if (dirty_status == 0 || (dirty_status > 0 && visited_)) {
+ // The usage cache is clean (dirty == 0) or the origin has already
+ // initialized and running. Read the cache file to get the usage.
+ fs_usage_ = FileSystemUsageCache::GetUsage(usage_file_path);
+ } else {
+ // The usage cache has not been initialized or the cache is dirty.
+ // Get the directory size now and update the cache.
+ if (FileSystemUsageCache::Exists(usage_file_path))
+ FileSystemUsageCache::Delete(usage_file_path);
+ int64 usage = file_util::ComputeDirectorySize(base_path);
+ // The result of ComputeDirectorySize does not include .usage file size.
+ usage += FileSystemUsageCache::kUsageFileSize;
+ // This clears the dirty flag too.
+ FileSystemUsageCache::UpdateUsage(usage_file_path, usage);
+ fs_usage_ = usage;
+ }
+ }
+ }
+
+ virtual void Completed() OVERRIDE {
+ quota_client_->DidGetOriginUsage(type_, origin_url_, fs_usage_);
+ }
+
+ SandboxQuotaClient* quota_client_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ GURL origin_url_;
+ FileSystemType type_;
+ int64 fs_usage_;
+ bool visited_;
+};
+
+class SandboxQuotaClient::GetOriginsTaskBase : public QuotaThreadTask {
+ public:
+ GetOriginsTaskBase(
+ SandboxQuotaClient* quota_client,
+ scoped_refptr<MessageLoopProxy> file_message_loop,
+ FileSystemType type)
+ : QuotaThreadTask(quota_client, file_message_loop),
+ quota_client_(quota_client),
+ type_(type) {
+ DCHECK(quota_client_);
+ file_system_context_ = quota_client_->file_system_context_;
+ }
+ virtual ~GetOriginsTaskBase() {}
+
+ protected:
+ virtual bool ShouldAddThisOrigin(const GURL& origin) const = 0;
+
+ virtual void RunOnTargetThread() OVERRIDE {
+ scoped_ptr<SandboxMountPointProvider::OriginEnumerator> enumerator(
+ sandbox_provider()->CreateOriginEnumerator());
+ GURL origin;
+ while (!(origin = enumerator->Next()).is_empty()) {
+ if (ShouldAddThisOrigin(origin) && enumerator->HasFileSystemType(type_))
+ origins_.insert(origin);
+ }
+ }
+
+ SandboxQuotaClient* quota_client() const { return quota_client_; }
+ const std::set<GURL>& origins() const { return origins_; }
+ FileSystemType type() const { return type_; }
+ SandboxMountPointProvider* sandbox_provider() const {
+ return file_system_context_->path_manager()->sandbox_provider();
+ }
+
+ private:
+ SandboxQuotaClient * quota_client_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ std::set<GURL> origins_;
+ FileSystemType type_;
+};
+
+class SandboxQuotaClient::GetOriginsForTypeTask
+ : public SandboxQuotaClient::GetOriginsTaskBase {
+ public:
+ GetOriginsForTypeTask(
+ SandboxQuotaClient* quota_client,
+ scoped_refptr<MessageLoopProxy> file_message_loop,
+ FileSystemType type)
+ : GetOriginsTaskBase(quota_client, file_message_loop, type) {}
+ virtual ~GetOriginsForTypeTask() {}
+
+ protected:
+ virtual bool ShouldAddThisOrigin(const GURL& origin) const OVERRIDE {
+ return true;
+ }
+
+ virtual void Completed() OVERRIDE {
+ quota_client()->DidGetOriginsForType(type(), origins());
+ }
+};
+
+quota::QuotaClient::ID SandboxQuotaClient::id() const {
+ return quota::QuotaClient::kFileSystem;
+}
+
+void SandboxQuotaClient::OnQuotaManagerDestroyed() {
+ delete this;
+}
+
+class SandboxQuotaClient::GetOriginsForHostTask
+ : public SandboxQuotaClient::GetOriginsTaskBase {
+ public:
+ GetOriginsForHostTask(
+ SandboxQuotaClient* quota_client,
+ scoped_refptr<MessageLoopProxy> file_message_loop,
+ FileSystemType type,
+ const std::string& host)
+ : GetOriginsTaskBase(quota_client, file_message_loop, type),
+ host_(host) {}
+ virtual ~GetOriginsForHostTask() {}
+
+ protected:
+ virtual bool ShouldAddThisOrigin(const GURL& origin) const OVERRIDE {
+ return (host_ == net::GetHostOrSpecFromURL(origin));
+ }
+
+ virtual void Completed() OVERRIDE {
+ quota_client()->DidGetOriginsForHost(std::make_pair(type(), host_),
+ origins());
+ }
+
+ private:
+ std::string host_;
+};
+
+SandboxQuotaClient::SandboxQuotaClient(
+ scoped_refptr<base::MessageLoopProxy> file_message_loop,
+ FileSystemContext* file_system_context,
+ bool is_incognito)
+ : file_message_loop_(file_message_loop),
+ file_system_context_(file_system_context),
+ is_incognito_(is_incognito) {
+ DCHECK(file_message_loop);
+}
+
+SandboxQuotaClient::~SandboxQuotaClient() {
+}
+
+void SandboxQuotaClient::GetOriginUsage(
+ const GURL& origin_url,
+ StorageType storage_type,
+ GetUsageCallback* callback_ptr) {
+ DCHECK(callback_ptr);
+ scoped_ptr<GetUsageCallback> callback(callback_ptr);
+
+ if (is_incognito_) {
+ // We don't support FileSystem in incognito mode yet.
+ callback->Run(0);
+ return;
+ }
+
+ FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
+ DCHECK(type != kFileSystemTypeUnknown);
+
+ if (pending_usage_callbacks_.Add(
+ std::make_pair(type, origin_url.spec()), callback.release())) {
+ scoped_refptr<GetOriginUsageTask> task(
+ new GetOriginUsageTask(this, file_message_loop_, origin_url, type));
+ task->Start();
+ }
+}
+
+void SandboxQuotaClient::GetOriginsForType(
+ StorageType storage_type,
+ GetOriginsCallback* callback_ptr) {
+ std::set<GURL> origins;
+ scoped_ptr<GetOriginsCallback> callback(callback_ptr);
+ if (is_incognito_) {
+ // We don't support FileSystem in incognito mode yet.
+ callback->Run(origins);
+ return;
+ }
+
+ FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
+ DCHECK(type != kFileSystemTypeUnknown);
+
+ if (pending_origins_for_type_callbacks_.Add(type, callback.release())) {
+ scoped_refptr<GetOriginsForTypeTask> task(
+ new GetOriginsForTypeTask(this, file_message_loop_, type));
+ task->Start();
+ }
+}
+
+void SandboxQuotaClient::GetOriginsForHost(
+ StorageType storage_type,
+ const std::string& host,
+ GetOriginsCallback* callback_ptr) {
+ std::set<GURL> origins;
+ scoped_ptr<GetOriginsCallback> callback(callback_ptr);
+ if (is_incognito_) {
+ // We don't support FileSystem in incognito mode yet.
+ callback->Run(origins);
+ return;
+ }
+
+ FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
+ DCHECK(type != kFileSystemTypeUnknown);
+
+ if (pending_origins_for_host_callbacks_.Add(
+ std::make_pair(type, host), callback.release())) {
+ scoped_refptr<GetOriginsForHostTask> task(
+ new GetOriginsForHostTask(this, file_message_loop_,
+ type, host));
+ task->Start();
+ }
+}
+
+void SandboxQuotaClient::DidGetOriginUsage(
+ FileSystemType type, const GURL& origin_url, int64 usage) {
+ visited_origins_.insert(origin_url);
+ TypeAndHostOrOrigin type_and_origin(std::make_pair(
+ type, origin_url.spec()));
+ DCHECK(pending_usage_callbacks_.HasCallbacks(type_and_origin));
+ pending_usage_callbacks_.Run(type_and_origin, usage);
+}
+
+void SandboxQuotaClient::DidGetOriginsForType(
+ FileSystemType type, const std::set<GURL>& origins) {
+ DCHECK(pending_origins_for_type_callbacks_.HasCallbacks(type));
+ pending_origins_for_type_callbacks_.Run(type, origins);
+}
+
+void SandboxQuotaClient::DidGetOriginsForHost(
+ const TypeAndHostOrOrigin& type_and_host, const std::set<GURL>& origins) {
+ DCHECK(pending_origins_for_host_callbacks_.HasCallbacks(type_and_host));
+ pending_origins_for_host_callbacks_.Run(type_and_host, origins);
+}
+
+} // namespace fileapi
diff --git a/webkit/fileapi/sandbox_quota_client.h b/webkit/fileapi/sandbox_quota_client.h
new file mode 100644
index 0000000..7aae5fb
--- /dev/null
+++ b/webkit/fileapi/sandbox_quota_client.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_FILEAPI_SANDBOX_QUOTA_CLIENT_H_
+#define WEBKIT_FILEAPI_SANDBOX_QUOTA_CLIENT_H_
+
+#include <deque>
+#include <list>
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "webkit/fileapi/file_system_path_manager.h"
+#include "webkit/fileapi/file_system_types.h"
+#include "webkit/quota/quota_client.h"
+#include "webkit/quota/quota_task.h"
+
+namespace fileapi {
+
+class FileSystemContext;
+
+// An instance of this class is created per-profile. This class
+// is self-destructed and will delete itself when OnQuotaManagerDestroyed
+// is called.
+class SandboxQuotaClient : public quota::QuotaClient,
+ public quota::QuotaTaskObserver {
+ public:
+ SandboxQuotaClient(
+ scoped_refptr<base::MessageLoopProxy> file_message_loop,
+ FileSystemContext* file_system_context,
+ bool is_incognito);
+ virtual ~SandboxQuotaClient();
+
+ // QuotaClient methods.
+ virtual quota::QuotaClient::ID id() const OVERRIDE;
+ virtual void OnQuotaManagerDestroyed() OVERRIDE;
+ virtual void GetOriginUsage(const GURL& origin_url,
+ quota::StorageType type,
+ GetUsageCallback* callback) OVERRIDE;
+ virtual void GetOriginsForType(quota::StorageType type,
+ GetOriginsCallback* callback) OVERRIDE;
+ virtual void GetOriginsForHost(quota::StorageType type,
+ const std::string& host,
+ GetOriginsCallback* callback) OVERRIDE;
+
+ private:
+ class GetOriginUsageTask;
+ class GetOriginsTaskBase;
+ class GetOriginsForTypeTask;
+ class GetOriginsForHostTask;
+
+ typedef std::pair<fileapi::FileSystemType, std::string> TypeAndHostOrOrigin;
+ typedef quota::CallbackQueueMap1<GetUsageCallback*,
+ TypeAndHostOrOrigin,
+ int64
+ > UsageCallbackMap;
+ typedef quota::CallbackQueueMap1<GetOriginsCallback*,
+ fileapi::FileSystemType,
+ const std::set<GURL>&
+ > OriginsForTypeCallbackMap;
+ typedef quota::CallbackQueueMap1<GetOriginsCallback*,
+ TypeAndHostOrOrigin,
+ const std::set<GURL>&
+ > OriginsForHostCallbackMap;
+
+ void DidGetOriginUsage(fileapi::FileSystemType type,
+ const GURL& origin, int64 usage);
+ void DidGetOriginsForType(fileapi::FileSystemType type,
+ const std::set<GURL>& origins);
+ void DidGetOriginsForHost(const TypeAndHostOrOrigin& type_and_host,
+ const std::set<GURL>& origins);
+
+ scoped_refptr<base::MessageLoopProxy> file_message_loop_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+
+ bool is_incognito_;
+
+ std::set<GURL> visited_origins_;
+
+ // Pending callbacks.
+ UsageCallbackMap pending_usage_callbacks_;
+ OriginsForTypeCallbackMap pending_origins_for_type_callbacks_;
+ OriginsForHostCallbackMap pending_origins_for_host_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(SandboxQuotaClient);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_FILEAPI_SANDBOX_QUOTA_CLIENT_H_
diff --git a/webkit/fileapi/sandbox_quota_client_unittest.cc b/webkit/fileapi/sandbox_quota_client_unittest.cc
new file mode 100644
index 0000000..c77e423
--- /dev/null
+++ b/webkit/fileapi/sandbox_quota_client_unittest.cc
@@ -0,0 +1,431 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/memory/scoped_callback_factory.h"
+#include "base/memory/scoped_temp_dir.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/platform_file.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/fileapi/file_system_context.h"
+#include "webkit/fileapi/file_system_types.h"
+#include "webkit/fileapi/file_system_usage_cache.h"
+#include "webkit/fileapi/file_system_util.h"
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
+#include "webkit/fileapi/sandbox_quota_client.h"
+#include "webkit/quota/quota_types.h"
+
+using namespace fileapi;
+
+namespace {
+const char kDummyURL1[] = "http://www.dummy.org";
+const char kDummyURL2[] = "http://www.example.com";
+const char kDummyURL3[] = "http://www.bleh";
+
+// Declared to shorten the variable names.
+const quota::StorageType kTemporary = quota::kStorageTypeTemporary;
+const quota::StorageType kPersistent = quota::kStorageTypePersistent;
+const int kUsageFileSize = FileSystemUsageCache::kUsageFileSize;
+
+class MockFileSystemPathManager : public FileSystemPathManager {
+ public:
+ MockFileSystemPathManager(const FilePath& filesystem_path)
+ : FileSystemPathManager(base::MessageLoopProxy::CreateForCurrentThread(),
+ filesystem_path, NULL, false, true) {}
+};
+}
+
+class SandboxQuotaClientTest : public testing::Test {
+ public:
+ SandboxQuotaClientTest()
+ : callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+ additional_callback_count_(0) {
+ }
+
+ void SetUp() {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ file_system_context_ =
+ new FileSystemContext(
+ base::MessageLoopProxy::CreateForCurrentThread(),
+ base::MessageLoopProxy::CreateForCurrentThread(),
+ NULL, NULL,
+ FilePath(), false /* is_incognito */,
+ false, true,
+ new MockFileSystemPathManager(data_dir_.path()));
+ }
+
+ struct TestFile {
+ bool isDirectory;
+ const char* name;
+ int64 size;
+ const char* origin_url;
+ quota::StorageType type;
+ };
+
+ protected:
+ SandboxQuotaClient* NewQuotaClient(bool is_incognito) {
+ return new SandboxQuotaClient(
+ base::MessageLoopProxy::CreateForCurrentThread(),
+ file_system_context_, is_incognito);
+ }
+
+ void GetOriginUsageAsync(SandboxQuotaClient* quota_client,
+ const char* origin_url,
+ quota::StorageType type) {
+ quota_client->GetOriginUsage(GURL(origin_url), type,
+ callback_factory_.NewCallback(
+ &SandboxQuotaClientTest::OnGetUsage));
+ }
+
+ int64 GetOriginUsage(SandboxQuotaClient* quota_client,
+ const char* origin_url,
+ quota::StorageType type) {
+ GetOriginUsageAsync(quota_client, origin_url, type);
+ MessageLoop::current()->RunAllPending();
+ return usage_;
+ }
+
+ const std::set<GURL>& GetOriginsForType(SandboxQuotaClient* quota_client,
+ quota::StorageType type) {
+ origins_.clear();
+ quota_client->GetOriginsForType(type,
+ callback_factory_.NewCallback(
+ &SandboxQuotaClientTest::OnGetOrigins));
+ MessageLoop::current()->RunAllPending();
+ return origins_;
+ }
+
+ const std::set<GURL>& GetOriginsForHost(SandboxQuotaClient* quota_client,
+ quota::StorageType type,
+ const char* host) {
+ origins_.clear();
+ quota_client->GetOriginsForHost(type, host,
+ callback_factory_.NewCallback(
+ &SandboxQuotaClientTest::OnGetOrigins));
+ MessageLoop::current()->RunAllPending();
+ return origins_;
+ }
+
+ void RunAdditionalOriginUsageTask(SandboxQuotaClient* quota_client,
+ const char* origin_url,
+ quota::StorageType type) {
+ quota_client->GetOriginUsage(GURL(origin_url), type,
+ callback_factory_.NewCallback(
+ &SandboxQuotaClientTest::OnGetAdditionalUsage));
+ }
+
+ FilePath GetOriginBasePath(const char* origin_url,
+ quota::StorageType type) {
+ return file_system_context_->path_manager()->sandbox_provider()->
+ GetBaseDirectoryForOriginAndType(
+ GURL(origin_url), QuotaStorageTypeToFileSystemType(type));
+ }
+
+ bool CreateFileSystemDirectory(const char* dir_name,
+ const char* origin_url,
+ quota::StorageType type) {
+ FilePath origin_base_path = GetOriginBasePath(origin_url, type);
+ FilePath dir_path;
+ if (dir_name != NULL)
+ dir_path = origin_base_path.AppendASCII(dir_name);
+ else
+ dir_path = origin_base_path;
+ if (dir_path.empty())
+ return false;
+
+ return file_util::CreateDirectory(dir_path);
+ }
+
+ bool CreateFileSystemFile(const char* file_name,
+ int64 file_size,
+ const char* origin_url,
+ quota::StorageType type) {
+ FilePath origin_base_path = GetOriginBasePath(origin_url, type);
+ FilePath file_path = origin_base_path.AppendASCII(file_name);
+
+ if (file_path.empty())
+ return false;
+
+ int file_flags = base::PLATFORM_FILE_CREATE_ALWAYS |
+ base::PLATFORM_FILE_WRITE;
+ base::PlatformFileError error_code;
+ base::PlatformFile file =
+ base::CreatePlatformFile(file_path, file_flags, NULL, &error_code);
+ if (error_code != base::PLATFORM_FILE_OK)
+ return false;
+
+ bool succeeded;
+ succeeded = base::TruncatePlatformFile(file, file_size);
+ succeeded = succeeded && base::ClosePlatformFile(file);
+ return succeeded;
+ }
+
+ void CreateFiles(const TestFile* files, int num_files) {
+ for (int i = 0; i < num_files; i++) {
+ if (files[i].isDirectory) {
+ ASSERT_TRUE(CreateFileSystemDirectory(
+ files[i].name, files[i].origin_url, files[i].type));
+ } else {
+ ASSERT_TRUE(CreateFileSystemFile(
+ files[i].name, files[i].size, files[i].origin_url, files[i].type));
+ }
+ }
+ }
+
+ int64 usage() const { return usage_; }
+ int additional_callback_count() const { return additional_callback_count_; }
+ void set_additional_callback_count(int count) {
+ additional_callback_count_ = count;
+ }
+
+ private:
+ void OnGetUsage(int64 usage) {
+ usage_ = usage;
+ }
+
+ void OnGetOrigins(const std::set<GURL>& origins) {
+ origins_ = origins;
+ }
+
+ void OnGetAdditionalUsage(int64) {
+ ++additional_callback_count_;
+ }
+
+ ScopedTempDir data_dir_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ base::ScopedCallbackFactory<SandboxQuotaClientTest> callback_factory_;
+ int64 usage_;
+ int additional_callback_count_;
+ std::set<GURL> origins_;
+
+ DISALLOW_COPY_AND_ASSIGN(SandboxQuotaClientTest);
+};
+
+TEST_F(SandboxQuotaClientTest, NoFileSystemTest) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+
+ EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+}
+
+TEST_F(SandboxQuotaClientTest, NoFileTest) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ }
+}
+
+TEST_F(SandboxQuotaClientTest, OneFileTest) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {false, "foo", 4921, kDummyURL1, kTemporary},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(4921 + kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ }
+}
+
+TEST_F(SandboxQuotaClientTest, TwoFilesTest) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {false, "foo", 10310, kDummyURL1, kTemporary},
+ {false, "bar", 41, kDummyURL1, kTemporary},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(10310 + 41 + kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ }
+}
+
+TEST_F(SandboxQuotaClientTest, EmptyFilesTest) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {false, "foo", 0, kDummyURL1, kTemporary},
+ {false, "bar", 0, kDummyURL1, kTemporary},
+ {false, "baz", 0, kDummyURL1, kTemporary},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ }
+}
+
+TEST_F(SandboxQuotaClientTest, SubDirectoryTest) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {true, "dirtest", 0, kDummyURL1, kTemporary},
+ {false, "dirtest/foo", 11921, kDummyURL1, kTemporary},
+ {false, "bar", 4814, kDummyURL1, kTemporary},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(11921 + 4814 + kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ }
+}
+
+TEST_F(SandboxQuotaClientTest, MultiTypeTest) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {true, "dirtest", 0, kDummyURL1, kTemporary},
+ {false, "dirtest/foo", 133, kDummyURL1, kTemporary},
+ {false, "bar", 14, kDummyURL1, kTemporary},
+ {true, NULL, 0, kDummyURL1, kPersistent},
+ {true, "dirtest", 0, kDummyURL1, kPersistent},
+ {false, "dirtest/foo", 193, kDummyURL1, kPersistent},
+ {false, "bar", 9, kDummyURL1, kPersistent},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(133 + 14 + kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ EXPECT_EQ(193 + 9 + kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent));
+ }
+}
+
+TEST_F(SandboxQuotaClientTest, MultiDomainTest) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {true, "dir1", 0, kDummyURL1, kTemporary},
+ {false, "dir1/foo", 1331, kDummyURL1, kTemporary},
+ {false, "bar", 134, kDummyURL1, kTemporary},
+ {true, NULL, 0, kDummyURL1, kPersistent},
+ {true, "dir2", 0, kDummyURL1, kPersistent},
+ {false, "dir2/foo", 1903, kDummyURL1, kPersistent},
+ {false, "bar", 19, kDummyURL1, kPersistent},
+ {true, NULL, 0, kDummyURL2, kTemporary},
+ {true, "dom", 0, kDummyURL2, kTemporary},
+ {false, "dom/fan", 1319, kDummyURL2, kTemporary},
+ {false, "bar", 113, kDummyURL2, kTemporary},
+ {true, NULL, 0, kDummyURL2, kPersistent},
+ {true, "dom", 0, kDummyURL2, kPersistent},
+ {false, "dom/fan", 2013, kDummyURL2, kPersistent},
+ {false, "baz", 18, kDummyURL2, kPersistent},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(1331 + 134 + kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ EXPECT_EQ(1903 + 19 + kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent));
+ EXPECT_EQ(1319 + 113 + kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL2, kTemporary));
+ EXPECT_EQ(2013 + 18 + kUsageFileSize,
+ GetOriginUsage(quota_client.get(), kDummyURL2, kPersistent));
+ }
+}
+
+TEST_F(SandboxQuotaClientTest, GetUsage_MultipleTasks) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {false, "foo", 11, kDummyURL1, kTemporary},
+ {false, "bar", 22, kDummyURL1, kTemporary},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ // Dispatching three GetUsage tasks.
+ set_additional_callback_count(0);
+ GetOriginUsageAsync(quota_client.get(), kDummyURL1, kTemporary);
+ RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
+ RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(11 + 22 + kUsageFileSize, usage());
+ EXPECT_EQ(2, additional_callback_count());
+
+ // Once more, in a different order.
+ set_additional_callback_count(0);
+ RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
+ GetOriginUsageAsync(quota_client.get(), kDummyURL1, kTemporary);
+ RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(11 + 22 + kUsageFileSize, usage());
+ EXPECT_EQ(2, additional_callback_count());
+}
+
+TEST_F(SandboxQuotaClientTest, GetOriginsForType) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {true, NULL, 0, kDummyURL2, kTemporary},
+ {true, NULL, 0, kDummyURL3, kPersistent},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ std::set<GURL> origins = GetOriginsForType(quota_client.get(), kTemporary);
+ EXPECT_EQ(2U, origins.size());
+ EXPECT_TRUE(origins.find(GURL(kDummyURL1)) != origins.end());
+ EXPECT_TRUE(origins.find(GURL(kDummyURL2)) != origins.end());
+ EXPECT_TRUE(origins.find(GURL(kDummyURL3)) == origins.end());
+}
+
+TEST_F(SandboxQuotaClientTest, GetOriginsForHost) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(false));
+ const char* kURL1 = "http://foo.com/";
+ const char* kURL2 = "https://foo.com/";
+ const char* kURL3 = "http://foo.com:1/";
+ const char* kURL4 = "http://foo2.com/";
+ const char* kURL5 = "http://foo.com:2/";
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kURL1, kTemporary},
+ {true, NULL, 0, kURL2, kTemporary},
+ {true, NULL, 0, kURL3, kTemporary},
+ {true, NULL, 0, kURL4, kTemporary},
+ {true, NULL, 0, kURL5, kPersistent},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ std::set<GURL> origins = GetOriginsForHost(
+ quota_client.get(), kTemporary, "foo.com");
+ EXPECT_EQ(3U, origins.size());
+ EXPECT_TRUE(origins.find(GURL(kURL1)) != origins.end());
+ EXPECT_TRUE(origins.find(GURL(kURL2)) != origins.end());
+ EXPECT_TRUE(origins.find(GURL(kURL3)) != origins.end());
+ EXPECT_TRUE(origins.find(GURL(kURL4)) == origins.end()); // Different host.
+ EXPECT_TRUE(origins.find(GURL(kURL5)) == origins.end()); // Different type.
+}
+
+TEST_F(SandboxQuotaClientTest, IncognitoTest) {
+ scoped_ptr<SandboxQuotaClient> quota_client(NewQuotaClient(true));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {false, "foo", 10, kDummyURL1, kTemporary},
+ };
+ CreateFiles(kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ // Having files in the usual directory wouldn't affect the result
+ // queried in incognito mode.
+ EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent));
+
+ std::set<GURL> origins = GetOriginsForType(quota_client.get(), kTemporary);
+ EXPECT_EQ(0U, origins.size());
+ origins = GetOriginsForHost(quota_client.get(), kTemporary, "www.dummy.org");
+ EXPECT_EQ(0U, origins.size());
+}
diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi
index 4d0ef77..aa70b0b 100644
--- a/webkit/fileapi/webkit_fileapi.gypi
+++ b/webkit/fileapi/webkit_fileapi.gypi
@@ -13,6 +13,7 @@
'<(DEPTH)/base/base.gyp:base',
'<(DEPTH)/net/net.gyp:net',
'<(DEPTH)/third_party/leveldb/leveldb.gyp:leveldb',
+ '<(DEPTH)/webkit/support/webkit_support.gyp:quota',
],
'sources': [
'file_system_callback_dispatcher.cc',
@@ -41,20 +42,20 @@
'file_system_url_request_job.h',
'file_system_url_request_job_base.cc',
'file_system_url_request_job_base.h',
- 'file_system_usage_tracker.cc',
- 'file_system_usage_tracker.h',
+ 'file_system_usage_cache.cc',
+ 'file_system_usage_cache.h',
'file_system_util.cc',
'file_system_util.h',
- 'file_system_usage_cache.h',
- 'file_system_usage_cache.cc',
'file_writer_delegate.cc',
'file_writer_delegate.h',
'local_file_system_file_util.cc',
'local_file_system_file_util.h',
- 'sandbox_mount_point_provider.cc',
- 'sandbox_mount_point_provider.h',
'quota_file_util.cc',
'quota_file_util.h',
+ 'sandbox_mount_point_provider.cc',
+ 'sandbox_mount_point_provider.h',
+ 'sandbox_quota_client.cc',
+ 'sandbox_quota_client.h',
'webfilewriter_base.cc',
'webfilewriter_base.h',
],
diff --git a/webkit/quota/mock_storage_client.cc b/webkit/quota/mock_storage_client.cc
index 93fe909..ee1a0b1 100644
--- a/webkit/quota/mock_storage_client.cc
+++ b/webkit/quota/mock_storage_client.cc
@@ -40,8 +40,8 @@ class MockStorageClientIDSequencer {
} // anonymous namespace
-MockStorageClient::MockStorageClient(QuotaManager* qm)
- : quota_manager_(qm),
+MockStorageClient::MockStorageClient(QuotaManagerProxy* quota_manager_proxy)
+ : quota_manager_proxy_(quota_manager_proxy),
id_(MockStorageClientIDSequencer::GetInstance()->NextMockID()),
runnable_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
}
@@ -52,10 +52,6 @@ MockStorageClient::~MockStorageClient() {
origins_callbacks_.begin(), origins_callbacks_.end());
}
-QuotaClient::ID MockStorageClient::id() const {
- return id_;
-}
-
void MockStorageClient::AddMockOriginData(
const GURL& origin_url, StorageType type, int64 size) {
origin_data_.insert(std::make_pair(origin_url, MockOriginData(type, size)));
@@ -69,7 +65,15 @@ void MockStorageClient::ModifyMockOriginDataSize(
AddMockOriginData(origin_url, type, delta);
return;
}
- quota_manager_->NotifyStorageModified(id(), origin_url, type, delta);
+ quota_manager_proxy_->NotifyStorageModified(id(), origin_url, type, delta);
+}
+
+QuotaClient::ID MockStorageClient::id() const {
+ return id_;
+}
+
+void MockStorageClient::OnQuotaManagerDestroyed() {
+ delete this;
}
void MockStorageClient::GetOriginUsage(const GURL& origin_url,
diff --git a/webkit/quota/mock_storage_client.h b/webkit/quota/mock_storage_client.h
index 3a803ff..ac2545b 100644
--- a/webkit/quota/mock_storage_client.h
+++ b/webkit/quota/mock_storage_client.h
@@ -14,25 +14,22 @@
namespace quota {
-class QuotaManager;
+class QuotaManagerProxy;
// Mock storage class for testing.
class MockStorageClient : public QuotaClient {
public:
- MockStorageClient(QuotaManager* qm);
+ MockStorageClient(QuotaManagerProxy* quota_manager_proxy);
virtual ~MockStorageClient();
- virtual QuotaClient::ID id() const OVERRIDE;
-
// To add or modify mock data in this client.
void AddMockOriginData(const GURL& origin_url, StorageType type, int64 size);
void ModifyMockOriginDataSize(
const GURL& origin_url, StorageType type, int64 delta);
- typedef QuotaClient::GetUsageCallback GetUsageCallback;
- typedef QuotaClient::GetOriginsCallback GetOriginsCallback;
-
// QuotaClient methods.
+ virtual QuotaClient::ID id() const OVERRIDE;
+ virtual void OnQuotaManagerDestroyed() OVERRIDE;
virtual void GetOriginUsage(const GURL& origin_url,
StorageType type,
GetUsageCallback* callback) OVERRIDE;
@@ -51,7 +48,7 @@ class MockStorageClient : public QuotaClient {
const std::string& host,
GetOriginsCallback* callback);
- QuotaManager* quota_manager_;
+ scoped_refptr<QuotaManagerProxy> quota_manager_proxy_;
const ID id_;
struct MockOriginData {
diff --git a/webkit/quota/quota_client.h b/webkit/quota/quota_client.h
index 1852e27..41db15b 100644
--- a/webkit/quota/quota_client.h
+++ b/webkit/quota/quota_client.h
@@ -37,6 +37,9 @@ class QuotaClient {
virtual ID id() const = 0;
+ // Called when the quota manager is destroyed.
+ virtual void OnQuotaManagerDestroyed() = 0;
+
// Called by the QuotaManager.
// Gets the amount of data stored in the storage specified by
// |origin_url| and |type|.
diff --git a/webkit/quota/quota_manager.cc b/webkit/quota/quota_manager.cc
index 647131c..0f18532 100644
--- a/webkit/quota/quota_manager.cc
+++ b/webkit/quota/quota_manager.cc
@@ -345,21 +345,22 @@ QuotaManager::QuotaManager(bool is_incognito,
scoped_refptr<base::MessageLoopProxy> db_thread)
: is_incognito_(is_incognito),
profile_path_(profile_path),
+ proxy_(new QuotaManagerProxy(
+ ALLOW_THIS_IN_INITIALIZER_LIST(this), io_thread)),
db_initialized_(false),
db_disabled_(false),
io_thread_(io_thread),
db_thread_(db_thread),
- temporary_global_quota_(-1),
- callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ temporary_global_quota_(-1) {
}
QuotaManager::~QuotaManager() {
- STLDeleteContainerPointers(clients_.begin(), clients_.end());
-}
-
-void QuotaManager::RegisterClient(QuotaClient* client) {
- DCHECK(!database_.get());
- clients_.push_back(client);
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ proxy_->manager_ = NULL;
+ std::for_each(clients_.begin(), clients_.end(),
+ std::mem_fun(&QuotaClient::OnQuotaManagerDestroyed));
+ if (database_.get())
+ db_thread_->DeleteSoon(FROM_HERE, database_.release());
}
void QuotaManager::GetUsageAndQuota(
@@ -399,15 +400,6 @@ void QuotaManager::RequestQuota(
delete callback;
}
-void QuotaManager::NotifyStorageModified(
- QuotaClient::ID client_id,
- const GURL& origin, StorageType type, int64 delta) {
- LazyInitialize();
- UsageTracker* tracker = GetUsageTracker(type);
- DCHECK(tracker);
- tracker->UpdateUsageCache(client_id, origin, delta);
-}
-
void QuotaManager::GetTemporaryGlobalQuota(QuotaCallback* callback) {
LazyInitialize();
if (temporary_global_quota_ >= 0) {
@@ -478,6 +470,21 @@ void QuotaManager::LazyInitialize() {
task->Start();
}
+void QuotaManager::RegisterClient(QuotaClient* client) {
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(!database_.get());
+ clients_.push_back(client);
+}
+
+void QuotaManager::NotifyStorageModified(
+ QuotaClient::ID client_id,
+ const GURL& origin, StorageType type, int64 delta) {
+ LazyInitialize();
+ UsageTracker* tracker = GetUsageTracker(type);
+ DCHECK(tracker);
+ tracker->UpdateUsageCache(client_id, origin, delta);
+}
+
UsageTracker* QuotaManager::GetUsageTracker(StorageType type) const {
switch (type) {
case kStorageTypeTemporary:
@@ -499,13 +506,10 @@ void QuotaManager::DidGetPersistentHostQuota(const std::string& host,
int64 quota) {
DCHECK(persistent_host_quota_.find(host) == persistent_host_quota_.end());
persistent_host_quota_[host] = quota;
- persistent_host_quota_callbacks_.Run(host, quota);
+ persistent_host_quota_callbacks_.Run(host, host, quota);
}
void QuotaManager::DeleteOnCorrectThread() const {
- if (database_.get()) {
- db_thread_->DeleteSoon(FROM_HERE, database_.release());
- }
if (!io_thread_->BelongsToCurrentThread()) {
io_thread_->DeleteSoon(FROM_HERE, this);
return;
@@ -513,4 +517,41 @@ void QuotaManager::DeleteOnCorrectThread() const {
delete this;
}
+// QuotaManagerProxy ----------------------------------------------------------
+
+void QuotaManagerProxy::RegisterClient(QuotaClient* client) {
+ if (!io_thread_->BelongsToCurrentThread()) {
+ io_thread_->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &QuotaManagerProxy::RegisterClient, client));
+ return;
+ }
+ if (manager_)
+ manager_->RegisterClient(client);
+ else
+ client->OnQuotaManagerDestroyed();
+}
+
+void QuotaManagerProxy::NotifyStorageModified(
+ QuotaClient::ID client_id,
+ const GURL& origin,
+ StorageType type,
+ int64 delta) {
+ if (!io_thread_->BelongsToCurrentThread()) {
+ io_thread_->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &QuotaManagerProxy::NotifyStorageModified,
+ client_id, origin, type, delta));
+ return;
+ }
+ if (manager_)
+ manager_->NotifyStorageModified(client_id, origin, type, delta);
+}
+
+QuotaManagerProxy::QuotaManagerProxy(
+ QuotaManager* manager, base::MessageLoopProxy* io_thread)
+ : manager_(manager), io_thread_(io_thread) {
+}
+
+QuotaManagerProxy::~QuotaManagerProxy() {
+}
+
} // namespace quota
diff --git a/webkit/quota/quota_manager.h b/webkit/quota/quota_manager.h
index a9a458c..eb8d70f 100644
--- a/webkit/quota/quota_manager.h
+++ b/webkit/quota/quota_manager.h
@@ -28,9 +28,11 @@ class QuotaDatabase;
class UsageTracker;
struct QuotaManagerDeleter;
+class QuotaManagerProxy;
// The quota manager class. This class is instantiated per profile and
-// held by the profile.
+// held by the profile. With the exception of the constructor and the
+// proxy() method, all methods should only be called on the IO thread.
class QuotaManager : public QuotaTaskObserver,
public base::RefCountedThreadSafe<
QuotaManager, QuotaManagerDeleter> {
@@ -48,26 +50,20 @@ class QuotaManager : public QuotaTaskObserver,
virtual ~QuotaManager();
- // The client's ownership is transferred to the manager.
- void RegisterClient(QuotaClient* client);
+ // Returns a proxy object that can be used on any thread.
+ QuotaManagerProxy* proxy() { return proxy_.get(); }
- // Called by clients or webapps on the IO thread.
- void GetUsageAndQuota(const GURL& origin, StorageType type,
+ // Called by clients or webapps.
+ void GetUsageAndQuota(const GURL& origin,
+ StorageType type,
GetUsageAndQuotaCallback* callback);
- // Called by webapps on the IO thread.
- void RequestQuota(const GURL& origin, StorageType type,
+ // Called by webapps.
+ void RequestQuota(const GURL& origin,
+ StorageType type,
int64 requested_size,
RequestQuotaCallback* callback);
- // Called by clients on the IO thread.
- // QuotaClients must call this method whenever they have made any
- // modifications that change the amount of data stored in their storage.
- void NotifyStorageModified(QuotaClient::ID client_id,
- const GURL& origin,
- StorageType type,
- int64 delta);
-
// Called by UI and internal modules.
void GetTemporaryGlobalQuota(QuotaCallback* callback);
void SetTemporaryGlobalQuota(int64 new_quota);
@@ -97,23 +93,39 @@ class QuotaManager : public QuotaTaskObserver,
typedef std::map<HostAndType, UsageAndQuotaDispatcherTask*>
UsageAndQuotaDispatcherTaskMap;
+ friend struct QuotaManagerDeleter;
+ friend class QuotaManagerProxy;
+
// This initialization method is lazily called on the IO thread
// when the first quota manager API is called.
// Initialize must be called after all quota clients are added to the
// manager by RegisterStorage.
void LazyInitialize();
+ // Called by clients via proxy.
+ // Registers a quota client to the manager.
+ // The client must remain valid until OnQuotaManagerDestored is called.
+ void RegisterClient(QuotaClient* client);
+
+ // Called by clients via proxy.
+ // QuotaClients must call this method whenever they have made any
+ // modifications that change the amount of data stored in their storage.
+ void NotifyStorageModified(QuotaClient::ID client_id,
+ const GURL& origin,
+ StorageType type,
+ int64 delta);
+
UsageTracker* GetUsageTracker(StorageType type) const;
void DidGetTemporaryGlobalQuota(int64 quota);
void DidGetPersistentHostQuota(const std::string& host, int64 quota);
- friend struct QuotaManagerDeleter;
void DeleteOnCorrectThread() const;
const bool is_incognito_;
const FilePath profile_path_;
+ scoped_refptr<QuotaManagerProxy> proxy_;
bool db_initialized_;
bool db_disabled_;
scoped_refptr<base::MessageLoopProxy> io_thread_;
@@ -133,8 +145,6 @@ class QuotaManager : public QuotaTaskObserver,
std::map<std::string, int64> persistent_host_quota_;
HostQuotaCallbackMap persistent_host_quota_callbacks_;
- base::ScopedCallbackFactory<QuotaManager> callback_factory_;
-
DISALLOW_COPY_AND_ASSIGN(QuotaManager);
};
@@ -144,6 +154,28 @@ struct QuotaManagerDeleter {
}
};
+// The proxy may be called and finally released on any thread.
+class QuotaManagerProxy
+ : public base::RefCountedThreadSafe<QuotaManagerProxy> {
+ public:
+ void RegisterClient(QuotaClient* client);
+ void NotifyStorageModified(QuotaClient::ID client_id,
+ const GURL& origin,
+ StorageType type,
+ int64 delta);
+ private:
+ friend class QuotaManager;
+ friend class base::RefCountedThreadSafe<QuotaManagerProxy>;
+ QuotaManagerProxy(QuotaManager* manager, base::MessageLoopProxy* io_thread);
+ ~QuotaManagerProxy();
+
+ QuotaManager* manager_; // only accessed on the io thread
+ scoped_refptr<base::MessageLoopProxy> io_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuotaManagerProxy);
+};
+
+
} // namespace quota
#endif // WEBKIT_QUOTA_QUOTA_MANAGER_H_
diff --git a/webkit/quota/quota_manager_unittest.cc b/webkit/quota/quota_manager_unittest.cc
index 47a4c27..eb0af8f 100644
--- a/webkit/quota/quota_manager_unittest.cc
+++ b/webkit/quota/quota_manager_unittest.cc
@@ -12,6 +12,7 @@
#include "base/memory/scoped_temp_dir.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
+#include "base/stl_util-inl.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageQuotaError.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageQuotaType.h"
#include "webkit/quota/mock_storage_client.h"
@@ -57,8 +58,7 @@ class QuotaManagerTest : public testing::Test {
protected:
MockStorageClient* CreateClient(
const MockOriginData* mock_data, size_t mock_data_size) {
- MockStorageClient* client(
- new MockStorageClient(quota_manager_.get()));
+ MockStorageClient* client = new MockStorageClient(quota_manager_->proxy());
for (size_t i = 0; i < mock_data_size; ++i) {
client->AddMockOriginData(GURL(mock_data[i].origin),
mock_data[i].type,
@@ -68,7 +68,7 @@ class QuotaManagerTest : public testing::Test {
}
void RegisterClient(MockStorageClient* client) {
- quota_manager_->RegisterClient(client);
+ quota_manager_->proxy()->RegisterClient(client);
}
void GetUsageAndQuota(const GURL& origin, StorageType type) {
diff --git a/webkit/quota/quota_types.h b/webkit/quota/quota_types.h
index 9c67b34..c01b97a 100644
--- a/webkit/quota/quota_types.h
+++ b/webkit/quota/quota_types.h
@@ -68,6 +68,7 @@ class CallbackQueue1 : public CallbackQueueBase<CallbackType1> {
typedef typename CallbackQueueBase<CallbackType1>::Queue Queue;
// Runs the callbacks added to the queue and clears the queue.
void Run(A1 arg) {
+ // Note: template-derived class needs 'this->' to access its base class.
for (typename Queue::iterator iter = this->callbacks_.begin();
iter != this->callbacks_.end(); ++iter) {
(*iter)->Run(arg);
@@ -95,15 +96,13 @@ class CallbackQueue2 : public CallbackQueueBase<CallbackType2> {
typedef CallbackQueue1<UsageCallback*, int64> UsageCallbackQueue;
typedef CallbackQueue1<QuotaCallback*, int64> QuotaCallbackQueue;
-template <typename CallbackType2, typename KEY = std::string,
- typename ARG = int64>
-class CallbackQueueMap {
+template <typename CallbackType, typename CallbackQueueType, typename KEY>
+class CallbackQueueMapBase {
public:
- typedef CallbackQueue2<CallbackType2, const KEY&, ARG> Queue;
- typedef std::map<KEY, Queue> CallbackMap;
+ typedef std::map<KEY, CallbackQueueType> CallbackMap;
typedef typename CallbackMap::iterator iterator;
- bool Add(const KEY& key, CallbackType2 callback) {
+ bool Add(const KEY& key, CallbackType callback) {
return callback_map_[key].Add(callback);
}
@@ -111,30 +110,65 @@ class CallbackQueueMap {
return (callback_map_.find(key) != callback_map_.end());
}
+ iterator Begin() { return callback_map_.begin(); }
+ iterator End() { return callback_map_.end(); }
+
+ void Clear() { callback_map_.clear(); }
+
+ protected:
+ CallbackMap callback_map_;
+};
+
+template <typename CallbackType1, typename KEY, typename ARG>
+class CallbackQueueMap1
+ : public CallbackQueueMapBase<CallbackType1,
+ CallbackQueue1<CallbackType1, ARG>,
+ KEY> {
+ public:
+ typedef typename CallbackQueueMapBase<
+ CallbackType1,
+ CallbackQueue1<CallbackType1, ARG>,
+ KEY>::iterator iterator;
+ typedef CallbackQueue1<CallbackType1, ARG> Queue;
+
// Runs the callbacks added for the given |key| and clears the key
// from the map.
void Run(const KEY& key, ARG arg) {
- if (!HasCallbacks(key))
+ if (!this->HasCallbacks(key))
return;
- Queue& queue = callback_map_[key];
- queue.Run(key, arg);
- callback_map_.erase(key);
- }
-
- iterator Begin() { return callback_map_.begin(); }
- iterator End() { return callback_map_.end(); }
- static void RunAt(iterator iter, ARG arg) {
- iter->second.Run(iter->first, arg);
+ Queue& queue = this->callback_map_[key];
+ queue.Run(arg);
+ this->callback_map_.erase(key);
}
+};
- void Clear() { callback_map_.clear(); }
+template <typename CallbackType2, typename KEY, typename ARG1, typename ARG2>
+class CallbackQueueMap2
+ : public CallbackQueueMapBase<CallbackType2,
+ CallbackQueue2<CallbackType2, ARG1, ARG2>,
+ KEY> {
+ public:
+ typedef typename CallbackQueueMapBase<
+ CallbackType2,
+ CallbackQueue2<CallbackType2, ARG1, ARG2>,
+ KEY>::iterator iterator;
+ typedef CallbackQueue2<CallbackType2, ARG1, ARG2> Queue;
- private:
- CallbackMap callback_map_;
+ // Runs the callbacks added for the given |key| and clears the key
+ // from the map.
+ void Run(const KEY& key, ARG1 arg1, ARG2 arg2) {
+ if (!this->HasCallbacks(key))
+ return;
+ Queue& queue = this->callback_map_[key];
+ queue.Run(arg1, arg2);
+ this->callback_map_.erase(key);
+ }
};
-typedef CallbackQueueMap<HostUsageCallback*> HostUsageCallbackMap;
-typedef CallbackQueueMap<HostQuotaCallback*> HostQuotaCallbackMap;
+typedef CallbackQueueMap2<HostUsageCallback*, std::string,
+ const std::string&, int64> HostUsageCallbackMap;
+typedef CallbackQueueMap2<HostUsageCallback*, std::string,
+ const std::string&, int64> HostQuotaCallbackMap;
} // namespace quota
diff --git a/webkit/quota/usage_tracker.cc b/webkit/quota/usage_tracker.cc
index 043373e..52d9782 100644
--- a/webkit/quota/usage_tracker.cc
+++ b/webkit/quota/usage_tracker.cc
@@ -252,7 +252,7 @@ void UsageTracker::DidGetClientHostUsage(const std::string& host, int64 usage) {
if (--info.pending_clients == 0) {
// All the clients have returned their usage data. Dispatches the
// pending callbacks.
- host_usage_callbacks_.Run(host, info.usage);
+ host_usage_callbacks_.Run(host, host, info.usage);
outstanding_host_usage_.erase(host);
}
}
@@ -372,9 +372,9 @@ void ClientUsageTracker::DidGetGlobalUsage(
std::map<std::string, int64>::iterator found =
host_usage_map_.find(iter->first);
if (found == host_usage_map_.end())
- HostUsageCallbackMap::RunAt(iter, 0);
+ iter->second.Run(iter->first, 0);
else
- HostUsageCallbackMap::RunAt(iter, found->second);
+ iter->second.Run(iter->first, found->second);
}
host_usage_callbacks_.Clear();
}
@@ -394,7 +394,7 @@ void ClientUsageTracker::DidGetHostUsage(
}
// Dispatches the host usage callback.
- host_usage_callbacks_.Run(host, host_usage_map_[host]);
+ host_usage_callbacks_.Run(host, host, host_usage_map_[host]);
}
} // namespace quota
diff --git a/webkit/tools/test_shell/simple_file_system.cc b/webkit/tools/test_shell/simple_file_system.cc
index e5959ce..ebda9bc 100644
--- a/webkit/tools/test_shell/simple_file_system.cc
+++ b/webkit/tools/test_shell/simple_file_system.cc
@@ -132,6 +132,7 @@ SimpleFileSystem::SimpleFileSystem() {
base::MessageLoopProxy::CreateForCurrentThread(),
base::MessageLoopProxy::CreateForCurrentThread(),
NULL /* special storage policy */,
+ NULL /* quota manager */,
file_system_dir_.path(),
false /* incognito */,
true /* allow_file_access */,
diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi
index 490b8aa..699901e 100644
--- a/webkit/tools/test_shell/test_shell.gypi
+++ b/webkit/tools/test_shell/test_shell.gypi
@@ -382,11 +382,12 @@
'../../fileapi/file_system_origin_database_unittest.cc',
'../../fileapi/file_system_path_manager_unittest.cc',
'../../fileapi/file_system_usage_cache_unittest.cc',
- '../../fileapi/file_system_usage_tracker_unittest.cc',
'../../fileapi/file_system_util_unittest.cc',
'../../fileapi/local_file_system_file_util_unittest.cc',
- '../../fileapi/sandbox_mount_point_provider_unittest.cc',
'../../fileapi/quota_file_util_unittest.cc',
+ '../../fileapi/sandbox_mount_point_provider_unittest.cc',
+ '../../fileapi/sandbox_mount_point_provider_unittest.cc',
+ '../../fileapi/sandbox_quota_client_unittest.cc',
'../../fileapi/webfilewriter_base_unittest.cc',
'../../glue/bookmarklet_unittest.cc',
'../../glue/context_menu_unittest.cc',