summaryrefslogtreecommitdiffstats
path: root/webkit/fileapi/obfuscated_file_util.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/fileapi/obfuscated_file_util.cc')
-rw-r--r--webkit/fileapi/obfuscated_file_util.cc690
1 files changed, 378 insertions, 312 deletions
diff --git a/webkit/fileapi/obfuscated_file_util.cc b/webkit/fileapi/obfuscated_file_util.cc
index 85ff199..544fd2b 100644
--- a/webkit/fileapi/obfuscated_file_util.cc
+++ b/webkit/fileapi/obfuscated_file_util.cc
@@ -26,10 +26,28 @@
#include "webkit/fileapi/sandbox_mount_point_provider.h"
#include "webkit/quota/quota_manager.h"
+// Example of various paths:
+// void ObfuscatedFileUtil::DoSomething(const FileSystemPath& path) {
+// FilePath virtual_path = path.internal_path();
+// FileSystemPath underlying_path = GetUnderlyingPath(path);
+// FilePath local_file_path = GetLocalFilePath(path);
+//
+// // |data_path| is native file path that is relative to the directory for
+// // the origin and type. We store |data_path| in DirectoryDatabase.
+// FilePath::StringType data_path =
+// UnderlyingPathToDataPath(underlying_path);
+//
+// underlying_file_util()->DoSomething(underlying_path);
+// file_util::DoAnother(local_file_path);
+// }
+
namespace fileapi {
namespace {
+typedef FileSystemDirectoryDatabase::FileId FileId;
+typedef FileSystemDirectoryDatabase::FileInfo FileInfo;
+
const int64 kFlushDelaySeconds = 10 * 60; // 10 minutes
void InitFileInfo(
@@ -41,9 +59,9 @@ void InitFileInfo(
file_info->name = file_name;
}
-bool IsRootDirectory(const FileSystemPath& virtual_path) {
- return (virtual_path.internal_path().empty() ||
- virtual_path.internal_path().value() == FILE_PATH_LITERAL("/"));
+bool IsRootDirectory(const FileSystemPath& path) {
+ return (path.internal_path().empty() ||
+ path.internal_path().value() == FILE_PATH_LITERAL("/"));
}
// Costs computed as per crbug.com/86114, based on the LevelDB implementation of
@@ -60,6 +78,9 @@ int64 UsageForPath(size_t length) {
}
bool AllocateQuota(FileSystemOperationContext* context, int64 growth) {
+ if (context->allowed_bytes_growth() == quota::QuotaManager::kNoLimit)
+ return true;
+
int64 new_quota = context->allowed_bytes_growth() - growth;
if (growth > 0 && new_quota < 0)
return false;
@@ -80,8 +101,7 @@ void UpdateUsage(
quota_manager_proxy, origin, type, growth);
}
-void TouchDirectory(FileSystemDirectoryDatabase* db,
- FileSystemDirectoryDatabase::FileId dir_id) {
+void TouchDirectory(FileSystemDirectoryDatabase* db, FileId dir_id) {
DCHECK(db);
if (!db->UpdateModificationTime(dir_id, base::Time::Now()))
NOTREACHED();
@@ -101,78 +121,65 @@ class ObfuscatedFileEnumerator
: public FileSystemFileUtil::AbstractFileEnumerator {
public:
ObfuscatedFileEnumerator(
- const FilePath& base_path,
FileSystemDirectoryDatabase* db,
FileSystemOperationContext* context,
- FileSystemFileUtil* underlying_file_util,
- const FileSystemPath& virtual_root_path,
+ ObfuscatedFileUtil* obfuscated_file_util,
+ const FileSystemPath& root_path,
bool recursive)
- : current_file_size_(0),
- base_path_(base_path),
- virtual_root_path_(virtual_root_path),
- db_(db),
+ : db_(db),
context_(context),
- underlying_file_util_(underlying_file_util),
+ obfuscated_file_util_(obfuscated_file_util),
+ origin_(root_path.origin()),
+ type_(root_path.type()),
recursive_(recursive) {
- DCHECK(db_);
- DCHECK(context_);
- DCHECK(underlying_file_util_);
-
+ FilePath root_virtual_path = root_path.internal_path();
FileId file_id;
- FileInfo file_info;
- if (!db_->GetFileWithPath(virtual_root_path.internal_path(), &file_id))
- return;
- if (!db_->GetFileInfo(file_id, &file_info))
- return;
- if (!file_info.is_directory())
+
+ if (!db_->GetFileWithPath(root_virtual_path, &file_id))
return;
- FileRecord record = { file_id, file_info,
- virtual_root_path.internal_path() };
+
+ FileRecord record = { file_id, root_virtual_path };
recurse_queue_.push(record);
}
- ~ObfuscatedFileEnumerator() {}
+ virtual ~ObfuscatedFileEnumerator() {}
virtual FilePath Next() OVERRIDE {
ProcessRecurseQueue();
- if (display_queue_.empty())
+ if (display_stack_.empty())
return FilePath();
- current_ = display_queue_.front();
- display_queue_.pop();
- if (current_.file_info.is_directory()) {
- current_file_size_ = 0;
- } else {
- base::PlatformFileInfo file_info;
- FilePath platform_file_path;
- FilePath local_path = base_path_.Append(current_.file_info.data_path);
-
- base::PlatformFileError error = underlying_file_util_->GetFileInfo(
- context_, virtual_root_path_.WithInternalPath(local_path),
- &file_info, &platform_file_path);
- if (error != base::PLATFORM_FILE_OK) {
- LOG(WARNING) << "Lost a backing file.";
- return Next();
- }
- current_.file_info.modification_time = file_info.last_modified;
- current_file_size_ = file_info.size;
- }
+ current_file_id_ = display_stack_.back();
+ display_stack_.pop_back();
- if (recursive_ && current_.file_info.is_directory())
- recurse_queue_.push(current_);
- return current_.file_path;
+ FileInfo file_info;
+ FilePath platform_file_path;
+ base::PlatformFileError error =
+ obfuscated_file_util_->GetFileInfoInternal(
+ db_, context_, origin_, type_, current_file_id_,
+ &file_info, &current_platform_file_info_, &platform_file_path);
+ if (error != base::PLATFORM_FILE_OK)
+ return Next();
+
+ 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_file_size_;
+ return current_platform_file_info_.size;
}
virtual base::Time LastModifiedTime() OVERRIDE {
- return current_.file_info.modification_time;
+ return current_platform_file_info_.last_modified;
}
virtual bool IsDirectory() OVERRIDE {
- return current_.file_info.is_directory();
+ return current_platform_file_info_.is_directory;
}
virtual bool IsLink() OVERRIDE {
@@ -185,39 +192,34 @@ class ObfuscatedFileEnumerator
struct FileRecord {
FileId file_id;
- FileInfo file_info;
- FilePath file_path;
+ FilePath virtual_path;
};
void ProcessRecurseQueue() {
- while (display_queue_.empty() && !recurse_queue_.empty()) {
- FileRecord directory = recurse_queue_.front();
- std::vector<FileId> children;
+ while (display_stack_.empty() && !recurse_queue_.empty()) {
+ FileRecord entry = recurse_queue_.front();
recurse_queue_.pop();
- if (!db_->ListChildren(directory.file_id, &children))
+ if (!db_->ListChildren(entry.file_id, &display_stack_)) {
+ display_stack_.clear();
return;
- std::vector<FileId>::iterator iter;
- for (iter = children.begin(); iter != children.end(); ++iter) {
- FileRecord child;
- child.file_id = *iter;
- if (!db_->GetFileInfo(child.file_id, &child.file_info))
- return;
- child.file_path = directory.file_path.Append(child.file_info.name);
- display_queue_.push(child);
}
+ current_parent_virtual_path_ = entry.virtual_path;
}
}
- std::queue<FileRecord> display_queue_;
- std::queue<FileRecord> recurse_queue_;
- FileRecord current_;
- int64 current_file_size_;
- FilePath base_path_;
- FileSystemPath virtual_root_path_;
FileSystemDirectoryDatabase* db_;
FileSystemOperationContext* context_;
- FileSystemFileUtil* underlying_file_util_;
+ ObfuscatedFileUtil* obfuscated_file_util_;
+ GURL origin_;
+ FileSystemType type_;
bool recursive_;
+
+ std::queue<FileRecord> recurse_queue_;
+ std::vector<FileId> display_stack_;
+ FilePath current_parent_virtual_path_;
+
+ FileId current_file_id_;
+ base::PlatformFileInfo current_platform_file_info_;
};
class ObfuscatedOriginEnumerator
@@ -226,8 +228,8 @@ class ObfuscatedOriginEnumerator
typedef FileSystemOriginDatabase::OriginRecord OriginRecord;
ObfuscatedOriginEnumerator(
FileSystemOriginDatabase* origin_database,
- const FilePath& base_path)
- : base_path_(base_path) {
+ const FilePath& base_file_path)
+ : base_file_path_(base_file_path) {
if (origin_database)
origin_database->ListAllOrigins(&origins_);
}
@@ -255,14 +257,14 @@ class ObfuscatedOriginEnumerator
NOTREACHED();
return false;
}
- FilePath path = base_path_.Append(current_.path).Append(type_string);
+ FilePath path = base_file_path_.Append(current_.path).Append(type_string);
return file_util::DirectoryExists(path);
}
private:
std::vector<OriginRecord> origins_;
OriginRecord current_;
- FilePath base_path_;
+ FilePath base_file_path_;
};
ObfuscatedFileUtil::ObfuscatedFileUtil(
@@ -274,39 +276,39 @@ ObfuscatedFileUtil::ObfuscatedFileUtil(
PlatformFileError ObfuscatedFileUtil::CreateOrOpen(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path, int file_flags,
+ const FileSystemPath& path, int file_flags,
PlatformFile* file_handle, bool* created) {
DCHECK(!(file_flags & (base::PLATFORM_FILE_DELETE_ON_CLOSE |
base::PLATFORM_FILE_HIDDEN | base::PLATFORM_FILE_EXCLUSIVE_READ |
base::PLATFORM_FILE_EXCLUSIVE_WRITE)));
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), true);
+ path.origin(), path.type(), true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
FileId file_id;
- if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id)) {
+ if (!db->GetFileWithPath(path.internal_path(), &file_id)) {
// The file doesn't exist.
if (!(file_flags & (base::PLATFORM_FILE_CREATE |
base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_OPEN_ALWAYS)))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileId parent_id;
- if (!db->GetFileWithPath(virtual_path.internal_path().DirName(),
+ if (!db->GetFileWithPath(path.internal_path().DirName(),
&parent_id))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileInfo file_info;
InitFileInfo(&file_info, parent_id,
- VirtualPath::BaseName(virtual_path.internal_path()).value());
+ VirtualPath::BaseName(path.internal_path()).value());
int64 growth = UsageForPath(file_info.name.size());
if (!AllocateQuota(context, growth))
return base::PLATFORM_FILE_ERROR_NO_SPACE;
PlatformFileError error = CreateFile(
- context, FileSystemPath(),
- virtual_path.origin(), virtual_path.type(), &file_info,
+ context, FilePath(),
+ path.origin(), path.type(), &file_info,
file_flags, file_handle);
if (created && base::PLATFORM_FILE_OK == error) {
*created = true;
- UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth);
+ UpdateUsage(context, path.origin(), path.type(), growth);
}
return error;
}
@@ -320,15 +322,14 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpen(
}
if (file_info.is_directory())
return base::PLATFORM_FILE_ERROR_NOT_A_FILE;
- FileSystemPath local_path = DataPathToLocalPath(
- virtual_path.origin(), virtual_path.type(), file_info.data_path);
+ FileSystemPath underlying_path = DataPathToUnderlyingPath(
+ path.origin(), path.type(), file_info.data_path);
base::PlatformFileError error = underlying_file_util()->CreateOrOpen(
- context, local_path, file_flags, file_handle, created);
+ context, underlying_path, file_flags, file_handle, created);
if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) {
// TODO(tzik): Also invalidate on-memory usage cache in UsageTracker.
// TODO(tzik): Delete database entry after ensuring the file lost.
- context->file_system_context()->GetQuotaUtil(virtual_path.type())->
- InvalidateUsageCache(virtual_path.origin(), virtual_path.type());
+ InvalidateUsageCache(context, path.origin(), path.type());
LOG(WARNING) << "Lost a backing file.";
error = base::PLATFORM_FILE_ERROR_FAILED;
}
@@ -337,14 +338,15 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpen(
PlatformFileError ObfuscatedFileUtil::EnsureFileExists(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path,
+ const FileSystemPath& path,
bool* created) {
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), true);
+ path.origin(), path.type(), true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
+
FileId file_id;
- if (db->GetFileWithPath(virtual_path.internal_path(), &file_id)) {
+ if (db->GetFileWithPath(path.internal_path(), &file_id)) {
FileInfo file_info;
if (!db->GetFileInfo(file_id, &file_info)) {
NOTREACHED();
@@ -357,38 +359,37 @@ PlatformFileError ObfuscatedFileUtil::EnsureFileExists(
return base::PLATFORM_FILE_OK;
}
FileId parent_id;
- if (!db->GetFileWithPath(virtual_path.internal_path().DirName(), &parent_id))
+ if (!db->GetFileWithPath(path.internal_path().DirName(), &parent_id))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileInfo file_info;
InitFileInfo(&file_info, parent_id,
- VirtualPath::BaseName(virtual_path.internal_path()).value());
+ VirtualPath::BaseName(path.internal_path()).value());
int64 growth = UsageForPath(file_info.name.size());
if (!AllocateQuota(context, growth))
return base::PLATFORM_FILE_ERROR_NO_SPACE;
- PlatformFileError error = CreateFile(context,
- FileSystemPath(),
- virtual_path.origin(), virtual_path.type(), &file_info,
- 0, NULL);
+ PlatformFileError error = CreateFile(
+ context, FilePath(), path.origin(), path.type(), &file_info, 0, NULL);
if (created && base::PLATFORM_FILE_OK == error) {
*created = true;
- UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth);
+ UpdateUsage(context, path.origin(), path.type(), growth);
}
return error;
}
PlatformFileError ObfuscatedFileUtil::CreateDirectory(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path,
+ const FileSystemPath& path,
bool exclusive,
bool recursive) {
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), true);
+ path.origin(), path.type(), true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
+
FileId file_id;
- if (db->GetFileWithPath(virtual_path.internal_path(), &file_id)) {
+ if (db->GetFileWithPath(path.internal_path(), &file_id)) {
FileInfo file_info;
if (exclusive)
return base::PLATFORM_FILE_ERROR_EXISTS;
@@ -402,7 +403,7 @@ PlatformFileError ObfuscatedFileUtil::CreateDirectory(
}
std::vector<FilePath::StringType> components;
- VirtualPath::GetComponents(virtual_path.internal_path(), &components);
+ VirtualPath::GetComponents(path.internal_path(), &components);
FileId parent_id = 0;
size_t index;
for (index = 0; index < components.size(); ++index) {
@@ -429,7 +430,7 @@ PlatformFileError ObfuscatedFileUtil::CreateDirectory(
NOTREACHED();
return base::PLATFORM_FILE_ERROR_FAILED;
}
- UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth);
+ UpdateUsage(context, path.origin(), path.type(), growth);
if (first) {
first = false;
TouchDirectory(db, file_info.parent_id);
@@ -440,19 +441,19 @@ PlatformFileError ObfuscatedFileUtil::CreateDirectory(
PlatformFileError ObfuscatedFileUtil::GetFileInfo(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path,
+ const FileSystemPath& path,
base::PlatformFileInfo* file_info,
FilePath* platform_file_path) {
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), false);
+ path.origin(), path.type(), false);
if (!db)
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileId file_id;
- if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id))
+ if (!db->GetFileWithPath(path.internal_path(), &file_id))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileInfo local_info;
return GetFileInfoInternal(db, context,
- virtual_path.origin(), virtual_path.type(),
+ path.origin(), path.type(),
file_id, &local_info,
file_info, platform_file_path);
}
@@ -467,37 +468,32 @@ ObfuscatedFileUtil::CreateFileEnumerator(
if (!db)
return new FileSystemFileUtil::EmptyFileEnumerator();
return new ObfuscatedFileEnumerator(
- GetDirectoryForOriginAndType(root_path.origin(),
- root_path.type(), false),
- db,
- context,
- underlying_file_util(),
- root_path, recursive);
+ db, context, this, root_path, recursive);
}
PlatformFileError ObfuscatedFileUtil::GetLocalFilePath(
FileSystemOperationContext* context,
- const FileSystemPath& file_system_path,
+ const FileSystemPath& path,
FilePath* local_file_path) {
- FileSystemPath local_path = GetLocalPath(file_system_path);
- if (local_path.internal_path().empty())
+ FileSystemPath underlying_path = GetUnderlyingPath(path);
+ if (underlying_path.internal_path().empty())
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
- *local_file_path = local_path.internal_path();
+ *local_file_path = underlying_path.internal_path();
return base::PLATFORM_FILE_OK;
}
PlatformFileError ObfuscatedFileUtil::Touch(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path,
+ const FileSystemPath& path,
const base::Time& last_access_time,
const base::Time& last_modified_time) {
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), false);
+ path.origin(), path.type(), false);
if (!db)
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileId file_id;
- if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id))
+ if (!db->GetFileWithPath(path.internal_path(), &file_id))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileInfo file_info;
@@ -510,21 +506,21 @@ PlatformFileError ObfuscatedFileUtil::Touch(
return base::PLATFORM_FILE_ERROR_FAILED;
return base::PLATFORM_FILE_OK;
}
- FileSystemPath local_path = DataPathToLocalPath(
- virtual_path.origin(), virtual_path.type(), file_info.data_path);
+ FileSystemPath underlying_path = DataPathToUnderlyingPath(
+ path.origin(), path.type(), file_info.data_path);
return underlying_file_util()->Touch(
- context, local_path,
+ context, underlying_path,
last_access_time, last_modified_time);
}
PlatformFileError ObfuscatedFileUtil::Truncate(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path,
+ const FileSystemPath& path,
int64 length) {
base::PlatformFileInfo file_info;
FilePath local_path;
base::PlatformFileError error =
- GetFileInfo(context, virtual_path, &file_info, &local_path);
+ GetFileInfo(context, path, &file_info, &local_path);
if (error != base::PLATFORM_FILE_OK)
return error;
@@ -532,27 +528,27 @@ PlatformFileError ObfuscatedFileUtil::Truncate(
if (!AllocateQuota(context, growth))
return base::PLATFORM_FILE_ERROR_NO_SPACE;
error = underlying_file_util()->Truncate(
- context, virtual_path.WithInternalPath(local_path), length);
+ context, path.WithInternalPath(local_path), length);
if (error == base::PLATFORM_FILE_OK)
- UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth);
+ UpdateUsage(context, path.origin(), path.type(), growth);
return error;
}
bool ObfuscatedFileUtil::PathExists(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path) {
+ const FileSystemPath& path) {
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), false);
+ path.origin(), path.type(), false);
if (!db)
return false;
FileId file_id;
- return db->GetFileWithPath(virtual_path.internal_path(), &file_id);
+ return db->GetFileWithPath(path.internal_path(), &file_id);
}
bool ObfuscatedFileUtil::DirectoryExists(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path) {
- if (IsRootDirectory(virtual_path)) {
+ const FileSystemPath& path) {
+ if (IsRootDirectory(path)) {
// It's questionable whether we should return true or false for the
// root directory of nonexistent origin, but here we return true
// as the current implementation of ReadDirectory always returns an empty
@@ -563,11 +559,11 @@ bool ObfuscatedFileUtil::DirectoryExists(
return true;
}
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), false);
+ path.origin(), path.type(), false);
if (!db)
return false;
FileId file_id;
- if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id))
+ if (!db->GetFileWithPath(path.internal_path(), &file_id))
return false;
FileInfo file_info;
if (!db->GetFileInfo(file_id, &file_info)) {
@@ -579,13 +575,13 @@ bool ObfuscatedFileUtil::DirectoryExists(
bool ObfuscatedFileUtil::IsDirectoryEmpty(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path) {
+ const FileSystemPath& path) {
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), false);
+ path.origin(), path.type(), false);
if (!db)
return true; // Not a great answer, but it's what others do.
FileId file_id;
- if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id))
+ if (!db->GetFileWithPath(path.internal_path(), &file_id))
return true; // Ditto.
FileInfo file_info;
if (!db->GetFileInfo(file_id, &file_info)) {
@@ -615,26 +611,69 @@ PlatformFileError ObfuscatedFileUtil::CopyOrMoveFile(
src_path.origin(), src_path.type(), true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
+
FileId src_file_id;
if (!db->GetFileWithPath(src_path.internal_path(), &src_file_id))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
+
FileId dest_file_id;
bool overwrite = db->GetFileWithPath(dest_path.internal_path(),
&dest_file_id);
+
FileInfo src_file_info;
- FileInfo dest_file_info;
- if (!db->GetFileInfo(src_file_id, &src_file_info) ||
- src_file_info.is_directory()) {
- NOTREACHED();
+ base::PlatformFileInfo src_platform_file_info;
+ FilePath src_local_file_path;
+ base::PlatformFileError error = GetFileInfoInternal(
+ db, context, src_path.origin(), src_path.type(), src_file_id,
+ &src_file_info, &src_platform_file_info, &src_local_file_path);
+ if (error != base::PLATFORM_FILE_OK)
+ return error;
+ if (src_file_info.is_directory())
return base::PLATFORM_FILE_ERROR_FAILED;
- }
+
+ FileInfo dest_file_info;
+ base::PlatformFileInfo dest_platform_file_info; // overwrite case only
+ FileSystemPath dest_underlying_path;
if (overwrite) {
- if (!db->GetFileInfo(dest_file_id, &dest_file_info) ||
- dest_file_info.is_directory()) {
- NOTREACHED();
+ FilePath dest_local_file_path;
+ base::PlatformFileError error = GetFileInfoInternal(
+ db, context, dest_path.origin(), dest_path.type(), dest_file_id,
+ &dest_file_info, &dest_platform_file_info, &dest_local_file_path);
+ if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
+ overwrite = false; // fallback to non-overwrite case
+ else if (error != base::PLATFORM_FILE_OK)
+ return error;
+ else if (dest_file_info.is_directory())
return base::PLATFORM_FILE_ERROR_FAILED;
+ else
+ dest_underlying_path = dest_path.WithInternalPath(dest_local_file_path);
+ }
+ if (!overwrite) {
+ FileId dest_parent_id;
+ if (!db->GetFileWithPath(dest_path.internal_path().DirName(),
+ &dest_parent_id)) {
+ NOTREACHED(); // We shouldn't be called in this case.
+ return base::PLATFORM_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_path.internal_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::PLATFORM_FILE_ERROR_NO_SPACE;
+
/*
* Copy-with-overwrite
* Just overwrite data file
@@ -649,176 +688,174 @@ PlatformFileError ObfuscatedFileUtil::CopyOrMoveFile(
* Move-without-overwrite
* Just update metadata
*/
+ error = base::PLATFORM_FILE_ERROR_FAILED;
if (copy) {
- FileSystemPath src_local_path = DataPathToLocalPath(
- src_path.origin(), src_path.type(), src_file_info.data_path);
- if (!underlying_file_util()->PathExists(context, src_local_path)) {
- // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker.
- context->file_system_context()->GetQuotaUtil(src_path.type())->
- InvalidateUsageCache(src_path.origin(), src_path.type());
- LOG(WARNING) << "Lost a backing file.";
- return base::PLATFORM_FILE_ERROR_FAILED;
- }
-
if (overwrite) {
- FileSystemPath dest_local_path = DataPathToLocalPath(
- dest_path.origin(), dest_path.type(), dest_file_info.data_path);
- PlatformFileError error = underlying_file_util()->CopyOrMoveFile(context,
- src_local_path, dest_local_path, copy);
- if (error == base::PLATFORM_FILE_OK)
- TouchDirectory(db, dest_file_info.parent_id);
- return error;
- } else {
- FileId dest_parent_id;
- if (!db->GetFileWithPath(dest_path.internal_path().DirName(),
- &dest_parent_id)) {
- NOTREACHED(); // We shouldn't be called in this case.
- return base::PLATFORM_FILE_ERROR_NOT_FOUND;
- }
- InitFileInfo(&dest_file_info, dest_parent_id,
- VirtualPath::BaseName(dest_path.internal_path()).value());
- int64 growth = UsageForPath(dest_file_info.name.size());
- if (!AllocateQuota(context, growth))
- return base::PLATFORM_FILE_ERROR_NO_SPACE;
- base::PlatformFileError error = CreateFile(
- context, src_local_path,
- dest_path.origin(), dest_path.type(), &dest_file_info,
- 0, NULL);
- if (error == base::PLATFORM_FILE_OK)
- UpdateUsage(context, dest_path.origin(), dest_path.type(), growth);
- return error;
+ error = underlying_file_util()->CopyOrMoveFile(
+ context,
+ src_path.WithInternalPath(src_local_file_path),
+ dest_underlying_path,
+ true /* copy */);
+ } else { // non-overwrite
+ error = CreateFile(context, src_local_file_path,
+ dest_path.origin(), dest_path.type(),
+ &dest_file_info, 0, NULL);
}
- } else { // It's a move.
+ } else {
if (overwrite) {
- int64 growth = -UsageForPath(src_file_info.name.size());
- AllocateQuota(context, growth);
- if (!db->OverwritingMoveFile(src_file_id, dest_file_id))
- return base::PLATFORM_FILE_ERROR_FAILED;
- FileSystemPath dest_local_path = DataPathToLocalPath(
- dest_path.origin(), dest_path.type(), dest_file_info.data_path);
- if (base::PLATFORM_FILE_OK !=
- underlying_file_util()->DeleteFile(context, dest_local_path))
- LOG(WARNING) << "Leaked a backing file.";
- UpdateUsage(context, src_path.origin(), src_path.type(), growth);
- TouchDirectory(db, src_file_info.parent_id);
- TouchDirectory(db, dest_file_info.parent_id);
- return base::PLATFORM_FILE_OK;
- } else {
- FileId dest_parent_id;
- if (!db->GetFileWithPath(dest_path.internal_path().DirName(),
- &dest_parent_id)) {
- NOTREACHED();
- return base::PLATFORM_FILE_ERROR_FAILED;
+ if (db->OverwritingMoveFile(src_file_id, dest_file_id)) {
+ if (base::PLATFORM_FILE_OK !=
+ underlying_file_util()->DeleteFile(context, dest_underlying_path))
+ LOG(WARNING) << "Leaked a backing file.";
+ error = base::PLATFORM_FILE_OK;
+ } else {
+ error = base::PLATFORM_FILE_ERROR_FAILED;
}
- FilePath dest_internal_path = dest_path.internal_path();
- FilePath src_internal_path = src_path.internal_path();
- int64 growth = UsageForPath(
- VirtualPath::BaseName(dest_internal_path).value().size());
- growth -= UsageForPath(src_file_info.name.size());
- if (!AllocateQuota(context, growth))
- return base::PLATFORM_FILE_ERROR_NO_SPACE;
- FileId src_parent_id = src_file_info.parent_id;
- src_file_info.parent_id = dest_parent_id;
- src_file_info.name =
- VirtualPath::BaseName(dest_path.internal_path()).value();
- if (!db->UpdateFileInfo(src_file_id, src_file_info))
- return base::PLATFORM_FILE_ERROR_FAILED;
- UpdateUsage(context, src_path.origin(), src_path.type(), growth);
- TouchDirectory(db, src_parent_id);
- TouchDirectory(db, dest_parent_id);
- return base::PLATFORM_FILE_OK;
+ } else { // non-overwrite
+ if (db->UpdateFileInfo(src_file_id, dest_file_info))
+ error = base::PLATFORM_FILE_OK;
+ else
+ error = base::PLATFORM_FILE_ERROR_FAILED;
}
}
- NOTREACHED();
- return base::PLATFORM_FILE_ERROR_FAILED;
+
+ if (error != base::PLATFORM_FILE_OK)
+ return error;
+
+ if (!copy)
+ TouchDirectory(db, src_file_info.parent_id);
+ TouchDirectory(db, dest_file_info.parent_id);
+
+ UpdateUsage(context, dest_path.origin(), dest_path.type(), growth);
+ return error;
}
PlatformFileError ObfuscatedFileUtil::CopyInForeignFile(
FileSystemOperationContext* context,
- const FileSystemPath& underlying_src_path,
+ const FilePath& src_file_path,
const FileSystemPath& dest_path) {
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
dest_path.origin(), dest_path.type(), true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
+
+ base::PlatformFileInfo src_platform_file_info;
+ if (!file_util::GetFileInfo(src_file_path, &src_platform_file_info))
+ return base::PLATFORM_FILE_ERROR_NOT_FOUND;
+
FileId dest_file_id;
bool overwrite = db->GetFileWithPath(dest_path.internal_path(),
&dest_file_id);
+
FileInfo dest_file_info;
+ base::PlatformFileInfo dest_platform_file_info; // overwrite case only
if (overwrite) {
- if (!db->GetFileInfo(dest_file_id, &dest_file_info) ||
- dest_file_info.is_directory()) {
- NOTREACHED();
+ FilePath dest_local_file_path;
+ base::PlatformFileError error = GetFileInfoInternal(
+ db, context, dest_path.origin(), dest_path.type(), dest_file_id,
+ &dest_file_info, &dest_platform_file_info, &dest_local_file_path);
+ if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
+ overwrite = false; // fallback to non-overwrite case
+ else if (error != base::PLATFORM_FILE_OK)
+ return error;
+ else if (dest_file_info.is_directory())
return base::PLATFORM_FILE_ERROR_FAILED;
- }
- FileSystemPath dest_local_path = DataPathToLocalPath(
- dest_path.origin(), dest_path.type(), dest_file_info.data_path);
- return underlying_file_util()->CopyOrMoveFile(context,
- underlying_src_path,
- dest_local_path, true /* copy */);
- } else {
+ }
+ if (!overwrite) {
FileId dest_parent_id;
if (!db->GetFileWithPath(dest_path.internal_path().DirName(),
- &dest_parent_id)) {
- NOTREACHED(); // We shouldn't be called in this case.
+ &dest_parent_id) ||
+ !dest_file_info.is_directory()) {
+ NOTREACHED();
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
}
InitFileInfo(&dest_file_info, dest_parent_id,
- VirtualPath::BaseName(dest_path.internal_path()).value());
- int64 growth = UsageForPath(dest_file_info.name.size());
- if (!AllocateQuota(context, growth))
- return base::PLATFORM_FILE_ERROR_NO_SPACE;
- base::PlatformFileError error =
- CreateFile(context, underlying_src_path,
- dest_path.origin(), dest_path.type(), &dest_file_info,
- 0, NULL);
- if (error == base::PLATFORM_FILE_OK)
- UpdateUsage(context, dest_path.origin(), dest_path.type(), growth);
- return error;
+ VirtualPath::BaseName(dest_path.internal_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::PLATFORM_FILE_ERROR_NO_SPACE;
+
+ base::PlatformFileError error;
+ if (overwrite) {
+ FileSystemPath dest_underlying_path = DataPathToUnderlyingPath(
+ dest_path.origin(), dest_path.type(), dest_file_info.data_path);
+ error = underlying_file_util()->CopyInForeignFile(
+ context, src_file_path, dest_underlying_path);
+ } else {
+ error = CreateFile(context, src_file_path,
+ dest_path.origin(), dest_path.type(),
+ &dest_file_info, 0, NULL);
}
- return base::PLATFORM_FILE_ERROR_FAILED;
+
+ if (error != base::PLATFORM_FILE_OK)
+ return error;
+
+ UpdateUsage(context, dest_path.origin(), dest_path.type(), growth);
+ TouchDirectory(db, dest_file_info.parent_id);
+ return base::PLATFORM_FILE_OK;
}
PlatformFileError ObfuscatedFileUtil::DeleteFile(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path) {
+ const FileSystemPath& path) {
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), true);
+ path.origin(), path.type(), true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
FileId file_id;
- if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id))
+ if (!db->GetFileWithPath(path.internal_path(), &file_id))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
+
FileInfo file_info;
- if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) {
+ base::PlatformFileInfo platform_file_info;
+ FilePath local_file_path;
+ base::PlatformFileError error = GetFileInfoInternal(
+ db, context, path.origin(), path.type(), file_id,
+ &file_info, &platform_file_info, &local_file_path);
+ if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND &&
+ error != base::PLATFORM_FILE_OK)
+ return error;
+
+ if (file_info.is_directory()) {
NOTREACHED();
return base::PLATFORM_FILE_ERROR_FAILED;
}
+
+ int64 growth = -UsageForPath(file_info.name.size()) - platform_file_info.size;
+ AllocateQuota(context, growth);
if (!db->RemoveFileInfo(file_id)) {
NOTREACHED();
return base::PLATFORM_FILE_ERROR_FAILED;
}
- int64 growth = -UsageForPath(file_info.name.size());
- AllocateQuota(context, growth);
- UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth);
- FileSystemPath local_path = DataPathToLocalPath(
- virtual_path.origin(), virtual_path.type(), file_info.data_path);
- if (base::PLATFORM_FILE_OK !=
- underlying_file_util()->DeleteFile(context, local_path))
- LOG(WARNING) << "Leaked a backing file.";
+ UpdateUsage(context, path.origin(), path.type(), growth);
TouchDirectory(db, file_info.parent_id);
+
+ if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
+ return base::PLATFORM_FILE_OK;
+
+ error = underlying_file_util()->DeleteFile(
+ context, path.WithInternalPath(local_file_path));
+ if (base::PLATFORM_FILE_OK != error)
+ LOG(WARNING) << "Leaked a backing file.";
return base::PLATFORM_FILE_OK;
}
PlatformFileError ObfuscatedFileUtil::DeleteSingleDirectory(
FileSystemOperationContext* context,
- const FileSystemPath& virtual_path) {
+ const FileSystemPath& path) {
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), true);
+ path.origin(), path.type(), true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
+
FileId file_id;
- if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id))
+ if (!db->GetFileWithPath(path.internal_path(), &file_id))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileInfo file_info;
if (!db->GetFileInfo(file_id, &file_info) || !file_info.is_directory()) {
@@ -829,7 +866,7 @@ PlatformFileError ObfuscatedFileUtil::DeleteSingleDirectory(
return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
int64 growth = -UsageForPath(file_info.name.size());
AllocateQuota(context, growth);
- UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth);
+ UpdateUsage(context, path.origin(), path.type(), growth);
TouchDirectory(db, file_info.parent_id);
return base::PLATFORM_FILE_OK;
}
@@ -1043,6 +1080,7 @@ PlatformFileError ObfuscatedFileUtil::GetFileInfoInternal(
}
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;
@@ -1052,15 +1090,22 @@ PlatformFileError ObfuscatedFileUtil::GetFileInfoInternal(
}
if (local_info->data_path.empty())
return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
- FileSystemPath local_path = DataPathToLocalPath(
+ FileSystemPath underlying_path = DataPathToUnderlyingPath(
origin, type, local_info->data_path);
- return underlying_file_util()->GetFileInfo(
- context, local_path, file_info, platform_file_path);
+ base::PlatformFileError error = underlying_file_util()->GetFileInfo(
+ context, underlying_path, file_info, platform_file_path);
+ if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) {
+ LOG(WARNING) << "Lost a backing file.";
+ InvalidateUsageCache(context, origin, type);
+ if (!db->RemoveFileInfo(file_id))
+ return base::PLATFORM_FILE_ERROR_FAILED;
+ }
+ return error;
}
PlatformFileError ObfuscatedFileUtil::CreateFile(
FileSystemOperationContext* context,
- const FileSystemPath& source_path,
+ const FilePath& src_file_path,
const GURL& dest_origin,
FileSystemType dest_type,
FileInfo* dest_file_info, int file_flags, PlatformFile* handle) {
@@ -1068,44 +1113,23 @@ PlatformFileError ObfuscatedFileUtil::CreateFile(
*handle = base::kInvalidPlatformFileValue;
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
dest_origin, dest_type, true);
- int64 number;
- if (!db || !db->GetNextInteger(&number))
- return base::PLATFORM_FILE_ERROR_FAILED;
- // We use the third- and fourth-to-last digits as the directory.
- int64 directory_number = number % 10000 / 100;
- // TODO(ericu): dest_file_path is an OS path;
- // underlying_file_util_ isn't guaranteed to understand OS paths.
- FilePath dest_file_path =
- GetDirectoryForOriginAndType(dest_origin, dest_type, false);
- if (dest_file_path.empty())
- return base::PLATFORM_FILE_ERROR_FAILED;
-
- dest_file_path = dest_file_path.AppendASCII(
- StringPrintf("%02" PRIu64, directory_number));
- FileSystemPath dest_path(dest_origin, dest_type, dest_file_path);
- PlatformFileError error;
- error = underlying_file_util()->CreateDirectory(
- context,
- dest_path,
- false /* exclusive */, false /* recursive */);
- if (base::PLATFORM_FILE_OK != error)
+ FileSystemPath dest_path;
+ PlatformFileError error = GenerateNewUnderlyingPath(
+ db, context, dest_origin, dest_type, &dest_path);
+ if (error != base::PLATFORM_FILE_OK)
return error;
- dest_file_path = dest_file_path.AppendASCII(
- StringPrintf("%08" PRIu64, number));
- dest_path.set_internal_path(dest_file_path);
-
- FilePath data_path = LocalPathToDataPath(dest_path);
+ FilePath data_path = UnderlyingPathToDataPath(dest_path);
if (data_path.empty())
return base::PLATFORM_FILE_ERROR_FAILED;
bool created = false;
- if (!source_path.internal_path().empty()) {
+ if (!src_file_path.empty()) {
DCHECK(!file_flags);
DCHECK(!handle);
- error = underlying_file_util()->CopyOrMoveFile(
- context, source_path, dest_path, true /* copy */);
+ error = underlying_file_util()->CopyInForeignFile(
+ context, src_file_path, dest_path);
created = true;
} else {
FilePath path;
@@ -1116,8 +1140,7 @@ PlatformFileError ObfuscatedFileUtil::CreateFile(
return base::PLATFORM_FILE_ERROR_FAILED;
}
LOG(WARNING) << "A stray file detected";
- context->file_system_context()->GetQuotaUtil(dest_type)->
- InvalidateUsageCache(dest_origin, dest_type);
+ InvalidateUsageCache(context, dest_origin, dest_type);
}
if (handle) {
@@ -1157,26 +1180,26 @@ PlatformFileError ObfuscatedFileUtil::CreateFile(
return base::PLATFORM_FILE_OK;
}
-FileSystemPath ObfuscatedFileUtil::GetLocalPath(
- const FileSystemPath& virtual_path) {
+FileSystemPath ObfuscatedFileUtil::GetUnderlyingPath(
+ const FileSystemPath& path) {
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
- virtual_path.origin(), virtual_path.type(), false);
+ path.origin(), path.type(), false);
if (!db)
return FileSystemPath();
FileId file_id;
- if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id))
+ if (!db->GetFileWithPath(path.internal_path(), &file_id))
return FileSystemPath();
FileInfo file_info;
if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) {
NOTREACHED();
- return FileSystemPath(); // Directories have no local path.
+ return FileSystemPath(); // Directories have no underlying path.
}
- return DataPathToLocalPath(virtual_path.origin(),
- virtual_path.type(),
- file_info.data_path);
+ return DataPathToUnderlyingPath(path.origin(),
+ path.type(),
+ file_info.data_path);
}
-FileSystemPath ObfuscatedFileUtil::DataPathToLocalPath(
+FileSystemPath ObfuscatedFileUtil::DataPathToUnderlyingPath(
const GURL& origin, FileSystemType type, const FilePath& data_path) {
FilePath root = GetDirectoryForOriginAndType(origin, type, false);
if (root.empty())
@@ -1184,16 +1207,16 @@ FileSystemPath ObfuscatedFileUtil::DataPathToLocalPath(
return FileSystemPath(origin, type, root.Append(data_path));
}
-FilePath ObfuscatedFileUtil::LocalPathToDataPath(
- const FileSystemPath& local_path) {
+FilePath ObfuscatedFileUtil::UnderlyingPathToDataPath(
+ const FileSystemPath& underlying_path) {
FilePath root = GetDirectoryForOriginAndType(
- local_path.origin(), local_path.type(), false);
+ underlying_path.origin(), underlying_path.type(), false);
if (root.empty())
return root;
// This removes the root, including the trailing slash, leaving a relative
// path.
- FilePath internal_path = local_path.internal_path();
- return FilePath(internal_path.value().substr(root.value().length() + 1));
+ FilePath local_file_path = underlying_path.internal_path();
+ return FilePath(local_file_path.value().substr(root.value().length() + 1));
}
// TODO: How to do the whole validation-without-creation thing? We may not have
@@ -1280,6 +1303,14 @@ FilePath ObfuscatedFileUtil::GetDirectoryForOrigin(
return path;
}
+void ObfuscatedFileUtil::InvalidateUsageCache(
+ FileSystemOperationContext* context,
+ const GURL& origin,
+ FileSystemType type) {
+ context->file_system_context()->GetQuotaUtil(type)->
+ InvalidateUsageCache(origin, type);
+}
+
void ObfuscatedFileUtil::MarkUsed() {
if (timer_.IsRunning())
timer_.Reset();
@@ -1310,4 +1341,39 @@ bool ObfuscatedFileUtil::InitOriginDatabase(bool create) {
return true;
}
+PlatformFileError ObfuscatedFileUtil::GenerateNewUnderlyingPath(
+ FileSystemDirectoryDatabase* db,
+ FileSystemOperationContext* context,
+ const GURL& origin,
+ FileSystemType type,
+ FileSystemPath* underlying_path) {
+ DCHECK(underlying_path);
+ int64 number;
+ if (!db || !db->GetNextInteger(&number))
+ return base::PLATFORM_FILE_ERROR_FAILED;
+
+ // We use the third- and fourth-to-last digits as the directory.
+ int64 directory_number = number % 10000 / 100;
+ // TODO(ericu): local_file_path is an OS path;
+ // underlying_file_util_ isn't guaranteed to understand OS paths.
+ FilePath local_file_path = GetDirectoryForOriginAndType(origin, type, false);
+ if (local_file_path.empty())
+ return base::PLATFORM_FILE_ERROR_FAILED;
+
+ local_file_path = local_file_path.AppendASCII(
+ StringPrintf("%02" PRId64, directory_number));
+
+ PlatformFileError error = underlying_file_util()->CreateDirectory(
+ context, FileSystemPath(origin, type, local_file_path),
+ false /* exclusive */, false /* recursive */);
+ if (error != base::PLATFORM_FILE_OK)
+ return error;
+
+ local_file_path = local_file_path.AppendASCII(
+ StringPrintf("%08" PRId64, number));
+
+ *underlying_path = FileSystemPath(origin, type, local_file_path);
+ return base::PLATFORM_FILE_OK;
+}
+
} // namespace fileapi