summaryrefslogtreecommitdiffstats
path: root/webkit/fileapi
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 /webkit/fileapi
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
Diffstat (limited to 'webkit/fileapi')
-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
21 files changed, 1028 insertions, 657 deletions
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',
],