diff options
author | pilgrim <pilgrim@chromium.org> | 2014-09-05 10:30:15 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-05 17:32:24 +0000 |
commit | 4af8c2120e23d17c1cac3f929c3a1d901c5701ab (patch) | |
tree | 40e4ca0d45ec498ea74b9b4b232764abc1ec6ab1 /webkit | |
parent | a602902631a762be0b49ac0af09de0c9c840e183 (diff) | |
download | chromium_src-4af8c2120e23d17c1cac3f929c3a1d901c5701ab.zip chromium_src-4af8c2120e23d17c1cac3f929c3a1d901c5701ab.tar.gz chromium_src-4af8c2120e23d17c1cac3f929c3a1d901c5701ab.tar.bz2 |
Migrate webkit/browser/ to storage/browser/
using TBR because Darin told me he defers to James' judgement. Using NOTRY because there is one presubmit error (dump_file_system.cc was moved and it spews printf).
BUG=338338
TBR=darin@chromium.org
NOTRY=true
Review URL: https://codereview.chromium.org/539143002
Cr-Commit-Position: refs/heads/master@{#293547}
Diffstat (limited to 'webkit')
153 files changed, 156 insertions, 29680 deletions
diff --git a/webkit/browser/BUILD.gn b/webkit/browser/BUILD.gn deleted file mode 100644 index 0a74f5e..0000000 --- a/webkit/browser/BUILD.gn +++ /dev/null @@ -1,192 +0,0 @@ -# Copyright 2014 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. - -# GYP version: webkit/storage_browser.gyp:storage -component("storage") { - output_name = "storage" - sources = [ - "storage_browser_export.h", - "blob/blob_data_handle.cc", - "blob/blob_data_handle.h", - "blob/blob_storage_context.cc", - "blob/blob_storage_context.h", - "blob/blob_url_request_job.cc", - "blob/blob_url_request_job.h", - "blob/blob_url_request_job_factory.cc", - "blob/blob_url_request_job_factory.h", - "blob/file_stream_reader.cc", - "blob/file_stream_reader.h", - "blob/local_file_stream_reader.cc", - "blob/local_file_stream_reader.h", - "blob/view_blob_internals_job.cc", - "blob/view_blob_internals_job.h", - "database/database_quota_client.cc", - "database/database_quota_client.h", - "database/database_tracker.cc", - "database/database_tracker.h", - "database/database_util.cc", - "database/database_util.h", - "database/databases_table.cc", - "database/databases_table.h", - "database/vfs_backend.cc", - "database/vfs_backend.h", - "fileapi/async_file_util.h", - "fileapi/async_file_util_adapter.cc", - "fileapi/async_file_util_adapter.h", - "fileapi/copy_or_move_file_validator.h", - "fileapi/copy_or_move_operation_delegate.cc", - "fileapi/copy_or_move_operation_delegate.h", - "fileapi/dragged_file_util.cc", - "fileapi/dragged_file_util.h", - "fileapi/external_mount_points.cc", - "fileapi/external_mount_points.h", - "fileapi/file_observers.h", - "fileapi/file_permission_policy.h", - "fileapi/file_stream_writer.h", - "fileapi/file_system_backend.h", - "fileapi/file_system_context.cc", - "fileapi/file_system_context.h", - "fileapi/file_system_dir_url_request_job.cc", - "fileapi/file_system_dir_url_request_job.h", - "fileapi/file_system_file_stream_reader.cc", - "fileapi/file_system_file_stream_reader.h", - "fileapi/file_system_file_util.cc", - "fileapi/file_system_file_util.h", - "fileapi/file_system_operation.h", - "fileapi/file_system_operation_context.cc", - "fileapi/file_system_operation_context.h", - "fileapi/file_system_operation_impl.cc", - "fileapi/file_system_operation_impl.h", - "fileapi/file_system_operation_runner.cc", - "fileapi/file_system_operation_runner.h", - "fileapi/file_system_options.cc", - "fileapi/file_system_options.h", - "fileapi/file_system_quota_client.cc", - "fileapi/file_system_quota_client.h", - "fileapi/file_system_quota_util.h", - "fileapi/file_system_url.cc", - "fileapi/file_system_url.h", - "fileapi/file_system_url_request_job.cc", - "fileapi/file_system_url_request_job.h", - "fileapi/file_system_url_request_job_factory.cc", - "fileapi/file_system_url_request_job_factory.h", - "fileapi/file_system_usage_cache.cc", - "fileapi/file_system_usage_cache.h", - "fileapi/file_writer_delegate.cc", - "fileapi/file_writer_delegate.h", - "fileapi/isolated_context.cc", - "fileapi/isolated_context.h", - "fileapi/isolated_file_system_backend.cc", - "fileapi/isolated_file_system_backend.h", - "fileapi/local_file_stream_writer.cc", - "fileapi/local_file_stream_writer.h", - "fileapi/local_file_util.cc", - "fileapi/local_file_util.h", - "fileapi/mount_points.cc", - "fileapi/mount_points.h", - "fileapi/native_file_util.cc", - "fileapi/native_file_util.h", - "fileapi/obfuscated_file_util.cc", - "fileapi/obfuscated_file_util.h", - "fileapi/open_file_system_mode.h", - "fileapi/plugin_private_file_system_backend.cc", - "fileapi/plugin_private_file_system_backend.h", - "fileapi/quota/open_file_handle.cc", - "fileapi/quota/open_file_handle.h", - "fileapi/quota/open_file_handle_context.cc", - "fileapi/quota/open_file_handle_context.h", - "fileapi/quota/quota_backend_impl.cc", - "fileapi/quota/quota_backend_impl.h", - "fileapi/quota/quota_reservation.cc", - "fileapi/quota/quota_reservation.h", - "fileapi/quota/quota_reservation_buffer.cc", - "fileapi/quota/quota_reservation_buffer.h", - "fileapi/quota/quota_reservation_manager.cc", - "fileapi/quota/quota_reservation_manager.h", - "fileapi/recursive_operation_delegate.cc", - "fileapi/recursive_operation_delegate.h", - "fileapi/remove_operation_delegate.cc", - "fileapi/remove_operation_delegate.h", - "fileapi/sandbox_directory_database.cc", - "fileapi/sandbox_directory_database.h", - "fileapi/sandbox_file_stream_writer.cc", - "fileapi/sandbox_file_stream_writer.h", - "fileapi/sandbox_file_system_backend.cc", - "fileapi/sandbox_file_system_backend.h", - "fileapi/sandbox_file_system_backend_delegate.cc", - "fileapi/sandbox_file_system_backend_delegate.h", - "fileapi/sandbox_isolated_origin_database.cc", - "fileapi/sandbox_isolated_origin_database.h", - "fileapi/sandbox_origin_database.cc", - "fileapi/sandbox_origin_database.h", - "fileapi/sandbox_origin_database_interface.cc", - "fileapi/sandbox_origin_database_interface.h", - "fileapi/sandbox_prioritized_origin_database.cc", - "fileapi/sandbox_prioritized_origin_database.h", - "fileapi/sandbox_quota_observer.cc", - "fileapi/sandbox_quota_observer.h", - "fileapi/task_runner_bound_observer_list.h", - "fileapi/timed_task_helper.cc", - "fileapi/timed_task_helper.h", - "fileapi/transient_file_util.cc", - "fileapi/transient_file_util.h", - "quota/quota_callbacks.h", - "quota/quota_client.h", - "quota/quota_database.cc", - "quota/quota_database.h", - "quota/quota_manager.cc", - "quota/quota_manager.h", - "quota/quota_manager_proxy.cc", - "quota/quota_manager_proxy.h", - "quota/quota_task.cc", - "quota/quota_task.h", - "quota/quota_temporary_storage_evictor.cc", - "quota/quota_temporary_storage_evictor.h", - "quota/special_storage_policy.cc", - "quota/special_storage_policy.h", - "quota/storage_monitor.cc", - "quota/storage_monitor.h", - "quota/storage_observer.cc", - "quota/storage_observer.h", - "quota/usage_tracker.cc", - "quota/usage_tracker.h", - ] - - defines = [ "STORAGE_BROWSER_IMPLEMENTATION" ] - configs += [ "//build/config/compiler:wexit_time_destructors" ] - if (is_win) { - cflags = [ "/wd4267" ] # TODO(jschuh): fix size_t to int truncations. - } - - deps = [ - "//base", - "//base:i18n", - "//base/third_party/dynamic_annotations", - "//net", - "//sql", - "//storage/common", - "//third_party/leveldatabase", - "//third_party/sqlite", - "//url", - ] - - # TODO(GYP) support chrome_multiple_dll - #['chrome_multiple_dll!=1', { - # 'dependencies': [ - # '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink', - # ], - #}], -} - -executable("dump_file_system") { - sources = [ - "fileapi/dump_file_system.cc", - ] - - deps = [ - ":storage", - "//base", - "//storage/common", - ] -} diff --git a/webkit/browser/DEPS b/webkit/browser/DEPS deleted file mode 100644 index 62bbdd0..0000000 --- a/webkit/browser/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "-webkit/renderer", -] diff --git a/webkit/browser/blob/OWNERS b/webkit/browser/blob/OWNERS deleted file mode 100644 index c7e8dcb..0000000 --- a/webkit/browser/blob/OWNERS +++ /dev/null @@ -1 +0,0 @@ -jianli@chromium.org diff --git a/webkit/browser/blob/blob_data_handle.cc b/webkit/browser/blob/blob_data_handle.cc deleted file mode 100644 index 667228a..0000000 --- a/webkit/browser/blob/blob_data_handle.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2013 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/browser/blob/blob_data_handle.h" - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/sequenced_task_runner.h" -#include "webkit/browser/blob/blob_storage_context.h" -#include "webkit/common/blob/blob_data.h" - -namespace storage { - -BlobDataHandle::BlobDataHandleShared::BlobDataHandleShared( - BlobData* blob_data, - BlobStorageContext* context, - base::SequencedTaskRunner* task_runner) - : blob_data_(blob_data), - context_(context->AsWeakPtr()) { - context_->IncrementBlobRefCount(blob_data->uuid()); -} - -BlobData* BlobDataHandle::BlobDataHandleShared::data() const { - return blob_data_.get(); -} - -const std::string& BlobDataHandle::BlobDataHandleShared::uuid() const { - return blob_data_->uuid(); -} - -BlobDataHandle::BlobDataHandleShared::~BlobDataHandleShared() { - if (context_.get()) - context_->DecrementBlobRefCount(blob_data_->uuid()); -} - -BlobDataHandle::BlobDataHandle(BlobData* blob_data, - BlobStorageContext* context, - base::SequencedTaskRunner* task_runner) - : io_task_runner_(task_runner), - shared_(new BlobDataHandleShared(blob_data, context, task_runner)) { - DCHECK(io_task_runner_.get()); - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); -} - -BlobDataHandle::BlobDataHandle(const BlobDataHandle& other) { - io_task_runner_ = other.io_task_runner_; - shared_ = other.shared_; -} - -BlobDataHandle::~BlobDataHandle() { - BlobDataHandleShared* raw = shared_.get(); - raw->AddRef(); - shared_ = 0; - io_task_runner_->ReleaseSoon(FROM_HERE, raw); -} - -BlobData* BlobDataHandle::data() const { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - return shared_->data(); -} - -std::string BlobDataHandle::uuid() const { - return shared_->uuid(); -} - -} // namespace storage diff --git a/webkit/browser/blob/blob_data_handle.h b/webkit/browser/blob/blob_data_handle.h index cb1e365..6e06b88 100644 --- a/webkit/browser/blob/blob_data_handle.h +++ b/webkit/browser/blob/blob_data_handle.h @@ -1,71 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_BLOB_BLOB_DATA_HANDLE_H_ -#define WEBKIT_BROWSER_BLOB_BLOB_DATA_HANDLE_H_ - -#include <string> - -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/supports_user_data.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class SequencedTaskRunner; -} - -namespace storage { - -class BlobData; -class BlobStorageContext; - -// A scoper object for use in chrome's main browser process, ensures -// the underlying BlobData and its uuid remain in BlobStorageContext's -// collection for the duration. This object has delete semantics and -// maybe deleted on any thread. -class STORAGE_EXPORT BlobDataHandle - : public base::SupportsUserData::Data { - public: - BlobDataHandle(const BlobDataHandle& other); // May be copied on any thread. - virtual ~BlobDataHandle(); // Maybe be deleted on any thread. - BlobData* data() const; // May only be accessed on the IO thread. - - std::string uuid() const; // May be accessed on any thread. - - private: - class BlobDataHandleShared - : public base::RefCountedThreadSafe<BlobDataHandleShared> { - public: - BlobDataHandleShared(BlobData* blob_data, - BlobStorageContext* context, - base::SequencedTaskRunner* task_runner); - - BlobData* data() const; - const std::string& uuid() const; - - private: - friend class base::DeleteHelper<BlobDataHandleShared>; - friend class base::RefCountedThreadSafe<BlobDataHandleShared>; - friend class BlobDataHandle; - - virtual ~BlobDataHandleShared(); - - scoped_refptr<BlobData> blob_data_; - base::WeakPtr<BlobStorageContext> context_; - - DISALLOW_COPY_AND_ASSIGN(BlobDataHandleShared); - }; - - friend class BlobStorageContext; - BlobDataHandle(BlobData* blob_data, BlobStorageContext* context, - base::SequencedTaskRunner* task_runner); - - scoped_refptr<base::SequencedTaskRunner> io_task_runner_; - scoped_refptr<BlobDataHandleShared> shared_; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_BLOB_BLOB_DATA_HANDLE_H_ +#include "storage/browser/blob/blob_data_handle.h" diff --git a/webkit/browser/blob/blob_storage_context.cc b/webkit/browser/blob/blob_storage_context.cc deleted file mode 100644 index 9c5f9bc..0000000 --- a/webkit/browser/blob/blob_storage_context.cc +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright (c) 2013 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/browser/blob/blob_storage_context.h" - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/message_loop/message_loop_proxy.h" -#include "url/gurl.h" -#include "webkit/browser/blob/blob_data_handle.h" -#include "webkit/common/blob/blob_data.h" - -namespace storage { - -namespace { - -// We can't use GURL directly for these hash fragment manipulations -// since it doesn't have specific knowlege of the BlobURL format. GURL -// treats BlobURLs as if they were PathURLs which don't support hash -// fragments. - -bool BlobUrlHasRef(const GURL& url) { - return url.spec().find('#') != std::string::npos; -} - -GURL ClearBlobUrlRef(const GURL& url) { - size_t hash_pos = url.spec().find('#'); - if (hash_pos == std::string::npos) - return url; - return GURL(url.spec().substr(0, hash_pos)); -} - -// TODO(michaeln): use base::SysInfo::AmountOfPhysicalMemoryMB() in some -// way to come up with a better limit. -static const int64 kMaxMemoryUsage = 500 * 1024 * 1024; // Half a gig. - -} // namespace - -BlobStorageContext::BlobMapEntry::BlobMapEntry() - : refcount(0), flags(0) { -} - -BlobStorageContext::BlobMapEntry::BlobMapEntry( - int refcount, int flags, BlobData* data) - : refcount(refcount), flags(flags), data(data) { -} - -BlobStorageContext::BlobMapEntry::~BlobMapEntry() { -} - -BlobStorageContext::BlobStorageContext() - : memory_usage_(0) { -} - -BlobStorageContext::~BlobStorageContext() { -} - -scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID( - const std::string& uuid) { - scoped_ptr<BlobDataHandle> result; - BlobMap::iterator found = blob_map_.find(uuid); - if (found == blob_map_.end()) - return result.Pass(); - if (found->second.flags & EXCEEDED_MEMORY) - return result.Pass(); - DCHECK(!(found->second.flags & BEING_BUILT)); - result.reset(new BlobDataHandle( - found->second.data.get(), this, base::MessageLoopProxy::current().get())); - return result.Pass(); -} - -scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromPublicURL( - const GURL& url) { - BlobURLMap::iterator found = public_blob_urls_.find( - BlobUrlHasRef(url) ? ClearBlobUrlRef(url) : url); - if (found == public_blob_urls_.end()) - return scoped_ptr<BlobDataHandle>(); - return GetBlobDataFromUUID(found->second); -} - -scoped_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob( - const BlobData* data) { - StartBuildingBlob(data->uuid()); - for (std::vector<BlobData::Item>::const_iterator iter = - data->items().begin(); - iter != data->items().end(); ++iter) { - AppendBlobDataItem(data->uuid(), *iter); - } - FinishBuildingBlob(data->uuid(), data->content_type()); - scoped_ptr<BlobDataHandle> handle = GetBlobDataFromUUID(data->uuid()); - DecrementBlobRefCount(data->uuid()); - return handle.Pass(); -} - -bool BlobStorageContext::RegisterPublicBlobURL( - const GURL& blob_url, const std::string& uuid) { - DCHECK(!BlobUrlHasRef(blob_url)); - DCHECK(IsInUse(uuid)); - DCHECK(!IsUrlRegistered(blob_url)); - if (!IsInUse(uuid) || IsUrlRegistered(blob_url)) - return false; - IncrementBlobRefCount(uuid); - public_blob_urls_[blob_url] = uuid; - return true; -} - -void BlobStorageContext::RevokePublicBlobURL(const GURL& blob_url) { - DCHECK(!BlobUrlHasRef(blob_url)); - if (!IsUrlRegistered(blob_url)) - return; - DecrementBlobRefCount(public_blob_urls_[blob_url]); - public_blob_urls_.erase(blob_url); -} - -void BlobStorageContext::StartBuildingBlob(const std::string& uuid) { - DCHECK(!IsInUse(uuid) && !uuid.empty()); - blob_map_[uuid] = BlobMapEntry(1, BEING_BUILT, new BlobData(uuid)); -} - -void BlobStorageContext::AppendBlobDataItem( - const std::string& uuid, const BlobData::Item& item) { - DCHECK(IsBeingBuilt(uuid)); - BlobMap::iterator found = blob_map_.find(uuid); - if (found == blob_map_.end()) - return; - if (found->second.flags & EXCEEDED_MEMORY) - return; - BlobData* target_blob_data = found->second.data.get(); - DCHECK(target_blob_data); - - bool exceeded_memory = false; - - // The blob data is stored in the canonical way which only contains a - // list of Data, File, and FileSystem items. Aggregated TYPE_BLOB items - // are expanded into the primitive constituent types. - // 1) The Data item is denoted by the raw data and length. - // 2) The File item is denoted by the file path, the range and the expected - // modification time. - // 3) The FileSystem File item is denoted by the FileSystem URL, the range - // and the expected modification time. - // 4) The Blob items are expanded. - // TODO(michaeln): Would be nice to avoid copying Data items when expanding. - - DCHECK(item.length() > 0); - switch (item.type()) { - case BlobData::Item::TYPE_BYTES: - DCHECK(!item.offset()); - exceeded_memory = !AppendBytesItem(target_blob_data, - item.bytes(), - static_cast<int64>(item.length())); - break; - case BlobData::Item::TYPE_FILE: - AppendFileItem(target_blob_data, - item.path(), - item.offset(), - item.length(), - item.expected_modification_time()); - break; - case BlobData::Item::TYPE_FILE_FILESYSTEM: - AppendFileSystemFileItem(target_blob_data, - item.filesystem_url(), - item.offset(), - item.length(), - item.expected_modification_time()); - break; - case BlobData::Item::TYPE_BLOB: { - scoped_ptr<BlobDataHandle> src = GetBlobDataFromUUID(item.blob_uuid()); - if (src) - exceeded_memory = !ExpandStorageItems(target_blob_data, - src->data(), - item.offset(), - item.length()); - break; - } - default: - NOTREACHED(); - break; - } - - // If we're using too much memory, drop this blob's data. - // TODO(michaeln): Blob memory storage does not yet spill over to disk, - // as a stop gap, we'll prevent memory usage over a max amount. - if (exceeded_memory) { - memory_usage_ -= target_blob_data->GetMemoryUsage(); - found->second.flags |= EXCEEDED_MEMORY; - found->second.data = new BlobData(uuid); - return; - } -} - -void BlobStorageContext::FinishBuildingBlob( - const std::string& uuid, const std::string& content_type) { - DCHECK(IsBeingBuilt(uuid)); - BlobMap::iterator found = blob_map_.find(uuid); - if (found == blob_map_.end()) - return; - found->second.data->set_content_type(content_type); - found->second.flags &= ~BEING_BUILT; -} - -void BlobStorageContext::CancelBuildingBlob(const std::string& uuid) { - DCHECK(IsBeingBuilt(uuid)); - DecrementBlobRefCount(uuid); -} - -void BlobStorageContext::IncrementBlobRefCount(const std::string& uuid) { - BlobMap::iterator found = blob_map_.find(uuid); - if (found == blob_map_.end()) { - DCHECK(false); - return; - } - ++(found->second.refcount); -} - -void BlobStorageContext::DecrementBlobRefCount(const std::string& uuid) { - BlobMap::iterator found = blob_map_.find(uuid); - if (found == blob_map_.end()) - return; - DCHECK_EQ(found->second.data->uuid(), uuid); - if (--(found->second.refcount) == 0) { - memory_usage_ -= found->second.data->GetMemoryUsage(); - blob_map_.erase(found); - } -} - -bool BlobStorageContext::ExpandStorageItems( - BlobData* target_blob_data, BlobData* src_blob_data, - uint64 offset, uint64 length) { - DCHECK(target_blob_data && src_blob_data && - length != static_cast<uint64>(-1)); - - std::vector<BlobData::Item>::const_iterator iter = - src_blob_data->items().begin(); - if (offset) { - for (; iter != src_blob_data->items().end(); ++iter) { - if (offset >= iter->length()) - offset -= iter->length(); - else - break; - } - } - - for (; iter != src_blob_data->items().end() && length > 0; ++iter) { - uint64 current_length = iter->length() - offset; - uint64 new_length = current_length > length ? length : current_length; - if (iter->type() == BlobData::Item::TYPE_BYTES) { - if (!AppendBytesItem( - target_blob_data, - iter->bytes() + static_cast<size_t>(iter->offset() + offset), - static_cast<int64>(new_length))) { - return false; // exceeded memory - } - } else if (iter->type() == BlobData::Item::TYPE_FILE) { - AppendFileItem(target_blob_data, - iter->path(), - iter->offset() + offset, - new_length, - iter->expected_modification_time()); - } else { - DCHECK(iter->type() == BlobData::Item::TYPE_FILE_FILESYSTEM); - AppendFileSystemFileItem(target_blob_data, - iter->filesystem_url(), - iter->offset() + offset, - new_length, - iter->expected_modification_time()); - } - length -= new_length; - offset = 0; - } - return true; -} - -bool BlobStorageContext::AppendBytesItem( - BlobData* target_blob_data, const char* bytes, int64 length) { - if (length < 0) { - DCHECK(false); - return false; - } - if (memory_usage_ + length > kMaxMemoryUsage) - return false; - target_blob_data->AppendData(bytes, static_cast<size_t>(length)); - memory_usage_ += length; - return true; -} - -void BlobStorageContext::AppendFileItem( - BlobData* target_blob_data, - const base::FilePath& file_path, uint64 offset, uint64 length, - const base::Time& expected_modification_time) { - target_blob_data->AppendFile(file_path, offset, length, - expected_modification_time); - - // It may be a temporary file that should be deleted when no longer needed. - scoped_refptr<ShareableFileReference> shareable_file = - ShareableFileReference::Get(file_path); - if (shareable_file.get()) - target_blob_data->AttachShareableFileReference(shareable_file.get()); -} - -void BlobStorageContext::AppendFileSystemFileItem( - BlobData* target_blob_data, - const GURL& filesystem_url, uint64 offset, uint64 length, - const base::Time& expected_modification_time) { - target_blob_data->AppendFileSystemFile(filesystem_url, offset, length, - expected_modification_time); -} - -bool BlobStorageContext::IsInUse(const std::string& uuid) { - return blob_map_.find(uuid) != blob_map_.end(); -} - -bool BlobStorageContext::IsBeingBuilt(const std::string& uuid) { - BlobMap::iterator found = blob_map_.find(uuid); - if (found == blob_map_.end()) - return false; - return found->second.flags & BEING_BUILT; -} - -bool BlobStorageContext::IsUrlRegistered(const GURL& blob_url) { - return public_blob_urls_.find(blob_url) != public_blob_urls_.end(); -} - -} // namespace storage diff --git a/webkit/browser/blob/blob_storage_context.h b/webkit/browser/blob/blob_storage_context.h index 32b7ea0..1a34b70 100644 --- a/webkit/browser/blob/blob_storage_context.h +++ b/webkit/browser/blob/blob_storage_context.h @@ -1,118 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_BLOB_BLOB_STORAGE_CONTEXT_H_ -#define WEBKIT_BROWSER_BLOB_BLOB_STORAGE_CONTEXT_H_ - -#include <map> -#include <string> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "webkit/browser/blob/blob_data_handle.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/blob/blob_data.h" - -class GURL; - -namespace base { -class FilePath; -class Time; -} - -namespace content { -class BlobStorageHost; -} - -namespace storage { - -class BlobDataHandle; - -// This class handles the logistics of blob Storage within the browser process, -// and maintains a mapping from blob uuid to the data. The class is single -// threaded and should only be used on the IO thread. -// In chromium, there is one instance per profile. -class STORAGE_EXPORT BlobStorageContext - : public base::SupportsWeakPtr<BlobStorageContext> { - public: - BlobStorageContext(); - ~BlobStorageContext(); - - scoped_ptr<BlobDataHandle> GetBlobDataFromUUID(const std::string& uuid); - scoped_ptr<BlobDataHandle> GetBlobDataFromPublicURL(const GURL& url); - - // Useful for coining blobs from within the browser process. If the - // blob cannot be added due to memory consumption, returns NULL. - scoped_ptr<BlobDataHandle> AddFinishedBlob(const BlobData* blob_data); - - // Useful for coining blob urls from within the browser process. - bool RegisterPublicBlobURL(const GURL& url, const std::string& uuid); - void RevokePublicBlobURL(const GURL& url); - - private: - friend class content::BlobStorageHost; - friend class BlobDataHandle::BlobDataHandleShared; - friend class ViewBlobInternalsJob; - - enum EntryFlags { - BEING_BUILT = 1 << 0, - EXCEEDED_MEMORY = 1 << 1, - }; - - struct BlobMapEntry { - int refcount; - int flags; - scoped_refptr<BlobData> data; - - BlobMapEntry(); - BlobMapEntry(int refcount, int flags, BlobData* data); - ~BlobMapEntry(); - }; - - typedef std::map<std::string, BlobMapEntry> - BlobMap; - typedef std::map<GURL, std::string> BlobURLMap; - - void StartBuildingBlob(const std::string& uuid); - void AppendBlobDataItem(const std::string& uuid, - const BlobData::Item& data_item); - void FinishBuildingBlob(const std::string& uuid, const std::string& type); - void CancelBuildingBlob(const std::string& uuid); - void IncrementBlobRefCount(const std::string& uuid); - void DecrementBlobRefCount(const std::string& uuid); - - bool ExpandStorageItems(BlobData* target_blob_data, - BlobData* src_blob_data, - uint64 offset, - uint64 length); - bool AppendBytesItem(BlobData* target_blob_data, - const char* data, int64 length); - void AppendFileItem(BlobData* target_blob_data, - const base::FilePath& file_path, - uint64 offset, uint64 length, - const base::Time& expected_modification_time); - void AppendFileSystemFileItem( - BlobData* target_blob_data, - const GURL& url, uint64 offset, uint64 length, - const base::Time& expected_modification_time); - - bool IsInUse(const std::string& uuid); - bool IsBeingBuilt(const std::string& uuid); - bool IsUrlRegistered(const GURL& blob_url); - - BlobMap blob_map_; - BlobURLMap public_blob_urls_; - - // Used to keep track of how much memory is being utilized for blob data, - // we count only the items of TYPE_DATA which are held in memory and not - // items of TYPE_FILE. - int64 memory_usage_; - - DISALLOW_COPY_AND_ASSIGN(BlobStorageContext); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_BLOB_BLOB_STORAGE_CONTEXT_H_ +#include "storage/browser/blob/blob_storage_context.h" diff --git a/webkit/browser/blob/blob_url_request_job.cc b/webkit/browser/blob/blob_url_request_job.cc deleted file mode 100644 index 9eb196a..0000000 --- a/webkit/browser/blob/blob_url_request_job.cc +++ /dev/null @@ -1,590 +0,0 @@ -// Copyright (c) 2012 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/browser/blob/blob_url_request_job.h" - -#include <limits> - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/files/file_util_proxy.h" -#include "base/format_macros.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/http/http_request_headers.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_response_info.h" -#include "net/http/http_util.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_error_job.h" -#include "net/url_request/url_request_status.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_url.h" - -namespace storage { - -namespace { - -bool IsFileType(BlobData::Item::Type type) { - switch (type) { - case BlobData::Item::TYPE_FILE: - case BlobData::Item::TYPE_FILE_FILESYSTEM: - return true; - default: - return false; - } -} - -} // namespace - -BlobURLRequestJob::BlobURLRequestJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const scoped_refptr<BlobData>& blob_data, - storage::FileSystemContext* file_system_context, - base::MessageLoopProxy* file_thread_proxy) - : net::URLRequestJob(request, network_delegate), - blob_data_(blob_data), - file_system_context_(file_system_context), - file_thread_proxy_(file_thread_proxy), - total_size_(0), - remaining_bytes_(0), - pending_get_file_info_count_(0), - current_item_index_(0), - current_item_offset_(0), - error_(false), - byte_range_set_(false), - weak_factory_(this) { - DCHECK(file_thread_proxy_.get()); -} - -void BlobURLRequestJob::Start() { - // Continue asynchronously. - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&BlobURLRequestJob::DidStart, weak_factory_.GetWeakPtr())); -} - -void BlobURLRequestJob::Kill() { - DeleteCurrentFileReader(); - - net::URLRequestJob::Kill(); - weak_factory_.InvalidateWeakPtrs(); -} - -bool BlobURLRequestJob::ReadRawData(net::IOBuffer* dest, - int dest_size, - int* bytes_read) { - DCHECK_NE(dest_size, 0); - DCHECK(bytes_read); - DCHECK_GE(remaining_bytes_, 0); - - // Bail out immediately if we encounter an error. - if (error_) { - *bytes_read = 0; - return true; - } - - if (remaining_bytes_ < dest_size) - dest_size = static_cast<int>(remaining_bytes_); - - // If we should copy zero bytes because |remaining_bytes_| is zero, short - // circuit here. - if (!dest_size) { - *bytes_read = 0; - return true; - } - - // Keep track of the buffer. - DCHECK(!read_buf_.get()); - read_buf_ = new net::DrainableIOBuffer(dest, dest_size); - - return ReadLoop(bytes_read); -} - -bool BlobURLRequestJob::GetMimeType(std::string* mime_type) const { - if (!response_info_) - return false; - - return response_info_->headers->GetMimeType(mime_type); -} - -void BlobURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { - if (response_info_) - *info = *response_info_; -} - -int BlobURLRequestJob::GetResponseCode() const { - if (!response_info_) - return -1; - - return response_info_->headers->response_code(); -} - -void BlobURLRequestJob::SetExtraRequestHeaders( - const net::HttpRequestHeaders& headers) { - std::string range_header; - if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { - // We only care about "Range" header here. - std::vector<net::HttpByteRange> ranges; - if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { - if (ranges.size() == 1) { - byte_range_set_ = true; - byte_range_ = ranges[0]; - } else { - // We don't support multiple range requests in one single URL request, - // because we need to do multipart encoding here. - // TODO(jianli): Support multipart byte range requests. - NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); - } - } - } -} - -BlobURLRequestJob::~BlobURLRequestJob() { - STLDeleteValues(&index_to_reader_); -} - -void BlobURLRequestJob::DidStart() { - error_ = false; - - // We only support GET request per the spec. - if (request()->method() != "GET") { - NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); - return; - } - - // If the blob data is not present, bail out. - if (!blob_data_.get()) { - NotifyFailure(net::ERR_FILE_NOT_FOUND); - return; - } - - CountSize(); -} - -bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) { - if (item_length > kint64max - total_size_) { - NotifyFailure(net::ERR_FAILED); - return false; - } - - // Cache the size and add it to the total size. - DCHECK_LT(index, item_length_list_.size()); - item_length_list_[index] = item_length; - total_size_ += item_length; - return true; -} - -void BlobURLRequestJob::CountSize() { - pending_get_file_info_count_ = 0; - total_size_ = 0; - item_length_list_.resize(blob_data_->items().size()); - - for (size_t i = 0; i < blob_data_->items().size(); ++i) { - const BlobData::Item& item = blob_data_->items().at(i); - if (IsFileType(item.type())) { - ++pending_get_file_info_count_; - GetFileStreamReader(i)->GetLength( - base::Bind(&BlobURLRequestJob::DidGetFileItemLength, - weak_factory_.GetWeakPtr(), i)); - continue; - } - - if (!AddItemLength(i, item.length())) - return; - } - - if (pending_get_file_info_count_ == 0) - DidCountSize(net::OK); -} - -void BlobURLRequestJob::DidCountSize(int error) { - DCHECK(!error_); - - // If an error occured, bail out. - if (error != net::OK) { - NotifyFailure(error); - return; - } - - // Apply the range requirement. - if (!byte_range_.ComputeBounds(total_size_)) { - NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); - return; - } - - remaining_bytes_ = byte_range_.last_byte_position() - - byte_range_.first_byte_position() + 1; - DCHECK_GE(remaining_bytes_, 0); - - // Do the seek at the beginning of the request. - if (byte_range_.first_byte_position()) - Seek(byte_range_.first_byte_position()); - - NotifySuccess(); -} - -void BlobURLRequestJob::DidGetFileItemLength(size_t index, int64 result) { - // Do nothing if we have encountered an error. - if (error_) - return; - - if (result == net::ERR_UPLOAD_FILE_CHANGED) { - NotifyFailure(net::ERR_FILE_NOT_FOUND); - return; - } else if (result < 0) { - NotifyFailure(result); - return; - } - - DCHECK_LT(index, blob_data_->items().size()); - const BlobData::Item& item = blob_data_->items().at(index); - DCHECK(IsFileType(item.type())); - - uint64 file_length = result; - uint64 item_offset = item.offset(); - uint64 item_length = item.length(); - - if (item_offset > file_length) { - NotifyFailure(net::ERR_FILE_NOT_FOUND); - return; - } - - uint64 max_length = file_length - item_offset; - - // If item length is -1, we need to use the file size being resolved - // in the real time. - if (item_length == static_cast<uint64>(-1)) { - item_length = max_length; - } else if (item_length > max_length) { - NotifyFailure(net::ERR_FILE_NOT_FOUND); - return; - } - - if (!AddItemLength(index, item_length)) - return; - - if (--pending_get_file_info_count_ == 0) - DidCountSize(net::OK); -} - -void BlobURLRequestJob::Seek(int64 offset) { - // Skip the initial items that are not in the range. - for (current_item_index_ = 0; - current_item_index_ < blob_data_->items().size() && - offset >= item_length_list_[current_item_index_]; - ++current_item_index_) { - offset -= item_length_list_[current_item_index_]; - } - - // Set the offset that need to jump to for the first item in the range. - current_item_offset_ = offset; - - if (offset == 0) - return; - - // Adjust the offset of the first stream if it is of file type. - const BlobData::Item& item = blob_data_->items().at(current_item_index_); - if (IsFileType(item.type())) { - DeleteCurrentFileReader(); - CreateFileStreamReader(current_item_index_, offset); - } -} - -bool BlobURLRequestJob::ReadItem() { - // Are we done with reading all the blob data? - if (remaining_bytes_ == 0) - return true; - - // If we get to the last item but still expect something to read, bail out - // since something is wrong. - if (current_item_index_ >= blob_data_->items().size()) { - NotifyFailure(net::ERR_FAILED); - return false; - } - - // Compute the bytes to read for current item. - int bytes_to_read = ComputeBytesToRead(); - - // If nothing to read for current item, advance to next item. - if (bytes_to_read == 0) { - AdvanceItem(); - return ReadItem(); - } - - // Do the reading. - const BlobData::Item& item = blob_data_->items().at(current_item_index_); - if (item.type() == BlobData::Item::TYPE_BYTES) - return ReadBytesItem(item, bytes_to_read); - if (IsFileType(item.type())) { - return ReadFileItem(GetFileStreamReader(current_item_index_), - bytes_to_read); - } - NOTREACHED(); - return false; -} - -void BlobURLRequestJob::AdvanceItem() { - // Close the file if the current item is a file. - DeleteCurrentFileReader(); - - // Advance to the next item. - current_item_index_++; - current_item_offset_ = 0; -} - -void BlobURLRequestJob::AdvanceBytesRead(int result) { - DCHECK_GT(result, 0); - - // Do we finish reading the current item? - current_item_offset_ += result; - if (current_item_offset_ == item_length_list_[current_item_index_]) - AdvanceItem(); - - // Subtract the remaining bytes. - remaining_bytes_ -= result; - DCHECK_GE(remaining_bytes_, 0); - - // Adjust the read buffer. - read_buf_->DidConsume(result); - DCHECK_GE(read_buf_->BytesRemaining(), 0); -} - -bool BlobURLRequestJob::ReadBytesItem(const BlobData::Item& item, - int bytes_to_read) { - DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); - - memcpy(read_buf_->data(), - item.bytes() + item.offset() + current_item_offset_, - bytes_to_read); - - AdvanceBytesRead(bytes_to_read); - return true; -} - -bool BlobURLRequestJob::ReadFileItem(FileStreamReader* reader, - int bytes_to_read) { - DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); - DCHECK(reader); - const int result = reader->Read( - read_buf_.get(), - bytes_to_read, - base::Bind(&BlobURLRequestJob::DidReadFile, base::Unretained(this))); - if (result >= 0) { - // Data is immediately available. - if (GetStatus().is_io_pending()) - DidReadFile(result); - else - AdvanceBytesRead(result); - return true; - } - if (result == net::ERR_IO_PENDING) - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - else - NotifyFailure(result); - return false; -} - -void BlobURLRequestJob::DidReadFile(int result) { - if (result <= 0) { - NotifyFailure(net::ERR_FAILED); - return; - } - SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status - - AdvanceBytesRead(result); - - // If the read buffer is completely filled, we're done. - if (!read_buf_->BytesRemaining()) { - int bytes_read = BytesReadCompleted(); - NotifyReadComplete(bytes_read); - return; - } - - // Otherwise, continue the reading. - int bytes_read = 0; - if (ReadLoop(&bytes_read)) - NotifyReadComplete(bytes_read); -} - -void BlobURLRequestJob::DeleteCurrentFileReader() { - IndexToReaderMap::iterator found = index_to_reader_.find(current_item_index_); - if (found != index_to_reader_.end() && found->second) { - delete found->second; - index_to_reader_.erase(found); - } -} - -int BlobURLRequestJob::BytesReadCompleted() { - int bytes_read = read_buf_->BytesConsumed(); - read_buf_ = NULL; - return bytes_read; -} - -int BlobURLRequestJob::ComputeBytesToRead() const { - int64 current_item_length = item_length_list_[current_item_index_]; - - int64 item_remaining = current_item_length - current_item_offset_; - int64 buf_remaining = read_buf_->BytesRemaining(); - int64 max_remaining = std::numeric_limits<int>::max(); - - int64 min = std::min(std::min(std::min(item_remaining, - buf_remaining), - remaining_bytes_), - max_remaining); - - return static_cast<int>(min); -} - -bool BlobURLRequestJob::ReadLoop(int* bytes_read) { - // Read until we encounter an error or could not get the data immediately. - while (remaining_bytes_ > 0 && read_buf_->BytesRemaining() > 0) { - if (!ReadItem()) - return false; - } - - *bytes_read = BytesReadCompleted(); - return true; -} - -void BlobURLRequestJob::NotifySuccess() { - net::HttpStatusCode status_code = net::HTTP_OK; - if (byte_range_set_ && byte_range_.IsValid()) - status_code = net::HTTP_PARTIAL_CONTENT; - HeadersCompleted(status_code); -} - -void BlobURLRequestJob::NotifyFailure(int error_code) { - error_ = true; - - // If we already return the headers on success, we can't change the headers - // now. Instead, we just error out. - if (response_info_) { - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, - error_code)); - return; - } - - net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR; - switch (error_code) { - case net::ERR_ACCESS_DENIED: - status_code = net::HTTP_FORBIDDEN; - break; - case net::ERR_FILE_NOT_FOUND: - status_code = net::HTTP_NOT_FOUND; - break; - case net::ERR_METHOD_NOT_SUPPORTED: - status_code = net::HTTP_METHOD_NOT_ALLOWED; - break; - case net::ERR_REQUEST_RANGE_NOT_SATISFIABLE: - status_code = net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE; - break; - case net::ERR_FAILED: - break; - default: - DCHECK(false); - break; - } - HeadersCompleted(status_code); -} - -void BlobURLRequestJob::HeadersCompleted(net::HttpStatusCode status_code) { - std::string status("HTTP/1.1 "); - status.append(base::IntToString(status_code)); - status.append(" "); - status.append(net::GetHttpReasonPhrase(status_code)); - status.append("\0\0", 2); - net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); - - if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT) { - std::string content_length_header(net::HttpRequestHeaders::kContentLength); - content_length_header.append(": "); - content_length_header.append(base::Int64ToString(remaining_bytes_)); - headers->AddHeader(content_length_header); - if (status_code == net::HTTP_PARTIAL_CONTENT) { - DCHECK(byte_range_set_); - DCHECK(byte_range_.IsValid()); - std::string content_range_header(net::HttpResponseHeaders::kContentRange); - content_range_header.append(": bytes "); - content_range_header.append(base::StringPrintf( - "%" PRId64 "-%" PRId64, - byte_range_.first_byte_position(), byte_range_.last_byte_position())); - content_range_header.append("/"); - content_range_header.append(base::StringPrintf("%" PRId64, total_size_)); - headers->AddHeader(content_range_header); - } - if (!blob_data_->content_type().empty()) { - std::string content_type_header(net::HttpRequestHeaders::kContentType); - content_type_header.append(": "); - content_type_header.append(blob_data_->content_type()); - headers->AddHeader(content_type_header); - } - if (!blob_data_->content_disposition().empty()) { - std::string content_disposition_header("Content-Disposition: "); - content_disposition_header.append(blob_data_->content_disposition()); - headers->AddHeader(content_disposition_header); - } - } - - response_info_.reset(new net::HttpResponseInfo()); - response_info_->headers = headers; - - set_expected_content_size(remaining_bytes_); - - NotifyHeadersComplete(); -} - -FileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) { - DCHECK_LT(index, blob_data_->items().size()); - const BlobData::Item& item = blob_data_->items().at(index); - if (!IsFileType(item.type())) - return NULL; - if (index_to_reader_.find(index) == index_to_reader_.end()) - CreateFileStreamReader(index, 0); - DCHECK(index_to_reader_[index]); - return index_to_reader_[index]; -} - -void BlobURLRequestJob::CreateFileStreamReader(size_t index, - int64 additional_offset) { - DCHECK_LT(index, blob_data_->items().size()); - const BlobData::Item& item = blob_data_->items().at(index); - DCHECK(IsFileType(item.type())); - DCHECK_EQ(0U, index_to_reader_.count(index)); - - FileStreamReader* reader = NULL; - switch (item.type()) { - case BlobData::Item::TYPE_FILE: - reader = FileStreamReader::CreateForLocalFile( - file_thread_proxy_.get(), - item.path(), - item.offset() + additional_offset, - item.expected_modification_time()); - break; - case BlobData::Item::TYPE_FILE_FILESYSTEM: - reader = file_system_context_->CreateFileStreamReader( - storage::FileSystemURL( - file_system_context_->CrackURL( - item.filesystem_url())), - item.offset() + additional_offset, - item.expected_modification_time()) - .release(); - break; - default: - NOTREACHED(); - } - DCHECK(reader); - index_to_reader_[index] = reader; -} - -} // namespace storage diff --git a/webkit/browser/blob/blob_url_request_job.h b/webkit/browser/blob/blob_url_request_job.h index 1f2bf5b..c494621 100644 --- a/webkit/browser/blob/blob_url_request_job.h +++ b/webkit/browser/blob/blob_url_request_job.h @@ -1,129 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_BLOB_BLOB_URL_REQUEST_JOB_H_ -#define WEBKIT_BROWSER_BLOB_BLOB_URL_REQUEST_JOB_H_ - -#include <map> - -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "net/http/http_byte_range.h" -#include "net/http/http_status_code.h" -#include "net/url_request/url_request_job.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/blob/blob_data.h" - -namespace base { -class MessageLoopProxy; -} - -namespace storage { -class FileSystemContext; -} - -namespace net { -class DrainableIOBuffer; -class IOBuffer; -} - -namespace storage { - -class FileStreamReader; - -// A request job that handles reading blob URLs. -class STORAGE_EXPORT BlobURLRequestJob - : public net::URLRequestJob { - public: - BlobURLRequestJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const scoped_refptr<BlobData>& blob_data, - storage::FileSystemContext* file_system_context, - base::MessageLoopProxy* resolving_message_loop_proxy); - - // net::URLRequestJob methods. - virtual void Start() OVERRIDE; - virtual void Kill() OVERRIDE; - virtual bool ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) OVERRIDE; - virtual bool GetMimeType(std::string* mime_type) const OVERRIDE; - virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE; - virtual int GetResponseCode() const OVERRIDE; - virtual void SetExtraRequestHeaders( - const net::HttpRequestHeaders& headers) OVERRIDE; - - protected: - virtual ~BlobURLRequestJob(); - - private: - typedef std::map<size_t, FileStreamReader*> IndexToReaderMap; - - // For preparing for read: get the size, apply the range and perform seek. - void DidStart(); - bool AddItemLength(size_t index, int64 item_length); - void CountSize(); - void DidCountSize(int error); - void DidGetFileItemLength(size_t index, int64 result); - void Seek(int64 offset); - - // For reading the blob. - bool ReadLoop(int* bytes_read); - bool ReadItem(); - void AdvanceItem(); - void AdvanceBytesRead(int result); - bool ReadBytesItem(const BlobData::Item& item, int bytes_to_read); - bool ReadFileItem(FileStreamReader* reader, int bytes_to_read); - - void DidReadFile(int result); - void DeleteCurrentFileReader(); - - int ComputeBytesToRead() const; - int BytesReadCompleted(); - - // These methods convert the result of blob data reading into response headers - // and pass it to URLRequestJob's NotifyDone() or NotifyHeadersComplete(). - void NotifySuccess(); - void NotifyFailure(int); - void HeadersCompleted(net::HttpStatusCode status_code); - - // Returns a FileStreamReader for a blob item at |index|. - // If the item at |index| is not of file this returns NULL. - FileStreamReader* GetFileStreamReader(size_t index); - - // Creates a FileStreamReader for the item at |index| with additional_offset. - void CreateFileStreamReader(size_t index, int64 additional_offset); - - scoped_refptr<BlobData> blob_data_; - - // Variables for controlling read from |blob_data_|. - scoped_refptr<storage::FileSystemContext> file_system_context_; - scoped_refptr<base::MessageLoopProxy> file_thread_proxy_; - std::vector<int64> item_length_list_; - int64 total_size_; - int64 remaining_bytes_; - int pending_get_file_info_count_; - IndexToReaderMap index_to_reader_; - size_t current_item_index_; - int64 current_item_offset_; - - // Holds the buffer for read data with the IOBuffer interface. - scoped_refptr<net::DrainableIOBuffer> read_buf_; - - // Is set when NotifyFailure() is called and reset when DidStart is called. - bool error_; - - bool byte_range_set_; - net::HttpByteRange byte_range_; - - scoped_ptr<net::HttpResponseInfo> response_info_; - - base::WeakPtrFactory<BlobURLRequestJob> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(BlobURLRequestJob); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_BLOB_BLOB_URL_REQUEST_JOB_H_ +#include "storage/browser/blob/blob_url_request_job.h" diff --git a/webkit/browser/blob/blob_url_request_job_factory.cc b/webkit/browser/blob/blob_url_request_job_factory.cc deleted file mode 100644 index d95f150..0000000 --- a/webkit/browser/blob/blob_url_request_job_factory.cc +++ /dev/null @@ -1,90 +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/browser/blob/blob_url_request_job_factory.h" - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/strings/string_util.h" -#include "net/base/request_priority.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_job_factory.h" -#include "webkit/browser/blob/blob_data_handle.h" -#include "webkit/browser/blob/blob_storage_context.h" -#include "webkit/browser/blob/blob_url_request_job.h" -#include "webkit/browser/fileapi/file_system_context.h" - -namespace storage { - -namespace { - -int kUserDataKey; // The value is not important, the addr is a key. - -BlobDataHandle* GetRequestedBlobDataHandle(net::URLRequest* request) { - return static_cast<BlobDataHandle*>(request->GetUserData(&kUserDataKey)); -} - -} // namespace - -// static -scoped_ptr<net::URLRequest> BlobProtocolHandler::CreateBlobRequest( - scoped_ptr<BlobDataHandle> blob_data_handle, - const net::URLRequestContext* request_context, - net::URLRequest::Delegate* request_delegate) { - const GURL kBlobUrl("blob://see_user_data/"); - scoped_ptr<net::URLRequest> request = request_context->CreateRequest( - kBlobUrl, net::DEFAULT_PRIORITY, request_delegate, NULL); - SetRequestedBlobDataHandle(request.get(), blob_data_handle.Pass()); - return request.Pass(); -} - -// static -void BlobProtocolHandler::SetRequestedBlobDataHandle( - net::URLRequest* request, - scoped_ptr<BlobDataHandle> blob_data_handle) { - request->SetUserData(&kUserDataKey, blob_data_handle.release()); -} - -BlobProtocolHandler::BlobProtocolHandler( - BlobStorageContext* context, - storage::FileSystemContext* file_system_context, - const scoped_refptr<base::MessageLoopProxy>& loop_proxy) - : file_system_context_(file_system_context), file_loop_proxy_(loop_proxy) { - if (context) - context_ = context->AsWeakPtr(); -} - -BlobProtocolHandler::~BlobProtocolHandler() { -} - -net::URLRequestJob* BlobProtocolHandler::MaybeCreateJob( - net::URLRequest* request, net::NetworkDelegate* network_delegate) const { - return new storage::BlobURLRequestJob(request, - network_delegate, - LookupBlobData(request), - file_system_context_.get(), - file_loop_proxy_.get()); -} - -scoped_refptr<storage::BlobData> BlobProtocolHandler::LookupBlobData( - net::URLRequest* request) const { - BlobDataHandle* blob_data_handle = GetRequestedBlobDataHandle(request); - if (blob_data_handle) - return blob_data_handle->data(); - if (!context_.get()) - return NULL; - - // Support looking up based on uuid, the FeedbackExtensionAPI relies on this. - // TODO(michaeln): Replace this use case and others like it with a BlobReader - // impl that does not depend on urlfetching to perform this function. - const std::string kPrefix("blob:uuid/"); - if (!StartsWithASCII(request->url().spec(), kPrefix, true)) - return NULL; - std::string uuid = request->url().spec().substr(kPrefix.length()); - scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(uuid); - return handle.get() ? handle->data() : NULL; -} - -} // namespace storage diff --git a/webkit/browser/blob/blob_url_request_job_factory.h b/webkit/browser/blob/blob_url_request_job_factory.h index 75bfe9a..b39167c 100644 --- a/webkit/browser/blob/blob_url_request_job_factory.h +++ b/webkit/browser/blob/blob_url_request_job_factory.h @@ -1,71 +1,5 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_BLOB_BLOB_URL_REQUEST_JOB_FACTORY_H_ -#define WEBKIT_BROWSER_BLOB_BLOB_URL_REQUEST_JOB_FACTORY_H_ - -#include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_job_factory.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class MessageLoopProxy; -} // namespace base - -namespace storage { -class FileSystemContext; -} // namespace storage - -namespace net { -class URLRequestContext; -} // namespace net - -namespace storage { - -class BlobData; -class BlobDataHandle; -class BlobStorageContext; - -class STORAGE_EXPORT BlobProtocolHandler - : public net::URLRequestJobFactory::ProtocolHandler { - public: - // A helper to manufacture an URLRequest to retrieve the given blob. - static scoped_ptr<net::URLRequest> CreateBlobRequest( - scoped_ptr<BlobDataHandle> blob_data_handle, - const net::URLRequestContext* request_context, - net::URLRequest::Delegate* request_delegate); - - // This class ignores the request's URL and uses the value given - // to SetRequestedBlobDataHandle instead. - static void SetRequestedBlobDataHandle( - net::URLRequest* request, - scoped_ptr<BlobDataHandle> blob_data_handle); - - BlobProtocolHandler( - BlobStorageContext* context, - storage::FileSystemContext* file_system_context, - const scoped_refptr<base::MessageLoopProxy>& file_loop_proxy); - virtual ~BlobProtocolHandler(); - - virtual net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const OVERRIDE; - - private: - scoped_refptr<BlobData> LookupBlobData( - net::URLRequest* request) const; - - base::WeakPtr<BlobStorageContext> context_; - const scoped_refptr<storage::FileSystemContext> file_system_context_; - const scoped_refptr<base::MessageLoopProxy> file_loop_proxy_; - - DISALLOW_COPY_AND_ASSIGN(BlobProtocolHandler); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_BLOB_BLOB_URL_REQUEST_JOB_FACTORY_H_ +#include "storage/browser/blob/blob_url_request_job_factory.h" diff --git a/webkit/browser/blob/file_stream_reader.cc b/webkit/browser/blob/file_stream_reader.cc deleted file mode 100644 index afb2ab8..0000000 --- a/webkit/browser/blob/file_stream_reader.cc +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2014 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/browser/blob/file_stream_reader.h" - -#include "base/time/time.h" - -namespace storage { - -// Verify if the underlying file has not been modified. -bool FileStreamReader::VerifySnapshotTime( - const base::Time& expected_modification_time, - const base::File::Info& file_info) { - return expected_modification_time.is_null() || - expected_modification_time.ToTimeT() == - file_info.last_modified.ToTimeT(); -} - -} // namespace storage diff --git a/webkit/browser/blob/file_stream_reader.h b/webkit/browser/blob/file_stream_reader.h index 0e7f969..d15eedf 100644 --- a/webkit/browser/blob/file_stream_reader.h +++ b/webkit/browser/blob/file_stream_reader.h @@ -1,99 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BLOB_FILE_STREAM_READER_H_ -#define WEBKIT_BLOB_FILE_STREAM_READER_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/files/file.h" -#include "net/base/completion_callback.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class FilePath; -class TaskRunner; -class Time; -} - -namespace net { -class IOBuffer; -} - -namespace storage { -class FileSystemContext; -class FileSystemURL; -} - -namespace storage { - -// A generic interface for reading a file-like object. -class FileStreamReader { - public: - // Creates a new FileReader for a local file |file_path|. - // |initial_offset| specifies the offset in the file where the first read - // should start. If the given offset is out of the file range any - // read operation may error out with net::ERR_REQUEST_RANGE_NOT_SATISFIABLE. - // |expected_modification_time| specifies the expected last modification - // If the value is non-null, the reader will check the underlying file's - // actual modification time to see if the file has been modified, and if - // it does any succeeding read operations should fail with - // ERR_UPLOAD_FILE_CHANGED error. - STORAGE_EXPORT static FileStreamReader* - CreateForLocalFile(base::TaskRunner* task_runner, - const base::FilePath& file_path, - int64 initial_offset, - const base::Time& expected_modification_time); - - // Creates a new reader for a filesystem URL |url| form |initial_offset|. - // |expected_modification_time| specifies the expected last modification if - // the value is non-null, the reader will check the underlying file's actual - // modification time to see if the file has been modified, and if it does any - // succeeding read operations should fail with ERR_UPLOAD_FILE_CHANGED error. - STORAGE_EXPORT static FileStreamReader* - CreateForFileSystemFile(storage::FileSystemContext* context, - const storage::FileSystemURL& url, - int64 initial_offset, - const base::Time& expected_modification_time); - - // Verify if the underlying file has not been modified. - STORAGE_EXPORT static bool VerifySnapshotTime( - const base::Time& expected_modification_time, - const base::File::Info& file_info); - - // It is valid to delete the reader at any time. If the stream is deleted - // while it has a pending read, its callback will not be called. - virtual ~FileStreamReader() {} - - // Reads from the current cursor position asynchronously. - // - // Up to buf_len bytes will be copied into buf. (In other words, partial - // reads are allowed.) Returns the number of bytes copied, 0 if at - // end-of-file, or an error code if the operation could not be performed. - // If the read could not complete synchronously, then ERR_IO_PENDING is - // returned, and the callback will be run on the thread where Read() - // was called, when the read has completed. - // - // It is invalid to call Read while there is an in-flight Read operation. - // - // If the stream is deleted while it has an in-flight Read operation - // |callback| will not be called. - virtual int Read(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) = 0; - - // Returns the length of the file if it could successfully retrieve the - // file info *and* its last modification time equals to - // expected modification time (rv >= 0 cases). - // Otherwise, a negative error code is returned (rv < 0 cases). - // If the stream is deleted while it has an in-flight GetLength operation - // |callback| will not be called. - // Note that the return type is int64 to return a larger file's size (a file - // larger than 2G) but an error code should fit in the int range (may be - // smaller than int64 range). - virtual int64 GetLength(const net::Int64CompletionCallback& callback) = 0; -}; - -} // namespace storage - -#endif // WEBKIT_BLOB_FILE_STREAM_READER_H_ +#include "storage/browser/blob/file_stream_reader.h" diff --git a/webkit/browser/blob/local_file_stream_reader.cc b/webkit/browser/blob/local_file_stream_reader.cc deleted file mode 100644 index 177f381..0000000 --- a/webkit/browser/blob/local_file_stream_reader.cc +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2012 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/browser/blob/local_file_stream_reader.h" - -#include "base/files/file_util.h" -#include "base/files/file_util_proxy.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/task_runner.h" -#include "net/base/file_stream.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" - -namespace storage { - -namespace { - -const int kOpenFlagsForRead = base::File::FLAG_OPEN | - base::File::FLAG_READ | - base::File::FLAG_ASYNC; - -} // namespace - -FileStreamReader* FileStreamReader::CreateForLocalFile( - base::TaskRunner* task_runner, - const base::FilePath& file_path, - int64 initial_offset, - const base::Time& expected_modification_time) { - return new LocalFileStreamReader(task_runner, file_path, initial_offset, - expected_modification_time); -} - -LocalFileStreamReader::~LocalFileStreamReader() { -} - -int LocalFileStreamReader::Read(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { - DCHECK(!has_pending_open_); - if (stream_impl_) - return stream_impl_->Read(buf, buf_len, callback); - return Open(base::Bind(&LocalFileStreamReader::DidOpenForRead, - weak_factory_.GetWeakPtr(), - make_scoped_refptr(buf), buf_len, callback)); -} - -int64 LocalFileStreamReader::GetLength( - const net::Int64CompletionCallback& callback) { - const bool posted = base::FileUtilProxy::GetFileInfo( - task_runner_.get(), - file_path_, - base::Bind(&LocalFileStreamReader::DidGetFileInfoForGetLength, - weak_factory_.GetWeakPtr(), - callback)); - DCHECK(posted); - return net::ERR_IO_PENDING; -} - -LocalFileStreamReader::LocalFileStreamReader( - base::TaskRunner* task_runner, - const base::FilePath& file_path, - int64 initial_offset, - const base::Time& expected_modification_time) - : task_runner_(task_runner), - file_path_(file_path), - initial_offset_(initial_offset), - expected_modification_time_(expected_modification_time), - has_pending_open_(false), - weak_factory_(this) {} - -int LocalFileStreamReader::Open(const net::CompletionCallback& callback) { - DCHECK(!has_pending_open_); - DCHECK(!stream_impl_.get()); - has_pending_open_ = true; - - // Call GetLength first to make it perform last-modified-time verification, - // and then call DidVerifyForOpen for do the rest. - return GetLength(base::Bind(&LocalFileStreamReader::DidVerifyForOpen, - weak_factory_.GetWeakPtr(), callback)); -} - -void LocalFileStreamReader::DidVerifyForOpen( - const net::CompletionCallback& callback, - int64 get_length_result) { - if (get_length_result < 0) { - callback.Run(static_cast<int>(get_length_result)); - return; - } - - stream_impl_.reset(new net::FileStream(task_runner_)); - const int result = stream_impl_->Open( - file_path_, kOpenFlagsForRead, - base::Bind(&LocalFileStreamReader::DidOpenFileStream, - weak_factory_.GetWeakPtr(), - callback)); - if (result != net::ERR_IO_PENDING) - callback.Run(result); -} - -void LocalFileStreamReader::DidOpenFileStream( - const net::CompletionCallback& callback, - int result) { - if (result != net::OK) { - callback.Run(result); - return; - } - result = stream_impl_->Seek( - base::File::FROM_BEGIN, initial_offset_, - base::Bind(&LocalFileStreamReader::DidSeekFileStream, - weak_factory_.GetWeakPtr(), - callback)); - if (result != net::ERR_IO_PENDING) { - callback.Run(result); - } -} - -void LocalFileStreamReader::DidSeekFileStream( - const net::CompletionCallback& callback, - int64 seek_result) { - if (seek_result < 0) { - callback.Run(static_cast<int>(seek_result)); - return; - } - if (seek_result != initial_offset_) { - callback.Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); - return; - } - callback.Run(net::OK); -} - -void LocalFileStreamReader::DidOpenForRead( - net::IOBuffer* buf, - int buf_len, - const net::CompletionCallback& callback, - int open_result) { - DCHECK(has_pending_open_); - has_pending_open_ = false; - if (open_result != net::OK) { - stream_impl_.reset(); - callback.Run(open_result); - return; - } - DCHECK(stream_impl_.get()); - const int read_result = stream_impl_->Read(buf, buf_len, callback); - if (read_result != net::ERR_IO_PENDING) - callback.Run(read_result); -} - -void LocalFileStreamReader::DidGetFileInfoForGetLength( - const net::Int64CompletionCallback& callback, - base::File::Error error, - const base::File::Info& file_info) { - if (file_info.is_directory) { - callback.Run(net::ERR_FILE_NOT_FOUND); - return; - } - if (error != base::File::FILE_OK) { - callback.Run(net::FileErrorToNetError(error)); - return; - } - if (!VerifySnapshotTime(expected_modification_time_, file_info)) { - callback.Run(net::ERR_UPLOAD_FILE_CHANGED); - return; - } - callback.Run(file_info.size); -} - -} // namespace storage diff --git a/webkit/browser/blob/local_file_stream_reader.h b/webkit/browser/blob/local_file_stream_reader.h index 94fafd2..c6fb7f6 100644 --- a/webkit/browser/blob/local_file_stream_reader.h +++ b/webkit/browser/blob/local_file_stream_reader.h @@ -1,81 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_BLOB_LOCAL_FILE_STREAM_READER_H_ -#define WEBKIT_BROWSER_BLOB_LOCAL_FILE_STREAM_READER_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/weak_ptr.h" -#include "base/time/time.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class TaskRunner; -} - -namespace content { -class LocalFileStreamReaderTest; -} - -namespace net { -class FileStream; -} - -namespace storage { - -// A thin wrapper of net::FileStream with range support for sliced file -// handling. -class STORAGE_EXPORT LocalFileStreamReader - : public NON_EXPORTED_BASE(FileStreamReader) { - public: - virtual ~LocalFileStreamReader(); - - // FileStreamReader overrides. - virtual int Read(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) OVERRIDE; - virtual int64 GetLength( - const net::Int64CompletionCallback& callback) OVERRIDE; - - private: - friend class FileStreamReader; - friend class content::LocalFileStreamReaderTest; - - LocalFileStreamReader(base::TaskRunner* task_runner, - const base::FilePath& file_path, - int64 initial_offset, - const base::Time& expected_modification_time); - int Open(const net::CompletionCallback& callback); - - // Callbacks that are chained from Open for Read. - void DidVerifyForOpen(const net::CompletionCallback& callback, - int64 get_length_result); - void DidOpenFileStream(const net::CompletionCallback& callback, - int result); - void DidSeekFileStream(const net::CompletionCallback& callback, - int64 seek_result); - void DidOpenForRead(net::IOBuffer* buf, - int buf_len, - const net::CompletionCallback& callback, - int open_result); - - void DidGetFileInfoForGetLength(const net::Int64CompletionCallback& callback, - base::File::Error error, - const base::File::Info& file_info); - - scoped_refptr<base::TaskRunner> task_runner_; - scoped_ptr<net::FileStream> stream_impl_; - const base::FilePath file_path_; - const int64 initial_offset_; - const base::Time expected_modification_time_; - bool has_pending_open_; - base::WeakPtrFactory<LocalFileStreamReader> weak_factory_; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_BLOB_LOCAL_FILE_STREAM_READER_H_ +#include "storage/browser/blob/local_file_stream_reader.h" diff --git a/webkit/browser/blob/view_blob_internals_job.cc b/webkit/browser/blob/view_blob_internals_job.cc deleted file mode 100644 index d9a4319..0000000 --- a/webkit/browser/blob/view_blob_internals_job.cc +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright (c) 2012 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/browser/blob/view_blob_internals_job.h" - -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/format_macros.h" -#include "base/i18n/number_formatting.h" -#include "base/i18n/time_formatting.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "net/base/escape.h" -#include "net/base/net_errors.h" -#include "net/url_request/url_request.h" -#include "webkit/browser/blob/blob_storage_context.h" -#include "webkit/common/blob/blob_data.h" - -namespace { - -const char kEmptyBlobStorageMessage[] = "No available blob data."; -const char kContentType[] = "Content Type: "; -const char kContentDisposition[] = "Content Disposition: "; -const char kCount[] = "Count: "; -const char kIndex[] = "Index: "; -const char kType[] = "Type: "; -const char kPath[] = "Path: "; -const char kURL[] = "URL: "; -const char kModificationTime[] = "Modification Time: "; -const char kOffset[] = "Offset: "; -const char kLength[] = "Length: "; -const char kUUID[] = "Uuid: "; -const char kRefcount[] = "Refcount: "; - -void StartHTML(std::string* out) { - out->append( - "<!DOCTYPE HTML>" - "<html><title>Blob Storage Internals</title>" - "<meta http-equiv=\"Content-Security-Policy\"" - " content=\"object-src 'none'; script-src 'none'\">\n" - "<style>\n" - "body { font-family: sans-serif; font-size: 0.8em; }\n" - "tt, code, pre { font-family: WebKitHack, monospace; }\n" - "form { display: inline }\n" - ".subsection_body { margin: 10px 0 10px 2em; }\n" - ".subsection_title { font-weight: bold; }\n" - "</style>\n" - "</head><body>\n\n"); -} - -void EndHTML(std::string* out) { - out->append("\n</body></html>"); -} - -void AddHTMLBoldText(const std::string& text, std::string* out) { - out->append("<b>"); - out->append(net::EscapeForHTML(text)); - out->append("</b>"); -} - -void StartHTMLList(std::string* out) { - out->append("\n<ul>"); -} - -void EndHTMLList(std::string* out) { - out->append("</ul>\n"); -} - -void AddHTMLListItem(const std::string& element_title, - const std::string& element_data, - std::string* out) { - out->append("<li>"); - // No need to escape element_title since constant string is passed. - out->append(element_title); - out->append(net::EscapeForHTML(element_data)); - out->append("</li>\n"); -} - -void AddHorizontalRule(std::string* out) { - out->append("\n<hr>\n"); -} - -} // namespace - -namespace storage { - -ViewBlobInternalsJob::ViewBlobInternalsJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - BlobStorageContext* blob_storage_context) - : net::URLRequestSimpleJob(request, network_delegate), - blob_storage_context_(blob_storage_context), - weak_factory_(this) { -} - -ViewBlobInternalsJob::~ViewBlobInternalsJob() { -} - -void ViewBlobInternalsJob::Start() { - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&ViewBlobInternalsJob::StartAsync, - weak_factory_.GetWeakPtr())); -} - -bool ViewBlobInternalsJob::IsRedirectResponse(GURL* location, - int* http_status_code) { - if (request_->url().has_query()) { - // Strip the query parameters. - GURL::Replacements replacements; - replacements.ClearQuery(); - *location = request_->url().ReplaceComponents(replacements); - *http_status_code = 307; - return true; - } - return false; -} - -void ViewBlobInternalsJob::Kill() { - net::URLRequestSimpleJob::Kill(); - weak_factory_.InvalidateWeakPtrs(); -} - -int ViewBlobInternalsJob::GetData( - std::string* mime_type, - std::string* charset, - std::string* data, - const net::CompletionCallback& callback) const { - mime_type->assign("text/html"); - charset->assign("UTF-8"); - - data->clear(); - StartHTML(data); - if (blob_storage_context_->blob_map_.empty()) - data->append(kEmptyBlobStorageMessage); - else - GenerateHTML(data); - EndHTML(data); - return net::OK; -} - -void ViewBlobInternalsJob::GenerateHTML(std::string* out) const { - for (BlobStorageContext::BlobMap::const_iterator iter = - blob_storage_context_->blob_map_.begin(); - iter != blob_storage_context_->blob_map_.end(); - ++iter) { - AddHTMLBoldText(iter->first, out); - GenerateHTMLForBlobData(*(iter->second.data.get()), - iter->second.refcount, - out); - } - if (!blob_storage_context_->public_blob_urls_.empty()) { - AddHorizontalRule(out); - for (BlobStorageContext::BlobURLMap::const_iterator iter = - blob_storage_context_->public_blob_urls_.begin(); - iter != blob_storage_context_->public_blob_urls_.end(); - ++iter) { - AddHTMLBoldText(iter->first.spec(), out); - StartHTMLList(out); - AddHTMLListItem(kUUID, iter->second, out); - EndHTMLList(out); - } - } -} - -void ViewBlobInternalsJob::GenerateHTMLForBlobData(const BlobData& blob_data, - int refcount, - std::string* out) { - StartHTMLList(out); - - AddHTMLListItem(kRefcount, base::IntToString(refcount), out); - if (!blob_data.content_type().empty()) - AddHTMLListItem(kContentType, blob_data.content_type(), out); - if (!blob_data.content_disposition().empty()) - AddHTMLListItem(kContentDisposition, blob_data.content_disposition(), out); - - bool has_multi_items = blob_data.items().size() > 1; - if (has_multi_items) { - AddHTMLListItem(kCount, - base::UTF16ToUTF8(base::FormatNumber(blob_data.items().size())), out); - } - - for (size_t i = 0; i < blob_data.items().size(); ++i) { - if (has_multi_items) { - AddHTMLListItem(kIndex, base::UTF16ToUTF8(base::FormatNumber(i)), out); - StartHTMLList(out); - } - const BlobData::Item& item = blob_data.items().at(i); - - switch (item.type()) { - case BlobData::Item::TYPE_BYTES: - AddHTMLListItem(kType, "data", out); - break; - case BlobData::Item::TYPE_FILE: - AddHTMLListItem(kType, "file", out); - AddHTMLListItem(kPath, - net::EscapeForHTML(item.path().AsUTF8Unsafe()), - out); - if (!item.expected_modification_time().is_null()) { - AddHTMLListItem(kModificationTime, base::UTF16ToUTF8( - TimeFormatFriendlyDateAndTime(item.expected_modification_time())), - out); - } - break; - case BlobData::Item::TYPE_BLOB: - NOTREACHED(); // Should be flattened in the storage context. - break; - case BlobData::Item::TYPE_FILE_FILESYSTEM: - AddHTMLListItem(kType, "filesystem", out); - AddHTMLListItem(kURL, item.filesystem_url().spec(), out); - if (!item.expected_modification_time().is_null()) { - AddHTMLListItem(kModificationTime, base::UTF16ToUTF8( - TimeFormatFriendlyDateAndTime(item.expected_modification_time())), - out); - } - break; - case BlobData::Item::TYPE_UNKNOWN: - NOTREACHED(); - break; - } - if (item.offset()) { - AddHTMLListItem(kOffset, base::UTF16ToUTF8(base::FormatNumber( - static_cast<int64>(item.offset()))), out); - } - if (static_cast<int64>(item.length()) != -1) { - AddHTMLListItem(kLength, base::UTF16ToUTF8(base::FormatNumber( - static_cast<int64>(item.length()))), out); - } - - if (has_multi_items) - EndHTMLList(out); - } - - EndHTMLList(out); -} - -} // namespace storage diff --git a/webkit/browser/blob/view_blob_internals_job.h b/webkit/browser/blob/view_blob_internals_job.h index 9fcf33d..21b33d3 100644 --- a/webkit/browser/blob/view_blob_internals_job.h +++ b/webkit/browser/blob/view_blob_internals_job.h @@ -1,57 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_BLOB_VIEW_BLOB_INTERNALS_JOB_H_ -#define WEBKIT_BROWSER_BLOB_VIEW_BLOB_INTERNALS_JOB_H_ - -#include <string> - -#include "base/memory/weak_ptr.h" -#include "net/url_request/url_request_simple_job.h" -#include "webkit/browser/storage_browser_export.h" - -namespace net { -class URLRequest; -} // namespace net - -namespace storage { - -class BlobData; -class BlobStorageContext; - -// A job subclass that implements a protocol to inspect the internal -// state of blob registry. -class STORAGE_EXPORT ViewBlobInternalsJob - : public net::URLRequestSimpleJob { - public: - ViewBlobInternalsJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - BlobStorageContext* blob_storage_context); - - virtual void Start() OVERRIDE; - virtual int GetData(std::string* mime_type, - std::string* charset, - std::string* data, - const net::CompletionCallback& callback) const OVERRIDE; - virtual bool IsRedirectResponse(GURL* location, - int* http_status_code) OVERRIDE; - virtual void Kill() OVERRIDE; - - private: - virtual ~ViewBlobInternalsJob(); - - void GenerateHTML(std::string* out) const; - static void GenerateHTMLForBlobData(const BlobData& blob_data, - int refcount, - std::string* out); - - BlobStorageContext* blob_storage_context_; - base::WeakPtrFactory<ViewBlobInternalsJob> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ViewBlobInternalsJob); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_BLOB_VIEW_BLOB_INTERNALS_JOB_H_ +#include "storage/browser/blob/view_blob_internals_job.h" diff --git a/webkit/browser/database/database_quota_client.cc b/webkit/browser/database/database_quota_client.cc deleted file mode 100644 index 19f746a..0000000 --- a/webkit/browser/database/database_quota_client.cc +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright (c) 2012 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/browser/database/database_quota_client.h" - -#include <vector> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/location.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/task_runner_util.h" -#include "net/base/net_errors.h" -#include "net/base/net_util.h" -#include "webkit/browser/database/database_tracker.h" -#include "webkit/browser/database/database_util.h" -#include "webkit/common/database/database_identifier.h" - -using storage::QuotaClient; - -namespace storage { - -namespace { - -int64 GetOriginUsageOnDBThread( - DatabaseTracker* db_tracker, - const GURL& origin_url) { - OriginInfo info; - if (db_tracker->GetOriginInfo(storage::GetIdentifierFromOrigin(origin_url), - &info)) - return info.TotalSize(); - return 0; -} - -void GetOriginsOnDBThread( - DatabaseTracker* db_tracker, - std::set<GURL>* origins_ptr) { - std::vector<std::string> origin_identifiers; - if (db_tracker->GetAllOriginIdentifiers(&origin_identifiers)) { - for (std::vector<std::string>::const_iterator iter = - origin_identifiers.begin(); - iter != origin_identifiers.end(); ++iter) { - GURL origin = storage::GetOriginFromIdentifier(*iter); - origins_ptr->insert(origin); - } - } -} - -void GetOriginsForHostOnDBThread( - DatabaseTracker* db_tracker, - std::set<GURL>* origins_ptr, - const std::string& host) { - std::vector<std::string> origin_identifiers; - if (db_tracker->GetAllOriginIdentifiers(&origin_identifiers)) { - for (std::vector<std::string>::const_iterator iter = - origin_identifiers.begin(); - iter != origin_identifiers.end(); ++iter) { - GURL origin = storage::GetOriginFromIdentifier(*iter); - if (host == net::GetHostOrSpecFromURL(origin)) - origins_ptr->insert(origin); - } - } -} - -void DidGetOrigins( - const QuotaClient::GetOriginsCallback& callback, - std::set<GURL>* origins_ptr) { - callback.Run(*origins_ptr); -} - -void DidDeleteOriginData( - base::SingleThreadTaskRunner* original_task_runner, - const QuotaClient::DeletionCallback& callback, - int result) { - if (result == net::ERR_IO_PENDING) { - // The callback will be invoked via - // DatabaseTracker::ScheduleDatabasesForDeletion. - return; - } - - storage::QuotaStatusCode status; - if (result == net::OK) - status = storage::kQuotaStatusOk; - else - status = storage::kQuotaStatusUnknown; - - if (original_task_runner->BelongsToCurrentThread()) - callback.Run(status); - else - original_task_runner->PostTask(FROM_HERE, base::Bind(callback, status)); -} - -} // namespace - -DatabaseQuotaClient::DatabaseQuotaClient( - base::MessageLoopProxy* db_tracker_thread, - DatabaseTracker* db_tracker) - : db_tracker_thread_(db_tracker_thread), db_tracker_(db_tracker) { -} - -DatabaseQuotaClient::~DatabaseQuotaClient() { - if (db_tracker_thread_.get() && - !db_tracker_thread_->RunsTasksOnCurrentThread() && db_tracker_.get()) { - DatabaseTracker* tracker = db_tracker_.get(); - tracker->AddRef(); - db_tracker_ = NULL; - if (!db_tracker_thread_->ReleaseSoon(FROM_HERE, tracker)) - tracker->Release(); - } -} - -QuotaClient::ID DatabaseQuotaClient::id() const { - return kDatabase; -} - -void DatabaseQuotaClient::OnQuotaManagerDestroyed() { - delete this; -} - -void DatabaseQuotaClient::GetOriginUsage(const GURL& origin_url, - storage::StorageType type, - const GetUsageCallback& callback) { - DCHECK(!callback.is_null()); - DCHECK(db_tracker_.get()); - - // All databases are in the temp namespace for now. - if (type != storage::kStorageTypeTemporary) { - callback.Run(0); - return; - } - - base::PostTaskAndReplyWithResult( - db_tracker_thread_.get(), - FROM_HERE, - base::Bind(&GetOriginUsageOnDBThread, db_tracker_, origin_url), - callback); -} - -void DatabaseQuotaClient::GetOriginsForType( - storage::StorageType type, - const GetOriginsCallback& callback) { - DCHECK(!callback.is_null()); - DCHECK(db_tracker_.get()); - - // All databases are in the temp namespace for now. - if (type != storage::kStorageTypeTemporary) { - callback.Run(std::set<GURL>()); - return; - } - - std::set<GURL>* origins_ptr = new std::set<GURL>(); - db_tracker_thread_->PostTaskAndReply( - FROM_HERE, - base::Bind(&GetOriginsOnDBThread, - db_tracker_, - base::Unretained(origins_ptr)), - base::Bind(&DidGetOrigins, - callback, - base::Owned(origins_ptr))); -} - -void DatabaseQuotaClient::GetOriginsForHost( - storage::StorageType type, - const std::string& host, - const GetOriginsCallback& callback) { - DCHECK(!callback.is_null()); - DCHECK(db_tracker_.get()); - - // All databases are in the temp namespace for now. - if (type != storage::kStorageTypeTemporary) { - callback.Run(std::set<GURL>()); - return; - } - - std::set<GURL>* origins_ptr = new std::set<GURL>(); - db_tracker_thread_->PostTaskAndReply( - FROM_HERE, - base::Bind(&GetOriginsForHostOnDBThread, - db_tracker_, - base::Unretained(origins_ptr), - host), - base::Bind(&DidGetOrigins, - callback, - base::Owned(origins_ptr))); -} - -void DatabaseQuotaClient::DeleteOriginData(const GURL& origin, - storage::StorageType type, - const DeletionCallback& callback) { - DCHECK(!callback.is_null()); - DCHECK(db_tracker_.get()); - - // All databases are in the temp namespace for now, so nothing to delete. - if (type != storage::kStorageTypeTemporary) { - callback.Run(storage::kQuotaStatusOk); - return; - } - - base::Callback<void(int)> delete_callback = - base::Bind(&DidDeleteOriginData, - base::MessageLoopProxy::current(), - callback); - - PostTaskAndReplyWithResult( - db_tracker_thread_.get(), - FROM_HERE, - base::Bind(&DatabaseTracker::DeleteDataForOrigin, - db_tracker_, - storage::GetIdentifierFromOrigin(origin), - delete_callback), - delete_callback); -} - -bool DatabaseQuotaClient::DoesSupport(storage::StorageType type) const { - return type == storage::kStorageTypeTemporary; -} - -} // namespace storage diff --git a/webkit/browser/database/database_quota_client.h b/webkit/browser/database/database_quota_client.h index 9325375..b5fec70 100644 --- a/webkit/browser/database/database_quota_client.h +++ b/webkit/browser/database/database_quota_client.h @@ -1,57 +1,5 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_DATABASE_DATABASE_QUOTA_CLIENT_H_ -#define WEBKIT_BROWSER_DATABASE_DATABASE_QUOTA_CLIENT_H_ - -#include <set> -#include <string> - -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop_proxy.h" -#include "webkit/browser/quota/quota_client.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/quota/quota_types.h" - -namespace storage { - -class DatabaseTracker; - -// A QuotaClient implementation to integrate WebSQLDatabases -// with the quota management system. This interface is used -// on the IO thread by the quota manager. -class STORAGE_EXPORT_PRIVATE DatabaseQuotaClient - : public storage::QuotaClient { - public: - DatabaseQuotaClient( - base::MessageLoopProxy* tracker_thread, - DatabaseTracker* tracker); - virtual ~DatabaseQuotaClient(); - - // QuotaClient method overrides - virtual ID id() const OVERRIDE; - virtual void OnQuotaManagerDestroyed() OVERRIDE; - virtual void GetOriginUsage(const GURL& origin_url, - storage::StorageType type, - const GetUsageCallback& callback) OVERRIDE; - virtual void GetOriginsForType(storage::StorageType type, - const GetOriginsCallback& callback) OVERRIDE; - virtual void GetOriginsForHost(storage::StorageType type, - const std::string& host, - const GetOriginsCallback& callback) OVERRIDE; - virtual void DeleteOriginData(const GURL& origin, - storage::StorageType type, - const DeletionCallback& callback) OVERRIDE; - virtual bool DoesSupport(storage::StorageType type) const OVERRIDE; - - private: - scoped_refptr<base::MessageLoopProxy> db_tracker_thread_; - scoped_refptr<DatabaseTracker> db_tracker_; // only used on its thread - - DISALLOW_COPY_AND_ASSIGN(DatabaseQuotaClient); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_DATABASE_DATABASE_QUOTA_CLIENT_H_ +#include "storage/browser/database/database_quota_client.h" diff --git a/webkit/browser/database/database_tracker.cc b/webkit/browser/database/database_tracker.cc deleted file mode 100644 index 9f76495..0000000 --- a/webkit/browser/database/database_tracker.cc +++ /dev/null @@ -1,869 +0,0 @@ -// Copyright (c) 2012 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/browser/database/database_tracker.h" - -#include <algorithm> -#include <vector> - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/files/file.h" -#include "base/files/file_enumerator.h" -#include "base/files/file_util.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "net/base/net_errors.h" -#include "sql/connection.h" -#include "sql/meta_table.h" -#include "sql/transaction.h" -#include "third_party/sqlite/sqlite3.h" -#include "webkit/browser/database/database_quota_client.h" -#include "webkit/browser/database/database_util.h" -#include "webkit/browser/database/databases_table.h" -#include "webkit/browser/quota/quota_manager_proxy.h" -#include "webkit/browser/quota/special_storage_policy.h" -#include "webkit/common/database/database_identifier.h" - -namespace storage { - -const base::FilePath::CharType kDatabaseDirectoryName[] = - FILE_PATH_LITERAL("databases"); -const base::FilePath::CharType kIncognitoDatabaseDirectoryName[] = - FILE_PATH_LITERAL("databases-incognito"); -const base::FilePath::CharType kTrackerDatabaseFileName[] = - FILE_PATH_LITERAL("Databases.db"); -static const int kCurrentVersion = 2; -static const int kCompatibleVersion = 1; - -const base::FilePath::CharType kTemporaryDirectoryPrefix[] = - FILE_PATH_LITERAL("DeleteMe"); -const base::FilePath::CharType kTemporaryDirectoryPattern[] = - FILE_PATH_LITERAL("DeleteMe*"); - -OriginInfo::OriginInfo() - : total_size_(0) {} - -OriginInfo::OriginInfo(const OriginInfo& origin_info) - : origin_identifier_(origin_info.origin_identifier_), - total_size_(origin_info.total_size_), - database_info_(origin_info.database_info_) {} - -OriginInfo::~OriginInfo() {} - -void OriginInfo::GetAllDatabaseNames( - std::vector<base::string16>* databases) const { - for (DatabaseInfoMap::const_iterator it = database_info_.begin(); - it != database_info_.end(); it++) { - databases->push_back(it->first); - } -} - -int64 OriginInfo::GetDatabaseSize(const base::string16& database_name) const { - DatabaseInfoMap::const_iterator it = database_info_.find(database_name); - if (it != database_info_.end()) - return it->second.first; - return 0; -} - -base::string16 OriginInfo::GetDatabaseDescription( - const base::string16& database_name) const { - DatabaseInfoMap::const_iterator it = database_info_.find(database_name); - if (it != database_info_.end()) - return it->second.second; - return base::string16(); -} - -OriginInfo::OriginInfo(const std::string& origin_identifier, int64 total_size) - : origin_identifier_(origin_identifier), total_size_(total_size) {} - -DatabaseTracker::DatabaseTracker( - const base::FilePath& profile_path, - bool is_incognito, - storage::SpecialStoragePolicy* special_storage_policy, - storage::QuotaManagerProxy* quota_manager_proxy, - base::MessageLoopProxy* db_tracker_thread) - : is_initialized_(false), - is_incognito_(is_incognito), - force_keep_session_state_(false), - shutting_down_(false), - profile_path_(profile_path), - db_dir_(is_incognito_ - ? profile_path_.Append(kIncognitoDatabaseDirectoryName) - : profile_path_.Append(kDatabaseDirectoryName)), - db_(new sql::Connection()), - special_storage_policy_(special_storage_policy), - quota_manager_proxy_(quota_manager_proxy), - db_tracker_thread_(db_tracker_thread), - incognito_origin_directories_generator_(0) { - if (quota_manager_proxy) { - quota_manager_proxy->RegisterClient( - new DatabaseQuotaClient(db_tracker_thread, this)); - } -} - -DatabaseTracker::~DatabaseTracker() { - DCHECK(dbs_to_be_deleted_.empty()); - DCHECK(deletion_callbacks_.empty()); -} - -void DatabaseTracker::DatabaseOpened(const std::string& origin_identifier, - const base::string16& database_name, - const base::string16& database_description, - int64 estimated_size, - int64* database_size) { - if (shutting_down_ || !LazyInit()) { - *database_size = 0; - return; - } - - if (quota_manager_proxy_.get()) - quota_manager_proxy_->NotifyStorageAccessed( - storage::QuotaClient::kDatabase, - storage::GetOriginFromIdentifier(origin_identifier), - storage::kStorageTypeTemporary); - - InsertOrUpdateDatabaseDetails(origin_identifier, database_name, - database_description, estimated_size); - if (database_connections_.AddConnection(origin_identifier, database_name)) { - *database_size = SeedOpenDatabaseInfo(origin_identifier, - database_name, - database_description); - return; - } - *database_size = UpdateOpenDatabaseInfoAndNotify(origin_identifier, - database_name, - &database_description); -} - -void DatabaseTracker::DatabaseModified(const std::string& origin_identifier, - const base::string16& database_name) { - if (!LazyInit()) - return; - UpdateOpenDatabaseSizeAndNotify(origin_identifier, database_name); -} - -void DatabaseTracker::DatabaseClosed(const std::string& origin_identifier, - const base::string16& database_name) { - if (database_connections_.IsEmpty()) { - DCHECK(!is_initialized_); - return; - } - - // We call NotifiyStorageAccessed when a db is opened and also when - // closed because we don't call it for read while open. - if (quota_manager_proxy_.get()) - quota_manager_proxy_->NotifyStorageAccessed( - storage::QuotaClient::kDatabase, - storage::GetOriginFromIdentifier(origin_identifier), - storage::kStorageTypeTemporary); - - UpdateOpenDatabaseSizeAndNotify(origin_identifier, database_name); - if (database_connections_.RemoveConnection(origin_identifier, database_name)) - DeleteDatabaseIfNeeded(origin_identifier, database_name); -} - -void DatabaseTracker::HandleSqliteError( - const std::string& origin_identifier, - const base::string16& database_name, - int error) { - // We only handle errors that indicate corruption and we - // do so with a heavy hand, we delete it. Any renderers/workers - // with this database open will receive a message to close it - // immediately, once all have closed, the files will be deleted. - // In the interim, all attempts to open a new connection to that - // database will fail. - // Note: the client-side filters out all but these two errors as - // a small optimization, see WebDatabaseObserverImpl::HandleSqliteError. - if (error == SQLITE_CORRUPT || error == SQLITE_NOTADB) { - DeleteDatabase(origin_identifier, database_name, - net::CompletionCallback()); - } -} - -void DatabaseTracker::CloseDatabases(const DatabaseConnections& connections) { - if (database_connections_.IsEmpty()) { - DCHECK(!is_initialized_ || connections.IsEmpty()); - return; - } - - // When being closed by this route, there's a chance that - // the tracker missed some DatabseModified calls. This method is used - // when a renderer crashes to cleanup its open resources. - // We need to examine what we have in connections for the - // size of each open databases and notify any differences between the - // actual file sizes now. - std::vector<std::pair<std::string, base::string16> > open_dbs; - connections.ListConnections(&open_dbs); - for (std::vector<std::pair<std::string, base::string16> >::iterator it = - open_dbs.begin(); it != open_dbs.end(); ++it) - UpdateOpenDatabaseSizeAndNotify(it->first, it->second); - - std::vector<std::pair<std::string, base::string16> > closed_dbs; - database_connections_.RemoveConnections(connections, &closed_dbs); - for (std::vector<std::pair<std::string, base::string16> >::iterator it = - closed_dbs.begin(); it != closed_dbs.end(); ++it) { - DeleteDatabaseIfNeeded(it->first, it->second); - } -} - -void DatabaseTracker::DeleteDatabaseIfNeeded( - const std::string& origin_identifier, - const base::string16& database_name) { - DCHECK(!database_connections_.IsDatabaseOpened(origin_identifier, - database_name)); - if (IsDatabaseScheduledForDeletion(origin_identifier, database_name)) { - DeleteClosedDatabase(origin_identifier, database_name); - dbs_to_be_deleted_[origin_identifier].erase(database_name); - if (dbs_to_be_deleted_[origin_identifier].empty()) - dbs_to_be_deleted_.erase(origin_identifier); - - PendingDeletionCallbacks::iterator callback = deletion_callbacks_.begin(); - while (callback != deletion_callbacks_.end()) { - DatabaseSet::iterator found_origin = - callback->second.find(origin_identifier); - if (found_origin != callback->second.end()) { - std::set<base::string16>& databases = found_origin->second; - databases.erase(database_name); - if (databases.empty()) { - callback->second.erase(found_origin); - if (callback->second.empty()) { - net::CompletionCallback cb = callback->first; - cb.Run(net::OK); - callback = deletion_callbacks_.erase(callback); - continue; - } - } - } - - ++callback; - } - } -} - -void DatabaseTracker::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void DatabaseTracker::RemoveObserver(Observer* observer) { - // When we remove a listener, we do not know which cached information - // is still needed and which information can be discarded. So we just - // clear all caches and re-populate them as needed. - observers_.RemoveObserver(observer); - ClearAllCachedOriginInfo(); -} - -void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() { - ClearAllCachedOriginInfo(); - - if (!is_incognito_) { - meta_table_.reset(NULL); - databases_table_.reset(NULL); - db_->Close(); - is_initialized_ = false; - } -} - -base::string16 DatabaseTracker::GetOriginDirectory( - const std::string& origin_identifier) { - if (!is_incognito_) - return base::UTF8ToUTF16(origin_identifier); - - OriginDirectoriesMap::const_iterator it = - incognito_origin_directories_.find(origin_identifier); - if (it != incognito_origin_directories_.end()) - return it->second; - - base::string16 origin_directory = - base::IntToString16(incognito_origin_directories_generator_++); - incognito_origin_directories_[origin_identifier] = origin_directory; - return origin_directory; -} - -base::FilePath DatabaseTracker::GetFullDBFilePath( - const std::string& origin_identifier, - const base::string16& database_name) { - DCHECK(!origin_identifier.empty()); - if (!LazyInit()) - return base::FilePath(); - - int64 id = databases_table_->GetDatabaseID(origin_identifier, database_name); - if (id < 0) - return base::FilePath(); - - return db_dir_.Append(base::FilePath::FromUTF16Unsafe( - GetOriginDirectory(origin_identifier))).AppendASCII( - base::Int64ToString(id)); -} - -bool DatabaseTracker::GetOriginInfo(const std::string& origin_identifier, - OriginInfo* info) { - DCHECK(info); - CachedOriginInfo* cached_info = GetCachedOriginInfo(origin_identifier); - if (!cached_info) - return false; - *info = OriginInfo(*cached_info); - return true; -} - -bool DatabaseTracker::GetAllOriginIdentifiers( - std::vector<std::string>* origin_identifiers) { - DCHECK(origin_identifiers); - DCHECK(origin_identifiers->empty()); - if (!LazyInit()) - return false; - return databases_table_->GetAllOriginIdentifiers(origin_identifiers); -} - -bool DatabaseTracker::GetAllOriginsInfo( - std::vector<OriginInfo>* origins_info) { - DCHECK(origins_info); - DCHECK(origins_info->empty()); - - std::vector<std::string> origins; - if (!GetAllOriginIdentifiers(&origins)) - return false; - - for (std::vector<std::string>::const_iterator it = origins.begin(); - it != origins.end(); it++) { - CachedOriginInfo* origin_info = GetCachedOriginInfo(*it); - if (!origin_info) { - // Restore 'origins_info' to its initial state. - origins_info->clear(); - return false; - } - origins_info->push_back(OriginInfo(*origin_info)); - } - - return true; -} - -bool DatabaseTracker::DeleteClosedDatabase( - const std::string& origin_identifier, - const base::string16& database_name) { - if (!LazyInit()) - return false; - - // Check if the database is opened by any renderer. - if (database_connections_.IsDatabaseOpened(origin_identifier, database_name)) - return false; - - int64 db_file_size = quota_manager_proxy_.get() - ? GetDBFileSize(origin_identifier, database_name) - : 0; - - // Try to delete the file on the hard drive. - base::FilePath db_file = GetFullDBFilePath(origin_identifier, database_name); - if (!sql::Connection::Delete(db_file)) - return false; - - if (quota_manager_proxy_.get() && db_file_size) - quota_manager_proxy_->NotifyStorageModified( - storage::QuotaClient::kDatabase, - storage::GetOriginFromIdentifier(origin_identifier), - storage::kStorageTypeTemporary, - -db_file_size); - - // Clean up the main database and invalidate the cached record. - databases_table_->DeleteDatabaseDetails(origin_identifier, database_name); - origins_info_map_.erase(origin_identifier); - - std::vector<DatabaseDetails> details; - if (databases_table_->GetAllDatabaseDetailsForOriginIdentifier( - origin_identifier, &details) && details.empty()) { - // Try to delete the origin in case this was the last database. - DeleteOrigin(origin_identifier, false); - } - return true; -} - -bool DatabaseTracker::DeleteOrigin(const std::string& origin_identifier, - bool force) { - if (!LazyInit()) - return false; - - // Check if any database in this origin is opened by any renderer. - if (database_connections_.IsOriginUsed(origin_identifier) && !force) - return false; - - int64 deleted_size = 0; - if (quota_manager_proxy_.get()) { - CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier); - if (origin_info) - deleted_size = origin_info->TotalSize(); - } - - origins_info_map_.erase(origin_identifier); - base::FilePath origin_dir = db_dir_.AppendASCII(origin_identifier); - - // Create a temporary directory to move possibly still existing databases to, - // as we can't delete the origin directory on windows if it contains opened - // files. - base::FilePath new_origin_dir; - base::CreateTemporaryDirInDir(db_dir_, - kTemporaryDirectoryPrefix, - &new_origin_dir); - base::FileEnumerator databases( - origin_dir, - false, - base::FileEnumerator::FILES); - for (base::FilePath database = databases.Next(); !database.empty(); - database = databases.Next()) { - base::FilePath new_file = new_origin_dir.Append(database.BaseName()); - base::Move(database, new_file); - } - base::DeleteFile(origin_dir, true); - base::DeleteFile(new_origin_dir, true); // might fail on windows. - - databases_table_->DeleteOriginIdentifier(origin_identifier); - - if (quota_manager_proxy_.get() && deleted_size) { - quota_manager_proxy_->NotifyStorageModified( - storage::QuotaClient::kDatabase, - storage::GetOriginFromIdentifier(origin_identifier), - storage::kStorageTypeTemporary, - -deleted_size); - } - - return true; -} - -bool DatabaseTracker::IsDatabaseScheduledForDeletion( - const std::string& origin_identifier, - const base::string16& database_name) { - DatabaseSet::iterator it = dbs_to_be_deleted_.find(origin_identifier); - if (it == dbs_to_be_deleted_.end()) - return false; - - std::set<base::string16>& databases = it->second; - return (databases.find(database_name) != databases.end()); -} - -bool DatabaseTracker::LazyInit() { - if (!is_initialized_ && !shutting_down_) { - DCHECK(!db_->is_open()); - DCHECK(!databases_table_.get()); - DCHECK(!meta_table_.get()); - - // If there are left-over directories from failed deletion attempts, clean - // them up. - if (base::DirectoryExists(db_dir_)) { - base::FileEnumerator directories( - db_dir_, - false, - base::FileEnumerator::DIRECTORIES, - kTemporaryDirectoryPattern); - for (base::FilePath directory = directories.Next(); !directory.empty(); - directory = directories.Next()) { - base::DeleteFile(directory, true); - } - } - - // If the tracker database exists, but it's corrupt or doesn't - // have a meta table, delete the database directory. - const base::FilePath kTrackerDatabaseFullPath = - db_dir_.Append(base::FilePath(kTrackerDatabaseFileName)); - if (base::DirectoryExists(db_dir_) && - base::PathExists(kTrackerDatabaseFullPath) && - (!db_->Open(kTrackerDatabaseFullPath) || - !sql::MetaTable::DoesTableExist(db_.get()))) { - db_->Close(); - if (!base::DeleteFile(db_dir_, true)) - return false; - } - - db_->set_histogram_tag("DatabaseTracker"); - - databases_table_.reset(new DatabasesTable(db_.get())); - meta_table_.reset(new sql::MetaTable()); - - is_initialized_ = - base::CreateDirectory(db_dir_) && - (db_->is_open() || - (is_incognito_ ? db_->OpenInMemory() : - db_->Open(kTrackerDatabaseFullPath))) && - UpgradeToCurrentVersion(); - if (!is_initialized_) { - databases_table_.reset(NULL); - meta_table_.reset(NULL); - db_->Close(); - } - } - return is_initialized_; -} - -bool DatabaseTracker::UpgradeToCurrentVersion() { - sql::Transaction transaction(db_.get()); - if (!transaction.Begin() || - !meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion) || - (meta_table_->GetCompatibleVersionNumber() > kCurrentVersion) || - !databases_table_->Init()) - return false; - - if (meta_table_->GetVersionNumber() < kCurrentVersion) - meta_table_->SetVersionNumber(kCurrentVersion); - - return transaction.Commit(); -} - -void DatabaseTracker::InsertOrUpdateDatabaseDetails( - const std::string& origin_identifier, - const base::string16& database_name, - const base::string16& database_description, - int64 estimated_size) { - DatabaseDetails details; - if (!databases_table_->GetDatabaseDetails( - origin_identifier, database_name, &details)) { - details.origin_identifier = origin_identifier; - details.database_name = database_name; - details.description = database_description; - details.estimated_size = estimated_size; - databases_table_->InsertDatabaseDetails(details); - } else if ((details.description != database_description) || - (details.estimated_size != estimated_size)) { - details.description = database_description; - details.estimated_size = estimated_size; - databases_table_->UpdateDatabaseDetails(details); - } -} - -void DatabaseTracker::ClearAllCachedOriginInfo() { - origins_info_map_.clear(); -} - -DatabaseTracker::CachedOriginInfo* DatabaseTracker::MaybeGetCachedOriginInfo( - const std::string& origin_identifier, bool create_if_needed) { - if (!LazyInit()) - return NULL; - - // Populate the cache with data for this origin if needed. - if (origins_info_map_.find(origin_identifier) == origins_info_map_.end()) { - if (!create_if_needed) - return NULL; - - std::vector<DatabaseDetails> details; - if (!databases_table_->GetAllDatabaseDetailsForOriginIdentifier( - origin_identifier, &details)) { - return NULL; - } - - CachedOriginInfo& origin_info = origins_info_map_[origin_identifier]; - origin_info.SetOriginIdentifier(origin_identifier); - for (std::vector<DatabaseDetails>::const_iterator it = details.begin(); - it != details.end(); it++) { - int64 db_file_size; - if (database_connections_.IsDatabaseOpened( - origin_identifier, it->database_name)) { - db_file_size = database_connections_.GetOpenDatabaseSize( - origin_identifier, it->database_name); - } else { - db_file_size = GetDBFileSize(origin_identifier, it->database_name); - } - origin_info.SetDatabaseSize(it->database_name, db_file_size); - origin_info.SetDatabaseDescription(it->database_name, it->description); - } - } - - return &origins_info_map_[origin_identifier]; -} - -int64 DatabaseTracker::GetDBFileSize(const std::string& origin_identifier, - const base::string16& database_name) { - base::FilePath db_file_name = GetFullDBFilePath(origin_identifier, - database_name); - int64 db_file_size = 0; - if (!base::GetFileSize(db_file_name, &db_file_size)) - db_file_size = 0; - return db_file_size; -} - -int64 DatabaseTracker::SeedOpenDatabaseInfo( - const std::string& origin_id, const base::string16& name, - const base::string16& description) { - DCHECK(database_connections_.IsDatabaseOpened(origin_id, name)); - int64 size = GetDBFileSize(origin_id, name); - database_connections_.SetOpenDatabaseSize(origin_id, name, size); - CachedOriginInfo* info = MaybeGetCachedOriginInfo(origin_id, false); - if (info) { - info->SetDatabaseSize(name, size); - info->SetDatabaseDescription(name, description); - } - return size; -} - -int64 DatabaseTracker::UpdateOpenDatabaseInfoAndNotify( - const std::string& origin_id, const base::string16& name, - const base::string16* opt_description) { - DCHECK(database_connections_.IsDatabaseOpened(origin_id, name)); - int64 new_size = GetDBFileSize(origin_id, name); - int64 old_size = database_connections_.GetOpenDatabaseSize(origin_id, name); - CachedOriginInfo* info = MaybeGetCachedOriginInfo(origin_id, false); - if (info && opt_description) - info->SetDatabaseDescription(name, *opt_description); - if (old_size != new_size) { - database_connections_.SetOpenDatabaseSize(origin_id, name, new_size); - if (info) - info->SetDatabaseSize(name, new_size); - if (quota_manager_proxy_.get()) - quota_manager_proxy_->NotifyStorageModified( - storage::QuotaClient::kDatabase, - storage::GetOriginFromIdentifier(origin_id), - storage::kStorageTypeTemporary, - new_size - old_size); - FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseSizeChanged( - origin_id, name, new_size)); - } - return new_size; -} - -void DatabaseTracker::ScheduleDatabaseForDeletion( - const std::string& origin_identifier, - const base::string16& database_name) { - DCHECK(database_connections_.IsDatabaseOpened(origin_identifier, - database_name)); - dbs_to_be_deleted_[origin_identifier].insert(database_name); - FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseScheduledForDeletion( - origin_identifier, database_name)); -} - -void DatabaseTracker::ScheduleDatabasesForDeletion( - const DatabaseSet& databases, - const net::CompletionCallback& callback) { - DCHECK(!databases.empty()); - - if (!callback.is_null()) - deletion_callbacks_.push_back(std::make_pair(callback, databases)); - for (DatabaseSet::const_iterator ori = databases.begin(); - ori != databases.end(); ++ori) { - for (std::set<base::string16>::const_iterator db = ori->second.begin(); - db != ori->second.end(); ++db) - ScheduleDatabaseForDeletion(ori->first, *db); - } -} - -int DatabaseTracker::DeleteDatabase(const std::string& origin_identifier, - const base::string16& database_name, - const net::CompletionCallback& callback) { - if (!LazyInit()) - return net::ERR_FAILED; - - if (database_connections_.IsDatabaseOpened(origin_identifier, - database_name)) { - if (!callback.is_null()) { - DatabaseSet set; - set[origin_identifier].insert(database_name); - deletion_callbacks_.push_back(std::make_pair(callback, set)); - } - ScheduleDatabaseForDeletion(origin_identifier, database_name); - return net::ERR_IO_PENDING; - } - DeleteClosedDatabase(origin_identifier, database_name); - return net::OK; -} - -int DatabaseTracker::DeleteDataModifiedSince( - const base::Time& cutoff, - const net::CompletionCallback& callback) { - if (!LazyInit()) - return net::ERR_FAILED; - - DatabaseSet to_be_deleted; - - std::vector<std::string> origins_identifiers; - if (!databases_table_->GetAllOriginIdentifiers(&origins_identifiers)) - return net::ERR_FAILED; - int rv = net::OK; - for (std::vector<std::string>::const_iterator ori = - origins_identifiers.begin(); - ori != origins_identifiers.end(); ++ori) { - if (special_storage_policy_.get() && - special_storage_policy_->IsStorageProtected( - storage::GetOriginFromIdentifier(*ori))) { - continue; - } - - std::vector<DatabaseDetails> details; - if (!databases_table_-> - GetAllDatabaseDetailsForOriginIdentifier(*ori, &details)) - rv = net::ERR_FAILED; - for (std::vector<DatabaseDetails>::const_iterator db = details.begin(); - db != details.end(); ++db) { - base::FilePath db_file = GetFullDBFilePath(*ori, db->database_name); - base::File::Info file_info; - base::GetFileInfo(db_file, &file_info); - if (file_info.last_modified < cutoff) - continue; - - // Check if the database is opened by any renderer. - if (database_connections_.IsDatabaseOpened(*ori, db->database_name)) - to_be_deleted[*ori].insert(db->database_name); - else - DeleteClosedDatabase(*ori, db->database_name); - } - } - - if (rv != net::OK) - return rv; - - if (!to_be_deleted.empty()) { - ScheduleDatabasesForDeletion(to_be_deleted, callback); - return net::ERR_IO_PENDING; - } - return net::OK; -} - -int DatabaseTracker::DeleteDataForOrigin( - const std::string& origin, const net::CompletionCallback& callback) { - if (!LazyInit()) - return net::ERR_FAILED; - - DatabaseSet to_be_deleted; - - std::vector<DatabaseDetails> details; - if (!databases_table_-> - GetAllDatabaseDetailsForOriginIdentifier(origin, &details)) - return net::ERR_FAILED; - for (std::vector<DatabaseDetails>::const_iterator db = details.begin(); - db != details.end(); ++db) { - // Check if the database is opened by any renderer. - if (database_connections_.IsDatabaseOpened(origin, db->database_name)) - to_be_deleted[origin].insert(db->database_name); - else - DeleteClosedDatabase(origin, db->database_name); - } - - if (!to_be_deleted.empty()) { - ScheduleDatabasesForDeletion(to_be_deleted, callback); - return net::ERR_IO_PENDING; - } - return net::OK; -} - -const base::File* DatabaseTracker::GetIncognitoFile( - const base::string16& vfs_file_name) const { - DCHECK(is_incognito_); - FileHandlesMap::const_iterator it = - incognito_file_handles_.find(vfs_file_name); - if (it != incognito_file_handles_.end()) - return it->second; - - return NULL; -} - -const base::File* DatabaseTracker::SaveIncognitoFile( - const base::string16& vfs_file_name, - base::File file) { - DCHECK(is_incognito_); - if (!file.IsValid()) - return NULL; - - base::File* to_insert = new base::File(file.Pass()); - std::pair<FileHandlesMap::iterator, bool> rv = - incognito_file_handles_.insert(std::make_pair(vfs_file_name, to_insert)); - DCHECK(rv.second); - return rv.first->second; -} - -void DatabaseTracker::CloseIncognitoFileHandle( - const base::string16& vfs_file_name) { - DCHECK(is_incognito_); - DCHECK(incognito_file_handles_.find(vfs_file_name) != - incognito_file_handles_.end()); - - FileHandlesMap::iterator it = incognito_file_handles_.find(vfs_file_name); - if (it != incognito_file_handles_.end()) { - delete it->second; - incognito_file_handles_.erase(it); - } -} - -bool DatabaseTracker::HasSavedIncognitoFileHandle( - const base::string16& vfs_file_name) const { - return (incognito_file_handles_.find(vfs_file_name) != - incognito_file_handles_.end()); -} - -void DatabaseTracker::DeleteIncognitoDBDirectory() { - is_initialized_ = false; - - for (FileHandlesMap::iterator it = incognito_file_handles_.begin(); - it != incognito_file_handles_.end(); it++) { - delete it->second; - } - - base::FilePath incognito_db_dir = - profile_path_.Append(kIncognitoDatabaseDirectoryName); - if (base::DirectoryExists(incognito_db_dir)) - base::DeleteFile(incognito_db_dir, true); -} - -void DatabaseTracker::ClearSessionOnlyOrigins() { - bool has_session_only_databases = - special_storage_policy_.get() && - special_storage_policy_->HasSessionOnlyOrigins(); - - // Clearing only session-only databases, and there are none. - if (!has_session_only_databases) - return; - - if (!LazyInit()) - return; - - std::vector<std::string> origin_identifiers; - GetAllOriginIdentifiers(&origin_identifiers); - - for (std::vector<std::string>::iterator origin = - origin_identifiers.begin(); - origin != origin_identifiers.end(); ++origin) { - GURL origin_url = storage::GetOriginFromIdentifier(*origin); - if (!special_storage_policy_->IsStorageSessionOnly(origin_url)) - continue; - if (special_storage_policy_->IsStorageProtected(origin_url)) - continue; - storage::OriginInfo origin_info; - std::vector<base::string16> databases; - GetOriginInfo(*origin, &origin_info); - origin_info.GetAllDatabaseNames(&databases); - - for (std::vector<base::string16>::iterator database = databases.begin(); - database != databases.end(); ++database) { - base::File file(GetFullDBFilePath(*origin, *database), - base::File::FLAG_OPEN_ALWAYS | - base::File::FLAG_SHARE_DELETE | - base::File::FLAG_DELETE_ON_CLOSE | - base::File::FLAG_READ); - } - DeleteOrigin(*origin, true); - } -} - - -void DatabaseTracker::Shutdown() { - DCHECK(db_tracker_thread_.get()); - DCHECK(db_tracker_thread_->BelongsToCurrentThread()); - if (shutting_down_) { - NOTREACHED(); - return; - } - shutting_down_ = true; - if (is_incognito_) - DeleteIncognitoDBDirectory(); - else if (!force_keep_session_state_) - ClearSessionOnlyOrigins(); - CloseTrackerDatabaseAndClearCaches(); -} - -void DatabaseTracker::SetForceKeepSessionState() { - DCHECK(db_tracker_thread_.get()); - if (!db_tracker_thread_->BelongsToCurrentThread()) { - db_tracker_thread_->PostTask( - FROM_HERE, - base::Bind(&DatabaseTracker::SetForceKeepSessionState, this)); - return; - } - force_keep_session_state_ = true; -} - -} // namespace storage diff --git a/webkit/browser/database/database_tracker.h b/webkit/browser/database/database_tracker.h index 6f14d7b..9bcd442 100644 --- a/webkit/browser/database/database_tracker.h +++ b/webkit/browser/database/database_tracker.h @@ -1,319 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_DATABASE_DATABASE_TRACKER_H_ -#define WEBKIT_BROWSER_DATABASE_DATABASE_TRACKER_H_ - -#include <map> -#include <set> -#include <utility> - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "base/strings/string16.h" -#include "base/strings/string_util.h" -#include "base/time/time.h" -#include "net/base/completion_callback.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/database/database_connections.h" - -namespace base { -class MessageLoopProxy; -} - -namespace content { -class DatabaseTracker_TestHelper_Test; -class MockDatabaseTracker; -} - -namespace sql { -class Connection; -class MetaTable; -} - -namespace storage { -class QuotaManagerProxy; -class SpecialStoragePolicy; -} - -namespace storage { - -STORAGE_EXPORT extern const base::FilePath::CharType - kDatabaseDirectoryName[]; -STORAGE_EXPORT extern const base::FilePath::CharType - kTrackerDatabaseFileName[]; - -class DatabasesTable; - -// This class is used to store information about all databases in an origin. -class STORAGE_EXPORT OriginInfo { - public: - OriginInfo(); - OriginInfo(const OriginInfo& origin_info); - ~OriginInfo(); - - const std::string& GetOriginIdentifier() const { return origin_identifier_; } - int64 TotalSize() const { return total_size_; } - void GetAllDatabaseNames(std::vector<base::string16>* databases) const; - int64 GetDatabaseSize(const base::string16& database_name) const; - base::string16 GetDatabaseDescription( - const base::string16& database_name) const; - - protected: - typedef std::map<base::string16, std::pair<int64, base::string16> > - DatabaseInfoMap; - - OriginInfo(const std::string& origin_identifier, int64 total_size); - - std::string origin_identifier_; - int64 total_size_; - DatabaseInfoMap database_info_; -}; - -// This class manages the main database and keeps track of open databases. -// -// The data in this class is not thread-safe, so all methods of this class -// should be called on the same thread. The only exceptions are the ctor(), -// the dtor() and the database_directory() and quota_manager_proxy() getters. -// -// Furthermore, some methods of this class have to read/write data from/to -// the disk. Therefore, in a multi-threaded application, all methods of this -// class should be called on the thread dedicated to file operations (file -// thread in the browser process, for example), if such a thread exists. -class STORAGE_EXPORT DatabaseTracker - : public base::RefCountedThreadSafe<DatabaseTracker> { - public: - class Observer { - public: - virtual void OnDatabaseSizeChanged(const std::string& origin_identifier, - const base::string16& database_name, - int64 database_size) = 0; - virtual void OnDatabaseScheduledForDeletion( - const std::string& origin_identifier, - const base::string16& database_name) = 0; - - protected: - virtual ~Observer() {} - }; - - DatabaseTracker(const base::FilePath& profile_path, - bool is_incognito, - storage::SpecialStoragePolicy* special_storage_policy, - storage::QuotaManagerProxy* quota_manager_proxy, - base::MessageLoopProxy* db_tracker_thread); - - void DatabaseOpened(const std::string& origin_identifier, - const base::string16& database_name, - const base::string16& database_details, - int64 estimated_size, - int64* database_size); - void DatabaseModified(const std::string& origin_identifier, - const base::string16& database_name); - void DatabaseClosed(const std::string& origin_identifier, - const base::string16& database_name); - void HandleSqliteError(const std::string& origin_identifier, - const base::string16& database_name, - int error); - - void CloseDatabases(const DatabaseConnections& connections); - - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - - void CloseTrackerDatabaseAndClearCaches(); - - const base::FilePath& DatabaseDirectory() const { return db_dir_; } - base::FilePath GetFullDBFilePath(const std::string& origin_identifier, - const base::string16& database_name); - - // virtual for unit-testing only - virtual bool GetOriginInfo(const std::string& origin_id, OriginInfo* info); - virtual bool GetAllOriginIdentifiers(std::vector<std::string>* origin_ids); - virtual bool GetAllOriginsInfo(std::vector<OriginInfo>* origins_info); - - // Safe to call on any thread. - storage::QuotaManagerProxy* quota_manager_proxy() const { - return quota_manager_proxy_.get(); - } - - bool IsDatabaseScheduledForDeletion(const std::string& origin_identifier, - const base::string16& database_name); - - // Deletes a single database. Returns net::OK on success, net::FAILED on - // failure, or net::ERR_IO_PENDING and |callback| is invoked upon completion, - // if non-NULL. - int DeleteDatabase(const std::string& origin_identifier, - const base::string16& database_name, - const net::CompletionCallback& callback); - - // Delete any databases that have been touched since the cutoff date that's - // supplied, omitting any that match IDs within |protected_origins|. - // Returns net::OK on success, net::FAILED if not all databases could be - // deleted, and net::ERR_IO_PENDING and |callback| is invoked upon completion, - // if non-NULL. Protected origins, according the the SpecialStoragePolicy, - // are not deleted by this method. - int DeleteDataModifiedSince(const base::Time& cutoff, - const net::CompletionCallback& callback); - - // Delete all databases that belong to the given origin. Returns net::OK on - // success, net::FAILED if not all databases could be deleted, and - // net::ERR_IO_PENDING and |callback| is invoked upon completion, if non-NULL. - // virtual for unit testing only - virtual int DeleteDataForOrigin(const std::string& origin_identifier, - const net::CompletionCallback& callback); - - bool IsIncognitoProfile() const { return is_incognito_; } - - const base::File* GetIncognitoFile(const base::string16& vfs_file_path) const; - const base::File* SaveIncognitoFile(const base::string16& vfs_file_path, - base::File file); - void CloseIncognitoFileHandle(const base::string16& vfs_file_path); - bool HasSavedIncognitoFileHandle(const base::string16& vfs_file_path) const; - - // Shutdown the database tracker, deleting database files if the tracker is - // used for an incognito profile. - void Shutdown(); - // Disables the exit-time deletion of session-only data. - void SetForceKeepSessionState(); - - private: - friend class base::RefCountedThreadSafe<DatabaseTracker>; - friend class content::DatabaseTracker_TestHelper_Test; - friend class content::MockDatabaseTracker; // for testing - - typedef std::map<std::string, std::set<base::string16> > DatabaseSet; - typedef std::vector<std::pair<net::CompletionCallback, DatabaseSet> > - PendingDeletionCallbacks; - typedef std::map<base::string16, base::File*> FileHandlesMap; - typedef std::map<std::string, base::string16> OriginDirectoriesMap; - - class CachedOriginInfo : public OriginInfo { - public: - CachedOriginInfo() : OriginInfo(std::string(), 0) {} - void SetOriginIdentifier(const std::string& origin_identifier) { - origin_identifier_ = origin_identifier; - } - void SetDatabaseSize(const base::string16& database_name, int64 new_size) { - int64 old_size = 0; - if (database_info_.find(database_name) != database_info_.end()) - old_size = database_info_[database_name].first; - database_info_[database_name].first = new_size; - if (new_size != old_size) - total_size_ += new_size - old_size; - } - void SetDatabaseDescription(const base::string16& database_name, - const base::string16& description) { - database_info_[database_name].second = description; - } - }; - - // virtual for unit-testing only. - virtual ~DatabaseTracker(); - - // Deletes the directory that stores all DBs in incognito mode, if it exists. - void DeleteIncognitoDBDirectory(); - - // Deletes session-only databases. Blocks databases from being created/opened. - void ClearSessionOnlyOrigins(); - - bool DeleteClosedDatabase(const std::string& origin_identifier, - const base::string16& database_name); - - // Delete all files belonging to the given origin given that no database - // connections within this origin are open, or if |force| is true, delete - // the meta data and rename the associated directory. - bool DeleteOrigin(const std::string& origin_identifier, bool force); - void DeleteDatabaseIfNeeded(const std::string& origin_identifier, - const base::string16& database_name); - - bool LazyInit(); - bool UpgradeToCurrentVersion(); - void InsertOrUpdateDatabaseDetails(const std::string& origin_identifier, - const base::string16& database_name, - const base::string16& database_details, - int64 estimated_size); - - void ClearAllCachedOriginInfo(); - CachedOriginInfo* MaybeGetCachedOriginInfo( - const std::string& origin_identifier, - bool create_if_needed); - CachedOriginInfo* GetCachedOriginInfo( - const std::string& origin_identifier) { - return MaybeGetCachedOriginInfo(origin_identifier, true); - } - - int64 GetDBFileSize(const std::string& origin_identifier, - const base::string16& database_name); - int64 SeedOpenDatabaseInfo(const std::string& origin_identifier, - const base::string16& database_name, - const base::string16& description); - int64 UpdateOpenDatabaseInfoAndNotify(const std::string& origin_identifier, - const base::string16& database_name, - const base::string16* opt_description); - int64 UpdateOpenDatabaseSizeAndNotify(const std::string& origin_identifier, - const base::string16& database_name) { - return UpdateOpenDatabaseInfoAndNotify( - origin_identifier, database_name, NULL); - } - - - void ScheduleDatabaseForDeletion(const std::string& origin_identifier, - const base::string16& database_name); - // Schedule a set of open databases for deletion. If non-null, callback is - // invoked upon completion. - void ScheduleDatabasesForDeletion(const DatabaseSet& databases, - const net::CompletionCallback& callback); - - // Returns the directory where all DB files for the given origin are stored. - base::string16 GetOriginDirectory(const std::string& origin_identifier); - - bool is_initialized_; - const bool is_incognito_; - bool force_keep_session_state_; - bool shutting_down_; - const base::FilePath profile_path_; - const base::FilePath db_dir_; - scoped_ptr<sql::Connection> db_; - scoped_ptr<DatabasesTable> databases_table_; - scoped_ptr<sql::MetaTable> meta_table_; - ObserverList<Observer, true> observers_; - std::map<std::string, CachedOriginInfo> origins_info_map_; - DatabaseConnections database_connections_; - - // The set of databases that should be deleted but are still opened - DatabaseSet dbs_to_be_deleted_; - PendingDeletionCallbacks deletion_callbacks_; - - // Apps and Extensions can have special rights. - scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_; - - scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; - - // The database tracker thread we're supposed to run file IO on. - scoped_refptr<base::MessageLoopProxy> db_tracker_thread_; - - // When in incognito mode, store a DELETE_ON_CLOSE handle to each - // main DB and journal file that was accessed. When the incognito profile - // goes away (or when the browser crashes), all these handles will be - // closed, and the files will be deleted. - FileHandlesMap incognito_file_handles_; - - // In a non-incognito profile, all DBs in an origin are stored in a directory - // named after the origin. In an incognito profile though, we do not want the - // directory structure to reveal the origins visited by the user (in case the - // browser process crashes and those directories are not deleted). So we use - // this map to assign directory names that do not reveal this information. - OriginDirectoriesMap incognito_origin_directories_; - int incognito_origin_directories_generator_; - - FRIEND_TEST_ALL_PREFIXES(DatabaseTracker, TestHelper); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_DATABASE_DATABASE_TRACKER_H_ +#include "storage/browser/database/database_tracker.h" diff --git a/webkit/browser/database/database_util.cc b/webkit/browser/database/database_util.cc deleted file mode 100644 index c6d797a..0000000 --- a/webkit/browser/database/database_util.cc +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2012 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/browser/database/database_util.h" - -#include "base/basictypes.h" -#include "base/strings/utf_string_conversions.h" -#include "webkit/browser/database/database_tracker.h" -#include "webkit/browser/database/vfs_backend.h" -#include "webkit/common/database/database_identifier.h" - -namespace storage { - -namespace { - -bool IsSafeSuffix(const base::string16& suffix) { - base::char16 prev_c = 0; - for (base::string16::const_iterator it = suffix.begin(); - it < suffix.end(); ++it) { - base::char16 c = *it; - if (!(IsAsciiAlpha(c) || IsAsciiDigit(c) || - c == '-' || c == '.' || c == '_')) { - return false; - } - if (c == '.' && prev_c == '.') - return false; - prev_c = c; - } - return true; -} - -} - -const char DatabaseUtil::kJournalFileSuffix[] = "-journal"; - -bool DatabaseUtil::CrackVfsFileName(const base::string16& vfs_file_name, - std::string* origin_identifier, - base::string16* database_name, - base::string16* sqlite_suffix) { - // 'vfs_file_name' is of the form <origin_identifier>/<db_name>#<suffix>. - // <suffix> is optional. - DCHECK(!vfs_file_name.empty()); - size_t first_slash_index = vfs_file_name.find('/'); - size_t last_pound_index = vfs_file_name.rfind('#'); - // '/' and '#' must be present in the string. Also, the string cannot start - // with a '/' (origin_identifier cannot be empty) and '/' must come before '#' - if ((first_slash_index == base::string16::npos) || - (last_pound_index == base::string16::npos) || - (first_slash_index == 0) || - (first_slash_index > last_pound_index)) { - return false; - } - - std::string origin_id = base::UTF16ToASCII( - vfs_file_name.substr(0, first_slash_index)); - if (!IsValidOriginIdentifier(origin_id)) - return false; - - base::string16 suffix = vfs_file_name.substr( - last_pound_index + 1, vfs_file_name.length() - last_pound_index - 1); - if (!IsSafeSuffix(suffix)) - return false; - - if (origin_identifier) - *origin_identifier = origin_id; - - if (database_name) { - *database_name = vfs_file_name.substr( - first_slash_index + 1, last_pound_index - first_slash_index - 1); - } - - if (sqlite_suffix) - *sqlite_suffix = suffix; - - return true; -} - -base::FilePath DatabaseUtil::GetFullFilePathForVfsFile( - DatabaseTracker* db_tracker, const base::string16& vfs_file_name) { - std::string origin_identifier; - base::string16 database_name; - base::string16 sqlite_suffix; - if (!CrackVfsFileName(vfs_file_name, &origin_identifier, - &database_name, &sqlite_suffix)) { - return base::FilePath(); // invalid vfs_file_name - } - - base::FilePath full_path = db_tracker->GetFullDBFilePath( - origin_identifier, database_name); - if (!full_path.empty() && !sqlite_suffix.empty()) { - DCHECK(full_path.Extension().empty()); - full_path = full_path.InsertBeforeExtensionASCII( - base::UTF16ToASCII(sqlite_suffix)); - } - // Watch out for directory traversal attempts from a compromised renderer. - if (full_path.value().find(FILE_PATH_LITERAL("..")) != - base::FilePath::StringType::npos) - return base::FilePath(); - return full_path; -} - -bool DatabaseUtil::IsValidOriginIdentifier( - const std::string& origin_identifier) { - return GetOriginFromIdentifier(origin_identifier).is_valid(); -} - -} // namespace storage diff --git a/webkit/browser/database/database_util.h b/webkit/browser/database/database_util.h index bb2a6f4..cce434c 100644 --- a/webkit/browser/database/database_util.h +++ b/webkit/browser/database/database_util.h @@ -1,39 +1,5 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_DATABASE_DATABASE_UTIL_H_ -#define WEBKIT_BROWSER_DATABASE_DATABASE_UTIL_H_ - -#include <string> -#include "base/strings/string16.h" -#include "url/gurl.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class FilePath; -} - -namespace storage { - -class DatabaseTracker; - -class STORAGE_EXPORT DatabaseUtil { - public: - static const char kJournalFileSuffix[]; - - // Extract various information from a database vfs_file_name. All return - // parameters are optional. - static bool CrackVfsFileName(const base::string16& vfs_file_name, - std::string* origin_identifier, - base::string16* database_name, - base::string16* sqlite_suffix); - static base::FilePath GetFullFilePathForVfsFile( - DatabaseTracker* db_tracker, - const base::string16& vfs_file_name); - static bool IsValidOriginIdentifier(const std::string& origin_identifier); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_DATABASE_DATABASE_UTIL_H_ +#include "storage/browser/database/database_util.h" diff --git a/webkit/browser/database/databases_table.cc b/webkit/browser/database/databases_table.cc deleted file mode 100644 index c5e239b..0000000 --- a/webkit/browser/database/databases_table.cc +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2012 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/browser/database/databases_table.h" - -#include "base/logging.h" -#include "base/strings/utf_string_conversions.h" -#include "sql/statement.h" - -namespace storage { - -DatabaseDetails::DatabaseDetails() : estimated_size(0) { } - -DatabaseDetails::~DatabaseDetails() {} - -bool DatabasesTable::Init() { - // 'Databases' schema: - // id A unique ID assigned to each database - // origin The originto which the database belongs. This is a - // string that can be used as part of a file name - // (http_webkit.org_0, for example). - // name The database name. - // description A short description of the database. - // estimated_size The estimated size of the database. - return db_->DoesTableExist("Databases") || - (db_->Execute( - "CREATE TABLE Databases (" - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "origin TEXT NOT NULL, " - "name TEXT NOT NULL, " - "description TEXT NOT NULL, " - "estimated_size INTEGER NOT NULL)") && - db_->Execute( - "CREATE INDEX origin_index ON Databases (origin)") && - db_->Execute( - "CREATE UNIQUE INDEX unique_index ON Databases (origin, name)")); -} - -int64 DatabasesTable::GetDatabaseID(const std::string& origin_identifier, - const base::string16& database_name) { - sql::Statement select_statement(db_->GetCachedStatement( - SQL_FROM_HERE, "SELECT id FROM Databases WHERE origin = ? AND name = ?")); - select_statement.BindString(0, origin_identifier); - select_statement.BindString16(1, database_name); - - if (select_statement.Step()) { - return select_statement.ColumnInt64(0); - } - - return -1; -} - -bool DatabasesTable::GetDatabaseDetails(const std::string& origin_identifier, - const base::string16& database_name, - DatabaseDetails* details) { - DCHECK(details); - sql::Statement select_statement(db_->GetCachedStatement( - SQL_FROM_HERE, "SELECT description, estimated_size FROM Databases " - "WHERE origin = ? AND name = ?")); - select_statement.BindString(0, origin_identifier); - select_statement.BindString16(1, database_name); - - if (select_statement.Step()) { - details->origin_identifier = origin_identifier; - details->database_name = database_name; - details->description = select_statement.ColumnString16(0); - details->estimated_size = select_statement.ColumnInt64(1); - return true; - } - - return false; -} - -bool DatabasesTable::InsertDatabaseDetails(const DatabaseDetails& details) { - sql::Statement insert_statement(db_->GetCachedStatement( - SQL_FROM_HERE, "INSERT INTO Databases (origin, name, description, " - "estimated_size) VALUES (?, ?, ?, ?)")); - insert_statement.BindString(0, details.origin_identifier); - insert_statement.BindString16(1, details.database_name); - insert_statement.BindString16(2, details.description); - insert_statement.BindInt64(3, details.estimated_size); - - return insert_statement.Run(); -} - -bool DatabasesTable::UpdateDatabaseDetails(const DatabaseDetails& details) { - sql::Statement update_statement(db_->GetCachedStatement( - SQL_FROM_HERE, "UPDATE Databases SET description = ?, " - "estimated_size = ? WHERE origin = ? AND name = ?")); - update_statement.BindString16(0, details.description); - update_statement.BindInt64(1, details.estimated_size); - update_statement.BindString(2, details.origin_identifier); - update_statement.BindString16(3, details.database_name); - - return (update_statement.Run() && db_->GetLastChangeCount()); -} - -bool DatabasesTable::DeleteDatabaseDetails( - const std::string& origin_identifier, - const base::string16& database_name) { - sql::Statement delete_statement(db_->GetCachedStatement( - SQL_FROM_HERE, "DELETE FROM Databases WHERE origin = ? AND name = ?")); - delete_statement.BindString(0, origin_identifier); - delete_statement.BindString16(1, database_name); - - return (delete_statement.Run() && db_->GetLastChangeCount()); -} - -bool DatabasesTable::GetAllOriginIdentifiers( - std::vector<std::string>* origin_identifiers) { - sql::Statement statement(db_->GetCachedStatement( - SQL_FROM_HERE, "SELECT DISTINCT origin FROM Databases ORDER BY origin")); - - while (statement.Step()) - origin_identifiers->push_back(statement.ColumnString(0)); - - return statement.Succeeded(); -} - -bool DatabasesTable::GetAllDatabaseDetailsForOriginIdentifier( - const std::string& origin_identifier, - std::vector<DatabaseDetails>* details_vector) { - sql::Statement statement(db_->GetCachedStatement( - SQL_FROM_HERE, "SELECT name, description, estimated_size " - "FROM Databases WHERE origin = ? ORDER BY name")); - statement.BindString(0, origin_identifier); - - while (statement.Step()) { - DatabaseDetails details; - details.origin_identifier = origin_identifier; - details.database_name = statement.ColumnString16(0); - details.description = statement.ColumnString16(1); - details.estimated_size = statement.ColumnInt64(2); - details_vector->push_back(details); - } - - return statement.Succeeded(); -} - -bool DatabasesTable::DeleteOriginIdentifier( - const std::string& origin_identifier) { - sql::Statement delete_statement(db_->GetCachedStatement( - SQL_FROM_HERE, "DELETE FROM Databases WHERE origin = ?")); - delete_statement.BindString(0, origin_identifier); - - return (delete_statement.Run() && db_->GetLastChangeCount()); -} - -} // namespace storage diff --git a/webkit/browser/database/databases_table.h b/webkit/browser/database/databases_table.h index c3cdbb82..18342b7 100644 --- a/webkit/browser/database/databases_table.h +++ b/webkit/browser/database/databases_table.h @@ -1,54 +1,5 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_DATABASE_DATABASES_TABLE_H_ -#define WEBKIT_BROWSER_DATABASE_DATABASES_TABLE_H_ - -#include <vector> - -#include "base/strings/string16.h" -#include "webkit/browser/storage_browser_export.h" - -namespace sql { -class Connection; -} - -namespace storage { - -struct STORAGE_EXPORT_PRIVATE DatabaseDetails { - DatabaseDetails(); - ~DatabaseDetails(); - - std::string origin_identifier; - base::string16 database_name; - base::string16 description; - int64 estimated_size; -}; - -class STORAGE_EXPORT_PRIVATE DatabasesTable { - public: - explicit DatabasesTable(sql::Connection* db) : db_(db) { } - - bool Init(); - int64 GetDatabaseID(const std::string& origin_identifier, - const base::string16& database_name); - bool GetDatabaseDetails(const std::string& origin_identifier, - const base::string16& database_name, - DatabaseDetails* details); - bool InsertDatabaseDetails(const DatabaseDetails& details); - bool UpdateDatabaseDetails(const DatabaseDetails& details); - bool DeleteDatabaseDetails(const std::string& origin_identifier, - const base::string16& database_name); - bool GetAllOriginIdentifiers(std::vector<std::string>* origin_identifiers); - bool GetAllDatabaseDetailsForOriginIdentifier( - const std::string& origin_identifier, - std::vector<DatabaseDetails>* details); - bool DeleteOriginIdentifier(const std::string& origin_identifier); - private: - sql::Connection* db_; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_DATABASE_DATABASES_TABLE_H_ +#include "storage/browser/database/databases_table.h" diff --git a/webkit/browser/database/vfs_backend.cc b/webkit/browser/database/vfs_backend.cc deleted file mode 100644 index 4c8e578..0000000 --- a/webkit/browser/database/vfs_backend.cc +++ /dev/null @@ -1,158 +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/browser/database/vfs_backend.h" - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "third_party/sqlite/sqlite3.h" - -namespace storage { - -static const int kFileTypeMask = 0x00007F00; - -// static -bool VfsBackend::OpenTypeIsReadWrite(int desired_flags) { - return (desired_flags & SQLITE_OPEN_READWRITE) != 0; -} - -// static -bool VfsBackend::OpenFileFlagsAreConsistent(int desired_flags) { - const int file_type = desired_flags & kFileTypeMask; - const bool is_exclusive = (desired_flags & SQLITE_OPEN_EXCLUSIVE) != 0; - const bool is_delete = (desired_flags & SQLITE_OPEN_DELETEONCLOSE) != 0; - const bool is_create = (desired_flags & SQLITE_OPEN_CREATE) != 0; - const bool is_read_only = (desired_flags & SQLITE_OPEN_READONLY) != 0; - const bool is_read_write = (desired_flags & SQLITE_OPEN_READWRITE) != 0; - - // All files should be opened either read-write or read-only, but not both. - if (is_read_only == is_read_write) - return false; - - // If a new file is created, it must also be writable. - if (is_create && !is_read_write) - return false; - - // If we're accessing an existing file, we cannot give exclusive access, and - // we can't delete it. - // Normally, we'd also check that 'is_delete' is false for a main DB, main - // journal or master journal file; however, when in incognito mode, we use - // the SQLITE_OPEN_DELETEONCLOSE flag when opening those files too and keep - // an open handle to them for as long as the incognito profile is around. - if ((is_exclusive || is_delete) && !is_create) - return false; - - // Make sure we're opening the DB directory or that a file type is set. - return (file_type == SQLITE_OPEN_MAIN_DB) || - (file_type == SQLITE_OPEN_TEMP_DB) || - (file_type == SQLITE_OPEN_MAIN_JOURNAL) || - (file_type == SQLITE_OPEN_TEMP_JOURNAL) || - (file_type == SQLITE_OPEN_SUBJOURNAL) || - (file_type == SQLITE_OPEN_MASTER_JOURNAL) || - (file_type == SQLITE_OPEN_TRANSIENT_DB); -} - -// static -base::File VfsBackend::OpenFile(const base::FilePath& file_path, - int desired_flags) { - DCHECK(!file_path.empty()); - - // Verify the flags for consistency and create the database - // directory if it doesn't exist. - if (!OpenFileFlagsAreConsistent(desired_flags) || - !base::CreateDirectory(file_path.DirName())) { - return base::File(); - } - - int flags = 0; - flags |= base::File::FLAG_READ; - if (desired_flags & SQLITE_OPEN_READWRITE) - flags |= base::File::FLAG_WRITE; - - if (!(desired_flags & SQLITE_OPEN_MAIN_DB)) - flags |= base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE; - - flags |= ((desired_flags & SQLITE_OPEN_CREATE) ? - base::File::FLAG_OPEN_ALWAYS : base::File::FLAG_OPEN); - - if (desired_flags & SQLITE_OPEN_EXCLUSIVE) - flags |= base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE; - - if (desired_flags & SQLITE_OPEN_DELETEONCLOSE) { - flags |= base::File::FLAG_TEMPORARY | base::File::FLAG_HIDDEN | - base::File::FLAG_DELETE_ON_CLOSE; - } - - // This flag will allow us to delete the file later on from the browser - // process. - flags |= base::File::FLAG_SHARE_DELETE; - - // Try to open/create the DB file. - return base::File(file_path, flags); -} - -// static -base::File VfsBackend::OpenTempFileInDirectory(const base::FilePath& dir_path, - int desired_flags) { - // We should be able to delete temp files when they're closed - // and create them as needed - if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE) || - !(desired_flags & SQLITE_OPEN_CREATE)) { - return base::File(); - } - - // Get a unique temp file name in the database directory. - base::FilePath temp_file_path; - if (!base::CreateTemporaryFileInDir(dir_path, &temp_file_path)) - return base::File(); - - return OpenFile(temp_file_path, desired_flags); -} - -// static -int VfsBackend::DeleteFile(const base::FilePath& file_path, bool sync_dir) { - if (!base::PathExists(file_path)) - return SQLITE_OK; - if (!base::DeleteFile(file_path, false)) - return SQLITE_IOERR_DELETE; - - int error_code = SQLITE_OK; -#if defined(OS_POSIX) - if (sync_dir) { - base::File dir(file_path.DirName(), base::File::FLAG_READ); - if (dir.IsValid()) { - if (!dir.Flush()) - error_code = SQLITE_IOERR_DIR_FSYNC; - } else { - error_code = SQLITE_CANTOPEN; - } - } -#endif - return error_code; -} - -// static -uint32 VfsBackend::GetFileAttributes(const base::FilePath& file_path) { -#if defined(OS_WIN) - uint32 attributes = ::GetFileAttributes(file_path.value().c_str()); -#elif defined(OS_POSIX) - uint32 attributes = 0; - if (!access(file_path.value().c_str(), R_OK)) - attributes |= static_cast<uint32>(R_OK); - if (!access(file_path.value().c_str(), W_OK)) - attributes |= static_cast<uint32>(W_OK); - if (!attributes) - attributes = -1; -#endif - return attributes; -} - -// static -int64 VfsBackend::GetFileSize(const base::FilePath& file_path) { - int64 size = 0; - return (base::GetFileSize(file_path, &size) ? size : 0); -} - -} // namespace storage diff --git a/webkit/browser/database/vfs_backend.h b/webkit/browser/database/vfs_backend.h index 3de6371..3904e15 100644 --- a/webkit/browser/database/vfs_backend.h +++ b/webkit/browser/database/vfs_backend.h @@ -1,42 +1,5 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_DATABASE_VFS_BACKEND_H_ -#define WEBKIT_BROWSER_DATABASE_VFS_BACKEND_H_ - -#include "base/files/file.h" -#include "base/process/process.h" -#include "base/strings/string16.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class FilePath; -} - -namespace storage { - -class STORAGE_EXPORT VfsBackend { - public: - static base::File OpenFile(const base::FilePath& file_path, - int desired_flags); - - static base::File OpenTempFileInDirectory(const base::FilePath& dir_path, - int desired_flags); - - static int DeleteFile(const base::FilePath& file_path, bool sync_dir); - - static uint32 GetFileAttributes(const base::FilePath& file_path); - - static int64 GetFileSize(const base::FilePath& file_path); - - // Used to make decisions in the DatabaseDispatcherHost. - static bool OpenTypeIsReadWrite(int desired_flags); - - private: - static bool OpenFileFlagsAreConsistent(int desired_flags); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_DATABASE_VFS_BACKEND_H_ +#include "storage/browser/database/vfs_backend.h" diff --git a/webkit/browser/fileapi/OWNERS b/webkit/browser/fileapi/OWNERS deleted file mode 100644 index 232db84..0000000 --- a/webkit/browser/fileapi/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -tzik@chromium.org -nhiroki@chromium.org diff --git a/webkit/browser/fileapi/async_file_util.h b/webkit/browser/fileapi/async_file_util.h index c2b1098..758963f 100644 --- a/webkit/browser/fileapi/async_file_util.h +++ b/webkit/browser/fileapi/async_file_util.h @@ -1,366 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_ASYNC_FILE_UTIL_H_ -#define WEBKIT_BROWSER_FILEAPI_ASYNC_FILE_UTIL_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/callback_forward.h" -#include "base/files/file.h" -#include "base/files/file_util_proxy.h" -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/file_system_operation.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/directory_entry.h" - -namespace base { -class Time; -} - -namespace storage { -class ShareableFileReference; -} - -namespace storage { - -class FileSystemOperationContext; -class FileSystemURL; - -// An interface which provides filesystem-specific file operations for -// FileSystemOperationImpl. -// -// Each filesystem which needs to be dispatched from FileSystemOperationImpl -// must implement this interface or a synchronous version of interface: -// FileSystemFileUtil. -// -// As far as an instance of this class is owned by a FileSystemBackend -// (which is owned by FileSystemContext), it's guaranteed that this instance's -// alive while FileSystemOperationContext given to each operation is kept -// alive. (Note that this instance might be freed on different thread -// from the thread it is created.) -// -// It is NOT valid to give null callback to this class, and implementors -// can assume that they don't get any null callbacks. -// -class AsyncFileUtil { - public: - typedef base::Callback<void(base::File::Error result)> StatusCallback; - - // |on_close_callback| will be called after the |file| is closed in the - // child process. |on_close_callback|.is_null() can be true, if no operation - // is needed on closing the file. - typedef base::Callback< - void(base::File file, - const base::Closure& on_close_callback)> CreateOrOpenCallback; - - typedef base::Callback< - void(base::File::Error result, - bool created)> EnsureFileExistsCallback; - - typedef base::Callback< - void(base::File::Error result, - const base::File::Info& file_info)> GetFileInfoCallback; - - typedef std::vector<DirectoryEntry> EntryList; - typedef base::Callback< - void(base::File::Error result, - const EntryList& file_list, - bool has_more)> ReadDirectoryCallback; - - typedef base::Callback< - void(base::File::Error result, - const base::File::Info& file_info, - const base::FilePath& platform_path, - const scoped_refptr<storage::ShareableFileReference>& file_ref)> - CreateSnapshotFileCallback; - - typedef base::Callback<void(int64 size)> CopyFileProgressCallback; - - typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption; - - // Creates an AsyncFileUtil instance which performs file operations on - // local native file system. The created instance assumes - // FileSystemURL::path() has the target platform path. - STORAGE_EXPORT static AsyncFileUtil* - CreateForLocalFileSystem(); - - AsyncFileUtil() {} - virtual ~AsyncFileUtil() {} - - // Creates or opens a file with the given flags. - // If File::FLAG_CREATE is set in |file_flags| it always tries to create - // a new file at the given |url| and calls back with - // File::FILE_ERROR_FILE_EXISTS if the |url| already exists. - // - // FileSystemOperationImpl::OpenFile calls this. - // This is used only by Pepper/NaCl File API. - // - virtual void CreateOrOpen( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - int file_flags, - const CreateOrOpenCallback& callback) = 0; - - // Ensures that the given |url| exist. This creates a empty new file - // at |url| if the |url| does not exist. - // - // FileSystemOperationImpl::CreateFile calls this. - // - // This reports following error code via |callback|: - // - File::FILE_OK and created==true if a file has not existed and - // is created at |url|. - // - File::FILE_OK and created==false if the file already exists. - // - Other error code (with created=false) if a file hasn't existed yet - // and there was an error while creating a new file. - // - virtual void EnsureFileExists( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const EnsureFileExistsCallback& callback) = 0; - - // Creates directory at given url. - // - // FileSystemOperationImpl::CreateDirectory calls this. - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if the |url|'s parent directory - // does not exist and |recursive| is false. - // - File::FILE_ERROR_EXISTS if a directory already exists at |url| - // and |exclusive| is true. - // - File::FILE_ERROR_EXISTS if a file already exists at |url| - // (regardless of |exclusive| value). - // - Other error code if it failed to create a directory. - // - virtual void CreateDirectory( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - bool exclusive, - bool recursive, - const StatusCallback& callback) = 0; - - // Retrieves the information about a file. - // - // FileSystemOperationImpl::GetMetadata calls this. - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if the file doesn't exist. - // - Other error code if there was an error while retrieving the file info. - // - virtual void GetFileInfo( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const GetFileInfoCallback& callback) = 0; - - // Reads contents of a directory at |path|. - // - // FileSystemOperationImpl::ReadDirectory calls this. - // - // Note that the |name| field of each entry in |file_list| - // returned by |callback| should have a base file name - // of the entry relative to the directory, but not an absolute path. - // - // (E.g. if ReadDirectory is called for a directory - // 'path/to/dir' and the directory has entries 'a' and 'b', - // the returned |file_list| should include entries whose names - // are 'a' and 'b', but not '/path/to/dir/a' and '/path/to/dir/b'.) - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if the target directory doesn't exist. - // - File::FILE_ERROR_NOT_A_DIRECTORY if an entry exists at |url| but - // is a file (not a directory). - // - virtual void ReadDirectory( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const ReadDirectoryCallback& callback) = 0; - - // Modifies timestamps of a file or directory at |url| with - // |last_access_time| and |last_modified_time|. The function DOES NOT - // create a file unlike 'touch' command on Linux. - // - // FileSystemOperationImpl::TouchFile calls this. - // This is used only by Pepper/NaCl File API. - // - virtual void Touch( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time, - const StatusCallback& callback) = 0; - - // Truncates a file at |path| to |length|. If |length| is larger than - // the original file size, the file will be extended, and the extended - // part is filled with null bytes. - // - // FileSystemOperationImpl::Truncate calls this. - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if the file doesn't exist. - // - virtual void Truncate( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - int64 length, - const StatusCallback& callback) = 0; - - // Copies a file from |src_url| to |dest_url|. - // This must be called for files that belong to the same filesystem - // (i.e. type() and origin() of the |src_url| and |dest_url| must match). - // |progress_callback| is a callback to report the progress update. - // See file_system_operations.h for details. This should be called on the - // same thread as where the method's called (IO thread). Calling this - // is optional. It is recommended to use this callback for heavier operations - // (such as file network downloading), so that, e.g., clients (UIs) can - // update its state to show progress to users. This may be a null callback. - // - // FileSystemOperationImpl::Copy calls this for same-filesystem copy case. - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if |src_url| - // or the parent directory of |dest_url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. - // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - File::FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - virtual void CopyFileLocal( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback) = 0; - - // Moves a local file from |src_url| to |dest_url|. - // This must be called for files that belong to the same filesystem - // (i.e. type() and origin() of the |src_url| and |dest_url| must match). - // - // FileSystemOperationImpl::Move calls this for same-filesystem move case. - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if |src_url| - // or the parent directory of |dest_url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. - // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - File::FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - virtual void MoveFileLocal( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) = 0; - - // Copies in a single file from a different filesystem. - // - // FileSystemOperationImpl::Copy or Move calls this for cross-filesystem - // cases. - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if |src_file_path| - // or the parent directory of |dest_url| does not exist. - // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - File::FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - virtual void CopyInForeignFile( - scoped_ptr<FileSystemOperationContext> context, - const base::FilePath& src_file_path, - const FileSystemURL& dest_url, - const StatusCallback& callback) = 0; - - // Deletes a single file. - // - // FileSystemOperationImpl::RemoveFile calls this. - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if |url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |url| is not a file. - // - virtual void DeleteFile( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const StatusCallback& callback) = 0; - - // Removes a single empty directory. - // - // FileSystemOperationImpl::RemoveDirectory calls this. - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if |url| does not exist. - // - File::FILE_ERROR_NOT_A_DIRECTORY if |url| is not a directory. - // - File::FILE_ERROR_NOT_EMPTY if |url| is not empty. - // - virtual void DeleteDirectory( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const StatusCallback& callback) = 0; - - // Removes a single file or a single directory with its contents - // (i.e. files/subdirectories under the directory). - // - // FileSystemOperationImpl::Remove calls this. - // On some platforms, such as Chrome OS Drive File System, recursive file - // deletion can be implemented more efficiently than calling DeleteFile() and - // DeleteDirectory() for each files/directories. - // This method is optional, so if not supported, - // File::FILE_ERROR_INVALID_OPERATION should be returned via |callback|. - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if |url| does not exist. - // - File::FILE_ERROR_INVALID_OPERATION if this operation is not supported. - virtual void DeleteRecursively( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const StatusCallback& callback) = 0; - - // Creates a local snapshot file for a given |url| and returns the - // metadata and platform path of the snapshot file via |callback|. - // In regular filesystem cases the implementation may simply return - // the metadata of the file itself (as well as GetMetadata does), - // while in non-regular filesystem case the backend may create a - // temporary snapshot file which holds the file data and return - // the metadata of the temporary file. - // - // In the callback, it returns: - // |file_info| is the metadata of the snapshot file created. - // |platform_path| is the full absolute platform path to the snapshot - // file created. If a file is not backed by a real local file in - // the implementor's FileSystem, the implementor must create a - // local snapshot file and return the path of the created file. - // - // If implementors creates a temporary file for snapshotting and wants - // FileAPI backend to take care of the lifetime of the file (so that - // it won't get deleted while JS layer has any references to the created - // File/Blob object), it should return non-empty |file_ref|. - // Via the |file_ref| implementors can schedule a file deletion - // or arbitrary callbacks when the last reference of File/Blob is dropped. - // - // FileSystemOperationImpl::CreateSnapshotFile calls this. - // - // This reports following error code via |callback|: - // - File::FILE_ERROR_NOT_FOUND if |url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |url| exists but is a directory. - // - // The field values of |file_info| are undefined (implementation - // dependent) in error cases, and the caller should always - // check the return code. - virtual void CreateSnapshotFile( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const CreateSnapshotFileCallback& callback) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(AsyncFileUtil); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_ASYNC_FILE_UTIL_H_ +#include "storage/browser/fileapi/async_file_util.h" diff --git a/webkit/browser/fileapi/async_file_util_adapter.cc b/webkit/browser/fileapi/async_file_util_adapter.cc deleted file mode 100644 index 62244b7..0000000 --- a/webkit/browser/fileapi/async_file_util_adapter.cc +++ /dev/null @@ -1,352 +0,0 @@ -// Copyright (c) 2013 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/browser/fileapi/async_file_util_adapter.h" - -#include <vector> - -#include "base/bind.h" -#include "base/sequenced_task_runner.h" -#include "base/task_runner_util.h" -#include "base/thread_task_runner_handle.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_file_util.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/common/blob/shareable_file_reference.h" -#include "webkit/common/fileapi/file_system_util.h" - -using base::Bind; -using base::Callback; -using base::Owned; -using base::Unretained; -using storage::ShareableFileReference; - -namespace storage { - -namespace { - -class EnsureFileExistsHelper { - public: - EnsureFileExistsHelper() : error_(base::File::FILE_OK), created_(false) {} - - void RunWork(FileSystemFileUtil* file_util, - FileSystemOperationContext* context, - const FileSystemURL& url) { - error_ = file_util->EnsureFileExists(context, url, &created_); - } - - void Reply(const AsyncFileUtil::EnsureFileExistsCallback& callback) { - callback.Run(error_, created_); - } - - private: - base::File::Error error_; - bool created_; - DISALLOW_COPY_AND_ASSIGN(EnsureFileExistsHelper); -}; - -class GetFileInfoHelper { - public: - GetFileInfoHelper() - : error_(base::File::FILE_OK) {} - - void GetFileInfo(FileSystemFileUtil* file_util, - FileSystemOperationContext* context, - const FileSystemURL& url) { - error_ = file_util->GetFileInfo(context, url, &file_info_, &platform_path_); - } - - void CreateSnapshotFile(FileSystemFileUtil* file_util, - FileSystemOperationContext* context, - const FileSystemURL& url) { - scoped_file_ = file_util->CreateSnapshotFile( - context, url, &error_, &file_info_, &platform_path_); - } - - void ReplyFileInfo(const AsyncFileUtil::GetFileInfoCallback& callback) { - callback.Run(error_, file_info_); - } - - void ReplySnapshotFile( - const AsyncFileUtil::CreateSnapshotFileCallback& callback) { - callback.Run(error_, file_info_, platform_path_, - ShareableFileReference::GetOrCreate(scoped_file_.Pass())); - } - - private: - base::File::Error error_; - base::File::Info file_info_; - base::FilePath platform_path_; - storage::ScopedFile scoped_file_; - DISALLOW_COPY_AND_ASSIGN(GetFileInfoHelper); -}; - -void ReadDirectoryHelper(FileSystemFileUtil* file_util, - FileSystemOperationContext* context, - const FileSystemURL& url, - base::SingleThreadTaskRunner* origin_loop, - const AsyncFileUtil::ReadDirectoryCallback& callback) { - base::File::Info file_info; - base::FilePath platform_path; - base::File::Error error = file_util->GetFileInfo( - context, url, &file_info, &platform_path); - - if (error == base::File::FILE_OK && !file_info.is_directory) - error = base::File::FILE_ERROR_NOT_A_DIRECTORY; - - std::vector<DirectoryEntry> entries; - if (error != base::File::FILE_OK) { - origin_loop->PostTask( - FROM_HERE, base::Bind(callback, error, entries, false /* has_more */)); - return; - } - - // Note: Increasing this value may make some tests in LayoutTests meaningless. - // (Namely, read-directory-many.html and read-directory-sync-many.html are - // assuming that they are reading much more entries than this constant.) - const size_t kResultChunkSize = 100; - - scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum( - file_util->CreateFileEnumerator(context, url)); - - base::FilePath current; - while (!(current = file_enum->Next()).empty()) { - DirectoryEntry entry; - entry.is_directory = file_enum->IsDirectory(); - entry.name = VirtualPath::BaseName(current).value(); - entry.size = file_enum->Size(); - entry.last_modified_time = file_enum->LastModifiedTime(); - entries.push_back(entry); - - if (entries.size() == kResultChunkSize) { - origin_loop->PostTask( - FROM_HERE, base::Bind(callback, base::File::FILE_OK, entries, - true /* has_more */)); - entries.clear(); - } - } - origin_loop->PostTask( - FROM_HERE, base::Bind(callback, base::File::FILE_OK, entries, - false /* has_more */)); -} - -void RunCreateOrOpenCallback( - FileSystemOperationContext* context, - const AsyncFileUtil::CreateOrOpenCallback& callback, - base::File file) { - callback.Run(file.Pass(), base::Closure()); -} - -} // namespace - -AsyncFileUtilAdapter::AsyncFileUtilAdapter( - FileSystemFileUtil* sync_file_util) - : sync_file_util_(sync_file_util) { - DCHECK(sync_file_util_.get()); -} - -AsyncFileUtilAdapter::~AsyncFileUtilAdapter() { -} - -void AsyncFileUtilAdapter::CreateOrOpen( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - int file_flags, - const CreateOrOpenCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - base::PostTaskAndReplyWithResult( - context_ptr->task_runner(), - FROM_HERE, - Bind(&FileSystemFileUtil::CreateOrOpen, Unretained(sync_file_util_.get()), - context_ptr, url, file_flags), - Bind(&RunCreateOrOpenCallback, base::Owned(context_ptr), callback)); -} - -void AsyncFileUtilAdapter::EnsureFileExists( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const EnsureFileExistsCallback& callback) { - EnsureFileExistsHelper* helper = new EnsureFileExistsHelper; - FileSystemOperationContext* context_ptr = context.release(); - const bool success = context_ptr->task_runner()->PostTaskAndReply( - FROM_HERE, - Bind(&EnsureFileExistsHelper::RunWork, Unretained(helper), - sync_file_util_.get(), base::Owned(context_ptr), url), - Bind(&EnsureFileExistsHelper::Reply, Owned(helper), callback)); - DCHECK(success); -} - -void AsyncFileUtilAdapter::CreateDirectory( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - bool exclusive, - bool recursive, - const StatusCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - const bool success = base::PostTaskAndReplyWithResult( - context_ptr->task_runner(), FROM_HERE, - Bind(&FileSystemFileUtil::CreateDirectory, - Unretained(sync_file_util_.get()), - base::Owned(context_ptr), url, exclusive, recursive), - callback); - DCHECK(success); -} - -void AsyncFileUtilAdapter::GetFileInfo( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const GetFileInfoCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - GetFileInfoHelper* helper = new GetFileInfoHelper; - const bool success = context_ptr->task_runner()->PostTaskAndReply( - FROM_HERE, - Bind(&GetFileInfoHelper::GetFileInfo, Unretained(helper), - sync_file_util_.get(), base::Owned(context_ptr), url), - Bind(&GetFileInfoHelper::ReplyFileInfo, Owned(helper), callback)); - DCHECK(success); -} - -void AsyncFileUtilAdapter::ReadDirectory( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const ReadDirectoryCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - const bool success = context_ptr->task_runner()->PostTask( - FROM_HERE, - Bind(&ReadDirectoryHelper, - sync_file_util_.get(), base::Owned(context_ptr), url, - base::ThreadTaskRunnerHandle::Get(), callback)); - DCHECK(success); -} - -void AsyncFileUtilAdapter::Touch( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time, - const StatusCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - const bool success = base::PostTaskAndReplyWithResult( - context_ptr->task_runner(), FROM_HERE, - Bind(&FileSystemFileUtil::Touch, Unretained(sync_file_util_.get()), - base::Owned(context_ptr), url, - last_access_time, last_modified_time), - callback); - DCHECK(success); -} - -void AsyncFileUtilAdapter::Truncate( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - int64 length, - const StatusCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - const bool success = base::PostTaskAndReplyWithResult( - context_ptr->task_runner(), FROM_HERE, - Bind(&FileSystemFileUtil::Truncate, Unretained(sync_file_util_.get()), - base::Owned(context_ptr), url, length), - callback); - DCHECK(success); -} - -void AsyncFileUtilAdapter::CopyFileLocal( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback) { - // TODO(hidehiko): Support progress_callback. - FileSystemOperationContext* context_ptr = context.release(); - const bool success = base::PostTaskAndReplyWithResult( - context_ptr->task_runner(), FROM_HERE, - Bind(&FileSystemFileUtil::CopyOrMoveFile, - Unretained(sync_file_util_.get()), base::Owned(context_ptr), - src_url, dest_url, option, true /* copy */), - callback); - DCHECK(success); -} - -void AsyncFileUtilAdapter::MoveFileLocal( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - const bool success = base::PostTaskAndReplyWithResult( - context_ptr->task_runner(), FROM_HERE, - Bind(&FileSystemFileUtil::CopyOrMoveFile, - Unretained(sync_file_util_.get()), base::Owned(context_ptr), - src_url, dest_url, option, false /* copy */), - callback); - DCHECK(success); -} - -void AsyncFileUtilAdapter::CopyInForeignFile( - scoped_ptr<FileSystemOperationContext> context, - const base::FilePath& src_file_path, - const FileSystemURL& dest_url, - const StatusCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - const bool success = base::PostTaskAndReplyWithResult( - context_ptr->task_runner(), FROM_HERE, - Bind(&FileSystemFileUtil::CopyInForeignFile, - Unretained(sync_file_util_.get()), - base::Owned(context_ptr), src_file_path, dest_url), - callback); - DCHECK(success); -} - -void AsyncFileUtilAdapter::DeleteFile( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const StatusCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - const bool success = base::PostTaskAndReplyWithResult( - context_ptr->task_runner(), FROM_HERE, - Bind(&FileSystemFileUtil::DeleteFile, - Unretained(sync_file_util_.get()), - base::Owned(context_ptr), url), - callback); - DCHECK(success); -} - -void AsyncFileUtilAdapter::DeleteDirectory( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const StatusCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - const bool success = base::PostTaskAndReplyWithResult( - context_ptr->task_runner(), FROM_HERE, - Bind(&FileSystemFileUtil::DeleteDirectory, - Unretained(sync_file_util_.get()), - base::Owned(context_ptr), url), - callback); - DCHECK(success); -} - -void AsyncFileUtilAdapter::DeleteRecursively( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const StatusCallback& callback) { - callback.Run(base::File::FILE_ERROR_INVALID_OPERATION); -} - -void AsyncFileUtilAdapter::CreateSnapshotFile( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const CreateSnapshotFileCallback& callback) { - FileSystemOperationContext* context_ptr = context.release(); - GetFileInfoHelper* helper = new GetFileInfoHelper; - const bool success = context_ptr->task_runner()->PostTaskAndReply( - FROM_HERE, - Bind(&GetFileInfoHelper::CreateSnapshotFile, Unretained(helper), - sync_file_util_.get(), base::Owned(context_ptr), url), - Bind(&GetFileInfoHelper::ReplySnapshotFile, Owned(helper), callback)); - DCHECK(success); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/async_file_util_adapter.h b/webkit/browser/fileapi/async_file_util_adapter.h index 1056035..f69908c 100644 --- a/webkit/browser/fileapi/async_file_util_adapter.h +++ b/webkit/browser/fileapi/async_file_util_adapter.h @@ -1,118 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_ASYNC_FILE_UTIL_ADAPTER_H_ -#define WEBKIT_BROWSER_FILEAPI_ASYNC_FILE_UTIL_ADAPTER_H_ - -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/async_file_util.h" - -namespace storage { - -class FileSystemFileUtil; - -// An adapter class for FileSystemFileUtil classes to provide asynchronous -// interface. -// -// A filesystem can do either: -// - implement a synchronous version of FileUtil by extending -// FileSystemFileUtil and atach it to this adapter, or -// - directly implement AsyncFileUtil. -// -// This instance (as thus this->sync_file_util_) is guaranteed to be alive -// as far as FileSystemOperationContext given to each operation is kept alive. -class STORAGE_EXPORT AsyncFileUtilAdapter - : public NON_EXPORTED_BASE(AsyncFileUtil) { - public: - // Creates a new AsyncFileUtil for |sync_file_util|. This takes the - // ownership of |sync_file_util|. (This doesn't take scoped_ptr<> just - // to save extra make_scoped_ptr; in all use cases a new fresh FileUtil is - // created only for this adapter.) - explicit AsyncFileUtilAdapter(FileSystemFileUtil* sync_file_util); - - virtual ~AsyncFileUtilAdapter(); - - FileSystemFileUtil* sync_file_util() { - return sync_file_util_.get(); - } - - // AsyncFileUtil overrides. - virtual void CreateOrOpen( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - int file_flags, - const CreateOrOpenCallback& callback) OVERRIDE; - virtual void EnsureFileExists( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const EnsureFileExistsCallback& callback) OVERRIDE; - virtual void CreateDirectory( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - bool exclusive, - bool recursive, - const StatusCallback& callback) OVERRIDE; - virtual void GetFileInfo( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const GetFileInfoCallback& callback) OVERRIDE; - virtual void ReadDirectory( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const ReadDirectoryCallback& callback) OVERRIDE; - virtual void Touch( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time, - const StatusCallback& callback) OVERRIDE; - virtual void Truncate( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - int64 length, - const StatusCallback& callback) OVERRIDE; - virtual void CopyFileLocal( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback) OVERRIDE; - virtual void MoveFileLocal( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) OVERRIDE; - virtual void CopyInForeignFile( - scoped_ptr<FileSystemOperationContext> context, - const base::FilePath& src_file_path, - const FileSystemURL& dest_url, - const StatusCallback& callback) OVERRIDE; - virtual void DeleteFile( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void DeleteDirectory( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void DeleteRecursively( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void CreateSnapshotFile( - scoped_ptr<FileSystemOperationContext> context, - const FileSystemURL& url, - const CreateSnapshotFileCallback& callback) OVERRIDE; - - private: - scoped_ptr<FileSystemFileUtil> sync_file_util_; - - DISALLOW_COPY_AND_ASSIGN(AsyncFileUtilAdapter); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_ASYNC_FILE_UTIL_ADAPTER_H_ +#include "storage/browser/fileapi/async_file_util_adapter.h" diff --git a/webkit/browser/fileapi/copy_or_move_file_validator.h b/webkit/browser/fileapi/copy_or_move_file_validator.h index 9ade9e5..2d5c629 100644 --- a/webkit/browser/fileapi/copy_or_move_file_validator.h +++ b/webkit/browser/fileapi/copy_or_move_file_validator.h @@ -1,54 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_COPY_OR_MOVE_FILE_VALIDATOR_H_ -#define WEBKIT_BROWSER_FILEAPI_COPY_OR_MOVE_FILE_VALIDATOR_H_ - -#include "base/callback.h" -#include "base/files/file.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class FilePath; -} - -namespace storage { - -class FileSystemURL; - -class STORAGE_EXPORT CopyOrMoveFileValidator { - public: - // Callback that is invoked when validation completes. A result of - // base::File::FILE_OK means the file validated. - typedef base::Callback<void(base::File::Error result)> ResultCallback; - - virtual ~CopyOrMoveFileValidator() {} - - // Called on a source file before copying or moving to the final - // destination. - virtual void StartPreWriteValidation( - const ResultCallback& result_callback) = 0; - - // Called on a destination file after copying or moving to the final - // destination. Suitable for running Anti-Virus checks. - virtual void StartPostWriteValidation( - const base::FilePath& dest_platform_path, - const ResultCallback& result_callback) = 0; -}; - -class CopyOrMoveFileValidatorFactory { - public: - virtual ~CopyOrMoveFileValidatorFactory() {} - - // This method must always return a non-NULL validator. |src_url| is needed - // in addition to |platform_path| because in the obfuscated file system - // case, |platform_path| will be an obfuscated filename and extension. - virtual CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator( - const FileSystemURL& src_url, - const base::FilePath& platform_path) = 0; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_COPY_OR_MOVE_FILE_VALIDATOR_H_ +#include "storage/browser/fileapi/copy_or_move_file_validator.h" diff --git a/webkit/browser/fileapi/copy_or_move_operation_delegate.cc b/webkit/browser/fileapi/copy_or_move_operation_delegate.cc deleted file mode 100644 index 84a6472..0000000 --- a/webkit/browser/fileapi/copy_or_move_operation_delegate.cc +++ /dev/null @@ -1,1034 +0,0 @@ -// Copyright (c) 2013 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/browser/fileapi/copy_or_move_operation_delegate.h" - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/copy_or_move_file_validator.h" -#include "webkit/browser/fileapi/file_observers.h" -#include "webkit/browser/fileapi/file_stream_writer.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_runner.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/recursive_operation_delegate.h" -#include "webkit/common/blob/shareable_file_reference.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace storage { - -const int64 kFlushIntervalInBytes = 10 << 20; // 10MB. - -class CopyOrMoveOperationDelegate::CopyOrMoveImpl { - public: - virtual ~CopyOrMoveImpl() {} - virtual void Run( - const CopyOrMoveOperationDelegate::StatusCallback& callback) = 0; - virtual void Cancel() = 0; - - protected: - CopyOrMoveImpl() {} - - private: - DISALLOW_COPY_AND_ASSIGN(CopyOrMoveImpl); -}; - -namespace { - -// Copies a file on a (same) file system. Just delegate the operation to -// |operation_runner|. -class CopyOrMoveOnSameFileSystemImpl - : public CopyOrMoveOperationDelegate::CopyOrMoveImpl { - public: - CopyOrMoveOnSameFileSystemImpl( - FileSystemOperationRunner* operation_runner, - CopyOrMoveOperationDelegate::OperationType operation_type, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOperationDelegate::CopyOrMoveOption option, - const FileSystemOperation::CopyFileProgressCallback& - file_progress_callback) - : operation_runner_(operation_runner), - operation_type_(operation_type), - src_url_(src_url), - dest_url_(dest_url), - option_(option), - file_progress_callback_(file_progress_callback) { - } - - virtual void Run( - const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE { - if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_MOVE) { - operation_runner_->MoveFileLocal(src_url_, dest_url_, option_, callback); - } else { - operation_runner_->CopyFileLocal( - src_url_, dest_url_, option_, file_progress_callback_, callback); - } - } - - virtual void Cancel() OVERRIDE { - // We can do nothing for the copy/move operation on a local file system. - // Assuming the operation is quickly done, it should be ok to just wait - // for the completion. - } - - private: - FileSystemOperationRunner* operation_runner_; - CopyOrMoveOperationDelegate::OperationType operation_type_; - FileSystemURL src_url_; - FileSystemURL dest_url_; - CopyOrMoveOperationDelegate::CopyOrMoveOption option_; - FileSystemOperation::CopyFileProgressCallback file_progress_callback_; - DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOnSameFileSystemImpl); -}; - -// Specifically for cross file system copy/move operation, this class creates -// a snapshot file, validates it if necessary, runs copying process, -// validates the created file, and removes source file for move (noop for -// copy). -class SnapshotCopyOrMoveImpl - : public CopyOrMoveOperationDelegate::CopyOrMoveImpl { - public: - SnapshotCopyOrMoveImpl( - FileSystemOperationRunner* operation_runner, - CopyOrMoveOperationDelegate::OperationType operation_type, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOperationDelegate::CopyOrMoveOption option, - CopyOrMoveFileValidatorFactory* validator_factory, - const FileSystemOperation::CopyFileProgressCallback& - file_progress_callback) - : operation_runner_(operation_runner), - operation_type_(operation_type), - src_url_(src_url), - dest_url_(dest_url), - option_(option), - validator_factory_(validator_factory), - file_progress_callback_(file_progress_callback), - cancel_requested_(false), - weak_factory_(this) { - } - - virtual void Run( - const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE { - file_progress_callback_.Run(0); - operation_runner_->CreateSnapshotFile( - src_url_, - base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCreateSnapshot, - weak_factory_.GetWeakPtr(), callback)); - } - - virtual void Cancel() OVERRIDE { - cancel_requested_ = true; - } - - private: - void RunAfterCreateSnapshot( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error, - const base::File::Info& file_info, - const base::FilePath& platform_path, - const scoped_refptr<storage::ShareableFileReference>& file_ref) { - if (cancel_requested_) - error = base::File::FILE_ERROR_ABORT; - - if (error != base::File::FILE_OK) { - callback.Run(error); - return; - } - - // For now we assume CreateSnapshotFile always return a valid local file - // path. - DCHECK(!platform_path.empty()); - - if (!validator_factory_) { - // No validation is needed. - RunAfterPreWriteValidation(platform_path, file_info, file_ref, callback, - base::File::FILE_OK); - return; - } - - // Run pre write validation. - PreWriteValidation( - platform_path, - base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPreWriteValidation, - weak_factory_.GetWeakPtr(), - platform_path, file_info, file_ref, callback)); - } - - void RunAfterPreWriteValidation( - const base::FilePath& platform_path, - const base::File::Info& file_info, - const scoped_refptr<storage::ShareableFileReference>& file_ref, - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error) { - if (cancel_requested_) - error = base::File::FILE_ERROR_ABORT; - - if (error != base::File::FILE_OK) { - callback.Run(error); - return; - } - - // |file_ref| is unused but necessary to keep the file alive until - // CopyInForeignFile() is completed. - operation_runner_->CopyInForeignFile( - platform_path, dest_url_, - base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCopyInForeignFile, - weak_factory_.GetWeakPtr(), file_info, file_ref, callback)); - } - - void RunAfterCopyInForeignFile( - const base::File::Info& file_info, - const scoped_refptr<storage::ShareableFileReference>& file_ref, - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error) { - if (cancel_requested_) - error = base::File::FILE_ERROR_ABORT; - - if (error != base::File::FILE_OK) { - callback.Run(error); - return; - } - - file_progress_callback_.Run(file_info.size); - - if (option_ == FileSystemOperation::OPTION_NONE) { - RunAfterTouchFile(callback, base::File::FILE_OK); - return; - } - - operation_runner_->TouchFile( - dest_url_, base::Time::Now() /* last_access */, - file_info.last_modified, - base::Bind(&SnapshotCopyOrMoveImpl::RunAfterTouchFile, - weak_factory_.GetWeakPtr(), callback)); - } - - void RunAfterTouchFile( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error) { - // Even if TouchFile is failed, just ignore it. - - if (cancel_requested_) { - callback.Run(base::File::FILE_ERROR_ABORT); - return; - } - - // |validator_| is NULL when the destination filesystem does not do - // validation. - if (!validator_) { - // No validation is needed. - RunAfterPostWriteValidation(callback, base::File::FILE_OK); - return; - } - - PostWriteValidation( - base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPostWriteValidation, - weak_factory_.GetWeakPtr(), callback)); - } - - void RunAfterPostWriteValidation( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error) { - if (cancel_requested_) { - callback.Run(base::File::FILE_ERROR_ABORT); - return; - } - - if (error != base::File::FILE_OK) { - // Failed to validate. Remove the destination file. - operation_runner_->Remove( - dest_url_, true /* recursive */, - base::Bind(&SnapshotCopyOrMoveImpl::DidRemoveDestForError, - weak_factory_.GetWeakPtr(), error, callback)); - return; - } - - if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) { - callback.Run(base::File::FILE_OK); - return; - } - - DCHECK_EQ(CopyOrMoveOperationDelegate::OPERATION_MOVE, operation_type_); - - // Remove the source for finalizing move operation. - operation_runner_->Remove( - src_url_, true /* recursive */, - base::Bind(&SnapshotCopyOrMoveImpl::RunAfterRemoveSourceForMove, - weak_factory_.GetWeakPtr(), callback)); - } - - void RunAfterRemoveSourceForMove( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error) { - if (cancel_requested_) - error = base::File::FILE_ERROR_ABORT; - - if (error == base::File::FILE_ERROR_NOT_FOUND) - error = base::File::FILE_OK; - callback.Run(error); - } - - void DidRemoveDestForError( - base::File::Error prior_error, - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error) { - if (error != base::File::FILE_OK) { - VLOG(1) << "Error removing destination file after validation error: " - << error; - } - callback.Run(prior_error); - } - - // Runs pre-write validation. - void PreWriteValidation( - const base::FilePath& platform_path, - const CopyOrMoveOperationDelegate::StatusCallback& callback) { - DCHECK(validator_factory_); - validator_.reset( - validator_factory_->CreateCopyOrMoveFileValidator( - src_url_, platform_path)); - validator_->StartPreWriteValidation(callback); - } - - // Runs post-write validation. - void PostWriteValidation( - const CopyOrMoveOperationDelegate::StatusCallback& callback) { - operation_runner_->CreateSnapshotFile( - dest_url_, - base::Bind( - &SnapshotCopyOrMoveImpl::PostWriteValidationAfterCreateSnapshotFile, - weak_factory_.GetWeakPtr(), callback)); - } - - void PostWriteValidationAfterCreateSnapshotFile( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error, - const base::File::Info& file_info, - const base::FilePath& platform_path, - const scoped_refptr<storage::ShareableFileReference>& file_ref) { - if (cancel_requested_) - error = base::File::FILE_ERROR_ABORT; - - if (error != base::File::FILE_OK) { - callback.Run(error); - return; - } - - DCHECK(validator_); - // Note: file_ref passed here to keep the file alive until after - // the StartPostWriteValidation operation finishes. - validator_->StartPostWriteValidation( - platform_path, - base::Bind(&SnapshotCopyOrMoveImpl::DidPostWriteValidation, - weak_factory_.GetWeakPtr(), file_ref, callback)); - } - - // |file_ref| is unused; it is passed here to make sure the reference is - // alive until after post-write validation is complete. - void DidPostWriteValidation( - const scoped_refptr<storage::ShareableFileReference>& file_ref, - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error) { - callback.Run(error); - } - - FileSystemOperationRunner* operation_runner_; - CopyOrMoveOperationDelegate::OperationType operation_type_; - FileSystemURL src_url_; - FileSystemURL dest_url_; - - CopyOrMoveOperationDelegate::CopyOrMoveOption option_; - CopyOrMoveFileValidatorFactory* validator_factory_; - scoped_ptr<CopyOrMoveFileValidator> validator_; - FileSystemOperation::CopyFileProgressCallback file_progress_callback_; - bool cancel_requested_; - base::WeakPtrFactory<SnapshotCopyOrMoveImpl> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(SnapshotCopyOrMoveImpl); -}; - -// The size of buffer for StreamCopyHelper. -const int kReadBufferSize = 32768; - -// To avoid too many progress callbacks, it should be called less -// frequently than 50ms. -const int kMinProgressCallbackInvocationSpanInMilliseconds = 50; - -// Specifically for cross file system copy/move operation, this class uses -// stream reader and writer for copying. Validator is not supported, so if -// necessary SnapshotCopyOrMoveImpl should be used. -class StreamCopyOrMoveImpl - : public CopyOrMoveOperationDelegate::CopyOrMoveImpl { - public: - StreamCopyOrMoveImpl( - FileSystemOperationRunner* operation_runner, - FileSystemContext* file_system_context, - CopyOrMoveOperationDelegate::OperationType operation_type, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOperationDelegate::CopyOrMoveOption option, - scoped_ptr<storage::FileStreamReader> reader, - scoped_ptr<FileStreamWriter> writer, - const FileSystemOperation::CopyFileProgressCallback& - file_progress_callback) - : operation_runner_(operation_runner), - file_system_context_(file_system_context), - operation_type_(operation_type), - src_url_(src_url), - dest_url_(dest_url), - option_(option), - reader_(reader.Pass()), - writer_(writer.Pass()), - file_progress_callback_(file_progress_callback), - cancel_requested_(false), - weak_factory_(this) {} - - virtual void Run( - const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE { - // Reader can be created even if the entry does not exist or the entry is - // a directory. To check errors before destination file creation, - // check metadata first. - operation_runner_->GetMetadata( - src_url_, - base::Bind(&StreamCopyOrMoveImpl::RunAfterGetMetadataForSource, - weak_factory_.GetWeakPtr(), callback)); - } - - virtual void Cancel() OVERRIDE { - cancel_requested_ = true; - if (copy_helper_) - copy_helper_->Cancel(); - } - - private: - void NotifyOnStartUpdate(const FileSystemURL& url) { - if (file_system_context_->GetUpdateObservers(url.type())) { - file_system_context_->GetUpdateObservers(url.type()) - ->Notify(&FileUpdateObserver::OnStartUpdate, MakeTuple(url)); - } - } - - void NotifyOnModifyFile(const FileSystemURL& url) { - if (file_system_context_->GetChangeObservers(url.type())) { - file_system_context_->GetChangeObservers(url.type()) - ->Notify(&FileChangeObserver::OnModifyFile, MakeTuple(url)); - } - } - - void NotifyOnEndUpdate(const FileSystemURL& url) { - if (file_system_context_->GetUpdateObservers(url.type())) { - file_system_context_->GetUpdateObservers(url.type()) - ->Notify(&FileUpdateObserver::OnEndUpdate, MakeTuple(url)); - } - } - - void RunAfterGetMetadataForSource( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error, - const base::File::Info& file_info) { - if (cancel_requested_) - error = base::File::FILE_ERROR_ABORT; - - if (error != base::File::FILE_OK) { - callback.Run(error); - return; - } - - if (file_info.is_directory) { - // If not a directory, failed with appropriate error code. - callback.Run(base::File::FILE_ERROR_NOT_A_FILE); - return; - } - - // To use FileStreamWriter, we need to ensure the destination file exists. - operation_runner_->CreateFile( - dest_url_, - true /* exclusive */, - base::Bind(&StreamCopyOrMoveImpl::RunAfterCreateFileForDestination, - weak_factory_.GetWeakPtr(), - callback, - file_info.last_modified)); - } - - void RunAfterCreateFileForDestination( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - const base::Time& last_modified, - base::File::Error error) { - if (cancel_requested_) - error = base::File::FILE_ERROR_ABORT; - // This conversion is to return the consistent status code with - // FileSystemFileUtil::Copy. - if (error == base::File::FILE_ERROR_NOT_A_FILE) - error = base::File::FILE_ERROR_INVALID_OPERATION; - - if (error != base::File::FILE_OK && - error != base::File::FILE_ERROR_EXISTS) { - callback.Run(error); - return; - } - - if (error == base::File::FILE_ERROR_EXISTS) { - operation_runner_->Truncate( - dest_url_, - 0 /* length */, - base::Bind(&StreamCopyOrMoveImpl::RunAfterTruncateForDestination, - weak_factory_.GetWeakPtr(), - callback, - last_modified)); - return; - } - RunAfterTruncateForDestination( - callback, last_modified, base::File::FILE_OK); - } - - void RunAfterTruncateForDestination( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - const base::Time& last_modified, - base::File::Error error) { - if (cancel_requested_) - error = base::File::FILE_ERROR_ABORT; - - if (error != base::File::FILE_OK) { - callback.Run(error); - return; - } - - const bool need_flush = dest_url_.mount_option().copy_sync_option() == - storage::COPY_SYNC_OPTION_SYNC; - - NotifyOnStartUpdate(dest_url_); - DCHECK(!copy_helper_); - copy_helper_.reset( - new CopyOrMoveOperationDelegate::StreamCopyHelper( - reader_.Pass(), writer_.Pass(), - need_flush, - kReadBufferSize, - file_progress_callback_, - base::TimeDelta::FromMilliseconds( - kMinProgressCallbackInvocationSpanInMilliseconds))); - copy_helper_->Run( - base::Bind(&StreamCopyOrMoveImpl::RunAfterStreamCopy, - weak_factory_.GetWeakPtr(), callback, last_modified)); - } - - void RunAfterStreamCopy( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - const base::Time& last_modified, - base::File::Error error) { - NotifyOnModifyFile(dest_url_); - NotifyOnEndUpdate(dest_url_); - if (cancel_requested_) - error = base::File::FILE_ERROR_ABORT; - - if (error != base::File::FILE_OK) { - callback.Run(error); - return; - } - - if (option_ == FileSystemOperation::OPTION_NONE) { - RunAfterTouchFile(callback, base::File::FILE_OK); - return; - } - - operation_runner_->TouchFile( - dest_url_, base::Time::Now() /* last_access */, last_modified, - base::Bind(&StreamCopyOrMoveImpl::RunAfterTouchFile, - weak_factory_.GetWeakPtr(), callback)); - } - - void RunAfterTouchFile( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error) { - // Even if TouchFile is failed, just ignore it. - if (cancel_requested_) { - callback.Run(base::File::FILE_ERROR_ABORT); - return; - } - - if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) { - callback.Run(base::File::FILE_OK); - return; - } - - DCHECK_EQ(CopyOrMoveOperationDelegate::OPERATION_MOVE, operation_type_); - - // Remove the source for finalizing move operation. - operation_runner_->Remove( - src_url_, false /* recursive */, - base::Bind(&StreamCopyOrMoveImpl::RunAfterRemoveForMove, - weak_factory_.GetWeakPtr(), callback)); - } - - void RunAfterRemoveForMove( - const CopyOrMoveOperationDelegate::StatusCallback& callback, - base::File::Error error) { - if (cancel_requested_) - error = base::File::FILE_ERROR_ABORT; - if (error == base::File::FILE_ERROR_NOT_FOUND) - error = base::File::FILE_OK; - callback.Run(error); - } - - FileSystemOperationRunner* operation_runner_; - scoped_refptr<FileSystemContext> file_system_context_; - CopyOrMoveOperationDelegate::OperationType operation_type_; - FileSystemURL src_url_; - FileSystemURL dest_url_; - CopyOrMoveOperationDelegate::CopyOrMoveOption option_; - scoped_ptr<storage::FileStreamReader> reader_; - scoped_ptr<FileStreamWriter> writer_; - FileSystemOperation::CopyFileProgressCallback file_progress_callback_; - scoped_ptr<CopyOrMoveOperationDelegate::StreamCopyHelper> copy_helper_; - bool cancel_requested_; - base::WeakPtrFactory<StreamCopyOrMoveImpl> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(StreamCopyOrMoveImpl); -}; - -} // namespace - -CopyOrMoveOperationDelegate::StreamCopyHelper::StreamCopyHelper( - scoped_ptr<storage::FileStreamReader> reader, - scoped_ptr<FileStreamWriter> writer, - bool need_flush, - int buffer_size, - const FileSystemOperation::CopyFileProgressCallback& file_progress_callback, - const base::TimeDelta& min_progress_callback_invocation_span) - : reader_(reader.Pass()), - writer_(writer.Pass()), - need_flush_(need_flush), - file_progress_callback_(file_progress_callback), - io_buffer_(new net::IOBufferWithSize(buffer_size)), - num_copied_bytes_(0), - previous_flush_offset_(0), - min_progress_callback_invocation_span_( - min_progress_callback_invocation_span), - cancel_requested_(false), - weak_factory_(this) { -} - -CopyOrMoveOperationDelegate::StreamCopyHelper::~StreamCopyHelper() { -} - -void CopyOrMoveOperationDelegate::StreamCopyHelper::Run( - const StatusCallback& callback) { - file_progress_callback_.Run(0); - last_progress_callback_invocation_time_ = base::Time::Now(); - Read(callback); -} - -void CopyOrMoveOperationDelegate::StreamCopyHelper::Cancel() { - cancel_requested_ = true; -} - -void CopyOrMoveOperationDelegate::StreamCopyHelper::Read( - const StatusCallback& callback) { - int result = reader_->Read( - io_buffer_.get(), io_buffer_->size(), - base::Bind(&StreamCopyHelper::DidRead, - weak_factory_.GetWeakPtr(), callback)); - if (result != net::ERR_IO_PENDING) - DidRead(callback, result); -} - -void CopyOrMoveOperationDelegate::StreamCopyHelper::DidRead( - const StatusCallback& callback, int result) { - if (cancel_requested_) { - callback.Run(base::File::FILE_ERROR_ABORT); - return; - } - - if (result < 0) { - callback.Run(NetErrorToFileError(result)); - return; - } - - if (result == 0) { - // Here is the EOF. - if (need_flush_) - Flush(callback, true /* is_eof */); - else - callback.Run(base::File::FILE_OK); - return; - } - - Write(callback, new net::DrainableIOBuffer(io_buffer_.get(), result)); -} - -void CopyOrMoveOperationDelegate::StreamCopyHelper::Write( - const StatusCallback& callback, - scoped_refptr<net::DrainableIOBuffer> buffer) { - DCHECK_GT(buffer->BytesRemaining(), 0); - - int result = writer_->Write( - buffer.get(), buffer->BytesRemaining(), - base::Bind(&StreamCopyHelper::DidWrite, - weak_factory_.GetWeakPtr(), callback, buffer)); - if (result != net::ERR_IO_PENDING) - DidWrite(callback, buffer, result); -} - -void CopyOrMoveOperationDelegate::StreamCopyHelper::DidWrite( - const StatusCallback& callback, - scoped_refptr<net::DrainableIOBuffer> buffer, - int result) { - if (cancel_requested_) { - callback.Run(base::File::FILE_ERROR_ABORT); - return; - } - - if (result < 0) { - callback.Run(NetErrorToFileError(result)); - return; - } - - buffer->DidConsume(result); - num_copied_bytes_ += result; - - // Check the elapsed time since last |file_progress_callback_| invocation. - base::Time now = base::Time::Now(); - if (now - last_progress_callback_invocation_time_ >= - min_progress_callback_invocation_span_) { - file_progress_callback_.Run(num_copied_bytes_); - last_progress_callback_invocation_time_ = now; - } - - if (buffer->BytesRemaining() > 0) { - Write(callback, buffer); - return; - } - - if (need_flush_ && - (num_copied_bytes_ - previous_flush_offset_) > kFlushIntervalInBytes) { - Flush(callback, false /* not is_eof */); - } else { - Read(callback); - } -} - -void CopyOrMoveOperationDelegate::StreamCopyHelper::Flush( - const StatusCallback& callback, bool is_eof) { - int result = writer_->Flush( - base::Bind(&StreamCopyHelper::DidFlush, - weak_factory_.GetWeakPtr(), callback, is_eof)); - if (result != net::ERR_IO_PENDING) - DidFlush(callback, is_eof, result); -} - -void CopyOrMoveOperationDelegate::StreamCopyHelper::DidFlush( - const StatusCallback& callback, bool is_eof, int result) { - if (cancel_requested_) { - callback.Run(base::File::FILE_ERROR_ABORT); - return; - } - - previous_flush_offset_ = num_copied_bytes_; - if (is_eof) - callback.Run(NetErrorToFileError(result)); - else - Read(callback); -} - -CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate( - FileSystemContext* file_system_context, - const FileSystemURL& src_root, - const FileSystemURL& dest_root, - OperationType operation_type, - CopyOrMoveOption option, - const CopyProgressCallback& progress_callback, - const StatusCallback& callback) - : RecursiveOperationDelegate(file_system_context), - src_root_(src_root), - dest_root_(dest_root), - operation_type_(operation_type), - option_(option), - progress_callback_(progress_callback), - callback_(callback), - weak_factory_(this) { - same_file_system_ = src_root_.IsInSameFileSystem(dest_root_); -} - -CopyOrMoveOperationDelegate::~CopyOrMoveOperationDelegate() { - STLDeleteElements(&running_copy_set_); -} - -void CopyOrMoveOperationDelegate::Run() { - // Not supported; this should never be called. - NOTREACHED(); -} - -void CopyOrMoveOperationDelegate::RunRecursively() { - // Perform light-weight checks first. - - // It is an error to try to copy/move an entry into its child. - if (same_file_system_ && src_root_.path().IsParent(dest_root_.path())) { - callback_.Run(base::File::FILE_ERROR_INVALID_OPERATION); - return; - } - - if (same_file_system_ && src_root_.path() == dest_root_.path()) { - // In JS API this should return error, but we return success because Pepper - // wants to return success and we have a code path that returns error in - // Blink for JS (http://crbug.com/329517). - callback_.Run(base::File::FILE_OK); - return; - } - - // Start to process the source directory recursively. - // TODO(kinuko): This could be too expensive for same_file_system_==true - // and operation==MOVE case, probably we can just rename the root directory. - // http://crbug.com/172187 - StartRecursiveOperation(src_root_, callback_); -} - -void CopyOrMoveOperationDelegate::ProcessFile( - const FileSystemURL& src_url, - const StatusCallback& callback) { - if (!progress_callback_.is_null()) { - progress_callback_.Run( - FileSystemOperation::BEGIN_COPY_ENTRY, src_url, FileSystemURL(), 0); - } - - FileSystemURL dest_url = CreateDestURL(src_url); - CopyOrMoveImpl* impl = NULL; - if (same_file_system_ && - (file_system_context() - ->GetFileSystemBackend(src_url.type()) - ->HasInplaceCopyImplementation(src_url.type()) || - operation_type_ == OperationType::OPERATION_MOVE)) { - impl = new CopyOrMoveOnSameFileSystemImpl( - operation_runner(), operation_type_, src_url, dest_url, option_, - base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress, - weak_factory_.GetWeakPtr(), src_url)); - } else { - // Cross filesystem case. - base::File::Error error = base::File::FILE_ERROR_FAILED; - CopyOrMoveFileValidatorFactory* validator_factory = - file_system_context()->GetCopyOrMoveFileValidatorFactory( - dest_root_.type(), &error); - if (error != base::File::FILE_OK) { - callback.Run(error); - return; - } - - if (!validator_factory) { - scoped_ptr<storage::FileStreamReader> reader = - file_system_context()->CreateFileStreamReader( - src_url, 0, base::Time()); - scoped_ptr<FileStreamWriter> writer = - file_system_context()->CreateFileStreamWriter(dest_url, 0); - if (reader && writer) { - impl = new StreamCopyOrMoveImpl( - operation_runner(), - file_system_context(), - operation_type_, - src_url, - dest_url, - option_, - reader.Pass(), - writer.Pass(), - base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress, - weak_factory_.GetWeakPtr(), - src_url)); - } - } - - if (!impl) { - impl = new SnapshotCopyOrMoveImpl( - operation_runner(), operation_type_, src_url, dest_url, option_, - validator_factory, - base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress, - weak_factory_.GetWeakPtr(), src_url)); - } - } - - // Register the running task. - running_copy_set_.insert(impl); - impl->Run(base::Bind( - &CopyOrMoveOperationDelegate::DidCopyOrMoveFile, - weak_factory_.GetWeakPtr(), src_url, dest_url, callback, impl)); -} - -void CopyOrMoveOperationDelegate::ProcessDirectory( - const FileSystemURL& src_url, - const StatusCallback& callback) { - if (src_url == src_root_) { - // The src_root_ looks to be a directory. - // Try removing the dest_root_ to see if it exists and/or it is an - // empty directory. - // We do not invoke |progress_callback_| for source root, because it is - // already called in ProcessFile(). - operation_runner()->RemoveDirectory( - dest_root_, - base::Bind(&CopyOrMoveOperationDelegate::DidTryRemoveDestRoot, - weak_factory_.GetWeakPtr(), callback)); - return; - } - - if (!progress_callback_.is_null()) { - progress_callback_.Run( - FileSystemOperation::BEGIN_COPY_ENTRY, src_url, FileSystemURL(), 0); - } - - ProcessDirectoryInternal(src_url, CreateDestURL(src_url), callback); -} - -void CopyOrMoveOperationDelegate::PostProcessDirectory( - const FileSystemURL& src_url, - const StatusCallback& callback) { - if (option_ == FileSystemOperation::OPTION_NONE) { - PostProcessDirectoryAfterTouchFile( - src_url, callback, base::File::FILE_OK); - return; - } - - operation_runner()->GetMetadata( - src_url, - base::Bind( - &CopyOrMoveOperationDelegate::PostProcessDirectoryAfterGetMetadata, - weak_factory_.GetWeakPtr(), src_url, callback)); -} - -void CopyOrMoveOperationDelegate::OnCancel() { - // Request to cancel all running Copy/Move file. - for (std::set<CopyOrMoveImpl*>::iterator iter = running_copy_set_.begin(); - iter != running_copy_set_.end(); ++iter) - (*iter)->Cancel(); -} - -void CopyOrMoveOperationDelegate::DidCopyOrMoveFile( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - const StatusCallback& callback, - CopyOrMoveImpl* impl, - base::File::Error error) { - running_copy_set_.erase(impl); - delete impl; - - if (!progress_callback_.is_null() && error == base::File::FILE_OK) { - progress_callback_.Run( - FileSystemOperation::END_COPY_ENTRY, src_url, dest_url, 0); - } - - callback.Run(error); -} - -void CopyOrMoveOperationDelegate::DidTryRemoveDestRoot( - const StatusCallback& callback, - base::File::Error error) { - if (error == base::File::FILE_ERROR_NOT_A_DIRECTORY) { - callback_.Run(base::File::FILE_ERROR_INVALID_OPERATION); - return; - } - if (error != base::File::FILE_OK && - error != base::File::FILE_ERROR_NOT_FOUND) { - callback_.Run(error); - return; - } - - ProcessDirectoryInternal(src_root_, dest_root_, callback); -} - -void CopyOrMoveOperationDelegate::ProcessDirectoryInternal( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - const StatusCallback& callback) { - // If operation_type == Move we may need to record directories and - // restore directory timestamps in the end, though it may have - // negative performance impact. - // See http://crbug.com/171284 for more details. - operation_runner()->CreateDirectory( - dest_url, false /* exclusive */, false /* recursive */, - base::Bind(&CopyOrMoveOperationDelegate::DidCreateDirectory, - weak_factory_.GetWeakPtr(), src_url, dest_url, callback)); -} - -void CopyOrMoveOperationDelegate::DidCreateDirectory( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - const StatusCallback& callback, - base::File::Error error) { - if (!progress_callback_.is_null() && error == base::File::FILE_OK) { - progress_callback_.Run( - FileSystemOperation::END_COPY_ENTRY, src_url, dest_url, 0); - } - - callback.Run(error); -} - -void CopyOrMoveOperationDelegate::PostProcessDirectoryAfterGetMetadata( - const FileSystemURL& src_url, - const StatusCallback& callback, - base::File::Error error, - const base::File::Info& file_info) { - if (error != base::File::FILE_OK) { - // Ignore the error, and run post process which should run after TouchFile. - PostProcessDirectoryAfterTouchFile( - src_url, callback, base::File::FILE_OK); - return; - } - - operation_runner()->TouchFile( - CreateDestURL(src_url), base::Time::Now() /* last access */, - file_info.last_modified, - base::Bind( - &CopyOrMoveOperationDelegate::PostProcessDirectoryAfterTouchFile, - weak_factory_.GetWeakPtr(), src_url, callback)); -} - -void CopyOrMoveOperationDelegate::PostProcessDirectoryAfterTouchFile( - const FileSystemURL& src_url, - const StatusCallback& callback, - base::File::Error error) { - // Even if the TouchFile is failed, just ignore it. - - if (operation_type_ == OPERATION_COPY) { - callback.Run(base::File::FILE_OK); - return; - } - - DCHECK_EQ(OPERATION_MOVE, operation_type_); - - // All files and subdirectories in the directory should be moved here, - // so remove the source directory for finalizing move operation. - operation_runner()->Remove( - src_url, false /* recursive */, - base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove, - weak_factory_.GetWeakPtr(), callback)); -} - -void CopyOrMoveOperationDelegate::DidRemoveSourceForMove( - const StatusCallback& callback, - base::File::Error error) { - if (error == base::File::FILE_ERROR_NOT_FOUND) - error = base::File::FILE_OK; - callback.Run(error); -} - -void CopyOrMoveOperationDelegate::OnCopyFileProgress( - const FileSystemURL& src_url, int64 size) { - if (!progress_callback_.is_null()) { - progress_callback_.Run( - FileSystemOperation::PROGRESS, src_url, FileSystemURL(), size); - } -} - -FileSystemURL CopyOrMoveOperationDelegate::CreateDestURL( - const FileSystemURL& src_url) const { - DCHECK_EQ(src_root_.type(), src_url.type()); - DCHECK_EQ(src_root_.origin(), src_url.origin()); - - base::FilePath relative = dest_root_.virtual_path(); - src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(), - &relative); - return file_system_context()->CreateCrackedFileSystemURL( - dest_root_.origin(), - dest_root_.mount_type(), - relative); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/copy_or_move_operation_delegate.h b/webkit/browser/fileapi/copy_or_move_operation_delegate.h index e0a574d..558f83c 100644 --- a/webkit/browser/fileapi/copy_or_move_operation_delegate.h +++ b/webkit/browser/fileapi/copy_or_move_operation_delegate.h @@ -1,162 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_COPY_OR_MOVE_OPERATION_DELEGATE_H_ -#define WEBKIT_BROWSER_FILEAPI_COPY_OR_MOVE_OPERATION_DELEGATE_H_ - -#include <set> -#include <stack> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "webkit/browser/fileapi/recursive_operation_delegate.h" - -namespace net { -class DrainableIOBuffer; -class IOBufferWithSize; -} - -namespace storage { -class FileStreamReader; -class ShareableFileReference; -} - -namespace storage { - -class CopyOrMoveFileValidator; -class FileStreamWriter; - -// A delegate class for recursive copy or move operations. -class CopyOrMoveOperationDelegate - : public RecursiveOperationDelegate { - public: - class CopyOrMoveImpl; - typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback; - typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption; - - enum OperationType { - OPERATION_COPY, - OPERATION_MOVE - }; - - // Helper to copy a file by reader and writer streams. - // Export for testing. - class STORAGE_EXPORT StreamCopyHelper { - public: - StreamCopyHelper( - scoped_ptr<storage::FileStreamReader> reader, - scoped_ptr<FileStreamWriter> writer, - bool need_flush, - int buffer_size, - const FileSystemOperation::CopyFileProgressCallback& - file_progress_callback, - const base::TimeDelta& min_progress_callback_invocation_span); - ~StreamCopyHelper(); - - void Run(const StatusCallback& callback); - - // Requests cancelling. After the cancelling is done, |callback| passed to - // Run will be called. - void Cancel(); - - private: - // Reads the content from the |reader_|. - void Read(const StatusCallback& callback); - void DidRead(const StatusCallback& callback, int result); - - // Writes the content in |buffer| to |writer_|. - void Write(const StatusCallback& callback, - scoped_refptr<net::DrainableIOBuffer> buffer); - void DidWrite(const StatusCallback& callback, - scoped_refptr<net::DrainableIOBuffer> buffer, int result); - - // Flushes the written content in |writer_|. - void Flush(const StatusCallback& callback, bool is_eof); - void DidFlush(const StatusCallback& callback, bool is_eof, int result); - - scoped_ptr<storage::FileStreamReader> reader_; - scoped_ptr<FileStreamWriter> writer_; - const bool need_flush_; - FileSystemOperation::CopyFileProgressCallback file_progress_callback_; - scoped_refptr<net::IOBufferWithSize> io_buffer_; - int64 num_copied_bytes_; - int64 previous_flush_offset_; - base::Time last_progress_callback_invocation_time_; - base::TimeDelta min_progress_callback_invocation_span_; - bool cancel_requested_; - base::WeakPtrFactory<StreamCopyHelper> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(StreamCopyHelper); - }; - - CopyOrMoveOperationDelegate( - FileSystemContext* file_system_context, - const FileSystemURL& src_root, - const FileSystemURL& dest_root, - OperationType operation_type, - CopyOrMoveOption option, - const CopyProgressCallback& progress_callback, - const StatusCallback& callback); - virtual ~CopyOrMoveOperationDelegate(); - - // RecursiveOperationDelegate overrides: - virtual void Run() OVERRIDE; - virtual void RunRecursively() OVERRIDE; - virtual void ProcessFile(const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void ProcessDirectory(const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void PostProcessDirectory(const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - - - protected: - virtual void OnCancel() OVERRIDE; - - private: - void DidCopyOrMoveFile(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - const StatusCallback& callback, - CopyOrMoveImpl* impl, - base::File::Error error); - void DidTryRemoveDestRoot(const StatusCallback& callback, - base::File::Error error); - void ProcessDirectoryInternal(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - const StatusCallback& callback); - void DidCreateDirectory(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - const StatusCallback& callback, - base::File::Error error); - void PostProcessDirectoryAfterGetMetadata( - const FileSystemURL& src_url, - const StatusCallback& callback, - base::File::Error error, - const base::File::Info& file_info); - void PostProcessDirectoryAfterTouchFile(const FileSystemURL& src_url, - const StatusCallback& callback, - base::File::Error error); - void DidRemoveSourceForMove(const StatusCallback& callback, - base::File::Error error); - - void OnCopyFileProgress(const FileSystemURL& src_url, int64 size); - FileSystemURL CreateDestURL(const FileSystemURL& src_url) const; - - FileSystemURL src_root_; - FileSystemURL dest_root_; - bool same_file_system_; - OperationType operation_type_; - CopyOrMoveOption option_; - CopyProgressCallback progress_callback_; - StatusCallback callback_; - - std::set<CopyOrMoveImpl*> running_copy_set_; - base::WeakPtrFactory<CopyOrMoveOperationDelegate> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOperationDelegate); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_COPY_OR_MOVE_OPERATION_DELEGATE_H_ +#include "storage/browser/fileapi/copy_or_move_operation_delegate.h" diff --git a/webkit/browser/fileapi/dragged_file_util.cc b/webkit/browser/fileapi/dragged_file_util.cc deleted file mode 100644 index 7b02798..0000000 --- a/webkit/browser/fileapi/dragged_file_util.cc +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2013 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/browser/fileapi/dragged_file_util.h" - -#include <string> -#include <vector> - -#include "base/files/file_util.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/isolated_context.h" -#include "webkit/browser/fileapi/native_file_util.h" -#include "webkit/common/blob/shareable_file_reference.h" - -namespace storage { - -typedef IsolatedContext::MountPointInfo FileInfo; - -namespace { - -// Simply enumerate each path from a given fileinfo set. -// Used to enumerate top-level paths of an isolated filesystem. -class SetFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { - public: - explicit SetFileEnumerator(const std::vector<FileInfo>& files) - : files_(files) { - file_iter_ = files_.begin(); - } - virtual ~SetFileEnumerator() {} - - // AbstractFileEnumerator overrides. - virtual base::FilePath Next() OVERRIDE { - if (file_iter_ == files_.end()) - return base::FilePath(); - base::FilePath platform_file = (file_iter_++)->path; - NativeFileUtil::GetFileInfo(platform_file, &file_info_); - return platform_file; - } - virtual int64 Size() OVERRIDE { return file_info_.size; } - virtual bool IsDirectory() OVERRIDE { return file_info_.is_directory; } - virtual base::Time LastModifiedTime() OVERRIDE { - return file_info_.last_modified; - } - - private: - std::vector<FileInfo> files_; - std::vector<FileInfo>::const_iterator file_iter_; - base::File::Info file_info_; -}; - -} // namespace - -//------------------------------------------------------------------------- - -DraggedFileUtil::DraggedFileUtil() {} - -base::File::Error DraggedFileUtil::GetFileInfo( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Info* file_info, - base::FilePath* platform_path) { - DCHECK(file_info); - std::string filesystem_id; - DCHECK(url.is_valid()); - if (url.path().empty()) { - // The root directory case. - // For now we leave three time fields (modified/accessed/creation time) - // NULL as it is not really clear what to be set for this virtual directory. - // TODO(kinuko): Maybe we want to set the time when this filesystem is - // created (i.e. when the files/directories are dropped). - file_info->is_directory = true; - file_info->is_symbolic_link = false; - file_info->size = 0; - return base::File::FILE_OK; - } - base::File::Error error = - NativeFileUtil::GetFileInfo(url.path(), file_info); - if (base::IsLink(url.path()) && !base::FilePath().IsParent(url.path())) { - // Don't follow symlinks unless it's the one that are selected by the user. - return base::File::FILE_ERROR_NOT_FOUND; - } - if (error == base::File::FILE_OK) - *platform_path = url.path(); - return error; -} - -scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> - DraggedFileUtil::CreateFileEnumerator( - FileSystemOperationContext* context, - const FileSystemURL& root) { - DCHECK(root.is_valid()); - if (!root.path().empty()) - return LocalFileUtil::CreateFileEnumerator(context, root); - - // Root path case. - std::vector<FileInfo> toplevels; - IsolatedContext::GetInstance()->GetDraggedFileInfo( - root.filesystem_id(), &toplevels); - return scoped_ptr<AbstractFileEnumerator>(new SetFileEnumerator(toplevels)); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/dragged_file_util.h b/webkit/browser/fileapi/dragged_file_util.h index bc0da85..7a33fef 100644 --- a/webkit/browser/fileapi/dragged_file_util.h +++ b/webkit/browser/fileapi/dragged_file_util.h @@ -1,41 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_DRAGGED_FILE_UTIL_H_ -#define WEBKIT_BROWSER_FILEAPI_DRAGGED_FILE_UTIL_H_ - -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/local_file_util.h" -#include "webkit/browser/storage_browser_export.h" - -namespace storage { - -class FileSystemOperationContext; - -// Dragged file system is a specialized LocalFileUtil where read access to -// the virtual root directory (i.e. empty cracked path case) is allowed -// and single isolated context may be associated with multiple file paths. -class STORAGE_EXPORT_PRIVATE DraggedFileUtil - : public LocalFileUtil { - public: - DraggedFileUtil(); - virtual ~DraggedFileUtil() {} - - // FileSystemFileUtil overrides. - virtual base::File::Error GetFileInfo( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Info* file_info, - base::FilePath* platform_path) OVERRIDE; - virtual scoped_ptr<AbstractFileEnumerator> CreateFileEnumerator( - FileSystemOperationContext* context, - const FileSystemURL& root_url) OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(DraggedFileUtil); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_DRAGGED_FILE_UTIL_H_ +#include "storage/browser/fileapi/dragged_file_util.h" diff --git a/webkit/browser/fileapi/dump_file_system.cc b/webkit/browser/fileapi/dump_file_system.cc deleted file mode 100644 index 0f30ef2..0000000 --- a/webkit/browser/fileapi/dump_file_system.cc +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) 2013 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. -// -// A tool to dump HTML5 filesystem from CUI. -// -// Usage: -// -// ./out/Release/dump_file_system [options] <filesystem dir> [origin]... -// -// If no origin is specified, this dumps all origins in the profile dir. -// -// Available options: -// -// -t : dumps temporary files instead of persistent. -// -s : dumps syncable files instead of persistent. -// -l : more information will be displayed. -// -// The format of -l option is: -// -// === ORIGIN origin_name origin_dir === -// file_name file_id file_size file_content_path -// ... -// -// where file_name has a trailing slash, file_size is the number of -// children, and file_content_path is empty if the file is a directory. -// - -#include <stdio.h> -#include <stdlib.h> - -#include <stack> -#include <string> -#include <utility> -#include <vector> - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/format_macros.h" -#include "base/strings/stringprintf.h" -#include "webkit/browser/fileapi/obfuscated_file_util.h" -#include "webkit/browser/fileapi/sandbox_directory_database.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend.h" -#include "webkit/browser/fileapi/sandbox_origin_database.h" -#include "webkit/common/fileapi/file_system_types.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace { - -bool g_opt_long; -const char* g_opt_fs_type = "p"; - -void ShowMessageAndExit(const std::string& msg) { - fprintf(stderr, "%s\n", msg.c_str()); - exit(EXIT_FAILURE); -} - -void ShowUsageAndExit(const std::string& arg0) { - ShowMessageAndExit( - "Usage: " + arg0 + - " [-l] [-t] [-s] <filesystem dir> [origin]..."); -} - -} // namespace - -namespace storage { - -static void DumpDirectoryTree(const std::string& origin_name, - base::FilePath origin_dir) { - origin_dir = origin_dir.Append(g_opt_fs_type); - - printf("=== ORIGIN %s %s ===\n", - origin_name.c_str(), FilePathToString(origin_dir).c_str()); - - if (!base::DirectoryExists(origin_dir)) - return; - - SandboxDirectoryDatabase directory_db(origin_dir, NULL); - SandboxDirectoryDatabase::FileId root_id; - if (!directory_db.GetFileWithPath(StringToFilePath("/"), &root_id)) - return; - - std::stack<std::pair<SandboxDirectoryDatabase::FileId, - std::string> > paths; - paths.push(std::make_pair(root_id, "")); - while (!paths.empty()) { - SandboxDirectoryDatabase::FileId id = paths.top().first; - const std::string dirname = paths.top().second; - paths.pop(); - - SandboxDirectoryDatabase::FileInfo info; - if (!directory_db.GetFileInfo(id, &info)) { - ShowMessageAndExit(base::StringPrintf("GetFileInfo failed for %"PRId64, - id)); - } - - const std::string name = - dirname + "/" + FilePathToString(base::FilePath(info.name)); - std::vector<SandboxDirectoryDatabase::FileId> children; - if (info.is_directory()) { - if (!directory_db.ListChildren(id, &children)) { - ShowMessageAndExit(base::StringPrintf( - "ListChildren failed for %s (%"PRId64")", - info.name.c_str(), id)); - } - - for (size_t j = children.size(); j; j--) - paths.push(make_pair(children[j-1], name)); - } - - // +1 for the leading extra slash. - const char* display_name = name.c_str() + 1; - const char* directory_suffix = info.is_directory() ? "/" : ""; - if (g_opt_long) { - int64 size; - if (info.is_directory()) { - size = static_cast<int64>(children.size()); - } else { - base::GetFileSize(origin_dir.Append(info.data_path), &size); - } - // TODO(hamaji): Modification time? - printf("%s%s %"PRId64" %"PRId64" %s\n", - display_name, - directory_suffix, - id, - size, - FilePathToString(info.data_path).c_str()); - } else { - printf("%s%s\n", display_name, directory_suffix); - } - } -} - -static void DumpOrigin(const base::FilePath& file_system_dir, - const std::string& origin_name) { - SandboxOriginDatabase origin_db(file_system_dir, NULL); - base::FilePath origin_dir; - if (!origin_db.HasOriginPath(origin_name)) { - ShowMessageAndExit("Origin " + origin_name + " is not in " + - FilePathToString(file_system_dir)); - } - - if (!origin_db.GetPathForOrigin(origin_name, &origin_dir)) { - ShowMessageAndExit("Failed to get path of origin " + origin_name + - " in " + FilePathToString(file_system_dir)); - } - DumpDirectoryTree(origin_name, file_system_dir.Append(origin_dir)); -} - -static void DumpFileSystem(const base::FilePath& file_system_dir) { - SandboxOriginDatabase origin_db(file_system_dir, NULL); - std::vector<SandboxOriginDatabase::OriginRecord> origins; - origin_db.ListAllOrigins(&origins); - for (size_t i = 0; i < origins.size(); i++) { - const SandboxOriginDatabase::OriginRecord& origin = origins[i]; - DumpDirectoryTree(origin.origin, file_system_dir.Append(origin.path)); - puts(""); - } -} - -} // namespace storage - -int main(int argc, char* argv[]) { - const char* arg0 = argv[0]; - std::string username = "Default"; - while (true) { - if (argc < 2) - ShowUsageAndExit(arg0); - - if (std::string(argv[1]) == "-l") { - g_opt_long = true; - argc--; - argv++; - } else if (std::string(argv[1]) == "-t") { - g_opt_fs_type = "t"; - argc--; - argv++; - } else if (std::string(argv[1]) == "-s") { - g_opt_fs_type = "s"; - argc--; - argv++; - } else { - break; - } - } - - if (argc < 2) - ShowUsageAndExit(arg0); - - const base::FilePath file_system_dir = storage::StringToFilePath(argv[1]); - if (!base::DirectoryExists(file_system_dir)) { - ShowMessageAndExit(storage::FilePathToString(file_system_dir) + - " is not a filesystem directory"); - } - - if (argc == 2) { - storage::DumpFileSystem(file_system_dir); - } else { - for (int i = 2; i < argc; i++) { - storage::DumpOrigin(file_system_dir, argv[i]); - } - } - return 0; -} diff --git a/webkit/browser/fileapi/external_mount_points.cc b/webkit/browser/fileapi/external_mount_points.cc deleted file mode 100644 index 29ea8ae..0000000 --- a/webkit/browser/fileapi/external_mount_points.cc +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright (c) 2013 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/browser/fileapi/external_mount_points.h" - -#include "base/files/file_path.h" -#include "base/lazy_instance.h" -#include "base/path_service.h" -#include "base/stl_util.h" -#include "webkit/browser/fileapi/file_system_url.h" - -namespace { - -// Normalizes file path so it has normalized separators and ends with exactly -// one separator. Paths have to be normalized this way for use in -// GetVirtualPath method. Separators cannot be completely stripped, or -// GetVirtualPath could not working in some edge cases. -// For example, /a/b/c(1)/d would be erroneously resolved as c/d if the -// following mount points were registered: "/a/b/c", "/a/b/c(1)". (Note: -// "/a/b/c" < "/a/b/c(1)" < "/a/b/c/"). -base::FilePath NormalizeFilePath(const base::FilePath& path) { - if (path.empty()) - return path; - - base::FilePath::StringType path_str = path.StripTrailingSeparators().value(); - if (!base::FilePath::IsSeparator(path_str[path_str.length() - 1])) - path_str.append(FILE_PATH_LITERAL("/")); - - return base::FilePath(path_str).NormalizePathSeparators(); -} - -bool IsOverlappingMountPathForbidden(storage::FileSystemType type) { - return type != storage::kFileSystemTypeNativeMedia && - type != storage::kFileSystemTypeDeviceMedia; -} - -// Wrapper around ref-counted ExternalMountPoints that will be used to lazily -// create and initialize LazyInstance system ExternalMountPoints. -class SystemMountPointsLazyWrapper { - public: - SystemMountPointsLazyWrapper() - : system_mount_points_(storage::ExternalMountPoints::CreateRefCounted()) { - } - - ~SystemMountPointsLazyWrapper() {} - - storage::ExternalMountPoints* get() { return system_mount_points_.get(); } - - private: - scoped_refptr<storage::ExternalMountPoints> system_mount_points_; -}; - -base::LazyInstance<SystemMountPointsLazyWrapper>::Leaky - g_external_mount_points = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -namespace storage { - -class ExternalMountPoints::Instance { - public: - Instance(FileSystemType type, - const base::FilePath& path, - const FileSystemMountOption& mount_option) - : type_(type), - path_(path.StripTrailingSeparators()), - mount_option_(mount_option) {} - ~Instance() {} - - FileSystemType type() const { return type_; } - const base::FilePath& path() const { return path_; } - const FileSystemMountOption& mount_option() const { return mount_option_; } - - private: - const FileSystemType type_; - const base::FilePath path_; - const FileSystemMountOption mount_option_; - - DISALLOW_COPY_AND_ASSIGN(Instance); -}; - -//-------------------------------------------------------------------------- - -// static -ExternalMountPoints* ExternalMountPoints::GetSystemInstance() { - return g_external_mount_points.Pointer()->get(); -} - -// static -scoped_refptr<ExternalMountPoints> ExternalMountPoints::CreateRefCounted() { - return new ExternalMountPoints(); -} - -bool ExternalMountPoints::RegisterFileSystem( - const std::string& mount_name, - FileSystemType type, - const FileSystemMountOption& mount_option, - const base::FilePath& path_in) { - // COPY_SYNC_OPTION_SYNC is only applicable to native local file system. - DCHECK(type == kFileSystemTypeNativeLocal || - mount_option.copy_sync_option() != COPY_SYNC_OPTION_SYNC); - - base::AutoLock locker(lock_); - - base::FilePath path = NormalizeFilePath(path_in); - if (!ValidateNewMountPoint(mount_name, type, path)) - return false; - - instance_map_[mount_name] = new Instance(type, path, mount_option); - if (!path.empty() && IsOverlappingMountPathForbidden(type)) - path_to_name_map_.insert(std::make_pair(path, mount_name)); - return true; -} - -bool ExternalMountPoints::HandlesFileSystemMountType( - FileSystemType type) const { - return type == kFileSystemTypeExternal || - type == kFileSystemTypeNativeForPlatformApp; -} - -bool ExternalMountPoints::RevokeFileSystem(const std::string& mount_name) { - base::AutoLock locker(lock_); - NameToInstance::iterator found = instance_map_.find(mount_name); - if (found == instance_map_.end()) - return false; - Instance* instance = found->second; - if (IsOverlappingMountPathForbidden(instance->type())) - path_to_name_map_.erase(NormalizeFilePath(instance->path())); - delete found->second; - instance_map_.erase(found); - return true; -} - -bool ExternalMountPoints::GetRegisteredPath( - const std::string& filesystem_id, base::FilePath* path) const { - DCHECK(path); - base::AutoLock locker(lock_); - NameToInstance::const_iterator found = instance_map_.find(filesystem_id); - if (found == instance_map_.end()) - return false; - *path = found->second->path(); - return true; -} - -bool ExternalMountPoints::CrackVirtualPath( - const base::FilePath& virtual_path, - std::string* mount_name, - FileSystemType* type, - std::string* cracked_id, - base::FilePath* path, - FileSystemMountOption* mount_option) const { - DCHECK(mount_name); - DCHECK(path); - - // The path should not contain any '..' references. - if (virtual_path.ReferencesParent()) - return false; - - // The virtual_path should comprise of <mount_name> and <relative_path> parts. - std::vector<base::FilePath::StringType> components; - virtual_path.GetComponents(&components); - if (components.size() < 1) - return false; - - std::vector<base::FilePath::StringType>::iterator component_iter = - components.begin(); - std::string maybe_mount_name = - base::FilePath(*component_iter++).MaybeAsASCII(); - if (maybe_mount_name.empty()) - return false; - - base::FilePath cracked_path; - { - base::AutoLock locker(lock_); - NameToInstance::const_iterator found_instance = - instance_map_.find(maybe_mount_name); - if (found_instance == instance_map_.end()) - return false; - - *mount_name = maybe_mount_name; - const Instance* instance = found_instance->second; - if (type) - *type = instance->type(); - cracked_path = instance->path(); - *mount_option = instance->mount_option(); - } - - for (; component_iter != components.end(); ++component_iter) - cracked_path = cracked_path.Append(*component_iter); - *path = cracked_path; - return true; -} - -FileSystemURL ExternalMountPoints::CrackURL(const GURL& url) const { - FileSystemURL filesystem_url = FileSystemURL(url); - if (!filesystem_url.is_valid()) - return FileSystemURL(); - return CrackFileSystemURL(filesystem_url); -} - -FileSystemURL ExternalMountPoints::CreateCrackedFileSystemURL( - const GURL& origin, - FileSystemType type, - const base::FilePath& path) const { - return CrackFileSystemURL(FileSystemURL(origin, type, path)); -} - -void ExternalMountPoints::AddMountPointInfosTo( - std::vector<MountPointInfo>* mount_points) const { - base::AutoLock locker(lock_); - DCHECK(mount_points); - for (NameToInstance::const_iterator iter = instance_map_.begin(); - iter != instance_map_.end(); ++iter) { - mount_points->push_back(MountPointInfo(iter->first, iter->second->path())); - } -} - -bool ExternalMountPoints::GetVirtualPath(const base::FilePath& path_in, - base::FilePath* virtual_path) const { - DCHECK(virtual_path); - - base::AutoLock locker(lock_); - - base::FilePath path = NormalizeFilePath(path_in); - std::map<base::FilePath, std::string>::const_reverse_iterator iter( - path_to_name_map_.upper_bound(path)); - if (iter == path_to_name_map_.rend()) - return false; - - *virtual_path = CreateVirtualRootPath(iter->second); - if (iter->first == path) - return true; - return iter->first.AppendRelativePath(path, virtual_path); -} - -base::FilePath ExternalMountPoints::CreateVirtualRootPath( - const std::string& mount_name) const { - return base::FilePath().AppendASCII(mount_name); -} - -FileSystemURL ExternalMountPoints::CreateExternalFileSystemURL( - const GURL& origin, - const std::string& mount_name, - const base::FilePath& path) const { - return CreateCrackedFileSystemURL( - origin, - storage::kFileSystemTypeExternal, - // Avoid using FilePath::Append as path may be an absolute path. - base::FilePath(CreateVirtualRootPath(mount_name).value() + - base::FilePath::kSeparators[0] + path.value())); -} - -void ExternalMountPoints::RevokeAllFileSystems() { - NameToInstance instance_map_copy; - { - base::AutoLock locker(lock_); - instance_map_copy = instance_map_; - instance_map_.clear(); - path_to_name_map_.clear(); - } - STLDeleteContainerPairSecondPointers(instance_map_copy.begin(), - instance_map_copy.end()); -} - -ExternalMountPoints::ExternalMountPoints() {} - -ExternalMountPoints::~ExternalMountPoints() { - STLDeleteContainerPairSecondPointers(instance_map_.begin(), - instance_map_.end()); -} - -FileSystemURL ExternalMountPoints::CrackFileSystemURL( - const FileSystemURL& url) const { - if (!HandlesFileSystemMountType(url.type())) - return FileSystemURL(); - - base::FilePath virtual_path = url.path(); - if (url.type() == kFileSystemTypeNativeForPlatformApp) { -#if defined(OS_CHROMEOS) - // On Chrome OS, find a mount point and virtual path for the external fs. - if (!GetVirtualPath(url.path(), &virtual_path)) - return FileSystemURL(); -#else - // On other OS, it is simply a native local path. - return FileSystemURL( - url.origin(), url.mount_type(), url.virtual_path(), - url.mount_filesystem_id(), kFileSystemTypeNativeLocal, - url.path(), url.filesystem_id(), url.mount_option()); -#endif - } - - std::string mount_name; - FileSystemType cracked_type; - std::string cracked_id; - base::FilePath cracked_path; - FileSystemMountOption cracked_mount_option; - - if (!CrackVirtualPath(virtual_path, &mount_name, &cracked_type, - &cracked_id, &cracked_path, &cracked_mount_option)) { - return FileSystemURL(); - } - - return FileSystemURL( - url.origin(), url.mount_type(), url.virtual_path(), - !url.filesystem_id().empty() ? url.filesystem_id() : mount_name, - cracked_type, cracked_path, - cracked_id.empty() ? mount_name : cracked_id, cracked_mount_option); -} - -bool ExternalMountPoints::ValidateNewMountPoint(const std::string& mount_name, - FileSystemType type, - const base::FilePath& path) { - lock_.AssertAcquired(); - - // Mount name must not be empty. - if (mount_name.empty()) - return false; - - // Verify there is no registered mount point with the same name. - NameToInstance::iterator found = instance_map_.find(mount_name); - if (found != instance_map_.end()) - return false; - - // Allow empty paths. - if (path.empty()) - return true; - - // Verify path is legal. - if (path.ReferencesParent() || !path.IsAbsolute()) - return false; - - if (IsOverlappingMountPathForbidden(type)) { - // Check there the new path does not overlap with one of the existing ones. - std::map<base::FilePath, std::string>::reverse_iterator potential_parent( - path_to_name_map_.upper_bound(path)); - if (potential_parent != path_to_name_map_.rend()) { - if (potential_parent->first == path || - potential_parent->first.IsParent(path)) { - return false; - } - } - - std::map<base::FilePath, std::string>::iterator potential_child = - path_to_name_map_.upper_bound(path); - if (potential_child != path_to_name_map_.end()) { - if (potential_child->first == path || - path.IsParent(potential_child->first)) { - return false; - } - } - } - - return true; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/external_mount_points.h b/webkit/browser/fileapi/external_mount_points.h index 842cba0..2cb7793 100644 --- a/webkit/browser/fileapi/external_mount_points.h +++ b/webkit/browser/fileapi/external_mount_points.h @@ -1,159 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_EXTERNAL_MOUNT_POINTS_H_ -#define WEBKIT_BROWSER_FILEAPI_EXTERNAL_MOUNT_POINTS_H_ - -#include <map> -#include <string> -#include <vector> - -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "webkit/browser/fileapi/mount_points.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_mount_option.h" -#include "webkit/common/fileapi/file_system_types.h" - -namespace base { -class FilePath; -} - -namespace storage { - -class FileSystemURL; - -// Manages external filesystem namespaces that are identified by 'mount name' -// and are persisted until RevokeFileSystem is called. -// Files in an external filesystem are identified by a filesystem URL like: -// -// filesystem:<origin>/external/<mount_name>/relative/path -// -class STORAGE_EXPORT ExternalMountPoints - : public base::RefCountedThreadSafe<ExternalMountPoints>, - public MountPoints { - public: - static ExternalMountPoints* GetSystemInstance(); - static scoped_refptr<ExternalMountPoints> CreateRefCounted(); - - // Registers a new named external filesystem. - // The |path| is registered as the root path of the mount point which - // is identified by a URL "filesystem:.../external/mount_name". - // - // For example, if the path "/media/removable" is registered with - // the mount_name "removable", a filesystem URL like - // "filesystem:.../external/removable/a/b" will be resolved as - // "/media/removable/a/b". - // - // The |mount_name| should NOT contain a path separator '/'. - // Returns false if the given name is already registered. - // - // Overlapping mount points in a single MountPoints instance are not allowed. - // Adding mount point whose path overlaps with an existing mount point will - // fail except for media galleries, which do not count toward registered - // paths for overlap calculation. - // - // If not empty, |path| must be absolute. It is allowed for the path to be - // empty, but |GetVirtualPath| will not work for those mount points. - // - // An external file system registered by this method can be revoked - // by calling RevokeFileSystem with |mount_name|. - bool RegisterFileSystem(const std::string& mount_name, - FileSystemType type, - const FileSystemMountOption& mount_option, - const base::FilePath& path); - - // MountPoints overrides. - virtual bool HandlesFileSystemMountType(FileSystemType type) const OVERRIDE; - virtual bool RevokeFileSystem(const std::string& mount_name) OVERRIDE; - virtual bool GetRegisteredPath(const std::string& mount_name, - base::FilePath* path) const OVERRIDE; - virtual bool CrackVirtualPath( - const base::FilePath& virtual_path, - std::string* mount_name, - FileSystemType* type, - std::string* cracked_id, - base::FilePath* path, - FileSystemMountOption* mount_option) const OVERRIDE; - virtual FileSystemURL CrackURL(const GURL& url) const OVERRIDE; - virtual FileSystemURL CreateCrackedFileSystemURL( - const GURL& origin, - FileSystemType type, - const base::FilePath& path) const OVERRIDE; - - // Returns a list of registered MountPointInfos (of <mount_name, path>). - void AddMountPointInfosTo(std::vector<MountPointInfo>* mount_points) const; - - // Converts a path on a registered file system to virtual path relative to the - // file system root. E.g. if 'Downloads' file system is mapped to - // '/usr/local/home/Downloads', and |absolute| path is set to - // '/usr/local/home/Downloads/foo', the method will set |virtual_path| to - // 'Downloads/foo'. - // Returns false if the path cannot be resolved (e.g. if the path is not - // part of any registered filesystem). - // - // Media gallery type file systems do not count for this calculation. i.e. - // if only a media gallery is registered for the path, false will be returned. - // If a media gallery and another file system are registered for related - // paths, only the other registration is taken into account. - // - // Returned virtual_path will have normalized path separators. - bool GetVirtualPath(const base::FilePath& absolute_path, - base::FilePath* virtual_path) const; - - // Returns the virtual root path that looks like /<mount_name>. - base::FilePath CreateVirtualRootPath(const std::string& mount_name) const; - - FileSystemURL CreateExternalFileSystemURL( - const GURL& origin, - const std::string& mount_name, - const base::FilePath& path) const; - - // Revoke all registered filesystems. Used only by testing (for clean-ups). - void RevokeAllFileSystems(); - - private: - friend class base::RefCountedThreadSafe<ExternalMountPoints>; - - // Represents each file system instance (defined in the .cc). - class Instance; - - typedef std::map<std::string, Instance*> NameToInstance; - - // Reverse map from registered path to its corresponding mount name. - typedef std::map<base::FilePath, std::string> PathToName; - - // Use |GetSystemInstance| of |CreateRefCounted| to get an instance. - ExternalMountPoints(); - virtual ~ExternalMountPoints(); - - // MountPoint overrides. - virtual FileSystemURL CrackFileSystemURL( - const FileSystemURL& url) const OVERRIDE; - - // Performs sanity checks on the new mount point. - // Checks the following: - // - there is no registered mount point with mount_name - // - path does not contain a reference to a parent - // - path is absolute - // - path does not overlap with an existing mount point path unless it is a - // media gallery type. - // - // |lock_| should be taken before calling this method. - bool ValidateNewMountPoint(const std::string& mount_name, - FileSystemType type, - const base::FilePath& path); - - // This lock needs to be obtained when accessing the instance_map_. - mutable base::Lock lock_; - - NameToInstance instance_map_; - PathToName path_to_name_map_; - - DISALLOW_COPY_AND_ASSIGN(ExternalMountPoints); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_EXTERNAL_MOUNT_POINTS_H_ +#include "storage/browser/fileapi/external_mount_points.h" diff --git a/webkit/browser/fileapi/file_observers.h b/webkit/browser/fileapi/file_observers.h index 2dfcc4e..a176f34 100644 --- a/webkit/browser/fileapi/file_observers.h +++ b/webkit/browser/fileapi/file_observers.h @@ -1,83 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_OBSERVERS_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_OBSERVERS_H_ - -#include "base/basictypes.h" -#include "webkit/browser/storage_browser_export.h" - -// TODO(kinuko): Split this file into per-observer multiple files. - -namespace storage { - -class FileSystemURL; - -// An abstract interface to observe update operations. -// -// OnStartUpdate and OnEndUpdate are called once for each target url -// before and after following operations regardless of whether the operation -// is made recursively or not (i.e. StartUpdate() will be called only once -// for destination url regardless of whether it is recursive copy or not): -// CreateFile(), CreateDirectory(), -// Copy() (destination only), -// Move() (both for source and destination), -// Remove(), Write(), Truncate(), TouchFile() -// -// OnUpdate() is called each time the |url| is updated but works only for -// sandboxed files (where usage is tracked). -class STORAGE_EXPORT FileUpdateObserver { - public: - FileUpdateObserver() {} - virtual ~FileUpdateObserver() {} - - virtual void OnStartUpdate(const FileSystemURL& url) = 0; - virtual void OnUpdate(const FileSystemURL& url, int64 delta) = 0; - virtual void OnEndUpdate(const FileSystemURL& url) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FileUpdateObserver); -}; - -// An abstract interface to observe file access. -// OnAccess is called whenever an operation reads file contents or metadata. -// (It is called only once per operation regardless of whether the operation -// is recursive or not) -class STORAGE_EXPORT FileAccessObserver { - public: - FileAccessObserver() {} - virtual ~FileAccessObserver() {} - - virtual void OnAccess(const FileSystemURL& url) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FileAccessObserver); -}; - -// An abstract interface to observe file changes. -// Each method of this class is called once per file/directory is created, -// removed or modified. For recursive operations each method is called for -// each subdirectory/subfile. Currently ChangeObserver is only supported -// by the local sandbox file system. -class STORAGE_EXPORT FileChangeObserver { - public: - FileChangeObserver() {} - virtual ~FileChangeObserver() {} - - virtual void OnCreateFile(const FileSystemURL& url) = 0; - virtual void OnCreateFileFrom(const FileSystemURL& url, - const FileSystemURL& src) = 0; - virtual void OnRemoveFile(const FileSystemURL& url) = 0; - virtual void OnModifyFile(const FileSystemURL& url) = 0; - - virtual void OnCreateDirectory(const FileSystemURL& url) = 0; - virtual void OnRemoveDirectory(const FileSystemURL& url) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FileChangeObserver); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_OBSERVERS_H_ +#include "storage/browser/fileapi/file_observers.h" diff --git a/webkit/browser/fileapi/file_permission_policy.h b/webkit/browser/fileapi/file_permission_policy.h index 9cf0b1e..1ef299a 100644 --- a/webkit/browser/fileapi/file_permission_policy.h +++ b/webkit/browser/fileapi/file_permission_policy.h @@ -1,28 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_PERMISSION_POLICY_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_PERMISSION_POLICY_H_ - -#include "webkit/browser/storage_browser_export.h" - -namespace storage { - -enum FilePermissionPolicy { - // Any access should be always denied. - FILE_PERMISSION_ALWAYS_DENY = 0x0, - - // Access is sandboxed, no extra permission check is necessary. - FILE_PERMISSION_SANDBOX = 1 << 0, - - // Access should be restricted to read-only. - FILE_PERMISSION_READ_ONLY = 1 << 1, - - // Access should be examined by per-file permission policy. - FILE_PERMISSION_USE_FILE_PERMISSION = 1 << 2, -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_PERMISSION_POLICY_H_ +#include "storage/browser/fileapi/file_permission_policy.h" diff --git a/webkit/browser/fileapi/file_stream_writer.h b/webkit/browser/fileapi/file_stream_writer.h index d2467b3..9a6e6f3 100644 --- a/webkit/browser/fileapi/file_stream_writer.h +++ b/webkit/browser/fileapi/file_stream_writer.h @@ -1,87 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_STREAM_WRITER_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_STREAM_WRITER_H_ - -#include "base/basictypes.h" -#include "net/base/completion_callback.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class FilePath; -class TaskRunner; -} - -namespace net { -class IOBuffer; -} - -namespace storage { - -// A generic interface for writing to a file-like object. -class FileStreamWriter { - public: - enum OpenOrCreate { OPEN_EXISTING_FILE, CREATE_NEW_FILE }; - - // Creates a writer for the existing file in the path |file_path| starting - // from |initial_offset|. Uses |task_runner| for async file operations. - STORAGE_EXPORT static FileStreamWriter* CreateForLocalFile( - base::TaskRunner* task_runner, - const base::FilePath& file_path, - int64 initial_offset, - OpenOrCreate open_or_create); - - // Closes the file. If there's an in-flight operation, it is canceled (i.e., - // the callback function associated with the operation is not called). - virtual ~FileStreamWriter() {} - - // Writes to the current cursor position asynchronously. - // - // Up to buf_len bytes will be written. (In other words, partial - // writes are allowed.) If the write completed synchronously, it returns - // the number of bytes written. If the operation could not be performed, it - // returns an error code. Otherwise, net::ERR_IO_PENDING is returned, and the - // callback will be run on the thread where Write() was called when the write - // has completed. - // - // This errors out (either synchronously or via callback) with: - // net::ERR_FILE_NOT_FOUND: When the target file is not found. - // net::ERR_ACCESS_DENIED: When the target file is a directory or - // the writer has no permission on the file. - // net::ERR_FILE_NO_SPACE: When the write will result in out of quota - // or there is not enough room left on the disk. - // - // It is invalid to call Write while there is an in-flight async operation. - virtual int Write(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) = 0; - - // Cancels an in-flight async operation. - // - // If the cancel is finished synchronously, it returns net::OK. If the - // cancel could not be performed, it returns an error code. Especially when - // there is no in-flight operation, net::ERR_UNEXPECTED is returned. - // Otherwise, net::ERR_IO_PENDING is returned, and the callback will be run on - // the thread where Cancel() was called when the cancel has completed. It is - // invalid to call Cancel() more than once on the same async operation. - // - // In either case, the callback function passed to the in-flight async - // operation is dismissed immediately when Cancel() is called, and thus - // will never be called. - virtual int Cancel(const net::CompletionCallback& callback) = 0; - - // Flushes the data written so far. - // - // If the flush finished synchronously, it return net::OK. If the flush could - // not be performed, it returns an error code. Otherwise, net::ERR_IO_PENDING - // is returned, and the callback will be run on the thread where Flush() was - // called when the flush has completed. - // - // It is invalid to call Flush while there is an in-flight async operation. - virtual int Flush(const net::CompletionCallback& callback) = 0; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_STREAM_WRITER_H_ +#include "storage/browser/fileapi/file_stream_writer.h" diff --git a/webkit/browser/fileapi/file_system_backend.h b/webkit/browser/fileapi/file_system_backend.h index 43bc3af..266819e 100644 --- a/webkit/browser/fileapi/file_system_backend.h +++ b/webkit/browser/fileapi/file_system_backend.h @@ -1,169 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_BACKEND_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_BACKEND_H_ - -#include <string> -#include <vector> - -#include "base/callback_forward.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/file_permission_policy.h" -#include "webkit/browser/fileapi/open_file_system_mode.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_types.h" - -class GURL; - -namespace storage { - -class AsyncFileUtil; -class CopyOrMoveFileValidatorFactory; -class FileSystemURL; -class FileStreamReader; -class FileStreamWriter; -class FileSystemContext; -class FileSystemFileUtil; -class FileSystemOperation; -class FileSystemQuotaUtil; -class WatcherManager; - -// Callback to take GURL. -typedef base::Callback<void(const GURL& url)> URLCallback; - -// An interface for defining a file system backend. -// -// NOTE: when you implement a new FileSystemBackend for your own -// FileSystem module, please contact to kinuko@chromium.org. -// -class STORAGE_EXPORT FileSystemBackend { - public: - // Callback for InitializeFileSystem. - typedef base::Callback<void(const GURL& root_url, - const std::string& name, - base::File::Error error)> - OpenFileSystemCallback; - virtual ~FileSystemBackend() {} - - // Returns true if this filesystem backend can handle |type|. - // One filesystem backend may be able to handle multiple filesystem types. - virtual bool CanHandleType(FileSystemType type) const = 0; - - // This method is called right after the backend is registered in the - // FileSystemContext and before any other methods are called. Each backend can - // do additional initialization which depends on FileSystemContext here. - virtual void Initialize(FileSystemContext* context) = 0; - - // Resolves the filesystem root URL and the name for the given |url|. - // This verifies if it is allowed to request (or create) the filesystem and if - // it can access (or create) the root directory. - // If |mode| is CREATE_IF_NONEXISTENT calling this may also create the root - // directory (and/or related database entries etc) for the filesystem if it - // doesn't exist. - virtual void ResolveURL(const FileSystemURL& url, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) = 0; - - // Returns the specialized AsyncFileUtil for this backend. - virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) = 0; - - // Returns the specialized WatcherManager for this backend. - virtual WatcherManager* GetWatcherManager(FileSystemType type) = 0; - - // Returns the specialized CopyOrMoveFileValidatorFactory for this backend - // and |type|. If |error_code| is File::FILE_OK and the result is NULL, - // then no validator is required. - virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( - FileSystemType type, base::File::Error* error_code) = 0; - - // Returns a new instance of the specialized FileSystemOperation for this - // backend based on the given triplet of |origin_url|, |file_system_type| - // and |virtual_path|. On failure to create a file system operation, set - // |error_code| correspondingly. - // This method is usually dispatched by - // FileSystemContext::CreateFileSystemOperation. - virtual FileSystemOperation* CreateFileSystemOperation( - const FileSystemURL& url, - FileSystemContext* context, - base::File::Error* error_code) const = 0; - - // Returns true if Blobs accessing |url| should use FileStreamReader. - // If false, Blobs are accessed using a snapshot file by calling - // AsyncFileUtil::CreateSnapshotFile. - virtual bool SupportsStreaming(const FileSystemURL& url) const = 0; - - // Returns true if specified |type| of filesystem can handle Copy() - // of the files in the same file system instead of streaming - // read/write implementation. - virtual bool HasInplaceCopyImplementation(FileSystemType type) const = 0; - - // Creates a new file stream reader for a given filesystem URL |url| with an - // offset |offset|. |expected_modification_time| specifies the expected last - // modification if the value is non-null, the reader will check the underlying - // file's actual modification time to see if the file has been modified, and - // if it does any succeeding read operations should fail with - // ERR_UPLOAD_FILE_CHANGED error. - // This method itself does *not* check if the given path exists and is a - // regular file. - // The |length| argument says how many bytes are going to be read using the - // instance of the file stream reader. If unknown, then equal to -1. - virtual scoped_ptr<storage::FileStreamReader> CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time, - FileSystemContext* context) const = 0; - - // Creates a new file stream writer for a given filesystem URL |url| with an - // offset |offset|. - // This method itself does *not* check if the given path exists and is a - // regular file. - virtual scoped_ptr<FileStreamWriter> CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset, - FileSystemContext* context) const = 0; - - // Returns the specialized FileSystemQuotaUtil for this backend. - // This could return NULL if this backend does not support quota. - virtual FileSystemQuotaUtil* GetQuotaUtil() = 0; -}; - -// An interface to control external file system access permissions. -// TODO(satorux): Move this out of 'webkit/browser/fileapi'. crbug.com/257279 -class ExternalFileSystemBackend : public FileSystemBackend { - public: - // Returns true if |url| is allowed to be accessed. - // This is supposed to perform ExternalFileSystem-specific security - // checks. - virtual bool IsAccessAllowed(const storage::FileSystemURL& url) const = 0; - // Returns the list of top level directories that are exposed by this - // provider. This list is used to set appropriate child process file access - // permissions. - virtual std::vector<base::FilePath> GetRootDirectories() const = 0; - // Grants access to all external file system from extension identified with - // |extension_id|. - virtual void GrantFullAccessToExtension(const std::string& extension_id) = 0; - // Grants access to |virtual_path| from |origin_url|. - virtual void GrantFileAccessToExtension( - const std::string& extension_id, - const base::FilePath& virtual_path) = 0; - // Revokes file access from extension identified with |extension_id|. - virtual void RevokeAccessForExtension( - const std::string& extension_id) = 0; - // Gets virtual path by known filesystem path. Returns false when filesystem - // path is not exposed by this provider. - virtual bool GetVirtualPath(const base::FilePath& file_system_path, - base::FilePath* virtual_path) = 0; - // Gets a redirect URL for contents. e.g. Google Drive URL for hosted - // documents. Returns empty URL if the entry does not have the redirect URL. - virtual void GetRedirectURLForContents( - const storage::FileSystemURL& url, - const storage::URLCallback& callback) = 0; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_BACKEND_H_ +#include "storage/browser/fileapi/file_system_backend.h" diff --git a/webkit/browser/fileapi/file_system_context.cc b/webkit/browser/fileapi/file_system_context.cc deleted file mode 100644 index 7de00a5..0000000 --- a/webkit/browser/fileapi/file_system_context.cc +++ /dev/null @@ -1,644 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_context.h" - -#include "base/bind.h" -#include "base/single_thread_task_runner.h" -#include "base/stl_util.h" -#include "base/task_runner_util.h" -#include "net/url_request/url_request.h" -#include "url/gurl.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/copy_or_move_file_validator.h" -#include "webkit/browser/fileapi/external_mount_points.h" -#include "webkit/browser/fileapi/file_permission_policy.h" -#include "webkit/browser/fileapi/file_stream_writer.h" -#include "webkit/browser/fileapi/file_system_file_util.h" -#include "webkit/browser/fileapi/file_system_operation.h" -#include "webkit/browser/fileapi/file_system_operation_runner.h" -#include "webkit/browser/fileapi/file_system_options.h" -#include "webkit/browser/fileapi/file_system_quota_client.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/isolated_context.h" -#include "webkit/browser/fileapi/isolated_file_system_backend.h" -#include "webkit/browser/fileapi/mount_points.h" -#include "webkit/browser/fileapi/quota/quota_reservation.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend.h" -#include "webkit/browser/quota/quota_manager_proxy.h" -#include "webkit/browser/quota/special_storage_policy.h" -#include "webkit/common/fileapi/file_system_info.h" -#include "webkit/common/fileapi/file_system_util.h" - -using storage::QuotaClient; - -namespace storage { - -namespace { - -QuotaClient* CreateQuotaClient( - FileSystemContext* context, - bool is_incognito) { - return new FileSystemQuotaClient(context, is_incognito); -} - - -void DidGetMetadataForResolveURL( - const base::FilePath& path, - const FileSystemContext::ResolveURLCallback& callback, - const FileSystemInfo& info, - base::File::Error error, - const base::File::Info& file_info) { - if (error != base::File::FILE_OK) { - if (error == base::File::FILE_ERROR_NOT_FOUND) { - callback.Run(base::File::FILE_OK, info, path, - FileSystemContext::RESOLVED_ENTRY_NOT_FOUND); - } else { - callback.Run(error, FileSystemInfo(), base::FilePath(), - FileSystemContext::RESOLVED_ENTRY_NOT_FOUND); - } - return; - } - callback.Run(error, info, path, file_info.is_directory ? - FileSystemContext::RESOLVED_ENTRY_DIRECTORY : - FileSystemContext::RESOLVED_ENTRY_FILE); -} - -void RelayResolveURLCallback( - scoped_refptr<base::MessageLoopProxy> message_loop, - const FileSystemContext::ResolveURLCallback& callback, - base::File::Error result, - const FileSystemInfo& info, - const base::FilePath& file_path, - FileSystemContext::ResolvedEntryType type) { - message_loop->PostTask( - FROM_HERE, base::Bind(callback, result, info, file_path, type)); -} - -} // namespace - -// static -int FileSystemContext::GetPermissionPolicy(FileSystemType type) { - switch (type) { - case kFileSystemTypeTemporary: - case kFileSystemTypePersistent: - case kFileSystemTypeSyncable: - return FILE_PERMISSION_SANDBOX; - - case kFileSystemTypeDrive: - case kFileSystemTypeNativeForPlatformApp: - case kFileSystemTypeNativeLocal: - case kFileSystemTypeCloudDevice: - case kFileSystemTypeProvided: - case kFileSystemTypeDeviceMediaAsFileStorage: - return FILE_PERMISSION_USE_FILE_PERMISSION; - - case kFileSystemTypeRestrictedNativeLocal: - return FILE_PERMISSION_READ_ONLY | - FILE_PERMISSION_USE_FILE_PERMISSION; - - case kFileSystemTypeDeviceMedia: - case kFileSystemTypeIphoto: - case kFileSystemTypeItunes: - case kFileSystemTypeNativeMedia: - case kFileSystemTypePicasa: - return FILE_PERMISSION_USE_FILE_PERMISSION; - - // Following types are only accessed via IsolatedFileSystem, and - // don't have their own permission policies. - case kFileSystemTypeDragged: - case kFileSystemTypeForTransientFile: - case kFileSystemTypePluginPrivate: - return FILE_PERMISSION_ALWAYS_DENY; - - // Following types only appear as mount_type, and will not be - // queried for their permission policies. - case kFileSystemTypeIsolated: - case kFileSystemTypeExternal: - return FILE_PERMISSION_ALWAYS_DENY; - - // Following types should not be used to access files by FileAPI clients. - case kFileSystemTypeTest: - case kFileSystemTypeSyncableForInternalSync: - case kFileSystemInternalTypeEnumEnd: - case kFileSystemInternalTypeEnumStart: - case kFileSystemTypeUnknown: - return FILE_PERMISSION_ALWAYS_DENY; - } - NOTREACHED(); - return FILE_PERMISSION_ALWAYS_DENY; -} - -FileSystemContext::FileSystemContext( - base::SingleThreadTaskRunner* io_task_runner, - base::SequencedTaskRunner* file_task_runner, - ExternalMountPoints* external_mount_points, - storage::SpecialStoragePolicy* special_storage_policy, - storage::QuotaManagerProxy* quota_manager_proxy, - ScopedVector<FileSystemBackend> additional_backends, - const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers, - const base::FilePath& partition_path, - const FileSystemOptions& options) - : io_task_runner_(io_task_runner), - default_file_task_runner_(file_task_runner), - quota_manager_proxy_(quota_manager_proxy), - sandbox_delegate_( - new SandboxFileSystemBackendDelegate(quota_manager_proxy, - file_task_runner, - partition_path, - special_storage_policy, - options)), - sandbox_backend_(new SandboxFileSystemBackend(sandbox_delegate_.get())), - isolated_backend_(new IsolatedFileSystemBackend()), - plugin_private_backend_( - new PluginPrivateFileSystemBackend(file_task_runner, - partition_path, - special_storage_policy, - options)), - additional_backends_(additional_backends.Pass()), - auto_mount_handlers_(auto_mount_handlers), - external_mount_points_(external_mount_points), - partition_path_(partition_path), - is_incognito_(options.is_incognito()), - operation_runner_(new FileSystemOperationRunner(this)) { - RegisterBackend(sandbox_backend_.get()); - RegisterBackend(isolated_backend_.get()); - RegisterBackend(plugin_private_backend_.get()); - - for (ScopedVector<FileSystemBackend>::const_iterator iter = - additional_backends_.begin(); - iter != additional_backends_.end(); ++iter) { - RegisterBackend(*iter); - } - - if (quota_manager_proxy) { - // Quota client assumes all backends have registered. - quota_manager_proxy->RegisterClient(CreateQuotaClient( - this, options.is_incognito())); - } - - sandbox_backend_->Initialize(this); - isolated_backend_->Initialize(this); - plugin_private_backend_->Initialize(this); - for (ScopedVector<FileSystemBackend>::const_iterator iter = - additional_backends_.begin(); - iter != additional_backends_.end(); ++iter) { - (*iter)->Initialize(this); - } - - // Additional mount points must be added before regular system-wide - // mount points. - if (external_mount_points) - url_crackers_.push_back(external_mount_points); - url_crackers_.push_back(ExternalMountPoints::GetSystemInstance()); - url_crackers_.push_back(IsolatedContext::GetInstance()); -} - -bool FileSystemContext::DeleteDataForOriginOnFileTaskRunner( - const GURL& origin_url) { - DCHECK(default_file_task_runner()->RunsTasksOnCurrentThread()); - DCHECK(origin_url == origin_url.GetOrigin()); - - bool success = true; - for (FileSystemBackendMap::iterator iter = backend_map_.begin(); - iter != backend_map_.end(); - ++iter) { - FileSystemBackend* backend = iter->second; - if (!backend->GetQuotaUtil()) - continue; - if (backend->GetQuotaUtil()->DeleteOriginDataOnFileTaskRunner( - this, quota_manager_proxy(), origin_url, iter->first) - != base::File::FILE_OK) { - // Continue the loop, but record the failure. - success = false; - } - } - - return success; -} - -scoped_refptr<QuotaReservation> -FileSystemContext::CreateQuotaReservationOnFileTaskRunner( - const GURL& origin_url, - FileSystemType type) { - DCHECK(default_file_task_runner()->RunsTasksOnCurrentThread()); - FileSystemBackend* backend = GetFileSystemBackend(type); - if (!backend || !backend->GetQuotaUtil()) - return scoped_refptr<QuotaReservation>(); - return backend->GetQuotaUtil()->CreateQuotaReservationOnFileTaskRunner( - origin_url, type); -} - -void FileSystemContext::Shutdown() { - if (!io_task_runner_->RunsTasksOnCurrentThread()) { - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&FileSystemContext::Shutdown, - make_scoped_refptr(this))); - return; - } - operation_runner_->Shutdown(); -} - -FileSystemQuotaUtil* -FileSystemContext::GetQuotaUtil(FileSystemType type) const { - FileSystemBackend* backend = GetFileSystemBackend(type); - if (!backend) - return NULL; - return backend->GetQuotaUtil(); -} - -AsyncFileUtil* FileSystemContext::GetAsyncFileUtil( - FileSystemType type) const { - FileSystemBackend* backend = GetFileSystemBackend(type); - if (!backend) - return NULL; - return backend->GetAsyncFileUtil(type); -} - -CopyOrMoveFileValidatorFactory* -FileSystemContext::GetCopyOrMoveFileValidatorFactory( - FileSystemType type, base::File::Error* error_code) const { - DCHECK(error_code); - *error_code = base::File::FILE_OK; - FileSystemBackend* backend = GetFileSystemBackend(type); - if (!backend) - return NULL; - return backend->GetCopyOrMoveFileValidatorFactory( - type, error_code); -} - -FileSystemBackend* FileSystemContext::GetFileSystemBackend( - FileSystemType type) const { - FileSystemBackendMap::const_iterator found = backend_map_.find(type); - if (found != backend_map_.end()) - return found->second; - NOTREACHED() << "Unknown filesystem type: " << type; - return NULL; -} - -WatcherManager* FileSystemContext::GetWatcherManager( - FileSystemType type) const { - FileSystemBackend* backend = GetFileSystemBackend(type); - if (!backend) - return NULL; - return backend->GetWatcherManager(type); -} - -bool FileSystemContext::IsSandboxFileSystem(FileSystemType type) const { - FileSystemBackendMap::const_iterator found = backend_map_.find(type); - return found != backend_map_.end() && found->second->GetQuotaUtil(); -} - -const UpdateObserverList* FileSystemContext::GetUpdateObservers( - FileSystemType type) const { - FileSystemBackend* backend = GetFileSystemBackend(type); - if (backend->GetQuotaUtil()) - return backend->GetQuotaUtil()->GetUpdateObservers(type); - return NULL; -} - -const ChangeObserverList* FileSystemContext::GetChangeObservers( - FileSystemType type) const { - FileSystemBackend* backend = GetFileSystemBackend(type); - if (backend->GetQuotaUtil()) - return backend->GetQuotaUtil()->GetChangeObservers(type); - return NULL; -} - -const AccessObserverList* FileSystemContext::GetAccessObservers( - FileSystemType type) const { - FileSystemBackend* backend = GetFileSystemBackend(type); - if (backend->GetQuotaUtil()) - return backend->GetQuotaUtil()->GetAccessObservers(type); - return NULL; -} - -void FileSystemContext::GetFileSystemTypes( - std::vector<FileSystemType>* types) const { - types->clear(); - for (FileSystemBackendMap::const_iterator iter = backend_map_.begin(); - iter != backend_map_.end(); ++iter) - types->push_back(iter->first); -} - -ExternalFileSystemBackend* -FileSystemContext::external_backend() const { - return static_cast<ExternalFileSystemBackend*>( - GetFileSystemBackend(kFileSystemTypeExternal)); -} - -void FileSystemContext::OpenFileSystem( - const GURL& origin_url, - FileSystemType type, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(!callback.is_null()); - - if (!FileSystemContext::IsSandboxFileSystem(type)) { - // Disallow opening a non-sandboxed filesystem. - callback.Run(GURL(), std::string(), base::File::FILE_ERROR_SECURITY); - return; - } - - FileSystemBackend* backend = GetFileSystemBackend(type); - if (!backend) { - callback.Run(GURL(), std::string(), base::File::FILE_ERROR_SECURITY); - return; - } - - backend->ResolveURL( - CreateCrackedFileSystemURL(origin_url, type, base::FilePath()), - mode, - callback); -} - -void FileSystemContext::ResolveURL( - const FileSystemURL& url, - const ResolveURLCallback& callback) { - DCHECK(!callback.is_null()); - - // If not on IO thread, forward before passing the task to the backend. - if (!io_task_runner_->RunsTasksOnCurrentThread()) { - ResolveURLCallback relay_callback = - base::Bind(&RelayResolveURLCallback, - base::MessageLoopProxy::current(), callback); - io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&FileSystemContext::ResolveURL, this, url, relay_callback)); - return; - } - - FileSystemBackend* backend = GetFileSystemBackend(url.type()); - if (!backend) { - callback.Run(base::File::FILE_ERROR_SECURITY, - FileSystemInfo(), base::FilePath(), - FileSystemContext::RESOLVED_ENTRY_NOT_FOUND); - return; - } - - backend->ResolveURL( - url, - OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, - base::Bind(&FileSystemContext::DidOpenFileSystemForResolveURL, - this, - url, - callback)); -} - -void FileSystemContext::AttemptAutoMountForURLRequest( - const net::URLRequest* url_request, - const std::string& storage_domain, - const StatusCallback& callback) { - FileSystemURL filesystem_url(url_request->url()); - if (filesystem_url.type() == kFileSystemTypeExternal) { - for (size_t i = 0; i < auto_mount_handlers_.size(); i++) { - if (auto_mount_handlers_[i].Run(url_request, filesystem_url, - storage_domain, callback)) { - return; - } - } - } - callback.Run(base::File::FILE_ERROR_NOT_FOUND); -} - -void FileSystemContext::DeleteFileSystem( - const GURL& origin_url, - FileSystemType type, - const StatusCallback& callback) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(origin_url == origin_url.GetOrigin()); - DCHECK(!callback.is_null()); - - FileSystemBackend* backend = GetFileSystemBackend(type); - if (!backend) { - callback.Run(base::File::FILE_ERROR_SECURITY); - return; - } - if (!backend->GetQuotaUtil()) { - callback.Run(base::File::FILE_ERROR_INVALID_OPERATION); - return; - } - - base::PostTaskAndReplyWithResult( - default_file_task_runner(), - FROM_HERE, - // It is safe to pass Unretained(quota_util) since context owns it. - base::Bind(&FileSystemQuotaUtil::DeleteOriginDataOnFileTaskRunner, - base::Unretained(backend->GetQuotaUtil()), - make_scoped_refptr(this), - base::Unretained(quota_manager_proxy()), - origin_url, - type), - callback); -} - -scoped_ptr<storage::FileStreamReader> FileSystemContext::CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time) { - if (!url.is_valid()) - return scoped_ptr<storage::FileStreamReader>(); - FileSystemBackend* backend = GetFileSystemBackend(url.type()); - if (!backend) - return scoped_ptr<storage::FileStreamReader>(); - return backend->CreateFileStreamReader( - url, offset, expected_modification_time, this); -} - -scoped_ptr<FileStreamWriter> FileSystemContext::CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset) { - if (!url.is_valid()) - return scoped_ptr<FileStreamWriter>(); - FileSystemBackend* backend = GetFileSystemBackend(url.type()); - if (!backend) - return scoped_ptr<FileStreamWriter>(); - return backend->CreateFileStreamWriter(url, offset, this); -} - -scoped_ptr<FileSystemOperationRunner> -FileSystemContext::CreateFileSystemOperationRunner() { - return make_scoped_ptr(new FileSystemOperationRunner(this)); -} - -FileSystemURL FileSystemContext::CrackURL(const GURL& url) const { - return CrackFileSystemURL(FileSystemURL(url)); -} - -FileSystemURL FileSystemContext::CreateCrackedFileSystemURL( - const GURL& origin, - FileSystemType type, - const base::FilePath& path) const { - return CrackFileSystemURL(FileSystemURL(origin, type, path)); -} - -#if defined(OS_CHROMEOS) -void FileSystemContext::EnableTemporaryFileSystemInIncognito() { - sandbox_backend_->set_enable_temporary_file_system_in_incognito(true); -} -#endif - -bool FileSystemContext::CanServeURLRequest(const FileSystemURL& url) const { - // We never support accessing files in isolated filesystems via an URL. - if (url.mount_type() == kFileSystemTypeIsolated) - return false; -#if defined(OS_CHROMEOS) - if (url.type() == kFileSystemTypeTemporary && - sandbox_backend_->enable_temporary_file_system_in_incognito()) { - return true; - } -#endif - return !is_incognito_ || !FileSystemContext::IsSandboxFileSystem(url.type()); -} - -bool FileSystemContext::ShouldFlushOnWriteCompletion( - FileSystemType type) const { - if (IsSandboxFileSystem(type)) { - // Disable Flush() for each write operation on SandboxFileSystems since it - // hurts the performance, assuming the FileSystems are stored in a local - // disk, we don't need to keep calling fsync() for it. - // On the other hand, other FileSystems that may stored on a removable media - // should be Flush()ed as soon as a write operation is completed, so that - // written data is saved over sudden media removal. - return false; - } - return true; -} - -void FileSystemContext::OpenPluginPrivateFileSystem( - const GURL& origin_url, - FileSystemType type, - const std::string& filesystem_id, - const std::string& plugin_id, - OpenFileSystemMode mode, - const StatusCallback& callback) { - DCHECK(plugin_private_backend_); - plugin_private_backend_->OpenPrivateFileSystem( - origin_url, type, filesystem_id, plugin_id, mode, callback); -} - -FileSystemContext::~FileSystemContext() { -} - -void FileSystemContext::DeleteOnCorrectThread() const { - if (!io_task_runner_->RunsTasksOnCurrentThread() && - io_task_runner_->DeleteSoon(FROM_HERE, this)) { - return; - } - delete this; -} - -FileSystemOperation* FileSystemContext::CreateFileSystemOperation( - const FileSystemURL& url, base::File::Error* error_code) { - if (!url.is_valid()) { - if (error_code) - *error_code = base::File::FILE_ERROR_INVALID_URL; - return NULL; - } - - FileSystemBackend* backend = GetFileSystemBackend(url.type()); - if (!backend) { - if (error_code) - *error_code = base::File::FILE_ERROR_FAILED; - return NULL; - } - - base::File::Error fs_error = base::File::FILE_OK; - FileSystemOperation* operation = - backend->CreateFileSystemOperation(url, this, &fs_error); - - if (error_code) - *error_code = fs_error; - return operation; -} - -FileSystemURL FileSystemContext::CrackFileSystemURL( - const FileSystemURL& url) const { - if (!url.is_valid()) - return FileSystemURL(); - - // The returned value in case there is no crackers which can crack the url. - // This is valid situation for non isolated/external file systems. - FileSystemURL current = url; - - // File system may be mounted multiple times (e.g., an isolated filesystem on - // top of an external filesystem). Hence cracking needs to be iterated. - for (;;) { - FileSystemURL cracked = current; - for (size_t i = 0; i < url_crackers_.size(); ++i) { - if (!url_crackers_[i]->HandlesFileSystemMountType(current.type())) - continue; - cracked = url_crackers_[i]->CrackFileSystemURL(current); - if (cracked.is_valid()) - break; - } - if (cracked == current) - break; - current = cracked; - } - return current; -} - -void FileSystemContext::RegisterBackend(FileSystemBackend* backend) { - const FileSystemType mount_types[] = { - kFileSystemTypeTemporary, - kFileSystemTypePersistent, - kFileSystemTypeIsolated, - kFileSystemTypeExternal, - }; - // Register file system backends for public mount types. - for (size_t j = 0; j < ARRAYSIZE_UNSAFE(mount_types); ++j) { - if (backend->CanHandleType(mount_types[j])) { - const bool inserted = backend_map_.insert( - std::make_pair(mount_types[j], backend)).second; - DCHECK(inserted); - } - } - // Register file system backends for internal types. - for (int t = kFileSystemInternalTypeEnumStart + 1; - t < kFileSystemInternalTypeEnumEnd; ++t) { - FileSystemType type = static_cast<FileSystemType>(t); - if (backend->CanHandleType(type)) { - const bool inserted = backend_map_.insert( - std::make_pair(type, backend)).second; - DCHECK(inserted); - } - } -} - -void FileSystemContext::DidOpenFileSystemForResolveURL( - const FileSystemURL& url, - const FileSystemContext::ResolveURLCallback& callback, - const GURL& filesystem_root, - const std::string& filesystem_name, - base::File::Error error) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - if (error != base::File::FILE_OK) { - callback.Run(error, FileSystemInfo(), base::FilePath(), - FileSystemContext::RESOLVED_ENTRY_NOT_FOUND); - return; - } - - storage::FileSystemInfo info( - filesystem_name, filesystem_root, url.mount_type()); - - // Extract the virtual path not containing a filesystem type part from |url|. - base::FilePath parent = CrackURL(filesystem_root).virtual_path(); - base::FilePath child = url.virtual_path(); - base::FilePath path; - - if (parent.empty()) { - path = child; - } else if (parent != child) { - bool result = parent.AppendRelativePath(child, &path); - DCHECK(result); - } - - operation_runner()->GetMetadata( - url, base::Bind(&DidGetMetadataForResolveURL, path, callback, info)); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_context.h b/webkit/browser/fileapi/file_system_context.h index f410195..6b016b9 100644 --- a/webkit/browser/fileapi/file_system_context.h +++ b/webkit/browser/fileapi/file_system_context.h @@ -1,428 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_ - -#include <map> -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/files/file.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/sequenced_task_runner_helpers.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/open_file_system_mode.h" -#include "webkit/browser/fileapi/plugin_private_file_system_backend.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" -#include "webkit/browser/fileapi/task_runner_bound_observer_list.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_types.h" - -namespace base { -class FilePath; -class SequencedTaskRunner; -class SingleThreadTaskRunner; -} - -namespace chrome { -class NativeMediaFileUtilTest; -} - -namespace storage { -class QuotaManagerProxy; -class SpecialStoragePolicy; -} - -namespace net { -class URLRequest; -} - -namespace storage { -class BlobURLRequestJobTest; -class FileStreamReader; -} - -namespace storage { - -class AsyncFileUtil; -class CopyOrMoveFileValidatorFactory; -class ExternalFileSystemBackend; -class ExternalMountPoints; -class FileStreamWriter; -class FileSystemBackend; -class FileSystemFileUtil; -class FileSystemOperation; -class FileSystemOperationRunner; -class FileSystemOptions; -class FileSystemQuotaUtil; -class FileSystemURL; -class IsolatedFileSystemBackend; -class MountPoints; -class QuotaReservation; -class SandboxFileSystemBackend; -class WatchManager; - -struct DefaultContextDeleter; -struct FileSystemInfo; - -// An auto mount handler will attempt to mount the file system requested in -// |url_request|. If the URL is for this auto mount handler, it returns true -// and calls |callback| when the attempt is complete. If the auto mounter -// does not recognize the URL, it returns false and does not call |callback|. -// Called on the IO thread. -typedef base::Callback<bool( - const net::URLRequest* url_request, - const FileSystemURL& filesystem_url, - const std::string& storage_domain, - const base::Callback<void(base::File::Error result)>& callback)> - URLRequestAutoMountHandler; - -// This class keeps and provides a file system context for FileSystem API. -// An instance of this class is created and owned by profile. -class STORAGE_EXPORT FileSystemContext - : public base::RefCountedThreadSafe<FileSystemContext, - DefaultContextDeleter> { - public: - // Returns file permission policy we should apply for the given |type|. - // The return value must be bitwise-or'd of FilePermissionPolicy. - // - // Note: if a part of a filesystem is returned via 'Isolated' mount point, - // its per-filesystem permission overrides the underlying filesystem's - // permission policy. - static int GetPermissionPolicy(FileSystemType type); - - // file_task_runner is used as default TaskRunner. - // Unless a FileSystemBackend is overridden in CreateFileSystemOperation, - // it is used for all file operations and file related meta operations. - // The code assumes that file_task_runner->RunsTasksOnCurrentThread() - // returns false if the current task is not running on the thread that allows - // blocking file operations (like SequencedWorkerPool implementation does). - // - // |external_mount_points| contains non-system external mount points available - // in the context. If not NULL, it will be used during URL cracking. - // |external_mount_points| may be NULL only on platforms different from - // ChromeOS (i.e. platforms that don't use external_mount_point_provider). - // - // |additional_backends| are added to the internal backend map - // to serve filesystem requests for non-regular types. - // If none is given, this context only handles HTML5 Sandbox FileSystem - // and Drag-and-drop Isolated FileSystem requests. - // - // |auto_mount_handlers| are used to resolve calls to - // AttemptAutoMountForURLRequest. Only external filesystems are auto mounted - // when a filesystem: URL request is made. - FileSystemContext( - base::SingleThreadTaskRunner* io_task_runner, - base::SequencedTaskRunner* file_task_runner, - ExternalMountPoints* external_mount_points, - storage::SpecialStoragePolicy* special_storage_policy, - storage::QuotaManagerProxy* quota_manager_proxy, - ScopedVector<FileSystemBackend> additional_backends, - const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers, - const base::FilePath& partition_path, - const FileSystemOptions& options); - - bool DeleteDataForOriginOnFileTaskRunner(const GURL& origin_url); - - // Creates a new QuotaReservation for the given |origin_url| and |type|. - // Returns NULL if |type| does not support quota or reservation fails. - // This should be run on |default_file_task_runner_| and the returned value - // should be destroyed on the runner. - scoped_refptr<QuotaReservation> CreateQuotaReservationOnFileTaskRunner( - const GURL& origin_url, - FileSystemType type); - - storage::QuotaManagerProxy* quota_manager_proxy() const { - return quota_manager_proxy_.get(); - } - - // Discards inflight operations in the operation runner. - void Shutdown(); - - // Returns a quota util for a given filesystem type. This may - // return NULL if the type does not support the usage tracking or - // it is not a quota-managed storage. - FileSystemQuotaUtil* GetQuotaUtil(FileSystemType type) const; - - // Returns the appropriate AsyncFileUtil instance for the given |type|. - AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) const; - - // Returns the appropriate CopyOrMoveFileValidatorFactory for the given - // |type|. If |error_code| is File::FILE_OK and the result is NULL, - // then no validator is required. - CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( - FileSystemType type, base::File::Error* error_code) const; - - // Returns the file system backend instance for the given |type|. - // This may return NULL if it is given an invalid or unsupported filesystem - // type. - FileSystemBackend* GetFileSystemBackend( - FileSystemType type) const; - - // Returns the watcher manager for the given |type|. - // This may return NULL if the type does not support watching. - WatcherManager* GetWatcherManager(FileSystemType type) const; - - // Returns true for sandboxed filesystems. Currently this does - // the same as GetQuotaUtil(type) != NULL. (In an assumption that - // all sandboxed filesystems must cooperate with QuotaManager so that - // they can get deleted) - bool IsSandboxFileSystem(FileSystemType type) const; - - // Returns observers for the given filesystem type. - const UpdateObserverList* GetUpdateObservers(FileSystemType type) const; - const ChangeObserverList* GetChangeObservers(FileSystemType type) const; - const AccessObserverList* GetAccessObservers(FileSystemType type) const; - - // Returns all registered filesystem types. - void GetFileSystemTypes(std::vector<FileSystemType>* types) const; - - // Returns a FileSystemBackend instance for external filesystem - // type, which is used only by chromeos for now. This is equivalent to - // calling GetFileSystemBackend(kFileSystemTypeExternal). - ExternalFileSystemBackend* external_backend() const; - - // Used for OpenFileSystem. - typedef base::Callback<void(const GURL& root, - const std::string& name, - base::File::Error result)> - OpenFileSystemCallback; - - // Used for ResolveURL. - enum ResolvedEntryType { - RESOLVED_ENTRY_FILE, - RESOLVED_ENTRY_DIRECTORY, - RESOLVED_ENTRY_NOT_FOUND, - }; - typedef base::Callback<void(base::File::Error result, - const FileSystemInfo& info, - const base::FilePath& file_path, - ResolvedEntryType type)> ResolveURLCallback; - - // Used for DeleteFileSystem and OpenPluginPrivateFileSystem. - typedef base::Callback<void(base::File::Error result)> StatusCallback; - - // Opens the filesystem for the given |origin_url| and |type|, and dispatches - // |callback| on completion. - // If |create| is true this may actually set up a filesystem instance - // (e.g. by creating the root directory or initializing the database - // entry etc). - void OpenFileSystem( - const GURL& origin_url, - FileSystemType type, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback); - - // Opens the filesystem for the given |url| as read-only, if the filesystem - // backend referred by the URL allows opening by resolveURL. Otherwise it - // fails with FILE_ERROR_SECURITY. The entry pointed by the URL can be - // absent; in that case RESOLVED_ENTRY_NOT_FOUND type is returned to the - // callback for indicating the absence. Can be called from any thread with - // a message loop. |callback| is invoked on the caller thread. - void ResolveURL( - const FileSystemURL& url, - const ResolveURLCallback& callback); - - // Attempts to mount the filesystem needed to satisfy |url_request| made - // from |storage_domain|. If an appropriate file system is not found, - // callback will return an error. - void AttemptAutoMountForURLRequest(const net::URLRequest* url_request, - const std::string& storage_domain, - const StatusCallback& callback); - - // Deletes the filesystem for the given |origin_url| and |type|. This should - // be called on the IO thread. - void DeleteFileSystem( - const GURL& origin_url, - FileSystemType type, - const StatusCallback& callback); - - // Creates new FileStreamReader instance to read a file pointed by the given - // filesystem URL |url| starting from |offset|. |expected_modification_time| - // specifies the expected last modification if the value is non-null, the - // reader will check the underlying file's actual modification time to see if - // the file has been modified, and if it does any succeeding read operations - // should fail with ERR_UPLOAD_FILE_CHANGED error. - // This method internally cracks the |url|, get an appropriate - // FileSystemBackend for the URL and call the backend's CreateFileReader. - // The resolved FileSystemBackend could perform further specialization - // depending on the filesystem type pointed by the |url|. - scoped_ptr<storage::FileStreamReader> CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time); - - // Creates new FileStreamWriter instance to write into a file pointed by - // |url| from |offset|. - scoped_ptr<FileStreamWriter> CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset); - - // Creates a new FileSystemOperationRunner. - scoped_ptr<FileSystemOperationRunner> CreateFileSystemOperationRunner(); - - base::SequencedTaskRunner* default_file_task_runner() { - return default_file_task_runner_.get(); - } - - FileSystemOperationRunner* operation_runner() { - return operation_runner_.get(); - } - - const base::FilePath& partition_path() const { return partition_path_; } - - // Same as |CrackFileSystemURL|, but cracks FileSystemURL created from |url|. - FileSystemURL CrackURL(const GURL& url) const; - // Same as |CrackFileSystemURL|, but cracks FileSystemURL created from method - // arguments. - FileSystemURL CreateCrackedFileSystemURL(const GURL& origin, - FileSystemType type, - const base::FilePath& path) const; - -#if defined(OS_CHROMEOS) - // Used only on ChromeOS for now. - void EnableTemporaryFileSystemInIncognito(); -#endif - - SandboxFileSystemBackendDelegate* sandbox_delegate() { - return sandbox_delegate_.get(); - } - - // Returns true if the requested url is ok to be served. - // (E.g. this returns false if the context is created for incognito mode) - bool CanServeURLRequest(const FileSystemURL& url) const; - - // Returns true if a file in the file system should be flushed for each write - // completion. - bool ShouldFlushOnWriteCompletion(FileSystemType type) const; - - // This must be used to open 'plugin private' filesystem. - // See "plugin_private_file_system_backend.h" for more details. - void OpenPluginPrivateFileSystem( - const GURL& origin_url, - FileSystemType type, - const std::string& filesystem_id, - const std::string& plugin_id, - OpenFileSystemMode mode, - const StatusCallback& callback); - - private: - typedef std::map<FileSystemType, FileSystemBackend*> - FileSystemBackendMap; - - // For CreateFileSystemOperation. - friend class FileSystemOperationRunner; - - // For sandbox_backend(). - friend class content::SandboxFileSystemTestHelper; - - // For plugin_private_backend(). - friend class content::PluginPrivateFileSystemBackendTest; - - // Deleters. - friend struct DefaultContextDeleter; - friend class base::DeleteHelper<FileSystemContext>; - friend class base::RefCountedThreadSafe<FileSystemContext, - DefaultContextDeleter>; - ~FileSystemContext(); - - void DeleteOnCorrectThread() const; - - // Creates a new FileSystemOperation instance by getting an appropriate - // FileSystemBackend for |url| and calling the backend's corresponding - // CreateFileSystemOperation method. - // The resolved FileSystemBackend could perform further specialization - // depending on the filesystem type pointed by the |url|. - // - // Called by FileSystemOperationRunner. - FileSystemOperation* CreateFileSystemOperation( - const FileSystemURL& url, - base::File::Error* error_code); - - // For non-cracked isolated and external mount points, returns a FileSystemURL - // created by cracking |url|. The url is cracked using MountPoints registered - // as |url_crackers_|. If the url cannot be cracked, returns invalid - // FileSystemURL. - // - // If the original url does not point to an isolated or external filesystem, - // returns the original url, without attempting to crack it. - FileSystemURL CrackFileSystemURL(const FileSystemURL& url) const; - - // For initial backend_map construction. This must be called only from - // the constructor. - void RegisterBackend(FileSystemBackend* backend); - - void DidOpenFileSystemForResolveURL( - const FileSystemURL& url, - const ResolveURLCallback& callback, - const GURL& filesystem_root, - const std::string& filesystem_name, - base::File::Error error); - - // Returns a FileSystemBackend, used only by test code. - SandboxFileSystemBackend* sandbox_backend() const { - return sandbox_backend_.get(); - } - - // Used only by test code. - PluginPrivateFileSystemBackend* plugin_private_backend() const { - return plugin_private_backend_.get(); - } - - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; - scoped_refptr<base::SequencedTaskRunner> default_file_task_runner_; - - scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; - - scoped_ptr<SandboxFileSystemBackendDelegate> sandbox_delegate_; - - // Regular file system backends. - scoped_ptr<SandboxFileSystemBackend> sandbox_backend_; - scoped_ptr<IsolatedFileSystemBackend> isolated_backend_; - - // Additional file system backends. - scoped_ptr<PluginPrivateFileSystemBackend> plugin_private_backend_; - ScopedVector<FileSystemBackend> additional_backends_; - - std::vector<URLRequestAutoMountHandler> auto_mount_handlers_; - - // Registered file system backends. - // The map must be constructed in the constructor since it can be accessed - // on multiple threads. - // This map itself doesn't retain each backend's ownership; ownerships - // of the backends are held by additional_backends_ or other scoped_ptr - // backend fields. - FileSystemBackendMap backend_map_; - - // External mount points visible in the file system context (excluding system - // external mount points). - scoped_refptr<ExternalMountPoints> external_mount_points_; - - // MountPoints used to crack FileSystemURLs. The MountPoints are ordered - // in order they should try to crack a FileSystemURL. - std::vector<MountPoints*> url_crackers_; - - // The base path of the storage partition for this context. - const base::FilePath partition_path_; - - bool is_incognito_; - - scoped_ptr<FileSystemOperationRunner> operation_runner_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemContext); -}; - -struct DefaultContextDeleter { - static void Destruct(const FileSystemContext* context) { - context->DeleteOnCorrectThread(); - } -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_ +#include "storage/browser/fileapi/file_system_context.h" diff --git a/webkit/browser/fileapi/file_system_dir_url_request_job.cc b/webkit/browser/fileapi/file_system_dir_url_request_job.cc deleted file mode 100644 index acedbce..0000000 --- a/webkit/browser/fileapi/file_system_dir_url_request_job.cc +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_dir_url_request_job.h" - -#include <algorithm> - -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" -#include "build/build_config.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/base/net_util.h" -#include "net/url_request/url_request.h" -#include "url/gurl.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_runner.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/common/fileapi/directory_entry.h" -#include "webkit/common/fileapi/file_system_util.h" - -using net::NetworkDelegate; -using net::URLRequest; -using net::URLRequestJob; -using net::URLRequestStatus; - -namespace storage { - -FileSystemDirURLRequestJob::FileSystemDirURLRequestJob( - URLRequest* request, - NetworkDelegate* network_delegate, - const std::string& storage_domain, - FileSystemContext* file_system_context) - : URLRequestJob(request, network_delegate), - storage_domain_(storage_domain), - file_system_context_(file_system_context), - weak_factory_(this) { -} - -FileSystemDirURLRequestJob::~FileSystemDirURLRequestJob() { -} - -bool FileSystemDirURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size, - int *bytes_read) { - int count = std::min(dest_size, static_cast<int>(data_.size())); - if (count > 0) { - memcpy(dest->data(), data_.data(), count); - data_.erase(0, count); - } - *bytes_read = count; - return true; -} - -void FileSystemDirURLRequestJob::Start() { - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&FileSystemDirURLRequestJob::StartAsync, - weak_factory_.GetWeakPtr())); -} - -void FileSystemDirURLRequestJob::Kill() { - URLRequestJob::Kill(); - weak_factory_.InvalidateWeakPtrs(); -} - -bool FileSystemDirURLRequestJob::GetMimeType(std::string* mime_type) const { - *mime_type = "text/html"; - return true; -} - -bool FileSystemDirURLRequestJob::GetCharset(std::string* charset) { - *charset = "utf-8"; - return true; -} - -void FileSystemDirURLRequestJob::StartAsync() { - if (!request_) - return; - url_ = file_system_context_->CrackURL(request_->url()); - if (!url_.is_valid()) { - file_system_context_->AttemptAutoMountForURLRequest( - request_, - storage_domain_, - base::Bind(&FileSystemDirURLRequestJob::DidAttemptAutoMount, - weak_factory_.GetWeakPtr())); - return; - } - if (!file_system_context_->CanServeURLRequest(url_)) { - // In incognito mode the API is not usable and there should be no data. - if (url_.is_valid() && VirtualPath::IsRootPath(url_.virtual_path())) { - // Return an empty directory if the filesystem root is queried. - DidReadDirectory(base::File::FILE_OK, - std::vector<DirectoryEntry>(), - false); - return; - } - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, - net::ERR_FILE_NOT_FOUND)); - return; - } - file_system_context_->operation_runner()->ReadDirectory( - url_, - base::Bind(&FileSystemDirURLRequestJob::DidReadDirectory, this)); -} - -void FileSystemDirURLRequestJob::DidAttemptAutoMount(base::File::Error result) { - if (result >= 0 && - file_system_context_->CrackURL(request_->url()).is_valid()) { - StartAsync(); - } else { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, - net::ERR_FILE_NOT_FOUND)); - } -} - -void FileSystemDirURLRequestJob::DidReadDirectory( - base::File::Error result, - const std::vector<DirectoryEntry>& entries, - bool has_more) { - if (result != base::File::FILE_OK) { - int rv = net::ERR_FILE_NOT_FOUND; - if (result == base::File::FILE_ERROR_INVALID_URL) - rv = net::ERR_INVALID_URL; - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); - return; - } - - if (!request_) - return; - - if (data_.empty()) { - base::FilePath relative_path = url_.path(); -#if defined(OS_POSIX) - relative_path = - base::FilePath(FILE_PATH_LITERAL("/") + relative_path.value()); -#endif - const base::string16& title = relative_path.LossyDisplayName(); - data_.append(net::GetDirectoryListingHeader(title)); - } - - typedef std::vector<DirectoryEntry>::const_iterator EntryIterator; - for (EntryIterator it = entries.begin(); it != entries.end(); ++it) { - const base::string16& name = base::FilePath(it->name).LossyDisplayName(); - data_.append(net::GetDirectoryListingEntry( - name, std::string(), it->is_directory, it->size, - it->last_modified_time)); - } - - if (!has_more) { - set_expected_content_size(data_.size()); - NotifyHeadersComplete(); - } -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_dir_url_request_job.h b/webkit/browser/fileapi/file_system_dir_url_request_job.h index 081792d..ad3285d 100644 --- a/webkit/browser/fileapi/file_system_dir_url_request_job.h +++ b/webkit/browser/fileapi/file_system_dir_url_request_job.h @@ -1,69 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_DIR_URL_REQUEST_JOB_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_DIR_URL_REQUEST_JOB_H_ - -#include <string> -#include <vector> - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop_proxy.h" -#include "net/url_request/url_request_job.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/storage_browser_export.h" - -namespace storage { - -class FileSystemContext; -struct DirectoryEntry; - -// A request job that handles reading filesystem: URLs for directories. -class STORAGE_EXPORT_PRIVATE FileSystemDirURLRequestJob - : public net::URLRequestJob { - public: - FileSystemDirURLRequestJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& storage_domain, - FileSystemContext* file_system_context); - - // URLRequestJob methods: - virtual void Start() OVERRIDE; - virtual void Kill() OVERRIDE; - virtual bool ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) OVERRIDE; - virtual bool GetCharset(std::string* charset) OVERRIDE; - - // FilterContext methods (via URLRequestJob): - virtual bool GetMimeType(std::string* mime_type) const OVERRIDE; - // TODO(adamk): Implement GetResponseInfo and GetResponseCode to simulate - // an HTTP response. - - private: - class CallbackDispatcher; - - virtual ~FileSystemDirURLRequestJob(); - - void StartAsync(); - void DidAttemptAutoMount(base::File::Error result); - void DidReadDirectory(base::File::Error result, - const std::vector<DirectoryEntry>& entries, - bool has_more); - - std::string data_; - FileSystemURL url_; - const std::string storage_domain_; - FileSystemContext* file_system_context_; - base::WeakPtrFactory<FileSystemDirURLRequestJob> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(FileSystemDirURLRequestJob); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_DIR_URL_REQUEST_JOB_H_ +#include "storage/browser/fileapi/file_system_dir_url_request_job.h" diff --git a/webkit/browser/fileapi/file_system_file_stream_reader.cc b/webkit/browser/fileapi/file_system_file_stream_reader.cc deleted file mode 100644 index aa99ab9..0000000 --- a/webkit/browser/fileapi/file_system_file_stream_reader.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_file_stream_reader.h" - -#include "base/files/file_util_proxy.h" -#include "base/single_thread_task_runner.h" -#include "net/base/file_stream.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_runner.h" - -using storage::FileStreamReader; - -// TODO(kinuko): Remove this temporary namespace hack after we move both -// blob and fileapi into content namespace. -namespace storage { - -FileStreamReader* FileStreamReader::CreateForFileSystemFile( - storage::FileSystemContext* file_system_context, - const storage::FileSystemURL& url, - int64 initial_offset, - const base::Time& expected_modification_time) { - return new storage::FileSystemFileStreamReader( - file_system_context, url, initial_offset, expected_modification_time); -} - -} // namespace storage - -namespace storage { - -namespace { - -void ReadAdapter(base::WeakPtr<FileSystemFileStreamReader> reader, - net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { - if (!reader.get()) - return; - int rv = reader->Read(buf, buf_len, callback); - if (rv != net::ERR_IO_PENDING) - callback.Run(rv); -} - -void GetLengthAdapter(base::WeakPtr<FileSystemFileStreamReader> reader, - const net::Int64CompletionCallback& callback) { - if (!reader.get()) - return; - int rv = reader->GetLength(callback); - if (rv != net::ERR_IO_PENDING) - callback.Run(rv); -} - -void Int64CallbackAdapter(const net::Int64CompletionCallback& callback, - int value) { - callback.Run(value); -} - -} // namespace - -FileSystemFileStreamReader::~FileSystemFileStreamReader() { -} - -int FileSystemFileStreamReader::Read( - net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { - if (local_file_reader_) - return local_file_reader_->Read(buf, buf_len, callback); - return CreateSnapshot( - base::Bind(&ReadAdapter, weak_factory_.GetWeakPtr(), - make_scoped_refptr(buf), buf_len, callback), - callback); -} - -int64 FileSystemFileStreamReader::GetLength( - const net::Int64CompletionCallback& callback) { - if (local_file_reader_) - return local_file_reader_->GetLength(callback); - return CreateSnapshot( - base::Bind(&GetLengthAdapter, weak_factory_.GetWeakPtr(), callback), - base::Bind(&Int64CallbackAdapter, callback)); -} - -FileSystemFileStreamReader::FileSystemFileStreamReader( - FileSystemContext* file_system_context, - const FileSystemURL& url, - int64 initial_offset, - const base::Time& expected_modification_time) - : file_system_context_(file_system_context), - url_(url), - initial_offset_(initial_offset), - expected_modification_time_(expected_modification_time), - has_pending_create_snapshot_(false), - weak_factory_(this) { -} - -int FileSystemFileStreamReader::CreateSnapshot( - const base::Closure& callback, - const net::CompletionCallback& error_callback) { - DCHECK(!has_pending_create_snapshot_); - has_pending_create_snapshot_ = true; - file_system_context_->operation_runner()->CreateSnapshotFile( - url_, - base::Bind(&FileSystemFileStreamReader::DidCreateSnapshot, - weak_factory_.GetWeakPtr(), - callback, - error_callback)); - return net::ERR_IO_PENDING; -} - -void FileSystemFileStreamReader::DidCreateSnapshot( - const base::Closure& callback, - const net::CompletionCallback& error_callback, - base::File::Error file_error, - const base::File::Info& file_info, - const base::FilePath& platform_path, - const scoped_refptr<storage::ShareableFileReference>& file_ref) { - DCHECK(has_pending_create_snapshot_); - DCHECK(!local_file_reader_.get()); - has_pending_create_snapshot_ = false; - - if (file_error != base::File::FILE_OK) { - error_callback.Run(net::FileErrorToNetError(file_error)); - return; - } - - // Keep the reference (if it's non-null) so that the file won't go away. - snapshot_ref_ = file_ref; - - local_file_reader_.reset( - FileStreamReader::CreateForLocalFile( - file_system_context_->default_file_task_runner(), - platform_path, initial_offset_, expected_modification_time_)); - - callback.Run(); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_file_stream_reader.h b/webkit/browser/fileapi/file_system_file_stream_reader.h index 8845aa0..3290fa0 100644 --- a/webkit/browser/fileapi/file_system_file_stream_reader.h +++ b/webkit/browser/fileapi/file_system_file_stream_reader.h @@ -1,79 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_FILE_STREAM_READER_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_FILE_STREAM_READER_H_ - -#include "base/bind.h" -#include "base/files/file.h" -#include "base/memory/ref_counted.h" -#include "base/time/time.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/blob/shareable_file_reference.h" - -namespace base { -class FilePath; -class SequencedTaskRunner; -} - -namespace content { -class FileSystemFileStreamReaderTest; -} - -namespace storage { - -class FileSystemContext; - -// Generic FileStreamReader implementation for FileSystem files. -// Note: This generic implementation would work for any filesystems but -// remote filesystem should implement its own reader rather than relying -// on FileSystemOperation::GetSnapshotFile() which may force downloading -// the entire contents for remote files. -class STORAGE_EXPORT_PRIVATE FileSystemFileStreamReader - : public NON_EXPORTED_BASE(storage::FileStreamReader) { - public: - virtual ~FileSystemFileStreamReader(); - - // FileStreamReader overrides. - virtual int Read(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) OVERRIDE; - virtual int64 GetLength( - const net::Int64CompletionCallback& callback) OVERRIDE; - - private: - friend class storage::FileStreamReader; - friend class content::FileSystemFileStreamReaderTest; - - FileSystemFileStreamReader(FileSystemContext* file_system_context, - const FileSystemURL& url, - int64 initial_offset, - const base::Time& expected_modification_time); - - int CreateSnapshot(const base::Closure& callback, - const net::CompletionCallback& error_callback); - void DidCreateSnapshot( - const base::Closure& callback, - const net::CompletionCallback& error_callback, - base::File::Error file_error, - const base::File::Info& file_info, - const base::FilePath& platform_path, - const scoped_refptr<storage::ShareableFileReference>& file_ref); - - scoped_refptr<FileSystemContext> file_system_context_; - FileSystemURL url_; - const int64 initial_offset_; - const base::Time expected_modification_time_; - scoped_ptr<storage::FileStreamReader> local_file_reader_; - scoped_refptr<storage::ShareableFileReference> snapshot_ref_; - bool has_pending_create_snapshot_; - base::WeakPtrFactory<FileSystemFileStreamReader> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(FileSystemFileStreamReader); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_FILE_STREAM_READER_H_ +#include "storage/browser/fileapi/file_system_file_stream_reader.h" diff --git a/webkit/browser/fileapi/file_system_file_util.cc b/webkit/browser/fileapi/file_system_file_util.cc deleted file mode 100644 index 35b1ceb..0000000 --- a/webkit/browser/fileapi/file_system_file_util.cc +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_file_util.h" - -namespace storage { - -base::FilePath FileSystemFileUtil::EmptyFileEnumerator::Next() { - return base::FilePath(); -} - -int64 FileSystemFileUtil::EmptyFileEnumerator::Size() { - return 0; -} - -base::Time FileSystemFileUtil::EmptyFileEnumerator::LastModifiedTime() { - return base::Time(); -} - -bool FileSystemFileUtil::EmptyFileEnumerator::IsDirectory() { - return false; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_file_util.h b/webkit/browser/fileapi/file_system_file_util.h index 2a93787..5aa3676 100644 --- a/webkit/browser/fileapi/file_system_file_util.h +++ b/webkit/browser/fileapi/file_system_file_util.h @@ -1,186 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_FILE_UTIL_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_FILE_UTIL_H_ - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/file_system_operation.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/blob/scoped_file.h" - -namespace base { -class Time; -} - -namespace storage { - -class FileSystemOperationContext; -class FileSystemURL; - -// A file utility interface that provides basic file utility methods for -// FileSystem API. -// -// Layering structure of the FileSystemFileUtil was split out. -// See http://crbug.com/128136 if you need it. -class STORAGE_EXPORT FileSystemFileUtil { - public: - typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption; - - // It will be implemented by each subclass such as FileSystemFileEnumerator. - class STORAGE_EXPORT AbstractFileEnumerator { - public: - virtual ~AbstractFileEnumerator() {} - - // Returns an empty string if there are no more results. - virtual base::FilePath Next() = 0; - - // These methods return metadata for the file most recently returned by - // Next(). If Next() has never been called, or if Next() most recently - // returned an empty string, then return the default values of 0, - // "null time", and false, respectively. - virtual int64 Size() = 0; - virtual base::Time LastModifiedTime() = 0; - virtual bool IsDirectory() = 0; - }; - - class STORAGE_EXPORT EmptyFileEnumerator - : public AbstractFileEnumerator { - virtual base::FilePath Next() OVERRIDE; - virtual int64 Size() OVERRIDE; - virtual base::Time LastModifiedTime() OVERRIDE; - virtual bool IsDirectory() OVERRIDE; - }; - - virtual ~FileSystemFileUtil() {} - - // Creates or opens a file with the given flags. - // See header comments for AsyncFileUtil::CreateOrOpen() for more details. - // This is used only by Pepper/NaCl File API. - virtual base::File CreateOrOpen( - FileSystemOperationContext* context, - const FileSystemURL& url, - int file_flags) = 0; - - // Ensures that the given |url| exist. This creates a empty new file - // at |url| if the |url| does not exist. - // See header comments for AsyncFileUtil::EnsureFileExists() for more details. - virtual base::File::Error EnsureFileExists( - FileSystemOperationContext* context, - const FileSystemURL& url, bool* created) = 0; - - // Creates directory at given url. - // See header comments for AsyncFileUtil::CreateDirectory() for more details. - virtual base::File::Error CreateDirectory( - FileSystemOperationContext* context, - const FileSystemURL& url, - bool exclusive, - bool recursive) = 0; - - // Retrieves the information about a file. - // See header comments for AsyncFileUtil::GetFileInfo() for more details. - virtual base::File::Error GetFileInfo( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Info* file_info, - base::FilePath* platform_path) = 0; - - // Returns a pointer to a new instance of AbstractFileEnumerator which is - // implemented for each FileSystemFileUtil subclass. The instance needs to be - // freed by the caller, and its lifetime should not extend past when the - // current call returns to the main FILE message loop. - // - // The supplied context must remain valid at least lifetime of the enumerator - // instance. - virtual scoped_ptr<AbstractFileEnumerator> CreateFileEnumerator( - FileSystemOperationContext* context, - const FileSystemURL& root_url) = 0; - - // Maps |file_system_url| given |context| into |local_file_path| - // which represents physical file location on the host OS. - // This may not always make sense for all subclasses. - virtual base::File::Error GetLocalFilePath( - FileSystemOperationContext* context, - const FileSystemURL& file_system_url, - base::FilePath* local_file_path) = 0; - - // Updates the file metadata information. - // See header comments for AsyncFileUtil::Touch() for more details. - virtual base::File::Error Touch( - FileSystemOperationContext* context, - const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time) = 0; - - // Truncates a file to the given length. - // See header comments for AsyncFileUtil::Truncate() for more details. - virtual base::File::Error Truncate( - FileSystemOperationContext* context, - const FileSystemURL& url, - int64 length) = 0; - - // Copies or moves a single file from |src_url| to |dest_url|. - // The filesystem type of |src_url| and |dest_url| MUST be same. - // For |option|, please see file_system_operation.h - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |src_url| - // or the parent directory of |dest_url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. - // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - File::FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - virtual base::File::Error CopyOrMoveFile( - FileSystemOperationContext* context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - bool copy) = 0; - - // Copies in a single file from a different filesystem. - // See header comments for AsyncFileUtil::CopyInForeignFile() for - // more details. - virtual base::File::Error CopyInForeignFile( - FileSystemOperationContext* context, - const base::FilePath& src_file_path, - const FileSystemURL& dest_url) = 0; - - // Deletes a single file. - // See header comments for AsyncFileUtil::DeleteFile() for more details. - virtual base::File::Error DeleteFile( - FileSystemOperationContext* context, - const FileSystemURL& url) = 0; - - // Deletes a single empty directory. - // See header comments for AsyncFileUtil::DeleteDirectory() for more details. - virtual base::File::Error DeleteDirectory( - FileSystemOperationContext* context, - const FileSystemURL& url) = 0; - - // Creates a local snapshot file for a given |url| and returns the - // metadata and platform path of the snapshot file via |callback|. - // - // See header comments for AsyncFileUtil::CreateSnapshotFile() for - // more details. - virtual storage::ScopedFile CreateSnapshotFile( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Error* error, - base::File::Info* file_info, - base::FilePath* platform_path) = 0; - - protected: - FileSystemFileUtil() {} - - private: - DISALLOW_COPY_AND_ASSIGN(FileSystemFileUtil); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_FILE_UTIL_H_ +#include "storage/browser/fileapi/file_system_file_util.h" diff --git a/webkit/browser/fileapi/file_system_operation.h b/webkit/browser/fileapi/file_system_operation.h index 7972a79..0eeb7b2 100644 --- a/webkit/browser/fileapi/file_system_operation.h +++ b/webkit/browser/fileapi/file_system_operation.h @@ -1,485 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_H_ - -#include <vector> - -#include "base/callback.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/process/process.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/directory_entry.h" - -namespace base { -class Time; -} - -namespace net { -class URLRequest; -} - -namespace storage { -class ShareableFileReference; -} - -class GURL; - -namespace storage { - -class FileSystemContext; -class FileSystemURL; -class FileWriterDelegate; - -// The interface class for FileSystemOperation implementations. -// -// This interface defines file system operations required to implement -// "File API: Directories and System" -// http://www.w3.org/TR/file-system-api/ -// -// DESIGN NOTES -// -// This class is designed to -// -// 1) Serve one-time file system operation per instance. Only one -// method(CreateFile, CreateDirectory, Copy, Move, DirectoryExists, -// GetMetadata, ReadDirectory and Remove) may be called during the -// lifetime of this object and it should be called no more than once. -// -// 2) Deliver the results of operations to the client via the callback function -// passed as the last parameter of the method. -// -// Note that it is valid to delete an operation while it is running. -// The callback will NOT be fired if the operation is deleted before -// it gets called. -class FileSystemOperation { - public: - STORAGE_EXPORT static FileSystemOperation* Create( - const FileSystemURL& url, - FileSystemContext* file_system_context, - scoped_ptr<FileSystemOperationContext> operation_context); - - virtual ~FileSystemOperation() {} - - // Used for CreateFile(), etc. |result| is the return code of the operation. - typedef base::Callback<void(base::File::Error result)> StatusCallback; - - // Used for GetMetadata(). |result| is the return code of the operation, - // |file_info| is the obtained file info. - typedef base::Callback< - void(base::File::Error result, - const base::File::Info& file_info)> GetMetadataCallback; - - // Used for OpenFile(). |on_close_callback| will be called after the file is - // closed in the child process. It can be null, if no operation is needed on - // closing a file. - typedef base::Callback< - void(base::File file, - const base::Closure& on_close_callback)> OpenFileCallback; - - // Used for ReadDirectoryCallback. - typedef std::vector<DirectoryEntry> FileEntryList; - - // Used for ReadDirectory(). |result| is the return code of the operation, - // |file_list| is the list of files read, and |has_more| is true if some files - // are yet to be read. - typedef base::Callback< - void(base::File::Error result, - const FileEntryList& file_list, - bool has_more)> ReadDirectoryCallback; - - // Used for CreateSnapshotFile(). (Please see the comment at - // CreateSnapshotFile() below for how the method is called) - // |result| is the return code of the operation. - // |file_info| is the metadata of the snapshot file created. - // |platform_path| is the path to the snapshot file created. - // - // The snapshot file could simply be of the local file pointed by the given - // filesystem URL in local filesystem cases; remote filesystems - // may want to download the file into a temporary snapshot file and then - // return the metadata of the temporary file. - // - // |file_ref| is used to manage the lifetime of the returned - // snapshot file. It can be set to let the chromium backend take - // care of the life time of the snapshot file. Otherwise (if the returned - // file does not require any handling) the implementation can just - // return NULL. In a more complex case, the implementaiton can manage - // the lifetime of the snapshot file on its own (e.g. by its cache system) - // but also can be notified via the reference when the file becomes no - // longer necessary in the javascript world. - // Please see the comment for ShareableFileReference for details. - // - typedef base::Callback< - void(base::File::Error result, - const base::File::Info& file_info, - const base::FilePath& platform_path, - const scoped_refptr<storage::ShareableFileReference>& file_ref)> - SnapshotFileCallback; - - // Used for progress update callback for Copy(). - // - // BEGIN_COPY_ENTRY is fired for each copy creation beginning (for both - // file and directory). - // The |source_url| is the URL of the source entry. |size| should not be - // used. - // - // END_COPY_ENTRY is fired for each copy creation finishing (for both - // file and directory). - // The |source_url| is the URL of the source entry. The |destination_url| is - // the URL of the destination entry. |size| should not be used. - // - // PROGRESS is fired periodically during file copying (not fired for - // directory copy). - // The |source_url| is the URL of the source file. |size| is the number - // of cumulative copied bytes for the currently copied file. - // Both at beginning and ending of file copying, PROGRESS event should be - // called. At beginning, |size| should be 0. At ending, |size| should be - // the size of the file. - // - // Here is an example callback sequence of recursive copy. Suppose - // there are a/b/c.txt (100 bytes) and a/b/d.txt (200 bytes), and trying to - // copy a to x recursively, then the progress update sequence will be: - // - // BEGIN_COPY_ENTRY a (starting create "a" directory in x/). - // END_COPY_ENTRY a x/a (creating "a" directory in x/ is finished). - // - // BEGIN_COPY_ENTRY a/b (starting create "b" directory in x/a). - // END_COPY_ENTRY a/b x/a/b (creating "b" directory in x/a/ is finished). - // - // BEGIN_COPY_ENTRY a/b/c.txt (starting to copy "c.txt" in x/a/b/). - // PROGRESS a/b/c.txt 0 (The first PROGRESS's |size| should be 0). - // PROGRESS a/b/c.txt 10 - // : - // PROGRESS a/b/c.txt 90 - // PROGRESS a/b/c.txt 100 (The last PROGRESS's |size| should be the size of - // the file). - // END_COPY_ENTRY a/b/c.txt x/a/b/c.txt (copying "c.txt" is finished). - // - // BEGIN_COPY_ENTRY a/b/d.txt (starting to copy "d.txt" in x/a/b). - // PROGRESS a/b/d.txt 0 (The first PROGRESS's |size| should be 0). - // PROGRESS a/b/d.txt 10 - // : - // PROGRESS a/b/d.txt 190 - // PROGRESS a/b/d.txt 200 (The last PROGRESS's |size| should be the size of - // the file). - // END_COPY_ENTRY a/b/d.txt x/a/b/d.txt (copy "d.txt" is finished). - // - // Note that event sequence of a/b/c.txt and a/b/d.txt can be interlaced, - // because they can be done in parallel. Also PROGRESS events are optional, - // so they may not be appeared. - // All the progress callback invocation should be done before StatusCallback - // given to the Copy is called. Especially if an error is found before first - // progres callback invocation, the progress callback may NOT invoked for the - // copy. - // - // Note for future extension. Currently this callback is only supported on - // Copy(). We can extend this to Move(), because Move() is sometimes - // implemented as "copy then delete." - // In more precise, Move() usually can be implemented either 1) by updating - // the metadata of resource (e.g. root of moving directory tree), or 2) by - // copying directory tree and them removing the source tree. - // For 1)'s case, we can simply add BEGIN_MOVE_ENTRY and END_MOVE_ENTRY - // for root directory. - // For 2)'s case, we can add BEGIN_DELETE_ENTRY and END_DELETE_ENTRY for each - // entry. - // For both cases, we probably won't need to use PROGRESS event because - // these operations should be done quickly (at least much faster than copying - // usually). - enum CopyProgressType { - BEGIN_COPY_ENTRY, - END_COPY_ENTRY, - PROGRESS, - }; - typedef base::Callback<void(CopyProgressType type, - const FileSystemURL& source_url, - const FileSystemURL& destination_url, - int64 size)> - CopyProgressCallback; - - // Used for CopyFileLocal() to report progress update. - // |size| is the cumulative copied bytes for the copy. - // At the beginning the progress callback should be called with |size| = 0, - // and also at the ending the progress callback should be called with |size| - // set to the copied file size. - typedef base::Callback<void(int64 size)> CopyFileProgressCallback; - - // The option for copy or move operation. - enum CopyOrMoveOption { - // No additional operation. - OPTION_NONE, - - // Preserves last modified time if possible. If the operation to update - // last modified time is not supported on the file system for the - // destination file, this option would be simply ignored (i.e. Copy would - // be successfully done without preserving last modified time). - OPTION_PRESERVE_LAST_MODIFIED, - }; - - // Used for Write(). - typedef base::Callback<void(base::File::Error result, - int64 bytes, - bool complete)> WriteCallback; - - // Creates a file at |path|. If |exclusive| is true, an error is raised - // in case a file is already present at the URL. - virtual void CreateFile(const FileSystemURL& path, - bool exclusive, - const StatusCallback& callback) = 0; - - // Creates a directory at |path|. If |exclusive| is true, an error is - // raised in case a directory is already present at the URL. If - // |recursive| is true, create parent directories as needed just like - // mkdir -p does. - virtual void CreateDirectory(const FileSystemURL& path, - bool exclusive, - bool recursive, - const StatusCallback& callback) = 0; - - // Copies a file or directory from |src_path| to |dest_path|. If - // |src_path| is a directory, the contents of |src_path| are copied to - // |dest_path| recursively. A new file or directory is created at - // |dest_path| as needed. - // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's - // comment for details. - // |progress_callback| is periodically called to report the progress - // update. See also the comment of CopyProgressCallback. This callback is - // optional. - // - // For recursive case this internally creates new FileSystemOperations and - // calls: - // - ReadDirectory, CopyFileLocal and CreateDirectory - // for same-filesystem case, or - // - ReadDirectory and CreateSnapshotFile on source filesystem and - // CopyInForeignFile and CreateDirectory on dest filesystem - // for cross-filesystem case. - // - virtual void Copy(const FileSystemURL& src_path, - const FileSystemURL& dest_path, - CopyOrMoveOption option, - const CopyProgressCallback& progress_callback, - const StatusCallback& callback) = 0; - - // Moves a file or directory from |src_path| to |dest_path|. A new file - // or directory is created at |dest_path| as needed. - // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's - // comment for details. - // - // For recursive case this internally creates new FileSystemOperations and - // calls: - // - ReadDirectory, MoveFileLocal, CreateDirectory and Remove - // for same-filesystem case, or - // - ReadDirectory, CreateSnapshotFile and Remove on source filesystem and - // CopyInForeignFile and CreateDirectory on dest filesystem - // for cross-filesystem case. - // - virtual void Move(const FileSystemURL& src_path, - const FileSystemURL& dest_path, - CopyOrMoveOption option, - const StatusCallback& callback) = 0; - - // Checks if a directory is present at |path|. - virtual void DirectoryExists(const FileSystemURL& path, - const StatusCallback& callback) = 0; - - // Checks if a file is present at |path|. - virtual void FileExists(const FileSystemURL& path, - const StatusCallback& callback) = 0; - - // Gets the metadata of a file or directory at |path|. - virtual void GetMetadata(const FileSystemURL& path, - const GetMetadataCallback& callback) = 0; - - // Reads contents of a directory at |path|. - virtual void ReadDirectory(const FileSystemURL& path, - const ReadDirectoryCallback& callback) = 0; - - // Removes a file or directory at |path|. If |recursive| is true, remove - // all files and directories under the directory at |path| recursively. - virtual void Remove(const FileSystemURL& path, bool recursive, - const StatusCallback& callback) = 0; - - // Writes the data read from |blob_request| using |writer_delegate|. - virtual void Write( - const FileSystemURL& url, - scoped_ptr<FileWriterDelegate> writer_delegate, - scoped_ptr<net::URLRequest> blob_request, - const WriteCallback& callback) = 0; - - // Truncates a file at |path| to |length|. If |length| is larger than - // the original file size, the file will be extended, and the extended - // part is filled with null bytes. - virtual void Truncate(const FileSystemURL& path, int64 length, - const StatusCallback& callback) = 0; - - // Tries to cancel the current operation [we support cancelling write or - // truncate only]. Reports failure for the current operation, then reports - // success for the cancel operation itself via the |cancel_dispatcher|. - // - // E.g. a typical cancel implementation would look like: - // - // virtual void SomeOperationImpl::Cancel( - // const StatusCallback& cancel_callback) { - // // Abort the current inflight operation first. - // ... - // - // // Dispatch ABORT error for the current operation by invoking - // // the callback function for the ongoing operation, - // operation_callback.Run(base::File::FILE_ERROR_ABORT, ...); - // - // // Dispatch 'success' for the cancel (or dispatch appropriate - // // error code with DidFail() if the cancel has somehow failed). - // cancel_callback.Run(base::File::FILE_OK); - // } - // - // Note that, for reporting failure, the callback function passed to a - // cancellable operations are kept around with the operation instance - // (as |operation_callback_| in the code example). - virtual void Cancel(const StatusCallback& cancel_callback) = 0; - - // Modifies timestamps of a file or directory at |path| with - // |last_access_time| and |last_modified_time|. The function DOES NOT - // create a file unlike 'touch' command on Linux. - // - // This function is used only by Pepper as of writing. - virtual void TouchFile(const FileSystemURL& path, - const base::Time& last_access_time, - const base::Time& last_modified_time, - const StatusCallback& callback) = 0; - - // Opens a file at |path| with |file_flags|, where flags are OR'ed - // values of base::File::Flags. - // - // This function is used only by Pepper as of writing. - virtual void OpenFile(const FileSystemURL& path, - int file_flags, - const OpenFileCallback& callback) = 0; - - // Creates a local snapshot file for a given |path| and returns the - // metadata and platform path of the snapshot file via |callback|. - // In local filesystem cases the implementation may simply return - // the metadata of the file itself (as well as GetMetadata does), - // while in remote filesystem case the backend may want to download the file - // into a temporary snapshot file and return the metadata of the - // temporary file. Or if the implementaiton already has the local cache - // data for |path| it can simply return the path to the cache. - virtual void CreateSnapshotFile(const FileSystemURL& path, - const SnapshotFileCallback& callback) = 0; - - // Copies in a single file from a different filesystem. - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |src_file_path| - // or the parent directory of |dest_url| does not exist. - // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - File::FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - virtual void CopyInForeignFile(const base::FilePath& src_local_disk_path, - const FileSystemURL& dest_url, - const StatusCallback& callback) = 0; - - // Removes a single file. - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |url| is not a file. - // - virtual void RemoveFile(const FileSystemURL& url, - const StatusCallback& callback) = 0; - - // Removes a single empty directory. - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |url| does not exist. - // - File::FILE_ERROR_NOT_A_DIRECTORY if |url| is not a directory. - // - File::FILE_ERROR_NOT_EMPTY if |url| is not empty. - // - virtual void RemoveDirectory(const FileSystemURL& url, - const StatusCallback& callback) = 0; - - // Copies a file from |src_url| to |dest_url|. - // This must be called for files that belong to the same filesystem - // (i.e. type() and origin() of the |src_url| and |dest_url| must match). - // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's - // comment for details. - // |progress_callback| is periodically called to report the progress - // update. See also the comment of CopyFileProgressCallback. This callback is - // optional. - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |src_url| - // or the parent directory of |dest_url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. - // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - File::FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - virtual void CopyFileLocal(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback) = 0; - - // Moves a local file from |src_url| to |dest_url|. - // This must be called for files that belong to the same filesystem - // (i.e. type() and origin() of the |src_url| and |dest_url| must match). - // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's - // comment for details. - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |src_url| - // or the parent directory of |dest_url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. - // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - File::FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - virtual void MoveFileLocal(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) = 0; - - // Synchronously gets the platform path for the given |url|. - // This may fail if the given |url|'s filesystem type is neither - // temporary nor persistent. - // In such a case, base::File::FILE_ERROR_INVALID_OPERATION will be - // returned. - virtual base::File::Error SyncGetPlatformPath( - const FileSystemURL& url, - base::FilePath* platform_path) = 0; - - protected: - // Used only for internal assertions. - enum OperationType { - kOperationNone, - kOperationCreateFile, - kOperationCreateDirectory, - kOperationCreateSnapshotFile, - kOperationCopy, - kOperationCopyInForeignFile, - kOperationMove, - kOperationDirectoryExists, - kOperationFileExists, - kOperationGetMetadata, - kOperationReadDirectory, - kOperationRemove, - kOperationWrite, - kOperationTruncate, - kOperationTouchFile, - kOperationOpenFile, - kOperationCloseFile, - kOperationGetLocalPath, - kOperationCancel, - }; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_H_ +#include "storage/browser/fileapi/file_system_operation.h" diff --git a/webkit/browser/fileapi/file_system_operation_context.cc b/webkit/browser/fileapi/file_system_operation_context.cc deleted file mode 100644 index 1cd1f37..0000000 --- a/webkit/browser/fileapi/file_system_operation_context.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_operation_context.h" - -#include "base/sequenced_task_runner.h" -#include "webkit/browser/fileapi/file_system_context.h" - -namespace storage { - -FileSystemOperationContext::FileSystemOperationContext( - FileSystemContext* context) - : file_system_context_(context), - task_runner_(file_system_context_->default_file_task_runner()), - allowed_bytes_growth_(0), - quota_limit_type_(storage::kQuotaLimitTypeUnknown) { -} - -FileSystemOperationContext::FileSystemOperationContext( - FileSystemContext* context, - base::SequencedTaskRunner* task_runner) - : file_system_context_(context), - task_runner_(task_runner), - allowed_bytes_growth_(0), - quota_limit_type_(storage::kQuotaLimitTypeUnknown) { -} - -FileSystemOperationContext::~FileSystemOperationContext() { - DetachUserDataThread(); - setter_thread_checker_.DetachFromThread(); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_operation_context.h b/webkit/browser/fileapi/file_system_operation_context.h index fe0a313..093389e 100644 --- a/webkit/browser/fileapi/file_system_operation_context.h +++ b/webkit/browser/fileapi/file_system_operation_context.h @@ -1,97 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_CONTEXT_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_CONTEXT_H_ - -#include "base/files/file_path.h" -#include "base/supports_user_data.h" -#include "base/threading/thread_checker.h" -#include "webkit/browser/fileapi/task_runner_bound_observer_list.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/quota/quota_types.h" - -namespace base { -class SequencedTaskRunner; -} - -namespace storage { - -class FileSystemContext; - -// A context class which is carried around by FileSystemOperation and -// its delegated tasks. It is valid to reuse one context instance across -// multiple operations as far as those operations are supposed to share -// the same context (e.g. use the same task runner, share the quota etc). -// Note that the remaining quota bytes (allowed_bytes_growth) may be -// updated during the execution of write operations. -class STORAGE_EXPORT_PRIVATE FileSystemOperationContext - : public base::SupportsUserData { - public: - explicit FileSystemOperationContext(FileSystemContext* context); - - // Specifies |task_runner| which the operation is performed on. - // The backend of |task_runner| must outlive the IO thread. - FileSystemOperationContext(FileSystemContext* context, - base::SequencedTaskRunner* task_runner); - - virtual ~FileSystemOperationContext(); - - FileSystemContext* file_system_context() const { - return file_system_context_.get(); - } - - // Updates the current remaining quota. - // This can be called to update the remaining quota during the operation. - void set_allowed_bytes_growth(const int64& allowed_bytes_growth) { - allowed_bytes_growth_ = allowed_bytes_growth; - } - - // Returns the current remaining quota. - int64 allowed_bytes_growth() const { return allowed_bytes_growth_; } - storage::QuotaLimitType quota_limit_type() const { return quota_limit_type_; } - base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); } - - ChangeObserverList* change_observers() { return &change_observers_; } - UpdateObserverList* update_observers() { return &update_observers_; } - - // Following setters should be called only on the same thread as the - // FileSystemOperationContext is created (i.e. are not supposed be updated - // after the context's passed onto other task runners). - void set_change_observers(const ChangeObserverList& list) { - DCHECK(setter_thread_checker_.CalledOnValidThread()); - change_observers_ = list; - } - void set_update_observers(const UpdateObserverList& list) { - DCHECK(setter_thread_checker_.CalledOnValidThread()); - update_observers_ = list; - } - void set_quota_limit_type(storage::QuotaLimitType limit_type) { - DCHECK(setter_thread_checker_.CalledOnValidThread()); - quota_limit_type_ = limit_type; - } - - private: - scoped_refptr<FileSystemContext> file_system_context_; - scoped_refptr<base::SequencedTaskRunner> task_runner_; - - // The current remaining quota, used by ObfuscatedFileUtil. - int64 allowed_bytes_growth_; - - // The current quota limit type, used by ObfuscatedFileUtil. - storage::QuotaLimitType quota_limit_type_; - - // Observers attached to this context. - ChangeObserverList change_observers_; - UpdateObserverList update_observers_; - - // Used to check its setters are not called on arbitrary thread. - base::ThreadChecker setter_thread_checker_; - - DISALLOW_COPY_AND_ASSIGN(FileSystemOperationContext); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_CONTEXT_H_ +#include "storage/browser/fileapi/file_system_operation_context.h" diff --git a/webkit/browser/fileapi/file_system_operation_impl.cc b/webkit/browser/fileapi/file_system_operation_impl.cc deleted file mode 100644 index 286f19f..0000000 --- a/webkit/browser/fileapi/file_system_operation_impl.cc +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright 2013 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/browser/fileapi/file_system_operation_impl.h" - -#include "base/bind.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" -#include "net/base/escape.h" -#include "net/url_request/url_request.h" -#include "webkit/browser/fileapi/async_file_util.h" -#include "webkit/browser/fileapi/copy_or_move_operation_delegate.h" -#include "webkit/browser/fileapi/file_observers.h" -#include "webkit/browser/fileapi/file_system_backend.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_file_util.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/file_writer_delegate.h" -#include "webkit/browser/fileapi/remove_operation_delegate.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend.h" -#include "webkit/browser/quota/quota_manager_proxy.h" -#include "webkit/common/blob/shareable_file_reference.h" -#include "webkit/common/fileapi/file_system_types.h" -#include "webkit/common/fileapi/file_system_util.h" -#include "webkit/common/quota/quota_types.h" - -using storage::ScopedFile; - -namespace storage { - -FileSystemOperation* FileSystemOperation::Create( - const FileSystemURL& url, - FileSystemContext* file_system_context, - scoped_ptr<FileSystemOperationContext> operation_context) { - return new FileSystemOperationImpl(url, file_system_context, - operation_context.Pass()); -} - -FileSystemOperationImpl::~FileSystemOperationImpl() { -} - -void FileSystemOperationImpl::CreateFile(const FileSystemURL& url, - bool exclusive, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationCreateFile)); - GetUsageAndQuotaThenRunTask( - url, - base::Bind(&FileSystemOperationImpl::DoCreateFile, - weak_factory_.GetWeakPtr(), url, callback, exclusive), - base::Bind(callback, base::File::FILE_ERROR_FAILED)); -} - -void FileSystemOperationImpl::CreateDirectory(const FileSystemURL& url, - bool exclusive, - bool recursive, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationCreateDirectory)); - GetUsageAndQuotaThenRunTask( - url, - base::Bind(&FileSystemOperationImpl::DoCreateDirectory, - weak_factory_.GetWeakPtr(), url, callback, - exclusive, recursive), - base::Bind(callback, base::File::FILE_ERROR_FAILED)); -} - -void FileSystemOperationImpl::Copy( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyProgressCallback& progress_callback, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationCopy)); - DCHECK(!recursive_operation_delegate_); - - // TODO(hidehiko): Support |progress_callback|. (crbug.com/278038). - recursive_operation_delegate_.reset( - new CopyOrMoveOperationDelegate( - file_system_context(), - src_url, dest_url, - CopyOrMoveOperationDelegate::OPERATION_COPY, - option, - progress_callback, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback))); - recursive_operation_delegate_->RunRecursively(); -} - -void FileSystemOperationImpl::Move(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationMove)); - DCHECK(!recursive_operation_delegate_); - recursive_operation_delegate_.reset( - new CopyOrMoveOperationDelegate( - file_system_context(), - src_url, dest_url, - CopyOrMoveOperationDelegate::OPERATION_MOVE, - option, - FileSystemOperation::CopyProgressCallback(), - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback))); - recursive_operation_delegate_->RunRecursively(); -} - -void FileSystemOperationImpl::DirectoryExists(const FileSystemURL& url, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationDirectoryExists)); - async_file_util_->GetFileInfo( - operation_context_.Pass(), url, - base::Bind(&FileSystemOperationImpl::DidDirectoryExists, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::FileExists(const FileSystemURL& url, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationFileExists)); - async_file_util_->GetFileInfo( - operation_context_.Pass(), url, - base::Bind(&FileSystemOperationImpl::DidFileExists, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::GetMetadata( - const FileSystemURL& url, const GetMetadataCallback& callback) { - DCHECK(SetPendingOperationType(kOperationGetMetadata)); - async_file_util_->GetFileInfo(operation_context_.Pass(), url, callback); -} - -void FileSystemOperationImpl::ReadDirectory( - const FileSystemURL& url, const ReadDirectoryCallback& callback) { - DCHECK(SetPendingOperationType(kOperationReadDirectory)); - async_file_util_->ReadDirectory( - operation_context_.Pass(), url, callback); -} - -void FileSystemOperationImpl::Remove(const FileSystemURL& url, - bool recursive, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationRemove)); - DCHECK(!recursive_operation_delegate_); - - if (recursive) { - // For recursive removal, try to delegate the operation to AsyncFileUtil - // first. If not supported, it is delegated to RemoveOperationDelegate - // in DidDeleteRecursively. - async_file_util_->DeleteRecursively( - operation_context_.Pass(), url, - base::Bind(&FileSystemOperationImpl::DidDeleteRecursively, - weak_factory_.GetWeakPtr(), url, callback)); - return; - } - - recursive_operation_delegate_.reset( - new RemoveOperationDelegate( - file_system_context(), url, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback))); - recursive_operation_delegate_->Run(); -} - -void FileSystemOperationImpl::Write( - const FileSystemURL& url, - scoped_ptr<FileWriterDelegate> writer_delegate, - scoped_ptr<net::URLRequest> blob_request, - const WriteCallback& callback) { - DCHECK(SetPendingOperationType(kOperationWrite)); - file_writer_delegate_ = writer_delegate.Pass(); - file_writer_delegate_->Start( - blob_request.Pass(), - base::Bind(&FileSystemOperationImpl::DidWrite, - weak_factory_.GetWeakPtr(), url, callback)); -} - -void FileSystemOperationImpl::Truncate(const FileSystemURL& url, int64 length, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationTruncate)); - GetUsageAndQuotaThenRunTask( - url, - base::Bind(&FileSystemOperationImpl::DoTruncate, - weak_factory_.GetWeakPtr(), url, callback, length), - base::Bind(callback, base::File::FILE_ERROR_FAILED)); -} - -void FileSystemOperationImpl::TouchFile(const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationTouchFile)); - async_file_util_->Touch( - operation_context_.Pass(), url, - last_access_time, last_modified_time, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::OpenFile(const FileSystemURL& url, - int file_flags, - const OpenFileCallback& callback) { - DCHECK(SetPendingOperationType(kOperationOpenFile)); - - if (file_flags & - (base::File::FLAG_TEMPORARY | base::File::FLAG_HIDDEN)) { - callback.Run(base::File(base::File::FILE_ERROR_FAILED), - base::Closure()); - return; - } - GetUsageAndQuotaThenRunTask( - url, - base::Bind(&FileSystemOperationImpl::DoOpenFile, - weak_factory_.GetWeakPtr(), - url, callback, file_flags), - base::Bind(callback, Passed(base::File(base::File::FILE_ERROR_FAILED)), - base::Closure())); -} - -// We can only get here on a write or truncate that's not yet completed. -// We don't support cancelling any other operation at this time. -void FileSystemOperationImpl::Cancel(const StatusCallback& cancel_callback) { - DCHECK(cancel_callback_.is_null()); - cancel_callback_ = cancel_callback; - - if (file_writer_delegate_.get()) { - DCHECK_EQ(kOperationWrite, pending_operation_); - // This will call DidWrite() with ABORT status code. - file_writer_delegate_->Cancel(); - } else if (recursive_operation_delegate_) { - // This will call DidFinishOperation() with ABORT status code. - recursive_operation_delegate_->Cancel(); - } else { - // For truncate we have no way to cancel the inflight operation (for now). - // Let it just run and dispatch cancel callback later. - DCHECK_EQ(kOperationTruncate, pending_operation_); - } -} - -void FileSystemOperationImpl::CreateSnapshotFile( - const FileSystemURL& url, - const SnapshotFileCallback& callback) { - DCHECK(SetPendingOperationType(kOperationCreateSnapshotFile)); - async_file_util_->CreateSnapshotFile( - operation_context_.Pass(), url, callback); -} - -void FileSystemOperationImpl::CopyInForeignFile( - const base::FilePath& src_local_disk_file_path, - const FileSystemURL& dest_url, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationCopyInForeignFile)); - GetUsageAndQuotaThenRunTask( - dest_url, - base::Bind(&FileSystemOperationImpl::DoCopyInForeignFile, - weak_factory_.GetWeakPtr(), src_local_disk_file_path, dest_url, - callback), - base::Bind(callback, base::File::FILE_ERROR_FAILED)); -} - -void FileSystemOperationImpl::RemoveFile( - const FileSystemURL& url, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationRemove)); - async_file_util_->DeleteFile( - operation_context_.Pass(), url, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::RemoveDirectory( - const FileSystemURL& url, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationRemove)); - async_file_util_->DeleteDirectory( - operation_context_.Pass(), url, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::CopyFileLocal( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationCopy)); - DCHECK(src_url.IsInSameFileSystem(dest_url)); - - GetUsageAndQuotaThenRunTask( - dest_url, - base::Bind(&FileSystemOperationImpl::DoCopyFileLocal, - weak_factory_.GetWeakPtr(), src_url, dest_url, option, - progress_callback, callback), - base::Bind(callback, base::File::FILE_ERROR_FAILED)); -} - -void FileSystemOperationImpl::MoveFileLocal( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) { - DCHECK(SetPendingOperationType(kOperationMove)); - DCHECK(src_url.IsInSameFileSystem(dest_url)); - GetUsageAndQuotaThenRunTask( - dest_url, - base::Bind(&FileSystemOperationImpl::DoMoveFileLocal, - weak_factory_.GetWeakPtr(), - src_url, dest_url, option, callback), - base::Bind(callback, base::File::FILE_ERROR_FAILED)); -} - -base::File::Error FileSystemOperationImpl::SyncGetPlatformPath( - const FileSystemURL& url, - base::FilePath* platform_path) { - DCHECK(SetPendingOperationType(kOperationGetLocalPath)); - if (!file_system_context()->IsSandboxFileSystem(url.type())) - return base::File::FILE_ERROR_INVALID_OPERATION; - FileSystemFileUtil* file_util = - file_system_context()->sandbox_delegate()->sync_file_util(); - file_util->GetLocalFilePath(operation_context_.get(), url, platform_path); - return base::File::FILE_OK; -} - -FileSystemOperationImpl::FileSystemOperationImpl( - const FileSystemURL& url, - FileSystemContext* file_system_context, - scoped_ptr<FileSystemOperationContext> operation_context) - : file_system_context_(file_system_context), - operation_context_(operation_context.Pass()), - async_file_util_(NULL), - pending_operation_(kOperationNone), - weak_factory_(this) { - DCHECK(operation_context_.get()); - operation_context_->DetachUserDataThread(); - async_file_util_ = file_system_context_->GetAsyncFileUtil(url.type()); - DCHECK(async_file_util_); -} - -void FileSystemOperationImpl::GetUsageAndQuotaThenRunTask( - const FileSystemURL& url, - const base::Closure& task, - const base::Closure& error_callback) { - storage::QuotaManagerProxy* quota_manager_proxy = - file_system_context()->quota_manager_proxy(); - if (!quota_manager_proxy || - !file_system_context()->GetQuotaUtil(url.type())) { - // If we don't have the quota manager or the requested filesystem type - // does not support quota, we should be able to let it go. - operation_context_->set_allowed_bytes_growth(kint64max); - task.Run(); - return; - } - - DCHECK(quota_manager_proxy); - DCHECK(quota_manager_proxy->quota_manager()); - quota_manager_proxy->quota_manager()->GetUsageAndQuota( - url.origin(), - FileSystemTypeToQuotaStorageType(url.type()), - base::Bind(&FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask, - weak_factory_.GetWeakPtr(), task, error_callback)); -} - -void FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask( - const base::Closure& task, - const base::Closure& error_callback, - storage::QuotaStatusCode status, - int64 usage, - int64 quota) { - if (status != storage::kQuotaStatusOk) { - LOG(WARNING) << "Got unexpected quota error : " << status; - error_callback.Run(); - return; - } - - operation_context_->set_allowed_bytes_growth(quota - usage); - task.Run(); -} - -void FileSystemOperationImpl::DoCreateFile( - const FileSystemURL& url, - const StatusCallback& callback, - bool exclusive) { - async_file_util_->EnsureFileExists( - operation_context_.Pass(), url, - base::Bind( - exclusive ? - &FileSystemOperationImpl::DidEnsureFileExistsExclusive : - &FileSystemOperationImpl::DidEnsureFileExistsNonExclusive, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::DoCreateDirectory( - const FileSystemURL& url, - const StatusCallback& callback, - bool exclusive, bool recursive) { - async_file_util_->CreateDirectory( - operation_context_.Pass(), - url, exclusive, recursive, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::DoCopyFileLocal( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback) { - async_file_util_->CopyFileLocal( - operation_context_.Pass(), src_url, dest_url, option, progress_callback, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::DoMoveFileLocal( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) { - async_file_util_->MoveFileLocal( - operation_context_.Pass(), src_url, dest_url, option, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::DoCopyInForeignFile( - const base::FilePath& src_local_disk_file_path, - const FileSystemURL& dest_url, - const StatusCallback& callback) { - async_file_util_->CopyInForeignFile( - operation_context_.Pass(), - src_local_disk_file_path, dest_url, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::DoTruncate(const FileSystemURL& url, - const StatusCallback& callback, - int64 length) { - async_file_util_->Truncate( - operation_context_.Pass(), url, length, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::DoOpenFile(const FileSystemURL& url, - const OpenFileCallback& callback, - int file_flags) { - async_file_util_->CreateOrOpen( - operation_context_.Pass(), url, file_flags, - base::Bind(&FileSystemOperationImpl::DidOpenFile, - weak_factory_.GetWeakPtr(), callback)); -} - -void FileSystemOperationImpl::DidEnsureFileExistsExclusive( - const StatusCallback& callback, - base::File::Error rv, bool created) { - if (rv == base::File::FILE_OK && !created) { - callback.Run(base::File::FILE_ERROR_EXISTS); - } else { - DidFinishOperation(callback, rv); - } -} - -void FileSystemOperationImpl::DidEnsureFileExistsNonExclusive( - const StatusCallback& callback, - base::File::Error rv, bool /* created */) { - DidFinishOperation(callback, rv); -} - -void FileSystemOperationImpl::DidFinishOperation( - const StatusCallback& callback, - base::File::Error rv) { - if (!cancel_callback_.is_null()) { - StatusCallback cancel_callback = cancel_callback_; - callback.Run(rv); - - // Return OK only if we succeeded to stop the operation. - cancel_callback.Run(rv == base::File::FILE_ERROR_ABORT ? - base::File::FILE_OK : - base::File::FILE_ERROR_INVALID_OPERATION); - } else { - callback.Run(rv); - } -} - -void FileSystemOperationImpl::DidDirectoryExists( - const StatusCallback& callback, - base::File::Error rv, - const base::File::Info& file_info) { - if (rv == base::File::FILE_OK && !file_info.is_directory) - rv = base::File::FILE_ERROR_NOT_A_DIRECTORY; - callback.Run(rv); -} - -void FileSystemOperationImpl::DidFileExists( - const StatusCallback& callback, - base::File::Error rv, - const base::File::Info& file_info) { - if (rv == base::File::FILE_OK && file_info.is_directory) - rv = base::File::FILE_ERROR_NOT_A_FILE; - callback.Run(rv); -} - -void FileSystemOperationImpl::DidDeleteRecursively( - const FileSystemURL& url, - const StatusCallback& callback, - base::File::Error rv) { - if (rv == base::File::FILE_ERROR_INVALID_OPERATION) { - // Recursive removal is not supported on this platform. - DCHECK(!recursive_operation_delegate_); - recursive_operation_delegate_.reset( - new RemoveOperationDelegate( - file_system_context(), url, - base::Bind(&FileSystemOperationImpl::DidFinishOperation, - weak_factory_.GetWeakPtr(), callback))); - recursive_operation_delegate_->RunRecursively(); - return; - } - - callback.Run(rv); -} - -void FileSystemOperationImpl::DidWrite( - const FileSystemURL& url, - const WriteCallback& write_callback, - base::File::Error rv, - int64 bytes, - FileWriterDelegate::WriteProgressStatus write_status) { - const bool complete = ( - write_status != FileWriterDelegate::SUCCESS_IO_PENDING); - if (complete && write_status != FileWriterDelegate::ERROR_WRITE_NOT_STARTED) { - DCHECK(operation_context_); - operation_context_->change_observers()->Notify( - &FileChangeObserver::OnModifyFile, MakeTuple(url)); - } - - StatusCallback cancel_callback = cancel_callback_; - write_callback.Run(rv, bytes, complete); - if (!cancel_callback.is_null()) - cancel_callback.Run(base::File::FILE_OK); -} - -void FileSystemOperationImpl::DidOpenFile( - const OpenFileCallback& callback, - base::File file, - const base::Closure& on_close_callback) { - callback.Run(file.Pass(), on_close_callback); -} - -bool FileSystemOperationImpl::SetPendingOperationType(OperationType type) { - if (pending_operation_ != kOperationNone) - return false; - pending_operation_ = type; - return true; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_operation_impl.h b/webkit/browser/fileapi/file_system_operation_impl.h index ae6abb0..ceae604 100644 --- a/webkit/browser/fileapi/file_system_operation_impl.h +++ b/webkit/browser/fileapi/file_system_operation_impl.h @@ -1,206 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_IMPL_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_IMPL_H_ - -#include <vector> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "webkit/browser/fileapi/file_system_operation.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/file_writer_delegate.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/blob/scoped_file.h" -#include "webkit/common/quota/quota_types.h" - -namespace storage { - -class AsyncFileUtil; -class FileSystemContext; -class RecursiveOperationDelegate; - -// The default implementation of FileSystemOperation for file systems. -class STORAGE_EXPORT FileSystemOperationImpl - : public NON_EXPORTED_BASE(FileSystemOperation) { - public: - virtual ~FileSystemOperationImpl(); - - // FileSystemOperation overrides. - virtual void CreateFile(const FileSystemURL& url, - bool exclusive, - const StatusCallback& callback) OVERRIDE; - virtual void CreateDirectory(const FileSystemURL& url, - bool exclusive, - bool recursive, - const StatusCallback& callback) OVERRIDE; - virtual void Copy(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyProgressCallback& progress_callback, - const StatusCallback& callback) OVERRIDE; - virtual void Move(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) OVERRIDE; - virtual void DirectoryExists(const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void FileExists(const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void GetMetadata(const FileSystemURL& url, - const GetMetadataCallback& callback) OVERRIDE; - virtual void ReadDirectory(const FileSystemURL& url, - const ReadDirectoryCallback& callback) OVERRIDE; - virtual void Remove(const FileSystemURL& url, bool recursive, - const StatusCallback& callback) OVERRIDE; - virtual void Write(const FileSystemURL& url, - scoped_ptr<FileWriterDelegate> writer_delegate, - scoped_ptr<net::URLRequest> blob_request, - const WriteCallback& callback) OVERRIDE; - virtual void Truncate(const FileSystemURL& url, int64 length, - const StatusCallback& callback) OVERRIDE; - virtual void TouchFile(const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time, - const StatusCallback& callback) OVERRIDE; - virtual void OpenFile(const FileSystemURL& url, - int file_flags, - const OpenFileCallback& callback) OVERRIDE; - virtual void Cancel(const StatusCallback& cancel_callback) OVERRIDE; - virtual void CreateSnapshotFile( - const FileSystemURL& path, - const SnapshotFileCallback& callback) OVERRIDE; - virtual void CopyInForeignFile(const base::FilePath& src_local_disk_path, - const FileSystemURL& dest_url, - const StatusCallback& callback) OVERRIDE; - virtual void RemoveFile(const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void RemoveDirectory(const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void CopyFileLocal(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback) OVERRIDE; - virtual void MoveFileLocal(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) OVERRIDE; - virtual base::File::Error SyncGetPlatformPath( - const FileSystemURL& url, - base::FilePath* platform_path) OVERRIDE; - - FileSystemContext* file_system_context() const { - return file_system_context_.get(); - } - - private: - friend class FileSystemOperation; - - FileSystemOperationImpl( - const FileSystemURL& url, - FileSystemContext* file_system_context, - scoped_ptr<FileSystemOperationContext> operation_context); - - // Queries the quota and usage and then runs the given |task|. - // If an error occurs during the quota query it runs |error_callback| instead. - void GetUsageAndQuotaThenRunTask( - const FileSystemURL& url, - const base::Closure& task, - const base::Closure& error_callback); - - // Called after the quota info is obtained from the quota manager - // (which is triggered by GetUsageAndQuotaThenRunTask). - // Sets the quota info in the operation_context_ and then runs the given - // |task| if the returned quota status is successful, otherwise runs - // |error_callback|. - void DidGetUsageAndQuotaAndRunTask(const base::Closure& task, - const base::Closure& error_callback, - storage::QuotaStatusCode status, - int64 usage, - int64 quota); - - // The 'body' methods that perform the actual work (i.e. posting the - // file task on proxy_) after the quota check. - void DoCreateFile(const FileSystemURL& url, - const StatusCallback& callback, bool exclusive); - void DoCreateDirectory(const FileSystemURL& url, - const StatusCallback& callback, - bool exclusive, - bool recursive); - void DoCopyFileLocal(const FileSystemURL& src, - const FileSystemURL& dest, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback); - void DoMoveFileLocal(const FileSystemURL& src, - const FileSystemURL& dest, - CopyOrMoveOption option, - const StatusCallback& callback); - void DoCopyInForeignFile(const base::FilePath& src_local_disk_file_path, - const FileSystemURL& dest, - const StatusCallback& callback); - void DoTruncate(const FileSystemURL& url, - const StatusCallback& callback, int64 length); - void DoOpenFile(const FileSystemURL& url, - const OpenFileCallback& callback, int file_flags); - - // Callback for CreateFile for |exclusive|=true cases. - void DidEnsureFileExistsExclusive(const StatusCallback& callback, - base::File::Error rv, - bool created); - - // Callback for CreateFile for |exclusive|=false cases. - void DidEnsureFileExistsNonExclusive(const StatusCallback& callback, - base::File::Error rv, - bool created); - - void DidFinishOperation(const StatusCallback& callback, - base::File::Error rv); - void DidDirectoryExists(const StatusCallback& callback, - base::File::Error rv, - const base::File::Info& file_info); - void DidFileExists(const StatusCallback& callback, - base::File::Error rv, - const base::File::Info& file_info); - void DidDeleteRecursively(const FileSystemURL& url, - const StatusCallback& callback, - base::File::Error rv); - void DidWrite(const FileSystemURL& url, - const WriteCallback& callback, - base::File::Error rv, - int64 bytes, - FileWriterDelegate::WriteProgressStatus write_status); - void DidOpenFile(const OpenFileCallback& callback, - base::File file, - const base::Closure& on_close_callback); - - // Used only for internal assertions. - // Returns false if there's another inflight pending operation. - bool SetPendingOperationType(OperationType type); - - scoped_refptr<FileSystemContext> file_system_context_; - - scoped_ptr<FileSystemOperationContext> operation_context_; - AsyncFileUtil* async_file_util_; // Not owned. - - scoped_ptr<FileWriterDelegate> file_writer_delegate_; - scoped_ptr<RecursiveOperationDelegate> recursive_operation_delegate_; - - StatusCallback cancel_callback_; - - // A flag to make sure we call operation only once per instance. - OperationType pending_operation_; - - base::WeakPtrFactory<FileSystemOperationImpl> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImpl); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_IMPL_H_ +#include "storage/browser/fileapi/file_system_operation_impl.h" diff --git a/webkit/browser/fileapi/file_system_operation_runner.cc b/webkit/browser/fileapi/file_system_operation_runner.cc deleted file mode 100644 index 0644b2f..0000000 --- a/webkit/browser/fileapi/file_system_operation_runner.cc +++ /dev/null @@ -1,687 +0,0 @@ -// Copyright 2013 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/browser/fileapi/file_system_operation_runner.h" - -#include "base/bind.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/stl_util.h" -#include "net/url_request/url_request_context.h" -#include "webkit/browser/blob/blob_url_request_job_factory.h" -#include "webkit/browser/fileapi/file_observers.h" -#include "webkit/browser/fileapi/file_stream_writer.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation.h" -#include "webkit/browser/fileapi/file_writer_delegate.h" -#include "webkit/common/blob/shareable_file_reference.h" - -namespace storage { - -typedef FileSystemOperationRunner::OperationID OperationID; - -class FileSystemOperationRunner::BeginOperationScoper - : public base::SupportsWeakPtr< - FileSystemOperationRunner::BeginOperationScoper> { - public: - BeginOperationScoper() {} - private: - DISALLOW_COPY_AND_ASSIGN(BeginOperationScoper); -}; - -FileSystemOperationRunner::OperationHandle::OperationHandle() {} -FileSystemOperationRunner::OperationHandle::~OperationHandle() {} - -FileSystemOperationRunner::~FileSystemOperationRunner() { -} - -void FileSystemOperationRunner::Shutdown() { - operations_.Clear(); -} - -OperationID FileSystemOperationRunner::CreateFile( - const FileSystemURL& url, - bool exclusive, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - PrepareForWrite(handle.id, url); - operation->CreateFile( - url, exclusive, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::CreateDirectory( - const FileSystemURL& url, - bool exclusive, - bool recursive, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - PrepareForWrite(handle.id, url); - operation->CreateDirectory( - url, exclusive, recursive, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::Copy( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyProgressCallback& progress_callback, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(dest_url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - PrepareForWrite(handle.id, dest_url); - PrepareForRead(handle.id, src_url); - operation->Copy( - src_url, dest_url, option, - progress_callback.is_null() ? - CopyProgressCallback() : - base::Bind(&FileSystemOperationRunner::OnCopyProgress, AsWeakPtr(), - handle, progress_callback), - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::Move( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(dest_url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - PrepareForWrite(handle.id, dest_url); - PrepareForWrite(handle.id, src_url); - operation->Move( - src_url, dest_url, option, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::DirectoryExists( - const FileSystemURL& url, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - PrepareForRead(handle.id, url); - operation->DirectoryExists( - url, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::FileExists( - const FileSystemURL& url, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - PrepareForRead(handle.id, url); - operation->FileExists( - url, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::GetMetadata( - const FileSystemURL& url, - const GetMetadataCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidGetMetadata(handle, callback, error, base::File::Info()); - return handle.id; - } - PrepareForRead(handle.id, url); - operation->GetMetadata( - url, - base::Bind(&FileSystemOperationRunner::DidGetMetadata, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::ReadDirectory( - const FileSystemURL& url, - const ReadDirectoryCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidReadDirectory(handle, callback, error, std::vector<DirectoryEntry>(), - false); - return handle.id; - } - PrepareForRead(handle.id, url); - operation->ReadDirectory( - url, - base::Bind(&FileSystemOperationRunner::DidReadDirectory, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::Remove( - const FileSystemURL& url, bool recursive, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - PrepareForWrite(handle.id, url); - operation->Remove( - url, recursive, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::Write( - const net::URLRequestContext* url_request_context, - const FileSystemURL& url, - scoped_ptr<storage::BlobDataHandle> blob, - int64 offset, - const WriteCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidWrite(handle, callback, error, 0, true); - return handle.id; - } - - scoped_ptr<FileStreamWriter> writer( - file_system_context_->CreateFileStreamWriter(url, offset)); - if (!writer) { - // Write is not supported. - DidWrite(handle, callback, base::File::FILE_ERROR_SECURITY, 0, true); - return handle.id; - } - - FileWriterDelegate::FlushPolicy flush_policy = - file_system_context_->ShouldFlushOnWriteCompletion(url.type()) - ? FileWriterDelegate::FLUSH_ON_COMPLETION - : FileWriterDelegate::NO_FLUSH_ON_COMPLETION; - scoped_ptr<FileWriterDelegate> writer_delegate( - new FileWriterDelegate(writer.Pass(), flush_policy)); - - scoped_ptr<net::URLRequest> blob_request( - storage::BlobProtocolHandler::CreateBlobRequest( - blob.Pass(), url_request_context, writer_delegate.get())); - - PrepareForWrite(handle.id, url); - operation->Write( - url, writer_delegate.Pass(), blob_request.Pass(), - base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::Truncate( - const FileSystemURL& url, int64 length, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - PrepareForWrite(handle.id, url); - operation->Truncate( - url, length, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -void FileSystemOperationRunner::Cancel( - OperationID id, - const StatusCallback& callback) { - if (ContainsKey(finished_operations_, id)) { - DCHECK(!ContainsKey(stray_cancel_callbacks_, id)); - stray_cancel_callbacks_[id] = callback; - return; - } - FileSystemOperation* operation = operations_.Lookup(id); - if (!operation) { - // There is no operation with |id|. - callback.Run(base::File::FILE_ERROR_INVALID_OPERATION); - return; - } - operation->Cancel(callback); -} - -OperationID FileSystemOperationRunner::TouchFile( - const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - PrepareForWrite(handle.id, url); - operation->TouchFile( - url, last_access_time, last_modified_time, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::OpenFile( - const FileSystemURL& url, - int file_flags, - const OpenFileCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidOpenFile(handle, callback, base::File(error), base::Closure()); - return handle.id; - } - if (file_flags & - (base::File::FLAG_CREATE | base::File::FLAG_OPEN_ALWAYS | - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_OPEN_TRUNCATED | - base::File::FLAG_WRITE | base::File::FLAG_EXCLUSIVE_WRITE | - base::File::FLAG_DELETE_ON_CLOSE | - base::File::FLAG_WRITE_ATTRIBUTES)) { - PrepareForWrite(handle.id, url); - } else { - PrepareForRead(handle.id, url); - } - operation->OpenFile( - url, file_flags, - base::Bind(&FileSystemOperationRunner::DidOpenFile, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::CreateSnapshotFile( - const FileSystemURL& url, - const SnapshotFileCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidCreateSnapshot(handle, callback, error, base::File::Info(), - base::FilePath(), NULL); - return handle.id; - } - PrepareForRead(handle.id, url); - operation->CreateSnapshotFile( - url, - base::Bind(&FileSystemOperationRunner::DidCreateSnapshot, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::CopyInForeignFile( - const base::FilePath& src_local_disk_path, - const FileSystemURL& dest_url, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(dest_url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - operation->CopyInForeignFile( - src_local_disk_path, dest_url, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::RemoveFile( - const FileSystemURL& url, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - operation->RemoveFile( - url, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::RemoveDirectory( - const FileSystemURL& url, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - operation->RemoveDirectory( - url, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::CopyFileLocal( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(src_url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - operation->CopyFileLocal( - src_url, dest_url, option, progress_callback, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -OperationID FileSystemOperationRunner::MoveFileLocal( - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback) { - base::File::Error error = base::File::FILE_OK; - FileSystemOperation* operation = - file_system_context_->CreateFileSystemOperation(src_url, &error); - BeginOperationScoper scope; - OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); - if (!operation) { - DidFinish(handle, callback, error); - return handle.id; - } - operation->MoveFileLocal( - src_url, dest_url, option, - base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), - handle, callback)); - return handle.id; -} - -base::File::Error FileSystemOperationRunner::SyncGetPlatformPath( - const FileSystemURL& url, - base::FilePath* platform_path) { - base::File::Error error = base::File::FILE_OK; - scoped_ptr<FileSystemOperation> operation( - file_system_context_->CreateFileSystemOperation(url, &error)); - if (!operation.get()) - return error; - return operation->SyncGetPlatformPath(url, platform_path); -} - -FileSystemOperationRunner::FileSystemOperationRunner( - FileSystemContext* file_system_context) - : file_system_context_(file_system_context) {} - -void FileSystemOperationRunner::DidFinish( - const OperationHandle& handle, - const StatusCallback& callback, - base::File::Error rv) { - if (handle.scope) { - finished_operations_.insert(handle.id); - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, base::Bind(&FileSystemOperationRunner::DidFinish, - AsWeakPtr(), handle, callback, rv)); - return; - } - callback.Run(rv); - FinishOperation(handle.id); -} - -void FileSystemOperationRunner::DidGetMetadata( - const OperationHandle& handle, - const GetMetadataCallback& callback, - base::File::Error rv, - const base::File::Info& file_info) { - if (handle.scope) { - finished_operations_.insert(handle.id); - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, base::Bind(&FileSystemOperationRunner::DidGetMetadata, - AsWeakPtr(), handle, callback, rv, file_info)); - return; - } - callback.Run(rv, file_info); - FinishOperation(handle.id); -} - -void FileSystemOperationRunner::DidReadDirectory( - const OperationHandle& handle, - const ReadDirectoryCallback& callback, - base::File::Error rv, - const std::vector<DirectoryEntry>& entries, - bool has_more) { - if (handle.scope) { - finished_operations_.insert(handle.id); - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, base::Bind(&FileSystemOperationRunner::DidReadDirectory, - AsWeakPtr(), handle, callback, rv, - entries, has_more)); - return; - } - callback.Run(rv, entries, has_more); - if (rv != base::File::FILE_OK || !has_more) - FinishOperation(handle.id); -} - -void FileSystemOperationRunner::DidWrite( - const OperationHandle& handle, - const WriteCallback& callback, - base::File::Error rv, - int64 bytes, - bool complete) { - if (handle.scope) { - finished_operations_.insert(handle.id); - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(), - handle, callback, rv, bytes, complete)); - return; - } - callback.Run(rv, bytes, complete); - if (rv != base::File::FILE_OK || complete) - FinishOperation(handle.id); -} - -void FileSystemOperationRunner::DidOpenFile( - const OperationHandle& handle, - const OpenFileCallback& callback, - base::File file, - const base::Closure& on_close_callback) { - if (handle.scope) { - finished_operations_.insert(handle.id); - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, base::Bind(&FileSystemOperationRunner::DidOpenFile, - AsWeakPtr(), handle, callback, Passed(&file), - on_close_callback)); - return; - } - callback.Run(file.Pass(), on_close_callback); - FinishOperation(handle.id); -} - -void FileSystemOperationRunner::DidCreateSnapshot( - const OperationHandle& handle, - const SnapshotFileCallback& callback, - base::File::Error rv, - const base::File::Info& file_info, - const base::FilePath& platform_path, - const scoped_refptr<storage::ShareableFileReference>& file_ref) { - if (handle.scope) { - finished_operations_.insert(handle.id); - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, base::Bind(&FileSystemOperationRunner::DidCreateSnapshot, - AsWeakPtr(), handle, callback, rv, file_info, - platform_path, file_ref)); - return; - } - callback.Run(rv, file_info, platform_path, file_ref); - FinishOperation(handle.id); -} - -void FileSystemOperationRunner::OnCopyProgress( - const OperationHandle& handle, - const CopyProgressCallback& callback, - FileSystemOperation::CopyProgressType type, - const FileSystemURL& source_url, - const FileSystemURL& dest_url, - int64 size) { - if (handle.scope) { - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, base::Bind( - &FileSystemOperationRunner::OnCopyProgress, - AsWeakPtr(), handle, callback, type, source_url, dest_url, size)); - return; - } - callback.Run(type, source_url, dest_url, size); -} - -void FileSystemOperationRunner::PrepareForWrite(OperationID id, - const FileSystemURL& url) { - if (file_system_context_->GetUpdateObservers(url.type())) { - file_system_context_->GetUpdateObservers(url.type())->Notify( - &FileUpdateObserver::OnStartUpdate, MakeTuple(url)); - } - write_target_urls_[id].insert(url); -} - -void FileSystemOperationRunner::PrepareForRead(OperationID id, - const FileSystemURL& url) { - if (file_system_context_->GetAccessObservers(url.type())) { - file_system_context_->GetAccessObservers(url.type())->Notify( - &FileAccessObserver::OnAccess, MakeTuple(url)); - } -} - -FileSystemOperationRunner::OperationHandle -FileSystemOperationRunner::BeginOperation( - FileSystemOperation* operation, - base::WeakPtr<BeginOperationScoper> scope) { - OperationHandle handle; - handle.id = operations_.Add(operation); - handle.scope = scope; - return handle; -} - -void FileSystemOperationRunner::FinishOperation(OperationID id) { - OperationToURLSet::iterator found = write_target_urls_.find(id); - if (found != write_target_urls_.end()) { - const FileSystemURLSet& urls = found->second; - for (FileSystemURLSet::const_iterator iter = urls.begin(); - iter != urls.end(); ++iter) { - if (file_system_context_->GetUpdateObservers(iter->type())) { - file_system_context_->GetUpdateObservers(iter->type())->Notify( - &FileUpdateObserver::OnEndUpdate, MakeTuple(*iter)); - } - } - write_target_urls_.erase(found); - } - - // IDMap::Lookup fails if the operation is NULL, so we don't check - // operations_.Lookup(id) here. - - operations_.Remove(id); - finished_operations_.erase(id); - - // Dispatch stray cancel callback if exists. - std::map<OperationID, StatusCallback>::iterator found_cancel = - stray_cancel_callbacks_.find(id); - if (found_cancel != stray_cancel_callbacks_.end()) { - // This cancel has been requested after the operation has finished, - // so report that we failed to stop it. - found_cancel->second.Run(base::File::FILE_ERROR_INVALID_OPERATION); - stray_cancel_callbacks_.erase(found_cancel); - } -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_operation_runner.h b/webkit/browser/fileapi/file_system_operation_runner.h index cd30d7b..783f9a3 100644 --- a/webkit/browser/fileapi/file_system_operation_runner.h +++ b/webkit/browser/fileapi/file_system_operation_runner.h @@ -1,322 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_RUNNER_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_RUNNER_H_ - -#include <map> -#include <set> -#include <vector> - -#include "base/basictypes.h" -#include "base/id_map.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "webkit/browser/blob/blob_data_handle.h" -#include "webkit/browser/fileapi/file_system_operation.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/storage_browser_export.h" - -namespace net { -class URLRequestContext; -} - -namespace storage { - -class FileSystemURL; -class FileSystemContext; - -// A central interface for running FileSystem API operations. -// All operation methods take callback and returns OperationID, which is -// an integer value which can be used for cancelling an operation. -// All operation methods return kErrorOperationID if running (posting) an -// operation fails, in addition to dispatching the callback with an error -// code (therefore in most cases the caller does not need to check the -// returned operation ID). -class STORAGE_EXPORT FileSystemOperationRunner - : public base::SupportsWeakPtr<FileSystemOperationRunner> { - public: - typedef FileSystemOperation::GetMetadataCallback GetMetadataCallback; - typedef FileSystemOperation::ReadDirectoryCallback ReadDirectoryCallback; - typedef FileSystemOperation::SnapshotFileCallback SnapshotFileCallback; - typedef FileSystemOperation::StatusCallback StatusCallback; - typedef FileSystemOperation::WriteCallback WriteCallback; - typedef FileSystemOperation::OpenFileCallback OpenFileCallback; - typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback; - typedef FileSystemOperation::CopyFileProgressCallback - CopyFileProgressCallback; - typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption; - - typedef int OperationID; - - virtual ~FileSystemOperationRunner(); - - // Cancels all inflight operations. - void Shutdown(); - - // Creates a file at |url|. If |exclusive| is true, an error is raised - // in case a file is already present at the URL. - OperationID CreateFile(const FileSystemURL& url, - bool exclusive, - const StatusCallback& callback); - - OperationID CreateDirectory(const FileSystemURL& url, - bool exclusive, - bool recursive, - const StatusCallback& callback); - - // Copies a file or directory from |src_url| to |dest_url|. If - // |src_url| is a directory, the contents of |src_url| are copied to - // |dest_url| recursively. A new file or directory is created at - // |dest_url| as needed. - // For |option| and |progress_callback|, see file_system_operation.h for - // details. - OperationID Copy(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyProgressCallback& progress_callback, - const StatusCallback& callback); - - // Moves a file or directory from |src_url| to |dest_url|. A new file - // or directory is created at |dest_url| as needed. - // For |option|, see file_system_operation.h for details. - OperationID Move(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback); - - // Checks if a directory is present at |url|. - OperationID DirectoryExists(const FileSystemURL& url, - const StatusCallback& callback); - - // Checks if a file is present at |url|. - OperationID FileExists(const FileSystemURL& url, - const StatusCallback& callback); - - // Gets the metadata of a file or directory at |url|. - OperationID GetMetadata(const FileSystemURL& url, - const GetMetadataCallback& callback); - - // Reads contents of a directory at |url|. - OperationID ReadDirectory(const FileSystemURL& url, - const ReadDirectoryCallback& callback); - - // Removes a file or directory at |url|. If |recursive| is true, remove - // all files and directories under the directory at |url| recursively. - OperationID Remove(const FileSystemURL& url, bool recursive, - const StatusCallback& callback); - - // Writes contents of |blob_url| to |url| at |offset|. - // |url_request_context| is used to read contents in |blob|. - OperationID Write(const net::URLRequestContext* url_request_context, - const FileSystemURL& url, - scoped_ptr<storage::BlobDataHandle> blob, - int64 offset, - const WriteCallback& callback); - - // Truncates a file at |url| to |length|. If |length| is larger than - // the original file size, the file will be extended, and the extended - // part is filled with null bytes. - OperationID Truncate(const FileSystemURL& url, int64 length, - const StatusCallback& callback); - - // Tries to cancel the operation |id| [we support cancelling write or - // truncate only]. Reports failure for the current operation, then reports - // success for the cancel operation itself via the |callback|. - void Cancel(OperationID id, const StatusCallback& callback); - - // Modifies timestamps of a file or directory at |url| with - // |last_access_time| and |last_modified_time|. The function DOES NOT - // create a file unlike 'touch' command on Linux. - // - // This function is used only by Pepper as of writing. - OperationID TouchFile(const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time, - const StatusCallback& callback); - - // Opens a file at |url| with |file_flags|, where flags are OR'ed - // values of base::PlatformFileFlags. - // - // |peer_handle| is the process handle of a pepper plugin process, which - // is necessary for underlying IPC calls with Pepper plugins. - // - // This function is used only by Pepper as of writing. - OperationID OpenFile(const FileSystemURL& url, - int file_flags, - const OpenFileCallback& callback); - - // Creates a local snapshot file for a given |url| and returns the - // metadata and platform url of the snapshot file via |callback|. - // In local filesystem cases the implementation may simply return - // the metadata of the file itself (as well as GetMetadata does), - // while in remote filesystem case the backend may want to download the file - // into a temporary snapshot file and return the metadata of the - // temporary file. Or if the implementaiton already has the local cache - // data for |url| it can simply return the url to the cache. - OperationID CreateSnapshotFile(const FileSystemURL& url, - const SnapshotFileCallback& callback); - - // Copies in a single file from a different filesystem. - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |src_file_path| - // or the parent directory of |dest_url| does not exist. - // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - File::FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - OperationID CopyInForeignFile(const base::FilePath& src_local_disk_path, - const FileSystemURL& dest_url, - const StatusCallback& callback); - - // Removes a single file. - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |url| is not a file. - // - OperationID RemoveFile(const FileSystemURL& url, - const StatusCallback& callback); - - // Removes a single empty directory. - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |url| does not exist. - // - File::FILE_ERROR_NOT_A_DIRECTORY if |url| is not a directory. - // - File::FILE_ERROR_NOT_EMPTY if |url| is not empty. - // - OperationID RemoveDirectory(const FileSystemURL& url, - const StatusCallback& callback); - - // Copies a file from |src_url| to |dest_url|. - // This must be called for files that belong to the same filesystem - // (i.e. type() and origin() of the |src_url| and |dest_url| must match). - // For |option| and |progress_callback|, see file_system_operation.h for - // details. - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |src_url| - // or the parent directory of |dest_url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. - // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - File::FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - OperationID CopyFileLocal(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const CopyFileProgressCallback& progress_callback, - const StatusCallback& callback); - - // Moves a local file from |src_url| to |dest_url|. - // This must be called for files that belong to the same filesystem - // (i.e. type() and origin() of the |src_url| and |dest_url| must match). - // For |option|, see file_system_operation.h for details. - // - // This returns: - // - File::FILE_ERROR_NOT_FOUND if |src_url| - // or the parent directory of |dest_url| does not exist. - // - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. - // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and - // is not a file. - // - File::FILE_ERROR_FAILED if |dest_url| does not exist and - // its parent path is a file. - // - OperationID MoveFileLocal(const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - const StatusCallback& callback); - - // This is called only by pepper plugin as of writing to synchronously get - // the underlying platform path to upload a file in the sandboxed filesystem - // (e.g. TEMPORARY or PERSISTENT). - base::File::Error SyncGetPlatformPath(const FileSystemURL& url, - base::FilePath* platform_path); - - private: - class BeginOperationScoper; - - struct OperationHandle { - OperationID id; - base::WeakPtr<BeginOperationScoper> scope; - - OperationHandle(); - ~OperationHandle(); - }; - - friend class FileSystemContext; - explicit FileSystemOperationRunner(FileSystemContext* file_system_context); - - void DidFinish(const OperationHandle& handle, - const StatusCallback& callback, - base::File::Error rv); - void DidGetMetadata(const OperationHandle& handle, - const GetMetadataCallback& callback, - base::File::Error rv, - const base::File::Info& file_info); - void DidReadDirectory(const OperationHandle& handle, - const ReadDirectoryCallback& callback, - base::File::Error rv, - const std::vector<DirectoryEntry>& entries, - bool has_more); - void DidWrite(const OperationHandle& handle, - const WriteCallback& callback, - base::File::Error rv, - int64 bytes, - bool complete); - void DidOpenFile( - const OperationHandle& handle, - const OpenFileCallback& callback, - base::File file, - const base::Closure& on_close_callback); - void DidCreateSnapshot( - const OperationHandle& handle, - const SnapshotFileCallback& callback, - base::File::Error rv, - const base::File::Info& file_info, - const base::FilePath& platform_path, - const scoped_refptr<storage::ShareableFileReference>& file_ref); - - void OnCopyProgress( - const OperationHandle& handle, - const CopyProgressCallback& callback, - FileSystemOperation::CopyProgressType type, - const FileSystemURL& source_url, - const FileSystemURL& dest_url, - int64 size); - - void PrepareForWrite(OperationID id, const FileSystemURL& url); - void PrepareForRead(OperationID id, const FileSystemURL& url); - - // These must be called at the beginning and end of any async operations. - OperationHandle BeginOperation(FileSystemOperation* operation, - base::WeakPtr<BeginOperationScoper> scope); - void FinishOperation(OperationID id); - - // Not owned; file_system_context owns this. - FileSystemContext* file_system_context_; - - // IDMap<FileSystemOperation, IDMapOwnPointer> operations_; - IDMap<FileSystemOperation, IDMapOwnPointer> operations_; - - // We keep track of the file to be modified by each operation so that - // we can notify observers when we're done. - typedef std::map<OperationID, FileSystemURLSet> OperationToURLSet; - OperationToURLSet write_target_urls_; - - // Operations that are finished but not yet fire their callbacks. - std::set<OperationID> finished_operations_; - - // Callbacks for stray cancels whose target operation is already finished. - std::map<OperationID, StatusCallback> stray_cancel_callbacks_; - - DISALLOW_COPY_AND_ASSIGN(FileSystemOperationRunner); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_RUNNER_H_ +#include "storage/browser/fileapi/file_system_operation_runner.h" diff --git a/webkit/browser/fileapi/file_system_options.cc b/webkit/browser/fileapi/file_system_options.cc deleted file mode 100644 index c1d6ff2..0000000 --- a/webkit/browser/fileapi/file_system_options.cc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_options.h" - -namespace storage { - -FileSystemOptions::FileSystemOptions( - ProfileMode profile_mode, - const std::vector<std::string>& additional_allowed_schemes, - leveldb::Env* env_override) - : profile_mode_(profile_mode), - additional_allowed_schemes_(additional_allowed_schemes), - env_override_(env_override) { -} - -FileSystemOptions::~FileSystemOptions() { -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_options.h b/webkit/browser/fileapi/file_system_options.h index 23048d9..c05e8d1 100644 --- a/webkit/browser/fileapi/file_system_options.h +++ b/webkit/browser/fileapi/file_system_options.h @@ -1,62 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_OPTIONS_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPTIONS_H_ - -#include <string> -#include <vector> - -#include "webkit/browser/storage_browser_export.h" - -namespace leveldb { -class Env; -} - -namespace storage { - -// Provides runtime options that may change FileSystem API behavior. -// This object is copyable. -class STORAGE_EXPORT FileSystemOptions { - public: - enum ProfileMode { - PROFILE_MODE_NORMAL = 0, - PROFILE_MODE_INCOGNITO - }; - - // |profile_mode| specifies if the profile (for this filesystem) - // is running in incognito mode (PROFILE_MODE_INCOGNITO) or no - // (PROFILE_MODE_NORMAL). - // |additional_allowed_schemes| specifies schemes that are allowed - // to access FileSystem API in addition to "http" and "https". - // Non-NULL |env_override| overrides internal LevelDB environment. - FileSystemOptions( - ProfileMode profile_mode, - const std::vector<std::string>& additional_allowed_schemes, - leveldb::Env* env_override); - - ~FileSystemOptions(); - - // Returns true if it is running in the incognito mode. - bool is_incognito() const { return profile_mode_ == PROFILE_MODE_INCOGNITO; } - - // Returns the schemes that must be allowed to access FileSystem API - // in addition to standard "http" and "https". - // (e.g. If the --allow-file-access-from-files option is given in chrome - // "file" scheme will also need to be allowed). - const std::vector<std::string>& additional_allowed_schemes() const { - return additional_allowed_schemes_; - } - - leveldb::Env* env_override() const { return env_override_; } - - private: - const ProfileMode profile_mode_; - const std::vector<std::string> additional_allowed_schemes_; - leveldb::Env* env_override_; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPTIONS_H_ +#include "storage/browser/fileapi/file_system_options.h" diff --git a/webkit/browser/fileapi/file_system_quota_client.cc b/webkit/browser/fileapi/file_system_quota_client.cc deleted file mode 100644 index 8d2fd68..0000000 --- a/webkit/browser/fileapi/file_system_quota_client.cc +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_quota_client.h" - -#include <algorithm> -#include <set> - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/sequenced_task_runner.h" -#include "base/single_thread_task_runner.h" -#include "base/task_runner_util.h" -#include "net/base/net_util.h" -#include "url/gurl.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_quota_util.h" -#include "webkit/browser/fileapi/file_system_usage_cache.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend.h" -#include "webkit/common/fileapi/file_system_util.h" - -using storage::StorageType; - -namespace storage { - -namespace { - -void GetOriginsForTypeOnFileTaskRunner( - FileSystemContext* context, - StorageType storage_type, - std::set<GURL>* origins_ptr) { - FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); - DCHECK(type != kFileSystemTypeUnknown); - - FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type); - if (!quota_util) - return; - quota_util->GetOriginsForTypeOnFileTaskRunner(type, origins_ptr); -} - -void GetOriginsForHostOnFileTaskRunner( - FileSystemContext* context, - StorageType storage_type, - const std::string& host, - std::set<GURL>* origins_ptr) { - FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); - DCHECK(type != kFileSystemTypeUnknown); - - FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type); - if (!quota_util) - return; - quota_util->GetOriginsForHostOnFileTaskRunner(type, host, origins_ptr); -} - -void DidGetOrigins(const storage::QuotaClient::GetOriginsCallback& callback, - std::set<GURL>* origins_ptr) { - callback.Run(*origins_ptr); -} - -storage::QuotaStatusCode DeleteOriginOnFileTaskRunner( - FileSystemContext* context, - const GURL& origin, - FileSystemType type) { - FileSystemBackend* provider = context->GetFileSystemBackend(type); - if (!provider || !provider->GetQuotaUtil()) - return storage::kQuotaErrorNotSupported; - base::File::Error result = - provider->GetQuotaUtil()->DeleteOriginDataOnFileTaskRunner( - context, context->quota_manager_proxy(), origin, type); - if (result == base::File::FILE_OK) - return storage::kQuotaStatusOk; - return storage::kQuotaErrorInvalidModification; -} - -} // namespace - -FileSystemQuotaClient::FileSystemQuotaClient( - FileSystemContext* file_system_context, - bool is_incognito) - : file_system_context_(file_system_context), - is_incognito_(is_incognito) { -} - -FileSystemQuotaClient::~FileSystemQuotaClient() {} - -storage::QuotaClient::ID FileSystemQuotaClient::id() const { - return storage::QuotaClient::kFileSystem; -} - -void FileSystemQuotaClient::OnQuotaManagerDestroyed() { - delete this; -} - -void FileSystemQuotaClient::GetOriginUsage( - const GURL& origin_url, - StorageType storage_type, - const GetUsageCallback& callback) { - DCHECK(!callback.is_null()); - - if (is_incognito_) { - // We don't support FileSystem in incognito mode yet. - callback.Run(0); - return; - } - - FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); - DCHECK(type != kFileSystemTypeUnknown); - - FileSystemQuotaUtil* quota_util = file_system_context_->GetQuotaUtil(type); - if (!quota_util) { - callback.Run(0); - return; - } - - base::PostTaskAndReplyWithResult( - file_task_runner(), - FROM_HERE, - // It is safe to pass Unretained(quota_util) since context owns it. - base::Bind(&FileSystemQuotaUtil::GetOriginUsageOnFileTaskRunner, - base::Unretained(quota_util), - file_system_context_, - origin_url, - type), - callback); -} - -void FileSystemQuotaClient::GetOriginsForType( - StorageType storage_type, - const GetOriginsCallback& callback) { - DCHECK(!callback.is_null()); - - if (is_incognito_) { - // We don't support FileSystem in incognito mode yet. - std::set<GURL> origins; - callback.Run(origins); - return; - } - - std::set<GURL>* origins_ptr = new std::set<GURL>(); - file_task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&GetOriginsForTypeOnFileTaskRunner, - file_system_context_, - storage_type, - base::Unretained(origins_ptr)), - base::Bind(&DidGetOrigins, - callback, - base::Owned(origins_ptr))); -} - -void FileSystemQuotaClient::GetOriginsForHost( - StorageType storage_type, - const std::string& host, - const GetOriginsCallback& callback) { - DCHECK(!callback.is_null()); - - if (is_incognito_) { - // We don't support FileSystem in incognito mode yet. - std::set<GURL> origins; - callback.Run(origins); - return; - } - - std::set<GURL>* origins_ptr = new std::set<GURL>(); - file_task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&GetOriginsForHostOnFileTaskRunner, - file_system_context_, - storage_type, - host, - base::Unretained(origins_ptr)), - base::Bind(&DidGetOrigins, - callback, - base::Owned(origins_ptr))); -} - -void FileSystemQuotaClient::DeleteOriginData( - const GURL& origin, - StorageType type, - const DeletionCallback& callback) { - FileSystemType fs_type = QuotaStorageTypeToFileSystemType(type); - DCHECK(fs_type != kFileSystemTypeUnknown); - - base::PostTaskAndReplyWithResult( - file_task_runner(), - FROM_HERE, - base::Bind(&DeleteOriginOnFileTaskRunner, - file_system_context_, - origin, - fs_type), - callback); -} - -bool FileSystemQuotaClient::DoesSupport( - storage::StorageType storage_type) const { - FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); - DCHECK(type != kFileSystemTypeUnknown); - return file_system_context_->IsSandboxFileSystem(type); -} - -base::SequencedTaskRunner* FileSystemQuotaClient::file_task_runner() const { - return file_system_context_->default_file_task_runner(); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_quota_client.h b/webkit/browser/fileapi/file_system_quota_client.h index 7709b6d..578a2dc 100644 --- a/webkit/browser/fileapi/file_system_quota_client.h +++ b/webkit/browser/fileapi/file_system_quota_client.h @@ -1,70 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_QUOTA_CLIENT_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_QUOTA_CLIENT_H_ - -#include <set> -#include <string> -#include <utility> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "webkit/browser/fileapi/file_system_quota_util.h" -#include "webkit/browser/quota/quota_client.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_types.h" - -namespace base { -class SequencedTaskRunner; -} - -namespace storage { - -class FileSystemContext; - -// An instance of this class is created per-profile. This class -// is self-destructed and will delete itself when OnQuotaManagerDestroyed -// is called. -// All of the public methods of this class are called by the quota manager -// (except for the constructor/destructor). -class STORAGE_EXPORT_PRIVATE FileSystemQuotaClient - : public NON_EXPORTED_BASE(storage::QuotaClient) { - public: - FileSystemQuotaClient( - FileSystemContext* file_system_context, - bool is_incognito); - virtual ~FileSystemQuotaClient(); - - // QuotaClient methods. - virtual storage::QuotaClient::ID id() const OVERRIDE; - virtual void OnQuotaManagerDestroyed() OVERRIDE; - virtual void GetOriginUsage(const GURL& origin_url, - storage::StorageType type, - const GetUsageCallback& callback) OVERRIDE; - virtual void GetOriginsForType(storage::StorageType type, - const GetOriginsCallback& callback) OVERRIDE; - virtual void GetOriginsForHost(storage::StorageType type, - const std::string& host, - const GetOriginsCallback& callback) OVERRIDE; - virtual void DeleteOriginData(const GURL& origin, - storage::StorageType type, - const DeletionCallback& callback) OVERRIDE; - virtual bool DoesSupport(storage::StorageType type) const OVERRIDE; - - private: - base::SequencedTaskRunner* file_task_runner() const; - - scoped_refptr<FileSystemContext> file_system_context_; - - bool is_incognito_; - - DISALLOW_COPY_AND_ASSIGN(FileSystemQuotaClient); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_QUOTA_CLIENT_H_ +#include "storage/browser/fileapi/file_system_quota_client.h" diff --git a/webkit/browser/fileapi/file_system_quota_util.h b/webkit/browser/fileapi/file_system_quota_util.h index 045c36d..f42e6d8 100644 --- a/webkit/browser/fileapi/file_system_quota_util.h +++ b/webkit/browser/fileapi/file_system_quota_util.h @@ -1,91 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_QUOTA_UTIL_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_QUOTA_UTIL_H_ - -#include <set> -#include <string> - -#include "base/basictypes.h" -#include "base/files/file.h" -#include "url/gurl.h" -#include "webkit/browser/fileapi/task_runner_bound_observer_list.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_types.h" - -namespace base { -class SequencedTaskRunner; -} - -namespace storage { -class QuotaManagerProxy; -} - -namespace storage { - -class FileSystemContext; -class QuotaReservation; - -// An abstract interface that provides common quota-related utility functions -// for file_system_quota_client. -// All the methods of this class are synchronous and need to be called on -// the thread that the method name implies. -class STORAGE_EXPORT FileSystemQuotaUtil { - public: - virtual ~FileSystemQuotaUtil() {} - - // Deletes the data on the origin and reports the amount of deleted data - // to the quota manager via |proxy|. - virtual base::File::Error DeleteOriginDataOnFileTaskRunner( - FileSystemContext* context, - storage::QuotaManagerProxy* proxy, - const GURL& origin_url, - FileSystemType type) = 0; - - virtual void GetOriginsForTypeOnFileTaskRunner(storage::FileSystemType type, - std::set<GURL>* origins) = 0; - - virtual void GetOriginsForHostOnFileTaskRunner(storage::FileSystemType type, - const std::string& host, - std::set<GURL>* origins) = 0; - - // Returns the amount of data used for the origin for usage tracking. - virtual int64 GetOriginUsageOnFileTaskRunner( - storage::FileSystemContext* file_system_context, - const GURL& origin_url, - storage::FileSystemType type) = 0; - - // Creates new reservation object for the origin and the type. - virtual scoped_refptr<QuotaReservation> - CreateQuotaReservationOnFileTaskRunner( - const GURL& origin_url, - FileSystemType type) = 0; - - virtual void AddFileUpdateObserver( - FileSystemType type, - FileUpdateObserver* observer, - base::SequencedTaskRunner* task_runner) = 0; - virtual void AddFileChangeObserver( - FileSystemType type, - FileChangeObserver* observer, - base::SequencedTaskRunner* task_runner) = 0; - virtual void AddFileAccessObserver( - FileSystemType type, - FileAccessObserver* observer, - base::SequencedTaskRunner* task_runner) = 0; - - // Returns the observer list for |type|, or returns NULL if any observers - // have not been registered on |type|. - virtual const UpdateObserverList* GetUpdateObservers( - FileSystemType type) const = 0; - virtual const ChangeObserverList* GetChangeObservers( - FileSystemType type) const = 0; - virtual const AccessObserverList* GetAccessObservers( - FileSystemType type) const = 0; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_QUOTA_UTIL_H_ +#include "storage/browser/fileapi/file_system_quota_util.h" diff --git a/webkit/browser/fileapi/file_system_url.cc b/webkit/browser/fileapi/file_system_url.cc deleted file mode 100644 index 29b2b3fb..0000000 --- a/webkit/browser/fileapi/file_system_url.cc +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_url.h" - -#include <sstream> - -#include "base/logging.h" -#include "base/strings/string_util.h" -#include "net/base/escape.h" -#include "webkit/common/fileapi/file_system_types.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace storage { - -namespace { - -} // namespace - -FileSystemURL::FileSystemURL() - : is_valid_(false), - mount_type_(kFileSystemTypeUnknown), - type_(kFileSystemTypeUnknown), - mount_option_(COPY_SYNC_OPTION_NO_SYNC) { -} - -// static -FileSystemURL FileSystemURL::CreateForTest(const GURL& url) { - return FileSystemURL(url); -} - -FileSystemURL FileSystemURL::CreateForTest(const GURL& origin, - FileSystemType mount_type, - const base::FilePath& virtual_path) { - return FileSystemURL(origin, mount_type, virtual_path); -} - -FileSystemURL::FileSystemURL(const GURL& url) - : mount_type_(kFileSystemTypeUnknown), - type_(kFileSystemTypeUnknown), - mount_option_(COPY_SYNC_OPTION_NO_SYNC) { - is_valid_ = ParseFileSystemSchemeURL(url, &origin_, &mount_type_, - &virtual_path_); - path_ = virtual_path_; - type_ = mount_type_; -} - -FileSystemURL::FileSystemURL(const GURL& origin, - FileSystemType mount_type, - const base::FilePath& virtual_path) - : is_valid_(true), - origin_(origin), - mount_type_(mount_type), - virtual_path_(virtual_path.NormalizePathSeparators()), - type_(mount_type), - path_(virtual_path.NormalizePathSeparators()), - mount_option_(COPY_SYNC_OPTION_NO_SYNC) { -} - -FileSystemURL::FileSystemURL(const GURL& origin, - FileSystemType mount_type, - const base::FilePath& virtual_path, - const std::string& mount_filesystem_id, - FileSystemType cracked_type, - const base::FilePath& cracked_path, - const std::string& filesystem_id, - const FileSystemMountOption& mount_option) - : is_valid_(true), - origin_(origin), - mount_type_(mount_type), - virtual_path_(virtual_path.NormalizePathSeparators()), - mount_filesystem_id_(mount_filesystem_id), - type_(cracked_type), - path_(cracked_path.NormalizePathSeparators()), - filesystem_id_(filesystem_id), - mount_option_(mount_option) { -} - -FileSystemURL::~FileSystemURL() {} - -GURL FileSystemURL::ToGURL() const { - if (!is_valid_) - return GURL(); - - std::string url = GetFileSystemRootURI(origin_, mount_type_).spec(); - if (url.empty()) - return GURL(); - - // Exactly match with DOMFileSystemBase::createFileSystemURL()'s encoding - // behavior, where the path is escaped by KURL::encodeWithURLEscapeSequences - // which is essentially encodeURIComponent except '/'. - std::string escaped = net::EscapeQueryParamValue( - virtual_path_.NormalizePathSeparatorsTo('/').AsUTF8Unsafe(), - false /* use_plus */); - ReplaceSubstringsAfterOffset(&escaped, 0, "%2F", "/"); - url.append(escaped); - - // Build nested GURL. - return GURL(url); -} - -std::string FileSystemURL::DebugString() const { - if (!is_valid_) - return "invalid filesystem: URL"; - std::ostringstream ss; - ss << GetFileSystemRootURI(origin_, mount_type_); - - // filesystem_id_ will be non empty for (and only for) cracked URLs. - if (!filesystem_id_.empty()) { - ss << virtual_path_.value(); - ss << " ("; - ss << GetFileSystemTypeString(type_) << "@" << filesystem_id_ << ":"; - ss << path_.value(); - ss << ")"; - } else { - ss << path_.value(); - } - return ss.str(); -} - -bool FileSystemURL::IsParent(const FileSystemURL& child) const { - return IsInSameFileSystem(child) && - path().IsParent(child.path()); -} - -bool FileSystemURL::IsInSameFileSystem(const FileSystemURL& other) const { - return origin() == other.origin() && - type() == other.type() && - filesystem_id() == other.filesystem_id(); -} - -bool FileSystemURL::operator==(const FileSystemURL& that) const { - return origin_ == that.origin_ && - type_ == that.type_ && - path_ == that.path_ && - filesystem_id_ == that.filesystem_id_ && - is_valid_ == that.is_valid_; -} - -bool FileSystemURL::Comparator::operator()(const FileSystemURL& lhs, - const FileSystemURL& rhs) const { - DCHECK(lhs.is_valid_ && rhs.is_valid_); - if (lhs.origin_ != rhs.origin_) - return lhs.origin_ < rhs.origin_; - if (lhs.type_ != rhs.type_) - return lhs.type_ < rhs.type_; - if (lhs.filesystem_id_ != rhs.filesystem_id_) - return lhs.filesystem_id_ < rhs.filesystem_id_; - return lhs.path_ < rhs.path_; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_url.h b/webkit/browser/fileapi/file_system_url.h index fe65c1b..5a6316e 100644 --- a/webkit/browser/fileapi/file_system_url.h +++ b/webkit/browser/fileapi/file_system_url.h @@ -1,180 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_URL_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_URL_H_ - -#include <set> -#include <string> - -#include "base/files/file_path.h" -#include "url/gurl.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_mount_option.h" -#include "webkit/common/fileapi/file_system_types.h" - -namespace storage { - -// A class representing a filesystem URL which consists of origin URL, -// type and an internal path used inside the filesystem. -// -// When a FileSystemURL instance is created for a GURL (for filesystem: scheme), -// each accessor method would return following values: -// -// Example: For a URL 'filesystem:http://foo.com/temporary/foo/bar': -// origin() returns 'http://foo.com', -// mount_type() returns kFileSystemTypeTemporary, -// virtual_path() returns 'foo/bar', -// type() returns the same value as mount_type(), -// path() returns the same value as virtual_path(), -// -// All other accessors return empty or invalid value. -// -// FileSystemURL can also be created to represent a 'cracked' filesystem URL if -// the original URL's type/path is pointing to a mount point which can be -// further resolved to a lower filesystem type/path. -// -// Example: Assume a path '/media/removable' is mounted at mount name -// 'mount_name' with type kFileSystemTypeFoo as an external file system. -// -// The original URL would look like: -// 'filesystem:http://bar.com/external/mount_name/foo/bar': -// -// FileSystemURL('http://bar.com', -// kFileSystemTypeExternal, -// 'mount_name/foo/bar' -// 'mount_name', -// kFileSystemTypeFoo, -// '/media/removable/foo/bar'); -// would create a FileSystemURL whose accessors return: -// -// origin() returns 'http://bar.com', -// mount_type() returns kFileSystemTypeExternal, -// virtual_path() returns 'mount_name/foo/bar', -// type() returns the kFileSystemTypeFoo, -// path() returns '/media/removable/foo/bar', -// -// Note that in either case virtual_path() always returns the path part after -// 'type' part in the original URL, and mount_type() always returns the 'type' -// part in the original URL. -// -// Additionally, following accessors would return valid values: -// filesystem_id() returns 'mount_name'. -// -// It is impossible to directly create a valid FileSystemURL instance (except by -// using CreatedForTest methods, which should not be used in production code). -// To get a valid FileSystemURL, one of the following methods can be used: -// <Friend>::CrackURL, <Friend>::CreateCrackedFileSystemURL, where <Friend> is -// one of the friended classes. -// -// TODO(ericu): Look into making virtual_path() [and all FileSystem API virtual -// paths] just an std::string, to prevent platform-specific base::FilePath -// behavior from getting invoked by accident. Currently the base::FilePath -// returned here needs special treatment, as it may contain paths that are -// illegal on the current platform. -// To avoid problems, use VirtualPath::BaseName and -// VirtualPath::GetComponents instead of the base::FilePath methods. -class STORAGE_EXPORT FileSystemURL { - public: - FileSystemURL(); - ~FileSystemURL(); - - // Methods for creating FileSystemURL without attempting to crack them. - // Should be used only in tests. - static FileSystemURL CreateForTest(const GURL& url); - static FileSystemURL CreateForTest(const GURL& origin, - FileSystemType mount_type, - const base::FilePath& virtual_path); - - // Returns true if this instance represents a valid FileSystem URL. - bool is_valid() const { return is_valid_; } - - // Returns the origin part of this URL. See the class comment for details. - const GURL& origin() const { return origin_; } - - // Returns the type part of this URL. See the class comment for details. - FileSystemType type() const { return type_; } - - // Returns the cracked path of this URL. See the class comment for details. - const base::FilePath& path() const { return path_; } - - // Returns the original path part of this URL. - // See the class comment for details. - // TODO(kinuko): this must return std::string. - const base::FilePath& virtual_path() const { return virtual_path_; } - - // Returns the filesystem ID/mount name for isolated/external filesystem URLs. - // See the class comment for details. - const std::string& filesystem_id() const { return filesystem_id_; } - const std::string& mount_filesystem_id() const { - return mount_filesystem_id_; - } - - FileSystemType mount_type() const { return mount_type_; } - - const FileSystemMountOption& mount_option() const { return mount_option_; } - - // Returns the formatted URL of this instance. - GURL ToGURL() const; - - std::string DebugString() const; - - // Returns true if this URL is a strict parent of the |child|. - bool IsParent(const FileSystemURL& child) const; - - bool IsInSameFileSystem(const FileSystemURL& other) const; - - bool operator==(const FileSystemURL& that) const; - - bool operator!=(const FileSystemURL& that) const { - return !(*this == that); - } - - struct STORAGE_EXPORT Comparator { - bool operator() (const FileSystemURL& lhs, const FileSystemURL& rhs) const; - }; - - private: - friend class FileSystemContext; - friend class ExternalMountPoints; - friend class IsolatedContext; - - explicit FileSystemURL(const GURL& filesystem_url); - FileSystemURL(const GURL& origin, - FileSystemType mount_type, - const base::FilePath& virtual_path); - // Creates a cracked FileSystemURL. - FileSystemURL(const GURL& origin, - FileSystemType mount_type, - const base::FilePath& virtual_path, - const std::string& mount_filesystem_id, - FileSystemType cracked_type, - const base::FilePath& cracked_path, - const std::string& filesystem_id, - const FileSystemMountOption& mount_option); - - bool is_valid_; - - // Values parsed from the original URL. - GURL origin_; - FileSystemType mount_type_; - base::FilePath virtual_path_; - - // Values obtained by cracking URLs. - // |mount_filesystem_id_| is retrieved from the first round of cracking, - // and the rest of the fields are from recursive cracking. Permission - // checking on the top-level mount information should be done with the former, - // and the low-level file operation should be implemented with the latter. - std::string mount_filesystem_id_; - FileSystemType type_; - base::FilePath path_; - std::string filesystem_id_; - FileSystemMountOption mount_option_; -}; - -typedef std::set<FileSystemURL, FileSystemURL::Comparator> FileSystemURLSet; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_URL_H_ +#include "storage/browser/fileapi/file_system_url.h" diff --git a/webkit/browser/fileapi/file_system_url_request_job.cc b/webkit/browser/fileapi/file_system_url_request_job.cc deleted file mode 100644 index bdfd931..0000000 --- a/webkit/browser/fileapi/file_system_url_request_job.cc +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_url_request_job.h" - -#include <vector> - -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/files/file_util_proxy.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/threading/thread_restrictions.h" -#include "base/time/time.h" -#include "build/build_config.h" -#include "net/base/file_stream.h" -#include "net/base/io_buffer.h" -#include "net/base/mime_util.h" -#include "net/base/net_errors.h" -#include "net/base/net_util.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_response_info.h" -#include "net/http/http_util.h" -#include "net/url_request/url_request.h" -#include "url/gurl.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_runner.h" -#include "webkit/common/fileapi/file_system_util.h" - -using net::NetworkDelegate; -using net::URLRequest; -using net::URLRequestJob; -using net::URLRequestStatus; - -namespace storage { - -static net::HttpResponseHeaders* CreateHttpResponseHeaders() { - // HttpResponseHeaders expects its input string to be terminated by two NULs. - static const char kStatus[] = "HTTP/1.1 200 OK\0"; - static const size_t kStatusLen = arraysize(kStatus); - - net::HttpResponseHeaders* headers = - new net::HttpResponseHeaders(std::string(kStatus, kStatusLen)); - - // Tell WebKit never to cache this content. - std::string cache_control(net::HttpRequestHeaders::kCacheControl); - cache_control.append(": no-cache"); - headers->AddHeader(cache_control); - - return headers; -} - -FileSystemURLRequestJob::FileSystemURLRequestJob( - URLRequest* request, - NetworkDelegate* network_delegate, - const std::string& storage_domain, - FileSystemContext* file_system_context) - : URLRequestJob(request, network_delegate), - storage_domain_(storage_domain), - file_system_context_(file_system_context), - is_directory_(false), - remaining_bytes_(0), - weak_factory_(this) { -} - -FileSystemURLRequestJob::~FileSystemURLRequestJob() {} - -void FileSystemURLRequestJob::Start() { - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&FileSystemURLRequestJob::StartAsync, - weak_factory_.GetWeakPtr())); -} - -void FileSystemURLRequestJob::Kill() { - reader_.reset(); - URLRequestJob::Kill(); - weak_factory_.InvalidateWeakPtrs(); -} - -bool FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size, - int *bytes_read) { - DCHECK_NE(dest_size, 0); - DCHECK(bytes_read); - DCHECK_GE(remaining_bytes_, 0); - - if (reader_.get() == NULL) - return false; - - if (remaining_bytes_ < dest_size) - dest_size = static_cast<int>(remaining_bytes_); - - if (!dest_size) { - *bytes_read = 0; - return true; - } - - const int rv = reader_->Read(dest, dest_size, - base::Bind(&FileSystemURLRequestJob::DidRead, - weak_factory_.GetWeakPtr())); - if (rv >= 0) { - // Data is immediately available. - *bytes_read = rv; - remaining_bytes_ -= rv; - DCHECK_GE(remaining_bytes_, 0); - return true; - } - if (rv == net::ERR_IO_PENDING) - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - else - NotifyFailed(rv); - return false; -} - -bool FileSystemURLRequestJob::GetMimeType(std::string* mime_type) const { - DCHECK(request_); - DCHECK(url_.is_valid()); - base::FilePath::StringType extension = url_.path().Extension(); - if (!extension.empty()) - extension = extension.substr(1); - return net::GetWellKnownMimeTypeFromExtension(extension, mime_type); -} - -void FileSystemURLRequestJob::SetExtraRequestHeaders( - const net::HttpRequestHeaders& headers) { - std::string range_header; - if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { - std::vector<net::HttpByteRange> ranges; - if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { - if (ranges.size() == 1) { - byte_range_ = ranges[0]; - } else { - // We don't support multiple range requests in one single URL request. - // TODO(adamk): decide whether we want to support multiple range - // requests. - NotifyFailed(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); - } - } - } -} - -void FileSystemURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { - if (response_info_) - *info = *response_info_; -} - -int FileSystemURLRequestJob::GetResponseCode() const { - if (response_info_) - return 200; - return URLRequestJob::GetResponseCode(); -} - -void FileSystemURLRequestJob::StartAsync() { - if (!request_) - return; - DCHECK(!reader_.get()); - url_ = file_system_context_->CrackURL(request_->url()); - if (!url_.is_valid()) { - file_system_context_->AttemptAutoMountForURLRequest( - request_, - storage_domain_, - base::Bind(&FileSystemURLRequestJob::DidAttemptAutoMount, - weak_factory_.GetWeakPtr())); - return; - } - if (!file_system_context_->CanServeURLRequest(url_)) { - // In incognito mode the API is not usable and there should be no data. - NotifyFailed(net::ERR_FILE_NOT_FOUND); - return; - } - file_system_context_->operation_runner()->GetMetadata( - url_, - base::Bind(&FileSystemURLRequestJob::DidGetMetadata, - weak_factory_.GetWeakPtr())); -} - -void FileSystemURLRequestJob::DidAttemptAutoMount(base::File::Error result) { - if (result >= 0 && - file_system_context_->CrackURL(request_->url()).is_valid()) { - StartAsync(); - } else { - NotifyFailed(net::ERR_FILE_NOT_FOUND); - } -} - -void FileSystemURLRequestJob::DidGetMetadata( - base::File::Error error_code, - const base::File::Info& file_info) { - if (error_code != base::File::FILE_OK) { - NotifyFailed(error_code == base::File::FILE_ERROR_INVALID_URL ? - net::ERR_INVALID_URL : net::ERR_FILE_NOT_FOUND); - return; - } - - // We may have been orphaned... - if (!request_) - return; - - is_directory_ = file_info.is_directory; - - if (!byte_range_.ComputeBounds(file_info.size)) { - NotifyFailed(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); - return; - } - - if (is_directory_) { - NotifyHeadersComplete(); - return; - } - - remaining_bytes_ = byte_range_.last_byte_position() - - byte_range_.first_byte_position() + 1; - DCHECK_GE(remaining_bytes_, 0); - - DCHECK(!reader_.get()); - reader_ = file_system_context_->CreateFileStreamReader( - url_, byte_range_.first_byte_position(), base::Time()); - - set_expected_content_size(remaining_bytes_); - response_info_.reset(new net::HttpResponseInfo()); - response_info_->headers = CreateHttpResponseHeaders(); - NotifyHeadersComplete(); -} - -void FileSystemURLRequestJob::DidRead(int result) { - if (result > 0) - SetStatus(URLRequestStatus()); // Clear the IO_PENDING status - else if (result == 0) - NotifyDone(URLRequestStatus()); - else - NotifyFailed(result); - - remaining_bytes_ -= result; - DCHECK_GE(remaining_bytes_, 0); - - NotifyReadComplete(result); -} - -bool FileSystemURLRequestJob::IsRedirectResponse(GURL* location, - int* http_status_code) { - if (is_directory_) { - // This happens when we discovered the file is a directory, so needs a - // slash at the end of the path. - std::string new_path = request_->url().path(); - new_path.push_back('/'); - GURL::Replacements replacements; - replacements.SetPathStr(new_path); - *location = request_->url().ReplaceComponents(replacements); - *http_status_code = 301; // simulate a permanent redirect - return true; - } - - return false; -} - -void FileSystemURLRequestJob::NotifyFailed(int rv) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_url_request_job.h b/webkit/browser/fileapi/file_system_url_request_job.h index 1d29914..30174d5 100644 --- a/webkit/browser/fileapi/file_system_url_request_job.h +++ b/webkit/browser/fileapi/file_system_url_request_job.h @@ -1,85 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_H_ - -#include <string> - -#include "base/files/file.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "net/http/http_byte_range.h" -#include "net/url_request/url_request_job.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/storage_browser_export.h" - -class GURL; - -namespace base { -class FilePath; -} - -namespace storage { -class FileStreamReader; -} - -namespace storage { -class FileSystemContext; - -// A request job that handles reading filesystem: URLs -class STORAGE_EXPORT_PRIVATE FileSystemURLRequestJob - : public net::URLRequestJob { - public: - FileSystemURLRequestJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& storage_domain, - FileSystemContext* file_system_context); - - // URLRequestJob methods: - virtual void Start() OVERRIDE; - virtual void Kill() OVERRIDE; - virtual bool ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) OVERRIDE; - virtual bool IsRedirectResponse(GURL* location, - int* http_status_code) OVERRIDE; - virtual void SetExtraRequestHeaders( - const net::HttpRequestHeaders& headers) OVERRIDE; - virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE; - virtual int GetResponseCode() const OVERRIDE; - - // FilterContext methods (via URLRequestJob): - virtual bool GetMimeType(std::string* mime_type) const OVERRIDE; - - private: - class CallbackDispatcher; - - virtual ~FileSystemURLRequestJob(); - - void StartAsync(); - void DidAttemptAutoMount(base::File::Error result); - void DidGetMetadata(base::File::Error error_code, - const base::File::Info& file_info); - void DidRead(int result); - void NotifyFailed(int rv); - - const std::string storage_domain_; - FileSystemContext* file_system_context_; - scoped_ptr<storage::FileStreamReader> reader_; - FileSystemURL url_; - bool is_directory_; - scoped_ptr<net::HttpResponseInfo> response_info_; - int64 remaining_bytes_; - net::HttpByteRange byte_range_; - base::WeakPtrFactory<FileSystemURLRequestJob> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(FileSystemURLRequestJob); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_H_ +#include "storage/browser/fileapi/file_system_url_request_job.h" diff --git a/webkit/browser/fileapi/file_system_url_request_job_factory.cc b/webkit/browser/fileapi/file_system_url_request_job_factory.cc deleted file mode 100644 index 6cc3ad0..0000000 --- a/webkit/browser/fileapi/file_system_url_request_job_factory.cc +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_url_request_job_factory.h" - -#include <string> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "net/url_request/url_request.h" -#include "webkit/browser/fileapi/file_system_dir_url_request_job.h" -#include "webkit/browser/fileapi/file_system_url_request_job.h" - -namespace storage { - -namespace { - -class FileSystemProtocolHandler - : public net::URLRequestJobFactory::ProtocolHandler { - public: - FileSystemProtocolHandler(const std::string& storage_domain, - FileSystemContext* context); - virtual ~FileSystemProtocolHandler(); - - virtual net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const OVERRIDE; - - private: - const std::string storage_domain_; - - // No scoped_refptr because |file_system_context_| is owned by the - // ProfileIOData, which also owns this ProtocolHandler. - FileSystemContext* const file_system_context_; - - DISALLOW_COPY_AND_ASSIGN(FileSystemProtocolHandler); -}; - -FileSystemProtocolHandler::FileSystemProtocolHandler( - const std::string& storage_domain, - FileSystemContext* context) - : storage_domain_(storage_domain), - file_system_context_(context) { - DCHECK(file_system_context_); -} - -FileSystemProtocolHandler::~FileSystemProtocolHandler() {} - -net::URLRequestJob* FileSystemProtocolHandler::MaybeCreateJob( - net::URLRequest* request, net::NetworkDelegate* network_delegate) const { - const std::string path = request->url().path(); - - // If the path ends with a /, we know it's a directory. If the path refers - // to a directory and gets dispatched to FileSystemURLRequestJob, that class - // redirects back here, by adding a / to the URL. - if (!path.empty() && path[path.size() - 1] == '/') { - return new FileSystemDirURLRequestJob( - request, network_delegate, storage_domain_, file_system_context_); - } - return new FileSystemURLRequestJob( - request, network_delegate, storage_domain_, file_system_context_); -} - -} // anonymous namespace - -net::URLRequestJobFactory::ProtocolHandler* CreateFileSystemProtocolHandler( - const std::string& storage_domain, FileSystemContext* context) { - DCHECK(context); - return new FileSystemProtocolHandler(storage_domain, context); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_url_request_job_factory.h b/webkit/browser/fileapi/file_system_url_request_job_factory.h index df97d21..05b9aba 100644 --- a/webkit/browser/fileapi/file_system_url_request_job_factory.h +++ b/webkit/browser/fileapi/file_system_url_request_job_factory.h @@ -1,31 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_FACTORY_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_FACTORY_H_ - -#include <string> - -#include "net/url_request/url_request_job_factory.h" - -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class MessageLoopProxy; -} // namespace base - -namespace storage { - -class FileSystemContext; - -// |context|'s lifetime should exceed the lifetime of the ProtocolHandler. -// Currently, this is only used by ProfileIOData which owns |context| and the -// ProtocolHandler. -STORAGE_EXPORT net::URLRequestJobFactory::ProtocolHandler* - CreateFileSystemProtocolHandler(const std::string& storage_domain, - FileSystemContext* context); - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_FACTORY_H_ +#include "storage/browser/fileapi/file_system_url_request_job_factory.h" diff --git a/webkit/browser/fileapi/file_system_usage_cache.cc b/webkit/browser/fileapi/file_system_usage_cache.cc deleted file mode 100644 index 039ee90..0000000 --- a/webkit/browser/fileapi/file_system_usage_cache.cc +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_system_usage_cache.h" - -#include <utility> - -#include "base/bind.h" -#include "base/debug/trace_event.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/pickle.h" -#include "base/stl_util.h" -#include "webkit/browser/fileapi/timed_task_helper.h" - -namespace storage { - -namespace { -const int64 kCloseDelaySeconds = 5; -const size_t kMaxHandleCacheSize = 2; -} // namespace - -FileSystemUsageCache::FileSystemUsageCache( - base::SequencedTaskRunner* task_runner) - : task_runner_(task_runner), - weak_factory_(this) { -} - -FileSystemUsageCache::~FileSystemUsageCache() { - task_runner_ = NULL; - CloseCacheFiles(); -} - -const base::FilePath::CharType FileSystemUsageCache::kUsageFileName[] = - FILE_PATH_LITERAL(".usage"); -const char FileSystemUsageCache::kUsageFileHeader[] = "FSU5"; -const int FileSystemUsageCache::kUsageFileHeaderSize = 4; - -// Pickle::{Read,Write}Bool treat bool as int -const int FileSystemUsageCache::kUsageFileSize = - sizeof(Pickle::Header) + - FileSystemUsageCache::kUsageFileHeaderSize + - sizeof(int) + sizeof(int32) + sizeof(int64); // NOLINT - -bool FileSystemUsageCache::GetUsage(const base::FilePath& usage_file_path, - int64* usage_out) { - TRACE_EVENT0("FileSystem", "UsageCache::GetUsage"); - DCHECK(CalledOnValidThread()); - DCHECK(usage_out); - bool is_valid = true; - uint32 dirty = 0; - int64 usage = 0; - if (!Read(usage_file_path, &is_valid, &dirty, &usage)) - return false; - *usage_out = usage; - return true; -} - -bool FileSystemUsageCache::GetDirty(const base::FilePath& usage_file_path, - uint32* dirty_out) { - TRACE_EVENT0("FileSystem", "UsageCache::GetDirty"); - DCHECK(CalledOnValidThread()); - DCHECK(dirty_out); - bool is_valid = true; - uint32 dirty = 0; - int64 usage = 0; - if (!Read(usage_file_path, &is_valid, &dirty, &usage)) - return false; - *dirty_out = dirty; - return true; -} - -bool FileSystemUsageCache::IncrementDirty( - const base::FilePath& usage_file_path) { - TRACE_EVENT0("FileSystem", "UsageCache::IncrementDirty"); - DCHECK(CalledOnValidThread()); - bool is_valid = true; - uint32 dirty = 0; - int64 usage = 0; - bool new_handle = !HasCacheFileHandle(usage_file_path); - if (!Read(usage_file_path, &is_valid, &dirty, &usage)) - return false; - - bool success = Write(usage_file_path, is_valid, dirty + 1, usage); - if (success && dirty == 0 && new_handle) - FlushFile(usage_file_path); - return success; -} - -bool FileSystemUsageCache::DecrementDirty( - const base::FilePath& usage_file_path) { - TRACE_EVENT0("FileSystem", "UsageCache::DecrementDirty"); - DCHECK(CalledOnValidThread()); - bool is_valid = true; - uint32 dirty = 0; - int64 usage = 0; - if (!Read(usage_file_path, &is_valid, &dirty, &usage) || dirty <= 0) - return false; - - if (dirty <= 0) - return false; - - return Write(usage_file_path, is_valid, dirty - 1, usage); -} - -bool FileSystemUsageCache::Invalidate(const base::FilePath& usage_file_path) { - TRACE_EVENT0("FileSystem", "UsageCache::Invalidate"); - DCHECK(CalledOnValidThread()); - bool is_valid = true; - uint32 dirty = 0; - int64 usage = 0; - if (!Read(usage_file_path, &is_valid, &dirty, &usage)) - return false; - - return Write(usage_file_path, false, dirty, usage); -} - -bool FileSystemUsageCache::IsValid(const base::FilePath& usage_file_path) { - TRACE_EVENT0("FileSystem", "UsageCache::IsValid"); - DCHECK(CalledOnValidThread()); - bool is_valid = true; - uint32 dirty = 0; - int64 usage = 0; - if (!Read(usage_file_path, &is_valid, &dirty, &usage)) - return false; - return is_valid; -} - -bool FileSystemUsageCache::AtomicUpdateUsageByDelta( - const base::FilePath& usage_file_path, int64 delta) { - TRACE_EVENT0("FileSystem", "UsageCache::AtomicUpdateUsageByDelta"); - DCHECK(CalledOnValidThread()); - bool is_valid = true; - uint32 dirty = 0; - int64 usage = 0;; - if (!Read(usage_file_path, &is_valid, &dirty, &usage)) - return false; - return Write(usage_file_path, is_valid, dirty, usage + delta); -} - -bool FileSystemUsageCache::UpdateUsage(const base::FilePath& usage_file_path, - int64 fs_usage) { - TRACE_EVENT0("FileSystem", "UsageCache::UpdateUsage"); - DCHECK(CalledOnValidThread()); - return Write(usage_file_path, true, 0, fs_usage); -} - -bool FileSystemUsageCache::Exists(const base::FilePath& usage_file_path) { - TRACE_EVENT0("FileSystem", "UsageCache::Exists"); - DCHECK(CalledOnValidThread()); - return base::PathExists(usage_file_path); -} - -bool FileSystemUsageCache::Delete(const base::FilePath& usage_file_path) { - TRACE_EVENT0("FileSystem", "UsageCache::Delete"); - DCHECK(CalledOnValidThread()); - CloseCacheFiles(); - return base::DeleteFile(usage_file_path, true); -} - -void FileSystemUsageCache::CloseCacheFiles() { - TRACE_EVENT0("FileSystem", "UsageCache::CloseCacheFiles"); - DCHECK(CalledOnValidThread()); - STLDeleteValues(&cache_files_); - timer_.reset(); -} - -bool FileSystemUsageCache::Read(const base::FilePath& usage_file_path, - bool* is_valid, - uint32* dirty_out, - int64* usage_out) { - TRACE_EVENT0("FileSystem", "UsageCache::Read"); - DCHECK(CalledOnValidThread()); - DCHECK(is_valid); - DCHECK(dirty_out); - DCHECK(usage_out); - char buffer[kUsageFileSize]; - const char *header; - if (usage_file_path.empty() || - !ReadBytes(usage_file_path, buffer, kUsageFileSize)) - return false; - Pickle read_pickle(buffer, kUsageFileSize); - PickleIterator iter(read_pickle); - uint32 dirty = 0; - int64 usage = 0; - - if (!read_pickle.ReadBytes(&iter, &header, kUsageFileHeaderSize) || - !read_pickle.ReadBool(&iter, is_valid) || - !read_pickle.ReadUInt32(&iter, &dirty) || - !read_pickle.ReadInt64(&iter, &usage)) - return false; - - if (header[0] != kUsageFileHeader[0] || - header[1] != kUsageFileHeader[1] || - header[2] != kUsageFileHeader[2] || - header[3] != kUsageFileHeader[3]) - return false; - - *dirty_out = dirty; - *usage_out = usage; - return true; -} - -bool FileSystemUsageCache::Write(const base::FilePath& usage_file_path, - bool is_valid, - int32 dirty, - int64 usage) { - TRACE_EVENT0("FileSystem", "UsageCache::Write"); - DCHECK(CalledOnValidThread()); - Pickle write_pickle; - write_pickle.WriteBytes(kUsageFileHeader, kUsageFileHeaderSize); - write_pickle.WriteBool(is_valid); - write_pickle.WriteUInt32(dirty); - write_pickle.WriteInt64(usage); - - if (!WriteBytes(usage_file_path, - static_cast<const char*>(write_pickle.data()), - write_pickle.size())) { - Delete(usage_file_path); - return false; - } - return true; -} - -base::File* FileSystemUsageCache::GetFile(const base::FilePath& file_path) { - DCHECK(CalledOnValidThread()); - if (cache_files_.size() >= kMaxHandleCacheSize) - CloseCacheFiles(); - ScheduleCloseTimer(); - - base::File* new_file = NULL; - std::pair<CacheFiles::iterator, bool> inserted = - cache_files_.insert(std::make_pair(file_path, new_file)); - if (!inserted.second) - return inserted.first->second; - - new_file = new base::File(file_path, - base::File::FLAG_OPEN_ALWAYS | - base::File::FLAG_READ | - base::File::FLAG_WRITE); - if (!new_file->IsValid()) { - cache_files_.erase(inserted.first); - delete new_file; - return NULL; - } - - inserted.first->second = new_file; - return new_file; -} - -bool FileSystemUsageCache::ReadBytes(const base::FilePath& file_path, - char* buffer, - int64 buffer_size) { - DCHECK(CalledOnValidThread()); - base::File* file = GetFile(file_path); - if (!file) - return false; - return file->Read(0, buffer, buffer_size) == buffer_size; -} - -bool FileSystemUsageCache::WriteBytes(const base::FilePath& file_path, - const char* buffer, - int64 buffer_size) { - DCHECK(CalledOnValidThread()); - base::File* file = GetFile(file_path); - if (!file) - return false; - return file->Write(0, buffer, buffer_size) == buffer_size; -} - -bool FileSystemUsageCache::FlushFile(const base::FilePath& file_path) { - TRACE_EVENT0("FileSystem", "UsageCache::FlushFile"); - DCHECK(CalledOnValidThread()); - base::File* file = GetFile(file_path); - if (!file) - return false; - return file->Flush(); -} - -void FileSystemUsageCache::ScheduleCloseTimer() { - DCHECK(CalledOnValidThread()); - if (!timer_) - timer_.reset(new TimedTaskHelper(task_runner_.get())); - - if (timer_->IsRunning()) { - timer_->Reset(); - return; - } - - timer_->Start(FROM_HERE, - base::TimeDelta::FromSeconds(kCloseDelaySeconds), - base::Bind(&FileSystemUsageCache::CloseCacheFiles, - weak_factory_.GetWeakPtr())); -} - -bool FileSystemUsageCache::CalledOnValidThread() { - return !task_runner_.get() || task_runner_->RunsTasksOnCurrentThread(); -} - -bool FileSystemUsageCache::HasCacheFileHandle(const base::FilePath& file_path) { - DCHECK(CalledOnValidThread()); - DCHECK_LE(cache_files_.size(), kMaxHandleCacheSize); - return ContainsKey(cache_files_, file_path); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_system_usage_cache.h b/webkit/browser/fileapi/file_system_usage_cache.h index 7cea495..89c8c43 100644 --- a/webkit/browser/fileapi/file_system_usage_cache.h +++ b/webkit/browser/fileapi/file_system_usage_cache.h @@ -1,105 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_SYSTEM_USAGE_CACHE_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_USAGE_CACHE_H_ - -#include <map> - -#include "base/basictypes.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" -#include "webkit/browser/storage_browser_export.h" - -namespace storage { - -class TimedTaskHelper; - -class STORAGE_EXPORT_PRIVATE FileSystemUsageCache { - public: - explicit FileSystemUsageCache(base::SequencedTaskRunner* task_runner); - ~FileSystemUsageCache(); - - // Gets the size described in the .usage file even if dirty > 0 or - // is_valid == false. Returns true if the .usage file is available. - bool GetUsage(const base::FilePath& usage_file_path, int64* usage); - - // Gets the dirty count in the .usage file. - // Returns true if the .usage file is available. - bool GetDirty(const base::FilePath& usage_file_path, uint32* dirty); - - // Increments or decrements the "dirty" entry in the .usage file. - // Returns false if no .usage is available. - bool IncrementDirty(const base::FilePath& usage_file_path); - bool DecrementDirty(const base::FilePath& usage_file_path); - - // Notifies quota system that it needs to recalculate the usage cache of the - // origin. Returns false if no .usage is available. - bool Invalidate(const base::FilePath& usage_file_path); - bool IsValid(const base::FilePath& usage_file_path); - - // Updates the size described in the .usage file. - bool UpdateUsage(const base::FilePath& usage_file_path, int64 fs_usage); - - // Updates the size described in the .usage file by delta with keeping dirty - // even if dirty > 0. - bool AtomicUpdateUsageByDelta(const base::FilePath& usage_file_path, - int64 delta); - - bool Exists(const base::FilePath& usage_file_path); - bool Delete(const base::FilePath& usage_file_path); - - void CloseCacheFiles(); - - static const base::FilePath::CharType kUsageFileName[]; - static const char kUsageFileHeader[]; - static const int kUsageFileSize; - static const int kUsageFileHeaderSize; - - private: - typedef std::map<base::FilePath, base::File*> CacheFiles; - - // Read the size, validity and the "dirty" entry described in the .usage file. - // Returns less than zero if no .usage file is available. - bool Read(const base::FilePath& usage_file_path, - bool* is_valid, - uint32* dirty, - int64* usage); - - bool Write(const base::FilePath& usage_file_path, - bool is_valid, - int32 dirty, - int64 fs_usage); - - base::File* GetFile(const base::FilePath& file_path); - - bool ReadBytes(const base::FilePath& file_path, - char* buffer, - int64 buffer_size); - bool WriteBytes(const base::FilePath& file_path, - const char* buffer, - int64 buffer_size); - bool FlushFile(const base::FilePath& file_path); - void ScheduleCloseTimer(); - - bool HasCacheFileHandle(const base::FilePath& file_path); - - bool CalledOnValidThread(); - - scoped_ptr<TimedTaskHelper> timer_; - CacheFiles cache_files_; - - scoped_refptr<base::SequencedTaskRunner> task_runner_; - - base::WeakPtrFactory<FileSystemUsageCache> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(FileSystemUsageCache); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_USAGE_CACHE_H_ +#include "storage/browser/fileapi/file_system_usage_cache.h" diff --git a/webkit/browser/fileapi/file_writer_delegate.cc b/webkit/browser/fileapi/file_writer_delegate.cc deleted file mode 100644 index 976debe..0000000 --- a/webkit/browser/fileapi/file_writer_delegate.cc +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/file_writer_delegate.h" - -#include "base/bind.h" -#include "base/callback.h" -#include "base/files/file_util_proxy.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/sequenced_task_runner.h" -#include "base/threading/thread_restrictions.h" -#include "net/base/net_errors.h" -#include "webkit/browser/fileapi/file_stream_writer.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace storage { - -static const int kReadBufSize = 32768; - -FileWriterDelegate::FileWriterDelegate( - scoped_ptr<FileStreamWriter> file_stream_writer, - FlushPolicy flush_policy) - : file_stream_writer_(file_stream_writer.Pass()), - writing_started_(false), - flush_policy_(flush_policy), - bytes_written_backlog_(0), - bytes_written_(0), - bytes_read_(0), - io_buffer_(new net::IOBufferWithSize(kReadBufSize)), - weak_factory_(this) { -} - -FileWriterDelegate::~FileWriterDelegate() { -} - -void FileWriterDelegate::Start(scoped_ptr<net::URLRequest> request, - const DelegateWriteCallback& write_callback) { - write_callback_ = write_callback; - request_ = request.Pass(); - request_->Start(); -} - -void FileWriterDelegate::Cancel() { - if (request_) { - // This halts any callbacks on this delegate. - request_->set_delegate(NULL); - request_->Cancel(); - } - - const int status = file_stream_writer_->Cancel( - base::Bind(&FileWriterDelegate::OnWriteCancelled, - weak_factory_.GetWeakPtr())); - // Return true to finish immediately if we have no pending writes. - // Otherwise we'll do the final cleanup in the Cancel callback. - if (status != net::ERR_IO_PENDING) { - write_callback_.Run(base::File::FILE_ERROR_ABORT, 0, - GetCompletionStatusOnError()); - } -} - -void FileWriterDelegate::OnReceivedRedirect( - net::URLRequest* request, - const net::RedirectInfo& redirect_info, - bool* defer_redirect) { - NOTREACHED(); - OnError(base::File::FILE_ERROR_SECURITY); -} - -void FileWriterDelegate::OnAuthRequired(net::URLRequest* request, - net::AuthChallengeInfo* auth_info) { - NOTREACHED(); - OnError(base::File::FILE_ERROR_SECURITY); -} - -void FileWriterDelegate::OnCertificateRequested( - net::URLRequest* request, - net::SSLCertRequestInfo* cert_request_info) { - NOTREACHED(); - OnError(base::File::FILE_ERROR_SECURITY); -} - -void FileWriterDelegate::OnSSLCertificateError(net::URLRequest* request, - const net::SSLInfo& ssl_info, - bool fatal) { - NOTREACHED(); - OnError(base::File::FILE_ERROR_SECURITY); -} - -void FileWriterDelegate::OnResponseStarted(net::URLRequest* request) { - DCHECK_EQ(request_.get(), request); - if (!request->status().is_success() || request->GetResponseCode() != 200) { - OnError(base::File::FILE_ERROR_FAILED); - return; - } - Read(); -} - -void FileWriterDelegate::OnReadCompleted(net::URLRequest* request, - int bytes_read) { - DCHECK_EQ(request_.get(), request); - if (!request->status().is_success()) { - OnError(base::File::FILE_ERROR_FAILED); - return; - } - OnDataReceived(bytes_read); -} - -void FileWriterDelegate::Read() { - bytes_written_ = 0; - bytes_read_ = 0; - if (request_->Read(io_buffer_.get(), io_buffer_->size(), &bytes_read_)) { - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&FileWriterDelegate::OnDataReceived, - weak_factory_.GetWeakPtr(), bytes_read_)); - } else if (!request_->status().is_io_pending()) { - OnError(base::File::FILE_ERROR_FAILED); - } -} - -void FileWriterDelegate::OnDataReceived(int bytes_read) { - bytes_read_ = bytes_read; - if (!bytes_read_) { // We're done. - OnProgress(0, true); - } else { - // This could easily be optimized to rotate between a pool of buffers, so - // that we could read and write at the same time. It's not yet clear that - // it's necessary. - cursor_ = new net::DrainableIOBuffer(io_buffer_.get(), bytes_read_); - Write(); - } -} - -void FileWriterDelegate::Write() { - writing_started_ = true; - int64 bytes_to_write = bytes_read_ - bytes_written_; - int write_response = - file_stream_writer_->Write(cursor_.get(), - static_cast<int>(bytes_to_write), - base::Bind(&FileWriterDelegate::OnDataWritten, - weak_factory_.GetWeakPtr())); - if (write_response > 0) { - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&FileWriterDelegate::OnDataWritten, - weak_factory_.GetWeakPtr(), write_response)); - } else if (net::ERR_IO_PENDING != write_response) { - OnError(NetErrorToFileError(write_response)); - } -} - -void FileWriterDelegate::OnDataWritten(int write_response) { - if (write_response > 0) { - OnProgress(write_response, false); - cursor_->DidConsume(write_response); - bytes_written_ += write_response; - if (bytes_written_ == bytes_read_) - Read(); - else - Write(); - } else { - OnError(NetErrorToFileError(write_response)); - } -} - -FileWriterDelegate::WriteProgressStatus -FileWriterDelegate::GetCompletionStatusOnError() const { - return writing_started_ ? ERROR_WRITE_STARTED : ERROR_WRITE_NOT_STARTED; -} - -void FileWriterDelegate::OnError(base::File::Error error) { - if (request_) { - request_->set_delegate(NULL); - request_->Cancel(); - } - - if (writing_started_) - MaybeFlushForCompletion(error, 0, ERROR_WRITE_STARTED); - else - write_callback_.Run(error, 0, ERROR_WRITE_NOT_STARTED); -} - -void FileWriterDelegate::OnProgress(int bytes_written, bool done) { - DCHECK(bytes_written + bytes_written_backlog_ >= bytes_written_backlog_); - static const int kMinProgressDelayMS = 200; - base::Time currentTime = base::Time::Now(); - if (done || last_progress_event_time_.is_null() || - (currentTime - last_progress_event_time_).InMilliseconds() > - kMinProgressDelayMS) { - bytes_written += bytes_written_backlog_; - last_progress_event_time_ = currentTime; - bytes_written_backlog_ = 0; - - if (done) { - MaybeFlushForCompletion(base::File::FILE_OK, bytes_written, - SUCCESS_COMPLETED); - } else { - write_callback_.Run(base::File::FILE_OK, bytes_written, - SUCCESS_IO_PENDING); - } - return; - } - bytes_written_backlog_ += bytes_written; -} - -void FileWriterDelegate::OnWriteCancelled(int status) { - write_callback_.Run(base::File::FILE_ERROR_ABORT, 0, - GetCompletionStatusOnError()); -} - -void FileWriterDelegate::MaybeFlushForCompletion( - base::File::Error error, - int bytes_written, - WriteProgressStatus progress_status) { - if (flush_policy_ == NO_FLUSH_ON_COMPLETION) { - write_callback_.Run(error, bytes_written, progress_status); - return; - } - DCHECK_EQ(FLUSH_ON_COMPLETION, flush_policy_); - - int flush_error = file_stream_writer_->Flush( - base::Bind(&FileWriterDelegate::OnFlushed, weak_factory_.GetWeakPtr(), - error, bytes_written, progress_status)); - if (flush_error != net::ERR_IO_PENDING) - OnFlushed(error, bytes_written, progress_status, flush_error); -} - -void FileWriterDelegate::OnFlushed(base::File::Error error, - int bytes_written, - WriteProgressStatus progress_status, - int flush_error) { - if (error == base::File::FILE_OK && flush_error != net::OK) { - // If the Flush introduced an error, overwrite the status. - // Otherwise, keep the original error status. - error = NetErrorToFileError(flush_error); - progress_status = GetCompletionStatusOnError(); - } - write_callback_.Run(error, bytes_written, progress_status); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/file_writer_delegate.h b/webkit/browser/fileapi/file_writer_delegate.h index f37dcf5..55fb98f 100644 --- a/webkit/browser/fileapi/file_writer_delegate.h +++ b/webkit/browser/fileapi/file_writer_delegate.h @@ -1,110 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_FILE_WRITER_DELEGATE_H_ -#define WEBKIT_BROWSER_FILEAPI_FILE_WRITER_DELEGATE_H_ - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/time/time.h" -#include "net/base/file_stream.h" -#include "net/base/io_buffer.h" -#include "net/url_request/url_request.h" -#include "webkit/browser/storage_browser_export.h" - -namespace storage { - -class FileStreamWriter; - -class STORAGE_EXPORT_PRIVATE FileWriterDelegate - : public net::URLRequest::Delegate { - public: - enum FlushPolicy { - FLUSH_ON_COMPLETION, - NO_FLUSH_ON_COMPLETION, - }; - - enum WriteProgressStatus { - SUCCESS_IO_PENDING, - SUCCESS_COMPLETED, - ERROR_WRITE_STARTED, - ERROR_WRITE_NOT_STARTED, - }; - - typedef base::Callback<void(base::File::Error result, - int64 bytes, - WriteProgressStatus write_status)> - DelegateWriteCallback; - - FileWriterDelegate(scoped_ptr<FileStreamWriter> file_writer, - FlushPolicy flush_policy); - virtual ~FileWriterDelegate(); - - void Start(scoped_ptr<net::URLRequest> request, - const DelegateWriteCallback& write_callback); - - // Cancels the current write operation. This will synchronously or - // asynchronously call the given write callback (which may result in - // deleting this). - void Cancel(); - - virtual void OnReceivedRedirect(net::URLRequest* request, - const net::RedirectInfo& redirect_info, - bool* defer_redirect) OVERRIDE; - virtual void OnAuthRequired(net::URLRequest* request, - net::AuthChallengeInfo* auth_info) OVERRIDE; - virtual void OnCertificateRequested( - net::URLRequest* request, - net::SSLCertRequestInfo* cert_request_info) OVERRIDE; - virtual void OnSSLCertificateError(net::URLRequest* request, - const net::SSLInfo& ssl_info, - bool fatal) OVERRIDE; - virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE; - virtual void OnReadCompleted(net::URLRequest* request, - int bytes_read) OVERRIDE; - - private: - void OnGetFileInfoAndStartRequest( - scoped_ptr<net::URLRequest> request, - base::File::Error error, - const base::File::Info& file_info); - void Read(); - void OnDataReceived(int bytes_read); - void Write(); - void OnDataWritten(int write_response); - void OnError(base::File::Error error); - void OnProgress(int bytes_read, bool done); - void OnWriteCancelled(int status); - void MaybeFlushForCompletion(base::File::Error error, - int bytes_written, - WriteProgressStatus progress_status); - void OnFlushed(base::File::Error error, - int bytes_written, - WriteProgressStatus progress_status, - int flush_error); - - WriteProgressStatus GetCompletionStatusOnError() const; - - DelegateWriteCallback write_callback_; - scoped_ptr<FileStreamWriter> file_stream_writer_; - base::Time last_progress_event_time_; - bool writing_started_; - FlushPolicy flush_policy_; - int bytes_written_backlog_; - int bytes_written_; - int bytes_read_; - scoped_refptr<net::IOBufferWithSize> io_buffer_; - scoped_refptr<net::DrainableIOBuffer> cursor_; - scoped_ptr<net::URLRequest> request_; - - base::WeakPtrFactory<FileWriterDelegate> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(FileWriterDelegate); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_FILE_WRITER_DELEGATE_H_ +#include "storage/browser/fileapi/file_writer_delegate.h" diff --git a/webkit/browser/fileapi/isolated_context.cc b/webkit/browser/fileapi/isolated_context.cc deleted file mode 100644 index 147e588..0000000 --- a/webkit/browser/fileapi/isolated_context.cc +++ /dev/null @@ -1,484 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/isolated_context.h" - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/rand_util.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "webkit/browser/fileapi/file_system_url.h" - -namespace storage { - -namespace { - -base::FilePath::StringType GetRegisterNameForPath(const base::FilePath& path) { - // If it's not a root path simply return a base name. - if (path.DirName() != path) - return path.BaseName().value(); - -#if defined(FILE_PATH_USES_DRIVE_LETTERS) - base::FilePath::StringType name; - for (size_t i = 0; - i < path.value().size() && !base::FilePath::IsSeparator(path.value()[i]); - ++i) { - if (path.value()[i] == L':') { - name.append(L"_drive"); - break; - } - name.append(1, path.value()[i]); - } - return name; -#else - return FILE_PATH_LITERAL("<root>"); -#endif -} - -bool IsSinglePathIsolatedFileSystem(FileSystemType type) { - DCHECK_NE(kFileSystemTypeUnknown, type); - // As of writing dragged file system is the only filesystem which could have - // multiple top-level paths. - return type != kFileSystemTypeDragged; -} - -static base::LazyInstance<IsolatedContext>::Leaky g_isolated_context = - LAZY_INSTANCE_INITIALIZER; - -} // namespace - -IsolatedContext::FileInfoSet::FileInfoSet() {} -IsolatedContext::FileInfoSet::~FileInfoSet() {} - -bool IsolatedContext::FileInfoSet::AddPath( - const base::FilePath& path, std::string* registered_name) { - // The given path should not contain any '..' and should be absolute. - if (path.ReferencesParent() || !path.IsAbsolute()) - return false; - base::FilePath::StringType name = GetRegisterNameForPath(path); - std::string utf8name = base::FilePath(name).AsUTF8Unsafe(); - base::FilePath normalized_path = path.NormalizePathSeparators(); - bool inserted = - fileset_.insert(MountPointInfo(utf8name, normalized_path)).second; - if (!inserted) { - int suffix = 1; - std::string basepart = - base::FilePath(name).RemoveExtension().AsUTF8Unsafe(); - std::string ext = - base::FilePath(base::FilePath(name).Extension()).AsUTF8Unsafe(); - while (!inserted) { - utf8name = base::StringPrintf("%s (%d)", basepart.c_str(), suffix++); - if (!ext.empty()) - utf8name.append(ext); - inserted = - fileset_.insert(MountPointInfo(utf8name, normalized_path)).second; - } - } - if (registered_name) - *registered_name = utf8name; - return true; -} - -bool IsolatedContext::FileInfoSet::AddPathWithName( - const base::FilePath& path, const std::string& name) { - // The given path should not contain any '..' and should be absolute. - if (path.ReferencesParent() || !path.IsAbsolute()) - return false; - return fileset_.insert( - MountPointInfo(name, path.NormalizePathSeparators())).second; -} - -//-------------------------------------------------------------------------- - -class IsolatedContext::Instance { - public: - enum PathType { - PLATFORM_PATH, - VIRTUAL_PATH - }; - - // For a single-path isolated file system, which could be registered by - // IsolatedContext::RegisterFileSystemForPath() or - // IsolatedContext::RegisterFileSystemForVirtualPath(). - // Most of isolated file system contexts should be of this type. - Instance(FileSystemType type, - const std::string& filesystem_id, - const MountPointInfo& file_info, - PathType path_type); - - // For a multi-paths isolated file system. As of writing only file system - // type which could have multi-paths is Dragged file system, and - // could be registered by IsolatedContext::RegisterDraggedFileSystem(). - Instance(FileSystemType type, const std::set<MountPointInfo>& files); - - ~Instance(); - - FileSystemType type() const { return type_; } - const std::string& filesystem_id() const { return filesystem_id_; } - const MountPointInfo& file_info() const { return file_info_; } - const std::set<MountPointInfo>& files() const { return files_; } - int ref_counts() const { return ref_counts_; } - - void AddRef() { ++ref_counts_; } - void RemoveRef() { --ref_counts_; } - - bool ResolvePathForName(const std::string& name, base::FilePath* path) const; - - // Returns true if the instance is a single-path instance. - bool IsSinglePathInstance() const; - - private: - const FileSystemType type_; - const std::string filesystem_id_; - - // For single-path instance. - const MountPointInfo file_info_; - const PathType path_type_; - - // For multiple-path instance (e.g. dragged file system). - const std::set<MountPointInfo> files_; - - // Reference counts. Note that an isolated filesystem is created with ref==0 - // and will get deleted when the ref count reaches <=0. - int ref_counts_; - - DISALLOW_COPY_AND_ASSIGN(Instance); -}; - -IsolatedContext::Instance::Instance(FileSystemType type, - const std::string& filesystem_id, - const MountPointInfo& file_info, - Instance::PathType path_type) - : type_(type), - filesystem_id_(filesystem_id), - file_info_(file_info), - path_type_(path_type), - ref_counts_(0) { - DCHECK(IsSinglePathIsolatedFileSystem(type_)); -} - -IsolatedContext::Instance::Instance(FileSystemType type, - const std::set<MountPointInfo>& files) - : type_(type), - path_type_(PLATFORM_PATH), - files_(files), - ref_counts_(0) { - DCHECK(!IsSinglePathIsolatedFileSystem(type_)); -} - -IsolatedContext::Instance::~Instance() {} - -bool IsolatedContext::Instance::ResolvePathForName(const std::string& name, - base::FilePath* path) const { - if (IsSinglePathIsolatedFileSystem(type_)) { - switch (path_type_) { - case PLATFORM_PATH: - *path = file_info_.path; - break; - case VIRTUAL_PATH: - *path = base::FilePath(); - break; - default: - NOTREACHED(); - } - - return file_info_.name == name; - } - std::set<MountPointInfo>::const_iterator found = files_.find( - MountPointInfo(name, base::FilePath())); - if (found == files_.end()) - return false; - *path = found->path; - return true; -} - -bool IsolatedContext::Instance::IsSinglePathInstance() const { - return IsSinglePathIsolatedFileSystem(type_); -} - -//-------------------------------------------------------------------------- - -// static -IsolatedContext* IsolatedContext::GetInstance() { - return g_isolated_context.Pointer(); -} - -// static -bool IsolatedContext::IsIsolatedType(FileSystemType type) { - return type == kFileSystemTypeIsolated || type == kFileSystemTypeExternal; -} - -std::string IsolatedContext::RegisterDraggedFileSystem( - const FileInfoSet& files) { - base::AutoLock locker(lock_); - std::string filesystem_id = GetNewFileSystemId(); - instance_map_[filesystem_id] = new Instance( - kFileSystemTypeDragged, files.fileset()); - return filesystem_id; -} - -std::string IsolatedContext::RegisterFileSystemForPath( - FileSystemType type, - const std::string& filesystem_id, - const base::FilePath& path_in, - std::string* register_name) { - base::FilePath path(path_in.NormalizePathSeparators()); - if (path.ReferencesParent() || !path.IsAbsolute()) - return std::string(); - std::string name; - if (register_name && !register_name->empty()) { - name = *register_name; - } else { - name = base::FilePath(GetRegisterNameForPath(path)).AsUTF8Unsafe(); - if (register_name) - register_name->assign(name); - } - - base::AutoLock locker(lock_); - std::string new_id = GetNewFileSystemId(); - instance_map_[new_id] = new Instance(type, filesystem_id, - MountPointInfo(name, path), - Instance::PLATFORM_PATH); - path_to_id_map_[path].insert(new_id); - return new_id; -} - -std::string IsolatedContext::RegisterFileSystemForVirtualPath( - FileSystemType type, - const std::string& register_name, - const base::FilePath& cracked_path_prefix) { - base::AutoLock locker(lock_); - base::FilePath path(cracked_path_prefix.NormalizePathSeparators()); - if (path.ReferencesParent()) - return std::string(); - std::string filesystem_id = GetNewFileSystemId(); - instance_map_[filesystem_id] = new Instance( - type, - std::string(), // filesystem_id - MountPointInfo(register_name, cracked_path_prefix), - Instance::VIRTUAL_PATH); - path_to_id_map_[path].insert(filesystem_id); - return filesystem_id; -} - -bool IsolatedContext::HandlesFileSystemMountType(FileSystemType type) const { - return type == kFileSystemTypeIsolated; -} - -bool IsolatedContext::RevokeFileSystem(const std::string& filesystem_id) { - base::AutoLock locker(lock_); - return UnregisterFileSystem(filesystem_id); -} - -bool IsolatedContext::GetRegisteredPath( - const std::string& filesystem_id, base::FilePath* path) const { - DCHECK(path); - base::AutoLock locker(lock_); - IDToInstance::const_iterator found = instance_map_.find(filesystem_id); - if (found == instance_map_.end() || !found->second->IsSinglePathInstance()) - return false; - *path = found->second->file_info().path; - return true; -} - -bool IsolatedContext::CrackVirtualPath( - const base::FilePath& virtual_path, - std::string* id_or_name, - FileSystemType* type, - std::string* cracked_id, - base::FilePath* path, - FileSystemMountOption* mount_option) const { - DCHECK(id_or_name); - DCHECK(path); - - // This should not contain any '..' references. - if (virtual_path.ReferencesParent()) - return false; - - // Set the default mount option. - *mount_option = FileSystemMountOption(); - - // The virtual_path should comprise <id_or_name> and <relative_path> parts. - std::vector<base::FilePath::StringType> components; - virtual_path.GetComponents(&components); - if (components.size() < 1) - return false; - std::vector<base::FilePath::StringType>::iterator component_iter = - components.begin(); - std::string fsid = base::FilePath(*component_iter++).MaybeAsASCII(); - if (fsid.empty()) - return false; - - base::FilePath cracked_path; - { - base::AutoLock locker(lock_); - IDToInstance::const_iterator found_instance = instance_map_.find(fsid); - if (found_instance == instance_map_.end()) - return false; - *id_or_name = fsid; - const Instance* instance = found_instance->second; - if (type) - *type = instance->type(); - if (cracked_id) - *cracked_id = instance->filesystem_id(); - - if (component_iter == components.end()) { - // The virtual root case. - path->clear(); - return true; - } - - // *component_iter should be a name of the registered path. - std::string name = base::FilePath(*component_iter++).AsUTF8Unsafe(); - if (!instance->ResolvePathForName(name, &cracked_path)) - return false; - } - - for (; component_iter != components.end(); ++component_iter) - cracked_path = cracked_path.Append(*component_iter); - *path = cracked_path; - return true; -} - -FileSystemURL IsolatedContext::CrackURL(const GURL& url) const { - FileSystemURL filesystem_url = FileSystemURL(url); - if (!filesystem_url.is_valid()) - return FileSystemURL(); - return CrackFileSystemURL(filesystem_url); -} - -FileSystemURL IsolatedContext::CreateCrackedFileSystemURL( - const GURL& origin, - FileSystemType type, - const base::FilePath& path) const { - return CrackFileSystemURL(FileSystemURL(origin, type, path)); -} - -void IsolatedContext::RevokeFileSystemByPath(const base::FilePath& path_in) { - base::AutoLock locker(lock_); - base::FilePath path(path_in.NormalizePathSeparators()); - PathToID::iterator ids_iter = path_to_id_map_.find(path); - if (ids_iter == path_to_id_map_.end()) - return; - std::set<std::string>& ids = ids_iter->second; - for (std::set<std::string>::iterator iter = ids.begin(); - iter != ids.end(); ++iter) { - IDToInstance::iterator found = instance_map_.find(*iter); - if (found != instance_map_.end()) { - delete found->second; - instance_map_.erase(found); - } - } - path_to_id_map_.erase(ids_iter); -} - -void IsolatedContext::AddReference(const std::string& filesystem_id) { - base::AutoLock locker(lock_); - DCHECK(instance_map_.find(filesystem_id) != instance_map_.end()); - instance_map_[filesystem_id]->AddRef(); -} - -void IsolatedContext::RemoveReference(const std::string& filesystem_id) { - base::AutoLock locker(lock_); - // This could get called for non-existent filesystem if it has been - // already deleted by RevokeFileSystemByPath. - IDToInstance::iterator found = instance_map_.find(filesystem_id); - if (found == instance_map_.end()) - return; - Instance* instance = found->second; - DCHECK_GT(instance->ref_counts(), 0); - instance->RemoveRef(); - if (instance->ref_counts() == 0) { - bool deleted = UnregisterFileSystem(filesystem_id); - DCHECK(deleted); - } -} - -bool IsolatedContext::GetDraggedFileInfo( - const std::string& filesystem_id, - std::vector<MountPointInfo>* files) const { - DCHECK(files); - base::AutoLock locker(lock_); - IDToInstance::const_iterator found = instance_map_.find(filesystem_id); - if (found == instance_map_.end() || - found->second->type() != kFileSystemTypeDragged) - return false; - files->assign(found->second->files().begin(), - found->second->files().end()); - return true; -} - -base::FilePath IsolatedContext::CreateVirtualRootPath( - const std::string& filesystem_id) const { - return base::FilePath().AppendASCII(filesystem_id); -} - -IsolatedContext::IsolatedContext() { -} - -IsolatedContext::~IsolatedContext() { - STLDeleteContainerPairSecondPointers(instance_map_.begin(), - instance_map_.end()); -} - -FileSystemURL IsolatedContext::CrackFileSystemURL( - const FileSystemURL& url) const { - if (!HandlesFileSystemMountType(url.type())) - return FileSystemURL(); - - std::string mount_name; - std::string cracked_mount_name; - FileSystemType cracked_type; - base::FilePath cracked_path; - FileSystemMountOption cracked_mount_option; - if (!CrackVirtualPath(url.path(), &mount_name, &cracked_type, - &cracked_mount_name, &cracked_path, - &cracked_mount_option)) { - return FileSystemURL(); - } - - return FileSystemURL( - url.origin(), url.mount_type(), url.virtual_path(), - !url.filesystem_id().empty() ? url.filesystem_id() : mount_name, - cracked_type, cracked_path, - cracked_mount_name.empty() ? mount_name : cracked_mount_name, - cracked_mount_option); -} - -bool IsolatedContext::UnregisterFileSystem(const std::string& filesystem_id) { - lock_.AssertAcquired(); - IDToInstance::iterator found = instance_map_.find(filesystem_id); - if (found == instance_map_.end()) - return false; - Instance* instance = found->second; - if (instance->IsSinglePathInstance()) { - PathToID::iterator ids_iter = path_to_id_map_.find( - instance->file_info().path); - DCHECK(ids_iter != path_to_id_map_.end()); - ids_iter->second.erase(filesystem_id); - if (ids_iter->second.empty()) - path_to_id_map_.erase(ids_iter); - } - delete found->second; - instance_map_.erase(found); - return true; -} - -std::string IsolatedContext::GetNewFileSystemId() const { - // Returns an arbitrary random string which must be unique in the map. - lock_.AssertAcquired(); - uint32 random_data[4]; - std::string id; - do { - base::RandBytes(random_data, sizeof(random_data)); - id = base::HexEncode(random_data, sizeof(random_data)); - } while (instance_map_.find(id) != instance_map_.end()); - return id; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/isolated_context.h b/webkit/browser/fileapi/isolated_context.h index 14a80ad..15917f4 100644 --- a/webkit/browser/fileapi/isolated_context.h +++ b/webkit/browser/fileapi/isolated_context.h @@ -1,201 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_ISOLATED_CONTEXT_H_ -#define WEBKIT_BROWSER_FILEAPI_ISOLATED_CONTEXT_H_ - -#include <map> -#include <set> -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "base/lazy_instance.h" -#include "base/memory/singleton.h" -#include "base/synchronization/lock.h" -#include "webkit/browser/fileapi/mount_points.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_types.h" - -namespace storage { -class FileSystemURL; -} - -namespace storage { - -// Manages isolated filesystem mount points which have no well-known names -// and are identified by a string 'filesystem ID', which usually just looks -// like random value. -// This type of filesystem can be created on the fly and may go away when it has -// no references from renderers. -// Files in an isolated filesystem are registered with corresponding names and -// identified by a filesystem URL like: -// -// filesystem:<origin>/isolated/<filesystem_id>/<name>/relative/path -// -// Some methods of this class are virtual just for mocking. -// -class STORAGE_EXPORT IsolatedContext : public MountPoints { - public: - class STORAGE_EXPORT FileInfoSet { - public: - FileInfoSet(); - ~FileInfoSet(); - - // Add the given |path| to the set and populates |registered_name| with - // the registered name assigned for the path. |path| needs to be - // absolute and should not contain parent references. - // Return false if the |path| is not valid and could not be added. - bool AddPath(const base::FilePath& path, std::string* registered_name); - - // Add the given |path| with the |name|. - // Return false if the |name| is already registered in the set or - // is not valid and could not be added. - bool AddPathWithName(const base::FilePath& path, const std::string& name); - - const std::set<MountPointInfo>& fileset() const { return fileset_; } - - private: - std::set<MountPointInfo> fileset_; - }; - - // The instance is lazily created per browser process. - static IsolatedContext* GetInstance(); - - // Returns true if the given filesystem type is managed by IsolatedContext - // (i.e. if the given |type| is Isolated or External). - // TODO(kinuko): needs a better function name. - static bool IsIsolatedType(FileSystemType type); - - // Registers a new isolated filesystem with the given FileInfoSet |files| - // and returns the new filesystem_id. The files are registered with their - // register_name as their keys so that later we can resolve the full paths - // for the given name. We only expose the name and the ID for the - // newly created filesystem to the renderer for the sake of security. - // - // The renderer will be sending filesystem requests with a virtual path like - // '/<filesystem_id>/<registered_name>/<relative_path_from_the_dropped_path>' - // for which we could crack in the browser process by calling - // CrackIsolatedPath to get the full path. - // - // For example: if a dropped file has a path like '/a/b/foo' and we register - // the path with the name 'foo' in the newly created filesystem. - // Later if the context is asked to crack a virtual path like '/<fsid>/foo' - // it can properly return the original path '/a/b/foo' by looking up the - // internal mapping. Similarly if a dropped entry is a directory and its - // path is like '/a/b/dir' a virtual path like '/<fsid>/dir/foo' can be - // cracked into '/a/b/dir/foo'. - // - // Note that the path in |fileset| that contains '..' or is not an - // absolute path is skipped and is not registered. - std::string RegisterDraggedFileSystem(const FileInfoSet& files); - - // Registers a new isolated filesystem for a given |path| of filesystem - // |type| filesystem with |filesystem_id| and returns a new filesystem ID. - // |path| must be an absolute path which has no parent references ('..'). - // If |register_name| is non-null and has non-empty string the path is - // registered as the given |register_name|, otherwise it is populated - // with the name internally assigned to the path. - std::string RegisterFileSystemForPath(FileSystemType type, - const std::string& filesystem_id, - const base::FilePath& path, - std::string* register_name); - - // Registers a virtual filesystem. This is different from - // RegisterFileSystemForPath because register_name is required, and - // cracked_path_prefix is allowed to be non-absolute. - // |register_name| is required, since we cannot infer one from the path. - // |cracked_path_prefix| has no parent references, but can be relative. - std::string RegisterFileSystemForVirtualPath( - FileSystemType type, - const std::string& register_name, - const base::FilePath& cracked_path_prefix); - - // Revokes all filesystem(s) registered for the given path. - // This is assumed to be called when the registered path becomes - // globally invalid, e.g. when a device for the path is detached. - // - // Note that this revokes the filesystem no matter how many references it has. - // It is ok to call this for the path that has no associated filesystems. - // Note that this only works for the filesystems registered by - // |RegisterFileSystemForPath|. - void RevokeFileSystemByPath(const base::FilePath& path); - - // Adds a reference to a filesystem specified by the given filesystem_id. - void AddReference(const std::string& filesystem_id); - - // Removes a reference to a filesystem specified by the given filesystem_id. - // If the reference count reaches 0 the isolated context gets destroyed. - // It is OK to call this on the filesystem that has been already deleted - // (e.g. by RevokeFileSystemByPath). - void RemoveReference(const std::string& filesystem_id); - - // Returns a set of dragged MountPointInfos registered for the - // |filesystem_id|. - // The filesystem_id must be pointing to a dragged file system - // (i.e. must be the one registered by RegisterDraggedFileSystem). - // Returns false if the |filesystem_id| is not valid. - bool GetDraggedFileInfo(const std::string& filesystem_id, - std::vector<MountPointInfo>* files) const; - - // MountPoints overrides. - virtual bool HandlesFileSystemMountType(FileSystemType type) const OVERRIDE; - virtual bool RevokeFileSystem(const std::string& filesystem_id) OVERRIDE; - virtual bool GetRegisteredPath(const std::string& filesystem_id, - base::FilePath* path) const OVERRIDE; - virtual bool CrackVirtualPath( - const base::FilePath& virtual_path, - std::string* filesystem_id, - FileSystemType* type, - std::string* cracked_id, - base::FilePath* path, - FileSystemMountOption* mount_option) const OVERRIDE; - virtual FileSystemURL CrackURL(const GURL& url) const OVERRIDE; - virtual FileSystemURL CreateCrackedFileSystemURL( - const GURL& origin, - FileSystemType type, - const base::FilePath& path) const OVERRIDE; - - // Returns the virtual root path that looks like /<filesystem_id>. - base::FilePath CreateVirtualRootPath(const std::string& filesystem_id) const; - - private: - friend struct base::DefaultLazyInstanceTraits<IsolatedContext>; - - // Represents each file system instance (defined in the .cc). - class Instance; - - typedef std::map<std::string, Instance*> IDToInstance; - - // Reverse map from registered path to IDs. - typedef std::map<base::FilePath, std::set<std::string> > PathToID; - - // Obtain an instance of this class via GetInstance(). - IsolatedContext(); - virtual ~IsolatedContext(); - - // MountPoints overrides. - virtual FileSystemURL CrackFileSystemURL( - const FileSystemURL& url) const OVERRIDE; - - // Unregisters a file system of given |filesystem_id|. Must be called with - // lock_ held. Returns true if the file system is unregistered. - bool UnregisterFileSystem(const std::string& filesystem_id); - - // Returns a new filesystem_id. Called with lock. - std::string GetNewFileSystemId() const; - - // This lock needs to be obtained when accessing the instance_map_. - mutable base::Lock lock_; - - IDToInstance instance_map_; - PathToID path_to_id_map_; - - DISALLOW_COPY_AND_ASSIGN(IsolatedContext); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_ISOLATED_CONTEXT_H_ +#include "storage/browser/fileapi/isolated_context.h" diff --git a/webkit/browser/fileapi/isolated_file_system_backend.cc b/webkit/browser/fileapi/isolated_file_system_backend.cc deleted file mode 100644 index 1b5f346..0000000 --- a/webkit/browser/fileapi/isolated_file_system_backend.cc +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/isolated_file_system_backend.h" - -#include <string> - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/files/file_util_proxy.h" -#include "base/logging.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/sequenced_task_runner.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/async_file_util_adapter.h" -#include "webkit/browser/fileapi/copy_or_move_file_validator.h" -#include "webkit/browser/fileapi/dragged_file_util.h" -#include "webkit/browser/fileapi/file_stream_writer.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/isolated_context.h" -#include "webkit/browser/fileapi/native_file_util.h" -#include "webkit/browser/fileapi/transient_file_util.h" -#include "webkit/browser/fileapi/watcher_manager.h" -#include "webkit/common/fileapi/file_system_types.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace storage { - -IsolatedFileSystemBackend::IsolatedFileSystemBackend() - : isolated_file_util_(new AsyncFileUtilAdapter(new LocalFileUtil())), - dragged_file_util_(new AsyncFileUtilAdapter(new DraggedFileUtil())), - transient_file_util_(new AsyncFileUtilAdapter(new TransientFileUtil())) { -} - -IsolatedFileSystemBackend::~IsolatedFileSystemBackend() { -} - -bool IsolatedFileSystemBackend::CanHandleType(FileSystemType type) const { - switch (type) { - case kFileSystemTypeIsolated: - case kFileSystemTypeDragged: - case kFileSystemTypeForTransientFile: - return true; -#if !defined(OS_CHROMEOS) - case kFileSystemTypeNativeLocal: - case kFileSystemTypeNativeForPlatformApp: - return true; -#endif - default: - return false; - } -} - -void IsolatedFileSystemBackend::Initialize(FileSystemContext* context) { -} - -void IsolatedFileSystemBackend::ResolveURL( - const FileSystemURL& url, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) { - // We never allow opening a new isolated FileSystem via usual ResolveURL. - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, - base::Bind(callback, - GURL(), - std::string(), - base::File::FILE_ERROR_SECURITY)); -} - -AsyncFileUtil* IsolatedFileSystemBackend::GetAsyncFileUtil( - FileSystemType type) { - switch (type) { - case kFileSystemTypeNativeLocal: - return isolated_file_util_.get(); - case kFileSystemTypeDragged: - return dragged_file_util_.get(); - case kFileSystemTypeForTransientFile: - return transient_file_util_.get(); - default: - NOTREACHED(); - } - return NULL; -} - -WatcherManager* IsolatedFileSystemBackend::GetWatcherManager( - FileSystemType type) { - return NULL; -} - -CopyOrMoveFileValidatorFactory* -IsolatedFileSystemBackend::GetCopyOrMoveFileValidatorFactory( - FileSystemType type, base::File::Error* error_code) { - DCHECK(error_code); - *error_code = base::File::FILE_OK; - return NULL; -} - -FileSystemOperation* IsolatedFileSystemBackend::CreateFileSystemOperation( - const FileSystemURL& url, - FileSystemContext* context, - base::File::Error* error_code) const { - return FileSystemOperation::Create( - url, context, make_scoped_ptr(new FileSystemOperationContext(context))); -} - -bool IsolatedFileSystemBackend::SupportsStreaming( - const storage::FileSystemURL& url) const { - return false; -} - -bool IsolatedFileSystemBackend::HasInplaceCopyImplementation( - storage::FileSystemType type) const { - DCHECK(type == kFileSystemTypeNativeLocal || type == kFileSystemTypeDragged || - type == kFileSystemTypeForTransientFile); - return false; -} - -scoped_ptr<storage::FileStreamReader> -IsolatedFileSystemBackend::CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time, - FileSystemContext* context) const { - return scoped_ptr<storage::FileStreamReader>( - storage::FileStreamReader::CreateForLocalFile( - context->default_file_task_runner(), - url.path(), - offset, - expected_modification_time)); -} - -scoped_ptr<FileStreamWriter> IsolatedFileSystemBackend::CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset, - FileSystemContext* context) const { - return scoped_ptr<FileStreamWriter>( - FileStreamWriter::CreateForLocalFile( - context->default_file_task_runner(), - url.path(), - offset, - FileStreamWriter::OPEN_EXISTING_FILE)); -} - -FileSystemQuotaUtil* IsolatedFileSystemBackend::GetQuotaUtil() { - // No quota support. - return NULL; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/isolated_file_system_backend.h b/webkit/browser/fileapi/isolated_file_system_backend.h index b252845..5a66c39 100644 --- a/webkit/browser/fileapi/isolated_file_system_backend.h +++ b/webkit/browser/fileapi/isolated_file_system_backend.h @@ -1,57 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_ISOLATED_FILE_SYSTEM_BACKEND_H_ -#define WEBKIT_BROWSER_FILEAPI_ISOLATED_FILE_SYSTEM_BACKEND_H_ - -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/file_system_backend.h" - -namespace storage { - -class AsyncFileUtilAdapter; - -class IsolatedFileSystemBackend : public FileSystemBackend { - public: - IsolatedFileSystemBackend(); - virtual ~IsolatedFileSystemBackend(); - - // FileSystemBackend implementation. - virtual bool CanHandleType(FileSystemType type) const OVERRIDE; - virtual void Initialize(FileSystemContext* context) OVERRIDE; - virtual void ResolveURL(const FileSystemURL& url, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; - virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE; - virtual WatcherManager* GetWatcherManager(FileSystemType type) OVERRIDE; - virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( - FileSystemType type, - base::File::Error* error_code) OVERRIDE; - virtual FileSystemOperation* CreateFileSystemOperation( - const FileSystemURL& url, - FileSystemContext* context, - base::File::Error* error_code) const OVERRIDE; - virtual bool SupportsStreaming(const FileSystemURL& url) const OVERRIDE; - virtual bool HasInplaceCopyImplementation( - storage::FileSystemType type) const OVERRIDE; - virtual scoped_ptr<storage::FileStreamReader> CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time, - FileSystemContext* context) const OVERRIDE; - virtual scoped_ptr<FileStreamWriter> CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset, - FileSystemContext* context) const OVERRIDE; - virtual FileSystemQuotaUtil* GetQuotaUtil() OVERRIDE; - - private: - scoped_ptr<AsyncFileUtilAdapter> isolated_file_util_; - scoped_ptr<AsyncFileUtilAdapter> dragged_file_util_; - scoped_ptr<AsyncFileUtilAdapter> transient_file_util_; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_ISOLATED_FILE_SYSTEM_BACKEND_H_ +#include "storage/browser/fileapi/isolated_file_system_backend.h" diff --git a/webkit/browser/fileapi/local_file_stream_writer.cc b/webkit/browser/fileapi/local_file_stream_writer.cc deleted file mode 100644 index 6f58ffa..0000000 --- a/webkit/browser/fileapi/local_file_stream_writer.cc +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/local_file_stream_writer.h" - -#include "base/callback.h" -#include "base/message_loop/message_loop.h" -#include "net/base/file_stream.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" - -namespace storage { - -namespace { - -const int kOpenFlagsForWrite = base::File::FLAG_OPEN | - base::File::FLAG_WRITE | - base::File::FLAG_ASYNC; -const int kCreateFlagsForWrite = base::File::FLAG_CREATE | - base::File::FLAG_WRITE | - base::File::FLAG_ASYNC; - -} // namespace - -FileStreamWriter* FileStreamWriter::CreateForLocalFile( - base::TaskRunner* task_runner, - const base::FilePath& file_path, - int64 initial_offset, - OpenOrCreate open_or_create) { - return new LocalFileStreamWriter( - task_runner, file_path, initial_offset, open_or_create); -} - -LocalFileStreamWriter::~LocalFileStreamWriter() { - // Invalidate weak pointers so that we won't receive any callbacks from - // in-flight stream operations, which might be triggered during the file close - // in the FileStream destructor. - weak_factory_.InvalidateWeakPtrs(); - - // FileStream's destructor closes the file safely, since we opened the file - // by its Open() method. -} - -int LocalFileStreamWriter::Write(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { - DCHECK(!has_pending_operation_); - DCHECK(cancel_callback_.is_null()); - - has_pending_operation_ = true; - if (stream_impl_) { - int result = InitiateWrite(buf, buf_len, callback); - if (result != net::ERR_IO_PENDING) - has_pending_operation_ = false; - return result; - } - return InitiateOpen(callback, - base::Bind(&LocalFileStreamWriter::ReadyToWrite, - weak_factory_.GetWeakPtr(), - make_scoped_refptr(buf), buf_len, callback)); -} - -int LocalFileStreamWriter::Cancel(const net::CompletionCallback& callback) { - if (!has_pending_operation_) - return net::ERR_UNEXPECTED; - - DCHECK(!callback.is_null()); - cancel_callback_ = callback; - return net::ERR_IO_PENDING; -} - -int LocalFileStreamWriter::Flush(const net::CompletionCallback& callback) { - DCHECK(!has_pending_operation_); - DCHECK(cancel_callback_.is_null()); - - // Write() is not called yet, so there's nothing to flush. - if (!stream_impl_) - return net::OK; - - has_pending_operation_ = true; - int result = InitiateFlush(callback); - if (result != net::ERR_IO_PENDING) - has_pending_operation_ = false; - return result; -} - -LocalFileStreamWriter::LocalFileStreamWriter(base::TaskRunner* task_runner, - const base::FilePath& file_path, - int64 initial_offset, - OpenOrCreate open_or_create) - : file_path_(file_path), - open_or_create_(open_or_create), - initial_offset_(initial_offset), - task_runner_(task_runner), - has_pending_operation_(false), - weak_factory_(this) {} - -int LocalFileStreamWriter::InitiateOpen( - const net::CompletionCallback& error_callback, - const base::Closure& main_operation) { - DCHECK(has_pending_operation_); - DCHECK(!stream_impl_.get()); - - stream_impl_.reset(new net::FileStream(task_runner_)); - - int open_flags = 0; - switch (open_or_create_) { - case OPEN_EXISTING_FILE: - open_flags = kOpenFlagsForWrite; - break; - case CREATE_NEW_FILE: - open_flags = kCreateFlagsForWrite; - break; - } - - return stream_impl_->Open(file_path_, - open_flags, - base::Bind(&LocalFileStreamWriter::DidOpen, - weak_factory_.GetWeakPtr(), - error_callback, - main_operation)); -} - -void LocalFileStreamWriter::DidOpen( - const net::CompletionCallback& error_callback, - const base::Closure& main_operation, - int result) { - DCHECK(has_pending_operation_); - DCHECK(stream_impl_.get()); - - if (CancelIfRequested()) - return; - - if (result != net::OK) { - has_pending_operation_ = false; - stream_impl_.reset(NULL); - error_callback.Run(result); - return; - } - - InitiateSeek(error_callback, main_operation); -} - -void LocalFileStreamWriter::InitiateSeek( - const net::CompletionCallback& error_callback, - const base::Closure& main_operation) { - DCHECK(has_pending_operation_); - DCHECK(stream_impl_.get()); - - if (initial_offset_ == 0) { - // No need to seek. - main_operation.Run(); - return; - } - - int result = stream_impl_->Seek(base::File::FROM_BEGIN, initial_offset_, - base::Bind(&LocalFileStreamWriter::DidSeek, - weak_factory_.GetWeakPtr(), - error_callback, - main_operation)); - if (result != net::ERR_IO_PENDING) { - has_pending_operation_ = false; - error_callback.Run(result); - } -} - -void LocalFileStreamWriter::DidSeek( - const net::CompletionCallback& error_callback, - const base::Closure& main_operation, - int64 result) { - DCHECK(has_pending_operation_); - - if (CancelIfRequested()) - return; - - if (result != initial_offset_) { - // TODO(kinaba) add a more specific error code. - result = net::ERR_FAILED; - } - - if (result < 0) { - has_pending_operation_ = false; - error_callback.Run(static_cast<int>(result)); - return; - } - - main_operation.Run(); -} - -void LocalFileStreamWriter::ReadyToWrite( - net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { - DCHECK(has_pending_operation_); - - int result = InitiateWrite(buf, buf_len, callback); - if (result != net::ERR_IO_PENDING) { - has_pending_operation_ = false; - callback.Run(result); - } -} - -int LocalFileStreamWriter::InitiateWrite( - net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { - DCHECK(has_pending_operation_); - DCHECK(stream_impl_.get()); - - return stream_impl_->Write(buf, buf_len, - base::Bind(&LocalFileStreamWriter::DidWrite, - weak_factory_.GetWeakPtr(), - callback)); -} - -void LocalFileStreamWriter::DidWrite(const net::CompletionCallback& callback, - int result) { - DCHECK(has_pending_operation_); - - if (CancelIfRequested()) - return; - has_pending_operation_ = false; - callback.Run(result); -} - -int LocalFileStreamWriter::InitiateFlush( - const net::CompletionCallback& callback) { - DCHECK(has_pending_operation_); - DCHECK(stream_impl_.get()); - - return stream_impl_->Flush(base::Bind(&LocalFileStreamWriter::DidFlush, - weak_factory_.GetWeakPtr(), - callback)); -} - -void LocalFileStreamWriter::DidFlush(const net::CompletionCallback& callback, - int result) { - DCHECK(has_pending_operation_); - - if (CancelIfRequested()) - return; - has_pending_operation_ = false; - callback.Run(result); -} - -bool LocalFileStreamWriter::CancelIfRequested() { - DCHECK(has_pending_operation_); - - if (cancel_callback_.is_null()) - return false; - - net::CompletionCallback pending_cancel = cancel_callback_; - has_pending_operation_ = false; - cancel_callback_.Reset(); - pending_cancel.Run(net::OK); - return true; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/local_file_stream_writer.h b/webkit/browser/fileapi/local_file_stream_writer.h index 0456614..8afb666 100644 --- a/webkit/browser/fileapi/local_file_stream_writer.h +++ b/webkit/browser/fileapi/local_file_stream_writer.h @@ -1,100 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_LOCAL_FILE_STREAM_WRITER_H_ -#define WEBKIT_BROWSER_FILEAPI_LOCAL_FILE_STREAM_WRITER_H_ - -#include <utility> - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/task_runner.h" -#include "webkit/browser/fileapi/file_stream_writer.h" -#include "webkit/browser/storage_browser_export.h" - -namespace content { -class LocalFileStreamWriterTest; -} - -namespace net { -class FileStream; -} - -namespace storage { - -// This class is a thin wrapper around net::FileStream for writing local files. -class STORAGE_EXPORT LocalFileStreamWriter - : public NON_EXPORTED_BASE(FileStreamWriter) { - public: - virtual ~LocalFileStreamWriter(); - - // FileStreamWriter overrides. - virtual int Write(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) OVERRIDE; - virtual int Cancel(const net::CompletionCallback& callback) OVERRIDE; - virtual int Flush(const net::CompletionCallback& callback) OVERRIDE; - - private: - friend class content::LocalFileStreamWriterTest; - friend class FileStreamWriter; - LocalFileStreamWriter(base::TaskRunner* task_runner, - const base::FilePath& file_path, - int64 initial_offset, - OpenOrCreate open_or_create); - - // Opens |file_path_| and if it succeeds, proceeds to InitiateSeek(). - // If failed, the error code is returned by calling |error_callback|. - int InitiateOpen(const net::CompletionCallback& error_callback, - const base::Closure& main_operation); - void DidOpen(const net::CompletionCallback& error_callback, - const base::Closure& main_operation, - int result); - - // Seeks to |initial_offset_| and proceeds to |main_operation| if it succeeds. - // If failed, the error code is returned by calling |error_callback|. - void InitiateSeek(const net::CompletionCallback& error_callback, - const base::Closure& main_operation); - void DidSeek(const net::CompletionCallback& error_callback, - const base::Closure& main_operation, - int64 result); - - // Passed as the |main_operation| of InitiateOpen() function. - void ReadyToWrite(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback); - - // Writes asynchronously to the file. - int InitiateWrite(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback); - void DidWrite(const net::CompletionCallback& callback, int result); - - // Flushes asynchronously to the file. - int InitiateFlush(const net::CompletionCallback& callback); - void DidFlush(const net::CompletionCallback& callback, int result); - - // Stops the in-flight operation and calls |cancel_callback_| if it has been - // set by Cancel() for the current operation. - bool CancelIfRequested(); - - // Initialization parameters. - const base::FilePath file_path_; - OpenOrCreate open_or_create_; - const int64 initial_offset_; - scoped_refptr<base::TaskRunner> task_runner_; - - // Current states of the operation. - bool has_pending_operation_; - scoped_ptr<net::FileStream> stream_impl_; - net::CompletionCallback cancel_callback_; - - base::WeakPtrFactory<LocalFileStreamWriter> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(LocalFileStreamWriter); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_LOCAL_FILE_STREAM_WRITER_H_ +#include "storage/browser/fileapi/local_file_stream_writer.h" diff --git a/webkit/browser/fileapi/local_file_util.cc b/webkit/browser/fileapi/local_file_util.cc deleted file mode 100644 index a33afdc..0000000 --- a/webkit/browser/fileapi/local_file_util.cc +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/local_file_util.h" - -#include "base/files/file_enumerator.h" -#include "base/files/file_util.h" -#include "base/files/file_util_proxy.h" -#include "url/gurl.h" -#include "webkit/browser/fileapi/async_file_util_adapter.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/native_file_util.h" -#include "webkit/common/fileapi/file_system_types.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace storage { - -AsyncFileUtil* AsyncFileUtil::CreateForLocalFileSystem() { - return new AsyncFileUtilAdapter(new LocalFileUtil()); -} - -class LocalFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { - public: - LocalFileEnumerator(const base::FilePath& platform_root_path, - const base::FilePath& virtual_root_path, - int file_type) - : file_enum_(platform_root_path, false /* recursive */, file_type), - platform_root_path_(platform_root_path), - virtual_root_path_(virtual_root_path) { - } - - virtual ~LocalFileEnumerator() {} - - virtual base::FilePath Next() OVERRIDE; - virtual int64 Size() OVERRIDE; - virtual base::Time LastModifiedTime() OVERRIDE; - virtual bool IsDirectory() OVERRIDE; - - private: - base::FileEnumerator file_enum_; - base::FileEnumerator::FileInfo file_util_info_; - base::FilePath platform_root_path_; - base::FilePath virtual_root_path_; -}; - -base::FilePath LocalFileEnumerator::Next() { - base::FilePath next = file_enum_.Next(); - // Don't return symlinks. - while (!next.empty() && base::IsLink(next)) - next = file_enum_.Next(); - if (next.empty()) - return next; - file_util_info_ = file_enum_.GetInfo(); - - base::FilePath path; - platform_root_path_.AppendRelativePath(next, &path); - return virtual_root_path_.Append(path); -} - -int64 LocalFileEnumerator::Size() { - return file_util_info_.GetSize(); -} - -base::Time LocalFileEnumerator::LastModifiedTime() { - return file_util_info_.GetLastModifiedTime(); -} - -bool LocalFileEnumerator::IsDirectory() { - return file_util_info_.IsDirectory(); -} - -LocalFileUtil::LocalFileUtil() {} - -LocalFileUtil::~LocalFileUtil() {} - -base::File LocalFileUtil::CreateOrOpen( - FileSystemOperationContext* context, - const FileSystemURL& url, int file_flags) { - base::FilePath file_path; - base::File::Error error = GetLocalFilePath(context, url, &file_path); - if (error != base::File::FILE_OK) - return base::File(error); - // Disallow opening files in symlinked paths. - if (base::IsLink(file_path)) - return base::File(base::File::FILE_ERROR_NOT_FOUND); - - return NativeFileUtil::CreateOrOpen(file_path, file_flags); -} - -base::File::Error LocalFileUtil::EnsureFileExists( - FileSystemOperationContext* context, - const FileSystemURL& url, - bool* created) { - base::FilePath file_path; - base::File::Error error = GetLocalFilePath(context, url, &file_path); - if (error != base::File::FILE_OK) - return error; - return NativeFileUtil::EnsureFileExists(file_path, created); -} - -base::File::Error LocalFileUtil::CreateDirectory( - FileSystemOperationContext* context, - const FileSystemURL& url, - bool exclusive, - bool recursive) { - base::FilePath file_path; - base::File::Error error = GetLocalFilePath(context, url, &file_path); - if (error != base::File::FILE_OK) - return error; - return NativeFileUtil::CreateDirectory(file_path, exclusive, recursive); -} - -base::File::Error LocalFileUtil::GetFileInfo( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Info* file_info, - base::FilePath* platform_file_path) { - base::FilePath file_path; - base::File::Error error = GetLocalFilePath(context, url, &file_path); - if (error != base::File::FILE_OK) - return error; - // We should not follow symbolic links in sandboxed file system. - if (base::IsLink(file_path)) - return base::File::FILE_ERROR_NOT_FOUND; - - error = NativeFileUtil::GetFileInfo(file_path, file_info); - if (error == base::File::FILE_OK) - *platform_file_path = file_path; - return error; -} - -scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> LocalFileUtil:: - CreateFileEnumerator( - FileSystemOperationContext* context, - const FileSystemURL& root_url) { - base::FilePath file_path; - if (GetLocalFilePath(context, root_url, &file_path) != - base::File::FILE_OK) { - return make_scoped_ptr(new EmptyFileEnumerator) - .PassAs<FileSystemFileUtil::AbstractFileEnumerator>(); - } - return make_scoped_ptr(new LocalFileEnumerator( - file_path, root_url.path(), - base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES)) - .PassAs<FileSystemFileUtil::AbstractFileEnumerator>(); -} - -base::File::Error LocalFileUtil::GetLocalFilePath( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::FilePath* local_file_path) { - DCHECK(local_file_path); - DCHECK(url.is_valid()); - if (url.path().empty()) { - // Root direcory case, which should not be accessed. - return base::File::FILE_ERROR_ACCESS_DENIED; - } - *local_file_path = url.path(); - return base::File::FILE_OK; -} - -base::File::Error LocalFileUtil::Touch( - FileSystemOperationContext* context, - const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time) { - base::FilePath file_path; - base::File::Error error = GetLocalFilePath(context, url, &file_path); - if (error != base::File::FILE_OK) - return error; - return NativeFileUtil::Touch(file_path, last_access_time, last_modified_time); -} - -base::File::Error LocalFileUtil::Truncate( - FileSystemOperationContext* context, - const FileSystemURL& url, - int64 length) { - base::FilePath file_path; - base::File::Error error = GetLocalFilePath(context, url, &file_path); - if (error != base::File::FILE_OK) - return error; - return NativeFileUtil::Truncate(file_path, length); -} - -base::File::Error LocalFileUtil::CopyOrMoveFile( - FileSystemOperationContext* context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - bool copy) { - base::FilePath src_file_path; - base::File::Error error = GetLocalFilePath(context, src_url, &src_file_path); - if (error != base::File::FILE_OK) - return error; - - base::FilePath dest_file_path; - error = GetLocalFilePath(context, dest_url, &dest_file_path); - if (error != base::File::FILE_OK) - return error; - - return NativeFileUtil::CopyOrMoveFile( - src_file_path, - dest_file_path, - option, - storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, copy)); -} - -base::File::Error LocalFileUtil::CopyInForeignFile( - FileSystemOperationContext* context, - const base::FilePath& src_file_path, - const FileSystemURL& dest_url) { - if (src_file_path.empty()) - return base::File::FILE_ERROR_INVALID_OPERATION; - - base::FilePath dest_file_path; - base::File::Error error = - GetLocalFilePath(context, dest_url, &dest_file_path); - if (error != base::File::FILE_OK) - return error; - return NativeFileUtil::CopyOrMoveFile( - src_file_path, - dest_file_path, - FileSystemOperation::OPTION_NONE, - storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, - true /* copy */)); -} - -base::File::Error LocalFileUtil::DeleteFile( - FileSystemOperationContext* context, - const FileSystemURL& url) { - base::FilePath file_path; - base::File::Error error = GetLocalFilePath(context, url, &file_path); - if (error != base::File::FILE_OK) - return error; - return NativeFileUtil::DeleteFile(file_path); -} - -base::File::Error LocalFileUtil::DeleteDirectory( - FileSystemOperationContext* context, - const FileSystemURL& url) { - base::FilePath file_path; - base::File::Error error = GetLocalFilePath(context, url, &file_path); - if (error != base::File::FILE_OK) - return error; - return NativeFileUtil::DeleteDirectory(file_path); -} - -storage::ScopedFile LocalFileUtil::CreateSnapshotFile( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Error* error, - base::File::Info* file_info, - base::FilePath* platform_path) { - DCHECK(file_info); - // We're just returning the local file information. - *error = GetFileInfo(context, url, file_info, platform_path); - if (*error == base::File::FILE_OK && file_info->is_directory) - *error = base::File::FILE_ERROR_NOT_A_FILE; - return storage::ScopedFile(); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/local_file_util.h b/webkit/browser/fileapi/local_file_util.h index 25b363d..dea7424d 100644 --- a/webkit/browser/fileapi/local_file_util.h +++ b/webkit/browser/fileapi/local_file_util.h @@ -1,94 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_LOCAL_FILE_UTIL_H_ -#define WEBKIT_BROWSER_FILEAPI_LOCAL_FILE_UTIL_H_ - -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/file_system_file_util.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class Time; -} - -class GURL; - -namespace storage { - -class FileSystemOperationContext; -class FileSystemURL; - -// An instance of this class is created and owned by *FileSystemBackend. -class STORAGE_EXPORT LocalFileUtil - : public FileSystemFileUtil { - public: - LocalFileUtil(); - virtual ~LocalFileUtil(); - - virtual base::File CreateOrOpen( - FileSystemOperationContext* context, - const FileSystemURL& url, - int file_flags) OVERRIDE; - virtual base::File::Error EnsureFileExists( - FileSystemOperationContext* context, - const FileSystemURL& url, bool* created) OVERRIDE; - virtual base::File::Error CreateDirectory( - FileSystemOperationContext* context, - const FileSystemURL& url, - bool exclusive, - bool recursive) OVERRIDE; - virtual base::File::Error GetFileInfo( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Info* file_info, - base::FilePath* platform_file) OVERRIDE; - virtual scoped_ptr<AbstractFileEnumerator> CreateFileEnumerator( - FileSystemOperationContext* context, - const FileSystemURL& root_url) OVERRIDE; - virtual base::File::Error GetLocalFilePath( - FileSystemOperationContext* context, - const FileSystemURL& file_system_url, - base::FilePath* local_file_path) OVERRIDE; - virtual base::File::Error Touch( - FileSystemOperationContext* context, - const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time) OVERRIDE; - virtual base::File::Error Truncate( - FileSystemOperationContext* context, - const FileSystemURL& url, - int64 length) OVERRIDE; - virtual base::File::Error CopyOrMoveFile( - FileSystemOperationContext* context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - bool copy) OVERRIDE; - virtual base::File::Error CopyInForeignFile( - FileSystemOperationContext* context, - const base::FilePath& src_file_path, - const FileSystemURL& dest_url) OVERRIDE; - virtual base::File::Error DeleteFile( - FileSystemOperationContext* context, - const FileSystemURL& url) OVERRIDE; - virtual base::File::Error DeleteDirectory( - FileSystemOperationContext* context, - const FileSystemURL& url) OVERRIDE; - virtual storage::ScopedFile CreateSnapshotFile( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Error* error, - base::File::Info* file_info, - base::FilePath* platform_path) OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(LocalFileUtil); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_LOCAL_FILE_UTIL_H_ +#include "storage/browser/fileapi/local_file_util.h" diff --git a/webkit/browser/fileapi/mount_points.cc b/webkit/browser/fileapi/mount_points.cc deleted file mode 100644 index 9523071..0000000 --- a/webkit/browser/fileapi/mount_points.cc +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) 2013 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/browser/fileapi/mount_points.h" - -namespace storage { - -MountPoints::MountPointInfo::MountPointInfo() {} -MountPoints::MountPointInfo::MountPointInfo( - const std::string& name, const base::FilePath& path) - : name(name), path(path) {} - -} // namespace storage diff --git a/webkit/browser/fileapi/mount_points.h b/webkit/browser/fileapi/mount_points.h index 8d71503..1803ac6 100644 --- a/webkit/browser/fileapi/mount_points.h +++ b/webkit/browser/fileapi/mount_points.h @@ -1,108 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_MOUNT_POINTS_H_ -#define WEBKIT_BROWSER_FILEAPI_MOUNT_POINTS_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_util.h" - -class GURL; - -namespace storage { -class FileSystemMountOption; -class FileSystemURL; -} - -namespace storage { - -// Represents a set of mount points for File API. -class STORAGE_EXPORT MountPoints { - public: - struct STORAGE_EXPORT MountPointInfo { - MountPointInfo(); - MountPointInfo(const std::string& name, const base::FilePath& path); - - // The name to be used to register the path. The registered file can - // be referred by a virtual path /<filesystem_id>/<name>. - // The name should NOT contain a path separator '/'. - std::string name; - - // The path of the file. - base::FilePath path; - - // For STL operation. - bool operator<(const MountPointInfo& that) const { - return name < that.name; - } - }; - - MountPoints() {} - virtual ~MountPoints() {} - - // Revokes a mount point identified by |mount_name|. - // Returns false if the |mount_name| is not (no longer) registered. - // TODO(kinuko): Probably this should be rather named RevokeMountPoint. - virtual bool RevokeFileSystem(const std::string& mount_name) = 0; - - // Returns true if the MountPoints implementation handles filesystems with - // the given mount type. - virtual bool HandlesFileSystemMountType(FileSystemType type) const = 0; - - // Same as CreateCrackedFileSystemURL, but cracks FileSystemURL created - // from |url|. - virtual FileSystemURL CrackURL(const GURL& url) const = 0; - - // Creates a FileSystemURL with the given origin, type and path and tries to - // crack it as a part of one of the registered mount points. - // If the the URL is not valid or does not belong to any of the mount points - // registered in this context, returns empty, invalid FileSystemURL. - virtual FileSystemURL CreateCrackedFileSystemURL( - const GURL& origin, - storage::FileSystemType type, - const base::FilePath& path) const = 0; - - // Returns the mount point root path registered for a given |mount_name|. - // Returns false if the given |mount_name| is not valid. - virtual bool GetRegisteredPath(const std::string& mount_name, - base::FilePath* path) const = 0; - - // Cracks the given |virtual_path| (which is the path part of a filesystem URL - // without '/external' or '/isolated' prefix part) and populates the - // |mount_name|, |type|, and |path| if the <mount_name> part embedded in - // the |virtual_path| (i.e. the first component of the |virtual_path|) is a - // valid registered filesystem ID or mount name for an existing mount point. - // - // Returns false if the given virtual_path cannot be cracked. - // - // Note that |path| is set to empty paths if the filesystem type is isolated - // and |virtual_path| has no <relative_path> part (i.e. pointing to the - // virtual root). - virtual bool CrackVirtualPath(const base::FilePath& virtual_path, - std::string* mount_name, - FileSystemType* type, - std::string* cracked_id, - base::FilePath* path, - FileSystemMountOption* mount_option) const = 0; - - protected: - friend class FileSystemContext; - - // Same as CrackURL and CreateCrackedFileSystemURL, but cracks the url already - // instantiated as the FileSystemURL class. This is internally used for nested - // URL cracking in FileSystemContext. - virtual FileSystemURL CrackFileSystemURL(const FileSystemURL& url) const = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(MountPoints); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_MOUNT_POINTS_H_ +#include "storage/browser/fileapi/mount_points.h" diff --git a/webkit/browser/fileapi/native_file_util.cc b/webkit/browser/fileapi/native_file_util.cc deleted file mode 100644 index fbfb6e4..0000000 --- a/webkit/browser/fileapi/native_file_util.cc +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/native_file_util.h" - -#include "base/files/file.h" -#include "base/files/file_enumerator.h" -#include "base/files/file_util.h" -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_url.h" - -namespace storage { - -namespace { - -// Sets permissions on directory at |dir_path| based on the target platform. -// Returns true on success, or false otherwise. -// -// TODO(benchan): Find a better place outside webkit to host this function. -bool SetPlatformSpecificDirectoryPermissions(const base::FilePath& dir_path) { -#if defined(OS_CHROMEOS) - // System daemons on Chrome OS may run as a user different than the Chrome - // process but need to access files under the directories created here. - // Because of that, grant the execute permission on the created directory - // to group and other users. - if (HANDLE_EINTR(chmod(dir_path.value().c_str(), - S_IRWXU | S_IXGRP | S_IXOTH)) != 0) { - return false; - } -#endif - // Keep the directory permissions unchanged on non-Chrome OS platforms. - return true; -} - -// Copies a file |from| to |to|, and ensure the written content is synced to -// the disk. This is essentially base::CopyFile followed by fsync(). -bool CopyFileAndSync(const base::FilePath& from, const base::FilePath& to) { - base::File infile(from, base::File::FLAG_OPEN | base::File::FLAG_READ); - if (!infile.IsValid()) { - return false; - } - - base::File outfile(to, - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - if (!outfile.IsValid()) { - return false; - } - - const int kBufferSize = 32768; - std::vector<char> buffer(kBufferSize); - - for (;;) { - int bytes_read = infile.ReadAtCurrentPos(&buffer[0], kBufferSize); - if (bytes_read < 0) - return false; - if (bytes_read == 0) - break; - for (int bytes_written = 0; bytes_written < bytes_read; ) { - int bytes_written_partial = outfile.WriteAtCurrentPos( - &buffer[bytes_written], bytes_read - bytes_written); - if (bytes_written_partial < 0) - return false; - bytes_written += bytes_written_partial; - } - } - - return outfile.Flush(); -} - -} // namespace - -using base::PlatformFile; - -class NativeFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { - public: - NativeFileEnumerator(const base::FilePath& root_path, - bool recursive, - int file_type) - : file_enum_(root_path, recursive, file_type) { - } - - virtual ~NativeFileEnumerator() {} - - virtual base::FilePath Next() OVERRIDE; - virtual int64 Size() OVERRIDE; - virtual base::Time LastModifiedTime() OVERRIDE; - virtual bool IsDirectory() OVERRIDE; - - private: - base::FileEnumerator file_enum_; - base::FileEnumerator::FileInfo file_util_info_; -}; - -base::FilePath NativeFileEnumerator::Next() { - base::FilePath rv = file_enum_.Next(); - if (!rv.empty()) - file_util_info_ = file_enum_.GetInfo(); - return rv; -} - -int64 NativeFileEnumerator::Size() { - return file_util_info_.GetSize(); -} - -base::Time NativeFileEnumerator::LastModifiedTime() { - return file_util_info_.GetLastModifiedTime(); -} - -bool NativeFileEnumerator::IsDirectory() { - return file_util_info_.IsDirectory(); -} - -NativeFileUtil::CopyOrMoveMode NativeFileUtil::CopyOrMoveModeForDestination( - const FileSystemURL& dest_url, bool copy) { - if (copy) { - return dest_url.mount_option().copy_sync_option() == COPY_SYNC_OPTION_SYNC ? - COPY_SYNC : COPY_NOSYNC; - } - return MOVE; -} - -base::File NativeFileUtil::CreateOrOpen(const base::FilePath& path, - int file_flags) { - if (!base::DirectoryExists(path.DirName())) { - // If its parent does not exist, should return NOT_FOUND error. - return base::File(base::File::FILE_ERROR_NOT_FOUND); - } - - // TODO(rvargas): Check |file_flags| instead. See bug 356358. - if (base::DirectoryExists(path)) - return base::File(base::File::FILE_ERROR_NOT_A_FILE); - - return base::File(path, file_flags); -} - -base::File::Error NativeFileUtil::EnsureFileExists( - const base::FilePath& path, - bool* created) { - if (!base::DirectoryExists(path.DirName())) - // If its parent does not exist, should return NOT_FOUND error. - return base::File::FILE_ERROR_NOT_FOUND; - - // Tries to create the |path| exclusively. This should fail - // with base::File::FILE_ERROR_EXISTS if the path already exists. - base::File file(path, base::File::FLAG_CREATE | base::File::FLAG_READ); - - if (file.IsValid()) { - if (created) - *created = file.created(); - return base::File::FILE_OK; - } - - base::File::Error error_code = file.error_details(); - if (error_code == base::File::FILE_ERROR_EXISTS) { - // Make sure created_ is false. - if (created) - *created = false; - error_code = base::File::FILE_OK; - } - return error_code; -} - -base::File::Error NativeFileUtil::CreateDirectory( - const base::FilePath& path, - bool exclusive, - bool recursive) { - // If parent dir of file doesn't exist. - if (!recursive && !base::PathExists(path.DirName())) - return base::File::FILE_ERROR_NOT_FOUND; - - bool path_exists = base::PathExists(path); - if (exclusive && path_exists) - return base::File::FILE_ERROR_EXISTS; - - // If file exists at the path. - if (path_exists && !base::DirectoryExists(path)) - return base::File::FILE_ERROR_EXISTS; - - if (!base::CreateDirectory(path)) - return base::File::FILE_ERROR_FAILED; - - if (!SetPlatformSpecificDirectoryPermissions(path)) { - // Since some file systems don't support permission setting, we do not treat - // an error from the function as the failure of copying. Just log it. - LOG(WARNING) << "Setting directory permission failed: " - << path.AsUTF8Unsafe(); - } - - return base::File::FILE_OK; -} - -base::File::Error NativeFileUtil::GetFileInfo( - const base::FilePath& path, - base::File::Info* file_info) { - if (!base::PathExists(path)) - return base::File::FILE_ERROR_NOT_FOUND; - - if (!base::GetFileInfo(path, file_info)) - return base::File::FILE_ERROR_FAILED; - return base::File::FILE_OK; -} - -scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> - NativeFileUtil::CreateFileEnumerator(const base::FilePath& root_path, - bool recursive) { - return make_scoped_ptr(new NativeFileEnumerator( - root_path, recursive, - base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES)) - .PassAs<FileSystemFileUtil::AbstractFileEnumerator>(); -} - -base::File::Error NativeFileUtil::Touch( - const base::FilePath& path, - const base::Time& last_access_time, - const base::Time& last_modified_time) { - if (!base::TouchFile(path, last_access_time, last_modified_time)) - return base::File::FILE_ERROR_FAILED; - return base::File::FILE_OK; -} - -base::File::Error NativeFileUtil::Truncate(const base::FilePath& path, - int64 length) { - base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_WRITE); - if (!file.IsValid()) - return file.error_details(); - - if (!file.SetLength(length)) - return base::File::FILE_ERROR_FAILED; - - return base::File::FILE_OK; -} - -bool NativeFileUtil::PathExists(const base::FilePath& path) { - return base::PathExists(path); -} - -bool NativeFileUtil::DirectoryExists(const base::FilePath& path) { - return base::DirectoryExists(path); -} - -base::File::Error NativeFileUtil::CopyOrMoveFile( - const base::FilePath& src_path, - const base::FilePath& dest_path, - FileSystemOperation::CopyOrMoveOption option, - CopyOrMoveMode mode) { - base::File::Info info; - base::File::Error error = NativeFileUtil::GetFileInfo(src_path, &info); - if (error != base::File::FILE_OK) - return error; - if (info.is_directory) - return base::File::FILE_ERROR_NOT_A_FILE; - base::Time last_modified = info.last_modified; - - error = NativeFileUtil::GetFileInfo(dest_path, &info); - if (error != base::File::FILE_OK && - error != base::File::FILE_ERROR_NOT_FOUND) - return error; - if (info.is_directory) - return base::File::FILE_ERROR_INVALID_OPERATION; - if (error == base::File::FILE_ERROR_NOT_FOUND) { - error = NativeFileUtil::GetFileInfo(dest_path.DirName(), &info); - if (error != base::File::FILE_OK) - return error; - if (!info.is_directory) - return base::File::FILE_ERROR_NOT_FOUND; - } - - switch (mode) { - case COPY_NOSYNC: - if (!base::CopyFile(src_path, dest_path)) - return base::File::FILE_ERROR_FAILED; - break; - case COPY_SYNC: - if (!CopyFileAndSync(src_path, dest_path)) - return base::File::FILE_ERROR_FAILED; - break; - case MOVE: - if (!base::Move(src_path, dest_path)) - return base::File::FILE_ERROR_FAILED; - break; - } - - // Preserve the last modified time. Do not return error here even if - // the setting is failed, because the copy itself is successfully done. - if (option == FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED) - base::TouchFile(dest_path, last_modified, last_modified); - - return base::File::FILE_OK; -} - -base::File::Error NativeFileUtil::DeleteFile(const base::FilePath& path) { - if (!base::PathExists(path)) - return base::File::FILE_ERROR_NOT_FOUND; - if (base::DirectoryExists(path)) - return base::File::FILE_ERROR_NOT_A_FILE; - if (!base::DeleteFile(path, false)) - return base::File::FILE_ERROR_FAILED; - return base::File::FILE_OK; -} - -base::File::Error NativeFileUtil::DeleteDirectory(const base::FilePath& path) { - if (!base::PathExists(path)) - return base::File::FILE_ERROR_NOT_FOUND; - if (!base::DirectoryExists(path)) - return base::File::FILE_ERROR_NOT_A_DIRECTORY; - if (!base::IsDirectoryEmpty(path)) - return base::File::FILE_ERROR_NOT_EMPTY; - if (!base::DeleteFile(path, false)) - return base::File::FILE_ERROR_FAILED; - return base::File::FILE_OK; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/native_file_util.h b/webkit/browser/fileapi/native_file_util.h index 645cff6..dea1335 100644 --- a/webkit/browser/fileapi/native_file_util.h +++ b/webkit/browser/fileapi/native_file_util.h @@ -1,73 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_NATIVE_FILE_UTIL_H_ -#define WEBKIT_BROWSER_FILEAPI_NATIVE_FILE_UTIL_H_ - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/files/file_util_proxy.h" -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/file_system_file_util.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class Time; -} - -namespace storage { - -// A thin wrapper class for accessing the OS native filesystem. -// This performs common error checks necessary to implement FileUtil family -// in addition to perform native filesystem operations. -// -// For the error checks it performs please see the comment for -// FileSystemFileUtil interface -// (webkit/browser/fileapi/file_system_file_util.h). -// -// Note that all the methods of this class are static and this does NOT -// inherit from FileSystemFileUtil. -class STORAGE_EXPORT_PRIVATE NativeFileUtil { - public: - enum CopyOrMoveMode { - COPY_NOSYNC, - COPY_SYNC, - MOVE - }; - static CopyOrMoveMode CopyOrMoveModeForDestination( - const FileSystemURL& dest_url, bool copy); - - static base::File CreateOrOpen(const base::FilePath& path, int file_flags); - static base::File::Error EnsureFileExists(const base::FilePath& path, - bool* created); - static base::File::Error CreateDirectory(const base::FilePath& path, - bool exclusive, - bool recursive); - static base::File::Error GetFileInfo(const base::FilePath& path, - base::File::Info* file_info); - static scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> - CreateFileEnumerator(const base::FilePath& root_path, - bool recursive); - static base::File::Error Touch(const base::FilePath& path, - const base::Time& last_access_time, - const base::Time& last_modified_time); - static base::File::Error Truncate(const base::FilePath& path, - int64 length); - static bool PathExists(const base::FilePath& path); - static bool DirectoryExists(const base::FilePath& path); - static base::File::Error CopyOrMoveFile( - const base::FilePath& src_path, - const base::FilePath& dest_path, - FileSystemOperation::CopyOrMoveOption option, - CopyOrMoveMode mode); - static base::File::Error DeleteFile(const base::FilePath& path); - static base::File::Error DeleteDirectory(const base::FilePath& path); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(NativeFileUtil); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_NATIVE_FILE_UTIL_H_ +#include "storage/browser/fileapi/native_file_util.h" diff --git a/webkit/browser/fileapi/obfuscated_file_util.cc b/webkit/browser/fileapi/obfuscated_file_util.cc deleted file mode 100644 index 42ee7d3..0000000 --- a/webkit/browser/fileapi/obfuscated_file_util.cc +++ /dev/null @@ -1,1424 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/obfuscated_file_util.h" - -#include <queue> -#include <string> -#include <vector> - -#include "base/files/file_util.h" -#include "base/format_macros.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/metrics/histogram.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" -#include "url/gurl.h" -#include "webkit/browser/fileapi/file_observers.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/native_file_util.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend.h" -#include "webkit/browser/fileapi/sandbox_isolated_origin_database.h" -#include "webkit/browser/fileapi/sandbox_origin_database.h" -#include "webkit/browser/fileapi/sandbox_prioritized_origin_database.h" -#include "webkit/browser/fileapi/timed_task_helper.h" -#include "webkit/browser/quota/quota_manager.h" -#include "webkit/common/database/database_identifier.h" -#include "webkit/common/fileapi/file_system_util.h" - -// Example of various paths: -// void ObfuscatedFileUtil::DoSomething(const FileSystemURL& url) { -// base::FilePath virtual_path = url.path(); -// base::FilePath local_path = GetLocalFilePath(url); -// -// NativeFileUtil::DoSomething(local_path); -// file_util::DoAnother(local_path); -// } - -namespace storage { - -namespace { - -typedef SandboxDirectoryDatabase::FileId FileId; -typedef SandboxDirectoryDatabase::FileInfo FileInfo; - -void InitFileInfo( - SandboxDirectoryDatabase::FileInfo* file_info, - SandboxDirectoryDatabase::FileId parent_id, - const base::FilePath::StringType& file_name) { - DCHECK(file_info); - file_info->parent_id = parent_id; - file_info->name = file_name; -} - -// Costs computed as per crbug.com/86114, based on the LevelDB implementation of -// path storage under Linux. It's not clear if that will differ on Windows, on -// which base::FilePath uses wide chars [since they're converted to UTF-8 for -// storage anyway], but as long as the cost is high enough that one can't cheat -// on quota by storing data in paths, it doesn't need to be all that accurate. -const int64 kPathCreationQuotaCost = 146; // Bytes per inode, basically. -const int64 kPathByteQuotaCost = 2; // Bytes per byte of path length in UTF-8. - -int64 UsageForPath(size_t length) { - return kPathCreationQuotaCost + - static_cast<int64>(length) * kPathByteQuotaCost; -} - -bool AllocateQuota(FileSystemOperationContext* context, int64 growth) { - if (context->allowed_bytes_growth() == storage::QuotaManager::kNoLimit) - return true; - - int64 new_quota = context->allowed_bytes_growth() - growth; - if (growth > 0 && new_quota < 0) - return false; - context->set_allowed_bytes_growth(new_quota); - return true; -} - -void UpdateUsage( - FileSystemOperationContext* context, - const FileSystemURL& url, - int64 growth) { - context->update_observers()->Notify( - &FileUpdateObserver::OnUpdate, MakeTuple(url, growth)); -} - -void TouchDirectory(SandboxDirectoryDatabase* db, FileId dir_id) { - DCHECK(db); - if (!db->UpdateModificationTime(dir_id, base::Time::Now())) - NOTREACHED(); -} - -enum IsolatedOriginStatus { - kIsolatedOriginMatch, - kIsolatedOriginDontMatch, - kIsolatedOriginStatusMax, -}; - -} // namespace - -class ObfuscatedFileEnumerator - : public FileSystemFileUtil::AbstractFileEnumerator { - public: - ObfuscatedFileEnumerator( - SandboxDirectoryDatabase* db, - FileSystemOperationContext* context, - ObfuscatedFileUtil* obfuscated_file_util, - const FileSystemURL& root_url, - bool recursive) - : db_(db), - context_(context), - obfuscated_file_util_(obfuscated_file_util), - root_url_(root_url), - recursive_(recursive), - current_file_id_(0) { - base::FilePath root_virtual_path = root_url.path(); - FileId file_id; - - if (!db_->GetFileWithPath(root_virtual_path, &file_id)) - return; - - FileRecord record = { file_id, root_virtual_path }; - recurse_queue_.push(record); - } - - virtual ~ObfuscatedFileEnumerator() {} - - virtual base::FilePath Next() OVERRIDE { - ProcessRecurseQueue(); - if (display_stack_.empty()) - return base::FilePath(); - - current_file_id_ = display_stack_.back(); - display_stack_.pop_back(); - - FileInfo file_info; - base::FilePath platform_file_path; - base::File::Error error = - obfuscated_file_util_->GetFileInfoInternal( - db_, context_, root_url_, current_file_id_, - &file_info, ¤t_platform_file_info_, &platform_file_path); - if (error != base::File::FILE_OK) - return Next(); - - base::FilePath virtual_path = - current_parent_virtual_path_.Append(file_info.name); - if (recursive_ && file_info.is_directory()) { - FileRecord record = { current_file_id_, virtual_path }; - recurse_queue_.push(record); - } - return virtual_path; - } - - virtual int64 Size() OVERRIDE { - return current_platform_file_info_.size; - } - - virtual base::Time LastModifiedTime() OVERRIDE { - return current_platform_file_info_.last_modified; - } - - virtual bool IsDirectory() OVERRIDE { - return current_platform_file_info_.is_directory; - } - - private: - typedef SandboxDirectoryDatabase::FileId FileId; - typedef SandboxDirectoryDatabase::FileInfo FileInfo; - - struct FileRecord { - FileId file_id; - base::FilePath virtual_path; - }; - - void ProcessRecurseQueue() { - while (display_stack_.empty() && !recurse_queue_.empty()) { - FileRecord entry = recurse_queue_.front(); - recurse_queue_.pop(); - if (!db_->ListChildren(entry.file_id, &display_stack_)) { - display_stack_.clear(); - return; - } - current_parent_virtual_path_ = entry.virtual_path; - } - } - - SandboxDirectoryDatabase* db_; - FileSystemOperationContext* context_; - ObfuscatedFileUtil* obfuscated_file_util_; - FileSystemURL root_url_; - bool recursive_; - - std::queue<FileRecord> recurse_queue_; - std::vector<FileId> display_stack_; - base::FilePath current_parent_virtual_path_; - - FileId current_file_id_; - base::File::Info current_platform_file_info_; -}; - -class ObfuscatedOriginEnumerator - : public ObfuscatedFileUtil::AbstractOriginEnumerator { - public: - typedef SandboxOriginDatabase::OriginRecord OriginRecord; - ObfuscatedOriginEnumerator( - SandboxOriginDatabaseInterface* origin_database, - const base::FilePath& base_file_path) - : base_file_path_(base_file_path) { - if (origin_database) - origin_database->ListAllOrigins(&origins_); - } - - virtual ~ObfuscatedOriginEnumerator() {} - - // Returns the next origin. Returns empty if there are no more origins. - virtual GURL Next() OVERRIDE { - OriginRecord record; - if (!origins_.empty()) { - record = origins_.back(); - origins_.pop_back(); - } - current_ = record; - return storage::GetOriginFromIdentifier(record.origin); - } - - // Returns the current origin's information. - virtual bool HasTypeDirectory(const std::string& type_string) const OVERRIDE { - if (current_.path.empty()) - return false; - if (type_string.empty()) { - NOTREACHED(); - return false; - } - base::FilePath path = - base_file_path_.Append(current_.path).AppendASCII(type_string); - return base::DirectoryExists(path); - } - - private: - std::vector<OriginRecord> origins_; - OriginRecord current_; - base::FilePath base_file_path_; -}; - -ObfuscatedFileUtil::ObfuscatedFileUtil( - storage::SpecialStoragePolicy* special_storage_policy, - const base::FilePath& file_system_directory, - leveldb::Env* env_override, - base::SequencedTaskRunner* file_task_runner, - const GetTypeStringForURLCallback& get_type_string_for_url, - const std::set<std::string>& known_type_strings, - SandboxFileSystemBackendDelegate* sandbox_delegate) - : special_storage_policy_(special_storage_policy), - file_system_directory_(file_system_directory), - env_override_(env_override), - db_flush_delay_seconds_(10 * 60), // 10 mins. - file_task_runner_(file_task_runner), - get_type_string_for_url_(get_type_string_for_url), - known_type_strings_(known_type_strings), - sandbox_delegate_(sandbox_delegate) { -} - -ObfuscatedFileUtil::~ObfuscatedFileUtil() { - DropDatabases(); -} - -base::File ObfuscatedFileUtil::CreateOrOpen( - FileSystemOperationContext* context, - const FileSystemURL& url, int file_flags) { - base::File file = CreateOrOpenInternal(context, url, file_flags); - if (file.IsValid() && file_flags & base::File::FLAG_WRITE && - context->quota_limit_type() == storage::kQuotaLimitTypeUnlimited && - sandbox_delegate_) { - sandbox_delegate_->StickyInvalidateUsageCache(url.origin(), url.type()); - } - return file.Pass(); -} - -base::File::Error ObfuscatedFileUtil::EnsureFileExists( - FileSystemOperationContext* context, - const FileSystemURL& url, - bool* created) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); - if (!db) - return base::File::FILE_ERROR_FAILED; - - FileId file_id; - if (db->GetFileWithPath(url.path(), &file_id)) { - FileInfo file_info; - if (!db->GetFileInfo(file_id, &file_info)) { - NOTREACHED(); - return base::File::FILE_ERROR_FAILED; - } - if (file_info.is_directory()) - return base::File::FILE_ERROR_NOT_A_FILE; - if (created) - *created = false; - return base::File::FILE_OK; - } - FileId parent_id; - if (!db->GetFileWithPath(VirtualPath::DirName(url.path()), &parent_id)) - return base::File::FILE_ERROR_NOT_FOUND; - - FileInfo file_info; - InitFileInfo(&file_info, parent_id, - VirtualPath::BaseName(url.path()).value()); - - int64 growth = UsageForPath(file_info.name.size()); - if (!AllocateQuota(context, growth)) - return base::File::FILE_ERROR_NO_SPACE; - base::File::Error error = CreateFile(context, base::FilePath(), url, - &file_info); - if (created && base::File::FILE_OK == error) { - *created = true; - UpdateUsage(context, url, growth); - context->change_observers()->Notify( - &FileChangeObserver::OnCreateFile, MakeTuple(url)); - } - return error; -} - -base::File::Error ObfuscatedFileUtil::CreateDirectory( - FileSystemOperationContext* context, - const FileSystemURL& url, - bool exclusive, - bool recursive) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); - if (!db) - return base::File::FILE_ERROR_FAILED; - - FileId file_id; - if (db->GetFileWithPath(url.path(), &file_id)) { - FileInfo file_info; - if (exclusive) - return base::File::FILE_ERROR_EXISTS; - if (!db->GetFileInfo(file_id, &file_info)) { - NOTREACHED(); - return base::File::FILE_ERROR_FAILED; - } - if (!file_info.is_directory()) - return base::File::FILE_ERROR_NOT_A_DIRECTORY; - return base::File::FILE_OK; - } - - std::vector<base::FilePath::StringType> components; - VirtualPath::GetComponents(url.path(), &components); - FileId parent_id = 0; - size_t index; - for (index = 0; index < components.size(); ++index) { - base::FilePath::StringType name = components[index]; - if (name == FILE_PATH_LITERAL("/")) - continue; - if (!db->GetChildWithName(parent_id, name, &parent_id)) - break; - } - if (!db->IsDirectory(parent_id)) - return base::File::FILE_ERROR_NOT_A_DIRECTORY; - if (!recursive && components.size() - index > 1) - return base::File::FILE_ERROR_NOT_FOUND; - bool first = true; - for (; index < components.size(); ++index) { - FileInfo file_info; - file_info.name = components[index]; - if (file_info.name == FILE_PATH_LITERAL("/")) - continue; - file_info.modification_time = base::Time::Now(); - file_info.parent_id = parent_id; - int64 growth = UsageForPath(file_info.name.size()); - if (!AllocateQuota(context, growth)) - return base::File::FILE_ERROR_NO_SPACE; - base::File::Error error = db->AddFileInfo(file_info, &parent_id); - if (error != base::File::FILE_OK) - return error; - UpdateUsage(context, url, growth); - context->change_observers()->Notify( - &FileChangeObserver::OnCreateDirectory, MakeTuple(url)); - if (first) { - first = false; - TouchDirectory(db, file_info.parent_id); - } - } - return base::File::FILE_OK; -} - -base::File::Error ObfuscatedFileUtil::GetFileInfo( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Info* file_info, - base::FilePath* platform_file_path) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false); - if (!db) - return base::File::FILE_ERROR_NOT_FOUND; - FileId file_id; - if (!db->GetFileWithPath(url.path(), &file_id)) - return base::File::FILE_ERROR_NOT_FOUND; - FileInfo local_info; - return GetFileInfoInternal(db, context, url, - file_id, &local_info, - file_info, platform_file_path); -} - -scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> - ObfuscatedFileUtil::CreateFileEnumerator( - FileSystemOperationContext* context, - const FileSystemURL& root_url) { - return CreateFileEnumerator(context, root_url, false /* recursive */); -} - -base::File::Error ObfuscatedFileUtil::GetLocalFilePath( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::FilePath* local_path) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false); - if (!db) - return base::File::FILE_ERROR_NOT_FOUND; - FileId file_id; - if (!db->GetFileWithPath(url.path(), &file_id)) - return base::File::FILE_ERROR_NOT_FOUND; - FileInfo file_info; - if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) { - NOTREACHED(); - // Directories have no local file path. - return base::File::FILE_ERROR_NOT_FOUND; - } - *local_path = DataPathToLocalPath(url, file_info.data_path); - - if (local_path->empty()) - return base::File::FILE_ERROR_NOT_FOUND; - return base::File::FILE_OK; -} - -base::File::Error ObfuscatedFileUtil::Touch( - FileSystemOperationContext* context, - const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false); - if (!db) - return base::File::FILE_ERROR_NOT_FOUND; - FileId file_id; - if (!db->GetFileWithPath(url.path(), &file_id)) - return base::File::FILE_ERROR_NOT_FOUND; - - FileInfo file_info; - if (!db->GetFileInfo(file_id, &file_info)) { - NOTREACHED(); - return base::File::FILE_ERROR_FAILED; - } - if (file_info.is_directory()) { - if (!db->UpdateModificationTime(file_id, last_modified_time)) - return base::File::FILE_ERROR_FAILED; - return base::File::FILE_OK; - } - return NativeFileUtil::Touch( - DataPathToLocalPath(url, file_info.data_path), - last_access_time, last_modified_time); -} - -base::File::Error ObfuscatedFileUtil::Truncate( - FileSystemOperationContext* context, - const FileSystemURL& url, - int64 length) { - base::File::Info file_info; - base::FilePath local_path; - base::File::Error error = - GetFileInfo(context, url, &file_info, &local_path); - if (error != base::File::FILE_OK) - return error; - - int64 growth = length - file_info.size; - if (!AllocateQuota(context, growth)) - return base::File::FILE_ERROR_NO_SPACE; - error = NativeFileUtil::Truncate(local_path, length); - if (error == base::File::FILE_OK) { - UpdateUsage(context, url, growth); - context->change_observers()->Notify( - &FileChangeObserver::OnModifyFile, MakeTuple(url)); - } - return error; -} - -base::File::Error ObfuscatedFileUtil::CopyOrMoveFile( - FileSystemOperationContext* context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - bool copy) { - // Cross-filesystem copies and moves should be handled via CopyInForeignFile. - DCHECK(src_url.origin() == dest_url.origin()); - DCHECK(src_url.type() == dest_url.type()); - - SandboxDirectoryDatabase* db = GetDirectoryDatabase(src_url, true); - if (!db) - return base::File::FILE_ERROR_FAILED; - - FileId src_file_id; - if (!db->GetFileWithPath(src_url.path(), &src_file_id)) - return base::File::FILE_ERROR_NOT_FOUND; - - FileId dest_file_id; - bool overwrite = db->GetFileWithPath(dest_url.path(), - &dest_file_id); - - FileInfo src_file_info; - base::File::Info src_platform_file_info; - base::FilePath src_local_path; - base::File::Error error = GetFileInfoInternal( - db, context, src_url, src_file_id, - &src_file_info, &src_platform_file_info, &src_local_path); - if (error != base::File::FILE_OK) - return error; - if (src_file_info.is_directory()) - return base::File::FILE_ERROR_NOT_A_FILE; - - FileInfo dest_file_info; - base::File::Info dest_platform_file_info; // overwrite case only - base::FilePath dest_local_path; // overwrite case only - if (overwrite) { - base::File::Error error = GetFileInfoInternal( - db, context, dest_url, dest_file_id, - &dest_file_info, &dest_platform_file_info, &dest_local_path); - if (error == base::File::FILE_ERROR_NOT_FOUND) - overwrite = false; // fallback to non-overwrite case - else if (error != base::File::FILE_OK) - return error; - else if (dest_file_info.is_directory()) - return base::File::FILE_ERROR_INVALID_OPERATION; - } - if (!overwrite) { - FileId dest_parent_id; - if (!db->GetFileWithPath(VirtualPath::DirName(dest_url.path()), - &dest_parent_id)) { - return base::File::FILE_ERROR_NOT_FOUND; - } - - dest_file_info = src_file_info; - dest_file_info.parent_id = dest_parent_id; - dest_file_info.name = - VirtualPath::BaseName(dest_url.path()).value(); - } - - int64 growth = 0; - if (copy) - growth += src_platform_file_info.size; - else - growth -= UsageForPath(src_file_info.name.size()); - if (overwrite) - growth -= dest_platform_file_info.size; - else - growth += UsageForPath(dest_file_info.name.size()); - if (!AllocateQuota(context, growth)) - return base::File::FILE_ERROR_NO_SPACE; - - /* - * Copy-with-overwrite - * Just overwrite data file - * Copy-without-overwrite - * Copy backing file - * Create new metadata pointing to new backing file. - * Move-with-overwrite - * transaction: - * Remove source entry. - * Point target entry to source entry's backing file. - * Delete target entry's old backing file - * Move-without-overwrite - * Just update metadata - */ - error = base::File::FILE_ERROR_FAILED; - if (copy) { - if (overwrite) { - error = NativeFileUtil::CopyOrMoveFile( - src_local_path, - dest_local_path, - option, - storage::NativeFileUtil::CopyOrMoveModeForDestination( - dest_url, true /* copy */)); - } else { // non-overwrite - error = CreateFile(context, src_local_path, dest_url, &dest_file_info); - } - } else { - if (overwrite) { - if (db->OverwritingMoveFile(src_file_id, dest_file_id)) { - if (base::File::FILE_OK != - NativeFileUtil::DeleteFile(dest_local_path)) - LOG(WARNING) << "Leaked a backing file."; - error = base::File::FILE_OK; - } else { - error = base::File::FILE_ERROR_FAILED; - } - } else { // non-overwrite - if (db->UpdateFileInfo(src_file_id, dest_file_info)) - error = base::File::FILE_OK; - else - error = base::File::FILE_ERROR_FAILED; - } - } - - if (error != base::File::FILE_OK) - return error; - - if (overwrite) { - context->change_observers()->Notify( - &FileChangeObserver::OnModifyFile, - MakeTuple(dest_url)); - } else { - context->change_observers()->Notify( - &FileChangeObserver::OnCreateFileFrom, - MakeTuple(dest_url, src_url)); - } - - if (!copy) { - context->change_observers()->Notify( - &FileChangeObserver::OnRemoveFile, MakeTuple(src_url)); - TouchDirectory(db, src_file_info.parent_id); - } - - TouchDirectory(db, dest_file_info.parent_id); - - UpdateUsage(context, dest_url, growth); - return error; -} - -base::File::Error ObfuscatedFileUtil::CopyInForeignFile( - FileSystemOperationContext* context, - const base::FilePath& src_file_path, - const FileSystemURL& dest_url) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true); - if (!db) - return base::File::FILE_ERROR_FAILED; - - base::File::Info src_platform_file_info; - if (!base::GetFileInfo(src_file_path, &src_platform_file_info)) - return base::File::FILE_ERROR_NOT_FOUND; - - FileId dest_file_id; - bool overwrite = db->GetFileWithPath(dest_url.path(), - &dest_file_id); - - FileInfo dest_file_info; - base::File::Info dest_platform_file_info; // overwrite case only - if (overwrite) { - base::FilePath dest_local_path; - base::File::Error error = GetFileInfoInternal( - db, context, dest_url, dest_file_id, - &dest_file_info, &dest_platform_file_info, &dest_local_path); - if (error == base::File::FILE_ERROR_NOT_FOUND) - overwrite = false; // fallback to non-overwrite case - else if (error != base::File::FILE_OK) - return error; - else if (dest_file_info.is_directory()) - return base::File::FILE_ERROR_INVALID_OPERATION; - } - if (!overwrite) { - FileId dest_parent_id; - if (!db->GetFileWithPath(VirtualPath::DirName(dest_url.path()), - &dest_parent_id)) { - return base::File::FILE_ERROR_NOT_FOUND; - } - if (!dest_file_info.is_directory()) - return base::File::FILE_ERROR_FAILED; - InitFileInfo(&dest_file_info, dest_parent_id, - VirtualPath::BaseName(dest_url.path()).value()); - } - - int64 growth = src_platform_file_info.size; - if (overwrite) - growth -= dest_platform_file_info.size; - else - growth += UsageForPath(dest_file_info.name.size()); - if (!AllocateQuota(context, growth)) - return base::File::FILE_ERROR_NO_SPACE; - - base::File::Error error; - if (overwrite) { - base::FilePath dest_local_path = - DataPathToLocalPath(dest_url, dest_file_info.data_path); - error = NativeFileUtil::CopyOrMoveFile( - src_file_path, - dest_local_path, - FileSystemOperation::OPTION_NONE, - storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, - true /* copy */)); - } else { - error = CreateFile(context, src_file_path, dest_url, &dest_file_info); - } - - if (error != base::File::FILE_OK) - return error; - - if (overwrite) { - context->change_observers()->Notify( - &FileChangeObserver::OnModifyFile, MakeTuple(dest_url)); - } else { - context->change_observers()->Notify( - &FileChangeObserver::OnCreateFile, MakeTuple(dest_url)); - } - - UpdateUsage(context, dest_url, growth); - TouchDirectory(db, dest_file_info.parent_id); - return base::File::FILE_OK; -} - -base::File::Error ObfuscatedFileUtil::DeleteFile( - FileSystemOperationContext* context, - const FileSystemURL& url) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); - if (!db) - return base::File::FILE_ERROR_FAILED; - FileId file_id; - if (!db->GetFileWithPath(url.path(), &file_id)) - return base::File::FILE_ERROR_NOT_FOUND; - - FileInfo file_info; - base::File::Info platform_file_info; - base::FilePath local_path; - base::File::Error error = GetFileInfoInternal( - db, context, url, file_id, &file_info, &platform_file_info, &local_path); - if (error != base::File::FILE_ERROR_NOT_FOUND && - error != base::File::FILE_OK) - return error; - - if (file_info.is_directory()) - return base::File::FILE_ERROR_NOT_A_FILE; - - int64 growth = -UsageForPath(file_info.name.size()) - platform_file_info.size; - AllocateQuota(context, growth); - if (!db->RemoveFileInfo(file_id)) { - NOTREACHED(); - return base::File::FILE_ERROR_FAILED; - } - UpdateUsage(context, url, growth); - TouchDirectory(db, file_info.parent_id); - - context->change_observers()->Notify( - &FileChangeObserver::OnRemoveFile, MakeTuple(url)); - - if (error == base::File::FILE_ERROR_NOT_FOUND) - return base::File::FILE_OK; - - error = NativeFileUtil::DeleteFile(local_path); - if (base::File::FILE_OK != error) - LOG(WARNING) << "Leaked a backing file."; - return base::File::FILE_OK; -} - -base::File::Error ObfuscatedFileUtil::DeleteDirectory( - FileSystemOperationContext* context, - const FileSystemURL& url) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); - if (!db) - return base::File::FILE_ERROR_FAILED; - - FileId file_id; - if (!db->GetFileWithPath(url.path(), &file_id)) - return base::File::FILE_ERROR_NOT_FOUND; - FileInfo file_info; - if (!db->GetFileInfo(file_id, &file_info)) { - NOTREACHED(); - return base::File::FILE_ERROR_FAILED; - } - if (!file_info.is_directory()) - return base::File::FILE_ERROR_NOT_A_DIRECTORY; - if (!db->RemoveFileInfo(file_id)) - return base::File::FILE_ERROR_NOT_EMPTY; - int64 growth = -UsageForPath(file_info.name.size()); - AllocateQuota(context, growth); - UpdateUsage(context, url, growth); - TouchDirectory(db, file_info.parent_id); - context->change_observers()->Notify( - &FileChangeObserver::OnRemoveDirectory, MakeTuple(url)); - return base::File::FILE_OK; -} - -storage::ScopedFile ObfuscatedFileUtil::CreateSnapshotFile( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Error* error, - base::File::Info* file_info, - base::FilePath* platform_path) { - // We're just returning the local file information. - *error = GetFileInfo(context, url, file_info, platform_path); - if (*error == base::File::FILE_OK && file_info->is_directory) { - *file_info = base::File::Info(); - *error = base::File::FILE_ERROR_NOT_A_FILE; - } - return storage::ScopedFile(); -} - -scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> - ObfuscatedFileUtil::CreateFileEnumerator( - FileSystemOperationContext* context, - const FileSystemURL& root_url, - bool recursive) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(root_url, false); - if (!db) { - return scoped_ptr<AbstractFileEnumerator>(new EmptyFileEnumerator()); - } - return scoped_ptr<AbstractFileEnumerator>( - new ObfuscatedFileEnumerator(db, context, this, root_url, recursive)); -} - -bool ObfuscatedFileUtil::IsDirectoryEmpty( - FileSystemOperationContext* context, - const FileSystemURL& url) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false); - if (!db) - return true; // Not a great answer, but it's what others do. - FileId file_id; - if (!db->GetFileWithPath(url.path(), &file_id)) - return true; // Ditto. - FileInfo file_info; - if (!db->GetFileInfo(file_id, &file_info)) { - DCHECK(!file_id); - // It's the root directory and the database hasn't been initialized yet. - return true; - } - if (!file_info.is_directory()) - return true; - std::vector<FileId> children; - // TODO(ericu): This could easily be made faster with help from the database. - if (!db->ListChildren(file_id, &children)) - return true; - return children.empty(); -} - -base::FilePath ObfuscatedFileUtil::GetDirectoryForOriginAndType( - const GURL& origin, - const std::string& type_string, - bool create, - base::File::Error* error_code) { - base::FilePath origin_dir = GetDirectoryForOrigin(origin, create, error_code); - if (origin_dir.empty()) - return base::FilePath(); - if (type_string.empty()) - return origin_dir; - base::FilePath path = origin_dir.AppendASCII(type_string); - base::File::Error error = base::File::FILE_OK; - if (!base::DirectoryExists(path) && - (!create || !base::CreateDirectory(path))) { - error = create ? - base::File::FILE_ERROR_FAILED : - base::File::FILE_ERROR_NOT_FOUND; - } - - if (error_code) - *error_code = error; - return path; -} - -bool ObfuscatedFileUtil::DeleteDirectoryForOriginAndType( - const GURL& origin, - const std::string& type_string) { - base::File::Error error = base::File::FILE_OK; - base::FilePath origin_type_path = GetDirectoryForOriginAndType( - origin, type_string, false, &error); - if (origin_type_path.empty()) - return true; - if (error != base::File::FILE_ERROR_NOT_FOUND) { - // TODO(dmikurube): Consider the return value of DestroyDirectoryDatabase. - // We ignore its error now since 1) it doesn't matter the final result, and - // 2) it always returns false in Windows because of LevelDB's - // implementation. - // Information about failure would be useful for debugging. - if (!type_string.empty()) - DestroyDirectoryDatabase(origin, type_string); - if (!base::DeleteFile(origin_type_path, true /* recursive */)) - return false; - } - - base::FilePath origin_path = VirtualPath::DirName(origin_type_path); - DCHECK_EQ(origin_path.value(), - GetDirectoryForOrigin(origin, false, NULL).value()); - - if (!type_string.empty()) { - // At this point we are sure we had successfully deleted the origin/type - // directory (i.e. we're ready to just return true). - // See if we have other directories in this origin directory. - for (std::set<std::string>::iterator iter = known_type_strings_.begin(); - iter != known_type_strings_.end(); - ++iter) { - if (*iter == type_string) - continue; - if (base::DirectoryExists(origin_path.AppendASCII(*iter))) { - // Other type's directory exists; just return true here. - return true; - } - } - } - - // No other directories seem exist. Try deleting the entire origin directory. - InitOriginDatabase(origin, false); - if (origin_database_) { - origin_database_->RemovePathForOrigin( - storage::GetIdentifierFromOrigin(origin)); - } - if (!base::DeleteFile(origin_path, true /* recursive */)) - return false; - - return true; -} - -ObfuscatedFileUtil::AbstractOriginEnumerator* -ObfuscatedFileUtil::CreateOriginEnumerator() { - std::vector<SandboxOriginDatabase::OriginRecord> origins; - - InitOriginDatabase(GURL(), false); - return new ObfuscatedOriginEnumerator( - origin_database_.get(), file_system_directory_); -} - -bool ObfuscatedFileUtil::DestroyDirectoryDatabase( - const GURL& origin, - const std::string& type_string) { - std::string key = GetDirectoryDatabaseKey(origin, type_string); - if (key.empty()) - return true; - DirectoryMap::iterator iter = directories_.find(key); - if (iter != directories_.end()) { - SandboxDirectoryDatabase* database = iter->second; - directories_.erase(iter); - delete database; - } - - base::File::Error error = base::File::FILE_OK; - base::FilePath path = GetDirectoryForOriginAndType( - origin, type_string, false, &error); - if (path.empty() || error == base::File::FILE_ERROR_NOT_FOUND) - return true; - return SandboxDirectoryDatabase::DestroyDatabase(path, env_override_); -} - -// static -int64 ObfuscatedFileUtil::ComputeFilePathCost(const base::FilePath& path) { - return UsageForPath(VirtualPath::BaseName(path).value().size()); -} - -void ObfuscatedFileUtil::MaybePrepopulateDatabase( - const std::vector<std::string>& type_strings_to_prepopulate) { - SandboxPrioritizedOriginDatabase database(file_system_directory_, - env_override_); - std::string origin_string = database.GetPrimaryOrigin(); - if (origin_string.empty() || !database.HasOriginPath(origin_string)) - return; - const GURL origin = storage::GetOriginFromIdentifier(origin_string); - - // Prepopulate the directory database(s) if and only if this instance - // has primary origin and the directory database is already there. - for (size_t i = 0; i < type_strings_to_prepopulate.size(); ++i) { - const std::string type_string = type_strings_to_prepopulate[i]; - // Only handles known types. - if (!ContainsKey(known_type_strings_, type_string)) - continue; - base::File::Error error = base::File::FILE_ERROR_FAILED; - base::FilePath path = GetDirectoryForOriginAndType( - origin, type_string, false, &error); - if (error != base::File::FILE_OK) - continue; - scoped_ptr<SandboxDirectoryDatabase> db( - new SandboxDirectoryDatabase(path, env_override_)); - if (db->Init(SandboxDirectoryDatabase::FAIL_ON_CORRUPTION)) { - directories_[GetDirectoryDatabaseKey(origin, type_string)] = db.release(); - MarkUsed(); - // Don't populate more than one database, as it may rather hurt - // performance. - break; - } - } -} - -base::FilePath ObfuscatedFileUtil::GetDirectoryForURL( - const FileSystemURL& url, - bool create, - base::File::Error* error_code) { - return GetDirectoryForOriginAndType( - url.origin(), CallGetTypeStringForURL(url), create, error_code); -} - -std::string ObfuscatedFileUtil::CallGetTypeStringForURL( - const FileSystemURL& url) { - DCHECK(!get_type_string_for_url_.is_null()); - return get_type_string_for_url_.Run(url); -} - -base::File::Error ObfuscatedFileUtil::GetFileInfoInternal( - SandboxDirectoryDatabase* db, - FileSystemOperationContext* context, - const FileSystemURL& url, - FileId file_id, - FileInfo* local_info, - base::File::Info* file_info, - base::FilePath* platform_file_path) { - DCHECK(db); - DCHECK(context); - DCHECK(file_info); - DCHECK(platform_file_path); - - if (!db->GetFileInfo(file_id, local_info)) { - NOTREACHED(); - return base::File::FILE_ERROR_FAILED; - } - - if (local_info->is_directory()) { - file_info->size = 0; - file_info->is_directory = true; - file_info->is_symbolic_link = false; - file_info->last_modified = local_info->modification_time; - *platform_file_path = base::FilePath(); - // We don't fill in ctime or atime. - return base::File::FILE_OK; - } - if (local_info->data_path.empty()) - return base::File::FILE_ERROR_INVALID_OPERATION; - base::FilePath local_path = DataPathToLocalPath(url, local_info->data_path); - base::File::Error error = NativeFileUtil::GetFileInfo( - local_path, file_info); - // We should not follow symbolic links in sandboxed file system. - if (base::IsLink(local_path)) { - LOG(WARNING) << "Found a symbolic file."; - error = base::File::FILE_ERROR_NOT_FOUND; - } - if (error == base::File::FILE_OK) { - *platform_file_path = local_path; - } else if (error == base::File::FILE_ERROR_NOT_FOUND) { - LOG(WARNING) << "Lost a backing file."; - InvalidateUsageCache(context, url.origin(), url.type()); - if (!db->RemoveFileInfo(file_id)) - return base::File::FILE_ERROR_FAILED; - } - return error; -} - -base::File ObfuscatedFileUtil::CreateAndOpenFile( - FileSystemOperationContext* context, - const FileSystemURL& dest_url, - FileInfo* dest_file_info, int file_flags) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true); - - base::FilePath root, dest_local_path; - base::File::Error error = GenerateNewLocalPath(db, context, dest_url, &root, - &dest_local_path); - if (error != base::File::FILE_OK) - return base::File(error); - - if (base::PathExists(dest_local_path)) { - if (!base::DeleteFile(dest_local_path, true /* recursive */)) - return base::File(base::File::FILE_ERROR_FAILED); - LOG(WARNING) << "A stray file detected"; - InvalidateUsageCache(context, dest_url.origin(), dest_url.type()); - } - - base::File file = NativeFileUtil::CreateOrOpen(dest_local_path, file_flags); - if (!file.IsValid()) - return file.Pass(); - - if (!file.created()) { - file.Close(); - base::DeleteFile(dest_local_path, false /* recursive */); - return base::File(base::File::FILE_ERROR_FAILED); - } - - error = CommitCreateFile(root, dest_local_path, db, dest_file_info); - if (error != base::File::FILE_OK) { - file.Close(); - base::DeleteFile(dest_local_path, false /* recursive */); - return base::File(error); - } - - return file.Pass(); -} - -base::File::Error ObfuscatedFileUtil::CreateFile( - FileSystemOperationContext* context, - const base::FilePath& src_file_path, - const FileSystemURL& dest_url, - FileInfo* dest_file_info) { - SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true); - - base::FilePath root, dest_local_path; - base::File::Error error = GenerateNewLocalPath(db, context, dest_url, &root, - &dest_local_path); - if (error != base::File::FILE_OK) - return error; - - bool created = false; - if (src_file_path.empty()) { - if (base::PathExists(dest_local_path)) { - if (!base::DeleteFile(dest_local_path, true /* recursive */)) - return base::File::FILE_ERROR_FAILED; - LOG(WARNING) << "A stray file detected"; - InvalidateUsageCache(context, dest_url.origin(), dest_url.type()); - } - - error = NativeFileUtil::EnsureFileExists(dest_local_path, &created); - } else { - error = NativeFileUtil::CopyOrMoveFile( - src_file_path, - dest_local_path, - FileSystemOperation::OPTION_NONE, - storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, - true /* copy */)); - created = true; - } - if (error != base::File::FILE_OK) - return error; - if (!created) - return base::File::FILE_ERROR_FAILED; - - return CommitCreateFile(root, dest_local_path, db, dest_file_info); -} - -base::File::Error ObfuscatedFileUtil::CommitCreateFile( - const base::FilePath& root, - const base::FilePath& local_path, - SandboxDirectoryDatabase* db, - FileInfo* dest_file_info) { - // This removes the root, including the trailing slash, leaving a relative - // path. - dest_file_info->data_path = base::FilePath( - local_path.value().substr(root.value().length() + 1)); - - FileId file_id; - base::File::Error error = db->AddFileInfo(*dest_file_info, &file_id); - if (error != base::File::FILE_OK) - return error; - - TouchDirectory(db, dest_file_info->parent_id); - return base::File::FILE_OK; -} - -base::FilePath ObfuscatedFileUtil::DataPathToLocalPath( - const FileSystemURL& url, const base::FilePath& data_path) { - base::File::Error error = base::File::FILE_OK; - base::FilePath root = GetDirectoryForURL(url, false, &error); - if (error != base::File::FILE_OK) - return base::FilePath(); - return root.Append(data_path); -} - -std::string ObfuscatedFileUtil::GetDirectoryDatabaseKey( - const GURL& origin, const std::string& type_string) { - if (type_string.empty()) { - LOG(WARNING) << "Unknown filesystem type requested:" << type_string; - return std::string(); - } - // For isolated origin we just use a type string as a key. - return storage::GetIdentifierFromOrigin(origin) + type_string; -} - -// TODO(ericu): How to do the whole validation-without-creation thing? -// We may not have quota even to create the database. -// Ah, in that case don't even get here? -// Still doesn't answer the quota issue, though. -SandboxDirectoryDatabase* ObfuscatedFileUtil::GetDirectoryDatabase( - const FileSystemURL& url, bool create) { - std::string key = GetDirectoryDatabaseKey( - url.origin(), CallGetTypeStringForURL(url)); - if (key.empty()) - return NULL; - - DirectoryMap::iterator iter = directories_.find(key); - if (iter != directories_.end()) { - MarkUsed(); - return iter->second; - } - - base::File::Error error = base::File::FILE_OK; - base::FilePath path = GetDirectoryForURL(url, create, &error); - if (error != base::File::FILE_OK) { - LOG(WARNING) << "Failed to get origin+type directory: " - << url.DebugString() << " error:" << error; - return NULL; - } - MarkUsed(); - SandboxDirectoryDatabase* database = - new SandboxDirectoryDatabase(path, env_override_); - directories_[key] = database; - return database; -} - -base::FilePath ObfuscatedFileUtil::GetDirectoryForOrigin( - const GURL& origin, bool create, base::File::Error* error_code) { - if (!InitOriginDatabase(origin, create)) { - if (error_code) { - *error_code = create ? - base::File::FILE_ERROR_FAILED : - base::File::FILE_ERROR_NOT_FOUND; - } - return base::FilePath(); - } - base::FilePath directory_name; - std::string id = storage::GetIdentifierFromOrigin(origin); - - bool exists_in_db = origin_database_->HasOriginPath(id); - if (!exists_in_db && !create) { - if (error_code) - *error_code = base::File::FILE_ERROR_NOT_FOUND; - return base::FilePath(); - } - if (!origin_database_->GetPathForOrigin(id, &directory_name)) { - if (error_code) - *error_code = base::File::FILE_ERROR_FAILED; - return base::FilePath(); - } - - base::FilePath path = file_system_directory_.Append(directory_name); - bool exists_in_fs = base::DirectoryExists(path); - if (!exists_in_db && exists_in_fs) { - if (!base::DeleteFile(path, true)) { - if (error_code) - *error_code = base::File::FILE_ERROR_FAILED; - return base::FilePath(); - } - exists_in_fs = false; - } - - if (!exists_in_fs) { - if (!create || !base::CreateDirectory(path)) { - if (error_code) - *error_code = create ? - base::File::FILE_ERROR_FAILED : - base::File::FILE_ERROR_NOT_FOUND; - return base::FilePath(); - } - } - - if (error_code) - *error_code = base::File::FILE_OK; - - return path; -} - -void ObfuscatedFileUtil::InvalidateUsageCache( - FileSystemOperationContext* context, - const GURL& origin, - FileSystemType type) { - if (sandbox_delegate_) - sandbox_delegate_->InvalidateUsageCache(origin, type); -} - -void ObfuscatedFileUtil::MarkUsed() { - if (!timer_) - timer_.reset(new TimedTaskHelper(file_task_runner_.get())); - - if (timer_->IsRunning()) { - timer_->Reset(); - } else { - timer_->Start(FROM_HERE, - base::TimeDelta::FromSeconds(db_flush_delay_seconds_), - base::Bind(&ObfuscatedFileUtil::DropDatabases, - base::Unretained(this))); - } -} - -void ObfuscatedFileUtil::DropDatabases() { - origin_database_.reset(); - STLDeleteContainerPairSecondPointers( - directories_.begin(), directories_.end()); - directories_.clear(); - timer_.reset(); -} - -bool ObfuscatedFileUtil::InitOriginDatabase(const GURL& origin_hint, - bool create) { - if (origin_database_) - return true; - - if (!create && !base::DirectoryExists(file_system_directory_)) - return false; - if (!base::CreateDirectory(file_system_directory_)) { - LOG(WARNING) << "Failed to create FileSystem directory: " << - file_system_directory_.value(); - return false; - } - - SandboxPrioritizedOriginDatabase* prioritized_origin_database = - new SandboxPrioritizedOriginDatabase(file_system_directory_, - env_override_); - origin_database_.reset(prioritized_origin_database); - - if (origin_hint.is_empty() || !HasIsolatedStorage(origin_hint)) - return true; - - const std::string isolated_origin_string = - storage::GetIdentifierFromOrigin(origin_hint); - - // TODO(kinuko): Deprecate this after a few release cycles, e.g. around M33. - base::FilePath isolated_origin_dir = file_system_directory_.Append( - SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory); - if (base::DirectoryExists(isolated_origin_dir) && - prioritized_origin_database->GetSandboxOriginDatabase()) { - SandboxIsolatedOriginDatabase::MigrateBackFromObsoleteOriginDatabase( - isolated_origin_string, - file_system_directory_, - prioritized_origin_database->GetSandboxOriginDatabase()); - } - - prioritized_origin_database->InitializePrimaryOrigin( - isolated_origin_string); - - return true; -} - -base::File::Error ObfuscatedFileUtil::GenerateNewLocalPath( - SandboxDirectoryDatabase* db, - FileSystemOperationContext* context, - const FileSystemURL& url, - base::FilePath* root, - base::FilePath* local_path) { - DCHECK(local_path); - int64 number; - if (!db || !db->GetNextInteger(&number)) - return base::File::FILE_ERROR_FAILED; - - base::File::Error error = base::File::FILE_OK; - *root = GetDirectoryForURL(url, false, &error); - if (error != base::File::FILE_OK) - return error; - - // We use the third- and fourth-to-last digits as the directory. - int64 directory_number = number % 10000 / 100; - base::FilePath new_local_path = root->AppendASCII( - base::StringPrintf("%02" PRId64, directory_number)); - - error = NativeFileUtil::CreateDirectory( - new_local_path, false /* exclusive */, false /* recursive */); - if (error != base::File::FILE_OK) - return error; - - *local_path = - new_local_path.AppendASCII(base::StringPrintf("%08" PRId64, number)); - return base::File::FILE_OK; -} - -base::File ObfuscatedFileUtil::CreateOrOpenInternal( - FileSystemOperationContext* context, - const FileSystemURL& url, int file_flags) { - DCHECK(!(file_flags & (base::File::FLAG_DELETE_ON_CLOSE | - base::File::FLAG_HIDDEN | base::File::FLAG_EXCLUSIVE_READ | - base::File::FLAG_EXCLUSIVE_WRITE))); - SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); - if (!db) - return base::File(base::File::FILE_ERROR_FAILED); - FileId file_id; - if (!db->GetFileWithPath(url.path(), &file_id)) { - // The file doesn't exist. - if (!(file_flags & (base::File::FLAG_CREATE | - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_OPEN_ALWAYS))) { - return base::File(base::File::FILE_ERROR_NOT_FOUND); - } - FileId parent_id; - if (!db->GetFileWithPath(VirtualPath::DirName(url.path()), &parent_id)) - return base::File(base::File::FILE_ERROR_NOT_FOUND); - FileInfo file_info; - InitFileInfo(&file_info, parent_id, - VirtualPath::BaseName(url.path()).value()); - - int64 growth = UsageForPath(file_info.name.size()); - if (!AllocateQuota(context, growth)) - return base::File(base::File::FILE_ERROR_NO_SPACE); - base::File file = CreateAndOpenFile(context, url, &file_info, file_flags); - if (file.IsValid()) { - UpdateUsage(context, url, growth); - context->change_observers()->Notify( - &FileChangeObserver::OnCreateFile, MakeTuple(url)); - } - return file.Pass(); - } - - if (file_flags & base::File::FLAG_CREATE) - return base::File(base::File::FILE_ERROR_EXISTS); - - base::File::Info platform_file_info; - base::FilePath local_path; - FileInfo file_info; - base::File::Error error = GetFileInfoInternal( - db, context, url, file_id, &file_info, &platform_file_info, &local_path); - if (error != base::File::FILE_OK) - return base::File(error); - if (file_info.is_directory()) - return base::File(base::File::FILE_ERROR_NOT_A_FILE); - - int64 delta = 0; - if (file_flags & (base::File::FLAG_CREATE_ALWAYS | - base::File::FLAG_OPEN_TRUNCATED)) { - // The file exists and we're truncating. - delta = -platform_file_info.size; - AllocateQuota(context, delta); - } - - base::File file = NativeFileUtil::CreateOrOpen(local_path, file_flags); - if (!file.IsValid()) { - error = file.error_details(); - if (error == base::File::FILE_ERROR_NOT_FOUND) { - // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker. - // TODO(tzik): Delete database entry after ensuring the file lost. - InvalidateUsageCache(context, url.origin(), url.type()); - LOG(WARNING) << "Lost a backing file."; - return base::File(base::File::FILE_ERROR_FAILED); - } - return file.Pass(); - } - - // If truncating we need to update the usage. - if (delta) { - UpdateUsage(context, url, delta); - context->change_observers()->Notify( - &FileChangeObserver::OnModifyFile, MakeTuple(url)); - } - return file.Pass(); -} - -bool ObfuscatedFileUtil::HasIsolatedStorage(const GURL& origin) { - return special_storage_policy_.get() && - special_storage_policy_->HasIsolatedStorage(origin); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/obfuscated_file_util.h b/webkit/browser/fileapi/obfuscated_file_util.h index aff2c7c..17d99c3 100644 --- a/webkit/browser/fileapi/obfuscated_file_util.h +++ b/webkit/browser/fileapi/obfuscated_file_util.h @@ -1,359 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_OBFUSCATED_FILE_UTIL_H_ -#define WEBKIT_BROWSER_FILEAPI_OBFUSCATED_FILE_UTIL_H_ - -#include <map> -#include <set> -#include <string> -#include <vector> - -#include "base/callback_forward.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/files/file_util_proxy.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/file_system_file_util.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/sandbox_directory_database.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/blob/shareable_file_reference.h" -#include "webkit/common/fileapi/file_system_types.h" - -namespace base { -class SequencedTaskRunner; -class TimeTicks; -} - -namespace content { -class ObfuscatedFileUtilTest; -class QuotaBackendImplTest; -} - -namespace storage { -class SpecialStoragePolicy; -} - -class GURL; - -namespace storage { - -class FileSystemOperationContext; -class SandboxOriginDatabaseInterface; -class TimedTaskHelper; - -// This file util stores directory information in LevelDB to obfuscate -// and to neutralize virtual file paths given by arbitrary apps. -// Files are stored with two-level isolation: per-origin and per-type. -// The isolation is done by storing data in separate directory partitions. -// For example, a file in Temporary file system for origin 'www.example.com' -// is stored in a different partition for a file in Persistent file system -// for the same origin, or for Temporary file system for another origin. -// -// * Per-origin directory name information is stored in a separate LevelDB, -// which is maintained by SandboxOriginDatabase. -// * Per-type directory name information is given by -// GetTypeStringForURLCallback that is given in CTOR. -// We use a small static mapping (e.g. 't' for Temporary type) for -// regular sandbox filesystems. -// -// The overall implementation philosophy of this class is that partial failures -// should leave us with an intact database; we'd prefer to leak the occasional -// backing file than have a database entry whose backing file is missing. When -// doing FSCK operations, if you find a loose backing file with no reference, -// you may safely delete it. -// -// This class must be deleted on the FILE thread, because that's where -// DropDatabases needs to be called. -class STORAGE_EXPORT_PRIVATE ObfuscatedFileUtil - : public FileSystemFileUtil { - public: - // Origin enumerator interface. - // An instance of this interface is assumed to be called on the file thread. - class AbstractOriginEnumerator { - public: - virtual ~AbstractOriginEnumerator() {} - - // Returns the next origin. Returns empty if there are no more origins. - virtual GURL Next() = 0; - - // Returns the current origin's information. - // |type_string| must be ascii string. - virtual bool HasTypeDirectory(const std::string& type_string) const = 0; - }; - - typedef base::Callback<std::string(const FileSystemURL&)> - GetTypeStringForURLCallback; - - // |get_type_string_for_url| is user-defined callback that should return - // a type string for the given FileSystemURL. The type string is used - // to provide per-type isolation in the sandboxed filesystem directory. - // Note that this method is called on file_task_runner. - // - // |known_type_strings| are known type string names that this file system - // should care about. - // This info is used to determine whether we could delete the entire - // origin directory or not in DeleteDirectoryForOriginAndType. If no directory - // for any known type exists the origin directory may get deleted when - // one origin/type pair is deleted. - // - ObfuscatedFileUtil(storage::SpecialStoragePolicy* special_storage_policy, - const base::FilePath& file_system_directory, - leveldb::Env* env_override, - base::SequencedTaskRunner* file_task_runner, - const GetTypeStringForURLCallback& get_type_string_for_url, - const std::set<std::string>& known_type_strings, - SandboxFileSystemBackendDelegate* sandbox_delegate); - virtual ~ObfuscatedFileUtil(); - - // FileSystemFileUtil overrides. - virtual base::File CreateOrOpen( - FileSystemOperationContext* context, - const FileSystemURL& url, - int file_flags) OVERRIDE; - virtual base::File::Error EnsureFileExists( - FileSystemOperationContext* context, - const FileSystemURL& url, bool* created) OVERRIDE; - virtual base::File::Error CreateDirectory( - FileSystemOperationContext* context, - const FileSystemURL& url, - bool exclusive, - bool recursive) OVERRIDE; - virtual base::File::Error GetFileInfo( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Info* file_info, - base::FilePath* platform_file) OVERRIDE; - virtual scoped_ptr<AbstractFileEnumerator> CreateFileEnumerator( - FileSystemOperationContext* context, - const FileSystemURL& root_url) OVERRIDE; - virtual base::File::Error GetLocalFilePath( - FileSystemOperationContext* context, - const FileSystemURL& file_system_url, - base::FilePath* local_path) OVERRIDE; - virtual base::File::Error Touch( - FileSystemOperationContext* context, - const FileSystemURL& url, - const base::Time& last_access_time, - const base::Time& last_modified_time) OVERRIDE; - virtual base::File::Error Truncate( - FileSystemOperationContext* context, - const FileSystemURL& url, - int64 length) OVERRIDE; - virtual base::File::Error CopyOrMoveFile( - FileSystemOperationContext* context, - const FileSystemURL& src_url, - const FileSystemURL& dest_url, - CopyOrMoveOption option, - bool copy) OVERRIDE; - virtual base::File::Error CopyInForeignFile( - FileSystemOperationContext* context, - const base::FilePath& src_file_path, - const FileSystemURL& dest_url) OVERRIDE; - virtual base::File::Error DeleteFile( - FileSystemOperationContext* context, - const FileSystemURL& url) OVERRIDE; - virtual base::File::Error DeleteDirectory( - FileSystemOperationContext* context, - const FileSystemURL& url) OVERRIDE; - virtual storage::ScopedFile CreateSnapshotFile( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Error* error, - base::File::Info* file_info, - base::FilePath* platform_path) OVERRIDE; - - // Same as the other CreateFileEnumerator, but with recursive support. - scoped_ptr<AbstractFileEnumerator> CreateFileEnumerator( - FileSystemOperationContext* context, - const FileSystemURL& root_url, - bool recursive); - - // Returns true if the directory |url| is empty. - bool IsDirectoryEmpty( - FileSystemOperationContext* context, - const FileSystemURL& url); - - // Gets the topmost directory specific to this origin and type. This will - // contain both the directory database's files and all the backing file - // subdirectories. - // Returns the topmost origin directory if |type_string| is empty. - // Returns an empty path if the directory is undefined. - // If the directory is defined, it will be returned, even if - // there is a file system error (e.g. the directory doesn't exist on disk and - // |create| is false). Callers should always check |error_code| to make sure - // the returned path is usable. - base::FilePath GetDirectoryForOriginAndType( - const GURL& origin, - const std::string& type_string, - bool create, - base::File::Error* error_code); - - // Deletes the topmost directory specific to this origin and type. This will - // delete its directory database. - // Deletes the topmost origin directory if |type_string| is empty. - bool DeleteDirectoryForOriginAndType( - const GURL& origin, - const std::string& type_string); - - // This method and all methods of its returned class must be called only on - // the FILE thread. The caller is responsible for deleting the returned - // object. - AbstractOriginEnumerator* CreateOriginEnumerator(); - - // Deletes a directory database from the database list in the ObfuscatedFSFU - // and destroys the database on the disk. - bool DestroyDirectoryDatabase(const GURL& origin, - const std::string& type_string); - - // Computes a cost for storing a given file in the obfuscated FSFU. - // As the cost of a file is independent of the cost of its parent directories, - // this ignores all but the BaseName of the supplied path. In order to - // compute the cost of adding a multi-segment directory recursively, call this - // on each path segment and add the results. - static int64 ComputeFilePathCost(const base::FilePath& path); - - // Tries to prepopulate directory database for the given type strings. - // This tries from the first one in the given type_strings and stops - // once it succeeds to do so for one database (i.e. it prepopulates - // at most one database). - void MaybePrepopulateDatabase( - const std::vector<std::string>& type_strings_to_prepopulate); - - private: - typedef SandboxDirectoryDatabase::FileId FileId; - typedef SandboxDirectoryDatabase::FileInfo FileInfo; - - friend class ObfuscatedFileEnumerator; - friend class content::ObfuscatedFileUtilTest; - friend class content::QuotaBackendImplTest; - - // Helper method to create an obfuscated file util for regular - // (temporary, persistent) file systems. Used only for testing. - // Note: this is implemented in sandbox_file_system_backend_delegate.cc. - static ObfuscatedFileUtil* CreateForTesting( - storage::SpecialStoragePolicy* special_storage_policy, - const base::FilePath& file_system_directory, - leveldb::Env* env_override, - base::SequencedTaskRunner* file_task_runner); - - base::FilePath GetDirectoryForURL( - const FileSystemURL& url, - bool create, - base::File::Error* error_code); - - // This just calls get_type_string_for_url_ callback that is given in ctor. - std::string CallGetTypeStringForURL(const FileSystemURL& url); - - base::File::Error GetFileInfoInternal( - SandboxDirectoryDatabase* db, - FileSystemOperationContext* context, - const FileSystemURL& url, - FileId file_id, - FileInfo* local_info, - base::File::Info* file_info, - base::FilePath* platform_file_path); - - // Creates a new file, both the underlying backing file and the entry in the - // database. |dest_file_info| is an in-out parameter. Supply the name and - // parent_id; data_path is ignored. On success, data_path will - // always be set to the relative path [from the root of the type-specific - // filesystem directory] of a NEW backing file. Returns the new file. - base::File CreateAndOpenFile( - FileSystemOperationContext* context, - const FileSystemURL& dest_url, - FileInfo* dest_file_info, - int file_flags); - - // The same as CreateAndOpenFile except that a file is not returned and if a - // path is provided in |source_path|, it will be used as a source from which - // to COPY data. - base::File::Error CreateFile( - FileSystemOperationContext* context, - const base::FilePath& source_file_path, - const FileSystemURL& dest_url, - FileInfo* dest_file_info); - - // Updates |db| and |dest_file_info| at the end of creating a new file. - base::File::Error CommitCreateFile( - const base::FilePath& root, - const base::FilePath& local_path, - SandboxDirectoryDatabase* db, - FileInfo* dest_file_info); - - // This converts from a relative path [as is stored in the FileInfo.data_path - // field] to an absolute platform path that can be given to the native - // filesystem. - base::FilePath DataPathToLocalPath( - const FileSystemURL& url, - const base::FilePath& data_file_path); - - std::string GetDirectoryDatabaseKey(const GURL& origin, - const std::string& type_string); - - // This returns NULL if |create| flag is false and a filesystem does not - // exist for the given |url|. - // For read operations |create| should be false. - SandboxDirectoryDatabase* GetDirectoryDatabase(const FileSystemURL& url, - bool create); - - // Gets the topmost directory specific to this origin. This will - // contain both the filesystem type subdirectories. - base::FilePath GetDirectoryForOrigin(const GURL& origin, - bool create, - base::File::Error* error_code); - - void InvalidateUsageCache(FileSystemOperationContext* context, - const GURL& origin, - FileSystemType type); - - void MarkUsed(); - void DropDatabases(); - - // Initializes the origin database. |origin_hint| may be used as a hint - // for initializing database if it's not empty. - bool InitOriginDatabase(const GURL& origin_hint, bool create); - - base::File::Error GenerateNewLocalPath( - SandboxDirectoryDatabase* db, - FileSystemOperationContext* context, - const FileSystemURL& url, - base::FilePath* root, - base::FilePath* local_path); - - base::File CreateOrOpenInternal( - FileSystemOperationContext* context, - const FileSystemURL& url, - int file_flags); - - bool HasIsolatedStorage(const GURL& origin); - - typedef std::map<std::string, SandboxDirectoryDatabase*> DirectoryMap; - DirectoryMap directories_; - scoped_ptr<SandboxOriginDatabaseInterface> origin_database_; - scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_; - base::FilePath file_system_directory_; - leveldb::Env* env_override_; - - // Used to delete database after a certain period of inactivity. - int64 db_flush_delay_seconds_; - - scoped_refptr<base::SequencedTaskRunner> file_task_runner_; - scoped_ptr<TimedTaskHelper> timer_; - - GetTypeStringForURLCallback get_type_string_for_url_; - std::set<std::string> known_type_strings_; - - // Not owned. - SandboxFileSystemBackendDelegate* sandbox_delegate_; - - DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtil); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_OBFUSCATED_FILE_UTIL_H_ +#include "storage/browser/fileapi/obfuscated_file_util.h" diff --git a/webkit/browser/fileapi/open_file_system_mode.h b/webkit/browser/fileapi/open_file_system_mode.h index 3bc352f..40e9fd9 100644 --- a/webkit/browser/fileapi/open_file_system_mode.h +++ b/webkit/browser/fileapi/open_file_system_mode.h @@ -1,22 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_OPEN_FILE_SYSTEM_MODE_H_ -#define WEBKIT_BROWSER_FILEAPI_OPEN_FILE_SYSTEM_MODE_H_ - -namespace storage { - -// Determines the behavior on OpenFileSystem when a specified -// FileSystem does not exist. -// Specifying CREATE_IF_NONEXISTENT may make actual modification on -// disk (e.g. creating a root directory, setting up a metadata database etc) -// if the filesystem hasn't been initialized. -enum OpenFileSystemMode { - OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, - OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_OPEN_FILE_SYSTEM_MODE_H_ +#include "storage/browser/fileapi/open_file_system_mode.h" diff --git a/webkit/browser/fileapi/plugin_private_file_system_backend.cc b/webkit/browser/fileapi/plugin_private_file_system_backend.cc deleted file mode 100644 index 0a3cbf9..0000000 --- a/webkit/browser/fileapi/plugin_private_file_system_backend.cc +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright 2013 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/browser/fileapi/plugin_private_file_system_backend.h" - -#include <map> - -#include "base/stl_util.h" -#include "base/synchronization/lock.h" -#include "base/task_runner_util.h" -#include "net/base/net_util.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/async_file_util_adapter.h" -#include "webkit/browser/fileapi/file_stream_writer.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_options.h" -#include "webkit/browser/fileapi/isolated_context.h" -#include "webkit/browser/fileapi/obfuscated_file_util.h" -#include "webkit/browser/fileapi/quota/quota_reservation.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace storage { - -class PluginPrivateFileSystemBackend::FileSystemIDToPluginMap { - public: - explicit FileSystemIDToPluginMap(base::SequencedTaskRunner* task_runner) - : task_runner_(task_runner) {} - ~FileSystemIDToPluginMap() {} - - std::string GetPluginIDForURL(const FileSystemURL& url) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - Map::iterator found = map_.find(url.filesystem_id()); - if (url.type() != kFileSystemTypePluginPrivate || found == map_.end()) { - NOTREACHED() << "Unsupported url is given: " << url.DebugString(); - return std::string(); - } - return found->second; - } - - void RegisterFileSystem(const std::string& filesystem_id, - const std::string& plugin_id) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - DCHECK(!filesystem_id.empty()); - DCHECK(!ContainsKey(map_, filesystem_id)) << filesystem_id; - map_[filesystem_id] = plugin_id; - } - - void RemoveFileSystem(const std::string& filesystem_id) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - map_.erase(filesystem_id); - } - - private: - typedef std::map<std::string, std::string> Map; - scoped_refptr<base::SequencedTaskRunner> task_runner_; - Map map_; -}; - -namespace { - -const base::FilePath::CharType* kFileSystemDirectory = - SandboxFileSystemBackendDelegate::kFileSystemDirectory; -const base::FilePath::CharType* kPluginPrivateDirectory = - FILE_PATH_LITERAL("Plugins"); - -base::File::Error OpenFileSystemOnFileTaskRunner( - ObfuscatedFileUtil* file_util, - PluginPrivateFileSystemBackend::FileSystemIDToPluginMap* plugin_map, - const GURL& origin_url, - const std::string& filesystem_id, - const std::string& plugin_id, - OpenFileSystemMode mode) { - base::File::Error error = base::File::FILE_ERROR_FAILED; - const bool create = (mode == OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT); - file_util->GetDirectoryForOriginAndType( - origin_url, plugin_id, create, &error); - if (error == base::File::FILE_OK) - plugin_map->RegisterFileSystem(filesystem_id, plugin_id); - return error; -} - -} // namespace - -PluginPrivateFileSystemBackend::PluginPrivateFileSystemBackend( - base::SequencedTaskRunner* file_task_runner, - const base::FilePath& profile_path, - storage::SpecialStoragePolicy* special_storage_policy, - const FileSystemOptions& file_system_options) - : file_task_runner_(file_task_runner), - file_system_options_(file_system_options), - base_path_(profile_path.Append(kFileSystemDirectory) - .Append(kPluginPrivateDirectory)), - plugin_map_(new FileSystemIDToPluginMap(file_task_runner)), - weak_factory_(this) { - file_util_.reset( - new AsyncFileUtilAdapter(new ObfuscatedFileUtil( - special_storage_policy, - base_path_, file_system_options.env_override(), - file_task_runner, - base::Bind(&FileSystemIDToPluginMap::GetPluginIDForURL, - base::Owned(plugin_map_)), - std::set<std::string>(), - NULL))); -} - -PluginPrivateFileSystemBackend::~PluginPrivateFileSystemBackend() { - if (!file_task_runner_->RunsTasksOnCurrentThread()) { - AsyncFileUtil* file_util = file_util_.release(); - if (!file_task_runner_->DeleteSoon(FROM_HERE, file_util)) - delete file_util; - } -} - -void PluginPrivateFileSystemBackend::OpenPrivateFileSystem( - const GURL& origin_url, - FileSystemType type, - const std::string& filesystem_id, - const std::string& plugin_id, - OpenFileSystemMode mode, - const StatusCallback& callback) { - if (!CanHandleType(type) || file_system_options_.is_incognito()) { - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, base::Bind(callback, base::File::FILE_ERROR_SECURITY)); - return; - } - - PostTaskAndReplyWithResult( - file_task_runner_.get(), - FROM_HERE, - base::Bind(&OpenFileSystemOnFileTaskRunner, - obfuscated_file_util(), plugin_map_, - origin_url, filesystem_id, plugin_id, mode), - callback); -} - -bool PluginPrivateFileSystemBackend::CanHandleType(FileSystemType type) const { - return type == kFileSystemTypePluginPrivate; -} - -void PluginPrivateFileSystemBackend::Initialize(FileSystemContext* context) { -} - -void PluginPrivateFileSystemBackend::ResolveURL( - const FileSystemURL& url, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) { - // We never allow opening a new plugin-private filesystem via usual - // ResolveURL. - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, - base::Bind(callback, GURL(), std::string(), - base::File::FILE_ERROR_SECURITY)); -} - -AsyncFileUtil* -PluginPrivateFileSystemBackend::GetAsyncFileUtil(FileSystemType type) { - return file_util_.get(); -} - -WatcherManager* PluginPrivateFileSystemBackend::GetWatcherManager( - FileSystemType type) { - return NULL; -} - -CopyOrMoveFileValidatorFactory* -PluginPrivateFileSystemBackend::GetCopyOrMoveFileValidatorFactory( - FileSystemType type, - base::File::Error* error_code) { - DCHECK(error_code); - *error_code = base::File::FILE_OK; - return NULL; -} - -FileSystemOperation* PluginPrivateFileSystemBackend::CreateFileSystemOperation( - const FileSystemURL& url, - FileSystemContext* context, - base::File::Error* error_code) const { - scoped_ptr<FileSystemOperationContext> operation_context( - new FileSystemOperationContext(context)); - return FileSystemOperation::Create(url, context, operation_context.Pass()); -} - -bool PluginPrivateFileSystemBackend::SupportsStreaming( - const storage::FileSystemURL& url) const { - return false; -} - -bool PluginPrivateFileSystemBackend::HasInplaceCopyImplementation( - storage::FileSystemType type) const { - return false; -} - -scoped_ptr<storage::FileStreamReader> -PluginPrivateFileSystemBackend::CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time, - FileSystemContext* context) const { - return scoped_ptr<storage::FileStreamReader>(); -} - -scoped_ptr<FileStreamWriter> -PluginPrivateFileSystemBackend::CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset, - FileSystemContext* context) const { - return scoped_ptr<FileStreamWriter>(); -} - -FileSystemQuotaUtil* PluginPrivateFileSystemBackend::GetQuotaUtil() { - return this; -} - -base::File::Error -PluginPrivateFileSystemBackend::DeleteOriginDataOnFileTaskRunner( - FileSystemContext* context, - storage::QuotaManagerProxy* proxy, - const GURL& origin_url, - FileSystemType type) { - if (!CanHandleType(type)) - return base::File::FILE_ERROR_SECURITY; - bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType( - origin_url, std::string()); - if (result) - return base::File::FILE_OK; - return base::File::FILE_ERROR_FAILED; -} - -void PluginPrivateFileSystemBackend::GetOriginsForTypeOnFileTaskRunner( - FileSystemType type, - std::set<GURL>* origins) { - if (!CanHandleType(type)) - return; - scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator( - obfuscated_file_util()->CreateOriginEnumerator()); - GURL origin; - while (!(origin = enumerator->Next()).is_empty()) - origins->insert(origin); -} - -void PluginPrivateFileSystemBackend::GetOriginsForHostOnFileTaskRunner( - FileSystemType type, - const std::string& host, - std::set<GURL>* origins) { - if (!CanHandleType(type)) - return; - scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator( - obfuscated_file_util()->CreateOriginEnumerator()); - GURL origin; - while (!(origin = enumerator->Next()).is_empty()) { - if (host == net::GetHostOrSpecFromURL(origin)) - origins->insert(origin); - } -} - -int64 PluginPrivateFileSystemBackend::GetOriginUsageOnFileTaskRunner( - FileSystemContext* context, - const GURL& origin_url, - FileSystemType type) { - // We don't track usage on this filesystem. - return 0; -} - -scoped_refptr<QuotaReservation> -PluginPrivateFileSystemBackend::CreateQuotaReservationOnFileTaskRunner( - const GURL& origin_url, - FileSystemType type) { - // We don't track usage on this filesystem. - NOTREACHED(); - return scoped_refptr<QuotaReservation>(); -} - -void PluginPrivateFileSystemBackend::AddFileUpdateObserver( - FileSystemType type, - FileUpdateObserver* observer, - base::SequencedTaskRunner* task_runner) {} - -void PluginPrivateFileSystemBackend::AddFileChangeObserver( - FileSystemType type, - FileChangeObserver* observer, - base::SequencedTaskRunner* task_runner) {} - -void PluginPrivateFileSystemBackend::AddFileAccessObserver( - FileSystemType type, - FileAccessObserver* observer, - base::SequencedTaskRunner* task_runner) {} - -const UpdateObserverList* PluginPrivateFileSystemBackend::GetUpdateObservers( - FileSystemType type) const { - return NULL; -} - -const ChangeObserverList* PluginPrivateFileSystemBackend::GetChangeObservers( - FileSystemType type) const { - return NULL; -} - -const AccessObserverList* PluginPrivateFileSystemBackend::GetAccessObservers( - FileSystemType type) const { - return NULL; -} - -ObfuscatedFileUtil* PluginPrivateFileSystemBackend::obfuscated_file_util() { - return static_cast<ObfuscatedFileUtil*>( - static_cast<AsyncFileUtilAdapter*>(file_util_.get())->sync_file_util()); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/plugin_private_file_system_backend.h b/webkit/browser/fileapi/plugin_private_file_system_backend.h index bd95bc9..86b19a4 100644 --- a/webkit/browser/fileapi/plugin_private_file_system_backend.h +++ b/webkit/browser/fileapi/plugin_private_file_system_backend.h @@ -1,149 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_PLUGIN_PRIVATE_FILE_SYSTEM_BACKEND_H_ -#define WEBKIT_BROWSER_FILEAPI_PLUGIN_PRIVATE_FILE_SYSTEM_BACKEND_H_ - -#include <set> -#include <string> - -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "webkit/browser/fileapi/file_system_backend.h" -#include "webkit/browser/fileapi/file_system_options.h" -#include "webkit/browser/fileapi/file_system_quota_util.h" - -namespace base { -class SequencedTaskRunner; -} - -namespace content { -class PluginPrivateFileSystemBackendTest; -} - -namespace storage { -class SpecialStoragePolicy; -} - -namespace storage { - -class ObfuscatedFileUtil; -class WatcherManager; - -class STORAGE_EXPORT PluginPrivateFileSystemBackend - : public FileSystemBackend, - public FileSystemQuotaUtil { - public: - class FileSystemIDToPluginMap; - typedef base::Callback<void(base::File::Error result)> StatusCallback; - - PluginPrivateFileSystemBackend( - base::SequencedTaskRunner* file_task_runner, - const base::FilePath& profile_path, - storage::SpecialStoragePolicy* special_storage_policy, - const FileSystemOptions& file_system_options); - virtual ~PluginPrivateFileSystemBackend(); - - // This must be used to open 'private' filesystem instead of regular - // OpenFileSystem. - // |plugin_id| must be an identifier string for per-plugin - // isolation, e.g. name, MIME type etc. - // NOTE: |plugin_id| must be sanitized ASCII string that doesn't - // include *any* dangerous character like '/'. - void OpenPrivateFileSystem( - const GURL& origin_url, - FileSystemType type, - const std::string& filesystem_id, - const std::string& plugin_id, - OpenFileSystemMode mode, - const StatusCallback& callback); - - // FileSystemBackend overrides. - virtual bool CanHandleType(FileSystemType type) const OVERRIDE; - virtual void Initialize(FileSystemContext* context) OVERRIDE; - virtual void ResolveURL(const FileSystemURL& url, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; - virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE; - virtual WatcherManager* GetWatcherManager(FileSystemType type) OVERRIDE; - virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( - FileSystemType type, - base::File::Error* error_code) OVERRIDE; - virtual FileSystemOperation* CreateFileSystemOperation( - const FileSystemURL& url, - FileSystemContext* context, - base::File::Error* error_code) const OVERRIDE; - virtual bool SupportsStreaming(const FileSystemURL& url) const OVERRIDE; - virtual bool HasInplaceCopyImplementation( - storage::FileSystemType type) const OVERRIDE; - virtual scoped_ptr<storage::FileStreamReader> CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time, - FileSystemContext* context) const OVERRIDE; - virtual scoped_ptr<FileStreamWriter> CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset, - FileSystemContext* context) const OVERRIDE; - virtual FileSystemQuotaUtil* GetQuotaUtil() OVERRIDE; - - // FileSystemQuotaUtil overrides. - virtual base::File::Error DeleteOriginDataOnFileTaskRunner( - FileSystemContext* context, - storage::QuotaManagerProxy* proxy, - const GURL& origin_url, - FileSystemType type) OVERRIDE; - virtual void GetOriginsForTypeOnFileTaskRunner( - FileSystemType type, - std::set<GURL>* origins) OVERRIDE; - virtual void GetOriginsForHostOnFileTaskRunner( - FileSystemType type, - const std::string& host, - std::set<GURL>* origins) OVERRIDE; - virtual int64 GetOriginUsageOnFileTaskRunner( - FileSystemContext* context, - const GURL& origin_url, - FileSystemType type) OVERRIDE; - virtual scoped_refptr<QuotaReservation> - CreateQuotaReservationOnFileTaskRunner( - const GURL& origin_url, - FileSystemType type) OVERRIDE; - virtual void AddFileUpdateObserver( - FileSystemType type, - FileUpdateObserver* observer, - base::SequencedTaskRunner* task_runner) OVERRIDE; - virtual void AddFileChangeObserver( - FileSystemType type, - FileChangeObserver* observer, - base::SequencedTaskRunner* task_runner) OVERRIDE; - virtual void AddFileAccessObserver( - FileSystemType type, - FileAccessObserver* observer, - base::SequencedTaskRunner* task_runner) OVERRIDE; - virtual const UpdateObserverList* GetUpdateObservers( - FileSystemType type) const OVERRIDE; - virtual const ChangeObserverList* GetChangeObservers( - FileSystemType type) const OVERRIDE; - virtual const AccessObserverList* GetAccessObservers( - FileSystemType type) const OVERRIDE; - - private: - friend class content::PluginPrivateFileSystemBackendTest; - - ObfuscatedFileUtil* obfuscated_file_util(); - const base::FilePath& base_path() const { return base_path_; } - - scoped_refptr<base::SequencedTaskRunner> file_task_runner_; - const FileSystemOptions file_system_options_; - const base::FilePath base_path_; - scoped_ptr<AsyncFileUtil> file_util_; - FileSystemIDToPluginMap* plugin_map_; // Owned by file_util_. - base::WeakPtrFactory<PluginPrivateFileSystemBackend> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(PluginPrivateFileSystemBackend); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_PLUGIN_PRIVATE_FILE_SYSTEM_BACKEND_H_ +#include "storage/browser/fileapi/plugin_private_file_system_backend.h" diff --git a/webkit/browser/fileapi/quota/open_file_handle.cc b/webkit/browser/fileapi/quota/open_file_handle.cc deleted file mode 100644 index b8c0b29..0000000 --- a/webkit/browser/fileapi/quota/open_file_handle.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013 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/browser/fileapi/quota/open_file_handle.h" - -#include "webkit/browser/fileapi/quota/open_file_handle_context.h" -#include "webkit/browser/fileapi/quota/quota_reservation.h" - -namespace storage { - -OpenFileHandle::~OpenFileHandle() { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); -} - -void OpenFileHandle::UpdateMaxWrittenOffset(int64 offset) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - - int64 growth = context_->UpdateMaxWrittenOffset(offset); - if (growth > 0) - reservation_->ConsumeReservation(growth); -} - -void OpenFileHandle::AddAppendModeWriteAmount(int64 amount) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - if (amount <= 0) - return; - - context_->AddAppendModeWriteAmount(amount); - reservation_->ConsumeReservation(amount); -} - -int64 OpenFileHandle::GetEstimatedFileSize() const { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - return context_->GetEstimatedFileSize(); -} - -int64 OpenFileHandle::GetMaxWrittenOffset() const { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - return context_->GetMaxWrittenOffset(); -} - -const base::FilePath& OpenFileHandle::platform_path() const { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - return context_->platform_path(); -} - -OpenFileHandle::OpenFileHandle(QuotaReservation* reservation, - OpenFileHandleContext* context) - : reservation_(reservation), - context_(context) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/quota/open_file_handle.h b/webkit/browser/fileapi/quota/open_file_handle.h index d54c033..361b86e 100644 --- a/webkit/browser/fileapi/quota/open_file_handle.h +++ b/webkit/browser/fileapi/quota/open_file_handle.h @@ -1,70 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_QUOTA_OPEN_FILE_HANDLE_H_ -#define WEBKIT_BROWSER_FILEAPI_QUOTA_OPEN_FILE_HANDLE_H_ - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class FilePath; -} - -namespace storage { - -class QuotaReservation; -class OpenFileHandleContext; -class QuotaReservationBuffer; - -// Represents an open file like a file descriptor. -// This should be alive while a consumer keeps a file opened and should be -// deleted when the plugin closes the file. -class STORAGE_EXPORT OpenFileHandle { - public: - ~OpenFileHandle(); - - // Updates cached file size and consumes quota for that. - // Both this and AddAppendModeWriteAmount should be called for each modified - // file before calling QuotaReservation::RefreshQuota and before closing the - // file. - void UpdateMaxWrittenOffset(int64 offset); - - // Notifies that |amount| of data is written to the file in append mode, and - // consumes quota for that. - // Both this and UpdateMaxWrittenOffset should be called for each modified - // file before calling QuotaReservation::RefreshQuota and before closing the - // file. - void AddAppendModeWriteAmount(int64 amount); - - // Returns the estimated file size for the quota consumption calculation. - // The client must consume its reserved quota when it writes data to the file - // beyond the estimated file size. - // The estimated file size is greater than or equal to actual file size after - // all clients report their file usage, and is monotonically increasing over - // OpenFileHandle object life cycle, so that client may cache the value. - int64 GetEstimatedFileSize() const; - - int64 GetMaxWrittenOffset() const; - const base::FilePath& platform_path() const; - - private: - friend class QuotaReservationBuffer; - - OpenFileHandle(QuotaReservation* reservation, - OpenFileHandleContext* context); - - scoped_refptr<QuotaReservation> reservation_; - scoped_refptr<OpenFileHandleContext> context_; - - base::SequenceChecker sequence_checker_; - - DISALLOW_COPY_AND_ASSIGN(OpenFileHandle); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_QUOTA_OPEN_FILE_HANDLE_H_ +#include "storage/browser/fileapi/quota/open_file_handle.h" diff --git a/webkit/browser/fileapi/quota/open_file_handle_context.cc b/webkit/browser/fileapi/quota/open_file_handle_context.cc deleted file mode 100644 index afc338e..0000000 --- a/webkit/browser/fileapi/quota/open_file_handle_context.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2013 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/browser/fileapi/quota/open_file_handle_context.h" - -#include "base/files/file_util.h" -#include "webkit/browser/fileapi/quota/quota_reservation_buffer.h" - -namespace storage { - -OpenFileHandleContext::OpenFileHandleContext( - const base::FilePath& platform_path, - QuotaReservationBuffer* reservation_buffer) - : initial_file_size_(0), - maximum_written_offset_(0), - append_mode_write_amount_(0), - platform_path_(platform_path), - reservation_buffer_(reservation_buffer) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - - base::GetFileSize(platform_path, &initial_file_size_); - maximum_written_offset_ = initial_file_size_; -} - -int64 OpenFileHandleContext::UpdateMaxWrittenOffset(int64 offset) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - if (offset <= maximum_written_offset_) - return 0; - - int64 growth = offset - maximum_written_offset_; - maximum_written_offset_ = offset; - return growth; -} - -void OpenFileHandleContext::AddAppendModeWriteAmount(int64 amount) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - append_mode_write_amount_ += amount; -} - -int64 OpenFileHandleContext::GetEstimatedFileSize() const { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - return maximum_written_offset_ + append_mode_write_amount_; -} - -int64 OpenFileHandleContext::GetMaxWrittenOffset() const { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - return maximum_written_offset_; -} - -OpenFileHandleContext::~OpenFileHandleContext() { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - - // TODO(tzik): Optimize this for single operation. - - int64 file_size = 0; - base::GetFileSize(platform_path_, &file_size); - int64 usage_delta = file_size - initial_file_size_; - - // |reserved_quota_consumption| may be greater than the recorded file growth - // when a plugin crashed before reporting its consumption. - // In this case, the reserved quota for the plugin should be handled as - // consumed quota. - int64 reserved_quota_consumption = - std::max(GetEstimatedFileSize(), file_size) - initial_file_size_; - - reservation_buffer_->CommitFileGrowth( - reserved_quota_consumption, usage_delta); - reservation_buffer_->DetachOpenFileHandleContext(this); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/quota/open_file_handle_context.h b/webkit/browser/fileapi/quota/open_file_handle_context.h index 86ecab2..f6543cd 100644 --- a/webkit/browser/fileapi/quota/open_file_handle_context.h +++ b/webkit/browser/fileapi/quota/open_file_handle_context.h @@ -1,61 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_OPEN_FILE_HANDLE_CONTEXT_H_ -#define WEBKIT_BROWSER_FILEAPI_OPEN_FILE_HANDLE_CONTEXT_H_ - -#include <map> - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "url/gurl.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_types.h" - -namespace storage { - -class QuotaReservationBuffer; - -// This class represents a underlying file of a managed FileSystem file. -// The instance keeps alive while at least one consumer keeps an open file -// handle. -// This class is usually manipulated only via OpenFileHandle. -class OpenFileHandleContext : public base::RefCounted<OpenFileHandleContext> { - public: - OpenFileHandleContext(const base::FilePath& platform_path, - QuotaReservationBuffer* reservation_buffer); - - // Updates the max written offset and returns the amount of growth. - int64 UpdateMaxWrittenOffset(int64 offset); - - void AddAppendModeWriteAmount(int64 amount); - - const base::FilePath& platform_path() const { - return platform_path_; - } - - int64 GetEstimatedFileSize() const; - int64 GetMaxWrittenOffset() const; - - private: - friend class base::RefCounted<OpenFileHandleContext>; - virtual ~OpenFileHandleContext(); - - int64 initial_file_size_; - int64 maximum_written_offset_; - int64 append_mode_write_amount_; - base::FilePath platform_path_; - - scoped_refptr<QuotaReservationBuffer> reservation_buffer_; - - base::SequenceChecker sequence_checker_; - - DISALLOW_COPY_AND_ASSIGN(OpenFileHandleContext); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_OPEN_FILE_HANDLE_CONTEXT_H_ +#include "storage/browser/fileapi/quota/open_file_handle_context.h" diff --git a/webkit/browser/fileapi/quota/quota_backend_impl.cc b/webkit/browser/fileapi/quota/quota_backend_impl.cc deleted file mode 100644 index deb100e..0000000 --- a/webkit/browser/fileapi/quota/quota_backend_impl.cc +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2013 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/browser/fileapi/quota/quota_backend_impl.h" - -#include <string> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/numerics/safe_conversions.h" -#include "base/sequenced_task_runner.h" -#include "webkit/browser/fileapi/file_system_usage_cache.h" -#include "webkit/browser/quota/quota_client.h" -#include "webkit/browser/quota/quota_manager_proxy.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace storage { - -QuotaBackendImpl::QuotaBackendImpl( - base::SequencedTaskRunner* file_task_runner, - ObfuscatedFileUtil* obfuscated_file_util, - FileSystemUsageCache* file_system_usage_cache, - storage::QuotaManagerProxy* quota_manager_proxy) - : file_task_runner_(file_task_runner), - obfuscated_file_util_(obfuscated_file_util), - file_system_usage_cache_(file_system_usage_cache), - quota_manager_proxy_(quota_manager_proxy), - weak_ptr_factory_(this) { -} - -QuotaBackendImpl::~QuotaBackendImpl() { -} - -void QuotaBackendImpl::ReserveQuota(const GURL& origin, - FileSystemType type, - int64 delta, - const ReserveQuotaCallback& callback) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(origin.is_valid()); - if (!delta) { - callback.Run(base::File::FILE_OK, 0); - return; - } - DCHECK(quota_manager_proxy_.get()); - quota_manager_proxy_->GetUsageAndQuota( - file_task_runner_.get(), - origin, - FileSystemTypeToQuotaStorageType(type), - base::Bind(&QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota, - weak_ptr_factory_.GetWeakPtr(), - QuotaReservationInfo(origin, type, delta), - callback)); -} - -void QuotaBackendImpl::ReleaseReservedQuota(const GURL& origin, - FileSystemType type, - int64 size) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(origin.is_valid()); - DCHECK_LE(0, size); - if (!size) - return; - ReserveQuotaInternal(QuotaReservationInfo(origin, type, -size)); -} - -void QuotaBackendImpl::CommitQuotaUsage(const GURL& origin, - FileSystemType type, - int64 delta) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(origin.is_valid()); - if (!delta) - return; - ReserveQuotaInternal(QuotaReservationInfo(origin, type, delta)); - base::FilePath path; - if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK) - return; - bool result = file_system_usage_cache_->AtomicUpdateUsageByDelta(path, delta); - DCHECK(result); -} - -void QuotaBackendImpl::IncrementDirtyCount(const GURL& origin, - FileSystemType type) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(origin.is_valid()); - base::FilePath path; - if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK) - return; - DCHECK(file_system_usage_cache_); - file_system_usage_cache_->IncrementDirty(path); -} - -void QuotaBackendImpl::DecrementDirtyCount(const GURL& origin, - FileSystemType type) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(origin.is_valid()); - base::FilePath path; - if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK) - return; - DCHECK(file_system_usage_cache_); - file_system_usage_cache_->DecrementDirty(path); -} - -void QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota( - const QuotaReservationInfo& info, - const ReserveQuotaCallback& callback, - storage::QuotaStatusCode status, - int64 usage, - int64 quota) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(info.origin.is_valid()); - DCHECK_LE(0, usage); - DCHECK_LE(0, quota); - if (status != storage::kQuotaStatusOk) { - callback.Run(base::File::FILE_ERROR_FAILED, 0); - return; - } - - QuotaReservationInfo normalized_info = info; - if (info.delta > 0) { - int64 new_usage = - base::saturated_cast<int64>(usage + static_cast<uint64>(info.delta)); - if (quota < new_usage) - new_usage = quota; - normalized_info.delta = std::max(static_cast<int64>(0), new_usage - usage); - } - - ReserveQuotaInternal(normalized_info); - if (callback.Run(base::File::FILE_OK, normalized_info.delta)) - return; - // The requester could not accept the reserved quota. Revert it. - ReserveQuotaInternal( - QuotaReservationInfo(normalized_info.origin, - normalized_info.type, - -normalized_info.delta)); -} - -void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(info.origin.is_valid()); - DCHECK(quota_manager_proxy_.get()); - quota_manager_proxy_->NotifyStorageModified( - storage::QuotaClient::kFileSystem, - info.origin, - FileSystemTypeToQuotaStorageType(info.type), - info.delta); -} - -base::File::Error QuotaBackendImpl::GetUsageCachePath( - const GURL& origin, - FileSystemType type, - base::FilePath* usage_file_path) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(origin.is_valid()); - DCHECK(usage_file_path); - base::File::Error error = base::File::FILE_OK; - *usage_file_path = - SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType( - obfuscated_file_util_, origin, type, &error); - return error; -} - -QuotaBackendImpl::QuotaReservationInfo::QuotaReservationInfo( - const GURL& origin, FileSystemType type, int64 delta) - : origin(origin), type(type), delta(delta) { -} - -QuotaBackendImpl::QuotaReservationInfo::~QuotaReservationInfo() { -} - -} // namespace storage diff --git a/webkit/browser/fileapi/quota/quota_backend_impl.h b/webkit/browser/fileapi/quota/quota_backend_impl.h index 033a61a..b6a153e 100644 --- a/webkit/browser/fileapi/quota/quota_backend_impl.h +++ b/webkit/browser/fileapi/quota/quota_backend_impl.h @@ -1,106 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_QUOTA_QUOTA_BACKEND_IMPL_H_ -#define WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_BACKEND_IMPL_H_ - -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "webkit/browser/fileapi/quota/quota_reservation_manager.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/quota/quota_status_code.h" - -namespace base { -class SequencedTaskRunner; -} - -namespace content { -class QuotaBackendImplTest; -} - -namespace storage { -class QuotaManagerProxy; -} - -namespace storage { - -class FileSystemUsageCache; -class ObfuscatedFileUtil; - -// An instance of this class is owned by QuotaReservationManager. -class STORAGE_EXPORT QuotaBackendImpl - : public QuotaReservationManager::QuotaBackend { - public: - typedef QuotaReservationManager::ReserveQuotaCallback - ReserveQuotaCallback; - - QuotaBackendImpl(base::SequencedTaskRunner* file_task_runner, - ObfuscatedFileUtil* obfuscated_file_util, - FileSystemUsageCache* file_system_usage_cache, - storage::QuotaManagerProxy* quota_manager_proxy); - virtual ~QuotaBackendImpl(); - - // QuotaReservationManager::QuotaBackend overrides. - virtual void ReserveQuota( - const GURL& origin, - FileSystemType type, - int64 delta, - const ReserveQuotaCallback& callback) OVERRIDE; - virtual void ReleaseReservedQuota( - const GURL& origin, - FileSystemType type, - int64 size) OVERRIDE; - virtual void CommitQuotaUsage( - const GURL& origin, - FileSystemType type, - int64 delta) OVERRIDE; - virtual void IncrementDirtyCount( - const GURL& origin, - FileSystemType type) OVERRIDE; - virtual void DecrementDirtyCount( - const GURL& origin, - FileSystemType type) OVERRIDE; - - private: - friend class content::QuotaBackendImplTest; - - struct QuotaReservationInfo { - QuotaReservationInfo(const GURL& origin, FileSystemType type, int64 delta); - ~QuotaReservationInfo(); - - GURL origin; - FileSystemType type; - int64 delta; - }; - - void DidGetUsageAndQuotaForReserveQuota(const QuotaReservationInfo& info, - const ReserveQuotaCallback& callback, - storage::QuotaStatusCode status, - int64 usage, - int64 quota); - - void ReserveQuotaInternal( - const QuotaReservationInfo& info); - base::File::Error GetUsageCachePath( - const GURL& origin, - FileSystemType type, - base::FilePath* usage_file_path); - - scoped_refptr<base::SequencedTaskRunner> file_task_runner_; - - // Owned by SandboxFileSystemBackendDelegate. - ObfuscatedFileUtil* obfuscated_file_util_; - FileSystemUsageCache* file_system_usage_cache_; - - scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; - - base::WeakPtrFactory<QuotaBackendImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(QuotaBackendImpl); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_BACKEND_IMPL_H_ +#include "storage/browser/fileapi/quota/quota_backend_impl.h" diff --git a/webkit/browser/fileapi/quota/quota_reservation.cc b/webkit/browser/fileapi/quota/quota_reservation.cc deleted file mode 100644 index 5139d0b..0000000 --- a/webkit/browser/fileapi/quota/quota_reservation.cc +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2013 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/browser/fileapi/quota/quota_reservation.h" - -#include "base/bind.h" -#include "webkit/browser/fileapi/quota/open_file_handle.h" -#include "webkit/browser/fileapi/quota/quota_reservation_buffer.h" - -namespace storage { - -void QuotaReservation::RefreshReservation( - int64 size, - const StatusCallback& callback) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - DCHECK(!running_refresh_request_); - DCHECK(!client_crashed_); - if (!reservation_manager()) - return; - - running_refresh_request_ = true; - - reservation_manager()->ReserveQuota( - origin(), type(), size - remaining_quota_, - base::Bind(&QuotaReservation::AdaptDidUpdateReservedQuota, - weak_ptr_factory_.GetWeakPtr(), - remaining_quota_, callback)); - - if (running_refresh_request_) - remaining_quota_ = 0; -} - -scoped_ptr<OpenFileHandle> QuotaReservation::GetOpenFileHandle( - const base::FilePath& platform_path) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - DCHECK(!client_crashed_); - return reservation_buffer_->GetOpenFileHandle(this, platform_path); -} - -void QuotaReservation::OnClientCrash() { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - client_crashed_ = true; - - if (remaining_quota_) { - reservation_buffer_->PutReservationToBuffer(remaining_quota_); - remaining_quota_ = 0; - } -} - -void QuotaReservation::ConsumeReservation(int64 size) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - DCHECK_LT(0, size); - DCHECK_LE(size, remaining_quota_); - if (client_crashed_) - return; - - remaining_quota_ -= size; - reservation_buffer_->PutReservationToBuffer(size); -} - -QuotaReservationManager* QuotaReservation::reservation_manager() { - return reservation_buffer_->reservation_manager(); -} - -const GURL& QuotaReservation::origin() const { - return reservation_buffer_->origin(); -} - -FileSystemType QuotaReservation::type() const { - return reservation_buffer_->type(); -} - -QuotaReservation::QuotaReservation( - QuotaReservationBuffer* reservation_buffer) - : client_crashed_(false), - running_refresh_request_(false), - remaining_quota_(0), - reservation_buffer_(reservation_buffer), - weak_ptr_factory_(this) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); -} - -QuotaReservation::~QuotaReservation() { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - - if (remaining_quota_ && reservation_manager()) { - reservation_manager()->ReleaseReservedQuota( - origin(), type(), remaining_quota_); - } -} - -// static -bool QuotaReservation::AdaptDidUpdateReservedQuota( - const base::WeakPtr<QuotaReservation>& reservation, - int64 previous_size, - const StatusCallback& callback, - base::File::Error error, - int64 delta) { - if (!reservation) - return false; - - return reservation->DidUpdateReservedQuota( - previous_size, callback, error, delta); -} - -bool QuotaReservation::DidUpdateReservedQuota( - int64 previous_size, - const StatusCallback& callback, - base::File::Error error, - int64 delta) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - DCHECK(running_refresh_request_); - running_refresh_request_ = false; - - if (client_crashed_) { - callback.Run(base::File::FILE_ERROR_ABORT); - return false; - } - - if (error == base::File::FILE_OK) - remaining_quota_ = previous_size + delta; - callback.Run(error); - return true; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/quota/quota_reservation.h b/webkit/browser/fileapi/quota/quota_reservation.h index edde151..f44071c 100644 --- a/webkit/browser/fileapi/quota/quota_reservation.h +++ b/webkit/browser/fileapi/quota/quota_reservation.h @@ -1,95 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_H_ -#define WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_H_ - -#include "base/basictypes.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "webkit/browser/fileapi/quota/quota_reservation_manager.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_types.h" - -class GURL; - -namespace storage { - -class QuotaReservationBuffer; -class OpenFileHandle; - -// Represents a unit of quota reservation. -class STORAGE_EXPORT QuotaReservation - : public base::RefCounted<QuotaReservation> { - public: - typedef base::Callback<void(base::File::Error error)> StatusCallback; - - // Reclaims unused quota and reserves another |size| of quota. So that the - // resulting new |remaining_quota_| will be same as |size| as far as available - // space is enough. |remaining_quota_| may be less than |size| if there is - // not enough space available. - // Invokes |callback| upon completion. - void RefreshReservation(int64 size, const StatusCallback& callback); - - // Associates |platform_path| to the QuotaReservation instance. - // Returns an OpenFileHandle instance that represents a quota managed file. - scoped_ptr<OpenFileHandle> GetOpenFileHandle( - const base::FilePath& platform_path); - - // Should be called when the associated client is crashed. - // This implies the client can no longer report its consumption of the - // reserved quota. - // QuotaReservation puts all remaining quota to the QuotaReservationBuffer, so - // that the remaining quota will be reclaimed after all open files associated - // to the origin and type. - void OnClientCrash(); - - // Consumes |size| of reserved quota for a associated file. - // Consumed quota is sent to associated QuotaReservationBuffer for staging. - void ConsumeReservation(int64 size); - - // Returns amount of unused reserved quota. - int64 remaining_quota() const { return remaining_quota_; } - - QuotaReservationManager* reservation_manager(); - const GURL& origin() const; - FileSystemType type() const; - - private: - friend class QuotaReservationBuffer; - - // Use QuotaReservationManager as the entry point. - explicit QuotaReservation(QuotaReservationBuffer* reservation_buffer); - - friend class base::RefCounted<QuotaReservation>; - virtual ~QuotaReservation(); - - static bool AdaptDidUpdateReservedQuota( - const base::WeakPtr<QuotaReservation>& reservation, - int64 previous_size, - const StatusCallback& callback, - base::File::Error error, - int64 delta); - bool DidUpdateReservedQuota(int64 previous_size, - const StatusCallback& callback, - base::File::Error error, - int64 delta); - - bool client_crashed_; - bool running_refresh_request_; - int64 remaining_quota_; - - scoped_refptr<QuotaReservationBuffer> reservation_buffer_; - - base::SequenceChecker sequence_checker_; - base::WeakPtrFactory<QuotaReservation> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(QuotaReservation); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_H_ +#include "storage/browser/fileapi/quota/quota_reservation.h" diff --git a/webkit/browser/fileapi/quota/quota_reservation_buffer.cc b/webkit/browser/fileapi/quota/quota_reservation_buffer.cc deleted file mode 100644 index cfa567f..0000000 --- a/webkit/browser/fileapi/quota/quota_reservation_buffer.cc +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2013 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/browser/fileapi/quota/quota_reservation_buffer.h" - -#include "base/bind.h" -#include "webkit/browser/fileapi/quota/open_file_handle.h" -#include "webkit/browser/fileapi/quota/open_file_handle_context.h" -#include "webkit/browser/fileapi/quota/quota_reservation.h" - -namespace storage { - -QuotaReservationBuffer::QuotaReservationBuffer( - base::WeakPtr<QuotaReservationManager> reservation_manager, - const GURL& origin, - FileSystemType type) - : reservation_manager_(reservation_manager), - origin_(origin), - type_(type), - reserved_quota_(0) { - DCHECK(origin.is_valid()); - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - reservation_manager_->IncrementDirtyCount(origin, type); -} - -scoped_refptr<QuotaReservation> QuotaReservationBuffer::CreateReservation() { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - return make_scoped_refptr(new QuotaReservation(this)); -} - -scoped_ptr<OpenFileHandle> QuotaReservationBuffer::GetOpenFileHandle( - QuotaReservation* reservation, - const base::FilePath& platform_path) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - OpenFileHandleContext** open_file = &open_files_[platform_path]; - if (!*open_file) - *open_file = new OpenFileHandleContext(platform_path, this); - return make_scoped_ptr(new OpenFileHandle(reservation, *open_file)); -} - -void QuotaReservationBuffer::CommitFileGrowth(int64 reserved_quota_consumption, - int64 usage_delta) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - if (!reservation_manager_) - return; - reservation_manager_->CommitQuotaUsage(origin_, type_, usage_delta); - - if (reserved_quota_consumption > 0) { - if (reserved_quota_consumption > reserved_quota_) { - LOG(ERROR) << "Detected over consumption of the storage quota beyond its" - << " reservation"; - reserved_quota_consumption = reserved_quota_; - } - - reserved_quota_ -= reserved_quota_consumption; - reservation_manager_->ReleaseReservedQuota( - origin_, type_, reserved_quota_consumption); - } -} - -void QuotaReservationBuffer::DetachOpenFileHandleContext( - OpenFileHandleContext* open_file) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - DCHECK_EQ(open_file, open_files_[open_file->platform_path()]); - open_files_.erase(open_file->platform_path()); -} - -void QuotaReservationBuffer::PutReservationToBuffer(int64 reservation) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - DCHECK_LE(0, reservation); - reserved_quota_ += reservation; -} - -QuotaReservationBuffer::~QuotaReservationBuffer() { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - if (!reservation_manager_) - return; - - DCHECK_LE(0, reserved_quota_); - if (reserved_quota_ && reservation_manager_) { - reservation_manager_->ReserveQuota( - origin_, type_, -reserved_quota_, - base::Bind(&QuotaReservationBuffer::DecrementDirtyCount, - reservation_manager_, origin_, type_)); - } - reservation_manager_->ReleaseReservationBuffer(this); -} - -// static -bool QuotaReservationBuffer::DecrementDirtyCount( - base::WeakPtr<QuotaReservationManager> reservation_manager, - const GURL& origin, - FileSystemType type, - base::File::Error error, - int64 delta_unused) { - DCHECK(origin.is_valid()); - if (error == base::File::FILE_OK && reservation_manager) { - reservation_manager->DecrementDirtyCount(origin, type); - return true; - } - return false; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/quota/quota_reservation_buffer.h b/webkit/browser/fileapi/quota/quota_reservation_buffer.h index 89b6e22..e7fe3f0 100644 --- a/webkit/browser/fileapi/quota/quota_reservation_buffer.h +++ b/webkit/browser/fileapi/quota/quota_reservation_buffer.h @@ -1,87 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_BUFFER_H_ -#define WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_BUFFER_H_ - -#include <map> - -#include "base/basictypes.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "url/gurl.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_types.h" - -namespace storage { - -class QuotaReservation; -class OpenFileHandle; -class OpenFileHandleContext; -class QuotaReservationManager; - -// QuotaReservationBuffer manages QuotaReservation instances. All consumed -// quota and leaked quota by associated QuotaReservation will be staged in -// QuotaReservationBuffer, and will be committed on a modified file is closed. -// The instance keeps alive while any associated QuotaReservation or -// OpenFileHandle alive. -// This class is usually manipulated only via OpenFileHandle and -// QuotaReservation. -class QuotaReservationBuffer : public base::RefCounted<QuotaReservationBuffer> { - public: - QuotaReservationBuffer( - base::WeakPtr<QuotaReservationManager> reservation_manager, - const GURL& origin, - FileSystemType type); - - scoped_refptr<QuotaReservation> CreateReservation(); - scoped_ptr<OpenFileHandle> GetOpenFileHandle( - QuotaReservation* reservation, - const base::FilePath& platform_path); - void CommitFileGrowth(int64 quota_consumption, int64 usage_delta); - void DetachOpenFileHandleContext(OpenFileHandleContext* context); - void PutReservationToBuffer(int64 size); - - QuotaReservationManager* reservation_manager() { - return reservation_manager_.get(); - } - - const GURL& origin() const { return origin_; } - FileSystemType type() const { return type_; } - - private: - friend class base::RefCounted<QuotaReservationBuffer>; - virtual ~QuotaReservationBuffer(); - - static bool DecrementDirtyCount( - base::WeakPtr<QuotaReservationManager> reservation_manager, - const GURL& origin, - FileSystemType type, - base::File::Error error, - int64 delta); - - typedef std::map<base::FilePath, OpenFileHandleContext*> - OpenFileHandleContextByPath; - - // Not owned. The destructor of OpenFileHandler should erase itself from - // |open_files_|. - OpenFileHandleContextByPath open_files_; - - base::WeakPtr<QuotaReservationManager> reservation_manager_; - - GURL origin_; - storage::FileSystemType type_; - - int64 reserved_quota_; - - base::SequenceChecker sequence_checker_; - - DISALLOW_COPY_AND_ASSIGN(QuotaReservationBuffer); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_BUFFER_H_ +#include "storage/browser/fileapi/quota/quota_reservation_buffer.h" diff --git a/webkit/browser/fileapi/quota/quota_reservation_manager.cc b/webkit/browser/fileapi/quota/quota_reservation_manager.cc deleted file mode 100644 index 6ab2c26..0000000 --- a/webkit/browser/fileapi/quota/quota_reservation_manager.cc +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2013 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/browser/fileapi/quota/quota_reservation_manager.h" - -#include "webkit/browser/fileapi/quota/quota_reservation.h" -#include "webkit/browser/fileapi/quota/quota_reservation_buffer.h" - -namespace storage { - -QuotaReservationManager::QuotaReservationManager( - scoped_ptr<QuotaBackend> backend) - : backend_(backend.Pass()), - weak_ptr_factory_(this) { - sequence_checker_.DetachFromSequence(); -} - -QuotaReservationManager::~QuotaReservationManager() { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); -} - -void QuotaReservationManager::ReserveQuota( - const GURL& origin, - FileSystemType type, - int64 size, - const ReserveQuotaCallback& callback) { - DCHECK(origin.is_valid()); - backend_->ReserveQuota(origin, type, size, callback); -} - -void QuotaReservationManager::ReleaseReservedQuota( - const GURL& origin, - FileSystemType type, - int64 size) { - DCHECK(origin.is_valid()); - backend_->ReleaseReservedQuota(origin, type, size); -} - -void QuotaReservationManager::CommitQuotaUsage( - const GURL& origin, - FileSystemType type, - int64 delta) { - DCHECK(origin.is_valid()); - backend_->CommitQuotaUsage(origin, type, delta); -} - -void QuotaReservationManager::IncrementDirtyCount(const GURL& origin, - FileSystemType type) { - DCHECK(origin.is_valid()); - backend_->IncrementDirtyCount(origin, type); -} - -void QuotaReservationManager::DecrementDirtyCount(const GURL& origin, - FileSystemType type) { - DCHECK(origin.is_valid()); - backend_->DecrementDirtyCount(origin, type); -} - -scoped_refptr<QuotaReservationBuffer> -QuotaReservationManager::GetReservationBuffer( - const GURL& origin, - FileSystemType type) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - DCHECK(origin.is_valid()); - QuotaReservationBuffer** buffer = - &reservation_buffers_[std::make_pair(origin, type)]; - if (!*buffer) { - *buffer = new QuotaReservationBuffer( - weak_ptr_factory_.GetWeakPtr(), origin, type); - } - return make_scoped_refptr(*buffer); -} - -void QuotaReservationManager::ReleaseReservationBuffer( - QuotaReservationBuffer* reservation_buffer) { - DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - std::pair<GURL, FileSystemType> key(reservation_buffer->origin(), - reservation_buffer->type()); - DCHECK_EQ(reservation_buffers_[key], reservation_buffer); - reservation_buffers_.erase(key); -} - -scoped_refptr<QuotaReservation> QuotaReservationManager::CreateReservation( - const GURL& origin, - FileSystemType type) { - DCHECK(origin.is_valid()); - return GetReservationBuffer(origin, type)->CreateReservation();; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/quota/quota_reservation_manager.h b/webkit/browser/fileapi/quota/quota_reservation_manager.h index 30e1801..cf2a126 100644 --- a/webkit/browser/fileapi/quota/quota_reservation_manager.h +++ b/webkit/browser/fileapi/quota/quota_reservation_manager.h @@ -1,127 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_MANAGER_H_ -#define WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_MANAGER_H_ - -#include <map> -#include <utility> - -#include "base/basictypes.h" -#include "base/callback_forward.h" -#include "base/files/file.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "url/gurl.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/fileapi/file_system_types.h" - -namespace content { -class QuotaReservationManagerTest; -} - -namespace storage { - -class QuotaReservation; -class QuotaReservationBuffer; -class OpenFileHandle; -class OpenFileHandleContext; - -class STORAGE_EXPORT QuotaReservationManager { - public: - // Callback for ReserveQuota. When this callback returns false, ReserveQuota - // operation should be reverted. - typedef base::Callback<bool(base::File::Error error, int64 delta)> - ReserveQuotaCallback; - - // An abstraction of backing quota system. - class STORAGE_EXPORT QuotaBackend { - public: - QuotaBackend() {} - virtual ~QuotaBackend() {} - - // Reserves or reclaims |delta| of quota for |origin| and |type| pair. - // Reserved quota should be counted as usage, but it should be on-memory - // and be cleared by a browser restart. - // Invokes |callback| upon completion with an error code. - // |callback| should return false if it can't accept the reservation, in - // that case, the backend should roll back the reservation. - virtual void ReserveQuota(const GURL& origin, - FileSystemType type, - int64 delta, - const ReserveQuotaCallback& callback) = 0; - - // Reclaims |size| of quota for |origin| and |type|. - virtual void ReleaseReservedQuota(const GURL& origin, - FileSystemType type, - int64 size) = 0; - - // Updates disk usage of |origin| and |type|. - // Invokes |callback| upon completion with an error code. - virtual void CommitQuotaUsage(const GURL& origin, - FileSystemType type, - int64 delta) = 0; - - virtual void IncrementDirtyCount(const GURL& origin, - FileSystemType type) = 0; - virtual void DecrementDirtyCount(const GURL& origin, - FileSystemType type) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(QuotaBackend); - }; - - explicit QuotaReservationManager(scoped_ptr<QuotaBackend> backend); - ~QuotaReservationManager(); - - // The entry point of the quota reservation. Creates new reservation object - // for |origin| and |type|. - scoped_refptr<QuotaReservation> CreateReservation( - const GURL& origin, - FileSystemType type); - - private: - typedef std::map<std::pair<GURL, FileSystemType>, QuotaReservationBuffer*> - ReservationBufferByOriginAndType; - - friend class QuotaReservation; - friend class QuotaReservationBuffer; - friend class content::QuotaReservationManagerTest; - - void ReserveQuota(const GURL& origin, - FileSystemType type, - int64 delta, - const ReserveQuotaCallback& callback); - - void ReleaseReservedQuota(const GURL& origin, - FileSystemType type, - int64 size); - - void CommitQuotaUsage(const GURL& origin, - FileSystemType type, - int64 delta); - - void IncrementDirtyCount(const GURL& origin, FileSystemType type); - void DecrementDirtyCount(const GURL& origin, FileSystemType type); - - scoped_refptr<QuotaReservationBuffer> GetReservationBuffer( - const GURL& origin, - FileSystemType type); - void ReleaseReservationBuffer(QuotaReservationBuffer* reservation_pool); - - scoped_ptr<QuotaBackend> backend_; - - // Not owned. The destructor of ReservationBuffer should erase itself from - // |reservation_buffers_| by calling ReleaseReservationBuffer. - ReservationBufferByOriginAndType reservation_buffers_; - - base::SequenceChecker sequence_checker_; - base::WeakPtrFactory<QuotaReservationManager> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(QuotaReservationManager); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_MANAGER_H_ +#include "storage/browser/fileapi/quota/quota_reservation_manager.h" diff --git a/webkit/browser/fileapi/recursive_operation_delegate.cc b/webkit/browser/fileapi/recursive_operation_delegate.cc deleted file mode 100644 index 7836b32..0000000 --- a/webkit/browser/fileapi/recursive_operation_delegate.cc +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (c) 2013 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/browser/fileapi/recursive_operation_delegate.h" - -#include "base/bind.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_runner.h" - -namespace storage { - -namespace { -// Don't start too many inflight operations. -const int kMaxInflightOperations = 5; -} - -RecursiveOperationDelegate::RecursiveOperationDelegate( - FileSystemContext* file_system_context) - : file_system_context_(file_system_context), - inflight_operations_(0), - canceled_(false) { -} - -RecursiveOperationDelegate::~RecursiveOperationDelegate() { -} - -void RecursiveOperationDelegate::Cancel() { - canceled_ = true; - OnCancel(); -} - -void RecursiveOperationDelegate::StartRecursiveOperation( - const FileSystemURL& root, - const StatusCallback& callback) { - DCHECK(pending_directory_stack_.empty()); - DCHECK(pending_files_.empty()); - DCHECK_EQ(0, inflight_operations_); - - callback_ = callback; - ++inflight_operations_; - ProcessFile( - root, - base::Bind(&RecursiveOperationDelegate::DidTryProcessFile, - AsWeakPtr(), root)); -} - -FileSystemOperationRunner* RecursiveOperationDelegate::operation_runner() { - return file_system_context_->operation_runner(); -} - -void RecursiveOperationDelegate::OnCancel() { -} - -void RecursiveOperationDelegate::DidTryProcessFile( - const FileSystemURL& root, - base::File::Error error) { - DCHECK(pending_directory_stack_.empty()); - DCHECK(pending_files_.empty()); - DCHECK_EQ(1, inflight_operations_); - - --inflight_operations_; - if (canceled_ || error != base::File::FILE_ERROR_NOT_A_FILE) { - Done(error); - return; - } - - pending_directory_stack_.push(std::queue<FileSystemURL>()); - pending_directory_stack_.top().push(root); - ProcessNextDirectory(); -} - -void RecursiveOperationDelegate::ProcessNextDirectory() { - DCHECK(pending_files_.empty()); - DCHECK(!pending_directory_stack_.empty()); - DCHECK(!pending_directory_stack_.top().empty()); - DCHECK_EQ(0, inflight_operations_); - - const FileSystemURL& url = pending_directory_stack_.top().front(); - - ++inflight_operations_; - ProcessDirectory( - url, - base::Bind( - &RecursiveOperationDelegate::DidProcessDirectory, AsWeakPtr())); -} - -void RecursiveOperationDelegate::DidProcessDirectory( - base::File::Error error) { - DCHECK(pending_files_.empty()); - DCHECK(!pending_directory_stack_.empty()); - DCHECK(!pending_directory_stack_.top().empty()); - DCHECK_EQ(1, inflight_operations_); - - --inflight_operations_; - if (canceled_ || error != base::File::FILE_OK) { - Done(error); - return; - } - - const FileSystemURL& parent = pending_directory_stack_.top().front(); - pending_directory_stack_.push(std::queue<FileSystemURL>()); - operation_runner()->ReadDirectory( - parent, - base::Bind(&RecursiveOperationDelegate::DidReadDirectory, - AsWeakPtr(), parent)); -} - -void RecursiveOperationDelegate::DidReadDirectory( - const FileSystemURL& parent, - base::File::Error error, - const FileEntryList& entries, - bool has_more) { - DCHECK(!pending_directory_stack_.empty()); - DCHECK_EQ(0, inflight_operations_); - - if (canceled_ || error != base::File::FILE_OK) { - Done(error); - return; - } - - for (size_t i = 0; i < entries.size(); i++) { - FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( - parent.origin(), - parent.mount_type(), - parent.virtual_path().Append(entries[i].name)); - if (entries[i].is_directory) - pending_directory_stack_.top().push(url); - else - pending_files_.push(url); - } - - // Wait for next entries. - if (has_more) - return; - - ProcessPendingFiles(); -} - -void RecursiveOperationDelegate::ProcessPendingFiles() { - DCHECK(!pending_directory_stack_.empty()); - - if ((pending_files_.empty() || canceled_) && inflight_operations_ == 0) { - ProcessSubDirectory(); - return; - } - - // Do not post any new tasks. - if (canceled_) - return; - - // Run ProcessFile in parallel (upto kMaxInflightOperations). - scoped_refptr<base::MessageLoopProxy> current_message_loop = - base::MessageLoopProxy::current(); - while (!pending_files_.empty() && - inflight_operations_ < kMaxInflightOperations) { - ++inflight_operations_; - current_message_loop->PostTask( - FROM_HERE, - base::Bind(&RecursiveOperationDelegate::ProcessFile, - AsWeakPtr(), pending_files_.front(), - base::Bind(&RecursiveOperationDelegate::DidProcessFile, - AsWeakPtr()))); - pending_files_.pop(); - } -} - -void RecursiveOperationDelegate::DidProcessFile( - base::File::Error error) { - --inflight_operations_; - if (error != base::File::FILE_OK) { - // If an error occurs, invoke Done immediately (even if there remain - // running operations). It is because in the callback, this instance is - // deleted. - Done(error); - return; - } - - ProcessPendingFiles(); -} - -void RecursiveOperationDelegate::ProcessSubDirectory() { - DCHECK(pending_files_.empty()); - DCHECK(!pending_directory_stack_.empty()); - DCHECK_EQ(0, inflight_operations_); - - if (canceled_) { - Done(base::File::FILE_ERROR_ABORT); - return; - } - - if (!pending_directory_stack_.top().empty()) { - // There remain some sub directories. Process them first. - ProcessNextDirectory(); - return; - } - - // All subdirectories are processed. - pending_directory_stack_.pop(); - if (pending_directory_stack_.empty()) { - // All files/directories are processed. - Done(base::File::FILE_OK); - return; - } - - DCHECK(!pending_directory_stack_.top().empty()); - ++inflight_operations_; - PostProcessDirectory( - pending_directory_stack_.top().front(), - base::Bind(&RecursiveOperationDelegate::DidPostProcessDirectory, - AsWeakPtr())); -} - -void RecursiveOperationDelegate::DidPostProcessDirectory( - base::File::Error error) { - DCHECK(pending_files_.empty()); - DCHECK(!pending_directory_stack_.empty()); - DCHECK(!pending_directory_stack_.top().empty()); - DCHECK_EQ(1, inflight_operations_); - - --inflight_operations_; - pending_directory_stack_.top().pop(); - if (canceled_ || error != base::File::FILE_OK) { - Done(error); - return; - } - - ProcessSubDirectory(); -} - -void RecursiveOperationDelegate::Done(base::File::Error error) { - if (canceled_ && error == base::File::FILE_OK) { - callback_.Run(base::File::FILE_ERROR_ABORT); - } else { - callback_.Run(error); - } -} - -} // namespace storage diff --git a/webkit/browser/fileapi/recursive_operation_delegate.h b/webkit/browser/fileapi/recursive_operation_delegate.h index 6386632..b1fbd66 100644 --- a/webkit/browser/fileapi/recursive_operation_delegate.h +++ b/webkit/browser/fileapi/recursive_operation_delegate.h @@ -1,152 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_RECURSIVE_OPERATION_DELEGATE_H_ -#define WEBKIT_BROWSER_FILEAPI_RECURSIVE_OPERATION_DELEGATE_H_ - -#include <queue> -#include <stack> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/memory/weak_ptr.h" -#include "webkit/browser/fileapi/file_system_operation.h" -#include "webkit/browser/fileapi/file_system_url.h" - -namespace storage { - -class FileSystemContext; -class FileSystemOperationRunner; - -// A base class for recursive operation delegates. -// -// In short, each subclass should override ProcessFile and ProcessDirectory -// to process a directory or a file. To start the recursive operation it -// should also call StartRecursiveOperation. -class STORAGE_EXPORT RecursiveOperationDelegate - : public base::SupportsWeakPtr<RecursiveOperationDelegate> { - public: - typedef FileSystemOperation::StatusCallback StatusCallback; - typedef FileSystemOperation::FileEntryList FileEntryList; - - virtual ~RecursiveOperationDelegate(); - - // This is called when the consumer of this instance starts a non-recursive - // operation. - virtual void Run() = 0; - - // This is called when the consumer of this instance starts a recursive - // operation. - virtual void RunRecursively() = 0; - - // This is called each time a file is found while recursively - // performing an operation. - virtual void ProcessFile(const FileSystemURL& url, - const StatusCallback& callback) = 0; - - // This is called each time a directory is found while recursively - // performing an operation. - virtual void ProcessDirectory(const FileSystemURL& url, - const StatusCallback& callback) = 0; - - - // This is called each time after files and subdirectories for a - // directory is processed while recursively performing an operation. - virtual void PostProcessDirectory(const FileSystemURL& url, - const StatusCallback& callback) = 0; - - // Cancels the currently running operation. - void Cancel(); - - protected: - explicit RecursiveOperationDelegate(FileSystemContext* file_system_context); - - // Starts to process files/directories recursively from the given |root|. - // This will call ProcessFile and ProcessDirectory on each file or directory. - // - // First, this tries to call ProcessFile with |root| regardless whether it is - // actually a file or a directory. If it is a directory, ProcessFile should - // return File::FILE_NOT_A_FILE. - // - // For each directory, the recursive operation works as follows: - // ProcessDirectory is called first for the directory. - // Then the directory contents are read (to obtain its sub directories and - // files in it). - // ProcessFile is called for found files. This may run in parallel. - // The same step is recursively applied to each subdirectory. - // After all files and subdirectories in a directory are processed, - // PostProcessDirectory is called for the directory. - // Here is an example; - // a_dir/ -+- b1_dir/ -+- c1_dir/ -+- d1_file - // | | | - // | +- c2_file +- d2_file - // | - // +- b2_dir/ --- e_dir/ - // | - // +- b3_file - // | - // +- b4_file - // Then traverse order is: - // ProcessFile(a_dir) (This should return File::FILE_NOT_A_FILE). - // ProcessDirectory(a_dir). - // ProcessFile(b3_file), ProcessFile(b4_file). (in parallel). - // ProcessDirectory(b1_dir). - // ProcessFile(c2_file) - // ProcessDirectory(c1_dir). - // ProcessFile(d1_file), ProcessFile(d2_file). (in parallel). - // PostProcessDirectory(c1_dir) - // PostProcessDirectory(b1_dir). - // ProcessDirectory(b2_dir) - // ProcessDirectory(e_dir) - // PostProcessDirectory(e_dir) - // PostProcessDirectory(b2_dir) - // PostProcessDirectory(a_dir) - // - // |callback| is fired with base::File::FILE_OK when every file/directory - // under |root| is processed, or fired earlier when any suboperation fails. - void StartRecursiveOperation(const FileSystemURL& root, - const StatusCallback& callback); - - FileSystemContext* file_system_context() { return file_system_context_; } - const FileSystemContext* file_system_context() const { - return file_system_context_; - } - - FileSystemOperationRunner* operation_runner(); - - // Called when Cancel() is called. This is a hook to do something more - // in a derived class. By default, do nothing. - virtual void OnCancel(); - - private: - void DidTryProcessFile(const FileSystemURL& root, - base::File::Error error); - void ProcessNextDirectory(); - void DidProcessDirectory(base::File::Error error); - void DidReadDirectory(const FileSystemURL& parent, - base::File::Error error, - const FileEntryList& entries, - bool has_more); - void ProcessPendingFiles(); - void DidProcessFile(base::File::Error error); - void ProcessSubDirectory(); - void DidPostProcessDirectory(base::File::Error error); - - // Called when all recursive operation is done (or an error occurs). - void Done(base::File::Error error); - - FileSystemContext* file_system_context_; - StatusCallback callback_; - std::stack<FileSystemURL> pending_directories_; - std::stack<std::queue<FileSystemURL> > pending_directory_stack_; - std::queue<FileSystemURL> pending_files_; - int inflight_operations_; - bool canceled_; - - DISALLOW_COPY_AND_ASSIGN(RecursiveOperationDelegate); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_RECURSIVE_OPERATION_DELEGATE_H_ +#include "storage/browser/fileapi/recursive_operation_delegate.h" diff --git a/webkit/browser/fileapi/remove_operation_delegate.cc b/webkit/browser/fileapi/remove_operation_delegate.cc deleted file mode 100644 index 8e645cd..0000000 --- a/webkit/browser/fileapi/remove_operation_delegate.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2013 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/browser/fileapi/remove_operation_delegate.h" - -#include "base/bind.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_runner.h" - -namespace storage { - -RemoveOperationDelegate::RemoveOperationDelegate( - FileSystemContext* file_system_context, - const FileSystemURL& url, - const StatusCallback& callback) - : RecursiveOperationDelegate(file_system_context), - url_(url), - callback_(callback), - weak_factory_(this) { -} - -RemoveOperationDelegate::~RemoveOperationDelegate() {} - -void RemoveOperationDelegate::Run() { - operation_runner()->RemoveFile(url_, base::Bind( - &RemoveOperationDelegate::DidTryRemoveFile, weak_factory_.GetWeakPtr())); -} - -void RemoveOperationDelegate::RunRecursively() { - StartRecursiveOperation(url_, callback_); -} - -void RemoveOperationDelegate::ProcessFile(const FileSystemURL& url, - const StatusCallback& callback) { - operation_runner()->RemoveFile( - url, - base::Bind(&RemoveOperationDelegate::DidRemoveFile, - weak_factory_.GetWeakPtr(), callback)); -} - -void RemoveOperationDelegate::ProcessDirectory(const FileSystemURL& url, - const StatusCallback& callback) { - callback.Run(base::File::FILE_OK); -} - -void RemoveOperationDelegate::PostProcessDirectory( - const FileSystemURL& url, const StatusCallback& callback) { - operation_runner()->RemoveDirectory(url, callback); -} - -void RemoveOperationDelegate::DidTryRemoveFile(base::File::Error error) { - if (error != base::File::FILE_ERROR_NOT_A_FILE && - error != base::File::FILE_ERROR_SECURITY) { - callback_.Run(error); - return; - } - operation_runner()->RemoveDirectory( - url_, - base::Bind(&RemoveOperationDelegate::DidTryRemoveDirectory, - weak_factory_.GetWeakPtr(), error)); -} - -void RemoveOperationDelegate::DidTryRemoveDirectory( - base::File::Error remove_file_error, - base::File::Error remove_directory_error) { - callback_.Run( - remove_directory_error == base::File::FILE_ERROR_NOT_A_DIRECTORY ? - remove_file_error : - remove_directory_error); -} - -void RemoveOperationDelegate::DidRemoveFile(const StatusCallback& callback, - base::File::Error error) { - if (error == base::File::FILE_ERROR_NOT_FOUND) { - callback.Run(base::File::FILE_OK); - return; - } - callback.Run(error); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/remove_operation_delegate.h b/webkit/browser/fileapi/remove_operation_delegate.h index 57380a3..2a7bea3 100644 --- a/webkit/browser/fileapi/remove_operation_delegate.h +++ b/webkit/browser/fileapi/remove_operation_delegate.h @@ -1,46 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_REMOVE_OPERATION_DELEGATE_H_ -#define WEBKIT_BROWSER_FILEAPI_REMOVE_OPERATION_DELEGATE_H_ - -#include <stack> - -#include "webkit/browser/fileapi/recursive_operation_delegate.h" - -namespace storage { - -class RemoveOperationDelegate : public RecursiveOperationDelegate { - public: - RemoveOperationDelegate(FileSystemContext* file_system_context, - const FileSystemURL& url, - const StatusCallback& callback); - virtual ~RemoveOperationDelegate(); - - // RecursiveOperationDelegate overrides: - virtual void Run() OVERRIDE; - virtual void RunRecursively() OVERRIDE; - virtual void ProcessFile(const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void ProcessDirectory(const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - virtual void PostProcessDirectory(const FileSystemURL& url, - const StatusCallback& callback) OVERRIDE; - - private: - void DidTryRemoveFile(base::File::Error error); - void DidTryRemoveDirectory(base::File::Error remove_file_error, - base::File::Error remove_directory_error); - void DidRemoveFile(const StatusCallback& callback, - base::File::Error error); - - FileSystemURL url_; - StatusCallback callback_; - base::WeakPtrFactory<RemoveOperationDelegate> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(RemoveOperationDelegate); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_REMOVE_OPERATION_DELEGATE_H_ +#include "storage/browser/fileapi/remove_operation_delegate.h" diff --git a/webkit/browser/fileapi/sandbox_directory_database.cc b/webkit/browser/fileapi/sandbox_directory_database.cc deleted file mode 100644 index 600562e..0000000 --- a/webkit/browser/fileapi/sandbox_directory_database.cc +++ /dev/null @@ -1,939 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/sandbox_directory_database.h" - -#include <math.h> -#include <algorithm> -#include <set> -#include <stack> - -#include "base/files/file_enumerator.h" -#include "base/files/file_util.h" -#include "base/location.h" -#include "base/metrics/histogram.h" -#include "base/pickle.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "third_party/leveldatabase/src/include/leveldb/db.h" -#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" -#include "webkit/browser/fileapi/file_system_usage_cache.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace { - -bool PickleFromFileInfo(const storage::SandboxDirectoryDatabase::FileInfo& info, - Pickle* pickle) { - DCHECK(pickle); - std::string data_path; - // Round off here to match the behavior of the filesystem on real files. - base::Time time = - base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT())); - std::string name; - - data_path = storage::FilePathToString(info.data_path); - name = storage::FilePathToString(base::FilePath(info.name)); - - if (pickle->WriteInt64(info.parent_id) && - pickle->WriteString(data_path) && - pickle->WriteString(name) && - pickle->WriteInt64(time.ToInternalValue())) - return true; - - NOTREACHED(); - return false; -} - -bool FileInfoFromPickle(const Pickle& pickle, - storage::SandboxDirectoryDatabase::FileInfo* info) { - PickleIterator iter(pickle); - std::string data_path; - std::string name; - int64 internal_time; - - if (pickle.ReadInt64(&iter, &info->parent_id) && - pickle.ReadString(&iter, &data_path) && - pickle.ReadString(&iter, &name) && - pickle.ReadInt64(&iter, &internal_time)) { - info->data_path = storage::StringToFilePath(data_path); - info->name = storage::StringToFilePath(name).value(); - info->modification_time = base::Time::FromInternalValue(internal_time); - return true; - } - LOG(ERROR) << "Pickle could not be digested!"; - return false; -} - -const base::FilePath::CharType kDirectoryDatabaseName[] = - FILE_PATH_LITERAL("Paths"); -const char kChildLookupPrefix[] = "CHILD_OF:"; -const char kChildLookupSeparator[] = ":"; -const char kLastFileIdKey[] = "LAST_FILE_ID"; -const char kLastIntegerKey[] = "LAST_INTEGER"; -const int64 kMinimumReportIntervalHours = 1; -const char kInitStatusHistogramLabel[] = "FileSystem.DirectoryDatabaseInit"; -const char kDatabaseRepairHistogramLabel[] = - "FileSystem.DirectoryDatabaseRepair"; - -enum InitStatus { - INIT_STATUS_OK = 0, - INIT_STATUS_CORRUPTION, - INIT_STATUS_IO_ERROR, - INIT_STATUS_UNKNOWN_ERROR, - INIT_STATUS_MAX -}; - -enum RepairResult { - DB_REPAIR_SUCCEEDED = 0, - DB_REPAIR_FAILED, - DB_REPAIR_MAX -}; - -std::string GetChildLookupKey( - storage::SandboxDirectoryDatabase::FileId parent_id, - const base::FilePath::StringType& child_name) { - std::string name; - name = storage::FilePathToString(base::FilePath(child_name)); - return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + - std::string(kChildLookupSeparator) + name; -} - -std::string GetChildListingKeyPrefix( - storage::SandboxDirectoryDatabase::FileId parent_id) { - return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + - std::string(kChildLookupSeparator); -} - -const char* LastFileIdKey() { - return kLastFileIdKey; -} - -const char* LastIntegerKey() { - return kLastIntegerKey; -} - -std::string GetFileLookupKey( - storage::SandboxDirectoryDatabase::FileId file_id) { - return base::Int64ToString(file_id); -} - -// Assumptions: -// - Any database entry is one of: -// - ("CHILD_OF:|parent_id|:<name>", "|file_id|"), -// - ("LAST_FILE_ID", "|last_file_id|"), -// - ("LAST_INTEGER", "|last_integer|"), -// - ("|file_id|", "pickled FileInfo") -// where FileInfo has |parent_id|, |data_path|, |name| and -// |modification_time|, -// Constraints: -// - Each file in the database has unique backing file. -// - Each file in |filesystem_data_directory_| has a database entry. -// - Directory structure is tree, i.e. connected and acyclic. -class DatabaseCheckHelper { - public: - typedef storage::SandboxDirectoryDatabase::FileId FileId; - typedef storage::SandboxDirectoryDatabase::FileInfo FileInfo; - - DatabaseCheckHelper(storage::SandboxDirectoryDatabase* dir_db, - leveldb::DB* db, - const base::FilePath& path); - - bool IsFileSystemConsistent() { - return IsDatabaseEmpty() || - (ScanDatabase() && ScanDirectory() && ScanHierarchy()); - } - - private: - bool IsDatabaseEmpty(); - // These 3 methods need to be called in the order. Each method requires its - // previous method finished successfully. They also require the database is - // not empty. - bool ScanDatabase(); - bool ScanDirectory(); - bool ScanHierarchy(); - - storage::SandboxDirectoryDatabase* dir_db_; - leveldb::DB* db_; - base::FilePath path_; - - std::set<base::FilePath> files_in_db_; - - size_t num_directories_in_db_; - size_t num_files_in_db_; - size_t num_hierarchy_links_in_db_; - - FileId last_file_id_; - FileId last_integer_; -}; - -DatabaseCheckHelper::DatabaseCheckHelper( - storage::SandboxDirectoryDatabase* dir_db, - leveldb::DB* db, - const base::FilePath& path) - : dir_db_(dir_db), - db_(db), - path_(path), - num_directories_in_db_(0), - num_files_in_db_(0), - num_hierarchy_links_in_db_(0), - last_file_id_(-1), - last_integer_(-1) { - DCHECK(dir_db_); - DCHECK(db_); - DCHECK(!path_.empty() && base::DirectoryExists(path_)); -} - -bool DatabaseCheckHelper::IsDatabaseEmpty() { - scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); - itr->SeekToFirst(); - return !itr->Valid(); -} - -bool DatabaseCheckHelper::ScanDatabase() { - // Scans all database entries sequentially to verify each of them has unique - // backing file. - int64 max_file_id = -1; - std::set<FileId> file_ids; - - scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); - for (itr->SeekToFirst(); itr->Valid(); itr->Next()) { - std::string key = itr->key().ToString(); - if (StartsWithASCII(key, kChildLookupPrefix, true)) { - // key: "CHILD_OF:<parent_id>:<name>" - // value: "<child_id>" - ++num_hierarchy_links_in_db_; - } else if (key == kLastFileIdKey) { - // key: "LAST_FILE_ID" - // value: "<last_file_id>" - if (last_file_id_ >= 0 || - !base::StringToInt64(itr->value().ToString(), &last_file_id_)) - return false; - - if (last_file_id_ < 0) - return false; - } else if (key == kLastIntegerKey) { - // key: "LAST_INTEGER" - // value: "<last_integer>" - if (last_integer_ >= 0 || - !base::StringToInt64(itr->value().ToString(), &last_integer_)) - return false; - } else { - // key: "<entry_id>" - // value: "<pickled FileInfo>" - FileInfo file_info; - if (!FileInfoFromPickle( - Pickle(itr->value().data(), itr->value().size()), &file_info)) - return false; - - FileId file_id = -1; - if (!base::StringToInt64(key, &file_id) || file_id < 0) - return false; - - if (max_file_id < file_id) - max_file_id = file_id; - if (!file_ids.insert(file_id).second) - return false; - - if (file_info.is_directory()) { - ++num_directories_in_db_; - DCHECK(file_info.data_path.empty()); - } else { - // Ensure any pair of file entry don't share their data_path. - if (!files_in_db_.insert(file_info.data_path).second) - return false; - - // Ensure the backing file exists as a normal file. - base::File::Info platform_file_info; - if (!base::GetFileInfo( - path_.Append(file_info.data_path), &platform_file_info) || - platform_file_info.is_directory || - platform_file_info.is_symbolic_link) { - // leveldb::Iterator iterates a snapshot of the database. - // So even after RemoveFileInfo() call, we'll visit hierarchy link - // from |parent_id| to |file_id|. - if (!dir_db_->RemoveFileInfo(file_id)) - return false; - --num_hierarchy_links_in_db_; - files_in_db_.erase(file_info.data_path); - } else { - ++num_files_in_db_; - } - } - } - } - - // TODO(tzik): Add constraint for |last_integer_| to avoid possible - // data path confliction on ObfuscatedFileUtil. - return max_file_id <= last_file_id_; -} - -bool DatabaseCheckHelper::ScanDirectory() { - // TODO(kinuko): Scans all local file system entries to verify each of them - // has a database entry. - const base::FilePath kExcludes[] = { - base::FilePath(kDirectoryDatabaseName), - base::FilePath(storage::FileSystemUsageCache::kUsageFileName), - }; - - // Any path in |pending_directories| is relative to |path_|. - std::stack<base::FilePath> pending_directories; - pending_directories.push(base::FilePath()); - - while (!pending_directories.empty()) { - base::FilePath dir_path = pending_directories.top(); - pending_directories.pop(); - - base::FileEnumerator file_enum( - dir_path.empty() ? path_ : path_.Append(dir_path), - false /* not recursive */, - base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES); - - base::FilePath absolute_file_path; - while (!(absolute_file_path = file_enum.Next()).empty()) { - base::FileEnumerator::FileInfo find_info = file_enum.GetInfo(); - - base::FilePath relative_file_path; - if (!path_.AppendRelativePath(absolute_file_path, &relative_file_path)) - return false; - - if (std::find(kExcludes, kExcludes + arraysize(kExcludes), - relative_file_path) != kExcludes + arraysize(kExcludes)) - continue; - - if (find_info.IsDirectory()) { - pending_directories.push(relative_file_path); - continue; - } - - // Check if the file has a database entry. - std::set<base::FilePath>::iterator itr = - files_in_db_.find(relative_file_path); - if (itr == files_in_db_.end()) { - if (!base::DeleteFile(absolute_file_path, false)) - return false; - } else { - files_in_db_.erase(itr); - } - } - } - - return files_in_db_.empty(); -} - -bool DatabaseCheckHelper::ScanHierarchy() { - size_t visited_directories = 0; - size_t visited_files = 0; - size_t visited_links = 0; - - std::stack<FileId> directories; - directories.push(0); - - // Check if the root directory exists as a directory. - FileInfo file_info; - if (!dir_db_->GetFileInfo(0, &file_info)) - return false; - if (file_info.parent_id != 0 || - !file_info.is_directory()) - return false; - - while (!directories.empty()) { - ++visited_directories; - FileId dir_id = directories.top(); - directories.pop(); - - std::vector<FileId> children; - if (!dir_db_->ListChildren(dir_id, &children)) - return false; - for (std::vector<FileId>::iterator itr = children.begin(); - itr != children.end(); - ++itr) { - // Any directory must not have root directory as child. - if (!*itr) - return false; - - // Check if the child knows the parent as its parent. - FileInfo file_info; - if (!dir_db_->GetFileInfo(*itr, &file_info)) - return false; - if (file_info.parent_id != dir_id) - return false; - - // Check if the parent knows the name of its child correctly. - FileId file_id; - if (!dir_db_->GetChildWithName(dir_id, file_info.name, &file_id) || - file_id != *itr) - return false; - - if (file_info.is_directory()) - directories.push(*itr); - else - ++visited_files; - ++visited_links; - } - } - - // Check if we've visited all database entries. - return num_directories_in_db_ == visited_directories && - num_files_in_db_ == visited_files && - num_hierarchy_links_in_db_ == visited_links; -} - -// Returns true if the given |data_path| contains no parent references ("..") -// and does not refer to special system files. -// This is called in GetFileInfo, AddFileInfo and UpdateFileInfo to -// ensure we're only dealing with valid data paths. -bool VerifyDataPath(const base::FilePath& data_path) { - // |data_path| should not contain any ".." and should be a relative path - // (to the filesystem_data_directory_). - if (data_path.ReferencesParent() || data_path.IsAbsolute()) - return false; - // See if it's not pointing to the special system paths. - const base::FilePath kExcludes[] = { - base::FilePath(kDirectoryDatabaseName), - base::FilePath(storage::FileSystemUsageCache::kUsageFileName), - }; - for (size_t i = 0; i < arraysize(kExcludes); ++i) { - if (data_path == kExcludes[i] || kExcludes[i].IsParent(data_path)) - return false; - } - return true; -} - -} // namespace - -namespace storage { - -SandboxDirectoryDatabase::FileInfo::FileInfo() : parent_id(0) { -} - -SandboxDirectoryDatabase::FileInfo::~FileInfo() { -} - -SandboxDirectoryDatabase::SandboxDirectoryDatabase( - const base::FilePath& filesystem_data_directory, - leveldb::Env* env_override) - : filesystem_data_directory_(filesystem_data_directory), - env_override_(env_override) { -} - -SandboxDirectoryDatabase::~SandboxDirectoryDatabase() { -} - -bool SandboxDirectoryDatabase::GetChildWithName( - FileId parent_id, - const base::FilePath::StringType& name, - FileId* child_id) { - if (!Init(REPAIR_ON_CORRUPTION)) - return false; - DCHECK(child_id); - std::string child_key = GetChildLookupKey(parent_id, name); - std::string child_id_string; - leveldb::Status status = - db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); - if (status.IsNotFound()) - return false; - if (status.ok()) { - if (!base::StringToInt64(child_id_string, child_id)) { - LOG(ERROR) << "Hit database corruption!"; - return false; - } - return true; - } - HandleError(FROM_HERE, status); - return false; -} - -bool SandboxDirectoryDatabase::GetFileWithPath( - const base::FilePath& path, FileId* file_id) { - std::vector<base::FilePath::StringType> components; - VirtualPath::GetComponents(path, &components); - FileId local_id = 0; - std::vector<base::FilePath::StringType>::iterator iter; - for (iter = components.begin(); iter != components.end(); ++iter) { - base::FilePath::StringType name; - name = *iter; - if (name == FILE_PATH_LITERAL("/")) - continue; - if (!GetChildWithName(local_id, name, &local_id)) - return false; - } - *file_id = local_id; - return true; -} - -bool SandboxDirectoryDatabase::ListChildren( - FileId parent_id, std::vector<FileId>* children) { - // Check to add later: fail if parent is a file, at least in debug builds. - if (!Init(REPAIR_ON_CORRUPTION)) - return false; - DCHECK(children); - std::string child_key_prefix = GetChildListingKeyPrefix(parent_id); - - scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); - iter->Seek(child_key_prefix); - children->clear(); - while (iter->Valid() && - StartsWithASCII(iter->key().ToString(), child_key_prefix, true)) { - std::string child_id_string = iter->value().ToString(); - FileId child_id; - if (!base::StringToInt64(child_id_string, &child_id)) { - LOG(ERROR) << "Hit database corruption!"; - return false; - } - children->push_back(child_id); - iter->Next(); - } - return true; -} - -bool SandboxDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { - if (!Init(REPAIR_ON_CORRUPTION)) - return false; - DCHECK(info); - std::string file_key = GetFileLookupKey(file_id); - std::string file_data_string; - leveldb::Status status = - db_->Get(leveldb::ReadOptions(), file_key, &file_data_string); - if (status.ok()) { - bool success = FileInfoFromPickle( - Pickle(file_data_string.data(), file_data_string.length()), info); - if (!success) - return false; - if (!VerifyDataPath(info->data_path)) { - LOG(ERROR) << "Resolved data path is invalid: " - << info->data_path.value(); - return false; - } - return true; - } - // Special-case the root, for databases that haven't been initialized yet. - // Without this, a query for the root's file info, made before creating the - // first file in the database, will fail and confuse callers. - if (status.IsNotFound() && !file_id) { - info->name = base::FilePath::StringType(); - info->data_path = base::FilePath(); - info->modification_time = base::Time::Now(); - info->parent_id = 0; - return true; - } - HandleError(FROM_HERE, status); - return false; -} - -base::File::Error SandboxDirectoryDatabase::AddFileInfo( - const FileInfo& info, FileId* file_id) { - if (!Init(REPAIR_ON_CORRUPTION)) - return base::File::FILE_ERROR_FAILED; - DCHECK(file_id); - std::string child_key = GetChildLookupKey(info.parent_id, info.name); - std::string child_id_string; - leveldb::Status status = - db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); - if (status.ok()) { - LOG(ERROR) << "File exists already!"; - return base::File::FILE_ERROR_EXISTS; - } - if (!status.IsNotFound()) { - HandleError(FROM_HERE, status); - return base::File::FILE_ERROR_NOT_FOUND; - } - - if (!IsDirectory(info.parent_id)) { - LOG(ERROR) << "New parent directory is a file!"; - return base::File::FILE_ERROR_NOT_A_DIRECTORY; - } - - // This would be a fine place to limit the number of files in a directory, if - // we decide to add that restriction. - - FileId temp_id; - if (!GetLastFileId(&temp_id)) - return base::File::FILE_ERROR_FAILED; - ++temp_id; - - leveldb::WriteBatch batch; - if (!AddFileInfoHelper(info, temp_id, &batch)) - return base::File::FILE_ERROR_FAILED; - - batch.Put(LastFileIdKey(), base::Int64ToString(temp_id)); - status = db_->Write(leveldb::WriteOptions(), &batch); - if (!status.ok()) { - HandleError(FROM_HERE, status); - return base::File::FILE_ERROR_FAILED; - } - *file_id = temp_id; - return base::File::FILE_OK; -} - -bool SandboxDirectoryDatabase::RemoveFileInfo(FileId file_id) { - if (!Init(REPAIR_ON_CORRUPTION)) - return false; - leveldb::WriteBatch batch; - if (!RemoveFileInfoHelper(file_id, &batch)) - return false; - leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); - if (!status.ok()) { - HandleError(FROM_HERE, status); - return false; - } - return true; -} - -bool SandboxDirectoryDatabase::UpdateFileInfo( - FileId file_id, const FileInfo& new_info) { - // TODO(ericu): We should also check to see that this doesn't create a loop, - // but perhaps only in a debug build. - if (!Init(REPAIR_ON_CORRUPTION)) - return false; - DCHECK(file_id); // You can't remove the root, ever. Just delete the DB. - FileInfo old_info; - if (!GetFileInfo(file_id, &old_info)) - return false; - if (old_info.parent_id != new_info.parent_id && - !IsDirectory(new_info.parent_id)) - return false; - if (old_info.parent_id != new_info.parent_id || - old_info.name != new_info.name) { - // Check for name clashes. - FileId temp_id; - if (GetChildWithName(new_info.parent_id, new_info.name, &temp_id)) { - LOG(ERROR) << "Name collision on move."; - return false; - } - } - leveldb::WriteBatch batch; - if (!RemoveFileInfoHelper(file_id, &batch) || - !AddFileInfoHelper(new_info, file_id, &batch)) - return false; - leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); - if (!status.ok()) { - HandleError(FROM_HERE, status); - return false; - } - return true; -} - -bool SandboxDirectoryDatabase::UpdateModificationTime( - FileId file_id, const base::Time& modification_time) { - FileInfo info; - if (!GetFileInfo(file_id, &info)) - return false; - info.modification_time = modification_time; - Pickle pickle; - if (!PickleFromFileInfo(info, &pickle)) - return false; - leveldb::Status status = db_->Put( - leveldb::WriteOptions(), - GetFileLookupKey(file_id), - leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), - pickle.size())); - if (!status.ok()) { - HandleError(FROM_HERE, status); - return false; - } - return true; -} - -bool SandboxDirectoryDatabase::OverwritingMoveFile( - FileId src_file_id, FileId dest_file_id) { - FileInfo src_file_info; - FileInfo dest_file_info; - - if (!GetFileInfo(src_file_id, &src_file_info)) - return false; - if (!GetFileInfo(dest_file_id, &dest_file_info)) - return false; - if (src_file_info.is_directory() || dest_file_info.is_directory()) - return false; - leveldb::WriteBatch batch; - // This is the only field that really gets moved over; if you add fields to - // FileInfo, e.g. ctime, they might need to be copied here. - dest_file_info.data_path = src_file_info.data_path; - if (!RemoveFileInfoHelper(src_file_id, &batch)) - return false; - Pickle pickle; - if (!PickleFromFileInfo(dest_file_info, &pickle)) - return false; - batch.Put( - GetFileLookupKey(dest_file_id), - leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), - pickle.size())); - leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); - if (!status.ok()) { - HandleError(FROM_HERE, status); - return false; - } - return true; -} - -bool SandboxDirectoryDatabase::GetNextInteger(int64* next) { - if (!Init(REPAIR_ON_CORRUPTION)) - return false; - DCHECK(next); - std::string int_string; - leveldb::Status status = - db_->Get(leveldb::ReadOptions(), LastIntegerKey(), &int_string); - if (status.ok()) { - int64 temp; - if (!base::StringToInt64(int_string, &temp)) { - LOG(ERROR) << "Hit database corruption!"; - return false; - } - ++temp; - status = db_->Put(leveldb::WriteOptions(), LastIntegerKey(), - base::Int64ToString(temp)); - if (!status.ok()) { - HandleError(FROM_HERE, status); - return false; - } - *next = temp; - return true; - } - if (!status.IsNotFound()) { - HandleError(FROM_HERE, status); - return false; - } - // The database must not yet exist; initialize it. - if (!StoreDefaultValues()) - return false; - - return GetNextInteger(next); -} - -// static -bool SandboxDirectoryDatabase::DestroyDatabase(const base::FilePath& path, - leveldb::Env* env_override) { - std::string name = FilePathToString(path.Append(kDirectoryDatabaseName)); - leveldb::Options options; - if (env_override) - options.env = env_override; - leveldb::Status status = leveldb::DestroyDB(name, options); - if (status.ok()) - return true; - LOG(WARNING) << "Failed to destroy a database with status " << - status.ToString(); - return false; -} - -bool SandboxDirectoryDatabase::Init(RecoveryOption recovery_option) { - if (db_) - return true; - - std::string path = - FilePathToString(filesystem_data_directory_.Append( - kDirectoryDatabaseName)); - leveldb::Options options; - options.max_open_files = 0; // Use minimum. - options.create_if_missing = true; - if (env_override_) - options.env = env_override_; - leveldb::DB* db; - leveldb::Status status = leveldb::DB::Open(options, path, &db); - ReportInitStatus(status); - if (status.ok()) { - db_.reset(db); - return true; - } - HandleError(FROM_HERE, status); - - // Corruption due to missing necessary MANIFEST-* file causes IOError instead - // of Corruption error. - // Try to repair database even when IOError case. - if (!status.IsCorruption() && !status.IsIOError()) - return false; - - switch (recovery_option) { - case FAIL_ON_CORRUPTION: - return false; - case REPAIR_ON_CORRUPTION: - LOG(WARNING) << "Corrupted SandboxDirectoryDatabase detected." - << " Attempting to repair."; - if (RepairDatabase(path)) { - UMA_HISTOGRAM_ENUMERATION(kDatabaseRepairHistogramLabel, - DB_REPAIR_SUCCEEDED, DB_REPAIR_MAX); - return true; - } - UMA_HISTOGRAM_ENUMERATION(kDatabaseRepairHistogramLabel, - DB_REPAIR_FAILED, DB_REPAIR_MAX); - LOG(WARNING) << "Failed to repair SandboxDirectoryDatabase."; - // fall through - case DELETE_ON_CORRUPTION: - LOG(WARNING) << "Clearing SandboxDirectoryDatabase."; - if (!base::DeleteFile(filesystem_data_directory_, true)) - return false; - if (!base::CreateDirectory(filesystem_data_directory_)) - return false; - return Init(FAIL_ON_CORRUPTION); - } - - NOTREACHED(); - return false; -} - -bool SandboxDirectoryDatabase::RepairDatabase(const std::string& db_path) { - DCHECK(!db_.get()); - leveldb::Options options; - options.max_open_files = 0; // Use minimum. - if (env_override_) - options.env = env_override_; - if (!leveldb::RepairDB(db_path, options).ok()) - return false; - if (!Init(FAIL_ON_CORRUPTION)) - return false; - if (IsFileSystemConsistent()) - return true; - db_.reset(); - return false; -} - -bool SandboxDirectoryDatabase::IsDirectory(FileId file_id) { - FileInfo info; - if (!file_id) - return true; // The root is a directory. - if (!GetFileInfo(file_id, &info)) - return false; - if (!info.is_directory()) - return false; - return true; -} - -bool SandboxDirectoryDatabase::IsFileSystemConsistent() { - if (!Init(FAIL_ON_CORRUPTION)) - return false; - DatabaseCheckHelper helper(this, db_.get(), filesystem_data_directory_); - return helper.IsFileSystemConsistent(); -} - -void SandboxDirectoryDatabase::ReportInitStatus( - const leveldb::Status& status) { - base::Time now = base::Time::Now(); - const base::TimeDelta minimum_interval = - base::TimeDelta::FromHours(kMinimumReportIntervalHours); - if (last_reported_time_ + minimum_interval >= now) - return; - last_reported_time_ = now; - - if (status.ok()) { - UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, - INIT_STATUS_OK, INIT_STATUS_MAX); - } else if (status.IsCorruption()) { - UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, - INIT_STATUS_CORRUPTION, INIT_STATUS_MAX); - } else if (status.IsIOError()) { - UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, - INIT_STATUS_IO_ERROR, INIT_STATUS_MAX); - } else { - UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, - INIT_STATUS_UNKNOWN_ERROR, INIT_STATUS_MAX); - } -} - -bool SandboxDirectoryDatabase::StoreDefaultValues() { - // Verify that this is a totally new database, and initialize it. - scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); - iter->SeekToFirst(); - if (iter->Valid()) { // DB was not empty--we shouldn't have been called. - LOG(ERROR) << "File system origin database is corrupt!"; - return false; - } - // This is always the first write into the database. If we ever add a - // version number, it should go in this transaction too. - FileInfo root; - root.parent_id = 0; - root.modification_time = base::Time::Now(); - leveldb::WriteBatch batch; - if (!AddFileInfoHelper(root, 0, &batch)) - return false; - batch.Put(LastFileIdKey(), base::Int64ToString(0)); - batch.Put(LastIntegerKey(), base::Int64ToString(-1)); - leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); - if (!status.ok()) { - HandleError(FROM_HERE, status); - return false; - } - return true; -} - -bool SandboxDirectoryDatabase::GetLastFileId(FileId* file_id) { - if (!Init(REPAIR_ON_CORRUPTION)) - return false; - DCHECK(file_id); - std::string id_string; - leveldb::Status status = - db_->Get(leveldb::ReadOptions(), LastFileIdKey(), &id_string); - if (status.ok()) { - if (!base::StringToInt64(id_string, file_id)) { - LOG(ERROR) << "Hit database corruption!"; - return false; - } - return true; - } - if (!status.IsNotFound()) { - HandleError(FROM_HERE, status); - return false; - } - // The database must not yet exist; initialize it. - if (!StoreDefaultValues()) - return false; - *file_id = 0; - return true; -} - -// This does very few safety checks! -bool SandboxDirectoryDatabase::AddFileInfoHelper( - const FileInfo& info, FileId file_id, leveldb::WriteBatch* batch) { - if (!VerifyDataPath(info.data_path)) { - LOG(ERROR) << "Invalid data path is given: " << info.data_path.value(); - return false; - } - std::string id_string = GetFileLookupKey(file_id); - if (!file_id) { - // The root directory doesn't need to be looked up by path from its parent. - DCHECK(!info.parent_id); - DCHECK(info.data_path.empty()); - } else { - std::string child_key = GetChildLookupKey(info.parent_id, info.name); - batch->Put(child_key, id_string); - } - Pickle pickle; - if (!PickleFromFileInfo(info, &pickle)) - return false; - batch->Put( - id_string, - leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), - pickle.size())); - return true; -} - -// This does very few safety checks! -bool SandboxDirectoryDatabase::RemoveFileInfoHelper( - FileId file_id, leveldb::WriteBatch* batch) { - DCHECK(file_id); // You can't remove the root, ever. Just delete the DB. - FileInfo info; - if (!GetFileInfo(file_id, &info)) - return false; - if (info.data_path.empty()) { // It's a directory - std::vector<FileId> children; - // TODO(ericu): Make a faster is-the-directory-empty check. - if (!ListChildren(file_id, &children)) - return false; - if (children.size()) { - LOG(ERROR) << "Can't remove a directory with children."; - return false; - } - } - batch->Delete(GetChildLookupKey(info.parent_id, info.name)); - batch->Delete(GetFileLookupKey(file_id)); - return true; -} - -void SandboxDirectoryDatabase::HandleError( - const tracked_objects::Location& from_here, - const leveldb::Status& status) { - LOG(ERROR) << "SandboxDirectoryDatabase failed at: " - << from_here.ToString() << " with error: " << status.ToString(); - db_.reset(); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/sandbox_directory_database.h b/webkit/browser/fileapi/sandbox_directory_database.h index 7dbc166..c8452b0 100644 --- a/webkit/browser/fileapi/sandbox_directory_database.h +++ b/webkit/browser/fileapi/sandbox_directory_database.h @@ -1,135 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_SANDBOX_DIRECTORY_DATABASE_H_ -#define WEBKIT_BROWSER_FILEAPI_SANDBOX_DIRECTORY_DATABASE_H_ - -#include <string> -#include <vector> - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "webkit/browser/storage_browser_export.h" - -namespace content { -class SandboxDirectoryDatabaseTest; -} - -namespace tracked_objects { -class Location; -} - -namespace leveldb { -class DB; -class Env; -class Status; -class WriteBatch; -} - -namespace storage { - -// This class WILL NOT protect you against producing directory loops, giving an -// empty directory a backing data file, giving two files the same backing file, -// or pointing to a nonexistent backing file. It does no file IO other than -// that involved with talking to its underlying database. It does not create or -// in any way touch real files; it only creates path entries in its database. - -// TODO(ericu): Safe mode, which does more checks such as the above on debug -// builds. -// TODO(ericu): Add a method that will give a unique filename for a data file. -class STORAGE_EXPORT_PRIVATE SandboxDirectoryDatabase { - public: - typedef int64 FileId; - - struct STORAGE_EXPORT_PRIVATE FileInfo { - FileInfo(); - ~FileInfo(); - - bool is_directory() const { - return data_path.empty(); - } - - FileId parent_id; - base::FilePath data_path; - base::FilePath::StringType name; - // This modification time is valid only for directories, not files, as - // FileWriter will get the files out of sync. - // For files, look at the modification time of the underlying data_path. - base::Time modification_time; - }; - - SandboxDirectoryDatabase( - const base::FilePath& filesystem_data_directory, - leveldb::Env* env_override); - ~SandboxDirectoryDatabase(); - - bool GetChildWithName( - FileId parent_id, - const base::FilePath::StringType& name, - FileId* child_id); - bool GetFileWithPath(const base::FilePath& path, FileId* file_id); - // ListChildren will succeed, returning 0 children, if parent_id doesn't - // exist. - bool ListChildren(FileId parent_id, std::vector<FileId>* children); - bool GetFileInfo(FileId file_id, FileInfo* info); - base::File::Error AddFileInfo(const FileInfo& info, FileId* file_id); - bool RemoveFileInfo(FileId file_id); - // This does a full update of the FileInfo, and is what you'd use for moves - // and renames. If you just want to update the modification_time, use - // UpdateModificationTime. - bool UpdateFileInfo(FileId file_id, const FileInfo& info); - bool UpdateModificationTime( - FileId file_id, const base::Time& modification_time); - // This is used for an overwriting move of a file [not a directory] on top of - // another file [also not a directory]; we need to alter two files' info in a - // single transaction to avoid weird backing file references in the event of a - // partial failure. - bool OverwritingMoveFile(FileId src_file_id, FileId dest_file_id); - - // This produces the series 0, 1, 2..., starting at 0 when the underlying - // filesystem is first created, and maintaining state across - // creation/destruction of SandboxDirectoryDatabase objects. - bool GetNextInteger(int64* next); - - bool IsDirectory(FileId file_id); - - // Returns true if the database looks consistent with local filesystem. - bool IsFileSystemConsistent(); - - static bool DestroyDatabase(const base::FilePath& path, - leveldb::Env* env_override); - - private: - enum RecoveryOption { - DELETE_ON_CORRUPTION, - REPAIR_ON_CORRUPTION, - FAIL_ON_CORRUPTION, - }; - - friend class content::SandboxDirectoryDatabaseTest; - friend class ObfuscatedFileUtil; - - bool Init(RecoveryOption recovery_option); - bool RepairDatabase(const std::string& db_path); - void ReportInitStatus(const leveldb::Status& status); - bool StoreDefaultValues(); - bool GetLastFileId(FileId* file_id); - bool AddFileInfoHelper( - const FileInfo& info, FileId file_id, leveldb::WriteBatch* batch); - bool RemoveFileInfoHelper(FileId file_id, leveldb::WriteBatch* batch); - void HandleError(const tracked_objects::Location& from_here, - const leveldb::Status& status); - - const base::FilePath filesystem_data_directory_; - leveldb::Env* env_override_; - scoped_ptr<leveldb::DB> db_; - base::Time last_reported_time_; - DISALLOW_COPY_AND_ASSIGN(SandboxDirectoryDatabase); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_DIRECTORY_DATABASE_H_ +#include "storage/browser/fileapi/sandbox_directory_database.h" diff --git a/webkit/browser/fileapi/sandbox_file_stream_writer.cc b/webkit/browser/fileapi/sandbox_file_stream_writer.cc deleted file mode 100644 index 8fd39bc..0000000 --- a/webkit/browser/fileapi/sandbox_file_stream_writer.cc +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/sandbox_file_stream_writer.h" - -#include "base/files/file_util_proxy.h" -#include "base/sequenced_task_runner.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/file_observers.h" -#include "webkit/browser/fileapi/file_stream_writer.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_runner.h" -#include "webkit/browser/quota/quota_manager_proxy.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace storage { - -namespace { - -// Adjust the |quota| value in overwriting case (i.e. |file_size| > 0 and -// |file_offset| < |file_size|) to make the remaining quota calculation easier. -// Specifically this widens the quota for overlapping range (so that we can -// simply compare written bytes against the adjusted quota). -int64 AdjustQuotaForOverlap(int64 quota, - int64 file_offset, - int64 file_size) { - DCHECK_LE(file_offset, file_size); - if (quota < 0) - quota = 0; - int64 overlap = file_size - file_offset; - if (kint64max - overlap > quota) - quota += overlap; - return quota; -} - -} // namespace - -SandboxFileStreamWriter::SandboxFileStreamWriter( - FileSystemContext* file_system_context, - const FileSystemURL& url, - int64 initial_offset, - const UpdateObserverList& observers) - : file_system_context_(file_system_context), - url_(url), - initial_offset_(initial_offset), - observers_(observers), - file_size_(0), - total_bytes_written_(0), - allowed_bytes_to_write_(0), - has_pending_operation_(false), - default_quota_(kint64max), - weak_factory_(this) { - DCHECK(url_.is_valid()); -} - -SandboxFileStreamWriter::~SandboxFileStreamWriter() {} - -int SandboxFileStreamWriter::Write( - net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { - has_pending_operation_ = true; - if (local_file_writer_) - return WriteInternal(buf, buf_len, callback); - - net::CompletionCallback write_task = - base::Bind(&SandboxFileStreamWriter::DidInitializeForWrite, - weak_factory_.GetWeakPtr(), - make_scoped_refptr(buf), buf_len, callback); - file_system_context_->operation_runner()->CreateSnapshotFile( - url_, base::Bind(&SandboxFileStreamWriter::DidCreateSnapshotFile, - weak_factory_.GetWeakPtr(), write_task)); - return net::ERR_IO_PENDING; -} - -int SandboxFileStreamWriter::Cancel(const net::CompletionCallback& callback) { - if (!has_pending_operation_) - return net::ERR_UNEXPECTED; - - DCHECK(!callback.is_null()); - cancel_callback_ = callback; - return net::ERR_IO_PENDING; -} - -int SandboxFileStreamWriter::WriteInternal( - net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { - // allowed_bytes_to_write could be negative if the file size is - // greater than the current (possibly new) quota. - DCHECK(total_bytes_written_ <= allowed_bytes_to_write_ || - allowed_bytes_to_write_ < 0); - if (total_bytes_written_ >= allowed_bytes_to_write_) { - has_pending_operation_ = false; - return net::ERR_FILE_NO_SPACE; - } - - if (buf_len > allowed_bytes_to_write_ - total_bytes_written_) - buf_len = allowed_bytes_to_write_ - total_bytes_written_; - - DCHECK(local_file_writer_.get()); - const int result = local_file_writer_->Write( - buf, buf_len, - base::Bind(&SandboxFileStreamWriter::DidWrite, weak_factory_.GetWeakPtr(), - callback)); - if (result != net::ERR_IO_PENDING) - has_pending_operation_ = false; - return result; -} - -void SandboxFileStreamWriter::DidCreateSnapshotFile( - const net::CompletionCallback& callback, - base::File::Error file_error, - const base::File::Info& file_info, - const base::FilePath& platform_path, - const scoped_refptr<storage::ShareableFileReference>& file_ref) { - DCHECK(!file_ref.get()); - - if (CancelIfRequested()) - return; - if (file_error != base::File::FILE_OK) { - callback.Run(net::FileErrorToNetError(file_error)); - return; - } - if (file_info.is_directory) { - // We should not be writing to a directory. - callback.Run(net::ERR_ACCESS_DENIED); - return; - } - file_size_ = file_info.size; - if (initial_offset_ > file_size_) { - LOG(ERROR) << initial_offset_ << ", " << file_size_; - // This shouldn't happen as long as we check offset in the renderer. - NOTREACHED(); - initial_offset_ = file_size_; - } - DCHECK(!local_file_writer_.get()); - local_file_writer_.reset(FileStreamWriter::CreateForLocalFile( - file_system_context_->default_file_task_runner(), - platform_path, - initial_offset_, - FileStreamWriter::OPEN_EXISTING_FILE)); - - storage::QuotaManagerProxy* quota_manager_proxy = - file_system_context_->quota_manager_proxy(); - if (!quota_manager_proxy) { - // If we don't have the quota manager or the requested filesystem type - // does not support quota, we should be able to let it go. - allowed_bytes_to_write_ = default_quota_; - callback.Run(net::OK); - return; - } - - DCHECK(quota_manager_proxy->quota_manager()); - quota_manager_proxy->quota_manager()->GetUsageAndQuota( - url_.origin(), - FileSystemTypeToQuotaStorageType(url_.type()), - base::Bind(&SandboxFileStreamWriter::DidGetUsageAndQuota, - weak_factory_.GetWeakPtr(), callback)); -} - -void SandboxFileStreamWriter::DidGetUsageAndQuota( - const net::CompletionCallback& callback, - storage::QuotaStatusCode status, - int64 usage, - int64 quota) { - if (CancelIfRequested()) - return; - if (status != storage::kQuotaStatusOk) { - LOG(WARNING) << "Got unexpected quota error : " << status; - callback.Run(net::ERR_FAILED); - return; - } - - allowed_bytes_to_write_ = quota - usage; - callback.Run(net::OK); -} - -void SandboxFileStreamWriter::DidInitializeForWrite( - net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback, - int init_status) { - if (CancelIfRequested()) - return; - if (init_status != net::OK) { - has_pending_operation_ = false; - callback.Run(init_status); - return; - } - allowed_bytes_to_write_ = AdjustQuotaForOverlap( - allowed_bytes_to_write_, initial_offset_, file_size_); - const int result = WriteInternal(buf, buf_len, callback); - if (result != net::ERR_IO_PENDING) - callback.Run(result); -} - -void SandboxFileStreamWriter::DidWrite( - const net::CompletionCallback& callback, - int write_response) { - DCHECK(has_pending_operation_); - has_pending_operation_ = false; - - if (write_response <= 0) { - if (CancelIfRequested()) - return; - callback.Run(write_response); - return; - } - - if (total_bytes_written_ + write_response + initial_offset_ > file_size_) { - int overlapped = file_size_ - total_bytes_written_ - initial_offset_; - if (overlapped < 0) - overlapped = 0; - observers_.Notify(&FileUpdateObserver::OnUpdate, - MakeTuple(url_, write_response - overlapped)); - } - total_bytes_written_ += write_response; - - if (CancelIfRequested()) - return; - callback.Run(write_response); -} - -bool SandboxFileStreamWriter::CancelIfRequested() { - if (cancel_callback_.is_null()) - return false; - - net::CompletionCallback pending_cancel = cancel_callback_; - has_pending_operation_ = false; - cancel_callback_.Reset(); - pending_cancel.Run(net::OK); - return true; -} - -int SandboxFileStreamWriter::Flush(const net::CompletionCallback& callback) { - DCHECK(!has_pending_operation_); - DCHECK(cancel_callback_.is_null()); - - // Write() is not called yet, so there's nothing to flush. - if (!local_file_writer_) - return net::OK; - - return local_file_writer_->Flush(callback); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/sandbox_file_stream_writer.h b/webkit/browser/fileapi/sandbox_file_stream_writer.h index e900c56..6b9ed33 100644 --- a/webkit/browser/fileapi/sandbox_file_stream_writer.h +++ b/webkit/browser/fileapi/sandbox_file_stream_writer.h @@ -1,96 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_SANDBOX_FILE_STREAM_WRITER_H_ -#define WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_STREAM_WRITER_H_ - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "url/gurl.h" -#include "webkit/browser/fileapi/file_stream_writer.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/task_runner_bound_observer_list.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/blob/shareable_file_reference.h" -#include "webkit/common/fileapi/file_system_types.h" -#include "webkit/common/quota/quota_types.h" - -namespace storage { - -class FileSystemContext; -class FileSystemQuotaUtil; -class FileStreamWriter; - -class STORAGE_EXPORT_PRIVATE SandboxFileStreamWriter - : public NON_EXPORTED_BASE(FileStreamWriter) { - public: - SandboxFileStreamWriter(FileSystemContext* file_system_context, - const FileSystemURL& url, - int64 initial_offset, - const UpdateObserverList& observers); - virtual ~SandboxFileStreamWriter(); - - // FileStreamWriter overrides. - virtual int Write(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) OVERRIDE; - virtual int Cancel(const net::CompletionCallback& callback) OVERRIDE; - virtual int Flush(const net::CompletionCallback& callback) OVERRIDE; - - // Used only by tests. - void set_default_quota(int64 quota) { - default_quota_ = quota; - } - - private: - // Performs quota calculation and calls local_file_writer_->Write(). - int WriteInternal(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback); - - // Callbacks that are chained for the first write. This eventually calls - // WriteInternal. - void DidCreateSnapshotFile( - const net::CompletionCallback& callback, - base::File::Error file_error, - const base::File::Info& file_info, - const base::FilePath& platform_path, - const scoped_refptr<storage::ShareableFileReference>& file_ref); - void DidGetUsageAndQuota(const net::CompletionCallback& callback, - storage::QuotaStatusCode status, - int64 usage, - int64 quota); - void DidInitializeForWrite(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback, - int init_status); - - void DidWrite(const net::CompletionCallback& callback, int write_response); - - // Stops the in-flight operation, calls |cancel_callback_| and returns true - // if there's a pending cancel request. - bool CancelIfRequested(); - - scoped_refptr<FileSystemContext> file_system_context_; - FileSystemURL url_; - int64 initial_offset_; - scoped_ptr<FileStreamWriter> local_file_writer_; - net::CompletionCallback cancel_callback_; - - UpdateObserverList observers_; - - base::FilePath file_path_; - int64 file_size_; - int64 total_bytes_written_; - int64 allowed_bytes_to_write_; - bool has_pending_operation_; - - int64 default_quota_; - - base::WeakPtrFactory<SandboxFileStreamWriter> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(SandboxFileStreamWriter); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_STREAM_WRITER_H_ +#include "storage/browser/fileapi/sandbox_file_stream_writer.h" diff --git a/webkit/browser/fileapi/sandbox_file_system_backend.cc b/webkit/browser/fileapi/sandbox_file_system_backend.cc deleted file mode 100644 index e80a0c4..0000000 --- a/webkit/browser/fileapi/sandbox_file_system_backend.cc +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/sandbox_file_system_backend.h" - -#include "base/bind.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/metrics/histogram.h" -#include "base/task_runner_util.h" -#include "url/gurl.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/async_file_util_adapter.h" -#include "webkit/browser/fileapi/copy_or_move_file_validator.h" -#include "webkit/browser/fileapi/file_stream_writer.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_options.h" -#include "webkit/browser/fileapi/file_system_usage_cache.h" -#include "webkit/browser/fileapi/obfuscated_file_util.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" -#include "webkit/browser/fileapi/sandbox_quota_observer.h" -#include "webkit/browser/quota/quota_manager.h" -#include "webkit/common/fileapi/file_system_types.h" -#include "webkit/common/fileapi/file_system_util.h" - -using storage::QuotaManagerProxy; -using storage::SpecialStoragePolicy; - -namespace storage { - -SandboxFileSystemBackend::SandboxFileSystemBackend( - SandboxFileSystemBackendDelegate* delegate) - : delegate_(delegate), - enable_temporary_file_system_in_incognito_(false) { -} - -SandboxFileSystemBackend::~SandboxFileSystemBackend() { -} - -bool SandboxFileSystemBackend::CanHandleType(FileSystemType type) const { - return type == kFileSystemTypeTemporary || - type == kFileSystemTypePersistent; -} - -void SandboxFileSystemBackend::Initialize(FileSystemContext* context) { - DCHECK(delegate_); - - // Set quota observers. - delegate_->RegisterQuotaUpdateObserver(storage::kFileSystemTypeTemporary); - delegate_->AddFileAccessObserver( - storage::kFileSystemTypeTemporary, delegate_->quota_observer(), NULL); - - delegate_->RegisterQuotaUpdateObserver(storage::kFileSystemTypePersistent); - delegate_->AddFileAccessObserver( - storage::kFileSystemTypePersistent, delegate_->quota_observer(), NULL); -} - -void SandboxFileSystemBackend::ResolveURL( - const FileSystemURL& url, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) { - DCHECK(CanHandleType(url.type())); - DCHECK(delegate_); - if (delegate_->file_system_options().is_incognito() && - !(url.type() == kFileSystemTypeTemporary && - enable_temporary_file_system_in_incognito_)) { - // TODO(kinuko): return an isolated temporary directory. - callback.Run(GURL(), std::string(), base::File::FILE_ERROR_SECURITY); - return; - } - - delegate_->OpenFileSystem(url.origin(), - url.type(), - mode, - callback, - GetFileSystemRootURI(url.origin(), url.type())); -} - -AsyncFileUtil* SandboxFileSystemBackend::GetAsyncFileUtil( - FileSystemType type) { - DCHECK(delegate_); - return delegate_->file_util(); -} - -WatcherManager* SandboxFileSystemBackend::GetWatcherManager( - FileSystemType type) { - return NULL; -} - -CopyOrMoveFileValidatorFactory* -SandboxFileSystemBackend::GetCopyOrMoveFileValidatorFactory( - FileSystemType type, - base::File::Error* error_code) { - DCHECK(error_code); - *error_code = base::File::FILE_OK; - return NULL; -} - -FileSystemOperation* SandboxFileSystemBackend::CreateFileSystemOperation( - const FileSystemURL& url, - FileSystemContext* context, - base::File::Error* error_code) const { - DCHECK(CanHandleType(url.type())); - DCHECK(error_code); - - DCHECK(delegate_); - scoped_ptr<FileSystemOperationContext> operation_context = - delegate_->CreateFileSystemOperationContext(url, context, error_code); - if (!operation_context) - return NULL; - - SpecialStoragePolicy* policy = delegate_->special_storage_policy(); - if (policy && policy->IsStorageUnlimited(url.origin())) - operation_context->set_quota_limit_type(storage::kQuotaLimitTypeUnlimited); - else - operation_context->set_quota_limit_type(storage::kQuotaLimitTypeLimited); - - return FileSystemOperation::Create(url, context, operation_context.Pass()); -} - -bool SandboxFileSystemBackend::SupportsStreaming( - const storage::FileSystemURL& url) const { - return false; -} - -bool SandboxFileSystemBackend::HasInplaceCopyImplementation( - storage::FileSystemType type) const { - return true; -} - -scoped_ptr<storage::FileStreamReader> -SandboxFileSystemBackend::CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time, - FileSystemContext* context) const { - DCHECK(CanHandleType(url.type())); - DCHECK(delegate_); - return delegate_->CreateFileStreamReader( - url, offset, expected_modification_time, context); -} - -scoped_ptr<storage::FileStreamWriter> -SandboxFileSystemBackend::CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset, - FileSystemContext* context) const { - DCHECK(CanHandleType(url.type())); - DCHECK(delegate_); - return delegate_->CreateFileStreamWriter(url, offset, context, url.type()); -} - -FileSystemQuotaUtil* SandboxFileSystemBackend::GetQuotaUtil() { - return delegate_; -} - -SandboxFileSystemBackendDelegate::OriginEnumerator* -SandboxFileSystemBackend::CreateOriginEnumerator() { - DCHECK(delegate_); - return delegate_->CreateOriginEnumerator(); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/sandbox_file_system_backend.h b/webkit/browser/fileapi/sandbox_file_system_backend.h index 3ab200c..fcbe680 100644 --- a/webkit/browser/fileapi/sandbox_file_system_backend.h +++ b/webkit/browser/fileapi/sandbox_file_system_backend.h @@ -1,85 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_BACKEND_H_ -#define WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_BACKEND_H_ - -#include <set> -#include <string> - -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/file_system_backend.h" -#include "webkit/browser/fileapi/file_system_quota_util.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" -#include "webkit/browser/fileapi/task_runner_bound_observer_list.h" -#include "webkit/browser/quota/special_storage_policy.h" -#include "webkit/browser/storage_browser_export.h" - -namespace storage { - -// TEMPORARY or PERSISTENT filesystems, which are placed under the user's -// profile directory in a sandboxed way. -// This interface also lets one enumerate and remove storage for the origins -// that use the filesystem. -class STORAGE_EXPORT SandboxFileSystemBackend - : public FileSystemBackend { - public: - explicit SandboxFileSystemBackend(SandboxFileSystemBackendDelegate* delegate); - virtual ~SandboxFileSystemBackend(); - - // FileSystemBackend overrides. - virtual bool CanHandleType(FileSystemType type) const OVERRIDE; - virtual void Initialize(FileSystemContext* context) OVERRIDE; - virtual void ResolveURL(const FileSystemURL& url, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; - virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE; - virtual WatcherManager* GetWatcherManager(FileSystemType type) OVERRIDE; - virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( - FileSystemType type, - base::File::Error* error_code) OVERRIDE; - virtual FileSystemOperation* CreateFileSystemOperation( - const FileSystemURL& url, - FileSystemContext* context, - base::File::Error* error_code) const OVERRIDE; - virtual bool SupportsStreaming(const FileSystemURL& url) const OVERRIDE; - virtual bool HasInplaceCopyImplementation( - storage::FileSystemType type) const OVERRIDE; - virtual scoped_ptr<storage::FileStreamReader> CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time, - FileSystemContext* context) const OVERRIDE; - virtual scoped_ptr<FileStreamWriter> CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset, - FileSystemContext* context) const OVERRIDE; - virtual FileSystemQuotaUtil* GetQuotaUtil() OVERRIDE; - - // Returns an origin enumerator of this backend. - // This method can only be called on the file thread. - SandboxFileSystemBackendDelegate::OriginEnumerator* CreateOriginEnumerator(); - - void set_enable_temporary_file_system_in_incognito(bool enable) { - enable_temporary_file_system_in_incognito_ = enable; - } - bool enable_temporary_file_system_in_incognito() const { - return enable_temporary_file_system_in_incognito_; - } - - - private: - SandboxFileSystemBackendDelegate* delegate_; // Not owned. - - bool enable_temporary_file_system_in_incognito_; - - DISALLOW_COPY_AND_ASSIGN(SandboxFileSystemBackend); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_BACKEND_H_ +#include "storage/browser/fileapi/sandbox_file_system_backend.h" diff --git a/webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc b/webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc deleted file mode 100644 index e8ba8a9..0000000 --- a/webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc +++ /dev/null @@ -1,673 +0,0 @@ -// Copyright 2013 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/browser/fileapi/sandbox_file_system_backend_delegate.h" - -#include <vector> - -#include "base/command_line.h" -#include "base/files/file_util.h" -#include "base/metrics/histogram.h" -#include "base/stl_util.h" -#include "base/task_runner_util.h" -#include "net/base/net_util.h" -#include "webkit/browser/blob/file_stream_reader.h" -#include "webkit/browser/fileapi/async_file_util_adapter.h" -#include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/file_system_usage_cache.h" -#include "webkit/browser/fileapi/obfuscated_file_util.h" -#include "webkit/browser/fileapi/quota/quota_backend_impl.h" -#include "webkit/browser/fileapi/quota/quota_reservation.h" -#include "webkit/browser/fileapi/quota/quota_reservation_manager.h" -#include "webkit/browser/fileapi/sandbox_file_stream_writer.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend.h" -#include "webkit/browser/fileapi/sandbox_quota_observer.h" -#include "webkit/browser/quota/quota_manager_proxy.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace storage { - -namespace { - -const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount"; -const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount"; - -const char kOpenFileSystemLabel[] = "FileSystem.OpenFileSystem"; -const char kOpenFileSystemDetailLabel[] = "FileSystem.OpenFileSystemDetail"; -const char kOpenFileSystemDetailNonThrottledLabel[] = - "FileSystem.OpenFileSystemDetailNonthrottled"; -int64 kMinimumStatsCollectionIntervalHours = 1; - -// For type directory names in ObfuscatedFileUtil. -// TODO(kinuko,nhiroki): Each type string registration should be done -// via its own backend. -const char kTemporaryDirectoryName[] = "t"; -const char kPersistentDirectoryName[] = "p"; -const char kSyncableDirectoryName[] = "s"; - -const char* kPrepopulateTypes[] = { - kPersistentDirectoryName, - kTemporaryDirectoryName -}; - -enum FileSystemError { - kOK = 0, - kIncognito, - kInvalidSchemeError, - kCreateDirectoryError, - kNotFound, - kUnknownError, - kFileSystemErrorMax, -}; - -// Restricted names. -// http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions -const base::FilePath::CharType* const kRestrictedNames[] = { - FILE_PATH_LITERAL("."), FILE_PATH_LITERAL(".."), -}; - -// Restricted chars. -const base::FilePath::CharType kRestrictedChars[] = { - FILE_PATH_LITERAL('/'), FILE_PATH_LITERAL('\\'), -}; - -std::string GetTypeStringForURL(const FileSystemURL& url) { - return SandboxFileSystemBackendDelegate::GetTypeString(url.type()); -} - -std::set<std::string> GetKnownTypeStrings() { - std::set<std::string> known_type_strings; - known_type_strings.insert(kTemporaryDirectoryName); - known_type_strings.insert(kPersistentDirectoryName); - known_type_strings.insert(kSyncableDirectoryName); - return known_type_strings; -} - -class ObfuscatedOriginEnumerator - : public SandboxFileSystemBackendDelegate::OriginEnumerator { - public: - explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil* file_util) { - enum_.reset(file_util->CreateOriginEnumerator()); - } - virtual ~ObfuscatedOriginEnumerator() {} - - virtual GURL Next() OVERRIDE { - return enum_->Next(); - } - - virtual bool HasFileSystemType(FileSystemType type) const OVERRIDE { - return enum_->HasTypeDirectory( - SandboxFileSystemBackendDelegate::GetTypeString(type)); - } - - private: - scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enum_; -}; - -void OpenFileSystemOnFileTaskRunner( - ObfuscatedFileUtil* file_util, - const GURL& origin_url, - FileSystemType type, - OpenFileSystemMode mode, - base::File::Error* error_ptr) { - DCHECK(error_ptr); - const bool create = (mode == OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT); - file_util->GetDirectoryForOriginAndType( - origin_url, SandboxFileSystemBackendDelegate::GetTypeString(type), - create, error_ptr); - if (*error_ptr != base::File::FILE_OK) { - UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, - kCreateDirectoryError, - kFileSystemErrorMax); - } else { - UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, kOK, kFileSystemErrorMax); - } - // The reference of file_util will be derefed on the FILE thread - // when the storage of this callback gets deleted regardless of whether - // this method is called or not. -} - -void DidOpenFileSystem( - base::WeakPtr<SandboxFileSystemBackendDelegate> delegate, - const base::Callback<void(base::File::Error error)>& callback, - base::File::Error* error) { - if (delegate.get()) - delegate.get()->CollectOpenFileSystemMetrics(*error); - callback.Run(*error); -} - -template <typename T> -void DeleteSoon(base::SequencedTaskRunner* runner, T* ptr) { - if (!runner->DeleteSoon(FROM_HERE, ptr)) - delete ptr; -} - -} // namespace - -const base::FilePath::CharType -SandboxFileSystemBackendDelegate::kFileSystemDirectory[] = - FILE_PATH_LITERAL("File System"); - -// static -std::string SandboxFileSystemBackendDelegate::GetTypeString( - FileSystemType type) { - switch (type) { - case kFileSystemTypeTemporary: - return kTemporaryDirectoryName; - case kFileSystemTypePersistent: - return kPersistentDirectoryName; - case kFileSystemTypeSyncable: - case kFileSystemTypeSyncableForInternalSync: - return kSyncableDirectoryName; - case kFileSystemTypeUnknown: - default: - NOTREACHED() << "Unknown filesystem type requested:" << type; - return std::string(); - } -} - -SandboxFileSystemBackendDelegate::SandboxFileSystemBackendDelegate( - storage::QuotaManagerProxy* quota_manager_proxy, - base::SequencedTaskRunner* file_task_runner, - const base::FilePath& profile_path, - storage::SpecialStoragePolicy* special_storage_policy, - const FileSystemOptions& file_system_options) - : file_task_runner_(file_task_runner), - sandbox_file_util_(new AsyncFileUtilAdapter( - new ObfuscatedFileUtil(special_storage_policy, - profile_path.Append(kFileSystemDirectory), - file_system_options.env_override(), - file_task_runner, - base::Bind(&GetTypeStringForURL), - GetKnownTypeStrings(), - this))), - file_system_usage_cache_(new FileSystemUsageCache(file_task_runner)), - quota_observer_(new SandboxQuotaObserver(quota_manager_proxy, - file_task_runner, - obfuscated_file_util(), - usage_cache())), - quota_reservation_manager_(new QuotaReservationManager( - scoped_ptr<QuotaReservationManager::QuotaBackend>( - new QuotaBackendImpl(file_task_runner_.get(), - obfuscated_file_util(), - usage_cache(), - quota_manager_proxy)))), - special_storage_policy_(special_storage_policy), - file_system_options_(file_system_options), - is_filesystem_opened_(false), - weak_factory_(this) { - // Prepopulate database only if it can run asynchronously (i.e. the current - // thread is not file_task_runner). Usually this is the case but may not - // in test code. - if (!file_system_options.is_incognito() && - !file_task_runner_->RunsTasksOnCurrentThread()) { - std::vector<std::string> types_to_prepopulate( - &kPrepopulateTypes[0], - &kPrepopulateTypes[arraysize(kPrepopulateTypes)]); - file_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase, - base::Unretained(obfuscated_file_util()), - types_to_prepopulate)); - } -} - -SandboxFileSystemBackendDelegate::~SandboxFileSystemBackendDelegate() { - io_thread_checker_.DetachFromThread(); - - if (!file_task_runner_->RunsTasksOnCurrentThread()) { - DeleteSoon(file_task_runner_.get(), quota_reservation_manager_.release()); - DeleteSoon(file_task_runner_.get(), sandbox_file_util_.release()); - DeleteSoon(file_task_runner_.get(), quota_observer_.release()); - DeleteSoon(file_task_runner_.get(), file_system_usage_cache_.release()); - } -} - -SandboxFileSystemBackendDelegate::OriginEnumerator* -SandboxFileSystemBackendDelegate::CreateOriginEnumerator() { - return new ObfuscatedOriginEnumerator(obfuscated_file_util()); -} - -base::FilePath -SandboxFileSystemBackendDelegate::GetBaseDirectoryForOriginAndType( - const GURL& origin_url, - FileSystemType type, - bool create) { - base::File::Error error = base::File::FILE_OK; - base::FilePath path = obfuscated_file_util()->GetDirectoryForOriginAndType( - origin_url, GetTypeString(type), create, &error); - if (error != base::File::FILE_OK) - return base::FilePath(); - return path; -} - -void SandboxFileSystemBackendDelegate::OpenFileSystem( - const GURL& origin_url, - FileSystemType type, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback, - const GURL& root_url) { - if (!IsAllowedScheme(origin_url)) { - callback.Run(GURL(), std::string(), base::File::FILE_ERROR_SECURITY); - return; - } - - std::string name = GetFileSystemName(origin_url, type); - - base::File::Error* error_ptr = new base::File::Error; - file_task_runner_->PostTaskAndReply( - FROM_HERE, - base::Bind(&OpenFileSystemOnFileTaskRunner, - obfuscated_file_util(), origin_url, type, mode, - base::Unretained(error_ptr)), - base::Bind(&DidOpenFileSystem, - weak_factory_.GetWeakPtr(), - base::Bind(callback, root_url, name), - base::Owned(error_ptr))); - - io_thread_checker_.DetachFromThread(); - is_filesystem_opened_ = true; -} - -scoped_ptr<FileSystemOperationContext> -SandboxFileSystemBackendDelegate::CreateFileSystemOperationContext( - const FileSystemURL& url, - FileSystemContext* context, - base::File::Error* error_code) const { - if (!IsAccessValid(url)) { - *error_code = base::File::FILE_ERROR_SECURITY; - return scoped_ptr<FileSystemOperationContext>(); - } - - const UpdateObserverList* update_observers = GetUpdateObservers(url.type()); - const ChangeObserverList* change_observers = GetChangeObservers(url.type()); - DCHECK(update_observers); - - scoped_ptr<FileSystemOperationContext> operation_context( - new FileSystemOperationContext(context)); - operation_context->set_update_observers(*update_observers); - operation_context->set_change_observers( - change_observers ? *change_observers : ChangeObserverList()); - - return operation_context.Pass(); -} - -scoped_ptr<storage::FileStreamReader> -SandboxFileSystemBackendDelegate::CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time, - FileSystemContext* context) const { - if (!IsAccessValid(url)) - return scoped_ptr<storage::FileStreamReader>(); - return scoped_ptr<storage::FileStreamReader>( - storage::FileStreamReader::CreateForFileSystemFile( - context, url, offset, expected_modification_time)); -} - -scoped_ptr<FileStreamWriter> -SandboxFileSystemBackendDelegate::CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset, - FileSystemContext* context, - FileSystemType type) const { - if (!IsAccessValid(url)) - return scoped_ptr<FileStreamWriter>(); - const UpdateObserverList* observers = GetUpdateObservers(type); - DCHECK(observers); - return scoped_ptr<FileStreamWriter>( - new SandboxFileStreamWriter(context, url, offset, *observers)); -} - -base::File::Error -SandboxFileSystemBackendDelegate::DeleteOriginDataOnFileTaskRunner( - FileSystemContext* file_system_context, - storage::QuotaManagerProxy* proxy, - const GURL& origin_url, - FileSystemType type) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - int64 usage = GetOriginUsageOnFileTaskRunner( - file_system_context, origin_url, type); - usage_cache()->CloseCacheFiles(); - bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType( - origin_url, GetTypeString(type)); - if (result && proxy) { - proxy->NotifyStorageModified(storage::QuotaClient::kFileSystem, - origin_url, - FileSystemTypeToQuotaStorageType(type), - -usage); - } - - if (result) - return base::File::FILE_OK; - return base::File::FILE_ERROR_FAILED; -} - -void SandboxFileSystemBackendDelegate::GetOriginsForTypeOnFileTaskRunner( - FileSystemType type, std::set<GURL>* origins) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(origins); - scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); - GURL origin; - while (!(origin = enumerator->Next()).is_empty()) { - if (enumerator->HasFileSystemType(type)) - origins->insert(origin); - } - switch (type) { - case kFileSystemTypeTemporary: - UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size()); - break; - case kFileSystemTypePersistent: - UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size()); - break; - default: - break; - } -} - -void SandboxFileSystemBackendDelegate::GetOriginsForHostOnFileTaskRunner( - FileSystemType type, const std::string& host, - std::set<GURL>* origins) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(origins); - scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); - GURL origin; - while (!(origin = enumerator->Next()).is_empty()) { - if (host == net::GetHostOrSpecFromURL(origin) && - enumerator->HasFileSystemType(type)) - origins->insert(origin); - } -} - -int64 SandboxFileSystemBackendDelegate::GetOriginUsageOnFileTaskRunner( - FileSystemContext* file_system_context, - const GURL& origin_url, - FileSystemType type) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - - // Don't use usage cache and return recalculated usage for sticky invalidated - // origins. - if (ContainsKey(sticky_dirty_origins_, std::make_pair(origin_url, type))) - return RecalculateUsage(file_system_context, origin_url, type); - - base::FilePath base_path = - GetBaseDirectoryForOriginAndType(origin_url, type, false); - if (base_path.empty() || !base::DirectoryExists(base_path)) - return 0; - base::FilePath usage_file_path = - base_path.Append(FileSystemUsageCache::kUsageFileName); - - bool is_valid = usage_cache()->IsValid(usage_file_path); - uint32 dirty_status = 0; - bool dirty_status_available = - usage_cache()->GetDirty(usage_file_path, &dirty_status); - bool visited = !visited_origins_.insert(origin_url).second; - if (is_valid && (dirty_status == 0 || (dirty_status_available && visited))) { - // The usage cache is clean (dirty == 0) or the origin is already - // initialized and running. Read the cache file to get the usage. - int64 usage = 0; - return usage_cache()->GetUsage(usage_file_path, &usage) ? usage : -1; - } - // The usage cache has not been initialized or the cache is dirty. - // Get the directory size now and update the cache. - usage_cache()->Delete(usage_file_path); - - int64 usage = RecalculateUsage(file_system_context, origin_url, type); - - // This clears the dirty flag too. - usage_cache()->UpdateUsage(usage_file_path, usage); - return usage; -} - -scoped_refptr<QuotaReservation> -SandboxFileSystemBackendDelegate::CreateQuotaReservationOnFileTaskRunner( - const GURL& origin, - FileSystemType type) { - DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(quota_reservation_manager_); - return quota_reservation_manager_->CreateReservation(origin, type); -} - -void SandboxFileSystemBackendDelegate::AddFileUpdateObserver( - FileSystemType type, - FileUpdateObserver* observer, - base::SequencedTaskRunner* task_runner) { - DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread()); - update_observers_[type] = - update_observers_[type].AddObserver(observer, task_runner); -} - -void SandboxFileSystemBackendDelegate::AddFileChangeObserver( - FileSystemType type, - FileChangeObserver* observer, - base::SequencedTaskRunner* task_runner) { - DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread()); - change_observers_[type] = - change_observers_[type].AddObserver(observer, task_runner); -} - -void SandboxFileSystemBackendDelegate::AddFileAccessObserver( - FileSystemType type, - FileAccessObserver* observer, - base::SequencedTaskRunner* task_runner) { - DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread()); - access_observers_[type] = - access_observers_[type].AddObserver(observer, task_runner); -} - -const UpdateObserverList* SandboxFileSystemBackendDelegate::GetUpdateObservers( - FileSystemType type) const { - std::map<FileSystemType, UpdateObserverList>::const_iterator iter = - update_observers_.find(type); - if (iter == update_observers_.end()) - return NULL; - return &iter->second; -} - -const ChangeObserverList* SandboxFileSystemBackendDelegate::GetChangeObservers( - FileSystemType type) const { - std::map<FileSystemType, ChangeObserverList>::const_iterator iter = - change_observers_.find(type); - if (iter == change_observers_.end()) - return NULL; - return &iter->second; -} - -const AccessObserverList* SandboxFileSystemBackendDelegate::GetAccessObservers( - FileSystemType type) const { - std::map<FileSystemType, AccessObserverList>::const_iterator iter = - access_observers_.find(type); - if (iter == access_observers_.end()) - return NULL; - return &iter->second; -} - -void SandboxFileSystemBackendDelegate::RegisterQuotaUpdateObserver( - FileSystemType type) { - AddFileUpdateObserver(type, quota_observer_.get(), file_task_runner_.get()); -} - -void SandboxFileSystemBackendDelegate::InvalidateUsageCache( - const GURL& origin, - FileSystemType type) { - base::File::Error error = base::File::FILE_OK; - base::FilePath usage_file_path = GetUsageCachePathForOriginAndType( - obfuscated_file_util(), origin, type, &error); - if (error != base::File::FILE_OK) - return; - usage_cache()->IncrementDirty(usage_file_path); -} - -void SandboxFileSystemBackendDelegate::StickyInvalidateUsageCache( - const GURL& origin, - FileSystemType type) { - sticky_dirty_origins_.insert(std::make_pair(origin, type)); - quota_observer()->SetUsageCacheEnabled(origin, type, false); - InvalidateUsageCache(origin, type); -} - -FileSystemFileUtil* SandboxFileSystemBackendDelegate::sync_file_util() { - return static_cast<AsyncFileUtilAdapter*>(file_util())->sync_file_util(); -} - -bool SandboxFileSystemBackendDelegate::IsAccessValid( - const FileSystemURL& url) const { - if (!IsAllowedScheme(url.origin())) - return false; - - if (url.path().ReferencesParent()) - return false; - - // Return earlier if the path is '/', because VirtualPath::BaseName() - // returns '/' for '/' and we fail the "basename != '/'" check below. - // (We exclude '.' because it's disallowed by spec.) - if (VirtualPath::IsRootPath(url.path()) && - url.path() != base::FilePath(base::FilePath::kCurrentDirectory)) - return true; - - // Restricted names specified in - // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions - base::FilePath filename = VirtualPath::BaseName(url.path()); - // See if the name is allowed to create. - for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) { - if (filename.value() == kRestrictedNames[i]) - return false; - } - for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) { - if (filename.value().find(kRestrictedChars[i]) != - base::FilePath::StringType::npos) - return false; - } - - return true; -} - -bool SandboxFileSystemBackendDelegate::IsAllowedScheme(const GURL& url) const { - // Basically we only accept http or https. We allow file:// URLs - // only if --allow-file-access-from-files flag is given. - if (url.SchemeIsHTTPOrHTTPS()) - return true; - if (url.SchemeIsFileSystem()) - return url.inner_url() && IsAllowedScheme(*url.inner_url()); - - for (size_t i = 0; - i < file_system_options_.additional_allowed_schemes().size(); - ++i) { - if (url.SchemeIs( - file_system_options_.additional_allowed_schemes()[i].c_str())) - return true; - } - return false; -} - -base::FilePath -SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType( - const GURL& origin_url, - FileSystemType type) { - base::File::Error error; - base::FilePath path = GetUsageCachePathForOriginAndType( - obfuscated_file_util(), origin_url, type, &error); - if (error != base::File::FILE_OK) - return base::FilePath(); - return path; -} - -// static -base::FilePath -SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType( - ObfuscatedFileUtil* sandbox_file_util, - const GURL& origin_url, - FileSystemType type, - base::File::Error* error_out) { - DCHECK(error_out); - *error_out = base::File::FILE_OK; - base::FilePath base_path = sandbox_file_util->GetDirectoryForOriginAndType( - origin_url, GetTypeString(type), false /* create */, error_out); - if (*error_out != base::File::FILE_OK) - return base::FilePath(); - return base_path.Append(FileSystemUsageCache::kUsageFileName); -} - -int64 SandboxFileSystemBackendDelegate::RecalculateUsage( - FileSystemContext* context, - const GURL& origin, - FileSystemType type) { - FileSystemOperationContext operation_context(context); - FileSystemURL url = context->CreateCrackedFileSystemURL( - origin, type, base::FilePath()); - scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator( - obfuscated_file_util()->CreateFileEnumerator( - &operation_context, url, true)); - - base::FilePath file_path_each; - int64 usage = 0; - - while (!(file_path_each = enumerator->Next()).empty()) { - usage += enumerator->Size(); - usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each); - } - - return usage; -} - -void SandboxFileSystemBackendDelegate::CollectOpenFileSystemMetrics( - base::File::Error error_code) { - base::Time now = base::Time::Now(); - bool throttled = now < next_release_time_for_open_filesystem_stat_; - if (!throttled) { - next_release_time_for_open_filesystem_stat_ = - now + base::TimeDelta::FromHours(kMinimumStatsCollectionIntervalHours); - } - -#define REPORT(report_value) \ - UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemDetailLabel, \ - (report_value), \ - kFileSystemErrorMax); \ - if (!throttled) { \ - UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemDetailNonThrottledLabel, \ - (report_value), \ - kFileSystemErrorMax); \ - } - - switch (error_code) { - case base::File::FILE_OK: - REPORT(kOK); - break; - case base::File::FILE_ERROR_INVALID_URL: - REPORT(kInvalidSchemeError); - break; - case base::File::FILE_ERROR_NOT_FOUND: - REPORT(kNotFound); - break; - case base::File::FILE_ERROR_FAILED: - default: - REPORT(kUnknownError); - break; - } -#undef REPORT -} - -ObfuscatedFileUtil* SandboxFileSystemBackendDelegate::obfuscated_file_util() { - return static_cast<ObfuscatedFileUtil*>(sync_file_util()); -} - -// Declared in obfuscated_file_util.h. -// static -ObfuscatedFileUtil* ObfuscatedFileUtil::CreateForTesting( - storage::SpecialStoragePolicy* special_storage_policy, - const base::FilePath& file_system_directory, - leveldb::Env* env_override, - base::SequencedTaskRunner* file_task_runner) { - return new ObfuscatedFileUtil(special_storage_policy, - file_system_directory, - env_override, - file_task_runner, - base::Bind(&GetTypeStringForURL), - GetKnownTypeStrings(), - NULL); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h b/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h index c0ce39e..cc883dc 100644 --- a/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h +++ b/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h @@ -1,260 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_BACKEND_DELEGATE_H_ -#define WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_BACKEND_DELEGATE_H_ - -#include <map> -#include <set> -#include <string> -#include <utility> - -#include "base/files/file_path.h" -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" -#include "base/time/time.h" -#include "webkit/browser/fileapi/file_system_backend.h" -#include "webkit/browser/fileapi/file_system_options.h" -#include "webkit/browser/fileapi/file_system_quota_util.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class SequencedTaskRunner; -} - -namespace content { -class SandboxFileSystemBackendDelegateTest; -class SandboxFileSystemTestHelper; -} - -namespace storage { -class QuotaManagerProxy; -class SpecialStoragePolicy; -} - -namespace storage { -class FileStreamReader; -} - -namespace storage { - -class AsyncFileUtil; -class FileStreamWriter; -class FileSystemFileUtil; -class FileSystemOperationContext; -class FileSystemURL; -class FileSystemUsageCache; -class ObfuscatedFileUtil; -class QuotaReservationManager; -class SandboxFileSystemBackend; -class SandboxQuotaObserver; - -// Delegate implementation of the some methods in Sandbox/SyncFileSystemBackend. -// An instance of this class is created and owned by FileSystemContext. -class STORAGE_EXPORT SandboxFileSystemBackendDelegate - : public FileSystemQuotaUtil { - public: - typedef FileSystemBackend::OpenFileSystemCallback OpenFileSystemCallback; - - // The FileSystem directory name. - static const base::FilePath::CharType kFileSystemDirectory[]; - - // 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; - }; - - // Returns the type directory name in sandbox directory for given |type|. - static std::string GetTypeString(FileSystemType type); - - SandboxFileSystemBackendDelegate( - storage::QuotaManagerProxy* quota_manager_proxy, - base::SequencedTaskRunner* file_task_runner, - const base::FilePath& profile_path, - storage::SpecialStoragePolicy* special_storage_policy, - const FileSystemOptions& file_system_options); - - virtual ~SandboxFileSystemBackendDelegate(); - - // Returns an origin enumerator of sandbox filesystem. - // This method can only be called on the file thread. - OriginEnumerator* CreateOriginEnumerator(); - - // 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 can only be called on the file thread. - base::FilePath GetBaseDirectoryForOriginAndType( - const GURL& origin_url, - FileSystemType type, - bool create); - - // FileSystemBackend helpers. - void OpenFileSystem( - const GURL& origin_url, - FileSystemType type, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback, - const GURL& root_url); - scoped_ptr<FileSystemOperationContext> CreateFileSystemOperationContext( - const FileSystemURL& url, - FileSystemContext* context, - base::File::Error* error_code) const; - scoped_ptr<storage::FileStreamReader> CreateFileStreamReader( - const FileSystemURL& url, - int64 offset, - const base::Time& expected_modification_time, - FileSystemContext* context) const; - scoped_ptr<FileStreamWriter> CreateFileStreamWriter( - const FileSystemURL& url, - int64 offset, - FileSystemContext* context, - FileSystemType type) const; - - // FileSystemQuotaUtil overrides. - virtual base::File::Error DeleteOriginDataOnFileTaskRunner( - FileSystemContext* context, - storage::QuotaManagerProxy* proxy, - const GURL& origin_url, - FileSystemType type) OVERRIDE; - virtual void GetOriginsForTypeOnFileTaskRunner( - FileSystemType type, - std::set<GURL>* origins) OVERRIDE; - virtual void GetOriginsForHostOnFileTaskRunner( - FileSystemType type, - const std::string& host, - std::set<GURL>* origins) OVERRIDE; - virtual int64 GetOriginUsageOnFileTaskRunner( - FileSystemContext* context, - const GURL& origin_url, - FileSystemType type) OVERRIDE; - virtual scoped_refptr<QuotaReservation> - CreateQuotaReservationOnFileTaskRunner( - const GURL& origin_url, - FileSystemType type) OVERRIDE; - virtual void AddFileUpdateObserver( - FileSystemType type, - FileUpdateObserver* observer, - base::SequencedTaskRunner* task_runner) OVERRIDE; - virtual void AddFileChangeObserver( - FileSystemType type, - FileChangeObserver* observer, - base::SequencedTaskRunner* task_runner) OVERRIDE; - virtual void AddFileAccessObserver( - FileSystemType type, - FileAccessObserver* observer, - base::SequencedTaskRunner* task_runner) OVERRIDE; - virtual const UpdateObserverList* GetUpdateObservers( - FileSystemType type) const OVERRIDE; - virtual const ChangeObserverList* GetChangeObservers( - FileSystemType type) const OVERRIDE; - virtual const AccessObserverList* GetAccessObservers( - FileSystemType type) const OVERRIDE; - - // Registers quota observer for file updates on filesystem of |type|. - void RegisterQuotaUpdateObserver(FileSystemType type); - - void InvalidateUsageCache(const GURL& origin_url, - FileSystemType type); - void StickyInvalidateUsageCache(const GURL& origin_url, - FileSystemType type); - - void CollectOpenFileSystemMetrics(base::File::Error error_code); - - base::SequencedTaskRunner* file_task_runner() { - return file_task_runner_.get(); - } - - AsyncFileUtil* file_util() { return sandbox_file_util_.get(); } - FileSystemUsageCache* usage_cache() { return file_system_usage_cache_.get(); } - SandboxQuotaObserver* quota_observer() { return quota_observer_.get(); } - - storage::SpecialStoragePolicy* special_storage_policy() { - return special_storage_policy_.get(); - } - - const FileSystemOptions& file_system_options() const { - return file_system_options_; - } - - FileSystemFileUtil* sync_file_util(); - - private: - friend class QuotaBackendImpl; - friend class SandboxQuotaObserver; - friend class content::SandboxFileSystemBackendDelegateTest; - friend class content::SandboxFileSystemTestHelper; - - // Performs API-specific validity checks on the given path |url|. - // Returns true if access to |url| is valid in this filesystem. - bool IsAccessValid(const FileSystemURL& url) const; - - // Returns true if the given |url|'s scheme is allowed to access - // filesystem. - bool IsAllowedScheme(const GURL& url) const; - - // Returns a path to the usage cache file. - base::FilePath GetUsageCachePathForOriginAndType( - const GURL& origin_url, - FileSystemType type); - - // Returns a path to the usage cache file (static version). - static base::FilePath GetUsageCachePathForOriginAndType( - ObfuscatedFileUtil* sandbox_file_util, - const GURL& origin_url, - FileSystemType type, - base::File::Error* error_out); - - int64 RecalculateUsage(FileSystemContext* context, - const GURL& origin, - FileSystemType type); - - ObfuscatedFileUtil* obfuscated_file_util(); - - scoped_refptr<base::SequencedTaskRunner> file_task_runner_; - - scoped_ptr<AsyncFileUtil> sandbox_file_util_; - scoped_ptr<FileSystemUsageCache> file_system_usage_cache_; - scoped_ptr<SandboxQuotaObserver> quota_observer_; - scoped_ptr<QuotaReservationManager> quota_reservation_manager_; - - scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_; - - FileSystemOptions file_system_options_; - - bool is_filesystem_opened_; - base::ThreadChecker io_thread_checker_; - - // Accessed only on the file thread. - std::set<GURL> visited_origins_; - - std::set<std::pair<GURL, FileSystemType> > sticky_dirty_origins_; - - std::map<FileSystemType, UpdateObserverList> update_observers_; - std::map<FileSystemType, ChangeObserverList> change_observers_; - std::map<FileSystemType, AccessObserverList> access_observers_; - - base::Time next_release_time_for_open_filesystem_stat_; - - base::WeakPtrFactory<SandboxFileSystemBackendDelegate> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(SandboxFileSystemBackendDelegate); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_BACKEND_DELEGATE_H_ +#include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h" diff --git a/webkit/browser/fileapi/sandbox_isolated_origin_database.cc b/webkit/browser/fileapi/sandbox_isolated_origin_database.cc deleted file mode 100644 index 9d8afea..0000000 --- a/webkit/browser/fileapi/sandbox_isolated_origin_database.cc +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2013 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/browser/fileapi/sandbox_isolated_origin_database.h" - -#include "base/files/file_util.h" -#include "base/logging.h" -#include "webkit/browser/fileapi/sandbox_origin_database.h" - -namespace storage { - -// Special directory name for isolated origin. -const base::FilePath::CharType -SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory[] = - FILE_PATH_LITERAL("iso"); - -SandboxIsolatedOriginDatabase::SandboxIsolatedOriginDatabase( - const std::string& origin, - const base::FilePath& file_system_directory, - const base::FilePath& origin_directory) - : migration_checked_(false), - origin_(origin), - file_system_directory_(file_system_directory), - origin_directory_(origin_directory) { -} - -SandboxIsolatedOriginDatabase::~SandboxIsolatedOriginDatabase() { -} - -bool SandboxIsolatedOriginDatabase::HasOriginPath( - const std::string& origin) { - return (origin_ == origin); -} - -bool SandboxIsolatedOriginDatabase::GetPathForOrigin( - const std::string& origin, base::FilePath* directory) { - if (origin != origin_) - return false; - *directory = origin_directory_; - return true; -} - -bool SandboxIsolatedOriginDatabase::RemovePathForOrigin( - const std::string& origin) { - return true; -} - -bool SandboxIsolatedOriginDatabase::ListAllOrigins( - std::vector<OriginRecord>* origins) { - origins->push_back(OriginRecord(origin_, origin_directory_)); - return true; -} - -void SandboxIsolatedOriginDatabase::DropDatabase() { -} - -void SandboxIsolatedOriginDatabase::MigrateBackFromObsoleteOriginDatabase( - const std::string& origin, - const base::FilePath& file_system_directory, - SandboxOriginDatabase* database) { - base::FilePath isolated_directory = - file_system_directory.Append(kObsoleteOriginDirectory); - - if (database->HasOriginPath(origin)) { - // Don't bother. - base::DeleteFile(isolated_directory, true /* recursive */); - return; - } - - base::FilePath directory_name; - if (database->GetPathForOrigin(origin, &directory_name)) { - base::FilePath origin_directory = - file_system_directory.Append(directory_name); - base::DeleteFile(origin_directory, true /* recursive */); - base::Move(isolated_directory, origin_directory); - } -} - -} // namespace storage diff --git a/webkit/browser/fileapi/sandbox_isolated_origin_database.h b/webkit/browser/fileapi/sandbox_isolated_origin_database.h index 2f7b766..940abb1 100644 --- a/webkit/browser/fileapi/sandbox_isolated_origin_database.h +++ b/webkit/browser/fileapi/sandbox_isolated_origin_database.h @@ -1,61 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_SANDBOX_ISOLATED_ORIGIN_DATABASE_H_ -#define WEBKIT_BROWSER_FILEAPI_SANDBOX_ISOLATED_ORIGIN_DATABASE_H_ - -#include <string> -#include <vector> - -#include "webkit/browser/fileapi/sandbox_origin_database_interface.h" - -namespace storage { - -class SandboxOriginDatabase; - -// This origin database implementation supports only one origin -// (therefore is expected to run very fast). -class STORAGE_EXPORT_PRIVATE SandboxIsolatedOriginDatabase - : public SandboxOriginDatabaseInterface { - public: - static const base::FilePath::CharType kObsoleteOriginDirectory[]; - - // Initialize this database for |origin| which makes GetPathForOrigin return - // |origin_directory| (in |file_system_directory|). - SandboxIsolatedOriginDatabase( - const std::string& origin, - const base::FilePath& file_system_directory, - const base::FilePath& origin_directory); - virtual ~SandboxIsolatedOriginDatabase(); - - // SandboxOriginDatabaseInterface overrides. - virtual bool HasOriginPath(const std::string& origin) OVERRIDE; - virtual bool GetPathForOrigin(const std::string& origin, - base::FilePath* directory) OVERRIDE; - virtual bool RemovePathForOrigin(const std::string& origin) OVERRIDE; - virtual bool ListAllOrigins(std::vector<OriginRecord>* origins) OVERRIDE; - virtual void DropDatabase() OVERRIDE; - - // TODO(kinuko): Deprecate this after a few release cycles, e.g. around M33. - static void MigrateBackFromObsoleteOriginDatabase( - const std::string& origin, - const base::FilePath& file_system_directory, - SandboxOriginDatabase* origin_database); - - const std::string& origin() const { return origin_; } - - private: - void MigrateDatabaseIfNeeded(); - - bool migration_checked_; - const std::string origin_; - const base::FilePath file_system_directory_; - const base::FilePath origin_directory_; - - DISALLOW_COPY_AND_ASSIGN(SandboxIsolatedOriginDatabase); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_ISOLATED_ORIGIN_DATABASE_H_ +#include "storage/browser/fileapi/sandbox_isolated_origin_database.h" diff --git a/webkit/browser/fileapi/sandbox_origin_database.cc b/webkit/browser/fileapi/sandbox_origin_database.cc deleted file mode 100644 index 42205ed..0000000 --- a/webkit/browser/fileapi/sandbox_origin_database.cc +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/sandbox_origin_database.h" - -#include <set> -#include <utility> - -#include "base/files/file_enumerator.h" -#include "base/files/file_util.h" -#include "base/format_macros.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/metrics/histogram.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "third_party/leveldatabase/src/include/leveldb/db.h" -#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace { - -const base::FilePath::CharType kOriginDatabaseName[] = - FILE_PATH_LITERAL("Origins"); -const char kOriginKeyPrefix[] = "ORIGIN:"; -const char kLastPathKey[] = "LAST_PATH"; -const int64 kMinimumReportIntervalHours = 1; -const char kInitStatusHistogramLabel[] = "FileSystem.OriginDatabaseInit"; -const char kDatabaseRepairHistogramLabel[] = "FileSystem.OriginDatabaseRepair"; - -enum InitStatus { - INIT_STATUS_OK = 0, - INIT_STATUS_CORRUPTION, - INIT_STATUS_IO_ERROR, - INIT_STATUS_UNKNOWN_ERROR, - INIT_STATUS_MAX -}; - -enum RepairResult { - DB_REPAIR_SUCCEEDED = 0, - DB_REPAIR_FAILED, - DB_REPAIR_MAX -}; - -std::string OriginToOriginKey(const std::string& origin) { - std::string key(kOriginKeyPrefix); - return key + origin; -} - -const char* LastPathKey() { - return kLastPathKey; -} - -} // namespace - -namespace storage { - -SandboxOriginDatabase::SandboxOriginDatabase( - const base::FilePath& file_system_directory, - leveldb::Env* env_override) - : file_system_directory_(file_system_directory), - env_override_(env_override) { -} - -SandboxOriginDatabase::~SandboxOriginDatabase() { -} - -bool SandboxOriginDatabase::Init(InitOption init_option, - RecoveryOption recovery_option) { - if (db_) - return true; - - base::FilePath db_path = GetDatabasePath(); - if (init_option == FAIL_IF_NONEXISTENT && !base::PathExists(db_path)) - return false; - - std::string path = FilePathToString(db_path); - leveldb::Options options; - options.max_open_files = 0; // Use minimum. - options.create_if_missing = true; - if (env_override_) - options.env = env_override_; - leveldb::DB* db; - leveldb::Status status = leveldb::DB::Open(options, path, &db); - ReportInitStatus(status); - if (status.ok()) { - db_.reset(db); - return true; - } - HandleError(FROM_HERE, status); - - // Corruption due to missing necessary MANIFEST-* file causes IOError instead - // of Corruption error. - // Try to repair database even when IOError case. - if (!status.IsCorruption() && !status.IsIOError()) - return false; - - switch (recovery_option) { - case FAIL_ON_CORRUPTION: - return false; - case REPAIR_ON_CORRUPTION: - LOG(WARNING) << "Attempting to repair SandboxOriginDatabase."; - - if (RepairDatabase(path)) { - UMA_HISTOGRAM_ENUMERATION(kDatabaseRepairHistogramLabel, - DB_REPAIR_SUCCEEDED, DB_REPAIR_MAX); - LOG(WARNING) << "Repairing SandboxOriginDatabase completed."; - return true; - } - UMA_HISTOGRAM_ENUMERATION(kDatabaseRepairHistogramLabel, - DB_REPAIR_FAILED, DB_REPAIR_MAX); - // fall through - case DELETE_ON_CORRUPTION: - if (!base::DeleteFile(file_system_directory_, true)) - return false; - if (!base::CreateDirectory(file_system_directory_)) - return false; - return Init(init_option, FAIL_ON_CORRUPTION); - } - NOTREACHED(); - return false; -} - -bool SandboxOriginDatabase::RepairDatabase(const std::string& db_path) { - DCHECK(!db_.get()); - leveldb::Options options; - options.max_open_files = 0; // Use minimum. - if (env_override_) - options.env = env_override_; - if (!leveldb::RepairDB(db_path, options).ok() || - !Init(FAIL_IF_NONEXISTENT, FAIL_ON_CORRUPTION)) { - LOG(WARNING) << "Failed to repair SandboxOriginDatabase."; - return false; - } - - // See if the repaired entries match with what we have on disk. - std::set<base::FilePath> directories; - base::FileEnumerator file_enum(file_system_directory_, - false /* recursive */, - base::FileEnumerator::DIRECTORIES); - base::FilePath path_each; - while (!(path_each = file_enum.Next()).empty()) - directories.insert(path_each.BaseName()); - std::set<base::FilePath>::iterator db_dir_itr = - directories.find(base::FilePath(kOriginDatabaseName)); - // Make sure we have the database file in its directory and therefore we are - // working on the correct path. - DCHECK(db_dir_itr != directories.end()); - directories.erase(db_dir_itr); - - std::vector<OriginRecord> origins; - if (!ListAllOrigins(&origins)) { - DropDatabase(); - return false; - } - - // Delete any obsolete entries from the origins database. - for (std::vector<OriginRecord>::iterator db_origin_itr = origins.begin(); - db_origin_itr != origins.end(); - ++db_origin_itr) { - std::set<base::FilePath>::iterator dir_itr = - directories.find(db_origin_itr->path); - if (dir_itr == directories.end()) { - if (!RemovePathForOrigin(db_origin_itr->origin)) { - DropDatabase(); - return false; - } - } else { - directories.erase(dir_itr); - } - } - - // Delete any directories not listed in the origins database. - for (std::set<base::FilePath>::iterator dir_itr = directories.begin(); - dir_itr != directories.end(); - ++dir_itr) { - if (!base::DeleteFile(file_system_directory_.Append(*dir_itr), - true /* recursive */)) { - DropDatabase(); - return false; - } - } - - return true; -} - -void SandboxOriginDatabase::HandleError( - const tracked_objects::Location& from_here, - const leveldb::Status& status) { - db_.reset(); - LOG(ERROR) << "SandboxOriginDatabase failed at: " - << from_here.ToString() << " with error: " << status.ToString(); -} - -void SandboxOriginDatabase::ReportInitStatus(const leveldb::Status& status) { - base::Time now = base::Time::Now(); - base::TimeDelta minimum_interval = - base::TimeDelta::FromHours(kMinimumReportIntervalHours); - if (last_reported_time_ + minimum_interval >= now) - return; - last_reported_time_ = now; - - if (status.ok()) { - UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, - INIT_STATUS_OK, INIT_STATUS_MAX); - } else if (status.IsCorruption()) { - UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, - INIT_STATUS_CORRUPTION, INIT_STATUS_MAX); - } else if (status.IsIOError()) { - UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, - INIT_STATUS_IO_ERROR, INIT_STATUS_MAX); - } else { - UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, - INIT_STATUS_UNKNOWN_ERROR, INIT_STATUS_MAX); - } -} - -bool SandboxOriginDatabase::HasOriginPath(const std::string& origin) { - if (!Init(FAIL_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) - return false; - if (origin.empty()) - return false; - std::string path; - leveldb::Status status = - db_->Get(leveldb::ReadOptions(), OriginToOriginKey(origin), &path); - if (status.ok()) - return true; - if (status.IsNotFound()) - return false; - HandleError(FROM_HERE, status); - return false; -} - -bool SandboxOriginDatabase::GetPathForOrigin( - const std::string& origin, base::FilePath* directory) { - if (!Init(CREATE_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) - return false; - DCHECK(directory); - if (origin.empty()) - return false; - std::string path_string; - std::string origin_key = OriginToOriginKey(origin); - leveldb::Status status = - db_->Get(leveldb::ReadOptions(), origin_key, &path_string); - if (status.IsNotFound()) { - int last_path_number; - if (!GetLastPathNumber(&last_path_number)) - return false; - path_string = base::StringPrintf("%03u", last_path_number + 1); - // store both back as a single transaction - leveldb::WriteBatch batch; - batch.Put(LastPathKey(), path_string); - batch.Put(origin_key, path_string); - status = db_->Write(leveldb::WriteOptions(), &batch); - if (!status.ok()) { - HandleError(FROM_HERE, status); - return false; - } - } - if (status.ok()) { - *directory = StringToFilePath(path_string); - return true; - } - HandleError(FROM_HERE, status); - return false; -} - -bool SandboxOriginDatabase::RemovePathForOrigin(const std::string& origin) { - if (!Init(CREATE_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) - return false; - leveldb::Status status = - db_->Delete(leveldb::WriteOptions(), OriginToOriginKey(origin)); - if (status.ok() || status.IsNotFound()) - return true; - HandleError(FROM_HERE, status); - return false; -} - -bool SandboxOriginDatabase::ListAllOrigins( - std::vector<OriginRecord>* origins) { - DCHECK(origins); - if (!Init(CREATE_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) { - origins->clear(); - return false; - } - scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); - std::string origin_key_prefix = OriginToOriginKey(std::string()); - iter->Seek(origin_key_prefix); - origins->clear(); - while (iter->Valid() && - StartsWithASCII(iter->key().ToString(), origin_key_prefix, true)) { - std::string origin = - iter->key().ToString().substr(origin_key_prefix.length()); - base::FilePath path = StringToFilePath(iter->value().ToString()); - origins->push_back(OriginRecord(origin, path)); - iter->Next(); - } - return true; -} - -void SandboxOriginDatabase::DropDatabase() { - db_.reset(); -} - -base::FilePath SandboxOriginDatabase::GetDatabasePath() const { - return file_system_directory_.Append(kOriginDatabaseName); -} - -void SandboxOriginDatabase::RemoveDatabase() { - DropDatabase(); - base::DeleteFile(GetDatabasePath(), true /* recursive */); -} - -bool SandboxOriginDatabase::GetLastPathNumber(int* number) { - DCHECK(db_); - DCHECK(number); - std::string number_string; - leveldb::Status status = - db_->Get(leveldb::ReadOptions(), LastPathKey(), &number_string); - if (status.ok()) - return base::StringToInt(number_string, number); - if (!status.IsNotFound()) { - HandleError(FROM_HERE, status); - return false; - } - // Verify that this is a totally new database, and initialize it. - scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); - iter->SeekToFirst(); - if (iter->Valid()) { // DB was not empty, but had no last path number! - LOG(ERROR) << "File system origin database is corrupt!"; - return false; - } - // This is always the first write into the database. If we ever add a - // version number, they should go in in a single transaction. - status = - db_->Put(leveldb::WriteOptions(), LastPathKey(), std::string("-1")); - if (!status.ok()) { - HandleError(FROM_HERE, status); - return false; - } - *number = -1; - return true; -} - -} // namespace storage diff --git a/webkit/browser/fileapi/sandbox_origin_database.h b/webkit/browser/fileapi/sandbox_origin_database.h index f358e14..d684a81 100644 --- a/webkit/browser/fileapi/sandbox_origin_database.h +++ b/webkit/browser/fileapi/sandbox_origin_database.h @@ -1,77 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_SANDBOX_ORIGIN_DATABASE_H_ -#define WEBKIT_BROWSER_FILEAPI_SANDBOX_ORIGIN_DATABASE_H_ - -#include <string> -#include <vector> - -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "webkit/browser/fileapi/sandbox_origin_database_interface.h" - -namespace leveldb { -class DB; -class Env; -class Status; -} - -namespace tracked_objects { -class Location; -} - -namespace storage { - -// All methods of this class other than the constructor may be used only from -// the browser's FILE thread. The constructor may be used on any thread. -class STORAGE_EXPORT_PRIVATE SandboxOriginDatabase - : public SandboxOriginDatabaseInterface { - public: - // Only one instance of SandboxOriginDatabase should exist for a given path - // at a given time. - SandboxOriginDatabase(const base::FilePath& file_system_directory, - leveldb::Env* env_override); - virtual ~SandboxOriginDatabase(); - - // SandboxOriginDatabaseInterface overrides. - virtual bool HasOriginPath(const std::string& origin) OVERRIDE; - virtual bool GetPathForOrigin(const std::string& origin, - base::FilePath* directory) OVERRIDE; - virtual bool RemovePathForOrigin(const std::string& origin) OVERRIDE; - virtual bool ListAllOrigins(std::vector<OriginRecord>* origins) OVERRIDE; - virtual void DropDatabase() OVERRIDE; - - base::FilePath GetDatabasePath() const; - void RemoveDatabase(); - - private: - enum RecoveryOption { - REPAIR_ON_CORRUPTION, - DELETE_ON_CORRUPTION, - FAIL_ON_CORRUPTION, - }; - - enum InitOption { - CREATE_IF_NONEXISTENT, - FAIL_IF_NONEXISTENT, - }; - - bool Init(InitOption init_option, RecoveryOption recovery_option); - bool RepairDatabase(const std::string& db_path); - void HandleError(const tracked_objects::Location& from_here, - const leveldb::Status& status); - void ReportInitStatus(const leveldb::Status& status); - bool GetLastPathNumber(int* number); - - base::FilePath file_system_directory_; - leveldb::Env* env_override_; - scoped_ptr<leveldb::DB> db_; - base::Time last_reported_time_; - DISALLOW_COPY_AND_ASSIGN(SandboxOriginDatabase); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_ORIGIN_DATABASE_H_ +#include "storage/browser/fileapi/sandbox_origin_database.h" diff --git a/webkit/browser/fileapi/sandbox_origin_database_interface.cc b/webkit/browser/fileapi/sandbox_origin_database_interface.cc deleted file mode 100644 index 855e4c3..0000000 --- a/webkit/browser/fileapi/sandbox_origin_database_interface.cc +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 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/browser/fileapi/sandbox_origin_database_interface.h" - -namespace storage { - -SandboxOriginDatabaseInterface::OriginRecord::OriginRecord() { -} - -SandboxOriginDatabaseInterface::OriginRecord::OriginRecord( - const std::string& origin_in, const base::FilePath& path_in) - : origin(origin_in), path(path_in) { -} - -SandboxOriginDatabaseInterface::OriginRecord::~OriginRecord() { -} - -} // namespace storage diff --git a/webkit/browser/fileapi/sandbox_origin_database_interface.h b/webkit/browser/fileapi/sandbox_origin_database_interface.h index 37f6f3d..64b5734 100644 --- a/webkit/browser/fileapi/sandbox_origin_database_interface.h +++ b/webkit/browser/fileapi/sandbox_origin_database_interface.h @@ -1,55 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_SANDBOX_ORIGIN_DATABASE_INTERFACE_H_ -#define WEBKIT_BROWSER_FILEAPI_SANDBOX_ORIGIN_DATABASE_INTERFACE_H_ - -#include <string> -#include <vector> - -#include "base/files/file_path.h" -#include "webkit/browser/storage_browser_export.h" - -namespace storage { - -class STORAGE_EXPORT_PRIVATE SandboxOriginDatabaseInterface { - public: - struct STORAGE_EXPORT_PRIVATE OriginRecord { - std::string origin; - base::FilePath path; - - OriginRecord(); - OriginRecord(const std::string& origin, const base::FilePath& path); - ~OriginRecord(); - }; - - virtual ~SandboxOriginDatabaseInterface() {} - - // Returns true if the origin's path is included in this database. - virtual bool HasOriginPath(const std::string& origin) = 0; - - // This will produce a unique path and add it to its database, if it's not - // already present. - virtual bool GetPathForOrigin(const std::string& origin, - base::FilePath* directory) = 0; - - // Removes the origin's path from the database. - // Returns success if the origin has been successfully removed, or - // the origin is not found. - // (This doesn't remove the actual path). - virtual bool RemovePathForOrigin(const std::string& origin) = 0; - - // Lists all origins in this database. - virtual bool ListAllOrigins(std::vector<OriginRecord>* origins) = 0; - - // This will release all database resources in use; call it to save memory. - virtual void DropDatabase() = 0; - - protected: - SandboxOriginDatabaseInterface() {} -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_ORIGIN_DATABASE_INTERFACE_H_ +#include "storage/browser/fileapi/sandbox_origin_database_interface.h" diff --git a/webkit/browser/fileapi/sandbox_prioritized_origin_database.cc b/webkit/browser/fileapi/sandbox_prioritized_origin_database.cc deleted file mode 100644 index 9308504..0000000 --- a/webkit/browser/fileapi/sandbox_prioritized_origin_database.cc +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright 2013 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/browser/fileapi/sandbox_prioritized_origin_database.h" - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/pickle.h" -#include "webkit/browser/fileapi/sandbox_isolated_origin_database.h" -#include "webkit/browser/fileapi/sandbox_origin_database.h" - -namespace storage { - -namespace { - -const base::FilePath::CharType kPrimaryDirectory[] = - FILE_PATH_LITERAL("primary"); -const base::FilePath::CharType kPrimaryOriginFile[] = - FILE_PATH_LITERAL("primary.origin"); - -bool WritePrimaryOriginFile(const base::FilePath& path, - const std::string& origin) { - base::File file(path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE); - if (!file.IsValid()) - return false; - if (!file.created()) - file.SetLength(0); - Pickle pickle; - pickle.WriteString(origin); - file.Write(0, static_cast<const char*>(pickle.data()), pickle.size()); - file.Flush(); - return true; -} - -bool ReadPrimaryOriginFile(const base::FilePath& path, - std::string* origin) { - std::string buffer; - if (!base::ReadFileToString(path, &buffer)) - return false; - Pickle pickle(buffer.data(), buffer.size()); - PickleIterator iter(pickle); - return pickle.ReadString(&iter, origin) && !origin->empty(); -} - -} // namespace - -SandboxPrioritizedOriginDatabase::SandboxPrioritizedOriginDatabase( - const base::FilePath& file_system_directory, - leveldb::Env* env_override) - : file_system_directory_(file_system_directory), - env_override_(env_override), - primary_origin_file_( - file_system_directory_.Append(kPrimaryOriginFile)) { -} - -SandboxPrioritizedOriginDatabase::~SandboxPrioritizedOriginDatabase() { -} - -bool SandboxPrioritizedOriginDatabase::InitializePrimaryOrigin( - const std::string& origin) { - if (!primary_origin_database_) { - if (!MaybeLoadPrimaryOrigin() && ResetPrimaryOrigin(origin)) { - MaybeMigrateDatabase(origin); - primary_origin_database_.reset( - new SandboxIsolatedOriginDatabase( - origin, - file_system_directory_, - base::FilePath(kPrimaryDirectory))); - return true; - } - } - - if (primary_origin_database_) - return primary_origin_database_->HasOriginPath(origin); - - return false; -} - -std::string SandboxPrioritizedOriginDatabase::GetPrimaryOrigin() { - MaybeLoadPrimaryOrigin(); - if (primary_origin_database_) - return primary_origin_database_->origin(); - return std::string(); -} - -bool SandboxPrioritizedOriginDatabase::HasOriginPath( - const std::string& origin) { - MaybeInitializeDatabases(false); - if (primary_origin_database_ && - primary_origin_database_->HasOriginPath(origin)) - return true; - if (origin_database_) - return origin_database_->HasOriginPath(origin); - return false; -} - -bool SandboxPrioritizedOriginDatabase::GetPathForOrigin( - const std::string& origin, base::FilePath* directory) { - MaybeInitializeDatabases(true); - if (primary_origin_database_ && - primary_origin_database_->GetPathForOrigin(origin, directory)) - return true; - DCHECK(origin_database_); - return origin_database_->GetPathForOrigin(origin, directory); -} - -bool SandboxPrioritizedOriginDatabase::RemovePathForOrigin( - const std::string& origin) { - MaybeInitializeDatabases(false); - if (primary_origin_database_ && - primary_origin_database_->HasOriginPath(origin)) { - primary_origin_database_.reset(); - base::DeleteFile(file_system_directory_.Append(kPrimaryOriginFile), - true /* recursive */); - return true; - } - if (origin_database_) - return origin_database_->RemovePathForOrigin(origin); - return true; -} - -bool SandboxPrioritizedOriginDatabase::ListAllOrigins( - std::vector<OriginRecord>* origins) { - // SandboxOriginDatabase may clear the |origins|, so call this before - // primary_origin_database_. - MaybeInitializeDatabases(false); - if (origin_database_ && !origin_database_->ListAllOrigins(origins)) - return false; - if (primary_origin_database_) - return primary_origin_database_->ListAllOrigins(origins); - return true; -} - -void SandboxPrioritizedOriginDatabase::DropDatabase() { - primary_origin_database_.reset(); - origin_database_.reset(); -} - -bool SandboxPrioritizedOriginDatabase::MaybeLoadPrimaryOrigin() { - if (primary_origin_database_) - return true; - std::string saved_origin; - if (!ReadPrimaryOriginFile(primary_origin_file_, &saved_origin)) - return false; - primary_origin_database_.reset( - new SandboxIsolatedOriginDatabase( - saved_origin, - file_system_directory_, - base::FilePath(kPrimaryDirectory))); - return true; -} - -bool SandboxPrioritizedOriginDatabase::ResetPrimaryOrigin( - const std::string& origin) { - DCHECK(!primary_origin_database_); - if (!WritePrimaryOriginFile(primary_origin_file_, origin)) - return false; - // We reset the primary origin directory too. - // (This means the origin file corruption causes data loss - // We could keep the directory there as the same origin will likely - // become the primary origin, but let's play conservatively.) - base::DeleteFile(file_system_directory_.Append(kPrimaryDirectory), - true /* recursive */); - return true; -} - -void SandboxPrioritizedOriginDatabase::MaybeMigrateDatabase( - const std::string& origin) { - MaybeInitializeNonPrimaryDatabase(false); - if (!origin_database_) - return; - if (origin_database_->HasOriginPath(origin)) { - base::FilePath directory_name; - if (origin_database_->GetPathForOrigin(origin, &directory_name) && - directory_name != base::FilePath(kPrimaryOriginFile)) { - base::FilePath from_path = file_system_directory_.Append(directory_name); - base::FilePath to_path = file_system_directory_.Append(kPrimaryDirectory); - - if (base::PathExists(to_path)) - base::DeleteFile(to_path, true /* recursive */); - base::Move(from_path, to_path); - } - - origin_database_->RemovePathForOrigin(origin); - } - - std::vector<OriginRecord> origins; - origin_database_->ListAllOrigins(&origins); - if (origins.empty()) { - origin_database_->RemoveDatabase(); - origin_database_.reset(); - } -} - -void SandboxPrioritizedOriginDatabase::MaybeInitializeDatabases( - bool create) { - MaybeLoadPrimaryOrigin(); - MaybeInitializeNonPrimaryDatabase(create); -} - -void SandboxPrioritizedOriginDatabase::MaybeInitializeNonPrimaryDatabase( - bool create) { - if (origin_database_) - return; - - origin_database_.reset(new SandboxOriginDatabase(file_system_directory_, - env_override_)); - if (!create && !base::DirectoryExists(origin_database_->GetDatabasePath())) { - origin_database_.reset(); - return; - } -} - -SandboxOriginDatabase* -SandboxPrioritizedOriginDatabase::GetSandboxOriginDatabase() { - MaybeInitializeNonPrimaryDatabase(true); - return origin_database_.get(); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/sandbox_prioritized_origin_database.h b/webkit/browser/fileapi/sandbox_prioritized_origin_database.h index 960ad27..0a745fd 100644 --- a/webkit/browser/fileapi/sandbox_prioritized_origin_database.h +++ b/webkit/browser/fileapi/sandbox_prioritized_origin_database.h @@ -1,72 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_SANDBOX_PRIORITIZED_ORIGIN_DATABASE_H_ -#define WEBKIT_BROWSER_FILEAPI_SANDBOX_PRIORITIZED_ORIGIN_DATABASE_H_ - -#include <string> -#include <vector> - -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/sandbox_origin_database_interface.h" - -namespace leveldb { -class Env; -} - -namespace storage { - -class ObfuscatedFileUtil; -class SandboxIsolatedOriginDatabase; -class SandboxOriginDatabase; - -class STORAGE_EXPORT_PRIVATE SandboxPrioritizedOriginDatabase - : public SandboxOriginDatabaseInterface { - public: - SandboxPrioritizedOriginDatabase(const base::FilePath& file_system_directory, - leveldb::Env* env_override); - virtual ~SandboxPrioritizedOriginDatabase(); - - // Sets |origin| as primary origin in this database (e.g. may - // allow faster access). - // Returns false if this database already has a primary origin - // which is different from |origin|. - bool InitializePrimaryOrigin(const std::string& origin); - std::string GetPrimaryOrigin(); - - // SandboxOriginDatabaseInterface overrides. - virtual bool HasOriginPath(const std::string& origin) OVERRIDE; - virtual bool GetPathForOrigin(const std::string& origin, - base::FilePath* directory) OVERRIDE; - virtual bool RemovePathForOrigin(const std::string& origin) OVERRIDE; - virtual bool ListAllOrigins(std::vector<OriginRecord>* origins) OVERRIDE; - virtual void DropDatabase() OVERRIDE; - - const base::FilePath& primary_origin_file() const { - return primary_origin_file_; - } - - private: - bool MaybeLoadPrimaryOrigin(); - bool ResetPrimaryOrigin(const std::string& origin); - void MaybeMigrateDatabase(const std::string& origin); - void MaybeInitializeDatabases(bool create); - void MaybeInitializeNonPrimaryDatabase(bool create); - - // For migration. - friend class ObfuscatedFileUtil; - SandboxOriginDatabase* GetSandboxOriginDatabase(); - - const base::FilePath file_system_directory_; - leveldb::Env* env_override_; - const base::FilePath primary_origin_file_; - scoped_ptr<SandboxOriginDatabase> origin_database_; - scoped_ptr<SandboxIsolatedOriginDatabase> primary_origin_database_; - - DISALLOW_COPY_AND_ASSIGN(SandboxPrioritizedOriginDatabase); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_PRIORITIZED_ORIGIN_DATABASE_H_ +#include "storage/browser/fileapi/sandbox_prioritized_origin_database.h" diff --git a/webkit/browser/fileapi/sandbox_quota_observer.cc b/webkit/browser/fileapi/sandbox_quota_observer.cc deleted file mode 100644 index 412fd50..0000000 --- a/webkit/browser/fileapi/sandbox_quota_observer.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2012 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/browser/fileapi/sandbox_quota_observer.h" - -#include "base/sequenced_task_runner.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/file_system_usage_cache.h" -#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" -#include "webkit/browser/fileapi/timed_task_helper.h" -#include "webkit/browser/quota/quota_client.h" -#include "webkit/browser/quota/quota_manager_proxy.h" -#include "webkit/common/fileapi/file_system_util.h" - -namespace storage { - -SandboxQuotaObserver::SandboxQuotaObserver( - storage::QuotaManagerProxy* quota_manager_proxy, - base::SequencedTaskRunner* update_notify_runner, - ObfuscatedFileUtil* sandbox_file_util, - FileSystemUsageCache* file_system_usage_cache) - : quota_manager_proxy_(quota_manager_proxy), - update_notify_runner_(update_notify_runner), - sandbox_file_util_(sandbox_file_util), - file_system_usage_cache_(file_system_usage_cache) { -} - -SandboxQuotaObserver::~SandboxQuotaObserver() {} - -void SandboxQuotaObserver::OnStartUpdate(const FileSystemURL& url) { - DCHECK(update_notify_runner_->RunsTasksOnCurrentThread()); - base::FilePath usage_file_path = GetUsageCachePath(url); - if (usage_file_path.empty()) - return; - file_system_usage_cache_->IncrementDirty(usage_file_path); -} - -void SandboxQuotaObserver::OnUpdate(const FileSystemURL& url, - int64 delta) { - DCHECK(update_notify_runner_->RunsTasksOnCurrentThread()); - - if (quota_manager_proxy_.get()) { - quota_manager_proxy_->NotifyStorageModified( - storage::QuotaClient::kFileSystem, - url.origin(), - FileSystemTypeToQuotaStorageType(url.type()), - delta); - } - - base::FilePath usage_file_path = GetUsageCachePath(url); - if (usage_file_path.empty()) - return; - - pending_update_notification_[usage_file_path] += delta; - if (!delayed_cache_update_helper_) { - delayed_cache_update_helper_.reset( - new TimedTaskHelper(update_notify_runner_.get())); - delayed_cache_update_helper_->Start( - FROM_HERE, - base::TimeDelta(), // No delay. - base::Bind(&SandboxQuotaObserver::ApplyPendingUsageUpdate, - base::Unretained(this))); - } -} - -void SandboxQuotaObserver::OnEndUpdate(const FileSystemURL& url) { - DCHECK(update_notify_runner_->RunsTasksOnCurrentThread()); - - base::FilePath usage_file_path = GetUsageCachePath(url); - if (usage_file_path.empty()) - return; - - PendingUpdateNotificationMap::iterator found = - pending_update_notification_.find(usage_file_path); - if (found != pending_update_notification_.end()) { - UpdateUsageCacheFile(found->first, found->second); - pending_update_notification_.erase(found); - } - - file_system_usage_cache_->DecrementDirty(usage_file_path); -} - -void SandboxQuotaObserver::OnAccess(const FileSystemURL& url) { - if (quota_manager_proxy_.get()) { - quota_manager_proxy_->NotifyStorageAccessed( - storage::QuotaClient::kFileSystem, - url.origin(), - FileSystemTypeToQuotaStorageType(url.type())); - } -} - -void SandboxQuotaObserver::SetUsageCacheEnabled( - const GURL& origin, - FileSystemType type, - bool enabled) { - if (quota_manager_proxy_.get()) { - quota_manager_proxy_->SetUsageCacheEnabled( - storage::QuotaClient::kFileSystem, - origin, - FileSystemTypeToQuotaStorageType(type), - enabled); - } -} - -base::FilePath SandboxQuotaObserver::GetUsageCachePath( - const FileSystemURL& url) { - DCHECK(sandbox_file_util_); - base::File::Error error = base::File::FILE_OK; - base::FilePath path = - SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType( - sandbox_file_util_, url.origin(), url.type(), &error); - if (error != base::File::FILE_OK) { - LOG(WARNING) << "Could not get usage cache path for: " - << url.DebugString(); - return base::FilePath(); - } - return path; -} - -void SandboxQuotaObserver::ApplyPendingUsageUpdate() { - delayed_cache_update_helper_.reset(); - for (PendingUpdateNotificationMap::iterator itr = - pending_update_notification_.begin(); - itr != pending_update_notification_.end(); - ++itr) { - UpdateUsageCacheFile(itr->first, itr->second); - } - pending_update_notification_.clear(); -} - -void SandboxQuotaObserver::UpdateUsageCacheFile( - const base::FilePath& usage_file_path, - int64 delta) { - DCHECK(!usage_file_path.empty()); - if (!usage_file_path.empty() && delta != 0) - file_system_usage_cache_->AtomicUpdateUsageByDelta(usage_file_path, delta); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/sandbox_quota_observer.h b/webkit/browser/fileapi/sandbox_quota_observer.h index 7a90757..1df1a65 100644 --- a/webkit/browser/fileapi/sandbox_quota_observer.h +++ b/webkit/browser/fileapi/sandbox_quota_observer.h @@ -1,81 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_SANDBOX_QUOTA_OBSERVER_H_ -#define WEBKIT_BROWSER_FILEAPI_SANDBOX_QUOTA_OBSERVER_H_ - -#include <map> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "webkit/browser/fileapi/file_observers.h" -#include "webkit/browser/fileapi/file_system_url.h" - -namespace base { -class SequencedTaskRunner; -} - -namespace storage { -class QuotaManagerProxy; -} - -namespace storage { - -class FileSystemUsageCache; -class FileSystemURL; -class TimedTaskHelper; -class ObfuscatedFileUtil; - -class SandboxQuotaObserver - : public FileUpdateObserver, - public FileAccessObserver { - public: - typedef std::map<base::FilePath, int64> PendingUpdateNotificationMap; - - SandboxQuotaObserver(storage::QuotaManagerProxy* quota_manager_proxy, - base::SequencedTaskRunner* update_notify_runner, - ObfuscatedFileUtil* sandbox_file_util, - FileSystemUsageCache* file_system_usage_cache_); - virtual ~SandboxQuotaObserver(); - - // FileUpdateObserver overrides. - virtual void OnStartUpdate(const FileSystemURL& url) OVERRIDE; - virtual void OnUpdate(const FileSystemURL& url, int64 delta) OVERRIDE; - virtual void OnEndUpdate(const FileSystemURL& url) OVERRIDE; - - // FileAccessObserver overrides. - virtual void OnAccess(const FileSystemURL& url) OVERRIDE; - - void SetUsageCacheEnabled(const GURL& origin, - FileSystemType type, - bool enabled); - - private: - void ApplyPendingUsageUpdate(); - void UpdateUsageCacheFile(const base::FilePath& usage_file_path, int64 delta); - - base::FilePath GetUsageCachePath(const FileSystemURL& url); - - scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; - scoped_refptr<base::SequencedTaskRunner> update_notify_runner_; - - // Not owned; sandbox_file_util_ should have identical lifetime with this. - ObfuscatedFileUtil* sandbox_file_util_; - - // Not owned; file_system_usage_cache_ should have longer lifetime than this. - FileSystemUsageCache* file_system_usage_cache_; - - PendingUpdateNotificationMap pending_update_notification_; - scoped_ptr<TimedTaskHelper> delayed_cache_update_helper_; - - DISALLOW_COPY_AND_ASSIGN(SandboxQuotaObserver); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_QUOTA_OBSERVER_H_ +#include "storage/browser/fileapi/sandbox_quota_observer.h" diff --git a/webkit/browser/fileapi/task_runner_bound_observer_list.h b/webkit/browser/fileapi/task_runner_bound_observer_list.h index a3228ff..a5f463e 100644 --- a/webkit/browser/fileapi/task_runner_bound_observer_list.h +++ b/webkit/browser/fileapi/task_runner_bound_observer_list.h @@ -1,99 +1,5 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_TASK_RUNNER_BOUND_OBSERVER_LIST_H_ -#define WEBKIT_BROWSER_FILEAPI_TASK_RUNNER_BOUND_OBSERVER_LIST_H_ - -#include <map> - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner.h" -#include "base/threading/thread.h" - -namespace storage { - -// A wrapper for dispatching method. -template <class T, class Method, class Params> -void NotifyWrapper(T obj, Method m, const Params& p) { - DispatchToMethod(base::internal::UnwrapTraits<T>::Unwrap(obj), m, p); -} - -// An observer list helper to notify on a given task runner. -// Observer pointers (stored as ObserverStoreType) must be kept alive -// until this list dispatches all the notifications. -// -// Unlike regular ObserverList or ObserverListThreadSafe internal observer -// list is immutable (though not declared const) and cannot be modified after -// constructed. -// -// It is ok to specify scoped_refptr<Observer> as ObserverStoreType to -// explicitly keep references if necessary. -template <class Observer, class ObserverStoreType = Observer*> -class TaskRunnerBoundObserverList { - public: - typedef scoped_refptr<base::SequencedTaskRunner> TaskRunnerPtr; - typedef std::map<ObserverStoreType, TaskRunnerPtr> ObserversListMap; - - // Creates an empty list. - TaskRunnerBoundObserverList<Observer, ObserverStoreType>() {} - - // Creates a new list with given |observers|. - explicit TaskRunnerBoundObserverList<Observer, ObserverStoreType>( - const ObserversListMap& observers) - : observers_(observers) {} - - virtual ~TaskRunnerBoundObserverList<Observer, ObserverStoreType>() {} - - // Returns a new observer list with given observer. - // It is valid to give NULL as |runner_to_notify|, and in that case - // notifications are dispatched on the current runner. - // Note that this is a const method and does NOT change 'this' observer - // list but returns a new list. - TaskRunnerBoundObserverList<Observer, ObserverStoreType> AddObserver( - Observer* observer, - base::SequencedTaskRunner* runner_to_notify) const { - ObserversListMap observers = observers_; - observers.insert(std::make_pair(observer, runner_to_notify)); - return TaskRunnerBoundObserverList<Observer, ObserverStoreType>(observers); - } - - // Notify on the task runner that is given to AddObserver. - // If we're already on the runner this just dispatches the method. - template <class Method, class Params> - void Notify(Method method, const Params& params) const { - COMPILE_ASSERT( - (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), - badunboundmethodparams); - for (typename ObserversListMap::const_iterator it = observers_.begin(); - it != observers_.end(); ++it) { - if (!it->second.get() || it->second->RunsTasksOnCurrentThread()) { - DispatchToMethod(UnwrapTraits::Unwrap(it->first), method, params); - continue; - } - it->second->PostTask( - FROM_HERE, - base::Bind(&NotifyWrapper<ObserverStoreType, Method, Params>, - it->first, method, params)); - } - } - - private: - typedef base::internal::UnwrapTraits<ObserverStoreType> UnwrapTraits; - - ObserversListMap observers_; -}; - -class FileAccessObserver; -class FileChangeObserver; -class FileUpdateObserver; - -typedef TaskRunnerBoundObserverList<FileAccessObserver> AccessObserverList; -typedef TaskRunnerBoundObserverList<FileChangeObserver> ChangeObserverList; -typedef TaskRunnerBoundObserverList<FileUpdateObserver> UpdateObserverList; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_TASK_RUNNER_BOUND_OBSERVER_LIST_H_ +#include "storage/browser/fileapi/task_runner_bound_observer_list.h" diff --git a/webkit/browser/fileapi/timed_task_helper.cc b/webkit/browser/fileapi/timed_task_helper.cc deleted file mode 100644 index 4794723..0000000 --- a/webkit/browser/fileapi/timed_task_helper.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2013 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/browser/fileapi/timed_task_helper.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/sequenced_task_runner.h" - -namespace storage { - -struct TimedTaskHelper::Tracker { - explicit Tracker(TimedTaskHelper* timer) : timer(timer) {} - - ~Tracker() { - if (timer) - timer->tracker_ = NULL; - } - - TimedTaskHelper* timer; -}; - -TimedTaskHelper::TimedTaskHelper(base::SequencedTaskRunner* task_runner) - : task_runner_(task_runner), - tracker_(NULL) { -} - -TimedTaskHelper::~TimedTaskHelper() { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - if (tracker_) - tracker_->timer = NULL; -} - -bool TimedTaskHelper::IsRunning() const { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - return tracker_ != NULL; -} - -void TimedTaskHelper::Start( - const tracked_objects::Location& posted_from, - base::TimeDelta delay, - const base::Closure& user_task) { - posted_from_ = posted_from; - delay_ = delay; - user_task_ = user_task; - Reset(); -} - -void TimedTaskHelper::Reset() { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - DCHECK(!user_task_.is_null()); - desired_run_time_ = base::TimeTicks::Now() + delay_; - - if (tracker_) - return; - - // Initialize the tracker for the first time. - tracker_ = new Tracker(this); - PostDelayedTask(make_scoped_ptr(tracker_), delay_); -} - -// static -void TimedTaskHelper::Fired(scoped_ptr<Tracker> tracker) { - if (!tracker->timer) - return; - TimedTaskHelper* timer = tracker->timer; - timer->OnFired(tracker.Pass()); -} - -void TimedTaskHelper::OnFired(scoped_ptr<Tracker> tracker) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - base::TimeTicks now = base::TimeTicks::Now(); - if (desired_run_time_ > now) { - PostDelayedTask(tracker.Pass(), desired_run_time_ - now); - return; - } - tracker.reset(); - base::Closure task = user_task_; - user_task_.Reset(); - task.Run(); -} - -void TimedTaskHelper::PostDelayedTask(scoped_ptr<Tracker> tracker, - base::TimeDelta delay) { - task_runner_->PostDelayedTask( - posted_from_, - base::Bind(&TimedTaskHelper::Fired, base::Passed(&tracker)), - delay); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/timed_task_helper.h b/webkit/browser/fileapi/timed_task_helper.h index 5ea145f..956eb58 100644 --- a/webkit/browser/fileapi/timed_task_helper.h +++ b/webkit/browser/fileapi/timed_task_helper.h @@ -1,59 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_TIMED_TASK_HELPER_H_ -#define WEBKIT_BROWSER_FILEAPI_TIMED_TASK_HELPER_H_ - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/location.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class SequencedTaskRunner; -} - -namespace storage { - -// Works similarly as base::Timer, but takes SequencedTaskRunner and -// runs tasks on it (instead of implicitly bound to a thread). -// TODO(kinuko): This has nothing to do with fileapi. Move somewhere -// more common place. -class STORAGE_EXPORT TimedTaskHelper { - public: - explicit TimedTaskHelper(base::SequencedTaskRunner* task_runner); - ~TimedTaskHelper(); - - bool IsRunning() const; - void Start(const tracked_objects::Location& posted_from, - base::TimeDelta delay, - const base::Closure& user_task); - void Reset(); - - private: - struct Tracker; - static void Fired(scoped_ptr<Tracker> tracker); - - void OnFired(scoped_ptr<Tracker> tracker); - void PostDelayedTask(scoped_ptr<Tracker> tracker, base::TimeDelta delay); - - scoped_refptr<base::SequencedTaskRunner> task_runner_; - tracked_objects::Location posted_from_; - base::TimeDelta delay_; - base::Closure user_task_; - - base::TimeTicks desired_run_time_; - - // This is set to non-null and owned by a timer task while timer is running. - Tracker* tracker_; - - DISALLOW_COPY_AND_ASSIGN(TimedTaskHelper); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_TIMED_TASK_HELPER_H_ +#include "storage/browser/fileapi/timed_task_helper.h" diff --git a/webkit/browser/fileapi/transient_file_util.cc b/webkit/browser/fileapi/transient_file_util.cc deleted file mode 100644 index 334b5ed..0000000 --- a/webkit/browser/fileapi/transient_file_util.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2013 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/browser/fileapi/transient_file_util.h" - -#include <string> - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/file_system_url.h" -#include "webkit/browser/fileapi/isolated_context.h" - -using storage::ScopedFile; - -namespace storage { - -namespace { - -void RevokeFileSystem(const std::string& filesystem_id, - const base::FilePath& /*path*/) { - IsolatedContext::GetInstance()->RevokeFileSystem(filesystem_id); -} - -} // namespace - -ScopedFile TransientFileUtil::CreateSnapshotFile( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Error* error, - base::File::Info* file_info, - base::FilePath* platform_path) { - DCHECK(file_info); - *error = GetFileInfo(context, url, file_info, platform_path); - if (*error == base::File::FILE_OK && file_info->is_directory) - *error = base::File::FILE_ERROR_NOT_A_FILE; - if (*error != base::File::FILE_OK) - return ScopedFile(); - - // Sets-up a transient filesystem. - DCHECK(!platform_path->empty()); - DCHECK(!url.filesystem_id().empty()); - - ScopedFile scoped_file( - *platform_path, - ScopedFile::DELETE_ON_SCOPE_OUT, - context->task_runner()); - scoped_file.AddScopeOutCallback( - base::Bind(&RevokeFileSystem, url.filesystem_id()), NULL); - - return scoped_file.Pass(); -} - -} // namespace storage diff --git a/webkit/browser/fileapi/transient_file_util.h b/webkit/browser/fileapi/transient_file_util.h index 4125788..cad9e89 100644 --- a/webkit/browser/fileapi/transient_file_util.h +++ b/webkit/browser/fileapi/transient_file_util.h @@ -1,36 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_FILEAPI_TRANSIENT_FILE_UTIL_H_ -#define WEBKIT_BROWSER_FILEAPI_TRANSIENT_FILE_UTIL_H_ - -#include "base/memory/scoped_ptr.h" -#include "webkit/browser/fileapi/local_file_util.h" -#include "webkit/browser/storage_browser_export.h" - -namespace storage { - -class FileSystemOperationContext; - -class STORAGE_EXPORT_PRIVATE TransientFileUtil - : public LocalFileUtil { - public: - TransientFileUtil() {} - virtual ~TransientFileUtil() {} - - // LocalFileUtil overrides. - virtual storage::ScopedFile CreateSnapshotFile( - FileSystemOperationContext* context, - const FileSystemURL& url, - base::File::Error* error, - base::File::Info* file_info, - base::FilePath* platform_path) OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(TransientFileUtil); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_TRANSIENT_FILE_UTIL_H_ +#include "storage/browser/fileapi/transient_file_util.h" diff --git a/webkit/browser/fileapi/watcher_manager.h b/webkit/browser/fileapi/watcher_manager.h index 83a64f6..0b51e73 100644 --- a/webkit/browser/fileapi/watcher_manager.h +++ b/webkit/browser/fileapi/watcher_manager.h @@ -2,66 +2,4 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBKIT_BROWSER_FILEAPI_WATCHER_MANAGER_H_ -#define WEBKIT_BROWSER_FILEAPI_WATCHER_MANAGER_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/callback_forward.h" -#include "base/files/file.h" - -namespace base { -class Time; -} - -namespace storage { - -class FileSystemOperationContext; -class FileSystemURL; - -// An interface for providing entry observing capability for file system -// backends. -// -// It is NOT valid to give null callback to this class, and implementors -// can assume that they don't get any null callbacks. -class WatcherManager { - public: - typedef base::Callback<void(base::File::Error result)> StatusCallback; - - // Observes watched entries. - class Observer { - public: - Observer() {} - virtual ~Observer() {} - - // Notifies about an entry represented by |url| being changed. - virtual void OnEntryChanged(const FileSystemURL& url) = 0; - - // Notifies about an entry represented by |url| being removed. - virtual void OnEntryRemoved(const FileSystemURL& url) = 0; - }; - - virtual ~WatcherManager() {} - - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - virtual bool HasObserver(Observer* observer) const = 0; - - // Observes a directory entry. If the |recursive| mode is not supported then - // FILE_ERROR_INVALID_OPERATION must be returned as an error. If the |url| is - // already watched, or setting up the watcher fails, then |callback| - // must be called with a specific error code. Otherwise |callback| must be - // called with the FILE_OK error code. - virtual void WatchDirectory(const FileSystemURL& url, - bool recursive, - const StatusCallback& callback) = 0; - - // Stops observing an entry represented by |url|. - virtual void UnwatchEntry(const FileSystemURL& url, - const StatusCallback& callback) = 0; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_FILEAPI_WATCHER_MANAGER_H_ +#include "storage/browser/fileapi/watcher_manager.h" diff --git a/webkit/browser/quota/OWNERS b/webkit/browser/quota/OWNERS deleted file mode 100644 index 66ba5d2..0000000 --- a/webkit/browser/quota/OWNERS +++ /dev/null @@ -1 +0,0 @@ -tzik@chromium.org diff --git a/webkit/browser/quota/quota_callbacks.h b/webkit/browser/quota/quota_callbacks.h index 7018aba..a68dee5 100644 --- a/webkit/browser/quota/quota_callbacks.h +++ b/webkit/browser/quota/quota_callbacks.h @@ -1,129 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_QUOTA_QUOTA_CALLBACKS_H_ -#define WEBKIT_BROWSER_QUOTA_QUOTA_CALLBACKS_H_ - -#include <map> -#include <set> -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/tuple.h" -#include "webkit/common/quota/quota_status_code.h" -#include "webkit/common/quota/quota_types.h" - -class GURL; - -namespace storage { - -struct UsageInfo; -typedef std::vector<UsageInfo> UsageInfoEntries; - -// Common callback types that are used throughout in the quota module. -typedef base::Callback<void(int64 usage, - int64 unlimited_usage)> GlobalUsageCallback; -typedef base::Callback<void(QuotaStatusCode status, int64 quota)> QuotaCallback; -typedef base::Callback<void(int64 usage)> UsageCallback; -typedef base::Callback<void(QuotaStatusCode, int64)> AvailableSpaceCallback; -typedef base::Callback<void(QuotaStatusCode)> StatusCallback; -typedef base::Callback<void(const std::set<GURL>& origins, - StorageType type)> GetOriginsCallback; -typedef base::Callback<void(const UsageInfoEntries&)> GetUsageInfoCallback; - -template<typename CallbackType, typename Args> -void DispatchToCallback(const CallbackType& callback, - const Args& args) { - DispatchToMethod(&callback, &CallbackType::Run, args); -} - -// Simple template wrapper for a callback queue. -template <typename CallbackType, typename Args> -class CallbackQueue { - public: - // Returns true if the given |callback| is the first one added to the queue. - bool Add(const CallbackType& callback) { - callbacks_.push_back(callback); - return (callbacks_.size() == 1); - } - - bool HasCallbacks() const { - return !callbacks_.empty(); - } - - // Runs the callbacks added to the queue and clears the queue. - void Run(const Args& args) { - typedef typename std::vector<CallbackType>::iterator iterator; - for (iterator iter = callbacks_.begin(); - iter != callbacks_.end(); ++iter) - DispatchToCallback(*iter, args); - callbacks_.clear(); - } - - private: - std::vector<CallbackType> callbacks_; -}; - -typedef CallbackQueue<GlobalUsageCallback, - Tuple2<int64, int64> > - GlobalUsageCallbackQueue; -typedef CallbackQueue<UsageCallback, Tuple1<int64> > - UsageCallbackQueue; -typedef CallbackQueue<AvailableSpaceCallback, - Tuple2<QuotaStatusCode, int64> > - AvailableSpaceCallbackQueue; -typedef CallbackQueue<QuotaCallback, - Tuple2<QuotaStatusCode, int64> > - GlobalQuotaCallbackQueue; -typedef CallbackQueue<base::Closure, Tuple0> ClosureQueue; - -template <typename CallbackType, typename Key, typename Args> -class CallbackQueueMap { - public: - typedef CallbackQueue<CallbackType, Args> CallbackQueueType; - typedef std::map<Key, CallbackQueueType> CallbackMap; - typedef typename CallbackMap::iterator iterator; - - bool Add(const Key& key, const CallbackType& callback) { - return callback_map_[key].Add(callback); - } - - bool HasCallbacks(const Key& key) const { - return (callback_map_.find(key) != callback_map_.end()); - } - - bool HasAnyCallbacks() const { - return !callback_map_.empty(); - } - - iterator Begin() { return callback_map_.begin(); } - iterator End() { return callback_map_.end(); } - - void Clear() { callback_map_.clear(); } - - // Runs the callbacks added for the given |key| and clears the key - // from the map. - void Run(const Key& key, const Args& args) { - if (!this->HasCallbacks(key)) - return; - CallbackQueueType& queue = callback_map_[key]; - queue.Run(args); - callback_map_.erase(key); - } - - private: - CallbackMap callback_map_; -}; - -typedef CallbackQueueMap<UsageCallback, std::string, Tuple1<int64> > - HostUsageCallbackMap; -typedef CallbackQueueMap<QuotaCallback, std::string, - Tuple2<QuotaStatusCode, int64> > - HostQuotaCallbackMap; - -} // namespace storage - -#endif // WEBKIT_QUOTA_QUOTA_TYPES_H_ +#include "storage/browser/quota/quota_callbacks.h" diff --git a/webkit/browser/quota/quota_client.h b/webkit/browser/quota/quota_client.h index 5f94dd0..435cf0f 100644 --- a/webkit/browser/quota/quota_client.h +++ b/webkit/browser/quota/quota_client.h @@ -1,81 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_QUOTA_QUOTA_CLIENT_H_ -#define WEBKIT_BROWSER_QUOTA_QUOTA_CLIENT_H_ - -#include <list> -#include <set> -#include <string> - -#include "base/callback.h" -#include "url/gurl.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/quota/quota_types.h" - -namespace storage { - -// An abstract interface for quota manager clients. -// Each storage API must provide an implementation of this interface and -// register it to the quota manager. -// All the methods are assumed to be called on the IO thread in the browser. -class STORAGE_EXPORT QuotaClient { - public: - typedef base::Callback<void(int64 usage)> GetUsageCallback; - typedef base::Callback<void(const std::set<GURL>& origins)> - GetOriginsCallback; - typedef base::Callback<void(QuotaStatusCode status)> DeletionCallback; - - virtual ~QuotaClient() {} - - enum ID { - kUnknown = 1 << 0, - kFileSystem = 1 << 1, - kDatabase = 1 << 2, - kAppcache = 1 << 3, - kIndexedDatabase = 1 << 4, - kAllClientsMask = -1, - }; - - virtual ID id() const = 0; - - // Called when the quota manager is destroyed. - virtual void OnQuotaManagerDestroyed() = 0; - - // Called by the QuotaManager. - // Gets the amount of data stored in the storage specified by - // |origin_url| and |type|. - // Note it is safe to fire the callback after the QuotaClient is destructed. - virtual void GetOriginUsage(const GURL& origin_url, - StorageType type, - const GetUsageCallback& callback) = 0; - - // Called by the QuotaManager. - // Returns a list of origins that has data in the |type| storage. - // Note it is safe to fire the callback after the QuotaClient is destructed. - virtual void GetOriginsForType(StorageType type, - const GetOriginsCallback& callback) = 0; - - // Called by the QuotaManager. - // Returns a list of origins that match the |host|. - // Note it is safe to fire the callback after the QuotaClient is destructed. - virtual void GetOriginsForHost(StorageType type, - const std::string& host, - const GetOriginsCallback& callback) = 0; - - // Called by the QuotaManager. - // Note it is safe to fire the callback after the QuotaClient is destructed. - virtual void DeleteOriginData(const GURL& origin, - StorageType type, - const DeletionCallback& callback) = 0; - - virtual bool DoesSupport(StorageType type) const = 0; -}; - -// TODO(dmikurube): Replace it to std::vector for efficiency. -typedef std::list<QuotaClient*> QuotaClientList; - -} // namespace storage - -#endif // WEBKIT_BROWSER_QUOTA_QUOTA_CLIENT_H_ +#include "storage/browser/quota/quota_client.h" diff --git a/webkit/browser/quota/quota_database.cc b/webkit/browser/quota/quota_database.cc deleted file mode 100644 index f455272..0000000 --- a/webkit/browser/quota/quota_database.cc +++ /dev/null @@ -1,657 +0,0 @@ -// Copyright 2013 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/browser/quota/quota_database.h" - -#include <string> -#include <vector> - -#include "base/auto_reset.h" -#include "base/bind.h" -#include "base/files/file_util.h" -#include "base/time/time.h" -#include "sql/connection.h" -#include "sql/meta_table.h" -#include "sql/statement.h" -#include "sql/transaction.h" -#include "url/gurl.h" -#include "webkit/browser/quota/special_storage_policy.h" - -namespace storage { -namespace { - -// Definitions for database schema. - -const int kCurrentVersion = 4; -const int kCompatibleVersion = 2; - -const char kHostQuotaTable[] = "HostQuotaTable"; -const char kOriginInfoTable[] = "OriginInfoTable"; -const char kIsOriginTableBootstrapped[] = "IsOriginTableBootstrapped"; - -bool VerifyValidQuotaConfig(const char* key) { - return (key != NULL && - (!strcmp(key, QuotaDatabase::kDesiredAvailableSpaceKey) || - !strcmp(key, QuotaDatabase::kTemporaryQuotaOverrideKey))); -} - -const int kCommitIntervalMs = 30000; - -} // anonymous namespace - -// static -const char QuotaDatabase::kDesiredAvailableSpaceKey[] = "DesiredAvailableSpace"; -const char QuotaDatabase::kTemporaryQuotaOverrideKey[] = - "TemporaryQuotaOverride"; - -const QuotaDatabase::TableSchema QuotaDatabase::kTables[] = { - { kHostQuotaTable, - "(host TEXT NOT NULL," - " type INTEGER NOT NULL," - " quota INTEGER DEFAULT 0," - " UNIQUE(host, type))" }, - { kOriginInfoTable, - "(origin TEXT NOT NULL," - " type INTEGER NOT NULL," - " used_count INTEGER DEFAULT 0," - " last_access_time INTEGER DEFAULT 0," - " last_modified_time INTEGER DEFAULT 0," - " UNIQUE(origin, type))" }, -}; - -// static -const QuotaDatabase::IndexSchema QuotaDatabase::kIndexes[] = { - { "HostIndex", - kHostQuotaTable, - "(host)", - false }, - { "OriginInfoIndex", - kOriginInfoTable, - "(origin)", - false }, - { "OriginLastAccessTimeIndex", - kOriginInfoTable, - "(last_access_time)", - false }, - { "OriginLastModifiedTimeIndex", - kOriginInfoTable, - "(last_modified_time)", - false }, -}; - -struct QuotaDatabase::QuotaTableImporter { - bool Append(const QuotaTableEntry& entry) { - entries.push_back(entry); - return true; - } - std::vector<QuotaTableEntry> entries; -}; - -// Clang requires explicit out-of-line constructors for them. -QuotaDatabase::QuotaTableEntry::QuotaTableEntry() - : type(kStorageTypeUnknown), - quota(0) { -} - -QuotaDatabase::QuotaTableEntry::QuotaTableEntry( - const std::string& host, - StorageType type, - int64 quota) - : host(host), - type(type), - quota(quota) { -} - -QuotaDatabase::OriginInfoTableEntry::OriginInfoTableEntry() - : type(kStorageTypeUnknown), - used_count(0) { -} - -QuotaDatabase::OriginInfoTableEntry::OriginInfoTableEntry( - const GURL& origin, - StorageType type, - int used_count, - const base::Time& last_access_time, - const base::Time& last_modified_time) - : origin(origin), - type(type), - used_count(used_count), - last_access_time(last_access_time), - last_modified_time(last_modified_time) { -} - -// QuotaDatabase ------------------------------------------------------------ -QuotaDatabase::QuotaDatabase(const base::FilePath& path) - : db_file_path_(path), - is_recreating_(false), - is_disabled_(false) { -} - -QuotaDatabase::~QuotaDatabase() { - if (db_) { - db_->CommitTransaction(); - } -} - -void QuotaDatabase::CloseConnection() { - meta_table_.reset(); - db_.reset(); -} - -bool QuotaDatabase::GetHostQuota( - const std::string& host, StorageType type, int64* quota) { - DCHECK(quota); - if (!LazyOpen(false)) - return false; - - const char* kSql = - "SELECT quota" - " FROM HostQuotaTable" - " WHERE host = ? AND type = ?"; - - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, host); - statement.BindInt(1, static_cast<int>(type)); - - if (!statement.Step()) - return false; - - *quota = statement.ColumnInt64(0); - return true; -} - -bool QuotaDatabase::SetHostQuota( - const std::string& host, StorageType type, int64 quota) { - DCHECK_GE(quota, 0); - if (!LazyOpen(true)) - return false; - - const char* kSql = - "INSERT OR REPLACE INTO HostQuotaTable" - " (quota, host, type)" - " VALUES (?, ?, ?)"; - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindInt64(0, quota); - statement.BindString(1, host); - statement.BindInt(2, static_cast<int>(type)); - - if (!statement.Run()) - return false; - - ScheduleCommit(); - return true; -} - -bool QuotaDatabase::SetOriginLastAccessTime( - const GURL& origin, StorageType type, base::Time last_access_time) { - if (!LazyOpen(true)) - return false; - - sql::Statement statement; - - int used_count = 1; - if (FindOriginUsedCount(origin, type, &used_count)) { - ++used_count; - const char* kSql = - "UPDATE OriginInfoTable" - " SET used_count = ?, last_access_time = ?" - " WHERE origin = ? AND type = ?"; - statement.Assign(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - } else { - const char* kSql = - "INSERT INTO OriginInfoTable" - " (used_count, last_access_time, origin, type)" - " VALUES (?, ?, ?, ?)"; - statement.Assign(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - } - statement.BindInt(0, used_count); - statement.BindInt64(1, last_access_time.ToInternalValue()); - statement.BindString(2, origin.spec()); - statement.BindInt(3, static_cast<int>(type)); - - if (!statement.Run()) - return false; - - ScheduleCommit(); - return true; -} - -bool QuotaDatabase::SetOriginLastModifiedTime( - const GURL& origin, StorageType type, base::Time last_modified_time) { - if (!LazyOpen(true)) - return false; - - sql::Statement statement; - - int dummy; - if (FindOriginUsedCount(origin, type, &dummy)) { - const char* kSql = - "UPDATE OriginInfoTable" - " SET last_modified_time = ?" - " WHERE origin = ? AND type = ?"; - statement.Assign(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - } else { - const char* kSql = - "INSERT INTO OriginInfoTable" - " (last_modified_time, origin, type) VALUES (?, ?, ?)"; - statement.Assign(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - } - statement.BindInt64(0, last_modified_time.ToInternalValue()); - statement.BindString(1, origin.spec()); - statement.BindInt(2, static_cast<int>(type)); - - if (!statement.Run()) - return false; - - ScheduleCommit(); - return true; -} - -bool QuotaDatabase::RegisterInitialOriginInfo( - const std::set<GURL>& origins, StorageType type) { - if (!LazyOpen(true)) - return false; - - typedef std::set<GURL>::const_iterator itr_type; - for (itr_type itr = origins.begin(), end = origins.end(); - itr != end; ++itr) { - const char* kSql = - "INSERT OR IGNORE INTO OriginInfoTable" - " (origin, type) VALUES (?, ?)"; - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, itr->spec()); - statement.BindInt(1, static_cast<int>(type)); - - if (!statement.Run()) - return false; - } - - ScheduleCommit(); - return true; -} - -bool QuotaDatabase::DeleteHostQuota( - const std::string& host, StorageType type) { - if (!LazyOpen(false)) - return false; - - const char* kSql = - "DELETE FROM HostQuotaTable" - " WHERE host = ? AND type = ?"; - - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, host); - statement.BindInt(1, static_cast<int>(type)); - - if (!statement.Run()) - return false; - - ScheduleCommit(); - return true; -} - -bool QuotaDatabase::DeleteOriginInfo( - const GURL& origin, StorageType type) { - if (!LazyOpen(false)) - return false; - - const char* kSql = - "DELETE FROM OriginInfoTable" - " WHERE origin = ? AND type = ?"; - - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.spec()); - statement.BindInt(1, static_cast<int>(type)); - - if (!statement.Run()) - return false; - - ScheduleCommit(); - return true; -} - -bool QuotaDatabase::GetQuotaConfigValue(const char* key, int64* value) { - if (!LazyOpen(false)) - return false; - DCHECK(VerifyValidQuotaConfig(key)); - return meta_table_->GetValue(key, value); -} - -bool QuotaDatabase::SetQuotaConfigValue(const char* key, int64 value) { - if (!LazyOpen(true)) - return false; - DCHECK(VerifyValidQuotaConfig(key)); - return meta_table_->SetValue(key, value); -} - -bool QuotaDatabase::GetLRUOrigin( - StorageType type, - const std::set<GURL>& exceptions, - SpecialStoragePolicy* special_storage_policy, - GURL* origin) { - DCHECK(origin); - if (!LazyOpen(false)) - return false; - - const char* kSql = "SELECT origin FROM OriginInfoTable" - " WHERE type = ?" - " ORDER BY last_access_time ASC"; - - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindInt(0, static_cast<int>(type)); - - while (statement.Step()) { - GURL url(statement.ColumnString(0)); - if (exceptions.find(url) != exceptions.end()) - continue; - if (special_storage_policy && - special_storage_policy->IsStorageUnlimited(url)) - continue; - *origin = url; - return true; - } - - *origin = GURL(); - return statement.Succeeded(); -} - -bool QuotaDatabase::GetOriginsModifiedSince( - StorageType type, std::set<GURL>* origins, base::Time modified_since) { - DCHECK(origins); - if (!LazyOpen(false)) - return false; - - const char* kSql = "SELECT origin FROM OriginInfoTable" - " WHERE type = ? AND last_modified_time >= ?"; - - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindInt(0, static_cast<int>(type)); - statement.BindInt64(1, modified_since.ToInternalValue()); - - origins->clear(); - while (statement.Step()) - origins->insert(GURL(statement.ColumnString(0))); - - return statement.Succeeded(); -} - -bool QuotaDatabase::IsOriginDatabaseBootstrapped() { - if (!LazyOpen(true)) - return false; - - int flag = 0; - return meta_table_->GetValue(kIsOriginTableBootstrapped, &flag) && flag; -} - -bool QuotaDatabase::SetOriginDatabaseBootstrapped(bool bootstrap_flag) { - if (!LazyOpen(true)) - return false; - - return meta_table_->SetValue(kIsOriginTableBootstrapped, bootstrap_flag); -} - -void QuotaDatabase::Commit() { - if (!db_) - return; - - if (timer_.IsRunning()) - timer_.Stop(); - - db_->CommitTransaction(); - db_->BeginTransaction(); -} - -void QuotaDatabase::ScheduleCommit() { - if (timer_.IsRunning()) - return; - timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCommitIntervalMs), - this, &QuotaDatabase::Commit); -} - -bool QuotaDatabase::FindOriginUsedCount( - const GURL& origin, StorageType type, int* used_count) { - DCHECK(used_count); - if (!LazyOpen(false)) - return false; - - const char* kSql = - "SELECT used_count FROM OriginInfoTable" - " WHERE origin = ? AND type = ?"; - - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.spec()); - statement.BindInt(1, static_cast<int>(type)); - - if (!statement.Step()) - return false; - - *used_count = statement.ColumnInt(0); - return true; -} - -bool QuotaDatabase::LazyOpen(bool create_if_needed) { - if (db_) - return true; - - // If we tried and failed once, don't try again in the same session - // to avoid creating an incoherent mess on disk. - if (is_disabled_) - return false; - - bool in_memory_only = db_file_path_.empty(); - if (!create_if_needed && - (in_memory_only || !base::PathExists(db_file_path_))) { - return false; - } - - db_.reset(new sql::Connection); - meta_table_.reset(new sql::MetaTable); - - db_->set_histogram_tag("Quota"); - - bool opened = false; - if (in_memory_only) { - opened = db_->OpenInMemory(); - } else if (!base::CreateDirectory(db_file_path_.DirName())) { - LOG(ERROR) << "Failed to create quota database directory."; - } else { - opened = db_->Open(db_file_path_); - if (opened) - db_->Preload(); - } - - if (!opened || !EnsureDatabaseVersion()) { - LOG(ERROR) << "Failed to open the quota database."; - is_disabled_ = true; - db_.reset(); - meta_table_.reset(); - return false; - } - - // Start a long-running transaction. - db_->BeginTransaction(); - - return true; -} - -bool QuotaDatabase::EnsureDatabaseVersion() { - static const size_t kTableCount = ARRAYSIZE_UNSAFE(kTables); - static const size_t kIndexCount = ARRAYSIZE_UNSAFE(kIndexes); - if (!sql::MetaTable::DoesTableExist(db_.get())) - return CreateSchema(db_.get(), meta_table_.get(), - kCurrentVersion, kCompatibleVersion, - kTables, kTableCount, - kIndexes, kIndexCount); - - if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion)) - return false; - - if (meta_table_->GetCompatibleVersionNumber() > kCurrentVersion) { - LOG(WARNING) << "Quota database is too new."; - return false; - } - - if (meta_table_->GetVersionNumber() < kCurrentVersion) { - if (!UpgradeSchema(meta_table_->GetVersionNumber())) - return ResetSchema(); - } - -#ifndef NDEBUG - DCHECK(sql::MetaTable::DoesTableExist(db_.get())); - for (size_t i = 0; i < kTableCount; ++i) { - DCHECK(db_->DoesTableExist(kTables[i].table_name)); - } -#endif - - return true; -} - -// static -bool QuotaDatabase::CreateSchema( - sql::Connection* database, - sql::MetaTable* meta_table, - int schema_version, int compatible_version, - const TableSchema* tables, size_t tables_size, - const IndexSchema* indexes, size_t indexes_size) { - // TODO(kinuko): Factor out the common code to create databases. - sql::Transaction transaction(database); - if (!transaction.Begin()) - return false; - - if (!meta_table->Init(database, schema_version, compatible_version)) - return false; - - for (size_t i = 0; i < tables_size; ++i) { - std::string sql("CREATE TABLE "); - sql += tables[i].table_name; - sql += tables[i].columns; - if (!database->Execute(sql.c_str())) { - VLOG(1) << "Failed to execute " << sql; - return false; - } - } - - for (size_t i = 0; i < indexes_size; ++i) { - std::string sql; - if (indexes[i].unique) - sql += "CREATE UNIQUE INDEX "; - else - sql += "CREATE INDEX "; - sql += indexes[i].index_name; - sql += " ON "; - sql += indexes[i].table_name; - sql += indexes[i].columns; - if (!database->Execute(sql.c_str())) { - VLOG(1) << "Failed to execute " << sql; - return false; - } - } - - return transaction.Commit(); -} - -bool QuotaDatabase::ResetSchema() { - DCHECK(!db_file_path_.empty()); - DCHECK(base::PathExists(db_file_path_)); - VLOG(1) << "Deleting existing quota data and starting over."; - - db_.reset(); - meta_table_.reset(); - - if (!sql::Connection::Delete(db_file_path_)) - return false; - - // So we can't go recursive. - if (is_recreating_) - return false; - - base::AutoReset<bool> auto_reset(&is_recreating_, true); - return LazyOpen(true); -} - -bool QuotaDatabase::UpgradeSchema(int current_version) { - if (current_version == 2) { - QuotaTableImporter importer; - typedef std::vector<QuotaTableEntry> QuotaTableEntries; - if (!DumpQuotaTable(base::Bind(&QuotaTableImporter::Append, - base::Unretained(&importer)))) { - return false; - } - ResetSchema(); - for (QuotaTableEntries::const_iterator iter = importer.entries.begin(); - iter != importer.entries.end(); ++iter) { - if (!SetHostQuota(iter->host, iter->type, iter->quota)) - return false; - } - Commit(); - return true; - } - return false; -} - -bool QuotaDatabase::DumpQuotaTable(const QuotaTableCallback& callback) { - if (!LazyOpen(true)) - return false; - - const char* kSql = "SELECT * FROM HostQuotaTable"; - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - - while (statement.Step()) { - QuotaTableEntry entry = QuotaTableEntry( - statement.ColumnString(0), - static_cast<StorageType>(statement.ColumnInt(1)), - statement.ColumnInt64(2)); - - if (!callback.Run(entry)) - return true; - } - - return statement.Succeeded(); -} - -bool QuotaDatabase::DumpOriginInfoTable( - const OriginInfoTableCallback& callback) { - - if (!LazyOpen(true)) - return false; - - const char* kSql = "SELECT * FROM OriginInfoTable"; - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - - while (statement.Step()) { - OriginInfoTableEntry entry( - GURL(statement.ColumnString(0)), - static_cast<StorageType>(statement.ColumnInt(1)), - statement.ColumnInt(2), - base::Time::FromInternalValue(statement.ColumnInt64(3)), - base::Time::FromInternalValue(statement.ColumnInt64(4))); - - if (!callback.Run(entry)) - return true; - } - - return statement.Succeeded(); -} - -bool operator<(const QuotaDatabase::QuotaTableEntry& lhs, - const QuotaDatabase::QuotaTableEntry& rhs) { - if (lhs.host < rhs.host) return true; - if (rhs.host < lhs.host) return false; - if (lhs.type < rhs.type) return true; - if (rhs.type < lhs.type) return false; - return lhs.quota < rhs.quota; -} - -bool operator<(const QuotaDatabase::OriginInfoTableEntry& lhs, - const QuotaDatabase::OriginInfoTableEntry& rhs) { - if (lhs.origin < rhs.origin) return true; - if (rhs.origin < lhs.origin) return false; - if (lhs.type < rhs.type) return true; - if (rhs.type < lhs.type) return false; - if (lhs.used_count < rhs.used_count) return true; - if (rhs.used_count < lhs.used_count) return false; - return lhs.last_access_time < rhs.last_access_time; -} - -} // namespace storage diff --git a/webkit/browser/quota/quota_database.h b/webkit/browser/quota/quota_database.h index 86ec718..1415004 100644 --- a/webkit/browser/quota/quota_database.h +++ b/webkit/browser/quota/quota_database.h @@ -1,190 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_QUOTA_QUOTA_DATABASE_H_ -#define WEBKIT_BROWSER_QUOTA_QUOTA_DATABASE_H_ - -#include <set> -#include <string> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/files/file_path.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "url/gurl.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/quota/quota_types.h" - -namespace content { -class QuotaDatabaseTest; -} - -namespace sql { -class Connection; -class MetaTable; -} - -class GURL; - -namespace storage { - -class SpecialStoragePolicy; - -// All the methods of this class must run on the DB thread. -class STORAGE_EXPORT_PRIVATE QuotaDatabase { - public: - // Constants for {Get,Set}QuotaConfigValue keys. - static const char kDesiredAvailableSpaceKey[]; - static const char kTemporaryQuotaOverrideKey[]; - - // If 'path' is empty, an in memory database will be used. - explicit QuotaDatabase(const base::FilePath& path); - ~QuotaDatabase(); - - void CloseConnection(); - - bool GetHostQuota(const std::string& host, StorageType type, int64* quota); - bool SetHostQuota(const std::string& host, StorageType type, int64 quota); - bool DeleteHostQuota(const std::string& host, StorageType type); - - bool SetOriginLastAccessTime(const GURL& origin, - StorageType type, - base::Time last_access_time); - - bool SetOriginLastModifiedTime(const GURL& origin, - StorageType type, - base::Time last_modified_time); - - // Register initial |origins| info |type| to the database. - // This method is assumed to be called only after the installation or - // the database schema reset. - bool RegisterInitialOriginInfo( - const std::set<GURL>& origins, StorageType type); - - bool DeleteOriginInfo(const GURL& origin, StorageType type); - - bool GetQuotaConfigValue(const char* key, int64* value); - bool SetQuotaConfigValue(const char* key, int64 value); - - // Sets |origin| to the least recently used origin of origins not included - // in |exceptions| and not granted the special unlimited storage right. - // It returns false when it failed in accessing the database. - // |origin| is set to empty when there is no matching origin. - bool GetLRUOrigin(StorageType type, - const std::set<GURL>& exceptions, - SpecialStoragePolicy* special_storage_policy, - GURL* origin); - - // Populates |origins| with the ones that have been modified since - // the |modified_since|. - bool GetOriginsModifiedSince(StorageType type, - std::set<GURL>* origins, - base::Time modified_since); - - // Returns false if SetOriginDatabaseBootstrapped has never - // been called before, which means existing origins may not have been - // registered. - bool IsOriginDatabaseBootstrapped(); - bool SetOriginDatabaseBootstrapped(bool bootstrap_flag); - - private: - struct STORAGE_EXPORT_PRIVATE QuotaTableEntry { - QuotaTableEntry(); - QuotaTableEntry( - const std::string& host, - StorageType type, - int64 quota); - std::string host; - StorageType type; - int64 quota; - }; - friend STORAGE_EXPORT_PRIVATE bool operator <( - const QuotaTableEntry& lhs, const QuotaTableEntry& rhs); - - struct STORAGE_EXPORT_PRIVATE OriginInfoTableEntry { - OriginInfoTableEntry(); - OriginInfoTableEntry( - const GURL& origin, - StorageType type, - int used_count, - const base::Time& last_access_time, - const base::Time& last_modified_time); - GURL origin; - StorageType type; - int used_count; - base::Time last_access_time; - base::Time last_modified_time; - }; - friend STORAGE_EXPORT_PRIVATE bool operator <( - const OriginInfoTableEntry& lhs, const OriginInfoTableEntry& rhs); - - // Structures used for CreateSchema. - struct TableSchema { - const char* table_name; - const char* columns; - }; - struct IndexSchema { - const char* index_name; - const char* table_name; - const char* columns; - bool unique; - }; - - typedef base::Callback<bool (const QuotaTableEntry&)> QuotaTableCallback; - typedef base::Callback<bool (const OriginInfoTableEntry&)> - OriginInfoTableCallback; - - struct QuotaTableImporter; - - // For long-running transactions support. We always keep a transaction open - // so that multiple transactions can be batched. They are flushed - // with a delay after a modification has been made. We support neither - // nested transactions nor rollback (as we don't need them for now). - void Commit(); - void ScheduleCommit(); - - bool FindOriginUsedCount(const GURL& origin, - StorageType type, - int* used_count); - - bool LazyOpen(bool create_if_needed); - bool EnsureDatabaseVersion(); - bool ResetSchema(); - bool UpgradeSchema(int current_version); - - static bool CreateSchema( - sql::Connection* database, - sql::MetaTable* meta_table, - int schema_version, int compatible_version, - const TableSchema* tables, size_t tables_size, - const IndexSchema* indexes, size_t indexes_size); - - // |callback| may return false to stop reading data. - bool DumpQuotaTable(const QuotaTableCallback& callback); - bool DumpOriginInfoTable(const OriginInfoTableCallback& callback); - - base::FilePath db_file_path_; - - scoped_ptr<sql::Connection> db_; - scoped_ptr<sql::MetaTable> meta_table_; - bool is_recreating_; - bool is_disabled_; - - base::OneShotTimer<QuotaDatabase> timer_; - - friend class content::QuotaDatabaseTest; - friend class QuotaManager; - - static const TableSchema kTables[]; - static const IndexSchema kIndexes[]; - - DISALLOW_COPY_AND_ASSIGN(QuotaDatabase); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_QUOTA_QUOTA_DATABASE_H_ +#include "storage/browser/quota/quota_database.h" diff --git a/webkit/browser/quota/quota_manager.cc b/webkit/browser/quota/quota_manager.cc deleted file mode 100644 index a669008..0000000 --- a/webkit/browser/quota/quota_manager.cc +++ /dev/null @@ -1,1631 +0,0 @@ -// Copyright 2013 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/browser/quota/quota_manager.h" - -#include <algorithm> -#include <deque> -#include <functional> -#include <set> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/metrics/histogram.h" -#include "base/sequenced_task_runner.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/sys_info.h" -#include "base/task_runner_util.h" -#include "base/time/time.h" -#include "net/base/net_util.h" -#include "webkit/browser/quota/quota_database.h" -#include "webkit/browser/quota/quota_manager_proxy.h" -#include "webkit/browser/quota/quota_temporary_storage_evictor.h" -#include "webkit/browser/quota/storage_monitor.h" -#include "webkit/browser/quota/usage_tracker.h" -#include "webkit/common/quota/quota_types.h" - -#define UMA_HISTOGRAM_MBYTES(name, sample) \ - UMA_HISTOGRAM_CUSTOM_COUNTS( \ - (name), static_cast<int>((sample) / kMBytes), \ - 1, 10 * 1024 * 1024 /* 10TB */, 100) - -namespace storage { - -namespace { - -const int64 kMBytes = 1024 * 1024; -const int kMinutesInMilliSeconds = 60 * 1000; - -const int64 kReportHistogramInterval = 60 * 60 * 1000; // 1 hour -const double kTemporaryQuotaRatioToAvail = 1.0 / 3.0; // 33% - -} // namespace - -// Arbitrary for now, but must be reasonably small so that -// in-memory databases can fit. -// TODO(kinuko): Refer SysInfo::AmountOfPhysicalMemory() to determine this. -const int64 QuotaManager::kIncognitoDefaultQuotaLimit = 100 * kMBytes; - -const int64 QuotaManager::kNoLimit = kint64max; - -const int QuotaManager::kPerHostTemporaryPortion = 5; // 20% - -// Cap size for per-host persistent quota determined by the histogram. -// This is a bit lax value because the histogram says nothing about per-host -// persistent storage usage and we determined by global persistent storage -// usage that is less than 10GB for almost all users. -const int64 QuotaManager::kPerHostPersistentQuotaLimit = 10 * 1024 * kMBytes; - -const char QuotaManager::kDatabaseName[] = "QuotaManager"; - -const int QuotaManager::kThresholdOfErrorsToBeBlacklisted = 3; - -// Preserve kMinimumPreserveForSystem disk space for system book-keeping -// when returning the quota to unlimited apps/extensions. -// TODO(kinuko): This should be like 10% of the actual disk space. -// For now we simply use a constant as getting the disk size needs -// platform-dependent code. (http://crbug.com/178976) -int64 QuotaManager::kMinimumPreserveForSystem = 1024 * kMBytes; - -const int QuotaManager::kEvictionIntervalInMilliSeconds = - 30 * kMinutesInMilliSeconds; - -// Heuristics: assuming average cloud server allows a few Gigs storage -// on the server side and the storage needs to be shared for user data -// and by multiple apps. -int64 QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes; - -namespace { - -void CountOriginType(const std::set<GURL>& origins, - SpecialStoragePolicy* policy, - size_t* protected_origins, - size_t* unlimited_origins) { - DCHECK(protected_origins); - DCHECK(unlimited_origins); - *protected_origins = 0; - *unlimited_origins = 0; - if (!policy) - return; - for (std::set<GURL>::const_iterator itr = origins.begin(); - itr != origins.end(); - ++itr) { - if (policy->IsStorageProtected(*itr)) - ++*protected_origins; - if (policy->IsStorageUnlimited(*itr)) - ++*unlimited_origins; - } -} - -bool SetTemporaryGlobalOverrideQuotaOnDBThread(int64* new_quota, - QuotaDatabase* database) { - DCHECK(database); - if (!database->SetQuotaConfigValue( - QuotaDatabase::kTemporaryQuotaOverrideKey, *new_quota)) { - *new_quota = -1; - return false; - } - return true; -} - -bool GetPersistentHostQuotaOnDBThread(const std::string& host, - int64* quota, - QuotaDatabase* database) { - DCHECK(database); - database->GetHostQuota(host, kStorageTypePersistent, quota); - return true; -} - -bool SetPersistentHostQuotaOnDBThread(const std::string& host, - int64* new_quota, - QuotaDatabase* database) { - DCHECK(database); - if (database->SetHostQuota(host, kStorageTypePersistent, *new_quota)) - return true; - *new_quota = 0; - return false; -} - -bool InitializeOnDBThread(int64* temporary_quota_override, - int64* desired_available_space, - QuotaDatabase* database) { - DCHECK(database); - database->GetQuotaConfigValue(QuotaDatabase::kTemporaryQuotaOverrideKey, - temporary_quota_override); - database->GetQuotaConfigValue(QuotaDatabase::kDesiredAvailableSpaceKey, - desired_available_space); - return true; -} - -bool GetLRUOriginOnDBThread(StorageType type, - std::set<GURL>* exceptions, - SpecialStoragePolicy* policy, - GURL* url, - QuotaDatabase* database) { - DCHECK(database); - database->GetLRUOrigin(type, *exceptions, policy, url); - return true; -} - -bool DeleteOriginInfoOnDBThread(const GURL& origin, - StorageType type, - QuotaDatabase* database) { - DCHECK(database); - return database->DeleteOriginInfo(origin, type); -} - -bool InitializeTemporaryOriginsInfoOnDBThread(const std::set<GURL>* origins, - QuotaDatabase* database) { - DCHECK(database); - if (database->IsOriginDatabaseBootstrapped()) - return true; - - // Register existing origins with 0 last time access. - if (database->RegisterInitialOriginInfo(*origins, kStorageTypeTemporary)) { - database->SetOriginDatabaseBootstrapped(true); - return true; - } - return false; -} - -bool UpdateAccessTimeOnDBThread(const GURL& origin, - StorageType type, - base::Time accessed_time, - QuotaDatabase* database) { - DCHECK(database); - return database->SetOriginLastAccessTime(origin, type, accessed_time); -} - -bool UpdateModifiedTimeOnDBThread(const GURL& origin, - StorageType type, - base::Time modified_time, - QuotaDatabase* database) { - DCHECK(database); - return database->SetOriginLastModifiedTime(origin, type, modified_time); -} - -int64 CallSystemGetAmountOfFreeDiskSpace(const base::FilePath& profile_path) { - // Ensure the profile path exists. - if (!base::CreateDirectory(profile_path)) { - LOG(WARNING) << "Create directory failed for path" << profile_path.value(); - return 0; - } - return base::SysInfo::AmountOfFreeDiskSpace(profile_path); -} - -int64 CalculateTemporaryGlobalQuota(int64 global_limited_usage, - int64 available_space) { - DCHECK_GE(global_limited_usage, 0); - int64 avail_space = available_space; - if (avail_space < kint64max - global_limited_usage) { - // We basically calculate the temporary quota by - // [available_space + space_used_for_temp] * kTempQuotaRatio, - // but make sure we'll have no overflow. - avail_space += global_limited_usage; - } - return avail_space * kTemporaryQuotaRatioToAvail; -} - -void DispatchTemporaryGlobalQuotaCallback( - const QuotaCallback& callback, - QuotaStatusCode status, - const UsageAndQuota& usage_and_quota) { - if (status != kQuotaStatusOk) { - callback.Run(status, 0); - return; - } - - callback.Run(status, CalculateTemporaryGlobalQuota( - usage_and_quota.global_limited_usage, - usage_and_quota.available_disk_space)); -} - -int64 CalculateQuotaWithDiskSpace( - int64 available_disk_space, int64 usage, int64 quota) { - if (available_disk_space < QuotaManager::kMinimumPreserveForSystem) { - LOG(WARNING) - << "Running out of disk space for profile." - << " QuotaManager starts forbidding further quota consumption."; - return usage; - } - - if (quota < usage) { - // No more space; cap the quota to the current usage. - return usage; - } - - available_disk_space -= QuotaManager::kMinimumPreserveForSystem; - if (available_disk_space < quota - usage) - return available_disk_space + usage; - - return quota; -} - -int64 CalculateTemporaryHostQuota(int64 host_usage, - int64 global_quota, - int64 global_limited_usage) { - DCHECK_GE(global_limited_usage, 0); - int64 host_quota = global_quota / QuotaManager::kPerHostTemporaryPortion; - if (global_limited_usage > global_quota) - host_quota = std::min(host_quota, host_usage); - return host_quota; -} - -void DispatchUsageAndQuotaForWebApps( - StorageType type, - bool is_incognito, - bool is_unlimited, - bool can_query_disk_size, - const QuotaManager::GetUsageAndQuotaCallback& callback, - QuotaStatusCode status, - const UsageAndQuota& usage_and_quota) { - if (status != kQuotaStatusOk) { - callback.Run(status, 0, 0); - return; - } - - int64 usage = usage_and_quota.usage; - int64 quota = usage_and_quota.quota; - - if (type == kStorageTypeTemporary && !is_unlimited) { - quota = CalculateTemporaryHostQuota( - usage, quota, usage_and_quota.global_limited_usage); - } - - if (is_incognito) { - quota = std::min(quota, QuotaManager::kIncognitoDefaultQuotaLimit); - callback.Run(status, usage, quota); - return; - } - - // For apps with unlimited permission or can_query_disk_size is true (and not - // in incognito mode). - // We assume we can expose the actual disk size for them and cap the quota by - // the available disk space. - if (is_unlimited || can_query_disk_size) { - callback.Run( - status, usage, - CalculateQuotaWithDiskSpace( - usage_and_quota.available_disk_space, - usage, quota)); - return; - } - - callback.Run(status, usage, quota); -} - -} // namespace - -UsageAndQuota::UsageAndQuota() - : usage(0), - global_limited_usage(0), - quota(0), - available_disk_space(0) { -} - -UsageAndQuota::UsageAndQuota( - int64 usage, - int64 global_limited_usage, - int64 quota, - int64 available_disk_space) - : usage(usage), - global_limited_usage(global_limited_usage), - quota(quota), - available_disk_space(available_disk_space) { -} - -class UsageAndQuotaCallbackDispatcher - : public QuotaTask, - public base::SupportsWeakPtr<UsageAndQuotaCallbackDispatcher> { - public: - explicit UsageAndQuotaCallbackDispatcher(QuotaManager* manager) - : QuotaTask(manager), - has_usage_(false), - has_global_limited_usage_(false), - has_quota_(false), - has_available_disk_space_(false), - status_(kQuotaStatusUnknown), - usage_and_quota_(-1, -1, -1, -1), - waiting_callbacks_(1) {} - - virtual ~UsageAndQuotaCallbackDispatcher() {} - - void WaitForResults(const QuotaManager::UsageAndQuotaCallback& callback) { - callback_ = callback; - Start(); - } - - void set_usage(int64 usage) { - usage_and_quota_.usage = usage; - has_usage_ = true; - } - - void set_global_limited_usage(int64 global_limited_usage) { - usage_and_quota_.global_limited_usage = global_limited_usage; - has_global_limited_usage_ = true; - } - - void set_quota(int64 quota) { - usage_and_quota_.quota = quota; - has_quota_ = true; - } - - void set_available_disk_space(int64 available_disk_space) { - usage_and_quota_.available_disk_space = available_disk_space; - has_available_disk_space_ = true; - } - - UsageCallback GetHostUsageCallback() { - ++waiting_callbacks_; - has_usage_ = true; - return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetHostUsage, - AsWeakPtr()); - } - - UsageCallback GetGlobalLimitedUsageCallback() { - ++waiting_callbacks_; - has_global_limited_usage_ = true; - return base::Bind( - &UsageAndQuotaCallbackDispatcher::DidGetGlobalLimitedUsage, - AsWeakPtr()); - } - - QuotaCallback GetQuotaCallback() { - ++waiting_callbacks_; - has_quota_ = true; - return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetQuota, - AsWeakPtr()); - } - - QuotaCallback GetAvailableSpaceCallback() { - ++waiting_callbacks_; - has_available_disk_space_ = true; - return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetAvailableSpace, - AsWeakPtr()); - } - - private: - void DidGetHostUsage(int64 usage) { - if (status_ == kQuotaStatusUnknown) - status_ = kQuotaStatusOk; - usage_and_quota_.usage = usage; - CheckCompleted(); - } - - void DidGetGlobalLimitedUsage(int64 limited_usage) { - if (status_ == kQuotaStatusUnknown) - status_ = kQuotaStatusOk; - usage_and_quota_.global_limited_usage = limited_usage; - CheckCompleted(); - } - - void DidGetQuota(QuotaStatusCode status, int64 quota) { - if (status_ == kQuotaStatusUnknown || status_ == kQuotaStatusOk) - status_ = status; - usage_and_quota_.quota = quota; - CheckCompleted(); - } - - void DidGetAvailableSpace(QuotaStatusCode status, int64 space) { - DCHECK_GE(space, 0); - if (status_ == kQuotaStatusUnknown || status_ == kQuotaStatusOk) - status_ = status; - usage_and_quota_.available_disk_space = space; - CheckCompleted(); - } - - virtual void Run() OVERRIDE { - // We initialize waiting_callbacks to 1 so that we won't run - // the completion callback until here even some of the callbacks - // are dispatched synchronously. - CheckCompleted(); - } - - virtual void Aborted() OVERRIDE { - callback_.Run(kQuotaErrorAbort, UsageAndQuota()); - DeleteSoon(); - } - - virtual void Completed() OVERRIDE { - DCHECK(!has_usage_ || usage_and_quota_.usage >= 0); - DCHECK(!has_global_limited_usage_ || - usage_and_quota_.global_limited_usage >= 0); - DCHECK(!has_quota_ || usage_and_quota_.quota >= 0); - DCHECK(!has_available_disk_space_ || - usage_and_quota_.available_disk_space >= 0); - - callback_.Run(status_, usage_and_quota_); - DeleteSoon(); - } - - void CheckCompleted() { - if (--waiting_callbacks_ <= 0) - CallCompleted(); - } - - // For sanity checks, they're checked only when DCHECK is on. - bool has_usage_; - bool has_global_limited_usage_; - bool has_quota_; - bool has_available_disk_space_; - - QuotaStatusCode status_; - UsageAndQuota usage_and_quota_; - QuotaManager::UsageAndQuotaCallback callback_; - int waiting_callbacks_; - - DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaCallbackDispatcher); -}; - -class QuotaManager::GetUsageInfoTask : public QuotaTask { - public: - GetUsageInfoTask( - QuotaManager* manager, - const GetUsageInfoCallback& callback) - : QuotaTask(manager), - callback_(callback), - weak_factory_(this) { - } - - protected: - virtual void Run() OVERRIDE { - remaining_trackers_ = 3; - // This will populate cached hosts and usage info. - manager()->GetUsageTracker(kStorageTypeTemporary)->GetGlobalUsage( - base::Bind(&GetUsageInfoTask::DidGetGlobalUsage, - weak_factory_.GetWeakPtr(), - kStorageTypeTemporary)); - manager()->GetUsageTracker(kStorageTypePersistent)->GetGlobalUsage( - base::Bind(&GetUsageInfoTask::DidGetGlobalUsage, - weak_factory_.GetWeakPtr(), - kStorageTypePersistent)); - manager()->GetUsageTracker(kStorageTypeSyncable)->GetGlobalUsage( - base::Bind(&GetUsageInfoTask::DidGetGlobalUsage, - weak_factory_.GetWeakPtr(), - kStorageTypeSyncable)); - } - - virtual void Completed() OVERRIDE { - callback_.Run(entries_); - DeleteSoon(); - } - - virtual void Aborted() OVERRIDE { - callback_.Run(UsageInfoEntries()); - DeleteSoon(); - } - - private: - void AddEntries(StorageType type, UsageTracker* tracker) { - std::map<std::string, int64> host_usage; - tracker->GetCachedHostsUsage(&host_usage); - for (std::map<std::string, int64>::const_iterator iter = host_usage.begin(); - iter != host_usage.end(); - ++iter) { - entries_.push_back(UsageInfo(iter->first, type, iter->second)); - } - if (--remaining_trackers_ == 0) - CallCompleted(); - } - - void DidGetGlobalUsage(StorageType type, int64, int64) { - DCHECK(manager()->GetUsageTracker(type)); - AddEntries(type, manager()->GetUsageTracker(type)); - } - - QuotaManager* manager() const { - return static_cast<QuotaManager*>(observer()); - } - - GetUsageInfoCallback callback_; - UsageInfoEntries entries_; - int remaining_trackers_; - base::WeakPtrFactory<GetUsageInfoTask> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(GetUsageInfoTask); -}; - -class QuotaManager::OriginDataDeleter : public QuotaTask { - public: - OriginDataDeleter(QuotaManager* manager, - const GURL& origin, - StorageType type, - int quota_client_mask, - const StatusCallback& callback) - : QuotaTask(manager), - origin_(origin), - type_(type), - quota_client_mask_(quota_client_mask), - error_count_(0), - remaining_clients_(-1), - skipped_clients_(0), - callback_(callback), - weak_factory_(this) {} - - protected: - virtual void Run() OVERRIDE { - error_count_ = 0; - remaining_clients_ = manager()->clients_.size(); - for (QuotaClientList::iterator iter = manager()->clients_.begin(); - iter != manager()->clients_.end(); ++iter) { - if (quota_client_mask_ & (*iter)->id()) { - (*iter)->DeleteOriginData( - origin_, type_, - base::Bind(&OriginDataDeleter::DidDeleteOriginData, - weak_factory_.GetWeakPtr())); - } else { - ++skipped_clients_; - if (--remaining_clients_ == 0) - CallCompleted(); - } - } - } - - virtual void Completed() OVERRIDE { - if (error_count_ == 0) { - // Only remove the entire origin if we didn't skip any client types. - if (skipped_clients_ == 0) - manager()->DeleteOriginFromDatabase(origin_, type_); - callback_.Run(kQuotaStatusOk); - } else { - callback_.Run(kQuotaErrorInvalidModification); - } - DeleteSoon(); - } - - virtual void Aborted() OVERRIDE { - callback_.Run(kQuotaErrorAbort); - DeleteSoon(); - } - - private: - void DidDeleteOriginData(QuotaStatusCode status) { - DCHECK_GT(remaining_clients_, 0); - - if (status != kQuotaStatusOk) - ++error_count_; - - if (--remaining_clients_ == 0) - CallCompleted(); - } - - QuotaManager* manager() const { - return static_cast<QuotaManager*>(observer()); - } - - GURL origin_; - StorageType type_; - int quota_client_mask_; - int error_count_; - int remaining_clients_; - int skipped_clients_; - StatusCallback callback_; - - base::WeakPtrFactory<OriginDataDeleter> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(OriginDataDeleter); -}; - -class QuotaManager::HostDataDeleter : public QuotaTask { - public: - HostDataDeleter(QuotaManager* manager, - const std::string& host, - StorageType type, - int quota_client_mask, - const StatusCallback& callback) - : QuotaTask(manager), - host_(host), - type_(type), - quota_client_mask_(quota_client_mask), - error_count_(0), - remaining_clients_(-1), - remaining_deleters_(-1), - callback_(callback), - weak_factory_(this) {} - - protected: - virtual void Run() OVERRIDE { - error_count_ = 0; - remaining_clients_ = manager()->clients_.size(); - for (QuotaClientList::iterator iter = manager()->clients_.begin(); - iter != manager()->clients_.end(); ++iter) { - (*iter)->GetOriginsForHost( - type_, host_, - base::Bind(&HostDataDeleter::DidGetOriginsForHost, - weak_factory_.GetWeakPtr())); - } - } - - virtual void Completed() OVERRIDE { - if (error_count_ == 0) { - callback_.Run(kQuotaStatusOk); - } else { - callback_.Run(kQuotaErrorInvalidModification); - } - DeleteSoon(); - } - - virtual void Aborted() OVERRIDE { - callback_.Run(kQuotaErrorAbort); - DeleteSoon(); - } - - private: - void DidGetOriginsForHost(const std::set<GURL>& origins) { - DCHECK_GT(remaining_clients_, 0); - - origins_.insert(origins.begin(), origins.end()); - - if (--remaining_clients_ == 0) { - if (!origins_.empty()) - ScheduleOriginsDeletion(); - else - CallCompleted(); - } - } - - void ScheduleOriginsDeletion() { - remaining_deleters_ = origins_.size(); - for (std::set<GURL>::const_iterator p = origins_.begin(); - p != origins_.end(); - ++p) { - OriginDataDeleter* deleter = - new OriginDataDeleter( - manager(), *p, type_, quota_client_mask_, - base::Bind(&HostDataDeleter::DidDeleteOriginData, - weak_factory_.GetWeakPtr())); - deleter->Start(); - } - } - - void DidDeleteOriginData(QuotaStatusCode status) { - DCHECK_GT(remaining_deleters_, 0); - - if (status != kQuotaStatusOk) - ++error_count_; - - if (--remaining_deleters_ == 0) - CallCompleted(); - } - - QuotaManager* manager() const { - return static_cast<QuotaManager*>(observer()); - } - - std::string host_; - StorageType type_; - int quota_client_mask_; - std::set<GURL> origins_; - int error_count_; - int remaining_clients_; - int remaining_deleters_; - StatusCallback callback_; - - base::WeakPtrFactory<HostDataDeleter> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(HostDataDeleter); -}; - -class QuotaManager::GetModifiedSinceHelper { - public: - bool GetModifiedSinceOnDBThread(StorageType type, - base::Time modified_since, - QuotaDatabase* database) { - DCHECK(database); - return database->GetOriginsModifiedSince(type, &origins_, modified_since); - } - - void DidGetModifiedSince(const base::WeakPtr<QuotaManager>& manager, - const GetOriginsCallback& callback, - StorageType type, - bool success) { - if (!manager) { - // The operation was aborted. - callback.Run(std::set<GURL>(), type); - return; - } - manager->DidDatabaseWork(success); - callback.Run(origins_, type); - } - - private: - std::set<GURL> origins_; -}; - -class QuotaManager::DumpQuotaTableHelper { - public: - bool DumpQuotaTableOnDBThread(QuotaDatabase* database) { - DCHECK(database); - return database->DumpQuotaTable( - base::Bind(&DumpQuotaTableHelper::AppendEntry, base::Unretained(this))); - } - - void DidDumpQuotaTable(const base::WeakPtr<QuotaManager>& manager, - const DumpQuotaTableCallback& callback, - bool success) { - if (!manager) { - // The operation was aborted. - callback.Run(QuotaTableEntries()); - return; - } - manager->DidDatabaseWork(success); - callback.Run(entries_); - } - - private: - bool AppendEntry(const QuotaTableEntry& entry) { - entries_.push_back(entry); - return true; - } - - QuotaTableEntries entries_; -}; - -class QuotaManager::DumpOriginInfoTableHelper { - public: - bool DumpOriginInfoTableOnDBThread(QuotaDatabase* database) { - DCHECK(database); - return database->DumpOriginInfoTable( - base::Bind(&DumpOriginInfoTableHelper::AppendEntry, - base::Unretained(this))); - } - - void DidDumpOriginInfoTable(const base::WeakPtr<QuotaManager>& manager, - const DumpOriginInfoTableCallback& callback, - bool success) { - if (!manager) { - // The operation was aborted. - callback.Run(OriginInfoTableEntries()); - return; - } - manager->DidDatabaseWork(success); - callback.Run(entries_); - } - - private: - bool AppendEntry(const OriginInfoTableEntry& entry) { - entries_.push_back(entry); - return true; - } - - OriginInfoTableEntries entries_; -}; - -// QuotaManager --------------------------------------------------------------- - -QuotaManager::QuotaManager( - bool is_incognito, - const base::FilePath& profile_path, - const scoped_refptr<base::SingleThreadTaskRunner>& io_thread, - const scoped_refptr<base::SequencedTaskRunner>& db_thread, - const scoped_refptr<SpecialStoragePolicy>& special_storage_policy) - : is_incognito_(is_incognito), - profile_path_(profile_path), - proxy_(new QuotaManagerProxy(this, io_thread)), - db_disabled_(false), - eviction_disabled_(false), - io_thread_(io_thread), - db_thread_(db_thread), - temporary_quota_initialized_(false), - temporary_quota_override_(-1), - desired_available_space_(-1), - special_storage_policy_(special_storage_policy), - get_disk_space_fn_(&CallSystemGetAmountOfFreeDiskSpace), - storage_monitor_(new StorageMonitor(this)), - weak_factory_(this) { -} - -void QuotaManager::GetUsageInfo(const GetUsageInfoCallback& callback) { - LazyInitialize(); - GetUsageInfoTask* get_usage_info = new GetUsageInfoTask(this, callback); - get_usage_info->Start(); -} - -void QuotaManager::GetUsageAndQuotaForWebApps( - const GURL& origin, - StorageType type, - const GetUsageAndQuotaCallback& callback) { - if (type != kStorageTypeTemporary && - type != kStorageTypePersistent && - type != kStorageTypeSyncable) { - callback.Run(kQuotaErrorNotSupported, 0, 0); - return; - } - - DCHECK(origin == origin.GetOrigin()); - LazyInitialize(); - - bool unlimited = IsStorageUnlimited(origin, type); - bool can_query_disk_size = CanQueryDiskSize(origin); - - UsageAndQuotaCallbackDispatcher* dispatcher = - new UsageAndQuotaCallbackDispatcher(this); - - UsageAndQuota usage_and_quota; - if (unlimited) { - dispatcher->set_quota(kNoLimit); - } else { - if (type == kStorageTypeTemporary) { - GetUsageTracker(type)->GetGlobalLimitedUsage( - dispatcher->GetGlobalLimitedUsageCallback()); - GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback()); - } else if (type == kStorageTypePersistent) { - GetPersistentHostQuota(net::GetHostOrSpecFromURL(origin), - dispatcher->GetQuotaCallback()); - } else { - dispatcher->set_quota(kSyncableStorageDefaultHostQuota); - } - } - - DCHECK(GetUsageTracker(type)); - GetUsageTracker(type)->GetHostUsage(net::GetHostOrSpecFromURL(origin), - dispatcher->GetHostUsageCallback()); - - if (!is_incognito_ && (unlimited || can_query_disk_size)) - GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); - - dispatcher->WaitForResults(base::Bind( - &DispatchUsageAndQuotaForWebApps, - type, is_incognito_, unlimited, can_query_disk_size, - callback)); -} - -void QuotaManager::GetUsageAndQuota( - const GURL& origin, StorageType type, - const GetUsageAndQuotaCallback& callback) { - DCHECK(origin == origin.GetOrigin()); - - if (IsStorageUnlimited(origin, type)) { - callback.Run(kQuotaStatusOk, 0, kNoLimit); - return; - } - - GetUsageAndQuotaForWebApps(origin, type, callback); -} - -void QuotaManager::NotifyStorageAccessed( - QuotaClient::ID client_id, - const GURL& origin, StorageType type) { - DCHECK(origin == origin.GetOrigin()); - NotifyStorageAccessedInternal(client_id, origin, type, base::Time::Now()); -} - -void QuotaManager::NotifyStorageModified( - QuotaClient::ID client_id, - const GURL& origin, StorageType type, int64 delta) { - DCHECK(origin == origin.GetOrigin()); - NotifyStorageModifiedInternal(client_id, origin, type, delta, - base::Time::Now()); -} - -void QuotaManager::NotifyOriginInUse(const GURL& origin) { - DCHECK(io_thread_->BelongsToCurrentThread()); - origins_in_use_[origin]++; -} - -void QuotaManager::NotifyOriginNoLongerInUse(const GURL& origin) { - DCHECK(io_thread_->BelongsToCurrentThread()); - DCHECK(IsOriginInUse(origin)); - int& count = origins_in_use_[origin]; - if (--count == 0) - origins_in_use_.erase(origin); -} - -void QuotaManager::SetUsageCacheEnabled(QuotaClient::ID client_id, - const GURL& origin, - StorageType type, - bool enabled) { - LazyInitialize(); - DCHECK(GetUsageTracker(type)); - GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled); -} - -void QuotaManager::DeleteOriginData( - const GURL& origin, StorageType type, int quota_client_mask, - const StatusCallback& callback) { - LazyInitialize(); - - if (origin.is_empty() || clients_.empty()) { - callback.Run(kQuotaStatusOk); - return; - } - - DCHECK(origin == origin.GetOrigin()); - OriginDataDeleter* deleter = - new OriginDataDeleter(this, origin, type, quota_client_mask, callback); - deleter->Start(); -} - -void QuotaManager::DeleteHostData(const std::string& host, - StorageType type, - int quota_client_mask, - const StatusCallback& callback) { - LazyInitialize(); - - if (host.empty() || clients_.empty()) { - callback.Run(kQuotaStatusOk); - return; - } - - HostDataDeleter* deleter = - new HostDataDeleter(this, host, type, quota_client_mask, callback); - deleter->Start(); -} - -void QuotaManager::GetAvailableSpace(const AvailableSpaceCallback& callback) { - if (!available_space_callbacks_.Add(callback)) - return; - - PostTaskAndReplyWithResult(db_thread_.get(), - FROM_HERE, - base::Bind(get_disk_space_fn_, profile_path_), - base::Bind(&QuotaManager::DidGetAvailableSpace, - weak_factory_.GetWeakPtr())); -} - -void QuotaManager::GetTemporaryGlobalQuota(const QuotaCallback& callback) { - LazyInitialize(); - if (!temporary_quota_initialized_) { - db_initialization_callbacks_.Add(base::Bind( - &QuotaManager::GetTemporaryGlobalQuota, - weak_factory_.GetWeakPtr(), callback)); - return; - } - - if (temporary_quota_override_ > 0) { - callback.Run(kQuotaStatusOk, temporary_quota_override_); - return; - } - - UsageAndQuotaCallbackDispatcher* dispatcher = - new UsageAndQuotaCallbackDispatcher(this); - GetUsageTracker(kStorageTypeTemporary)-> - GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback()); - GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); - dispatcher->WaitForResults( - base::Bind(&DispatchTemporaryGlobalQuotaCallback, callback)); -} - -void QuotaManager::SetTemporaryGlobalOverrideQuota( - int64 new_quota, const QuotaCallback& callback) { - LazyInitialize(); - - if (new_quota < 0) { - if (!callback.is_null()) - callback.Run(kQuotaErrorInvalidModification, -1); - return; - } - - if (db_disabled_) { - if (!callback.is_null()) - callback.Run(kQuotaErrorInvalidAccess, -1); - return; - } - - int64* new_quota_ptr = new int64(new_quota); - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&SetTemporaryGlobalOverrideQuotaOnDBThread, - base::Unretained(new_quota_ptr)), - base::Bind(&QuotaManager::DidSetTemporaryGlobalOverrideQuota, - weak_factory_.GetWeakPtr(), - callback, - base::Owned(new_quota_ptr))); -} - -void QuotaManager::GetPersistentHostQuota(const std::string& host, - const QuotaCallback& callback) { - LazyInitialize(); - if (host.empty()) { - // This could happen if we are called on file:///. - // TODO(kinuko) We may want to respect --allow-file-access-from-files - // command line switch. - callback.Run(kQuotaStatusOk, 0); - return; - } - - if (!persistent_host_quota_callbacks_.Add(host, callback)) - return; - - int64* quota_ptr = new int64(0); - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&GetPersistentHostQuotaOnDBThread, - host, - base::Unretained(quota_ptr)), - base::Bind(&QuotaManager::DidGetPersistentHostQuota, - weak_factory_.GetWeakPtr(), - host, - base::Owned(quota_ptr))); -} - -void QuotaManager::SetPersistentHostQuota(const std::string& host, - int64 new_quota, - const QuotaCallback& callback) { - LazyInitialize(); - if (host.empty()) { - // This could happen if we are called on file:///. - callback.Run(kQuotaErrorNotSupported, 0); - return; - } - - if (new_quota < 0) { - callback.Run(kQuotaErrorInvalidModification, -1); - return; - } - - if (kPerHostPersistentQuotaLimit < new_quota) { - // Cap the requested size at the per-host quota limit. - new_quota = kPerHostPersistentQuotaLimit; - } - - if (db_disabled_) { - callback.Run(kQuotaErrorInvalidAccess, -1); - return; - } - - int64* new_quota_ptr = new int64(new_quota); - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&SetPersistentHostQuotaOnDBThread, - host, - base::Unretained(new_quota_ptr)), - base::Bind(&QuotaManager::DidSetPersistentHostQuota, - weak_factory_.GetWeakPtr(), - host, - callback, - base::Owned(new_quota_ptr))); -} - -void QuotaManager::GetGlobalUsage(StorageType type, - const GlobalUsageCallback& callback) { - LazyInitialize(); - DCHECK(GetUsageTracker(type)); - GetUsageTracker(type)->GetGlobalUsage(callback); -} - -void QuotaManager::GetHostUsage(const std::string& host, - StorageType type, - const UsageCallback& callback) { - LazyInitialize(); - DCHECK(GetUsageTracker(type)); - GetUsageTracker(type)->GetHostUsage(host, callback); -} - -void QuotaManager::GetHostUsage(const std::string& host, - StorageType type, - QuotaClient::ID client_id, - const UsageCallback& callback) { - LazyInitialize(); - DCHECK(GetUsageTracker(type)); - ClientUsageTracker* tracker = - GetUsageTracker(type)->GetClientTracker(client_id); - if (!tracker) { - callback.Run(0); - return; - } - tracker->GetHostUsage(host, callback); -} - -bool QuotaManager::IsTrackingHostUsage(StorageType type, - QuotaClient::ID client_id) const { - UsageTracker* tracker = GetUsageTracker(type); - return tracker && tracker->GetClientTracker(client_id); -} - -void QuotaManager::GetStatistics( - std::map<std::string, std::string>* statistics) { - DCHECK(statistics); - if (temporary_storage_evictor_) { - std::map<std::string, int64> stats; - temporary_storage_evictor_->GetStatistics(&stats); - for (std::map<std::string, int64>::iterator p = stats.begin(); - p != stats.end(); - ++p) - (*statistics)[p->first] = base::Int64ToString(p->second); - } -} - -bool QuotaManager::IsStorageUnlimited(const GURL& origin, - StorageType type) const { - // For syncable storage we should always enforce quota (since the - // quota must be capped by the server limit). - if (type == kStorageTypeSyncable) - return false; - if (type == kStorageTypeQuotaNotManaged) - return true; - return special_storage_policy_.get() && - special_storage_policy_->IsStorageUnlimited(origin); -} - -void QuotaManager::GetOriginsModifiedSince(StorageType type, - base::Time modified_since, - const GetOriginsCallback& callback) { - LazyInitialize(); - GetModifiedSinceHelper* helper = new GetModifiedSinceHelper; - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&GetModifiedSinceHelper::GetModifiedSinceOnDBThread, - base::Unretained(helper), - type, - modified_since), - base::Bind(&GetModifiedSinceHelper::DidGetModifiedSince, - base::Owned(helper), - weak_factory_.GetWeakPtr(), - callback, - type)); -} - -bool QuotaManager::ResetUsageTracker(StorageType type) { - DCHECK(GetUsageTracker(type)); - if (GetUsageTracker(type)->IsWorking()) - return false; - switch (type) { - case kStorageTypeTemporary: - temporary_usage_tracker_.reset(new UsageTracker( - clients_, kStorageTypeTemporary, special_storage_policy_.get(), - storage_monitor_.get())); - return true; - case kStorageTypePersistent: - persistent_usage_tracker_.reset(new UsageTracker( - clients_, kStorageTypePersistent, special_storage_policy_.get(), - storage_monitor_.get())); - return true; - case kStorageTypeSyncable: - syncable_usage_tracker_.reset(new UsageTracker( - clients_, kStorageTypeSyncable, special_storage_policy_.get(), - storage_monitor_.get())); - return true; - default: - NOTREACHED(); - } - return true; -} - -void QuotaManager::AddStorageObserver( - StorageObserver* observer, const StorageObserver::MonitorParams& params) { - DCHECK(observer); - storage_monitor_->AddObserver(observer, params); -} - -void QuotaManager::RemoveStorageObserver(StorageObserver* observer) { - DCHECK(observer); - storage_monitor_->RemoveObserver(observer); -} - -void QuotaManager::RemoveStorageObserverForFilter( - StorageObserver* observer, const StorageObserver::Filter& filter) { - DCHECK(observer); - storage_monitor_->RemoveObserverForFilter(observer, filter); -} - -QuotaManager::~QuotaManager() { - proxy_->manager_ = NULL; - std::for_each(clients_.begin(), clients_.end(), - std::mem_fun(&QuotaClient::OnQuotaManagerDestroyed)); - if (database_) - db_thread_->DeleteSoon(FROM_HERE, database_.release()); -} - -QuotaManager::EvictionContext::EvictionContext() - : evicted_type(kStorageTypeUnknown) { -} - -QuotaManager::EvictionContext::~EvictionContext() { -} - -void QuotaManager::LazyInitialize() { - DCHECK(io_thread_->BelongsToCurrentThread()); - if (database_) { - // Initialization seems to be done already. - return; - } - - // Use an empty path to open an in-memory only databse for incognito. - database_.reset(new QuotaDatabase(is_incognito_ ? base::FilePath() : - profile_path_.AppendASCII(kDatabaseName))); - - temporary_usage_tracker_.reset(new UsageTracker( - clients_, kStorageTypeTemporary, special_storage_policy_.get(), - storage_monitor_.get())); - persistent_usage_tracker_.reset(new UsageTracker( - clients_, kStorageTypePersistent, special_storage_policy_.get(), - storage_monitor_.get())); - syncable_usage_tracker_.reset(new UsageTracker( - clients_, kStorageTypeSyncable, special_storage_policy_.get(), - storage_monitor_.get())); - - int64* temporary_quota_override = new int64(-1); - int64* desired_available_space = new int64(-1); - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&InitializeOnDBThread, - base::Unretained(temporary_quota_override), - base::Unretained(desired_available_space)), - base::Bind(&QuotaManager::DidInitialize, - weak_factory_.GetWeakPtr(), - base::Owned(temporary_quota_override), - base::Owned(desired_available_space))); -} - -void QuotaManager::RegisterClient(QuotaClient* client) { - DCHECK(!database_.get()); - clients_.push_back(client); -} - -UsageTracker* QuotaManager::GetUsageTracker(StorageType type) const { - switch (type) { - case kStorageTypeTemporary: - return temporary_usage_tracker_.get(); - case kStorageTypePersistent: - return persistent_usage_tracker_.get(); - case kStorageTypeSyncable: - return syncable_usage_tracker_.get(); - case kStorageTypeQuotaNotManaged: - return NULL; - case kStorageTypeUnknown: - NOTREACHED(); - } - return NULL; -} - -void QuotaManager::GetCachedOrigins( - StorageType type, std::set<GURL>* origins) { - DCHECK(origins); - LazyInitialize(); - DCHECK(GetUsageTracker(type)); - GetUsageTracker(type)->GetCachedOrigins(origins); -} - -void QuotaManager::NotifyStorageAccessedInternal( - QuotaClient::ID client_id, - const GURL& origin, StorageType type, - base::Time accessed_time) { - LazyInitialize(); - if (type == kStorageTypeTemporary && !lru_origin_callback_.is_null()) { - // Record the accessed origins while GetLRUOrigin task is runing - // to filter out them from eviction. - access_notified_origins_.insert(origin); - } - - if (db_disabled_) - return; - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&UpdateAccessTimeOnDBThread, origin, type, accessed_time), - base::Bind(&QuotaManager::DidDatabaseWork, - weak_factory_.GetWeakPtr())); -} - -void QuotaManager::NotifyStorageModifiedInternal( - QuotaClient::ID client_id, - const GURL& origin, - StorageType type, - int64 delta, - base::Time modified_time) { - LazyInitialize(); - DCHECK(GetUsageTracker(type)); - GetUsageTracker(type)->UpdateUsageCache(client_id, origin, delta); - - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&UpdateModifiedTimeOnDBThread, origin, type, modified_time), - base::Bind(&QuotaManager::DidDatabaseWork, - weak_factory_.GetWeakPtr())); -} - -void QuotaManager::DumpQuotaTable(const DumpQuotaTableCallback& callback) { - DumpQuotaTableHelper* helper = new DumpQuotaTableHelper; - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&DumpQuotaTableHelper::DumpQuotaTableOnDBThread, - base::Unretained(helper)), - base::Bind(&DumpQuotaTableHelper::DidDumpQuotaTable, - base::Owned(helper), - weak_factory_.GetWeakPtr(), - callback)); -} - -void QuotaManager::DumpOriginInfoTable( - const DumpOriginInfoTableCallback& callback) { - DumpOriginInfoTableHelper* helper = new DumpOriginInfoTableHelper; - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&DumpOriginInfoTableHelper::DumpOriginInfoTableOnDBThread, - base::Unretained(helper)), - base::Bind(&DumpOriginInfoTableHelper::DidDumpOriginInfoTable, - base::Owned(helper), - weak_factory_.GetWeakPtr(), - callback)); -} - -void QuotaManager::StartEviction() { - DCHECK(!temporary_storage_evictor_.get()); - temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor( - this, kEvictionIntervalInMilliSeconds)); - if (desired_available_space_ >= 0) - temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction( - desired_available_space_); - temporary_storage_evictor_->Start(); -} - -void QuotaManager::DeleteOriginFromDatabase( - const GURL& origin, StorageType type) { - LazyInitialize(); - if (db_disabled_) - return; - - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&DeleteOriginInfoOnDBThread, origin, type), - base::Bind(&QuotaManager::DidDatabaseWork, - weak_factory_.GetWeakPtr())); -} - -void QuotaManager::DidOriginDataEvicted(QuotaStatusCode status) { - DCHECK(io_thread_->BelongsToCurrentThread()); - - // We only try evict origins that are not in use, so basically - // deletion attempt for eviction should not fail. Let's record - // the origin if we get error and exclude it from future eviction - // if the error happens consistently (> kThresholdOfErrorsToBeBlacklisted). - if (status != kQuotaStatusOk) - origins_in_error_[eviction_context_.evicted_origin]++; - - eviction_context_.evict_origin_data_callback.Run(status); - eviction_context_.evict_origin_data_callback.Reset(); -} - -void QuotaManager::ReportHistogram() { - GetGlobalUsage(kStorageTypeTemporary, - base::Bind( - &QuotaManager::DidGetTemporaryGlobalUsageForHistogram, - weak_factory_.GetWeakPtr())); - GetGlobalUsage(kStorageTypePersistent, - base::Bind( - &QuotaManager::DidGetPersistentGlobalUsageForHistogram, - weak_factory_.GetWeakPtr())); -} - -void QuotaManager::DidGetTemporaryGlobalUsageForHistogram( - int64 usage, - int64 unlimited_usage) { - UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfTemporaryStorage", usage); - - std::set<GURL> origins; - GetCachedOrigins(kStorageTypeTemporary, &origins); - - size_t num_origins = origins.size(); - size_t protected_origins = 0; - size_t unlimited_origins = 0; - CountOriginType(origins, - special_storage_policy_.get(), - &protected_origins, - &unlimited_origins); - - UMA_HISTOGRAM_COUNTS("Quota.NumberOfTemporaryStorageOrigins", - num_origins); - UMA_HISTOGRAM_COUNTS("Quota.NumberOfProtectedTemporaryStorageOrigins", - protected_origins); - UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedTemporaryStorageOrigins", - unlimited_origins); -} - -void QuotaManager::DidGetPersistentGlobalUsageForHistogram( - int64 usage, - int64 unlimited_usage) { - UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfPersistentStorage", usage); - - std::set<GURL> origins; - GetCachedOrigins(kStorageTypePersistent, &origins); - - size_t num_origins = origins.size(); - size_t protected_origins = 0; - size_t unlimited_origins = 0; - CountOriginType(origins, - special_storage_policy_.get(), - &protected_origins, - &unlimited_origins); - - UMA_HISTOGRAM_COUNTS("Quota.NumberOfPersistentStorageOrigins", - num_origins); - UMA_HISTOGRAM_COUNTS("Quota.NumberOfProtectedPersistentStorageOrigins", - protected_origins); - UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedPersistentStorageOrigins", - unlimited_origins); -} - -void QuotaManager::GetLRUOrigin( - StorageType type, - const GetLRUOriginCallback& callback) { - LazyInitialize(); - // This must not be called while there's an in-flight task. - DCHECK(lru_origin_callback_.is_null()); - lru_origin_callback_ = callback; - if (db_disabled_) { - lru_origin_callback_.Run(GURL()); - lru_origin_callback_.Reset(); - return; - } - - std::set<GURL>* exceptions = new std::set<GURL>; - for (std::map<GURL, int>::const_iterator p = origins_in_use_.begin(); - p != origins_in_use_.end(); - ++p) { - if (p->second > 0) - exceptions->insert(p->first); - } - for (std::map<GURL, int>::const_iterator p = origins_in_error_.begin(); - p != origins_in_error_.end(); - ++p) { - if (p->second > QuotaManager::kThresholdOfErrorsToBeBlacklisted) - exceptions->insert(p->first); - } - - GURL* url = new GURL; - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&GetLRUOriginOnDBThread, - type, - base::Owned(exceptions), - special_storage_policy_, - base::Unretained(url)), - base::Bind(&QuotaManager::DidGetLRUOrigin, - weak_factory_.GetWeakPtr(), - base::Owned(url))); -} - -void QuotaManager::EvictOriginData( - const GURL& origin, - StorageType type, - const EvictOriginDataCallback& callback) { - DCHECK(io_thread_->BelongsToCurrentThread()); - DCHECK_EQ(type, kStorageTypeTemporary); - - eviction_context_.evicted_origin = origin; - eviction_context_.evicted_type = type; - eviction_context_.evict_origin_data_callback = callback; - - DeleteOriginData(origin, type, QuotaClient::kAllClientsMask, - base::Bind(&QuotaManager::DidOriginDataEvicted, - weak_factory_.GetWeakPtr())); -} - -void QuotaManager::GetUsageAndQuotaForEviction( - const UsageAndQuotaCallback& callback) { - DCHECK(io_thread_->BelongsToCurrentThread()); - LazyInitialize(); - - UsageAndQuotaCallbackDispatcher* dispatcher = - new UsageAndQuotaCallbackDispatcher(this); - GetUsageTracker(kStorageTypeTemporary)-> - GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback()); - GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback()); - GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); - dispatcher->WaitForResults(callback); -} - -void QuotaManager::DidSetTemporaryGlobalOverrideQuota( - const QuotaCallback& callback, - const int64* new_quota, - bool success) { - QuotaStatusCode status = kQuotaErrorInvalidAccess; - DidDatabaseWork(success); - if (success) { - temporary_quota_override_ = *new_quota; - status = kQuotaStatusOk; - } - - if (callback.is_null()) - return; - - callback.Run(status, *new_quota); -} - -void QuotaManager::DidGetPersistentHostQuota(const std::string& host, - const int64* quota, - bool success) { - DidDatabaseWork(success); - persistent_host_quota_callbacks_.Run( - host, MakeTuple(kQuotaStatusOk, *quota)); -} - -void QuotaManager::DidSetPersistentHostQuota(const std::string& host, - const QuotaCallback& callback, - const int64* new_quota, - bool success) { - DidDatabaseWork(success); - callback.Run(success ? kQuotaStatusOk : kQuotaErrorInvalidAccess, *new_quota); -} - -void QuotaManager::DidInitialize(int64* temporary_quota_override, - int64* desired_available_space, - bool success) { - temporary_quota_override_ = *temporary_quota_override; - desired_available_space_ = *desired_available_space; - temporary_quota_initialized_ = true; - DidDatabaseWork(success); - - histogram_timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds( - kReportHistogramInterval), - this, &QuotaManager::ReportHistogram); - - db_initialization_callbacks_.Run(MakeTuple()); - GetTemporaryGlobalQuota( - base::Bind(&QuotaManager::DidGetInitialTemporaryGlobalQuota, - weak_factory_.GetWeakPtr())); -} - -void QuotaManager::DidGetLRUOrigin(const GURL* origin, - bool success) { - DidDatabaseWork(success); - // Make sure the returned origin is (still) not in the origin_in_use_ set - // and has not been accessed since we posted the task. - if (origins_in_use_.find(*origin) != origins_in_use_.end() || - access_notified_origins_.find(*origin) != access_notified_origins_.end()) - lru_origin_callback_.Run(GURL()); - else - lru_origin_callback_.Run(*origin); - access_notified_origins_.clear(); - lru_origin_callback_.Reset(); -} - -void QuotaManager::DidGetInitialTemporaryGlobalQuota( - QuotaStatusCode status, int64 quota_unused) { - if (eviction_disabled_) - return; - - std::set<GURL>* origins = new std::set<GURL>; - temporary_usage_tracker_->GetCachedOrigins(origins); - // This will call the StartEviction() when initial origin registration - // is completed. - PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::Bind(&InitializeTemporaryOriginsInfoOnDBThread, - base::Owned(origins)), - base::Bind(&QuotaManager::DidInitializeTemporaryOriginsInfo, - weak_factory_.GetWeakPtr())); -} - -void QuotaManager::DidInitializeTemporaryOriginsInfo(bool success) { - DidDatabaseWork(success); - if (success) - StartEviction(); -} - -void QuotaManager::DidGetAvailableSpace(int64 space) { - available_space_callbacks_.Run(MakeTuple(kQuotaStatusOk, space)); -} - -void QuotaManager::DidDatabaseWork(bool success) { - db_disabled_ = !success; -} - -void QuotaManager::DeleteOnCorrectThread() const { - if (!io_thread_->BelongsToCurrentThread() && - io_thread_->DeleteSoon(FROM_HERE, this)) { - return; - } - delete this; -} - -void QuotaManager::PostTaskAndReplyWithResultForDBThread( - const tracked_objects::Location& from_here, - const base::Callback<bool(QuotaDatabase*)>& task, - const base::Callback<void(bool)>& reply) { - // Deleting manager will post another task to DB thread to delete - // |database_|, therefore we can be sure that database_ is alive when this - // task runs. - base::PostTaskAndReplyWithResult( - db_thread_.get(), - from_here, - base::Bind(task, base::Unretained(database_.get())), - reply); -} - -} // namespace storage diff --git a/webkit/browser/quota/quota_manager.h b/webkit/browser/quota/quota_manager.h index 19c26f2..86c55a8 100644 --- a/webkit/browser/quota/quota_manager.h +++ b/webkit/browser/quota/quota_manager.h @@ -1,460 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_QUOTA_QUOTA_MANAGER_H_ -#define WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_H_ - -#include <deque> -#include <list> -#include <map> -#include <set> -#include <string> -#include <utility> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner_helpers.h" -#include "webkit/browser/quota/quota_callbacks.h" -#include "webkit/browser/quota/quota_client.h" -#include "webkit/browser/quota/quota_database.h" -#include "webkit/browser/quota/quota_task.h" -#include "webkit/browser/quota/special_storage_policy.h" -#include "webkit/browser/quota/storage_observer.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class FilePath; -class SequencedTaskRunner; -class SingleThreadTaskRunner; -} - -namespace quota_internals { -class QuotaInternalsProxy; -} - -namespace content { -class MockQuotaManager; -class MockStorageClient; -class QuotaManagerTest; -class StorageMonitorTest; - -} - -namespace storage { - -class QuotaDatabase; -class QuotaManagerProxy; -class QuotaTemporaryStorageEvictor; -class StorageMonitor; -class UsageTracker; - -struct QuotaManagerDeleter; - -struct STORAGE_EXPORT UsageAndQuota { - int64 usage; - int64 global_limited_usage; - int64 quota; - int64 available_disk_space; - - UsageAndQuota(); - UsageAndQuota(int64 usage, - int64 global_limited_usage, - int64 quota, - int64 available_disk_space); -}; - -// An interface called by QuotaTemporaryStorageEvictor. -class STORAGE_EXPORT QuotaEvictionHandler { - public: - typedef base::Callback<void(const GURL&)> GetLRUOriginCallback; - typedef StatusCallback EvictOriginDataCallback; - typedef base::Callback<void(QuotaStatusCode status, - const UsageAndQuota& usage_and_quota)> - UsageAndQuotaCallback; - - // Returns the least recently used origin. It might return empty - // GURL when there are no evictable origins. - virtual void GetLRUOrigin( - StorageType type, - const GetLRUOriginCallback& callback) = 0; - - virtual void EvictOriginData( - const GURL& origin, - StorageType type, - const EvictOriginDataCallback& callback) = 0; - - virtual void GetUsageAndQuotaForEviction( - const UsageAndQuotaCallback& callback) = 0; - - protected: - virtual ~QuotaEvictionHandler() {} -}; - -struct UsageInfo { - UsageInfo(const std::string& host, StorageType type, int64 usage) - : host(host), - type(type), - usage(usage) {} - std::string host; - StorageType type; - int64 usage; -}; - -// The quota manager class. This class is instantiated per profile and -// held by the profile. With the exception of the constructor and the -// proxy() method, all methods should only be called on the IO thread. -class STORAGE_EXPORT QuotaManager - : public QuotaTaskObserver, - public QuotaEvictionHandler, - public base::RefCountedThreadSafe<QuotaManager, QuotaManagerDeleter> { - public: - typedef base::Callback<void(QuotaStatusCode, - int64 /* usage */, - int64 /* quota */)> - GetUsageAndQuotaCallback; - - static const int64 kIncognitoDefaultQuotaLimit; - static const int64 kNoLimit; - - QuotaManager( - bool is_incognito, - const base::FilePath& profile_path, - const scoped_refptr<base::SingleThreadTaskRunner>& io_thread, - const scoped_refptr<base::SequencedTaskRunner>& db_thread, - const scoped_refptr<SpecialStoragePolicy>& special_storage_policy); - - // Returns a proxy object that can be used on any thread. - QuotaManagerProxy* proxy() { return proxy_.get(); } - - // Called by clients or webapps. Returns usage per host. - void GetUsageInfo(const GetUsageInfoCallback& callback); - - // Called by Web Apps. - // This method is declared as virtual to allow test code to override it. - virtual void GetUsageAndQuotaForWebApps( - const GURL& origin, - StorageType type, - const GetUsageAndQuotaCallback& callback); - - // Called by StorageClients. - // This method is declared as virtual to allow test code to override it. - // - // For UnlimitedStorage origins, this version skips usage and quota handling - // to avoid extra query cost. - // Do not call this method for apps/user-facing code. - virtual void GetUsageAndQuota( - const GURL& origin, - StorageType type, - const GetUsageAndQuotaCallback& callback); - - // Called by clients via proxy. - // Client storage should call this method when storage is accessed. - // Used to maintain LRU ordering. - void NotifyStorageAccessed(QuotaClient::ID client_id, - const GURL& origin, - StorageType type); - - // Called by clients via proxy. - // Client storage must call this method whenever they have made any - // modifications that change the amount of data stored in their storage. - void NotifyStorageModified(QuotaClient::ID client_id, - const GURL& origin, - StorageType type, - int64 delta); - - // Used to avoid evicting origins with open pages. - // A call to NotifyOriginInUse must be balanced by a later call - // to NotifyOriginNoLongerInUse. - void NotifyOriginInUse(const GURL& origin); - void NotifyOriginNoLongerInUse(const GURL& origin); - bool IsOriginInUse(const GURL& origin) const { - return origins_in_use_.find(origin) != origins_in_use_.end(); - } - - void SetUsageCacheEnabled(QuotaClient::ID client_id, - const GURL& origin, - StorageType type, - bool enabled); - - // DeleteOriginData and DeleteHostData (surprisingly enough) delete data of a - // particular StorageType associated with either a specific origin or set of - // origins. Each method additionally requires a |quota_client_mask| which - // specifies the types of QuotaClients to delete from the origin. This is - // specified by the caller as a bitmask built from QuotaClient::IDs. Setting - // the mask to QuotaClient::kAllClientsMask will remove all clients from the - // origin, regardless of type. - virtual void DeleteOriginData(const GURL& origin, - StorageType type, - int quota_client_mask, - const StatusCallback& callback); - void DeleteHostData(const std::string& host, - StorageType type, - int quota_client_mask, - const StatusCallback& callback); - - // Called by UI and internal modules. - void GetAvailableSpace(const AvailableSpaceCallback& callback); - void GetTemporaryGlobalQuota(const QuotaCallback& callback); - - // Ok to call with NULL callback. - void SetTemporaryGlobalOverrideQuota(int64 new_quota, - const QuotaCallback& callback); - - void GetPersistentHostQuota(const std::string& host, - const QuotaCallback& callback); - void SetPersistentHostQuota(const std::string& host, - int64 new_quota, - const QuotaCallback& callback); - void GetGlobalUsage(StorageType type, const GlobalUsageCallback& callback); - void GetHostUsage(const std::string& host, StorageType type, - const UsageCallback& callback); - void GetHostUsage(const std::string& host, StorageType type, - QuotaClient::ID client_id, - const UsageCallback& callback); - - bool IsTrackingHostUsage(StorageType type, QuotaClient::ID client_id) const; - - void GetStatistics(std::map<std::string, std::string>* statistics); - - bool IsStorageUnlimited(const GURL& origin, StorageType type) const; - - bool CanQueryDiskSize(const GURL& origin) const { - return special_storage_policy_.get() && - special_storage_policy_->CanQueryDiskSize(origin); - } - - virtual void GetOriginsModifiedSince(StorageType type, - base::Time modified_since, - const GetOriginsCallback& callback); - - bool ResetUsageTracker(StorageType type); - - // Used to register/deregister observers that wish to monitor storage events. - void AddStorageObserver(StorageObserver* observer, - const StorageObserver::MonitorParams& params); - void RemoveStorageObserver(StorageObserver* observer); - void RemoveStorageObserverForFilter(StorageObserver* observer, - const StorageObserver::Filter& filter); - - // Determines the portion of the temp pool that can be - // utilized by a single host (ie. 5 for 20%). - static const int kPerHostTemporaryPortion; - - static const int64 kPerHostPersistentQuotaLimit; - - static const char kDatabaseName[]; - - static const int kThresholdOfErrorsToBeBlacklisted; - - static const int kEvictionIntervalInMilliSeconds; - - // These are kept non-const so that test code can change the value. - // TODO(kinuko): Make this a real const value and add a proper way to set - // the quota for syncable storage. (http://crbug.com/155488) - static int64 kMinimumPreserveForSystem; - static int64 kSyncableStorageDefaultHostQuota; - - protected: - virtual ~QuotaManager(); - - private: - friend class base::DeleteHelper<QuotaManager>; - friend class base::RefCountedThreadSafe<QuotaManager, QuotaManagerDeleter>; - friend class content::QuotaManagerTest; - friend class content::StorageMonitorTest; - friend class content::MockQuotaManager; - friend class content::MockStorageClient; - friend class quota_internals::QuotaInternalsProxy; - friend class QuotaManagerProxy; - friend class QuotaTemporaryStorageEvictor; - friend struct QuotaManagerDeleter; - - class GetUsageInfoTask; - - class OriginDataDeleter; - class HostDataDeleter; - - class GetModifiedSinceHelper; - class DumpQuotaTableHelper; - class DumpOriginInfoTableHelper; - - typedef QuotaDatabase::QuotaTableEntry QuotaTableEntry; - typedef QuotaDatabase::OriginInfoTableEntry OriginInfoTableEntry; - typedef std::vector<QuotaTableEntry> QuotaTableEntries; - typedef std::vector<OriginInfoTableEntry> OriginInfoTableEntries; - - // Function pointer type used to store the function which returns the - // available disk space for the disk containing the given FilePath. - typedef int64 (*GetAvailableDiskSpaceFn)(const base::FilePath&); - - typedef base::Callback<void(const QuotaTableEntries&)> - DumpQuotaTableCallback; - typedef base::Callback<void(const OriginInfoTableEntries&)> - DumpOriginInfoTableCallback; - - struct EvictionContext { - EvictionContext(); - virtual ~EvictionContext(); - GURL evicted_origin; - StorageType evicted_type; - - EvictOriginDataCallback evict_origin_data_callback; - }; - - typedef QuotaEvictionHandler::UsageAndQuotaCallback - UsageAndQuotaDispatcherCallback; - - // This initialization method is lazily called on the IO thread - // when the first quota manager API is called. - // Initialize must be called after all quota clients are added to the - // manager by RegisterStorage. - void LazyInitialize(); - - // Called by clients via proxy. - // Registers a quota client to the manager. - // The client must remain valid until OnQuotaManagerDestored is called. - void RegisterClient(QuotaClient* client); - - UsageTracker* GetUsageTracker(StorageType type) const; - - // Extract cached origins list from the usage tracker. - // (Might return empty list if no origin is tracked by the tracker.) - void GetCachedOrigins(StorageType type, std::set<GURL>* origins); - - // These internal methods are separately defined mainly for testing. - void NotifyStorageAccessedInternal( - QuotaClient::ID client_id, - const GURL& origin, - StorageType type, - base::Time accessed_time); - void NotifyStorageModifiedInternal( - QuotaClient::ID client_id, - const GURL& origin, - StorageType type, - int64 delta, - base::Time modified_time); - - void DumpQuotaTable(const DumpQuotaTableCallback& callback); - void DumpOriginInfoTable(const DumpOriginInfoTableCallback& callback); - - // Methods for eviction logic. - void StartEviction(); - void DeleteOriginFromDatabase(const GURL& origin, StorageType type); - - void DidOriginDataEvicted(QuotaStatusCode status); - - void ReportHistogram(); - void DidGetTemporaryGlobalUsageForHistogram(int64 usage, - int64 unlimited_usage); - void DidGetPersistentGlobalUsageForHistogram(int64 usage, - int64 unlimited_usage); - - // QuotaEvictionHandler. - virtual void GetLRUOrigin( - StorageType type, - const GetLRUOriginCallback& callback) OVERRIDE; - virtual void EvictOriginData( - const GURL& origin, - StorageType type, - const EvictOriginDataCallback& callback) OVERRIDE; - virtual void GetUsageAndQuotaForEviction( - const UsageAndQuotaCallback& callback) OVERRIDE; - - void DidSetTemporaryGlobalOverrideQuota(const QuotaCallback& callback, - const int64* new_quota, - bool success); - void DidGetPersistentHostQuota(const std::string& host, - const int64* quota, - bool success); - void DidSetPersistentHostQuota(const std::string& host, - const QuotaCallback& callback, - const int64* new_quota, - bool success); - void DidInitialize(int64* temporary_quota_override, - int64* desired_available_space, - bool success); - void DidGetLRUOrigin(const GURL* origin, - bool success); - void DidGetInitialTemporaryGlobalQuota(QuotaStatusCode status, - int64 quota_unused); - void DidInitializeTemporaryOriginsInfo(bool success); - void DidGetAvailableSpace(int64 space); - void DidDatabaseWork(bool success); - - void DeleteOnCorrectThread() const; - - void PostTaskAndReplyWithResultForDBThread( - const tracked_objects::Location& from_here, - const base::Callback<bool(QuotaDatabase*)>& task, - const base::Callback<void(bool)>& reply); - - const bool is_incognito_; - const base::FilePath profile_path_; - - scoped_refptr<QuotaManagerProxy> proxy_; - bool db_disabled_; - bool eviction_disabled_; - scoped_refptr<base::SingleThreadTaskRunner> io_thread_; - scoped_refptr<base::SequencedTaskRunner> db_thread_; - mutable scoped_ptr<QuotaDatabase> database_; - - GetLRUOriginCallback lru_origin_callback_; - std::set<GURL> access_notified_origins_; - - QuotaClientList clients_; - - scoped_ptr<UsageTracker> temporary_usage_tracker_; - scoped_ptr<UsageTracker> persistent_usage_tracker_; - scoped_ptr<UsageTracker> syncable_usage_tracker_; - // TODO(michaeln): Need a way to clear the cache, drop and - // reinstantiate the trackers when they're not handling requests. - - scoped_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_; - EvictionContext eviction_context_; - - ClosureQueue db_initialization_callbacks_; - AvailableSpaceCallbackQueue available_space_callbacks_; - GlobalQuotaCallbackQueue temporary_global_quota_callbacks_; - HostQuotaCallbackMap persistent_host_quota_callbacks_; - - bool temporary_quota_initialized_; - int64 temporary_quota_override_; - - int64 desired_available_space_; - - // Map from origin to count. - std::map<GURL, int> origins_in_use_; - // Map from origin to error count. - std::map<GURL, int> origins_in_error_; - - scoped_refptr<SpecialStoragePolicy> special_storage_policy_; - - base::RepeatingTimer<QuotaManager> histogram_timer_; - - // Pointer to the function used to get the available disk space. This is - // overwritten by QuotaManagerTest in order to attain a deterministic reported - // value. The default value points to base::SysInfo::AmountOfFreeDiskSpace. - GetAvailableDiskSpaceFn get_disk_space_fn_; - - scoped_ptr<StorageMonitor> storage_monitor_; - - base::WeakPtrFactory<QuotaManager> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(QuotaManager); -}; - -struct QuotaManagerDeleter { - static void Destruct(const QuotaManager* manager) { - manager->DeleteOnCorrectThread(); - } -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_H_ +#include "storage/browser/quota/quota_manager.h" diff --git a/webkit/browser/quota/quota_manager_proxy.cc b/webkit/browser/quota/quota_manager_proxy.cc deleted file mode 100644 index 499535e..0000000 --- a/webkit/browser/quota/quota_manager_proxy.cc +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2014 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/browser/quota/quota_manager_proxy.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/sequenced_task_runner.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/task_runner_util.h" - -namespace storage { - -namespace { - -void DidGetUsageAndQuota( - base::SequencedTaskRunner* original_task_runner, - const QuotaManagerProxy::GetUsageAndQuotaCallback& callback, - QuotaStatusCode status, int64 usage, int64 quota) { - if (!original_task_runner->RunsTasksOnCurrentThread()) { - original_task_runner->PostTask( - FROM_HERE, - base::Bind(&DidGetUsageAndQuota, - make_scoped_refptr(original_task_runner), - callback, status, usage, quota)); - return; - } - callback.Run(status, usage, quota); -} - -} // namespace - -void QuotaManagerProxy::RegisterClient(QuotaClient* client) { - if (!io_thread_->BelongsToCurrentThread() && - io_thread_->PostTask( - FROM_HERE, - base::Bind(&QuotaManagerProxy::RegisterClient, this, client))) { - return; - } - - if (manager_) - manager_->RegisterClient(client); - else - client->OnQuotaManagerDestroyed(); -} - -void QuotaManagerProxy::NotifyStorageAccessed( - QuotaClient::ID client_id, - const GURL& origin, - StorageType type) { - if (!io_thread_->BelongsToCurrentThread()) { - io_thread_->PostTask( - FROM_HERE, - base::Bind(&QuotaManagerProxy::NotifyStorageAccessed, this, client_id, - origin, type)); - return; - } - - if (manager_) - manager_->NotifyStorageAccessed(client_id, origin, type); -} - -void QuotaManagerProxy::NotifyStorageModified( - QuotaClient::ID client_id, - const GURL& origin, - StorageType type, - int64 delta) { - if (!io_thread_->BelongsToCurrentThread()) { - io_thread_->PostTask( - FROM_HERE, - base::Bind(&QuotaManagerProxy::NotifyStorageModified, this, client_id, - origin, type, delta)); - return; - } - - if (manager_) - manager_->NotifyStorageModified(client_id, origin, type, delta); -} - -void QuotaManagerProxy::NotifyOriginInUse( - const GURL& origin) { - if (!io_thread_->BelongsToCurrentThread()) { - io_thread_->PostTask( - FROM_HERE, - base::Bind(&QuotaManagerProxy::NotifyOriginInUse, this, origin)); - return; - } - - if (manager_) - manager_->NotifyOriginInUse(origin); -} - -void QuotaManagerProxy::NotifyOriginNoLongerInUse( - const GURL& origin) { - if (!io_thread_->BelongsToCurrentThread()) { - io_thread_->PostTask( - FROM_HERE, - base::Bind(&QuotaManagerProxy::NotifyOriginNoLongerInUse, this, - origin)); - return; - } - if (manager_) - manager_->NotifyOriginNoLongerInUse(origin); -} - -void QuotaManagerProxy::SetUsageCacheEnabled(QuotaClient::ID client_id, - const GURL& origin, - StorageType type, - bool enabled) { - if (!io_thread_->BelongsToCurrentThread()) { - io_thread_->PostTask( - FROM_HERE, - base::Bind(&QuotaManagerProxy::SetUsageCacheEnabled, this, - client_id, origin, type, enabled)); - return; - } - if (manager_) - manager_->SetUsageCacheEnabled(client_id, origin, type, enabled); -} - -void QuotaManagerProxy::GetUsageAndQuota( - base::SequencedTaskRunner* original_task_runner, - const GURL& origin, - StorageType type, - const GetUsageAndQuotaCallback& callback) { - if (!io_thread_->BelongsToCurrentThread()) { - io_thread_->PostTask( - FROM_HERE, - base::Bind(&QuotaManagerProxy::GetUsageAndQuota, this, - make_scoped_refptr(original_task_runner), - origin, type, callback)); - return; - } - if (!manager_) { - DidGetUsageAndQuota(original_task_runner, callback, kQuotaErrorAbort, 0, 0); - return; - } - manager_->GetUsageAndQuota( - origin, type, - base::Bind(&DidGetUsageAndQuota, - make_scoped_refptr(original_task_runner), callback)); -} - -QuotaManager* QuotaManagerProxy::quota_manager() const { - DCHECK(!io_thread_.get() || io_thread_->BelongsToCurrentThread()); - return manager_; -} - -QuotaManagerProxy::QuotaManagerProxy( - QuotaManager* manager, - const scoped_refptr<base::SingleThreadTaskRunner>& io_thread) - : manager_(manager), io_thread_(io_thread) { -} - -QuotaManagerProxy::~QuotaManagerProxy() { -} - -} // namespace storage diff --git a/webkit/browser/quota/quota_manager_proxy.h b/webkit/browser/quota/quota_manager_proxy.h index 447664c..49e7b21 100644 --- a/webkit/browser/quota/quota_manager_proxy.h +++ b/webkit/browser/quota/quota_manager_proxy.h @@ -2,78 +2,4 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_PROXY_H_ -#define WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_PROXY_H_ - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner_helpers.h" -#include "webkit/browser/quota/quota_callbacks.h" -#include "webkit/browser/quota/quota_client.h" -#include "webkit/browser/quota/quota_database.h" -#include "webkit/browser/quota/quota_manager.h" -#include "webkit/browser/quota/quota_task.h" -#include "webkit/browser/quota/special_storage_policy.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class SequencedTaskRunner; -class SingleThreadTaskRunner; -} - -namespace storage { - -// The proxy may be called and finally released on any thread. -class STORAGE_EXPORT QuotaManagerProxy - : public base::RefCountedThreadSafe<QuotaManagerProxy> { - public: - typedef QuotaManager::GetUsageAndQuotaCallback - GetUsageAndQuotaCallback; - - virtual void RegisterClient(QuotaClient* client); - virtual void NotifyStorageAccessed(QuotaClient::ID client_id, - const GURL& origin, - StorageType type); - virtual void NotifyStorageModified(QuotaClient::ID client_id, - const GURL& origin, - StorageType type, - int64 delta); - virtual void NotifyOriginInUse(const GURL& origin); - virtual void NotifyOriginNoLongerInUse(const GURL& origin); - - virtual void SetUsageCacheEnabled(QuotaClient::ID client_id, - const GURL& origin, - StorageType type, - bool enabled); - virtual void GetUsageAndQuota( - base::SequencedTaskRunner* original_task_runner, - const GURL& origin, - StorageType type, - const GetUsageAndQuotaCallback& callback); - - // This method may only be called on the IO thread. - // It may return NULL if the manager has already been deleted. - QuotaManager* quota_manager() const; - - protected: - friend class QuotaManager; - friend class base::RefCountedThreadSafe<QuotaManagerProxy>; - - QuotaManagerProxy( - QuotaManager* manager, - const scoped_refptr<base::SingleThreadTaskRunner>& io_thread); - virtual ~QuotaManagerProxy(); - - QuotaManager* manager_; // only accessed on the io thread - scoped_refptr<base::SingleThreadTaskRunner> io_thread_; - - DISALLOW_COPY_AND_ASSIGN(QuotaManagerProxy); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_PROXY_H_ +#include "storage/browser/quota/quota_manager_proxy.h" diff --git a/webkit/browser/quota/quota_task.cc b/webkit/browser/quota/quota_task.cc deleted file mode 100644 index 98594a9..0000000 --- a/webkit/browser/quota/quota_task.cc +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2013 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/browser/quota/quota_task.h" - -#include <algorithm> -#include <functional> - -#include "base/bind.h" -#include "base/location.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/single_thread_task_runner.h" - -using base::TaskRunner; - -namespace storage { - -// QuotaTask --------------------------------------------------------------- - -QuotaTask::~QuotaTask() { -} - -void QuotaTask::Start() { - DCHECK(observer_); - observer()->RegisterTask(this); - Run(); -} - -QuotaTask::QuotaTask(QuotaTaskObserver* observer) - : observer_(observer), - original_task_runner_(base::MessageLoopProxy::current()), - delete_scheduled_(false) { -} - -void QuotaTask::CallCompleted() { - DCHECK(original_task_runner_->BelongsToCurrentThread()); - if (observer_) { - observer_->UnregisterTask(this); - Completed(); - } -} - -void QuotaTask::Abort() { - DCHECK(original_task_runner_->BelongsToCurrentThread()); - observer_ = NULL; - Aborted(); -} - -void QuotaTask::DeleteSoon() { - DCHECK(original_task_runner_->BelongsToCurrentThread()); - if (delete_scheduled_) - return; - delete_scheduled_ = true; - base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); -} - -// QuotaTaskObserver ------------------------------------------------------- - -QuotaTaskObserver::~QuotaTaskObserver() { - std::for_each(running_quota_tasks_.begin(), - running_quota_tasks_.end(), - std::mem_fun(&QuotaTask::Abort)); -} - -QuotaTaskObserver::QuotaTaskObserver() { -} - -void QuotaTaskObserver::RegisterTask(QuotaTask* task) { - running_quota_tasks_.insert(task); -} - -void QuotaTaskObserver::UnregisterTask(QuotaTask* task) { - DCHECK(running_quota_tasks_.find(task) != running_quota_tasks_.end()); - running_quota_tasks_.erase(task); -} - -} // namespace storage diff --git a/webkit/browser/quota/quota_task.h b/webkit/browser/quota/quota_task.h index 5201a61..66f2256 100644 --- a/webkit/browser/quota/quota_task.h +++ b/webkit/browser/quota/quota_task.h @@ -1,79 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_QUOTA_QUOTA_TASK_H_ -#define WEBKIT_BROWSER_QUOTA_QUOTA_TASK_H_ - -#include <set> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner_helpers.h" -#include "webkit/browser/storage_browser_export.h" - -namespace base { -class SingleThreadTaskRunner; -class TaskRunner; -} - -namespace storage { - -class QuotaTaskObserver; - -// A base class for quota tasks. -// TODO(kinuko): Revise this using base::Callback. -class QuotaTask { - public: - void Start(); - - protected: - explicit QuotaTask(QuotaTaskObserver* observer); - virtual ~QuotaTask(); - - // The task body. - virtual void Run() = 0; - - // Called upon completion, on the original message loop. - virtual void Completed() = 0; - - // Called when the task is aborted. - virtual void Aborted() {} - - void CallCompleted(); - - // Call this to delete itself. - void DeleteSoon(); - - QuotaTaskObserver* observer() const { return observer_; } - base::SingleThreadTaskRunner* original_task_runner() const { - return original_task_runner_.get(); - } - - private: - friend class base::DeleteHelper<QuotaTask>; - friend class QuotaTaskObserver; - - void Abort(); - QuotaTaskObserver* observer_; - scoped_refptr<base::SingleThreadTaskRunner> original_task_runner_; - bool delete_scheduled_; -}; - -class STORAGE_EXPORT QuotaTaskObserver { - protected: - friend class QuotaTask; - - QuotaTaskObserver(); - virtual ~QuotaTaskObserver(); - - void RegisterTask(QuotaTask* task); - void UnregisterTask(QuotaTask* task); - - typedef std::set<QuotaTask*> TaskSet; - TaskSet running_quota_tasks_; -}; -} - -#endif // WEBKIT_BROWSER_QUOTA_QUOTA_TASK_H_ +#include "storage/browser/quota/quota_task.h" diff --git a/webkit/browser/quota/quota_temporary_storage_evictor.cc b/webkit/browser/quota/quota_temporary_storage_evictor.cc deleted file mode 100644 index 3eaad3f..0000000 --- a/webkit/browser/quota/quota_temporary_storage_evictor.cc +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2013 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/browser/quota/quota_temporary_storage_evictor.h" - -#include <algorithm> - -#include "base/bind.h" -#include "base/metrics/histogram.h" -#include "url/gurl.h" -#include "webkit/browser/quota/quota_manager.h" - -#define UMA_HISTOGRAM_MBYTES(name, sample) \ - UMA_HISTOGRAM_CUSTOM_COUNTS( \ - (name), static_cast<int>((sample) / kMBytes), \ - 1, 10 * 1024 * 1024 /* 10TB */, 100) - -#define UMA_HISTOGRAM_MINUTES(name, sample) \ - UMA_HISTOGRAM_CUSTOM_TIMES( \ - (name), (sample), \ - base::TimeDelta::FromMinutes(1), \ - base::TimeDelta::FromDays(1), 50) - -namespace { -const int64 kMBytes = 1024 * 1024; -const double kUsageRatioToStartEviction = 0.7; -const int kThresholdOfErrorsToStopEviction = 5; -const int kHistogramReportIntervalMinutes = 60; -} - -namespace storage { - -const int QuotaTemporaryStorageEvictor:: - kMinAvailableDiskSpaceToStartEvictionNotSpecified = -1; - -QuotaTemporaryStorageEvictor::EvictionRoundStatistics::EvictionRoundStatistics() - : in_round(false), - is_initialized(false), - usage_overage_at_round(-1), - diskspace_shortage_at_round(-1), - usage_on_beginning_of_round(-1), - usage_on_end_of_round(-1), - num_evicted_origins_in_round(0) { -} - -QuotaTemporaryStorageEvictor::QuotaTemporaryStorageEvictor( - QuotaEvictionHandler* quota_eviction_handler, - int64 interval_ms) - : min_available_disk_space_to_start_eviction_( - kMinAvailableDiskSpaceToStartEvictionNotSpecified), - quota_eviction_handler_(quota_eviction_handler), - interval_ms_(interval_ms), - repeated_eviction_(true), - weak_factory_(this) { - DCHECK(quota_eviction_handler); -} - -QuotaTemporaryStorageEvictor::~QuotaTemporaryStorageEvictor() { -} - -void QuotaTemporaryStorageEvictor::GetStatistics( - std::map<std::string, int64>* statistics) { - DCHECK(statistics); - - (*statistics)["errors-on-evicting-origin"] = - statistics_.num_errors_on_evicting_origin; - (*statistics)["errors-on-getting-usage-and-quota"] = - statistics_.num_errors_on_getting_usage_and_quota; - (*statistics)["evicted-origins"] = - statistics_.num_evicted_origins; - (*statistics)["eviction-rounds"] = - statistics_.num_eviction_rounds; - (*statistics)["skipped-eviction-rounds"] = - statistics_.num_skipped_eviction_rounds; -} - -void QuotaTemporaryStorageEvictor::ReportPerRoundHistogram() { - DCHECK(round_statistics_.in_round); - DCHECK(round_statistics_.is_initialized); - - base::Time now = base::Time::Now(); - UMA_HISTOGRAM_TIMES("Quota.TimeSpentToAEvictionRound", - now - round_statistics_.start_time); - if (!time_of_end_of_last_round_.is_null()) - UMA_HISTOGRAM_MINUTES("Quota.TimeDeltaOfEvictionRounds", - now - time_of_end_of_last_round_); - UMA_HISTOGRAM_MBYTES("Quota.UsageOverageOfTemporaryGlobalStorage", - round_statistics_.usage_overage_at_round); - UMA_HISTOGRAM_MBYTES("Quota.DiskspaceShortage", - round_statistics_.diskspace_shortage_at_round); - UMA_HISTOGRAM_MBYTES("Quota.EvictedBytesPerRound", - round_statistics_.usage_on_beginning_of_round - - round_statistics_.usage_on_end_of_round); - UMA_HISTOGRAM_COUNTS("Quota.NumberOfEvictedOriginsPerRound", - round_statistics_.num_evicted_origins_in_round); -} - -void QuotaTemporaryStorageEvictor::ReportPerHourHistogram() { - Statistics stats_in_hour(statistics_); - stats_in_hour.subtract_assign(previous_statistics_); - previous_statistics_ = statistics_; - - UMA_HISTOGRAM_COUNTS("Quota.ErrorsOnEvictingOriginPerHour", - stats_in_hour.num_errors_on_evicting_origin); - UMA_HISTOGRAM_COUNTS("Quota.ErrorsOnGettingUsageAndQuotaPerHour", - stats_in_hour.num_errors_on_getting_usage_and_quota); - UMA_HISTOGRAM_COUNTS("Quota.EvictedOriginsPerHour", - stats_in_hour.num_evicted_origins); - UMA_HISTOGRAM_COUNTS("Quota.EvictionRoundsPerHour", - stats_in_hour.num_eviction_rounds); - UMA_HISTOGRAM_COUNTS("Quota.SkippedEvictionRoundsPerHour", - stats_in_hour.num_skipped_eviction_rounds); -} - -void QuotaTemporaryStorageEvictor::OnEvictionRoundStarted() { - if (round_statistics_.in_round) - return; - round_statistics_.in_round = true; - round_statistics_.start_time = base::Time::Now(); - ++statistics_.num_eviction_rounds; -} - -void QuotaTemporaryStorageEvictor::OnEvictionRoundFinished() { - // Check if skipped round - if (round_statistics_.num_evicted_origins_in_round) { - ReportPerRoundHistogram(); - time_of_end_of_last_nonskipped_round_ = base::Time::Now(); - } else { - ++statistics_.num_skipped_eviction_rounds; - } - // Reset stats for next round. - round_statistics_ = EvictionRoundStatistics(); -} - -void QuotaTemporaryStorageEvictor::Start() { - DCHECK(CalledOnValidThread()); - StartEvictionTimerWithDelay(0); - - if (histogram_timer_.IsRunning()) - return; - - histogram_timer_.Start( - FROM_HERE, base::TimeDelta::FromMinutes(kHistogramReportIntervalMinutes), - this, &QuotaTemporaryStorageEvictor::ReportPerHourHistogram); -} - -void QuotaTemporaryStorageEvictor::StartEvictionTimerWithDelay(int delay_ms) { - if (eviction_timer_.IsRunning()) - return; - eviction_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms), - this, &QuotaTemporaryStorageEvictor::ConsiderEviction); -} - -void QuotaTemporaryStorageEvictor::ConsiderEviction() { - OnEvictionRoundStarted(); - - // Get usage and disk space, then continue. - quota_eviction_handler_->GetUsageAndQuotaForEviction( - base::Bind(&QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction, - weak_factory_.GetWeakPtr())); -} - -void QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction( - QuotaStatusCode status, - const UsageAndQuota& qau) { - DCHECK(CalledOnValidThread()); - - int64 usage = qau.global_limited_usage; - DCHECK_GE(usage, 0); - - if (status != kQuotaStatusOk) - ++statistics_.num_errors_on_getting_usage_and_quota; - - int64 usage_overage = std::max( - static_cast<int64>(0), - usage - static_cast<int64>(qau.quota * kUsageRatioToStartEviction)); - - // min_available_disk_space_to_start_eviction_ might be < 0 if no value - // is explicitly configured yet. - int64 diskspace_shortage = std::max( - static_cast<int64>(0), - min_available_disk_space_to_start_eviction_ - qau.available_disk_space); - - if (!round_statistics_.is_initialized) { - round_statistics_.usage_overage_at_round = usage_overage; - round_statistics_.diskspace_shortage_at_round = diskspace_shortage; - round_statistics_.usage_on_beginning_of_round = usage; - round_statistics_.is_initialized = true; - } - round_statistics_.usage_on_end_of_round = usage; - - int64 amount_to_evict = std::max(usage_overage, diskspace_shortage); - if (status == kQuotaStatusOk && amount_to_evict > 0) { - // Space is getting tight. Get the least recently used origin and continue. - // TODO(michaeln): if the reason for eviction is low physical disk space, - // make 'unlimited' origins subject to eviction too. - quota_eviction_handler_->GetLRUOrigin( - kStorageTypeTemporary, - base::Bind(&QuotaTemporaryStorageEvictor::OnGotLRUOrigin, - weak_factory_.GetWeakPtr())); - } else { - if (repeated_eviction_) { - // No action required, sleep for a while and check again later. - if (statistics_.num_errors_on_getting_usage_and_quota < - kThresholdOfErrorsToStopEviction) { - StartEvictionTimerWithDelay(interval_ms_); - } else { - // TODO(dmikurube): Try restarting eviction after a while. - LOG(WARNING) << "Stopped eviction of temporary storage due to errors " - "in GetUsageAndQuotaForEviction."; - } - } - OnEvictionRoundFinished(); - } - - // TODO(dmikurube): Add error handling for the case status != kQuotaStatusOk. -} - -void QuotaTemporaryStorageEvictor::OnGotLRUOrigin(const GURL& origin) { - DCHECK(CalledOnValidThread()); - - if (origin.is_empty()) { - if (repeated_eviction_) - StartEvictionTimerWithDelay(interval_ms_); - OnEvictionRoundFinished(); - return; - } - - quota_eviction_handler_->EvictOriginData(origin, kStorageTypeTemporary, - base::Bind( - &QuotaTemporaryStorageEvictor::OnEvictionComplete, - weak_factory_.GetWeakPtr())); -} - -void QuotaTemporaryStorageEvictor::OnEvictionComplete( - QuotaStatusCode status) { - DCHECK(CalledOnValidThread()); - - // Just calling ConsiderEviction() or StartEvictionTimerWithDelay() here is - // ok. No need to deal with the case that all of the Delete operations fail - // for a certain origin. It doesn't result in trying to evict the same - // origin permanently. The evictor skips origins which had deletion errors - // a few times. - - if (status == kQuotaStatusOk) { - ++statistics_.num_evicted_origins; - ++round_statistics_.num_evicted_origins_in_round; - // We many need to get rid of more space so reconsider immediately. - ConsiderEviction(); - } else { - ++statistics_.num_errors_on_evicting_origin; - if (repeated_eviction_) { - // Sleep for a while and retry again until we see too many errors. - StartEvictionTimerWithDelay(interval_ms_); - } - OnEvictionRoundFinished(); - } -} - -} // namespace storage diff --git a/webkit/browser/quota/quota_temporary_storage_evictor.h b/webkit/browser/quota/quota_temporary_storage_evictor.h index 6a4fbd7..e7b63c7 100644 --- a/webkit/browser/quota/quota_temporary_storage_evictor.h +++ b/webkit/browser/quota/quota_temporary_storage_evictor.h @@ -1,134 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_QUOTA_QUOTA_TEMPORARY_STORAGE_EVICTOR_H_ -#define WEBKIT_BROWSER_QUOTA_QUOTA_TEMPORARY_STORAGE_EVICTOR_H_ - -#include <map> -#include <string> - -#include "base/memory/weak_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "base/timer/timer.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/quota/quota_types.h" - -class GURL; - -namespace content { -class QuotaTemporaryStorageEvictorTest; -} - -namespace storage { - -class QuotaEvictionHandler; -struct UsageAndQuota; - -class STORAGE_EXPORT_PRIVATE QuotaTemporaryStorageEvictor - : public base::NonThreadSafe { - public: - struct Statistics { - Statistics() - : num_errors_on_evicting_origin(0), - num_errors_on_getting_usage_and_quota(0), - num_evicted_origins(0), - num_eviction_rounds(0), - num_skipped_eviction_rounds(0) {} - int64 num_errors_on_evicting_origin; - int64 num_errors_on_getting_usage_and_quota; - int64 num_evicted_origins; - int64 num_eviction_rounds; - int64 num_skipped_eviction_rounds; - - void subtract_assign(const Statistics& rhs) { - num_errors_on_evicting_origin -= rhs.num_errors_on_evicting_origin; - num_errors_on_getting_usage_and_quota -= - rhs.num_errors_on_getting_usage_and_quota; - num_evicted_origins -= rhs.num_evicted_origins; - num_eviction_rounds -= rhs.num_eviction_rounds; - num_skipped_eviction_rounds -= rhs.num_skipped_eviction_rounds; - } - }; - - struct EvictionRoundStatistics { - EvictionRoundStatistics(); - - bool in_round; - bool is_initialized; - - base::Time start_time; - int64 usage_overage_at_round; - int64 diskspace_shortage_at_round; - - int64 usage_on_beginning_of_round; - int64 usage_on_end_of_round; - int64 num_evicted_origins_in_round; - }; - - QuotaTemporaryStorageEvictor( - QuotaEvictionHandler* quota_eviction_handler, - int64 interval_ms); - virtual ~QuotaTemporaryStorageEvictor(); - - void GetStatistics(std::map<std::string, int64>* statistics); - void ReportPerRoundHistogram(); - void ReportPerHourHistogram(); - void Start(); - - int64 min_available_disk_space_to_start_eviction() { - return min_available_disk_space_to_start_eviction_; - } - void reset_min_available_disk_space_to_start_eviction() { - min_available_disk_space_to_start_eviction_ = - kMinAvailableDiskSpaceToStartEvictionNotSpecified; - } - void set_min_available_disk_space_to_start_eviction(int64 value) { - min_available_disk_space_to_start_eviction_ = value; - } - - private: - friend class content::QuotaTemporaryStorageEvictorTest; - - void StartEvictionTimerWithDelay(int delay_ms); - void ConsiderEviction(); - void OnGotUsageAndQuotaForEviction( - QuotaStatusCode status, - const UsageAndQuota& quota_and_usage); - void OnGotLRUOrigin(const GURL& origin); - void OnEvictionComplete(QuotaStatusCode status); - - void OnEvictionRoundStarted(); - void OnEvictionRoundFinished(); - - // This is only used for tests. - void set_repeated_eviction(bool repeated_eviction) { - repeated_eviction_ = repeated_eviction; - } - - static const int kMinAvailableDiskSpaceToStartEvictionNotSpecified; - - int64 min_available_disk_space_to_start_eviction_; - - // Not owned; quota_eviction_handler owns us. - QuotaEvictionHandler* quota_eviction_handler_; - - Statistics statistics_; - Statistics previous_statistics_; - EvictionRoundStatistics round_statistics_; - base::Time time_of_end_of_last_nonskipped_round_; - base::Time time_of_end_of_last_round_; - - int64 interval_ms_; - bool repeated_eviction_; - - base::OneShotTimer<QuotaTemporaryStorageEvictor> eviction_timer_; - base::RepeatingTimer<QuotaTemporaryStorageEvictor> histogram_timer_; - base::WeakPtrFactory<QuotaTemporaryStorageEvictor> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(QuotaTemporaryStorageEvictor); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_QUOTA_QUOTA_TEMPORARY_STORAGE_EVICTOR_H_ +#include "storage/browser/quota/quota_temporary_storage_evictor.h" diff --git a/webkit/browser/quota/special_storage_policy.cc b/webkit/browser/quota/special_storage_policy.cc deleted file mode 100644 index eac7ba0..0000000 --- a/webkit/browser/quota/special_storage_policy.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2013 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/browser/quota/special_storage_policy.h" - -namespace storage { - -SpecialStoragePolicy::Observer::~Observer() {} - -SpecialStoragePolicy::SpecialStoragePolicy() {} - -SpecialStoragePolicy::~SpecialStoragePolicy() {} - -void SpecialStoragePolicy::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void SpecialStoragePolicy::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -void SpecialStoragePolicy::NotifyGranted(const GURL& origin, int change_flags) { - scoped_refptr<SpecialStoragePolicy> protect(this); - FOR_EACH_OBSERVER(Observer, observers_, OnGranted(origin, change_flags)); -} - -void SpecialStoragePolicy::NotifyRevoked(const GURL& origin, int change_flags) { - scoped_refptr<SpecialStoragePolicy> protect(this); - FOR_EACH_OBSERVER(Observer, observers_, OnRevoked(origin, change_flags)); -} - -void SpecialStoragePolicy::NotifyCleared() { - scoped_refptr<SpecialStoragePolicy> protect(this); - FOR_EACH_OBSERVER(Observer, observers_, OnCleared()); -} - -} // namespace storage diff --git a/webkit/browser/quota/special_storage_policy.h b/webkit/browser/quota/special_storage_policy.h index 5ddc821..b0430fd 100644 --- a/webkit/browser/quota/special_storage_policy.h +++ b/webkit/browser/quota/special_storage_policy.h @@ -1,86 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_QUOTA_SPECIAL_STORAGE_POLICY_H_ -#define WEBKIT_BROWSER_QUOTA_SPECIAL_STORAGE_POLICY_H_ - -#include <string> - -#include "base/memory/ref_counted.h" -#include "base/observer_list.h" -#include "webkit/browser/storage_browser_export.h" - -class GURL; - -namespace storage { - -// Special rights are granted to 'extensions' and 'applications'. The -// storage subsystems query this interface to determine which origins -// have these rights. Chrome provides an impl that is cognizant of what -// is currently installed in the extensions system. -// The IsSomething() methods must be thread-safe, however Observers should -// only be notified, added, and removed on the IO thead. -class STORAGE_EXPORT SpecialStoragePolicy - : public base::RefCountedThreadSafe<SpecialStoragePolicy> { - public: - typedef int StoragePolicy; - enum ChangeFlags { - STORAGE_PROTECTED = 1 << 0, - STORAGE_UNLIMITED = 1 << 1, - }; - - class STORAGE_EXPORT Observer { - public: - virtual void OnGranted(const GURL& origin, int change_flags) = 0; - virtual void OnRevoked(const GURL& origin, int change_flags) = 0; - virtual void OnCleared() = 0; - - protected: - virtual ~Observer(); - }; - - SpecialStoragePolicy(); - - // Protected storage is not subject to removal by the browsing data remover. - virtual bool IsStorageProtected(const GURL& origin) = 0; - - // Unlimited storage is not subject to 'quotas'. - virtual bool IsStorageUnlimited(const GURL& origin) = 0; - - // Some origins (e.g. installed apps) have access to the size of the remaining - // disk capacity. - virtual bool CanQueryDiskSize(const GURL& origin) = 0; - - // Checks if extension identified with |extension_id| is registered as - // file handler. - virtual bool IsFileHandler(const std::string& extension_id) = 0; - - // Checks if the origin contains per-site isolated storage. - virtual bool HasIsolatedStorage(const GURL& origin) = 0; - - // Some origins are only allowed to store session-only data which is deleted - // when the session ends. - virtual bool IsStorageSessionOnly(const GURL& origin) = 0; - - // Returns true if some origins are only allowed session-only storage. - virtual bool HasSessionOnlyOrigins() = 0; - - // Adds/removes an observer, the policy does not take - // ownership of the observer. Should only be called on the IO thread. - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - - protected: - friend class base::RefCountedThreadSafe<SpecialStoragePolicy>; - virtual ~SpecialStoragePolicy(); - void NotifyGranted(const GURL& origin, int change_flags); - void NotifyRevoked(const GURL& origin, int change_flags); - void NotifyCleared(); - - ObserverList<Observer> observers_; -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_QUOTA_SPECIAL_STORAGE_POLICY_H_ +#include "storage/browser/quota/special_storage_policy.h" diff --git a/webkit/browser/quota/storage_monitor.cc b/webkit/browser/quota/storage_monitor.cc deleted file mode 100644 index 366d4d7..0000000 --- a/webkit/browser/quota/storage_monitor.cc +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright 2014 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/browser/quota/storage_monitor.h" - -#include <algorithm> - -#include "base/stl_util.h" -#include "net/base/net_util.h" -#include "webkit/browser/quota/quota_manager.h" -#include "webkit/common/quota/quota_status_code.h" - -namespace storage { - -// StorageObserverList: - -StorageObserverList::ObserverState::ObserverState() - : requires_update(false) { -} - -StorageObserverList::StorageObserverList() {} - -StorageObserverList::~StorageObserverList() {} - -void StorageObserverList::AddObserver( - StorageObserver* observer, const StorageObserver::MonitorParams& params) { - ObserverState& observer_state = observers_[observer]; - observer_state.origin = params.filter.origin; - observer_state.rate = params.rate; -} - -void StorageObserverList::RemoveObserver(StorageObserver* observer) { - observers_.erase(observer); -} - -int StorageObserverList::ObserverCount() const { - return observers_.size(); -} - -void StorageObserverList::OnStorageChange(const StorageObserver::Event& event) { - for (StorageObserverStateMap::iterator it = observers_.begin(); - it != observers_.end(); ++it) { - it->second.requires_update = true; - } - - MaybeDispatchEvent(event); -} - -void StorageObserverList::MaybeDispatchEvent( - const StorageObserver::Event& event) { - notification_timer_.Stop(); - base::TimeDelta min_delay = base::TimeDelta::Max(); - bool all_observers_notified = true; - - for (StorageObserverStateMap::iterator it = observers_.begin(); - it != observers_.end(); ++it) { - if (!it->second.requires_update) - continue; - - base::TimeTicks current_time = base::TimeTicks::Now(); - base::TimeDelta delta = current_time - it->second.last_notification_time; - if (it->second.last_notification_time.is_null() || - delta >= it->second.rate) { - it->second.requires_update = false; - it->second.last_notification_time = current_time; - - if (it->second.origin == event.filter.origin) { - it->first->OnStorageEvent(event); - } else { - // When the quota and usage of an origin is requested, QuotaManager - // returns the quota and usage of the host. Multiple origins can map to - // to the same host, so ensure the |origin| field in the dispatched - // event matches the |origin| specified by the observer when it was - // registered. - StorageObserver::Event dispatch_event(event); - dispatch_event.filter.origin = it->second.origin; - it->first->OnStorageEvent(dispatch_event); - } - } else { - all_observers_notified = false; - base::TimeDelta delay = it->second.rate - delta; - if (delay < min_delay) - min_delay = delay; - } - } - - // We need to respect the notification rate specified by observers. So if it - // is too soon to dispatch an event to an observer, save the event and - // dispatch it after a delay. If we simply drop the event, another one may - // not arrive anytime soon and the observer will miss the most recent event. - if (!all_observers_notified) { - pending_event_ = event; - notification_timer_.Start( - FROM_HERE, - min_delay, - this, - &StorageObserverList::DispatchPendingEvent); - } -} - -void StorageObserverList::ScheduleUpdateForObserver(StorageObserver* observer) { - DCHECK(ContainsKey(observers_, observer)); - observers_[observer].requires_update = true; -} - -void StorageObserverList::DispatchPendingEvent() { - MaybeDispatchEvent(pending_event_); -} - - -// HostStorageObservers: - -HostStorageObservers::HostStorageObservers(QuotaManager* quota_manager) - : quota_manager_(quota_manager), - initialized_(false), - initializing_(false), - event_occurred_before_init_(false), - usage_deltas_during_init_(0), - cached_usage_(0), - cached_quota_(0), - weak_factory_(this) { -} - -HostStorageObservers::~HostStorageObservers() {} - -void HostStorageObservers::AddObserver( - StorageObserver* observer, - const StorageObserver::MonitorParams& params) { - observers_.AddObserver(observer, params); - - if (!params.dispatch_initial_state) - return; - - if (initialized_) { - StorageObserver::Event event(params.filter, - std::max<int64>(cached_usage_, 0), - std::max<int64>(cached_quota_, 0)); - observer->OnStorageEvent(event); - return; - } - - // Ensure the observer receives the initial storage state once initialization - // is complete. - observers_.ScheduleUpdateForObserver(observer); - StartInitialization(params.filter); -} - -void HostStorageObservers::RemoveObserver(StorageObserver* observer) { - observers_.RemoveObserver(observer); -} - -bool HostStorageObservers::ContainsObservers() const { - return observers_.ObserverCount() > 0; -} - -void HostStorageObservers::NotifyUsageChange( - const StorageObserver::Filter& filter, int64 delta) { - if (initialized_) { - cached_usage_ += delta; - DispatchEvent(filter, true); - return; - } - - // If a storage change occurs before initialization, ensure all observers will - // receive an event once initialization is complete. - event_occurred_before_init_ = true; - - // During QuotaManager::GetUsageAndQuotaForWebApps(), cached data is read - // synchronously, but other data may be retrieved asynchronously. A usage - // change may occur between the function call and callback. These deltas need - // to be added to the usage received by GotHostUsageAndQuota() to ensure - // |cached_usage_| is correctly initialized. - if (initializing_) { - usage_deltas_during_init_ += delta; - return; - } - - StartInitialization(filter); -} - -void HostStorageObservers::StartInitialization( - const StorageObserver::Filter& filter) { - if (initialized_ || initializing_) - return; - - initializing_ = true; - quota_manager_->GetUsageAndQuotaForWebApps( - filter.origin, - filter.storage_type, - base::Bind(&HostStorageObservers::GotHostUsageAndQuota, - weak_factory_.GetWeakPtr(), - filter)); -} - -void HostStorageObservers::GotHostUsageAndQuota( - const StorageObserver::Filter& filter, - QuotaStatusCode status, - int64 usage, - int64 quota) { - initializing_ = false; - if (status != kQuotaStatusOk) - return; - - initialized_ = true; - cached_quota_ = quota; - cached_usage_ = usage + usage_deltas_during_init_; - DispatchEvent(filter, event_occurred_before_init_); -} - -void HostStorageObservers::DispatchEvent( - const StorageObserver::Filter& filter, bool is_update) { - StorageObserver::Event event(filter, - std::max<int64>(cached_usage_, 0), - std::max<int64>(cached_quota_, 0)); - if (is_update) - observers_.OnStorageChange(event); - else - observers_.MaybeDispatchEvent(event); -} - - -// StorageTypeObservers: - -StorageTypeObservers::StorageTypeObservers(QuotaManager* quota_manager) - : quota_manager_(quota_manager) { -} - -StorageTypeObservers::~StorageTypeObservers() { - STLDeleteValues(&host_observers_map_); -} - -void StorageTypeObservers::AddObserver( - StorageObserver* observer, const StorageObserver::MonitorParams& params) { - std::string host = net::GetHostOrSpecFromURL(params.filter.origin); - if (host.empty()) - return; - - HostStorageObservers* host_observers = NULL; - HostObserversMap::iterator it = host_observers_map_.find(host); - if (it == host_observers_map_.end()) { - host_observers = new HostStorageObservers(quota_manager_); - host_observers_map_[host] = host_observers; - } else { - host_observers = it->second; - } - - host_observers->AddObserver(observer, params); -} - -void StorageTypeObservers::RemoveObserver(StorageObserver* observer) { - for (HostObserversMap::iterator it = host_observers_map_.begin(); - it != host_observers_map_.end(); ) { - it->second->RemoveObserver(observer); - if (!it->second->ContainsObservers()) { - delete it->second; - host_observers_map_.erase(it++); - } else { - ++it; - } - } -} - -void StorageTypeObservers::RemoveObserverForFilter( - StorageObserver* observer, const StorageObserver::Filter& filter) { - std::string host = net::GetHostOrSpecFromURL(filter.origin); - HostObserversMap::iterator it = host_observers_map_.find(host); - if (it == host_observers_map_.end()) - return; - - it->second->RemoveObserver(observer); - if (!it->second->ContainsObservers()) { - delete it->second; - host_observers_map_.erase(it); - } -} - -const HostStorageObservers* StorageTypeObservers::GetHostObservers( - const std::string& host) const { - HostObserversMap::const_iterator it = host_observers_map_.find(host); - if (it != host_observers_map_.end()) - return it->second; - - return NULL; -} - -void StorageTypeObservers::NotifyUsageChange( - const StorageObserver::Filter& filter, int64 delta) { - std::string host = net::GetHostOrSpecFromURL(filter.origin); - HostObserversMap::iterator it = host_observers_map_.find(host); - if (it == host_observers_map_.end()) - return; - - it->second->NotifyUsageChange(filter, delta); -} - - -// StorageMonitor: - -StorageMonitor::StorageMonitor(QuotaManager* quota_manager) - : quota_manager_(quota_manager) { -} - -StorageMonitor::~StorageMonitor() { - STLDeleteValues(&storage_type_observers_map_); -} - -void StorageMonitor::AddObserver( - StorageObserver* observer, const StorageObserver::MonitorParams& params) { - DCHECK(observer); - - // Check preconditions. - if (params.filter.storage_type == kStorageTypeUnknown || - params.filter.storage_type == kStorageTypeQuotaNotManaged || - params.filter.origin.is_empty()) { - NOTREACHED(); - return; - } - - StorageTypeObservers* type_observers = NULL; - StorageTypeObserversMap::iterator it = - storage_type_observers_map_.find(params.filter.storage_type); - if (it == storage_type_observers_map_.end()) { - type_observers = new StorageTypeObservers(quota_manager_); - storage_type_observers_map_[params.filter.storage_type] = type_observers; - } else { - type_observers = it->second; - } - - type_observers->AddObserver(observer, params); -} - -void StorageMonitor::RemoveObserver(StorageObserver* observer) { - for (StorageTypeObserversMap::iterator it = - storage_type_observers_map_.begin(); - it != storage_type_observers_map_.end(); ++it) { - it->second->RemoveObserver(observer); - } -} - -void StorageMonitor::RemoveObserverForFilter( - StorageObserver* observer, const StorageObserver::Filter& filter) { - StorageTypeObserversMap::iterator it = - storage_type_observers_map_.find(filter.storage_type); - if (it == storage_type_observers_map_.end()) - return; - - it->second->RemoveObserverForFilter(observer, filter); -} - -const StorageTypeObservers* StorageMonitor::GetStorageTypeObservers( - StorageType storage_type) const { - StorageTypeObserversMap::const_iterator it = - storage_type_observers_map_.find(storage_type); - if (it != storage_type_observers_map_.end()) - return it->second; - - return NULL; -} - -void StorageMonitor::NotifyUsageChange( - const StorageObserver::Filter& filter, int64 delta) { - // Check preconditions. - if (filter.storage_type == kStorageTypeUnknown || - filter.storage_type == kStorageTypeQuotaNotManaged || - filter.origin.is_empty()) { - NOTREACHED(); - return; - } - - StorageTypeObserversMap::iterator it = - storage_type_observers_map_.find(filter.storage_type); - if (it == storage_type_observers_map_.end()) - return; - - it->second->NotifyUsageChange(filter, delta); -} - -} // namespace storage diff --git a/webkit/browser/quota/storage_monitor.h b/webkit/browser/quota/storage_monitor.h index 66a7e8a..48992e4 100644 --- a/webkit/browser/quota/storage_monitor.h +++ b/webkit/browser/quota/storage_monitor.h @@ -2,179 +2,4 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBKIT_BROWSER_QUOTA_STORAGE_MONITOR_H_ -#define WEBKIT_BROWSER_QUOTA_STORAGE_MONITOR_H_ - -#include <map> - -#include "base/memory/weak_ptr.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "webkit/browser/quota/storage_observer.h" - -namespace content { -class StorageMonitorTestBase; -} - -namespace storage { - -class QuotaManager; - -// This class dispatches storage events to observers of a common -// StorageObserver::Filter. -class STORAGE_EXPORT_PRIVATE StorageObserverList { - public: - StorageObserverList(); - virtual ~StorageObserverList(); - - // Adds/removes an observer. - void AddObserver(StorageObserver* observer, - const StorageObserver::MonitorParams& params); - void RemoveObserver(StorageObserver* observer); - - // Returns the number of observers. - int ObserverCount() const; - - // Forwards a storage change to observers. The event may be dispatched - // immediately to an observer or after a delay, depending on the desired event - // rate of the observer. - void OnStorageChange(const StorageObserver::Event& event); - - // Dispatch an event to observers that require it. - void MaybeDispatchEvent(const StorageObserver::Event& event); - - // Ensure the specified observer receives the next dispatched event. - void ScheduleUpdateForObserver(StorageObserver* observer); - - private: - struct STORAGE_EXPORT_PRIVATE ObserverState { - GURL origin; - base::TimeTicks last_notification_time; - base::TimeDelta rate; - bool requires_update; - - ObserverState(); - }; - typedef std::map<StorageObserver*, ObserverState> StorageObserverStateMap; - - void DispatchPendingEvent(); - - StorageObserverStateMap observers_; - base::OneShotTimer<StorageObserverList> notification_timer_; - StorageObserver::Event pending_event_; - - friend class content::StorageMonitorTestBase; - - DISALLOW_COPY_AND_ASSIGN(StorageObserverList); -}; - - -// Manages the storage observers of a common host. Caches the usage and quota of -// the host to avoid accumulating for every change. -class STORAGE_EXPORT_PRIVATE HostStorageObservers { - public: - explicit HostStorageObservers(QuotaManager* quota_manager); - virtual ~HostStorageObservers(); - - bool is_initialized() const { return initialized_; } - - // Adds/removes an observer. - void AddObserver( - StorageObserver* observer, - const StorageObserver::MonitorParams& params); - void RemoveObserver(StorageObserver* observer); - bool ContainsObservers() const; - - // Handles a usage change. - void NotifyUsageChange(const StorageObserver::Filter& filter, int64 delta); - - private: - void StartInitialization(const StorageObserver::Filter& filter); - void GotHostUsageAndQuota(const StorageObserver::Filter& filter, - QuotaStatusCode status, - int64 usage, - int64 quota); - void DispatchEvent(const StorageObserver::Filter& filter, bool is_update); - - QuotaManager* quota_manager_; - StorageObserverList observers_; - - // Flags used during initialization of the cached properties. - bool initialized_; - bool initializing_; - bool event_occurred_before_init_; - int64 usage_deltas_during_init_; - - // Cached accumulated usage and quota for the host. - int64 cached_usage_; - int64 cached_quota_; - - base::WeakPtrFactory<HostStorageObservers> weak_factory_; - - friend class content::StorageMonitorTestBase; - - DISALLOW_COPY_AND_ASSIGN(HostStorageObservers); -}; - - -// Manages the observers of a common storage type. -class STORAGE_EXPORT_PRIVATE StorageTypeObservers { - public: - explicit StorageTypeObservers(QuotaManager* quota_manager); - virtual ~StorageTypeObservers(); - - // Adds and removes an observer. - void AddObserver(StorageObserver* observer, - const StorageObserver::MonitorParams& params); - void RemoveObserver(StorageObserver* observer); - void RemoveObserverForFilter(StorageObserver* observer, - const StorageObserver::Filter& filter); - - // Returns the observers of a specific host. - const HostStorageObservers* GetHostObservers(const std::string& host) const; - - // Handles a usage change. - void NotifyUsageChange(const StorageObserver::Filter& filter, int64 delta); - - private: - typedef std::map<std::string, HostStorageObservers*> HostObserversMap; - - QuotaManager* quota_manager_; - HostObserversMap host_observers_map_; - - DISALLOW_COPY_AND_ASSIGN(StorageTypeObservers); -}; - - -// Storage monitor manages observers and dispatches storage events to them. -class STORAGE_EXPORT_PRIVATE StorageMonitor { - public: - explicit StorageMonitor(QuotaManager* quota_manager); - virtual ~StorageMonitor(); - - // Adds and removes an observer. - void AddObserver(StorageObserver* observer, - const StorageObserver::MonitorParams& params); - void RemoveObserver(StorageObserver* observer); - void RemoveObserverForFilter(StorageObserver* observer, - const StorageObserver::Filter& filter); - - // Returns the observers of a specific storage type. - const StorageTypeObservers* GetStorageTypeObservers( - StorageType storage_type) const; - - // Handles a usage change. - void NotifyUsageChange(const StorageObserver::Filter& filter, int64 delta); - - private: - typedef std::map<StorageType, StorageTypeObservers*> StorageTypeObserversMap; - - QuotaManager* quota_manager_; - StorageTypeObserversMap storage_type_observers_map_; - - DISALLOW_COPY_AND_ASSIGN(StorageMonitor); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_QUOTA_STORAGE_MONITOR_H_ +#include "storage/browser/quota/storage_monitor.h" diff --git a/webkit/browser/quota/storage_observer.cc b/webkit/browser/quota/storage_observer.cc deleted file mode 100644 index ec0fe23..0000000 --- a/webkit/browser/quota/storage_observer.cc +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2014 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/browser/quota/storage_observer.h" - -namespace storage { - -// StorageObserver::Filter - -StorageObserver::Filter::Filter() - : storage_type(kStorageTypeUnknown) { -} - -StorageObserver::Filter::Filter(StorageType storage_type, const GURL& origin) - : storage_type(storage_type), origin(origin) { -} - -bool StorageObserver::Filter::operator==(const Filter& other) const { - return storage_type == other.storage_type && - origin == other.origin; -} - -// StorageObserver::MonitorParams - -StorageObserver::MonitorParams::MonitorParams() - : dispatch_initial_state(false) { -} - -StorageObserver::MonitorParams::MonitorParams( - StorageType storage_type, - const GURL& origin, - const base::TimeDelta& rate, - bool get_initial_state) - : filter(storage_type, origin), - rate(rate), - dispatch_initial_state(get_initial_state) { -} - -StorageObserver::MonitorParams::MonitorParams( - const Filter& filter, - const base::TimeDelta& rate, - bool get_initial_state) - : filter(filter), - rate(rate), - dispatch_initial_state(get_initial_state) { -} - -// StorageObserver::Event - -StorageObserver::Event::Event() - : usage(0), quota(0) { -} - -StorageObserver::Event::Event(const Filter& filter, int64 usage, int64 quota) - : filter(filter), usage(usage), quota(quota) { -} - -bool StorageObserver::Event::operator==(const Event& other) const { - return filter == other.filter && - usage == other.usage && - quota == other.quota; -} - -} // namespace storage diff --git a/webkit/browser/quota/storage_observer.h b/webkit/browser/quota/storage_observer.h index 1272f941..e732df1 100644 --- a/webkit/browser/quota/storage_observer.h +++ b/webkit/browser/quota/storage_observer.h @@ -2,78 +2,4 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBKIT_BROWSER_QUOTA_STORAGE_OBSERVER_H_ -#define WEBKIT_BROWSER_QUOTA_STORAGE_OBSERVER_H_ - -#include "base/basictypes.h" -#include "base/time/time.h" -#include "url/gurl.h" -#include "webkit/browser/quota/quota_client.h" -#include "webkit/common/quota/quota_types.h" - -namespace storage { - -// This interface is implemented by observers that wish to monitor storage -// events, such as changes in quota or usage. -class STORAGE_EXPORT StorageObserver { - public: - struct STORAGE_EXPORT Filter { - // The storage type to monitor. This must not be kStorageTypeUnknown or - // kStorageTypeQuotaNotManaged. - StorageType storage_type; - - // The origin to monitor usage for. Must be specified. - GURL origin; - - Filter(); - Filter(StorageType storage_type, const GURL& origin); - bool operator==(const Filter& other) const; - }; - - struct STORAGE_EXPORT MonitorParams { - // Storage type and origin to monitor. - Filter filter; - - // The rate at which storage events will be fired. Events will be fired at - // approximately this rate, or when a storage status change has been - // detected, whichever is the least frequent. - base::TimeDelta rate; - - // If set to true, the observer will be dispatched an event when added. - bool dispatch_initial_state; - - MonitorParams(); - MonitorParams(StorageType storage_type, - const GURL& origin, - const base::TimeDelta& rate, - bool get_initial_state); - MonitorParams(const Filter& filter, - const base::TimeDelta& rate, - bool get_initial_state); - }; - - struct STORAGE_EXPORT Event { - // The storage type and origin monitored. - Filter filter; - - // The current usage corresponding to the filter. - int64 usage; - - // The quota corresponding to the filter. - int64 quota; - - Event(); - Event(const Filter& filter, int64 usage, int64 quota); - bool operator==(const Event& other) const; - }; - - // Will be called on the IO thread when a storage event occurs. - virtual void OnStorageEvent(const Event& event) = 0; - - protected: - virtual ~StorageObserver() {} -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_QUOTA_STORAGE_OBSERVER_H_ +#include "storage/browser/quota/storage_observer.h" diff --git a/webkit/browser/quota/usage_tracker.cc b/webkit/browser/quota/usage_tracker.cc deleted file mode 100644 index c2aa4c6..0000000 --- a/webkit/browser/quota/usage_tracker.cc +++ /dev/null @@ -1,694 +0,0 @@ -// Copyright 2013 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/browser/quota/usage_tracker.h" - -#include <algorithm> -#include <deque> -#include <set> -#include <string> -#include <vector> - -#include "base/bind.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/stl_util.h" -#include "net/base/net_util.h" -#include "webkit/browser/quota/storage_monitor.h" -#include "webkit/browser/quota/storage_observer.h" - -namespace storage { - -namespace { - -typedef ClientUsageTracker::OriginUsageAccumulator OriginUsageAccumulator; -typedef ClientUsageTracker::OriginSetByHost OriginSetByHost; - -void DidGetOriginUsage(const OriginUsageAccumulator& accumulator, - const GURL& origin, - int64 usage) { - accumulator.Run(origin, usage); -} - -void DidGetHostUsage(const UsageCallback& callback, - int64 limited_usage, - int64 unlimited_usage) { - DCHECK_GE(limited_usage, 0); - DCHECK_GE(unlimited_usage, 0); - callback.Run(limited_usage + unlimited_usage); -} - -bool EraseOriginFromOriginSet(OriginSetByHost* origins_by_host, - const std::string& host, - const GURL& origin) { - OriginSetByHost::iterator found = origins_by_host->find(host); - if (found == origins_by_host->end()) - return false; - - if (!found->second.erase(origin)) - return false; - - if (found->second.empty()) - origins_by_host->erase(host); - return true; -} - -bool OriginSetContainsOrigin(const OriginSetByHost& origins, - const std::string& host, - const GURL& origin) { - OriginSetByHost::const_iterator itr = origins.find(host); - return itr != origins.end() && ContainsKey(itr->second, origin); -} - -void DidGetGlobalUsageForLimitedGlobalUsage(const UsageCallback& callback, - int64 total_global_usage, - int64 global_unlimited_usage) { - callback.Run(total_global_usage - global_unlimited_usage); -} - -} // namespace - -// UsageTracker ---------------------------------------------------------- - -UsageTracker::UsageTracker(const QuotaClientList& clients, - StorageType type, - SpecialStoragePolicy* special_storage_policy, - StorageMonitor* storage_monitor) - : type_(type), - storage_monitor_(storage_monitor), - weak_factory_(this) { - for (QuotaClientList::const_iterator iter = clients.begin(); - iter != clients.end(); - ++iter) { - if ((*iter)->DoesSupport(type)) { - client_tracker_map_[(*iter)->id()] = - new ClientUsageTracker(this, *iter, type, special_storage_policy, - storage_monitor_); - } - } -} - -UsageTracker::~UsageTracker() { - STLDeleteValues(&client_tracker_map_); -} - -ClientUsageTracker* UsageTracker::GetClientTracker(QuotaClient::ID client_id) { - ClientTrackerMap::iterator found = client_tracker_map_.find(client_id); - if (found != client_tracker_map_.end()) - return found->second; - return NULL; -} - -void UsageTracker::GetGlobalLimitedUsage(const UsageCallback& callback) { - if (global_usage_callbacks_.HasCallbacks()) { - global_usage_callbacks_.Add(base::Bind( - &DidGetGlobalUsageForLimitedGlobalUsage, callback)); - return; - } - - if (!global_limited_usage_callbacks_.Add(callback)) - return; - - AccumulateInfo* info = new AccumulateInfo; - // Calling GetGlobalLimitedUsage(accumulator) may synchronously - // return if the usage is cached, which may in turn dispatch - // the completion callback before we finish looping over - // all clients (because info->pending_clients may reach 0 - // during the loop). - // To avoid this, we add one more pending client as a sentinel - // and fire the sentinel callback at the end. - info->pending_clients = client_tracker_map_.size() + 1; - UsageCallback accumulator = base::Bind( - &UsageTracker::AccumulateClientGlobalLimitedUsage, - weak_factory_.GetWeakPtr(), base::Owned(info)); - - for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); - iter != client_tracker_map_.end(); - ++iter) - iter->second->GetGlobalLimitedUsage(accumulator); - - // Fire the sentinel as we've now called GetGlobalUsage for all clients. - accumulator.Run(0); -} - -void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { - if (!global_usage_callbacks_.Add(callback)) - return; - - AccumulateInfo* info = new AccumulateInfo; - // Calling GetGlobalUsage(accumulator) may synchronously - // return if the usage is cached, which may in turn dispatch - // the completion callback before we finish looping over - // all clients (because info->pending_clients may reach 0 - // during the loop). - // To avoid this, we add one more pending client as a sentinel - // and fire the sentinel callback at the end. - info->pending_clients = client_tracker_map_.size() + 1; - GlobalUsageCallback accumulator = base::Bind( - &UsageTracker::AccumulateClientGlobalUsage, weak_factory_.GetWeakPtr(), - base::Owned(info)); - - for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); - iter != client_tracker_map_.end(); - ++iter) - iter->second->GetGlobalUsage(accumulator); - - // Fire the sentinel as we've now called GetGlobalUsage for all clients. - accumulator.Run(0, 0); -} - -void UsageTracker::GetHostUsage(const std::string& host, - const UsageCallback& callback) { - if (!host_usage_callbacks_.Add(host, callback)) - return; - - AccumulateInfo* info = new AccumulateInfo; - // Calling GetHostUsage(accumulator) may synchronously - // return if the usage is cached, which may in turn dispatch - // the completion callback before we finish looping over - // all clients (because info->pending_clients may reach 0 - // during the loop). - // To avoid this, we add one more pending client as a sentinel - // and fire the sentinel callback at the end. - info->pending_clients = client_tracker_map_.size() + 1; - UsageCallback accumulator = base::Bind( - &UsageTracker::AccumulateClientHostUsage, weak_factory_.GetWeakPtr(), - base::Owned(info), host); - - for (ClientTrackerMap::iterator iter = client_tracker_map_.begin(); - iter != client_tracker_map_.end(); - ++iter) - iter->second->GetHostUsage(host, accumulator); - - // Fire the sentinel as we've now called GetHostUsage for all clients. - accumulator.Run(0); -} - -void UsageTracker::UpdateUsageCache( - QuotaClient::ID client_id, const GURL& origin, int64 delta) { - ClientUsageTracker* client_tracker = GetClientTracker(client_id); - DCHECK(client_tracker); - client_tracker->UpdateUsageCache(origin, delta); -} - -void UsageTracker::GetCachedHostsUsage( - std::map<std::string, int64>* host_usage) const { - DCHECK(host_usage); - host_usage->clear(); - for (ClientTrackerMap::const_iterator iter = client_tracker_map_.begin(); - iter != client_tracker_map_.end(); ++iter) { - iter->second->GetCachedHostsUsage(host_usage); - } -} - -void UsageTracker::GetCachedOrigins(std::set<GURL>* origins) const { - DCHECK(origins); - origins->clear(); - for (ClientTrackerMap::const_iterator iter = client_tracker_map_.begin(); - iter != client_tracker_map_.end(); ++iter) { - iter->second->GetCachedOrigins(origins); - } -} - -void UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id, - const GURL& origin, - bool enabled) { - ClientUsageTracker* client_tracker = GetClientTracker(client_id); - DCHECK(client_tracker); - - client_tracker->SetUsageCacheEnabled(origin, enabled); -} - -void UsageTracker::AccumulateClientGlobalLimitedUsage(AccumulateInfo* info, - int64 limited_usage) { - info->usage += limited_usage; - if (--info->pending_clients) - return; - - // All the clients have returned their usage data. Dispatch the - // pending callbacks. - global_limited_usage_callbacks_.Run(MakeTuple(info->usage)); -} - -void UsageTracker::AccumulateClientGlobalUsage(AccumulateInfo* info, - int64 usage, - int64 unlimited_usage) { - info->usage += usage; - info->unlimited_usage += unlimited_usage; - if (--info->pending_clients) - return; - - // Defend against confusing inputs from clients. - if (info->usage < 0) - info->usage = 0; - - // TODO(michaeln): The unlimited number is not trustworthy, it - // can get out of whack when apps are installed or uninstalled. - if (info->unlimited_usage > info->usage) - info->unlimited_usage = info->usage; - else if (info->unlimited_usage < 0) - info->unlimited_usage = 0; - - // All the clients have returned their usage data. Dispatch the - // pending callbacks. - global_usage_callbacks_.Run(MakeTuple(info->usage, info->unlimited_usage)); -} - -void UsageTracker::AccumulateClientHostUsage(AccumulateInfo* info, - const std::string& host, - int64 usage) { - info->usage += usage; - if (--info->pending_clients) - return; - - // Defend against confusing inputs from clients. - if (info->usage < 0) - info->usage = 0; - - // All the clients have returned their usage data. Dispatch the - // pending callbacks. - host_usage_callbacks_.Run(host, MakeTuple(info->usage)); -} - -// ClientUsageTracker ---------------------------------------------------- - -ClientUsageTracker::ClientUsageTracker( - UsageTracker* tracker, QuotaClient* client, StorageType type, - SpecialStoragePolicy* special_storage_policy, - StorageMonitor* storage_monitor) - : tracker_(tracker), - client_(client), - type_(type), - storage_monitor_(storage_monitor), - global_limited_usage_(0), - global_unlimited_usage_(0), - global_usage_retrieved_(false), - special_storage_policy_(special_storage_policy) { - DCHECK(tracker_); - DCHECK(client_); - if (special_storage_policy_.get()) - special_storage_policy_->AddObserver(this); -} - -ClientUsageTracker::~ClientUsageTracker() { - if (special_storage_policy_.get()) - special_storage_policy_->RemoveObserver(this); -} - -void ClientUsageTracker::GetGlobalLimitedUsage(const UsageCallback& callback) { - if (!global_usage_retrieved_) { - GetGlobalUsage(base::Bind(&DidGetGlobalUsageForLimitedGlobalUsage, - callback)); - return; - } - - if (non_cached_limited_origins_by_host_.empty()) { - callback.Run(global_limited_usage_); - return; - } - - AccumulateInfo* info = new AccumulateInfo; - info->pending_jobs = non_cached_limited_origins_by_host_.size() + 1; - UsageCallback accumulator = base::Bind( - &ClientUsageTracker::AccumulateLimitedOriginUsage, AsWeakPtr(), - base::Owned(info), callback); - - for (OriginSetByHost::iterator host_itr = - non_cached_limited_origins_by_host_.begin(); - host_itr != non_cached_limited_origins_by_host_.end(); ++host_itr) { - for (std::set<GURL>::iterator origin_itr = host_itr->second.begin(); - origin_itr != host_itr->second.end(); ++origin_itr) - client_->GetOriginUsage(*origin_itr, type_, accumulator); - } - - accumulator.Run(global_limited_usage_); -} - -void ClientUsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { - if (global_usage_retrieved_ && - non_cached_limited_origins_by_host_.empty() && - non_cached_unlimited_origins_by_host_.empty()) { - callback.Run(global_limited_usage_ + global_unlimited_usage_, - global_unlimited_usage_); - return; - } - - client_->GetOriginsForType(type_, base::Bind( - &ClientUsageTracker::DidGetOriginsForGlobalUsage, AsWeakPtr(), - callback)); -} - -void ClientUsageTracker::GetHostUsage( - const std::string& host, const UsageCallback& callback) { - if (ContainsKey(cached_hosts_, host) && - !ContainsKey(non_cached_limited_origins_by_host_, host) && - !ContainsKey(non_cached_unlimited_origins_by_host_, host)) { - // TODO(kinuko): Drop host_usage_map_ cache periodically. - callback.Run(GetCachedHostUsage(host)); - return; - } - - if (!host_usage_accumulators_.Add( - host, base::Bind(&DidGetHostUsage, callback))) - return; - client_->GetOriginsForHost(type_, host, base::Bind( - &ClientUsageTracker::DidGetOriginsForHostUsage, AsWeakPtr(), host)); -} - -void ClientUsageTracker::UpdateUsageCache( - const GURL& origin, int64 delta) { - std::string host = net::GetHostOrSpecFromURL(origin); - if (cached_hosts_.find(host) != cached_hosts_.end()) { - if (!IsUsageCacheEnabledForOrigin(origin)) - return; - - cached_usage_by_host_[host][origin] += delta; - if (IsStorageUnlimited(origin)) - global_unlimited_usage_ += delta; - else - global_limited_usage_ += delta; - DCHECK_GE(cached_usage_by_host_[host][origin], 0); - DCHECK_GE(global_limited_usage_, 0); - - // Notify the usage monitor that usage has changed. The storage monitor may - // be NULL during tests. - if (storage_monitor_) { - StorageObserver::Filter filter(type_, origin); - storage_monitor_->NotifyUsageChange(filter, delta); - } - return; - } - - // We don't know about this host yet, so populate our cache for it. - GetHostUsage(host, base::Bind(&ClientUsageTracker::DidGetHostUsageAfterUpdate, - AsWeakPtr(), origin)); -} - -void ClientUsageTracker::GetCachedHostsUsage( - std::map<std::string, int64>* host_usage) const { - DCHECK(host_usage); - for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin(); - host_iter != cached_usage_by_host_.end(); host_iter++) { - const std::string& host = host_iter->first; - (*host_usage)[host] += GetCachedHostUsage(host); - } -} - -void ClientUsageTracker::GetCachedOrigins(std::set<GURL>* origins) const { - DCHECK(origins); - for (HostUsageMap::const_iterator host_iter = cached_usage_by_host_.begin(); - host_iter != cached_usage_by_host_.end(); host_iter++) { - const UsageMap& origin_map = host_iter->second; - for (UsageMap::const_iterator origin_iter = origin_map.begin(); - origin_iter != origin_map.end(); origin_iter++) { - origins->insert(origin_iter->first); - } - } -} - -void ClientUsageTracker::SetUsageCacheEnabled(const GURL& origin, - bool enabled) { - std::string host = net::GetHostOrSpecFromURL(origin); - if (!enabled) { - // Erase |origin| from cache and subtract its usage. - HostUsageMap::iterator found_host = cached_usage_by_host_.find(host); - if (found_host != cached_usage_by_host_.end()) { - UsageMap& cached_usage_for_host = found_host->second; - - UsageMap::iterator found = cached_usage_for_host.find(origin); - if (found != cached_usage_for_host.end()) { - int64 usage = found->second; - UpdateUsageCache(origin, -usage); - cached_usage_for_host.erase(found); - if (cached_usage_for_host.empty()) { - cached_usage_by_host_.erase(found_host); - cached_hosts_.erase(host); - } - } - } - - if (IsStorageUnlimited(origin)) - non_cached_unlimited_origins_by_host_[host].insert(origin); - else - non_cached_limited_origins_by_host_[host].insert(origin); - } else { - // Erase |origin| from |non_cached_origins_| and invalidate the usage cache - // for the host. - if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, - host, origin) || - EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, - host, origin)) { - cached_hosts_.erase(host); - global_usage_retrieved_ = false; - } - } -} - -void ClientUsageTracker::AccumulateLimitedOriginUsage( - AccumulateInfo* info, - const UsageCallback& callback, - int64 usage) { - info->limited_usage += usage; - if (--info->pending_jobs) - return; - - callback.Run(info->limited_usage); -} - -void ClientUsageTracker::DidGetOriginsForGlobalUsage( - const GlobalUsageCallback& callback, - const std::set<GURL>& origins) { - OriginSetByHost origins_by_host; - for (std::set<GURL>::const_iterator itr = origins.begin(); - itr != origins.end(); ++itr) - origins_by_host[net::GetHostOrSpecFromURL(*itr)].insert(*itr); - - AccumulateInfo* info = new AccumulateInfo; - // Getting host usage may synchronously return the result if the usage is - // cached, which may in turn dispatch the completion callback before we finish - // looping over all hosts (because info->pending_jobs may reach 0 during the - // loop). To avoid this, we add one more pending host as a sentinel and - // fire the sentinel callback at the end. - info->pending_jobs = origins_by_host.size() + 1; - HostUsageAccumulator accumulator = - base::Bind(&ClientUsageTracker::AccumulateHostUsage, AsWeakPtr(), - base::Owned(info), callback); - - for (OriginSetByHost::iterator itr = origins_by_host.begin(); - itr != origins_by_host.end(); ++itr) { - if (host_usage_accumulators_.Add(itr->first, accumulator)) - GetUsageForOrigins(itr->first, itr->second); - } - - // Fire the sentinel as we've now called GetUsageForOrigins for all clients. - accumulator.Run(0, 0); -} - -void ClientUsageTracker::AccumulateHostUsage( - AccumulateInfo* info, - const GlobalUsageCallback& callback, - int64 limited_usage, - int64 unlimited_usage) { - info->limited_usage += limited_usage; - info->unlimited_usage += unlimited_usage; - if (--info->pending_jobs) - return; - - DCHECK_GE(info->limited_usage, 0); - DCHECK_GE(info->unlimited_usage, 0); - - global_usage_retrieved_ = true; - callback.Run(info->limited_usage + info->unlimited_usage, - info->unlimited_usage); -} - -void ClientUsageTracker::DidGetOriginsForHostUsage( - const std::string& host, - const std::set<GURL>& origins) { - GetUsageForOrigins(host, origins); -} - -void ClientUsageTracker::GetUsageForOrigins( - const std::string& host, - const std::set<GURL>& origins) { - AccumulateInfo* info = new AccumulateInfo; - // Getting origin usage may synchronously return the result if the usage is - // cached, which may in turn dispatch the completion callback before we finish - // looping over all origins (because info->pending_jobs may reach 0 during the - // loop). To avoid this, we add one more pending origin as a sentinel and - // fire the sentinel callback at the end. - info->pending_jobs = origins.size() + 1; - OriginUsageAccumulator accumulator = - base::Bind(&ClientUsageTracker::AccumulateOriginUsage, AsWeakPtr(), - base::Owned(info), host); - - for (std::set<GURL>::const_iterator itr = origins.begin(); - itr != origins.end(); ++itr) { - DCHECK_EQ(host, net::GetHostOrSpecFromURL(*itr)); - - int64 origin_usage = 0; - if (GetCachedOriginUsage(*itr, &origin_usage)) { - accumulator.Run(*itr, origin_usage); - } else { - client_->GetOriginUsage(*itr, type_, base::Bind( - &DidGetOriginUsage, accumulator, *itr)); - } - } - - // Fire the sentinel as we've now called GetOriginUsage for all clients. - accumulator.Run(GURL(), 0); -} - -void ClientUsageTracker::AccumulateOriginUsage(AccumulateInfo* info, - const std::string& host, - const GURL& origin, - int64 usage) { - if (!origin.is_empty()) { - if (usage < 0) - usage = 0; - - if (IsStorageUnlimited(origin)) - info->unlimited_usage += usage; - else - info->limited_usage += usage; - if (IsUsageCacheEnabledForOrigin(origin)) - AddCachedOrigin(origin, usage); - } - if (--info->pending_jobs) - return; - - AddCachedHost(host); - host_usage_accumulators_.Run( - host, MakeTuple(info->limited_usage, info->unlimited_usage)); -} - -void ClientUsageTracker::DidGetHostUsageAfterUpdate( - const GURL& origin, int64 usage) { - if (!storage_monitor_) - return; - - StorageObserver::Filter filter(type_, origin); - storage_monitor_->NotifyUsageChange(filter, 0); -} - -void ClientUsageTracker::AddCachedOrigin( - const GURL& origin, int64 new_usage) { - DCHECK(IsUsageCacheEnabledForOrigin(origin)); - - std::string host = net::GetHostOrSpecFromURL(origin); - int64* usage = &cached_usage_by_host_[host][origin]; - int64 delta = new_usage - *usage; - *usage = new_usage; - if (delta) { - if (IsStorageUnlimited(origin)) - global_unlimited_usage_ += delta; - else - global_limited_usage_ += delta; - } - DCHECK_GE(*usage, 0); - DCHECK_GE(global_limited_usage_, 0); -} - -void ClientUsageTracker::AddCachedHost(const std::string& host) { - cached_hosts_.insert(host); -} - -int64 ClientUsageTracker::GetCachedHostUsage(const std::string& host) const { - HostUsageMap::const_iterator found = cached_usage_by_host_.find(host); - if (found == cached_usage_by_host_.end()) - return 0; - - int64 usage = 0; - const UsageMap& map = found->second; - for (UsageMap::const_iterator iter = map.begin(); - iter != map.end(); ++iter) { - usage += iter->second; - } - return usage; -} - -bool ClientUsageTracker::GetCachedOriginUsage( - const GURL& origin, - int64* usage) const { - std::string host = net::GetHostOrSpecFromURL(origin); - HostUsageMap::const_iterator found_host = cached_usage_by_host_.find(host); - if (found_host == cached_usage_by_host_.end()) - return false; - - UsageMap::const_iterator found = found_host->second.find(origin); - if (found == found_host->second.end()) - return false; - - DCHECK(IsUsageCacheEnabledForOrigin(origin)); - *usage = found->second; - return true; -} - -bool ClientUsageTracker::IsUsageCacheEnabledForOrigin( - const GURL& origin) const { - std::string host = net::GetHostOrSpecFromURL(origin); - return !OriginSetContainsOrigin(non_cached_limited_origins_by_host_, - host, origin) && - !OriginSetContainsOrigin(non_cached_unlimited_origins_by_host_, - host, origin); -} - -void ClientUsageTracker::OnGranted(const GURL& origin, - int change_flags) { - DCHECK(CalledOnValidThread()); - if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { - int64 usage = 0; - if (GetCachedOriginUsage(origin, &usage)) { - global_unlimited_usage_ += usage; - global_limited_usage_ -= usage; - } - - std::string host = net::GetHostOrSpecFromURL(origin); - if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, - host, origin)) - non_cached_unlimited_origins_by_host_[host].insert(origin); - } -} - -void ClientUsageTracker::OnRevoked(const GURL& origin, - int change_flags) { - DCHECK(CalledOnValidThread()); - if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { - int64 usage = 0; - if (GetCachedOriginUsage(origin, &usage)) { - global_unlimited_usage_ -= usage; - global_limited_usage_ += usage; - } - - std::string host = net::GetHostOrSpecFromURL(origin); - if (EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, - host, origin)) - non_cached_limited_origins_by_host_[host].insert(origin); - } -} - -void ClientUsageTracker::OnCleared() { - DCHECK(CalledOnValidThread()); - global_limited_usage_ += global_unlimited_usage_; - global_unlimited_usage_ = 0; - - for (OriginSetByHost::const_iterator host_itr = - non_cached_unlimited_origins_by_host_.begin(); - host_itr != non_cached_unlimited_origins_by_host_.end(); - ++host_itr) { - for (std::set<GURL>::const_iterator origin_itr = host_itr->second.begin(); - origin_itr != host_itr->second.end(); - ++origin_itr) - non_cached_limited_origins_by_host_[host_itr->first].insert(*origin_itr); - } - non_cached_unlimited_origins_by_host_.clear(); -} - -bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { - if (type_ == kStorageTypeSyncable) - return false; - return special_storage_policy_.get() && - special_storage_policy_->IsStorageUnlimited(origin); -} - -} // namespace storage diff --git a/webkit/browser/quota/usage_tracker.h b/webkit/browser/quota/usage_tracker.h index 85792ac..e576d00 100644 --- a/webkit/browser/quota/usage_tracker.h +++ b/webkit/browser/quota/usage_tracker.h @@ -1,202 +1,5 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_QUOTA_USAGE_TRACKER_H_ -#define WEBKIT_BROWSER_QUOTA_USAGE_TRACKER_H_ - -#include <list> -#include <map> -#include <set> -#include <string> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "url/gurl.h" -#include "webkit/browser/quota/quota_callbacks.h" -#include "webkit/browser/quota/quota_client.h" -#include "webkit/browser/quota/quota_task.h" -#include "webkit/browser/quota/special_storage_policy.h" -#include "webkit/browser/storage_browser_export.h" -#include "webkit/common/quota/quota_types.h" - -namespace storage { - -class ClientUsageTracker; -class StorageMonitor; - -// A helper class that gathers and tracks the amount of data stored in -// all quota clients. -// An instance of this class is created per storage type. -class STORAGE_EXPORT UsageTracker : public QuotaTaskObserver { - public: - UsageTracker(const QuotaClientList& clients, StorageType type, - SpecialStoragePolicy* special_storage_policy, - StorageMonitor* storage_monitor); - virtual ~UsageTracker(); - - StorageType type() const { return type_; } - ClientUsageTracker* GetClientTracker(QuotaClient::ID client_id); - - void GetGlobalLimitedUsage(const UsageCallback& callback); - void GetGlobalUsage(const GlobalUsageCallback& callback); - void GetHostUsage(const std::string& host, const UsageCallback& callback); - void UpdateUsageCache(QuotaClient::ID client_id, - const GURL& origin, - int64 delta); - void GetCachedHostsUsage(std::map<std::string, int64>* host_usage) const; - void GetCachedOrigins(std::set<GURL>* origins) const; - bool IsWorking() const { - return global_usage_callbacks_.HasCallbacks() || - host_usage_callbacks_.HasAnyCallbacks(); - } - - void SetUsageCacheEnabled(QuotaClient::ID client_id, - const GURL& origin, - bool enabled); - - private: - struct AccumulateInfo { - AccumulateInfo() : pending_clients(0), usage(0), unlimited_usage(0) {} - int pending_clients; - int64 usage; - int64 unlimited_usage; - }; - - typedef std::map<QuotaClient::ID, ClientUsageTracker*> ClientTrackerMap; - - friend class ClientUsageTracker; - void AccumulateClientGlobalLimitedUsage(AccumulateInfo* info, - int64 limited_usage); - void AccumulateClientGlobalUsage(AccumulateInfo* info, - int64 usage, - int64 unlimited_usage); - void AccumulateClientHostUsage(AccumulateInfo* info, - const std::string& host, - int64 usage); - - const StorageType type_; - ClientTrackerMap client_tracker_map_; - - UsageCallbackQueue global_limited_usage_callbacks_; - GlobalUsageCallbackQueue global_usage_callbacks_; - HostUsageCallbackMap host_usage_callbacks_; - - StorageMonitor* storage_monitor_; - - base::WeakPtrFactory<UsageTracker> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(UsageTracker); -}; - -// This class holds per-client usage tracking information and caches per-host -// usage data. An instance of this class is created per client. -class ClientUsageTracker : public SpecialStoragePolicy::Observer, - public base::NonThreadSafe, - public base::SupportsWeakPtr<ClientUsageTracker> { - public: - typedef base::Callback<void(int64 limited_usage, - int64 unlimited_usage)> HostUsageAccumulator; - typedef base::Callback<void(const GURL& origin, - int64 usage)> OriginUsageAccumulator; - typedef std::map<std::string, std::set<GURL> > OriginSetByHost; - - ClientUsageTracker(UsageTracker* tracker, - QuotaClient* client, - StorageType type, - SpecialStoragePolicy* special_storage_policy, - StorageMonitor* storage_monitor); - virtual ~ClientUsageTracker(); - - void GetGlobalLimitedUsage(const UsageCallback& callback); - void GetGlobalUsage(const GlobalUsageCallback& callback); - void GetHostUsage(const std::string& host, const UsageCallback& callback); - void UpdateUsageCache(const GURL& origin, int64 delta); - void GetCachedHostsUsage(std::map<std::string, int64>* host_usage) const; - void GetCachedOrigins(std::set<GURL>* origins) const; - int64 GetCachedOriginsUsage(const std::set<GURL>& origins, - std::vector<GURL>* origins_not_in_cache); - bool IsUsageCacheEnabledForOrigin(const GURL& origin) const; - void SetUsageCacheEnabled(const GURL& origin, bool enabled); - - private: - typedef CallbackQueueMap<HostUsageAccumulator, std::string, - Tuple2<int64, int64> > HostUsageAccumulatorMap; - - typedef std::set<std::string> HostSet; - typedef std::map<GURL, int64> UsageMap; - typedef std::map<std::string, UsageMap> HostUsageMap; - - struct AccumulateInfo { - int pending_jobs; - int64 limited_usage; - int64 unlimited_usage; - - AccumulateInfo() - : pending_jobs(0), limited_usage(0), unlimited_usage(0) {} - }; - - void AccumulateLimitedOriginUsage(AccumulateInfo* info, - const UsageCallback& callback, - int64 usage); - void DidGetOriginsForGlobalUsage(const GlobalUsageCallback& callback, - const std::set<GURL>& origins); - void AccumulateHostUsage(AccumulateInfo* info, - const GlobalUsageCallback& callback, - int64 limited_usage, - int64 unlimited_usage); - - void DidGetOriginsForHostUsage(const std::string& host, - const std::set<GURL>& origins); - - void GetUsageForOrigins(const std::string& host, - const std::set<GURL>& origins); - void AccumulateOriginUsage(AccumulateInfo* info, - const std::string& host, - const GURL& origin, - int64 usage); - - void DidGetHostUsageAfterUpdate(const GURL& origin, int64 usage); - - // Methods used by our GatherUsage tasks, as a task makes progress - // origins and hosts are added incrementally to the cache. - void AddCachedOrigin(const GURL& origin, int64 usage); - void AddCachedHost(const std::string& host); - - int64 GetCachedHostUsage(const std::string& host) const; - int64 GetCachedGlobalUnlimitedUsage(); - bool GetCachedOriginUsage(const GURL& origin, int64* usage) const; - - // SpecialStoragePolicy::Observer overrides - virtual void OnGranted(const GURL& origin, int change_flags) OVERRIDE; - virtual void OnRevoked(const GURL& origin, int change_flags) OVERRIDE; - virtual void OnCleared() OVERRIDE; - - bool IsStorageUnlimited(const GURL& origin) const; - - UsageTracker* tracker_; - QuotaClient* client_; - const StorageType type_; - StorageMonitor* storage_monitor_; - - int64 global_limited_usage_; - int64 global_unlimited_usage_; - bool global_usage_retrieved_; - HostSet cached_hosts_; - HostUsageMap cached_usage_by_host_; - - OriginSetByHost non_cached_limited_origins_by_host_; - OriginSetByHost non_cached_unlimited_origins_by_host_; - - GlobalUsageCallbackQueue global_usage_callback_; - HostUsageAccumulatorMap host_usage_accumulators_; - - scoped_refptr<SpecialStoragePolicy> special_storage_policy_; - - DISALLOW_COPY_AND_ASSIGN(ClientUsageTracker); -}; - -} // namespace storage - -#endif // WEBKIT_BROWSER_QUOTA_USAGE_TRACKER_H_ +#include "storage/browser/quota/usage_tracker.h" diff --git a/webkit/browser/storage_browser_export.h b/webkit/browser/storage_browser_export.h index 293ce40..421ae558 100644 --- a/webkit/browser/storage_browser_export.h +++ b/webkit/browser/storage_browser_export.h @@ -1,34 +1,5 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2014 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_BROWSER_STORAGE_BROWSER_EXPORT_H__ -#define WEBKIT_BROWSER_STORAGE_BROWSER_EXPORT_H__ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(STORAGE_BROWSER_IMPLEMENTATION) -#define STORAGE_EXPORT __declspec(dllexport) -#define STORAGE_EXPORT_PRIVATE __declspec(dllexport) -#else -#define STORAGE_EXPORT __declspec(dllimport) -#define STORAGE_EXPORT_PRIVATE __declspec(dllimport) -#endif // defined(STORAGE_BROWSER_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(STORAGE_BROWSER_IMPLEMENTATION) -#define STORAGE_EXPORT __attribute__((visibility("default"))) -#define STORAGE_EXPORT_PRIVATE __attribute__((visibility("default"))) -#else -#define STORAGE_EXPORT -#define STORAGE_EXPORT_PRIVATE -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define STORAGE_EXPORT -#define STORAGE_EXPORT_PRIVATE -#endif - -#endif // WEBKIT_BROWSER_STORAGE_BROWSER_EXPORT_H__ +#include "storage/browser/storage_browser_export.h" diff --git a/webkit/storage_browser.gyp b/webkit/storage_browser.gyp deleted file mode 100644 index ed08918..0000000 --- a/webkit/storage_browser.gyp +++ /dev/null @@ -1,199 +0,0 @@ -# Copyright 2013 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. - -{ - 'variables': { - 'chromium_code': 1, - }, - 'targets': [ - { - # GN version: //webkit/browser:storage - 'target_name': 'storage', - 'type': '<(component)', - 'variables': { 'enable_wexit_time_destructors': 1, }, - 'dependencies': [ - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/base/base.gyp:base_i18n', - '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', - '<(DEPTH)/net/net.gyp:net', - '<(DEPTH)/sql/sql.gyp:sql', - '<(DEPTH)/storage/storage_common.gyp:storage_common', - '<(DEPTH)/third_party/leveldatabase/leveldatabase.gyp:leveldatabase', - '<(DEPTH)/third_party/sqlite/sqlite.gyp:sqlite', - '<(DEPTH)/url/url.gyp:url_lib', - ], - 'defines': ['STORAGE_BROWSER_IMPLEMENTATION'], - 'sources': [ - 'browser/blob/blob_data_handle.cc', - 'browser/blob/blob_data_handle.h', - 'browser/blob/blob_storage_context.cc', - 'browser/blob/blob_storage_context.h', - 'browser/blob/blob_url_request_job.cc', - 'browser/blob/blob_url_request_job.h', - 'browser/blob/blob_url_request_job_factory.cc', - 'browser/blob/blob_url_request_job_factory.h', - 'browser/blob/file_stream_reader.cc', - 'browser/blob/file_stream_reader.h', - 'browser/blob/local_file_stream_reader.cc', - 'browser/blob/local_file_stream_reader.h', - 'browser/blob/view_blob_internals_job.cc', - 'browser/blob/view_blob_internals_job.h', - 'browser/database/database_quota_client.cc', - 'browser/database/database_quota_client.h', - 'browser/database/database_tracker.cc', - 'browser/database/database_tracker.h', - 'browser/database/database_util.cc', - 'browser/database/database_util.h', - 'browser/database/databases_table.cc', - 'browser/database/databases_table.h', - 'browser/database/vfs_backend.cc', - 'browser/database/vfs_backend.h', - 'browser/fileapi/async_file_util.h', - 'browser/fileapi/async_file_util_adapter.cc', - 'browser/fileapi/async_file_util_adapter.h', - 'browser/fileapi/copy_or_move_file_validator.h', - 'browser/fileapi/copy_or_move_operation_delegate.cc', - 'browser/fileapi/copy_or_move_operation_delegate.h', - 'browser/fileapi/dragged_file_util.cc', - 'browser/fileapi/dragged_file_util.h', - 'browser/fileapi/external_mount_points.cc', - 'browser/fileapi/external_mount_points.h', - 'browser/fileapi/file_observers.h', - 'browser/fileapi/file_permission_policy.h', - 'browser/fileapi/file_stream_writer.h', - 'browser/fileapi/file_system_backend.h', - 'browser/fileapi/file_system_context.cc', - 'browser/fileapi/file_system_context.h', - 'browser/fileapi/file_system_dir_url_request_job.cc', - 'browser/fileapi/file_system_dir_url_request_job.h', - 'browser/fileapi/file_system_file_stream_reader.cc', - 'browser/fileapi/file_system_file_stream_reader.h', - 'browser/fileapi/file_system_file_util.cc', - 'browser/fileapi/file_system_file_util.h', - 'browser/fileapi/file_system_operation.h', - 'browser/fileapi/file_system_operation_context.cc', - 'browser/fileapi/file_system_operation_context.h', - 'browser/fileapi/file_system_operation_impl.cc', - 'browser/fileapi/file_system_operation_impl.h', - 'browser/fileapi/file_system_operation_runner.cc', - 'browser/fileapi/file_system_operation_runner.h', - 'browser/fileapi/file_system_options.cc', - 'browser/fileapi/file_system_options.h', - 'browser/fileapi/file_system_quota_client.cc', - 'browser/fileapi/file_system_quota_client.h', - 'browser/fileapi/file_system_quota_util.h', - 'browser/fileapi/file_system_url.cc', - 'browser/fileapi/file_system_url.h', - 'browser/fileapi/file_system_url_request_job.cc', - 'browser/fileapi/file_system_url_request_job.h', - 'browser/fileapi/file_system_url_request_job_factory.cc', - 'browser/fileapi/file_system_url_request_job_factory.h', - 'browser/fileapi/file_system_usage_cache.cc', - 'browser/fileapi/file_system_usage_cache.h', - 'browser/fileapi/file_writer_delegate.cc', - 'browser/fileapi/file_writer_delegate.h', - 'browser/fileapi/isolated_context.cc', - 'browser/fileapi/isolated_context.h', - 'browser/fileapi/isolated_file_system_backend.cc', - 'browser/fileapi/isolated_file_system_backend.h', - 'browser/fileapi/local_file_stream_writer.cc', - 'browser/fileapi/local_file_stream_writer.h', - 'browser/fileapi/local_file_util.cc', - 'browser/fileapi/local_file_util.h', - 'browser/fileapi/mount_points.cc', - 'browser/fileapi/mount_points.h', - 'browser/fileapi/native_file_util.cc', - 'browser/fileapi/native_file_util.h', - 'browser/fileapi/obfuscated_file_util.cc', - 'browser/fileapi/obfuscated_file_util.h', - 'browser/fileapi/open_file_system_mode.h', - 'browser/fileapi/plugin_private_file_system_backend.cc', - 'browser/fileapi/plugin_private_file_system_backend.h', - 'browser/fileapi/quota/open_file_handle.cc', - 'browser/fileapi/quota/open_file_handle.h', - 'browser/fileapi/quota/open_file_handle_context.cc', - 'browser/fileapi/quota/open_file_handle_context.h', - 'browser/fileapi/quota/quota_backend_impl.cc', - 'browser/fileapi/quota/quota_backend_impl.h', - 'browser/fileapi/quota/quota_reservation.cc', - 'browser/fileapi/quota/quota_reservation.h', - 'browser/fileapi/quota/quota_reservation_buffer.cc', - 'browser/fileapi/quota/quota_reservation_buffer.h', - 'browser/fileapi/quota/quota_reservation_manager.cc', - 'browser/fileapi/quota/quota_reservation_manager.h', - 'browser/fileapi/recursive_operation_delegate.cc', - 'browser/fileapi/recursive_operation_delegate.h', - 'browser/fileapi/remove_operation_delegate.cc', - 'browser/fileapi/remove_operation_delegate.h', - 'browser/fileapi/sandbox_directory_database.cc', - 'browser/fileapi/sandbox_directory_database.h', - 'browser/fileapi/sandbox_file_stream_writer.cc', - 'browser/fileapi/sandbox_file_stream_writer.h', - 'browser/fileapi/sandbox_file_system_backend.cc', - 'browser/fileapi/sandbox_file_system_backend.h', - 'browser/fileapi/sandbox_file_system_backend_delegate.cc', - 'browser/fileapi/sandbox_file_system_backend_delegate.h', - 'browser/fileapi/sandbox_isolated_origin_database.cc', - 'browser/fileapi/sandbox_isolated_origin_database.h', - 'browser/fileapi/sandbox_origin_database.cc', - 'browser/fileapi/sandbox_origin_database.h', - 'browser/fileapi/sandbox_origin_database_interface.cc', - 'browser/fileapi/sandbox_origin_database_interface.h', - 'browser/fileapi/sandbox_prioritized_origin_database.cc', - 'browser/fileapi/sandbox_prioritized_origin_database.h', - 'browser/fileapi/sandbox_quota_observer.cc', - 'browser/fileapi/sandbox_quota_observer.h', - 'browser/fileapi/task_runner_bound_observer_list.h', - 'browser/fileapi/timed_task_helper.cc', - 'browser/fileapi/timed_task_helper.h', - 'browser/fileapi/transient_file_util.cc', - 'browser/fileapi/transient_file_util.h', - 'browser/quota/quota_callbacks.h', - 'browser/quota/quota_client.h', - 'browser/quota/quota_database.cc', - 'browser/quota/quota_database.h', - 'browser/quota/quota_manager.cc', - 'browser/quota/quota_manager.h', - 'browser/quota/quota_manager_proxy.cc', - 'browser/quota/quota_manager_proxy.h', - 'browser/quota/quota_task.cc', - 'browser/quota/quota_task.h', - 'browser/quota/quota_temporary_storage_evictor.cc', - 'browser/quota/quota_temporary_storage_evictor.h', - 'browser/quota/special_storage_policy.cc', - 'browser/quota/special_storage_policy.h', - 'browser/quota/storage_monitor.cc', - 'browser/quota/storage_monitor.h', - 'browser/quota/storage_observer.cc', - 'browser/quota/storage_observer.h', - 'browser/quota/usage_tracker.cc', - 'browser/quota/usage_tracker.h', - 'browser/storage_browser_export.h', - ], - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - 'msvs_disabled_warnings': [ 4267, ], - - 'conditions': [ - ['chrome_multiple_dll!=1', { - 'dependencies': [ - '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink', - ], - }], - ], - }, - { - # GN version: //webkit/browser:dump_file_system - 'target_name': 'dump_file_system', - 'type': 'executable', - 'sources': [ - 'browser/fileapi/dump_file_system.cc', - ], - 'dependencies': [ - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/storage/storage_common.gyp:storage_common', - 'storage', - ], - }, - ], -} |