diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-10 13:17:58 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-10 13:17:58 +0000 |
commit | 955dd7ebf6808dd93dd1aedc7390e7280e848f80 (patch) | |
tree | 6a9e559583084a956005c367249026647e3879bf /webkit/fileapi | |
parent | 0c5e07b0a63a5aea8ab0c2b50177b4c99e7c9538 (diff) | |
download | chromium_src-955dd7ebf6808dd93dd1aedc7390e7280e848f80.zip chromium_src-955dd7ebf6808dd93dd1aedc7390e7280e848f80.tar.gz chromium_src-955dd7ebf6808dd93dd1aedc7390e7280e848f80.tar.bz2 |
Add 1st cut of FileSystemUsageTracker that tracks the usage changes in FileSystem API.
For now it has no meaningful implementation yet; mostly just for
defining a few interfaces.
BUG=
TEST=FileSystemUsageTrackerTest.DummyTest
Review URL: http://codereview.chromium.org/6426001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@74429 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
-rw-r--r-- | webkit/fileapi/file_system_path_manager.cc | 53 | ||||
-rw-r--r-- | webkit/fileapi/file_system_path_manager.h | 24 | ||||
-rw-r--r-- | webkit/fileapi/file_system_usage_tracker.cc | 158 | ||||
-rw-r--r-- | webkit/fileapi/file_system_usage_tracker.h | 71 | ||||
-rw-r--r-- | webkit/fileapi/file_system_usage_tracker_unittest.cc | 66 | ||||
-rw-r--r-- | webkit/fileapi/sandboxed_file_system_context.cc | 11 | ||||
-rw-r--r-- | webkit/fileapi/sandboxed_file_system_context.h | 6 | ||||
-rw-r--r-- | webkit/fileapi/webkit_fileapi.gypi | 2 |
8 files changed, 362 insertions, 29 deletions
diff --git a/webkit/fileapi/file_system_path_manager.cc b/webkit/fileapi/file_system_path_manager.cc index 72c5355..3e0cd5e 100644 --- a/webkit/fileapi/file_system_path_manager.cc +++ b/webkit/fileapi/file_system_path_manager.cc @@ -77,6 +77,14 @@ FilePath::StringType CreateUniqueDirectoryName(const GURL& origin_url) { static const char kExtensionScheme[] = "chrome-extension"; +inline std::string GetFileSystemTypeString(fileapi::FileSystemType type) { + if (type == fileapi::kFileSystemTypeTemporary) + return fileapi::FileSystemPathManager::kTemporaryName; + else if (type == fileapi::kFileSystemTypePersistent) + return fileapi::FileSystemPathManager::kPersistentName; + return std::string(); +} + } // anonymous namespace class FileSystemPathManager::GetFileSystemRootPathTask @@ -198,29 +206,17 @@ void FileSystemPathManager::GetFileSystemRootPath( return; } - if (type != fileapi::kFileSystemTypeTemporary && - type != fileapi::kFileSystemTypePersistent) { - LOG(WARNING) << "Unknown filesystem type is requested:" << type; + FilePath origin_base_path = GetFileSystemBaseDirectoryForOriginAndType( + base_path(), origin_url, type); + if (origin_base_path.empty()) { callback->Run(false, FilePath(), std::string()); return; } - std::string storage_identifier = GetStorageIdentifierFromURL(origin_url); - - std::string type_string; - if (type == fileapi::kFileSystemTypeTemporary) - type_string = kTemporaryName; - else if (type == fileapi::kFileSystemTypePersistent) - type_string = kPersistentName; - DCHECK(!type_string.empty()); - - FilePath origin_base_path = base_path_.AppendASCII(storage_identifier) - .AppendASCII(type_string); - std::string name = storage_identifier + ":" + type_string; - scoped_refptr<GetFileSystemRootPathTask> task( new GetFileSystemRootPathTask(file_message_loop_, - name, callback.release())); + GetFileSystemName(origin_url, type), + callback.release())); task->Start(origin_url, origin_base_path, create); } @@ -326,6 +322,14 @@ bool FileSystemPathManager::IsAllowedScheme(const GURL& url) const { (url.SchemeIsFile() && allow_file_access_from_files_); } +// static +std::string FileSystemPathManager::GetFileSystemName( + const GURL& origin_url, fileapi::FileSystemType type) { + return GetStorageIdentifierFromURL(origin_url) + .append(":").append(GetFileSystemTypeString(type)); +} + +// static std::string FileSystemPathManager::GetStorageIdentifierFromURL( const GURL& url) { WebKit::WebSecurityOrigin web_security_origin = @@ -333,6 +337,21 @@ std::string FileSystemPathManager::GetStorageIdentifierFromURL( return web_security_origin.databaseIdentifier().utf8(); } +// static +FilePath FileSystemPathManager::GetFileSystemBaseDirectoryForOriginAndType( + const FilePath& base_path, const GURL& origin_url, + fileapi::FileSystemType type) { + if (!origin_url.is_valid()) + return FilePath(); + std::string type_string = GetFileSystemTypeString(type); + if (type_string.empty()) { + LOG(WARNING) << "Unknown filesystem type is requested:" << type; + return FilePath(); + } + return base_path.AppendASCII(GetStorageIdentifierFromURL(origin_url)) + .AppendASCII(type_string); +} + } // namespace fileapi COMPILE_ASSERT(int(WebFileSystem::TypeTemporary) == \ diff --git a/webkit/fileapi/file_system_path_manager.h b/webkit/fileapi/file_system_path_manager.h index 16c7182..f7a3803 100644 --- a/webkit/fileapi/file_system_path_manager.h +++ b/webkit/fileapi/file_system_path_manager.h @@ -5,8 +5,6 @@ #ifndef WEBKIT_FILEAPI_FILE_SYSTEM_PATH_MANAGER_H_ #define WEBKIT_FILEAPI_FILE_SYSTEM_PATH_MANAGER_H_ -#include <map> - #include "base/callback.h" #include "base/file_path.h" #include "base/scoped_ptr.h" @@ -20,6 +18,12 @@ class MessageLoopProxy; namespace fileapi { +// An interface to construct or crack sandboxed filesystem paths. +// Currently each sandboxed filesystem path looks like: +// +// <profile_dir>/FileSystem/<origin_identifier>/<type>/chrome-<unique>/... +// +// where <type> is either one of "Temporary" or "Persistent". class FileSystemPathManager { public: FileSystemPathManager(scoped_refptr<base::MessageLoopProxy> file_message_loop, @@ -74,9 +78,25 @@ class FileSystemPathManager { return base_path_; } + // Returns the filesystem name string for the given |origin_url| and |type|. + static std::string GetFileSystemName(const GURL& url, + fileapi::FileSystemType type); + // Returns the storage identifier string for the given |url|. static std::string GetStorageIdentifierFromURL(const GURL& url); + // Gets a base directory path of the sandboxed filesystem that is + // specified by |origin_url| 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 actural root path for the filesystem. + static FilePath GetFileSystemBaseDirectoryForOriginAndType( + const FilePath& base_path, + const GURL& origin_url, + fileapi::FileSystemType type); + private: class GetFileSystemRootPathTask; diff --git a/webkit/fileapi/file_system_usage_tracker.cc b/webkit/fileapi/file_system_usage_tracker.cc new file mode 100644 index 0000000..2b16a1f --- /dev/null +++ b/webkit/fileapi/file_system_usage_tracker.cc @@ -0,0 +1,158 @@ +// 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/message_loop_proxy.h" +#include "base/scoped_ptr.h" +#include "base/task.h" +#include "googleurl/src/gurl.h" +#include "webkit/fileapi/file_system_path_manager.h" + +namespace fileapi { + +class FileSystemUsageTracker::GetUsageTask + : public base::RefCountedThreadSafe<GetUsageTask> { + public: + GetUsageTask( + FileSystemUsageTracker* tracker, + scoped_refptr<base::MessageLoopProxy> file_message_loop, + std::string fs_name, + const FilePath& origin_base_path) + : tracker_(tracker), + file_message_loop_(file_message_loop), + original_message_loop_( + base::MessageLoopProxy::CreateForCurrentThread()), + fs_name_(fs_name), + 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()); + + // TODO(dmikurube): add the code that retrieves the origin usage here. + + 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_name_, fs_usage_); + } + } + + FileSystemUsageTracker* tracker_; + scoped_refptr<base::MessageLoopProxy> file_message_loop_; + scoped_refptr<base::MessageLoopProxy> original_message_loop_; + std::string fs_name_; + 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( + FileSystemPathManager::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 fs_name = FileSystemPathManager::GetFileSystemName( + origin_url, type); + if (pending_usage_callbacks_.find(fs_name) != + pending_usage_callbacks_.end()) { + // Another get usage task is running. Add the callback to + // the pending queue and return. + pending_usage_callbacks_[fs_name].push_back(callback.release()); + return; + } + + // Get the filesystem base path (i.e. "FileSystem/<origin>/<type>", + // without unique part). + FilePath origin_base_path = + FileSystemPathManager::GetFileSystemBaseDirectoryForOriginAndType( + base_path_, origin_url, type); + if (origin_base_path.empty()) { + // The directory does not exist. + callback->Run(0); + return; + } + + pending_usage_callbacks_[fs_name].push_back(callback.release()); + scoped_refptr<GetUsageTask> task( + new GetUsageTask(this, file_message_loop_, fs_name, 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_name, int64 usage) { + PendingUsageCallbackMap::iterator cb_list_iter = + pending_usage_callbacks_.find(fs_name); + 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 new file mode 100644 index 0000000..10a5177 --- /dev/null +++ b/webkit/fileapi/file_system_usage_tracker.h @@ -0,0 +1,71 @@ +// 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/ref_counted.h" +#include "webkit/fileapi/file_system_types.h" + +class GURL; + +namespace base { +class MessageLoopProxy; +} + +namespace fileapi { + +// Owned by the SandboxedFileSystemContext, which is a per-profile +// instance, and has the same lifetime as the SandboxedFileSystemContext. +// 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, SandboxedFileSystemContext.) +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 new file mode 100644 index 0000000..0d8a33c --- /dev/null +++ b/webkit/fileapi/file_system_usage_tracker_unittest.cc @@ -0,0 +1,66 @@ +// 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/message_loop.h" +#include "base/message_loop_proxy.h" +#include "base/scoped_callback_factory.h" +#include "googleurl/src/gurl.h" +#include "base/scoped_temp_dir.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/fileapi/file_system_path_manager.h" +#include "webkit/fileapi/file_system_types.h" + +using namespace fileapi; + +class FileSystemUsageTrackerTest : public testing::Test { + public: + FileSystemUsageTrackerTest() + : callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { + } + + void SetUp() { + ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); + } + + 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_; + } + + private: + void OnGetUsage(int64 usage) { + usage_ = usage; + } + + ScopedTempDir data_dir_; + base::ScopedCallbackFactory<FileSystemUsageTrackerTest> callback_factory_; + int64 usage_; + + DISALLOW_COPY_AND_ASSIGN(FileSystemUsageTrackerTest); +}; + +// TODO(dmikurube): change this test to a meaningful one once we add +// the real code in the FileSystemUsageTracker. +TEST_F(FileSystemUsageTrackerTest, DummyTest) { + scoped_ptr<FileSystemUsageTracker> tracker(NewUsageTracker(false)); + ASSERT_EQ(0, GetOriginUsage(tracker.get(), + GURL("http://www.dummy.org/"), + fileapi::kFileSystemTypeTemporary)); +} diff --git a/webkit/fileapi/sandboxed_file_system_context.cc b/webkit/fileapi/sandboxed_file_system_context.cc index 16232d5..1fd458d 100644 --- a/webkit/fileapi/sandboxed_file_system_context.cc +++ b/webkit/fileapi/sandboxed_file_system_context.cc @@ -8,6 +8,7 @@ #include "base/message_loop_proxy.h" #include "webkit/fileapi/file_system_path_manager.h" #include "webkit/fileapi/file_system_quota_manager.h" +#include "webkit/fileapi/file_system_usage_tracker.h" namespace fileapi { @@ -23,18 +24,14 @@ SandboxedFileSystemContext::SandboxedFileSystemContext( path_manager_(new FileSystemPathManager( file_message_loop, profile_path, is_incognito, allow_file_access)), quota_manager_(new FileSystemQuotaManager( - allow_file_access, unlimited_quota)) { + allow_file_access, unlimited_quota)), + usage_tracker_(new FileSystemUsageTracker( + file_message_loop, profile_path, is_incognito)) { } SandboxedFileSystemContext::~SandboxedFileSystemContext() { } -void SandboxedFileSystemContext::Shutdown() { - DCHECK(io_message_loop_->BelongsToCurrentThread()); - path_manager_.reset(); - quota_manager_.reset(); -} - void SandboxedFileSystemContext::DeleteDataForOriginOnFileThread( const GURL& origin_url) { DCHECK(path_manager_.get()); diff --git a/webkit/fileapi/sandboxed_file_system_context.h b/webkit/fileapi/sandboxed_file_system_context.h index fcb90bb..e3b7a67 100644 --- a/webkit/fileapi/sandboxed_file_system_context.h +++ b/webkit/fileapi/sandboxed_file_system_context.h @@ -19,6 +19,7 @@ namespace fileapi { class FileSystemPathManager; class FileSystemQuotaManager; +class FileSystemUsageTracker; class SandboxedFileSystemContext; struct DefaultContextDeleter; @@ -37,8 +38,6 @@ class SandboxedFileSystemContext bool unlimited_quota); ~SandboxedFileSystemContext(); - void Shutdown(); - void DeleteDataForOriginOnFileThread(const GURL& origin_url); // Quota related methods. @@ -47,16 +46,17 @@ class SandboxedFileSystemContext FileSystemPathManager* path_manager() { return path_manager_.get(); } FileSystemQuotaManager* quota_manager() { return quota_manager_.get(); } + FileSystemUsageTracker* usage_tracker() { return usage_tracker_.get(); } private: friend struct DefaultContextDeleter; void DeleteOnCorrectThread() const; - bool allow_file_access_from_files_; scoped_refptr<base::MessageLoopProxy> file_message_loop_; scoped_refptr<base::MessageLoopProxy> io_message_loop_; scoped_ptr<FileSystemPathManager> path_manager_; scoped_ptr<FileSystemQuotaManager> quota_manager_; + scoped_ptr<FileSystemUsageTracker> usage_tracker_; DISALLOW_IMPLICIT_CONSTRUCTORS(SandboxedFileSystemContext); }; diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi index f5f8675..c1beb11 100644 --- a/webkit/fileapi/webkit_fileapi.gypi +++ b/webkit/fileapi/webkit_fileapi.gypi @@ -26,6 +26,8 @@ 'file_system_types.h', 'file_system_url_request_job.cc', 'file_system_url_request_job.h', + 'file_system_usage_tracker.cc', + 'file_system_usage_tracker.h', 'file_system_util.cc', 'file_system_util.h', 'file_writer_delegate.cc', |