summaryrefslogtreecommitdiffstats
path: root/webkit/fileapi/obfuscated_file_system_file_util.cc
diff options
context:
space:
mode:
authorericu@chromium.org <ericu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-19 22:37:16 +0000
committerericu@chromium.org <ericu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-19 22:37:16 +0000
commit0c5ebe34efad06c35892dbb3838e54e26ebfcc2e (patch)
tree6698e3a6cb024e0ed65b800129c6e53a79ae7e67 /webkit/fileapi/obfuscated_file_system_file_util.cc
parenta738ccd6ecebdbd7ee794e7e88a4d78804b84a7c (diff)
downloadchromium_src-0c5ebe34efad06c35892dbb3838e54e26ebfcc2e.zip
chromium_src-0c5ebe34efad06c35892dbb3838e54e26ebfcc2e.tar.gz
chromium_src-0c5ebe34efad06c35892dbb3838e54e26ebfcc2e.tar.bz2
Simplify directory path accounting.
BUG=none TEST=existing test_shell_tests plus a new OFSFU test. Review URL: http://codereview.chromium.org/7608011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97522 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi/obfuscated_file_system_file_util.cc')
-rw-r--r--webkit/fileapi/obfuscated_file_system_file_util.cc110
1 files changed, 97 insertions, 13 deletions
diff --git a/webkit/fileapi/obfuscated_file_system_file_util.cc b/webkit/fileapi/obfuscated_file_system_file_util.cc
index 52113d6..dc6b70e 100644
--- a/webkit/fileapi/obfuscated_file_system_file_util.cc
+++ b/webkit/fileapi/obfuscated_file_system_file_util.cc
@@ -19,8 +19,10 @@
#include "webkit/fileapi/file_system_context.h"
#include "webkit/fileapi/file_system_operation_context.h"
#include "webkit/fileapi/file_system_path_manager.h"
+#include "webkit/fileapi/file_system_quota_util.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/fileapi/sandbox_mount_point_provider.h"
+#include "webkit/quota/quota_manager.h"
namespace {
@@ -43,6 +45,52 @@ bool IsRootDirectory(const FilePath& virtual_path) {
virtual_path.value() == FILE_PATH_LITERAL("/"));
}
+// 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 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 GetPathQuotaUsage(
+ int growth_in_number_of_paths,
+ int64 growth_in_bytes_of_path_length) {
+ return growth_in_number_of_paths * kPathCreationQuotaCost +
+ growth_in_bytes_of_path_length * kPathByteQuotaCost;
+}
+
+bool AllocateQuotaForPath(
+ fileapi::FileSystemOperationContext* context,
+ int growth_in_number_of_paths,
+ int64 growth_in_bytes_of_path_length) {
+ int64 growth = GetPathQuotaUsage(growth_in_number_of_paths,
+ growth_in_bytes_of_path_length);
+ int64 new_quota = context->allowed_bytes_growth() - growth;
+
+ if (growth <= 0 || new_quota >= 0) {
+ context->set_allowed_bytes_growth(new_quota);
+ return true;
+ }
+ return false;
+}
+
+void UpdatePathQuotaUsage(
+ fileapi::FileSystemOperationContext* context,
+ const GURL& origin_url,
+ fileapi::FileSystemType type,
+ int growth_in_number_of_paths, // -1, 0, or 1
+ int64 growth_in_bytes_of_path_length) {
+ int64 growth = GetPathQuotaUsage(growth_in_number_of_paths,
+ growth_in_bytes_of_path_length);
+ fileapi::FileSystemQuotaUtil* quota_util =
+ context->file_system_context()->GetQuotaUtil(type);
+ quota::QuotaManagerProxy* quota_manager_proxy =
+ context->file_system_context()->quota_manager_proxy();
+ quota_util->UpdateOriginUsageOnFileThread(quota_manager_proxy, origin_url,
+ type, growth);
+}
+
const FilePath::CharType kLegacyDataDirectory[] = FILE_PATH_LITERAL("Legacy");
const FilePath::CharType kTemporaryDirectoryName[] = FILE_PATH_LITERAL("t");
@@ -88,6 +136,8 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateOrOpen(
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileInfo file_info;
InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value());
+ if (!AllocateQuotaForPath(context, 1, file_info.name.size()))
+ return base::PLATFORM_FILE_ERROR_NO_SPACE;
PlatformFileError error = CreateFile(
context, context->src_origin_url(), context->src_type(), FilePath(),
&file_info, file_flags, file_handle);
@@ -138,6 +188,8 @@ PlatformFileError ObfuscatedFileSystemFileUtil::EnsureFileExists(
FileInfo file_info;
InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value());
+ if (!AllocateQuotaForPath(context, 1, file_info.name.size()))
+ return base::PLATFORM_FILE_ERROR_NO_SPACE;
PlatformFileError error = CreateFile(context, context->src_origin_url(),
context->src_type(), FilePath(), &file_info, 0, NULL);
if (created && base::PLATFORM_FILE_OK == error)
@@ -265,12 +317,6 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateDirectory(
}
if (!recursive && components.size() - index > 1)
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
- // TODO(dmikurube): Eliminate do_not_write_actually in future.
- bool do_not_write_actually = context->do_not_write_actually();
- context->set_do_not_write_actually(true);
- underlying_file_util_->CreateDirectory(context,
- FilePath(), exclusive, recursive);
- context->set_do_not_write_actually(do_not_write_actually);
for (; index < components.size(); ++index) {
FileInfo file_info;
file_info.name = components[index];
@@ -278,10 +324,14 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateDirectory(
continue;
file_info.modification_time = base::Time::Now();
file_info.parent_id = parent_id;
+ if (!AllocateQuotaForPath(context, 1, file_info.name.size()))
+ return base::PLATFORM_FILE_ERROR_NO_SPACE;
if (!db->AddFileInfo(file_info, &parent_id)) {
NOTREACHED();
return base::PLATFORM_FILE_ERROR_FAILED;
}
+ UpdatePathQuotaUsage(context, context->src_origin_url(),
+ context->src_type(), 1, file_info.name.size());
}
return base::PLATFORM_FILE_OK;
}
@@ -291,6 +341,10 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CopyOrMoveFile(
const FilePath& src_file_path,
const FilePath& dest_file_path,
bool copy) {
+ // Cross-filesystem copies and moves should be handled via CopyInForeignFile.
+ DCHECK(context->src_origin_url() == context->dest_origin_url());
+ DCHECK(context->src_type() == context->dest_type());
+
FileSystemDirectoryDatabase* db = GetDirectoryDatabase(
context->src_origin_url(), context->src_type(), true);
if (!db)
@@ -344,12 +398,16 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CopyOrMoveFile(
}
InitFileInfo(&dest_file_info, dest_parent_id,
dest_file_path.BaseName().value());
+ if (!AllocateQuotaForPath(context, 1, dest_file_info.name.size()))
+ return base::PLATFORM_FILE_ERROR_NO_SPACE;
return CreateFile(context, context->dest_origin_url(),
context->dest_type(), src_data_path, &dest_file_info, 0,
NULL);
}
} else { // It's a move.
if (overwrite) {
+ AllocateQuotaForPath(context, -1,
+ -static_cast<int64>(src_file_info.name.size()));
if (!db->OverwritingMoveFile(src_file_id, dest_file_id))
return base::PLATFORM_FILE_ERROR_FAILED;
FilePath dest_data_path = DataPathToLocalPath(context->src_origin_url(),
@@ -357,6 +415,9 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CopyOrMoveFile(
if (base::PLATFORM_FILE_OK !=
underlying_file_util_->DeleteFile(context, dest_data_path))
LOG(WARNING) << "Leaked a backing file.";
+ UpdatePathQuotaUsage(context, context->src_origin_url(),
+ context->src_type(), -1,
+ -static_cast<int64>(src_file_info.name.size()));
return base::PLATFORM_FILE_OK;
} else {
FileId dest_parent_id;
@@ -364,10 +425,19 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CopyOrMoveFile(
NOTREACHED();
return base::PLATFORM_FILE_ERROR_FAILED;
}
+ if (!AllocateQuotaForPath(
+ context, 0,
+ static_cast<int64>(dest_file_path.BaseName().value().size())
+ - static_cast<int64>(src_file_info.name.size())))
+ return base::PLATFORM_FILE_ERROR_NO_SPACE;
src_file_info.parent_id = dest_parent_id;
src_file_info.name = dest_file_path.BaseName().value();
if (!db->UpdateFileInfo(src_file_id, src_file_info))
return base::PLATFORM_FILE_ERROR_FAILED;
+ UpdatePathQuotaUsage(
+ context, context->src_origin_url(), context->src_type(), 0,
+ static_cast<int64>(dest_file_path.BaseName().value().size()) -
+ static_cast<int64>(src_file_path.BaseName().value().size()));
return base::PLATFORM_FILE_OK;
}
}
@@ -404,6 +474,8 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CopyInForeignFile(
}
InitFileInfo(&dest_file_info, dest_parent_id,
dest_file_path.BaseName().value());
+ if (!AllocateQuotaForPath(context, 1, dest_file_info.name.size()))
+ return base::PLATFORM_FILE_ERROR_NO_SPACE;
return CreateFile(context, context->dest_origin_url(),
context->dest_type(), src_file_path, &dest_file_info, 0, NULL);
}
@@ -429,6 +501,9 @@ PlatformFileError ObfuscatedFileSystemFileUtil::DeleteFile(
NOTREACHED();
return base::PLATFORM_FILE_ERROR_FAILED;
}
+ AllocateQuotaForPath(context, -1, -static_cast<int64>(file_info.name.size()));
+ UpdatePathQuotaUsage(context, context->src_origin_url(), context->src_type(),
+ -1, -static_cast<int64>(file_info.name.size()));
FilePath data_path = DataPathToLocalPath(context->src_origin_url(),
context->src_type(), file_info.data_path);
if (base::PLATFORM_FILE_OK !=
@@ -454,6 +529,9 @@ PlatformFileError ObfuscatedFileSystemFileUtil::DeleteSingleDirectory(
}
if (!db->RemoveFileInfo(file_id))
return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
+ AllocateQuotaForPath(context, -1, -static_cast<int64>(file_info.name.size()));
+ UpdatePathQuotaUsage(context, context->src_origin_url(), context->src_type(),
+ -1, -static_cast<int64>(file_info.name.size()));
return base::PLATFORM_FILE_OK;
}
@@ -492,6 +570,8 @@ PlatformFileError ObfuscatedFileSystemFileUtil::Touch(
InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value());
// In the event of a sporadic underlying failure, we might create a new file,
// but fail to update its mtime + atime.
+ if (!AllocateQuotaForPath(context, 1, file_info.name.size()))
+ return base::PLATFORM_FILE_ERROR_NO_SPACE;
PlatformFileError error = CreateFile(context, context->src_origin_url(),
context->src_type(), FilePath(), &file_info, 0, NULL);
if (base::PLATFORM_FILE_OK != error)
@@ -768,17 +848,15 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile(
return base::PLATFORM_FILE_ERROR_FAILED;
path = path.AppendASCII(StringPrintf("%02" PRIu64, directory_number));
- if (file_util::DirectoryExists(path.DirName())) {
- if (!file_util::DirectoryExists(path) && !file_util::CreateDirectory(path))
- return base::PLATFORM_FILE_ERROR_FAILED;
- } else {
- return base::PLATFORM_FILE_ERROR_NOT_FOUND;
- }
+ PlatformFileError error;
+ error = underlying_file_util_->CreateDirectory(
+ context, path, false /* exclusive */, false /* recursive */);
+ if (base::PLATFORM_FILE_OK != error)
+ return error;
path = path.AppendASCII(StringPrintf("%08" PRIu64, number));
FilePath data_path = LocalPathToDataPath(origin_url, type, path);
if (data_path.empty())
return base::PLATFORM_FILE_ERROR_FAILED;
- PlatformFileError error;
bool created = false;
if (!source_path.empty()) {
DCHECK(!file_flags);
@@ -819,6 +897,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile(
underlying_file_util_->DeleteFile(context, path);
return base::PLATFORM_FILE_ERROR_FAILED;
}
+ UpdatePathQuotaUsage(context, origin_url, type, 1, file_info->name.size());
return base::PLATFORM_FILE_OK;
}
@@ -1058,6 +1137,11 @@ void ObfuscatedFileSystemFileUtil::DropDatabases() {
directories_.clear();
}
+// static
+int64 ObfuscatedFileSystemFileUtil::ComputeFilePathCost(const FilePath& path) {
+ return GetPathQuotaUsage(1, path.BaseName().value().size());
+}
+
bool ObfuscatedFileSystemFileUtil::DestroyDirectoryDatabase(
const GURL& origin, FileSystemType type) {
std::string type_string =