summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorericu@chromium.org <ericu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-20 21:02:35 +0000
committerericu@chromium.org <ericu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-20 21:02:35 +0000
commit6b931158eff95b7969107824049fcf786325f0a7 (patch)
tree3a49d28cc7f222b4221f93218d221302eb3e64d2
parent798dce5e549ff3a9f71f6903eb65f773782310d5 (diff)
downloadchromium_src-6b931158eff95b7969107824049fcf786325f0a7.zip
chromium_src-6b931158eff95b7969107824049fcf786325f0a7.tar.gz
chromium_src-6b931158eff95b7969107824049fcf786325f0a7.tar.bz2
Code to migrate a single directory from the old sandbox to the new.
Also cleans up the new directory path format just a bit, and makes the database store relative paths instead of absolute ones, so that if the user moves her profile path, things don't break. BUG=none TEST=unit test Review URL: http://codereview.chromium.org/7042029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86145 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--webkit/fileapi/file_system_directory_database.cc16
-rw-r--r--webkit/fileapi/file_system_directory_database.h2
-rw-r--r--webkit/fileapi/file_system_origin_database.cc4
-rw-r--r--webkit/fileapi/obfuscated_file_system_file_util.cc208
-rw-r--r--webkit/fileapi/obfuscated_file_system_file_util.h44
-rw-r--r--webkit/fileapi/obfuscated_file_system_file_util_unittest.cc98
6 files changed, 329 insertions, 43 deletions
diff --git a/webkit/fileapi/file_system_directory_database.cc b/webkit/fileapi/file_system_directory_database.cc
index c21ba49..2ff4758 100644
--- a/webkit/fileapi/file_system_directory_database.cc
+++ b/webkit/fileapi/file_system_directory_database.cc
@@ -389,6 +389,22 @@ bool FileSystemDirectoryDatabase::GetNextInteger(int64* next) {
return GetNextInteger(next);
}
+// static
+bool FileSystemDirectoryDatabase::DestroyDatabase(const FilePath& path) {
+ std::string name;
+#if defined(OS_POSIX)
+ name = path.value();
+#elif defined(OS_WIN)
+ name = base::SysWideToUTF8(path.value());
+#endif
+ leveldb::Status status = leveldb::DestroyDB(name, leveldb::Options());
+ if (status.ok())
+ return true;
+ LOG(WARNING) << "Failed to destroy a database with status " <<
+ status.ToString();
+ return false;
+}
+
bool FileSystemDirectoryDatabase::Init() {
if (db_.get())
return true;
diff --git a/webkit/fileapi/file_system_directory_database.h b/webkit/fileapi/file_system_directory_database.h
index 22f1212..0c36463 100644
--- a/webkit/fileapi/file_system_directory_database.h
+++ b/webkit/fileapi/file_system_directory_database.h
@@ -80,6 +80,8 @@ class FileSystemDirectoryDatabase {
// creation/destruction of FileSystemDirectoryDatabase objects.
bool GetNextInteger(int64* next);
+ static bool DestroyDatabase(const FilePath& path);
+
private:
bool Init();
bool StoreDefaultValues();
diff --git a/webkit/fileapi/file_system_origin_database.cc b/webkit/fileapi/file_system_origin_database.cc
index a559c1b..f028cdc 100644
--- a/webkit/fileapi/file_system_origin_database.cc
+++ b/webkit/fileapi/file_system_origin_database.cc
@@ -4,8 +4,10 @@
#include "webkit/fileapi/file_system_origin_database.h"
+#include "base/format_macros.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
+#include "base/stringprintf.h"
#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "third_party/leveldb/include/leveldb/iterator.h"
@@ -93,7 +95,7 @@ bool FileSystemOriginDatabase::GetPathForOrigin(
int last_path_number;
if (!GetLastPathNumber(&last_path_number))
return false;
- path_string = base::IntToString(last_path_number + 1);
+ path_string = StringPrintf("%03u", last_path_number + 1);
// store both back as a single transaction
leveldb::WriteBatch batch;
batch.Put(LastPathKey(), path_string);
diff --git a/webkit/fileapi/obfuscated_file_system_file_util.cc b/webkit/fileapi/obfuscated_file_system_file_util.cc
index d91f0b4..1e7c16e 100644
--- a/webkit/fileapi/obfuscated_file_system_file_util.cc
+++ b/webkit/fileapi/obfuscated_file_system_file_util.cc
@@ -7,9 +7,11 @@
#include <queue>
#include "base/file_util.h"
+#include "base/format_macros.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/string_number_conversions.h"
+#include "base/stringprintf.h"
#include "base/sys_string_conversions.h"
#include "base/stl_util-inl.h"
#include "googleurl/src/gurl.h"
@@ -32,14 +34,17 @@ const char kDirectoryDatabaseName[] = "Paths";
void InitFileInfo(
fileapi::FileSystemDirectoryDatabase::FileInfo* file_info,
fileapi::FileSystemDirectoryDatabase::FileId parent_id,
- const FilePath::StringType& file_name,
- const FilePath& data_path) {
+ const FilePath::StringType& file_name) {
DCHECK(file_info);
file_info->parent_id = parent_id;
- file_info->data_path = data_path;
file_info->name = file_name;
}
+const FilePath::CharType kLegacyDataDirectory[] = FILE_PATH_LITERAL("Legacy");
+
+const FilePath::CharType kTemporaryDirectoryName[] = FILE_PATH_LITERAL("t");
+const FilePath::CharType kPersistentDirectoryName[] = FILE_PATH_LITERAL("p");
+
} // namespace
namespace fileapi {
@@ -77,11 +82,10 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateOrOpen(
if (!db->GetFileWithPath(virtual_path.DirName(), &parent_id))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileInfo file_info;
- InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value(),
- FilePath());
+ InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value());
PlatformFileError error = CreateFile(
- context, context->src_origin_url(), context->src_type(), &file_info,
- file_flags, file_handle);
+ context, context->src_origin_url(), context->src_type(), FilePath(),
+ &file_info, file_flags, file_handle);
if (created && base::PLATFORM_FILE_OK == error)
*created = true;
return error;
@@ -96,8 +100,10 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateOrOpen(
}
if (file_info.is_directory())
return base::PLATFORM_FILE_ERROR_NOT_A_FILE;
+ FilePath data_path = DataPathToLocalPath(context->src_origin_url(),
+ context->src_type(), file_info.data_path);
return FileSystemFileUtil::GetInstance()->CreateOrOpen(
- context, file_info.data_path, file_flags, file_handle, created);
+ context, data_path, file_flags, file_handle, created);
}
PlatformFileError ObfuscatedFileSystemFileUtil::EnsureFileExists(
@@ -126,10 +132,9 @@ PlatformFileError ObfuscatedFileSystemFileUtil::EnsureFileExists(
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileInfo file_info;
- InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value(),
- FilePath());
- PlatformFileError error = CreateFile(context,
- context->src_origin_url(), context->src_type(), &file_info, 0, NULL);
+ InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value());
+ PlatformFileError error = CreateFile(context, context->src_origin_url(),
+ context->src_type(), FilePath(), &file_info, 0, NULL);
if (created && base::PLATFORM_FILE_OK == error)
*created = true;
return error;
@@ -176,8 +181,10 @@ PlatformFileError ObfuscatedFileSystemFileUtil::GetFileInfo(
}
if (local_info.data_path.empty())
return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ FilePath data_path = DataPathToLocalPath(context->src_origin_url(),
+ context->src_type(), local_info.data_path);
return FileSystemFileUtil::GetInstance()->GetFileInfo(
- context, local_info.data_path, file_info, platform_file_path);
+ context, data_path, file_info, platform_file_path);
}
PlatformFileError ObfuscatedFileSystemFileUtil::ReadDirectory(
@@ -318,9 +325,13 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CopyOrMoveFile(
* Just update metadata
*/
if (copy) {
+ FilePath src_data_path = DataPathToLocalPath(context->src_origin_url(),
+ context->src_type(), src_file_info.data_path);
if (overwrite) {
+ FilePath dest_data_path = DataPathToLocalPath(context->src_origin_url(),
+ context->src_type(), dest_file_info.data_path);
return FileSystemFileUtil::GetInstance()->CopyOrMoveFile(context,
- src_file_info.data_path, dest_file_info.data_path, copy);
+ src_data_path, dest_data_path, copy);
} else {
FileId dest_parent_id;
if (!db->GetFileWithPath(dest_file_path.DirName(), &dest_parent_id)) {
@@ -328,17 +339,20 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CopyOrMoveFile(
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
}
InitFileInfo(&dest_file_info, dest_parent_id,
- dest_file_path.BaseName().value(), src_file_info.data_path);
+ dest_file_path.BaseName().value());
return CreateFile(context, context->dest_origin_url(),
- context->dest_type(), &dest_file_info, 0, NULL);
+ context->dest_type(), src_data_path, &dest_file_info, 0,
+ NULL);
}
} else { // It's a move.
if (overwrite) {
if (!db->OverwritingMoveFile(src_file_id, dest_file_id))
return base::PLATFORM_FILE_ERROR_FAILED;
+ FilePath dest_data_path = DataPathToLocalPath(context->src_origin_url(),
+ context->src_type(), dest_file_info.data_path);
if (base::PLATFORM_FILE_OK !=
FileSystemFileUtil::GetInstance()->DeleteFile(
- context, dest_file_info.data_path))
+ context, dest_data_path))
LOG(WARNING) << "Leaked a backing file.";
return base::PLATFORM_FILE_OK;
} else {
@@ -377,9 +391,10 @@ PlatformFileError ObfuscatedFileSystemFileUtil::DeleteFile(
NOTREACHED();
return base::PLATFORM_FILE_ERROR_FAILED;
}
+ FilePath data_path = DataPathToLocalPath(context->src_origin_url(),
+ context->src_type(), file_info.data_path);
if (base::PLATFORM_FILE_OK !=
- FileSystemFileUtil::GetInstance()->DeleteFile(
- context, file_info.data_path))
+ FileSystemFileUtil::GetInstance()->DeleteFile(context, data_path))
LOG(WARNING) << "Leaked a backing file.";
return base::PLATFORM_FILE_OK;
}
@@ -426,24 +441,27 @@ PlatformFileError ObfuscatedFileSystemFileUtil::Touch(
return base::PLATFORM_FILE_ERROR_FAILED;
return base::PLATFORM_FILE_OK;
}
+ FilePath data_path = DataPathToLocalPath(context->src_origin_url(),
+ context->src_type(), file_info.data_path);
return FileSystemFileUtil::GetInstance()->Touch(
- context, file_info.data_path, last_access_time, last_modified_time);
+ context, data_path, last_access_time, last_modified_time);
}
FileId parent_id;
if (!db->GetFileWithPath(virtual_path.DirName(), &parent_id))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileInfo file_info;
- InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value(),
- FilePath());
+ 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.
- PlatformFileError error = CreateFile(context,
- context->src_origin_url(), context->src_type(), &file_info, 0, NULL);
+ PlatformFileError error = CreateFile(context, context->src_origin_url(),
+ context->src_type(), FilePath(), &file_info, 0, NULL);
if (base::PLATFORM_FILE_OK != error)
return error;
- return FileSystemFileUtil::GetInstance()->Touch(context, file_info.data_path,
+ FilePath data_path = DataPathToLocalPath(context->src_origin_url(),
+ context->src_type(), file_info.data_path);
+ return FileSystemFileUtil::GetInstance()->Touch(context, data_path,
last_access_time, last_modified_time);
}
@@ -598,7 +616,7 @@ ObfuscatedFileSystemFileUtil::CreateFileEnumerator(
PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile(
FileSystemOperationContext* context,
- const GURL& origin_url, FileSystemType type,
+ const GURL& origin_url, FileSystemType type, const FilePath& source_path,
FileInfo* file_info, int file_flags, PlatformFile* handle) {
if (handle)
*handle = base::kInvalidPlatformFileValue;
@@ -612,19 +630,23 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile(
GetDirectoryForOriginAndType(origin_url, type, false);
if (path.empty())
return base::PLATFORM_FILE_ERROR_FAILED;
- path = path.AppendASCII(base::Int64ToString(directory_number));
+
+ path = path.AppendASCII(StringPrintf("%02" PRIu64, directory_number));
PlatformFileError error;
error = FileSystemFileUtil::GetInstance()->CreateDirectory(
context, path, false /* exclusive */, false /* recursive */);
if (base::PLATFORM_FILE_OK != error)
return error;
- path = path.AppendASCII(base::Int64ToString(number));
+ 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;
bool created = false;
- if (!file_info->data_path.empty()) {
+ if (!source_path.empty()) {
DCHECK(!file_flags);
DCHECK(!handle);
error = FileSystemFileUtil::GetInstance()->CopyOrMoveFile(
- context, file_info->data_path, path, true /* copy */);
+ context, source_path, path, true /* copy */);
created = true;
} else {
if (handle) {
@@ -648,7 +670,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile(
}
return base::PLATFORM_FILE_ERROR_FAILED;
}
- file_info->data_path = path;
+ file_info->data_path = data_path;
FileId file_id;
if (!db->AddFileInfo(*file_info, &file_id)) {
if (handle)
@@ -675,7 +697,7 @@ FilePath ObfuscatedFileSystemFileUtil::GetLocalPath(
NOTREACHED();
return FilePath(); // Directories have no local path.
}
- return file_info.data_path;
+ return DataPathToLocalPath(origin_url, type, file_info.data_path);
}
FilePath ObfuscatedFileSystemFileUtil::GetDirectoryForOriginAndType(
@@ -683,13 +705,12 @@ FilePath ObfuscatedFileSystemFileUtil::GetDirectoryForOriginAndType(
FilePath origin_dir = GetDirectoryForOrigin(origin, create);
if (origin_dir.empty())
return FilePath();
- std::string type_string =
- FileSystemPathManager::GetFileSystemTypeString(type);
+ FilePath::StringType type_string = GetDirectoryNameForType(type);
if (type_string.empty()) {
LOG(WARNING) << "Unknown filesystem type requested:" << type;
return FilePath();
}
- return origin_dir.AppendASCII(type_string);
+ return origin_dir.Append(type_string);
}
FilePath ObfuscatedFileSystemFileUtil::GetDirectoryForOrigin(
@@ -717,6 +738,99 @@ FilePath ObfuscatedFileSystemFileUtil::GetDirectoryForOrigin(
return file_system_directory_.Append(directory_name);
}
+bool ObfuscatedFileSystemFileUtil::MigrateFromOldSandbox(
+ const GURL& origin_url, FileSystemType type, const FilePath& src_root) {
+ if (!DestroyDirectoryDatabase(origin_url, type))
+ return false;
+ FilePath dest_root = GetDirectoryForOriginAndType(origin_url, type, true);
+ if (dest_root.empty())
+ return false;
+ FileSystemDirectoryDatabase* db = GetDirectoryDatabase(origin_url, type);
+ if (!db)
+ return false;
+
+ file_util::FileEnumerator file_enum(src_root, true,
+ static_cast<file_util::FileEnumerator::FILE_TYPE>(
+ file_util::FileEnumerator::FILES |
+ file_util::FileEnumerator::DIRECTORIES));
+ FilePath src_full_path;
+ size_t root_path_length = src_root.value().length() + 1; // +1 for the slash
+ while (!(src_full_path = file_enum.Next()).empty()) {
+ file_util::FileEnumerator::FindInfo info;
+ file_enum.GetFindInfo(&info);
+ FilePath relative_virtual_path =
+ FilePath(src_full_path.value().substr(root_path_length));
+ if (relative_virtual_path.empty()) {
+ LOG(WARNING) << "Failed to convert path to relative: " <<
+ src_full_path.value();
+ return false;
+ }
+ FileId file_id;
+ if (db->GetFileWithPath(relative_virtual_path, &file_id)) {
+ NOTREACHED(); // File already exists.
+ return false;
+ }
+ if (!db->GetFileWithPath(relative_virtual_path.DirName(), &file_id)) {
+ NOTREACHED(); // Parent doesn't exist.
+ return false;
+ }
+
+ FileInfo file_info;
+ file_info.name = src_full_path.BaseName().value();
+ if (file_util::FileEnumerator::IsDirectory(info)) {
+#if defined(OS_WIN)
+ file_info.modification_time =
+ base::Time::FromFileTime(info.ftLastWriteTime);
+#elif defined(OS_POSIX)
+ file_info.modification_time = base::Time::FromTimeT(info.stat.st_mtime);
+#endif
+ } else {
+ file_info.data_path =
+ FilePath(kLegacyDataDirectory).Append(relative_virtual_path);
+ }
+ file_info.parent_id = file_id;
+ if (!db->AddFileInfo(file_info, &file_id)) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ // TODO(ericu): Should we adjust the mtime of the root directory to match as
+ // well?
+ FilePath legacy_dest_dir = dest_root.Append(kLegacyDataDirectory);
+ return file_util::Move(src_root, legacy_dest_dir);
+}
+
+FilePath::StringType ObfuscatedFileSystemFileUtil::GetDirectoryNameForType(
+ FileSystemType type) const {
+ switch (type) {
+ case kFileSystemTypeTemporary:
+ return kTemporaryDirectoryName;
+ case kFileSystemTypePersistent:
+ return kPersistentDirectoryName;
+ case kFileSystemTypeUnknown:
+ default:
+ return FilePath::StringType();
+ }
+}
+
+FilePath ObfuscatedFileSystemFileUtil::DataPathToLocalPath(
+ const GURL& origin, FileSystemType type, const FilePath& data_path) {
+ FilePath root = GetDirectoryForOriginAndType(origin, type, false);
+ if (root.empty())
+ return root;
+ return root.Append(data_path);
+}
+
+FilePath ObfuscatedFileSystemFileUtil::LocalPathToDataPath(
+ const GURL& origin, FileSystemType type, const FilePath& local_path) {
+ FilePath root = GetDirectoryForOriginAndType(origin, type, false);
+ if (root.empty())
+ return root;
+ // This removes the root, including the trailing slash, leaving a relative
+ // path.
+ return FilePath(local_path.value().substr(root.value().length() + 1));
+}
+
// TODO: 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.
@@ -767,4 +881,28 @@ void ObfuscatedFileSystemFileUtil::DropDatabases() {
directories_.clear();
}
+bool ObfuscatedFileSystemFileUtil::DestroyDirectoryDatabase(
+ const GURL& origin, FileSystemType type) {
+ std::string type_string =
+ FileSystemPathManager::GetFileSystemTypeString(type);
+ if (type_string.empty()) {
+ LOG(WARNING) << "Unknown filesystem type requested:" << type;
+ return true;
+ }
+ // TODO(ericu): This should probably be using GetOriginIdentifierFromURL from
+ // sandbox_mount_point_provider.cc, instead of just using origin.spec().
+ std::string key = origin.spec() + type_string;
+ DirectoryMap::iterator iter = directories_.find(key);
+ if (iter != directories_.end())
+ directories_.erase(iter);
+
+ FilePath path = GetDirectoryForOriginAndType(origin, type, false);
+ if (path.empty())
+ return true;
+ if (!file_util::DirectoryExists(path))
+ return true;
+ path = path.AppendASCII(kDirectoryDatabaseName);
+ return FileSystemDirectoryDatabase::DestroyDatabase(path);
+}
+
} // namespace fileapi
diff --git a/webkit/fileapi/obfuscated_file_system_file_util.h b/webkit/fileapi/obfuscated_file_system_file_util.h
index c6a4498..65e4e5f 100644
--- a/webkit/fileapi/obfuscated_file_system_file_util.h
+++ b/webkit/fileapi/obfuscated_file_system_file_util.h
@@ -41,6 +41,9 @@ class FileSystemOperationContext;
// SandboxMountPointProvider [and the task it uses to drop the reference] and
// SandboxMountPointProvider::GetFileSystemRootPathTask. Without that last one,
// we wouldn't need ref counting.
+//
+// TODO(ericu): We don't ever update directory mtimes; which operations should
+// do that?
class ObfuscatedFileSystemFileUtil : public FileSystemFileUtil,
public base::RefCountedThreadSafe<ObfuscatedFileSystemFileUtil> {
public:
@@ -131,6 +134,21 @@ class ObfuscatedFileSystemFileUtil : public FileSystemFileUtil,
// about migration; TODO(ericu): implement migration and fix these comments.
FilePath GetDirectoryForOrigin(const GURL& origin, bool create);
+ // This will migrate a filesystem from the old passthrough sandbox into the
+ // new obfuscated one. It won't obfuscate the old filenames [it will maintain
+ // the old structure, but move it to a new root], but any new files created
+ // will go into the new standard locations. This will be completely
+ // transparent to the user. This migration is atomic in that it won't alter
+ // the source data until it's done, and that will be with a single directory
+ // move [the directory with the unguessable name will move into the new
+ // filesystem storage directory]. However, if this fails partway through, it
+ // might leave a seemingly-valid database for this origin. When it starts up,
+ // it will clear any such database, just in case.
+ bool MigrateFromOldSandbox(
+ const GURL& origin, FileSystemType type, const FilePath& root);
+
+ FilePath::StringType GetDirectoryNameForType(FileSystemType type) const;
+
protected:
virtual AbstractFileEnumerator* CreateFileEnumerator(
FileSystemOperationContext* context,
@@ -142,29 +160,41 @@ class ObfuscatedFileSystemFileUtil : public FileSystemFileUtil,
// Creates a new file, both the underlying backing file and the entry in the
// database. file_info is an in-out parameter. Supply the name and
- // parent_id; supply data_path if you want it to be used as a source from
- // which to COPY data--otherwise leave it empty. On success, data_path will
- // always be set to the full path of a NEW backing file, and handle, if
- // supplied, will hold open PlatformFile for the backing file, which the
- // caller is responsible for closing.
+ // 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, and handle, if supplied, will
+ // hold open PlatformFile for the backing file, which the caller is
+ // responsible for closing. If you supply a path in source_path, it will be
+ // used as a source from which to COPY data.
// Caveat: do not supply handle if you're also supplying a data path. It was
// easier not to support this, and no code has needed it so far, so it will
// DCHECK and handle will hold base::kInvalidPlatformFileValue.
base::PlatformFileError CreateFile(
FileSystemOperationContext* context,
const GURL& origin_url, FileSystemType type,
- FileInfo* file_info,
+ const FilePath& source_path, FileInfo* file_info,
int file_flags, base::PlatformFile* handle);
// Given the filesystem's root URL and a virtual path, produces a real, full
- // local path to the underlying data file.
+ // local path to the underlying data file. This does a database lookup, and
+ // verifies that the file exists.
FilePath GetLocalPath(
const GURL& origin_url,
FileSystemType type,
const FilePath& virtual_path);
+ // This converts from a relative path [as is stored in the FileInfo.data_path
+ // field] to an absolute local path that can be given to the operating system.
+ // It does no checks as to whether the file actually exists; it's pure path
+ // manipulation.
+ FilePath DataPathToLocalPath(
+ const GURL& origin, FileSystemType type, const FilePath& data_path);
+ // This does the reverse of DataPathToLocalPath.
+ FilePath LocalPathToDataPath(
+ const GURL& origin, FileSystemType type, const FilePath& local_path);
FileSystemDirectoryDatabase* GetDirectoryDatabase(
const GURL& origin_url, FileSystemType type);
void MarkUsed();
void DropDatabases();
+ bool DestroyDirectoryDatabase(const GURL& origin, FileSystemType type);
typedef std::map<std::string, FileSystemDirectoryDatabase*> DirectoryMap;
DirectoryMap directories_;
diff --git a/webkit/fileapi/obfuscated_file_system_file_util_unittest.cc b/webkit/fileapi/obfuscated_file_system_file_util_unittest.cc
index 47db73b..549a542 100644
--- a/webkit/fileapi/obfuscated_file_system_file_util_unittest.cc
+++ b/webkit/fileapi/obfuscated_file_system_file_util_unittest.cc
@@ -66,6 +66,33 @@ const CopyMoveTestCaseRecord kCopyMoveTestCases[] = {
{false, "dir0/file0", "dir1/file1", true},
};
+struct MigrationTestCaseRecord {
+ bool is_directory;
+ const FilePath::CharType path[64];
+ int64 data_file_size;
+};
+
+const MigrationTestCaseRecord kMigrationTestCases[] = {
+ {true, FILE_PATH_LITERAL("dir a"), 0},
+ {true, FILE_PATH_LITERAL("dir a/dir a"), 0},
+ {true, FILE_PATH_LITERAL("dir a/dir d"), 0},
+ {true, FILE_PATH_LITERAL("dir a/dir d/dir e"), 0},
+ {true, FILE_PATH_LITERAL("dir a/dir d/dir e/dir f"), 0},
+ {true, FILE_PATH_LITERAL("dir a/dir d/dir e/dir g"), 0},
+ {true, FILE_PATH_LITERAL("dir a/dir d/dir e/dir h"), 0},
+ {true, FILE_PATH_LITERAL("dir b"), 0},
+ {true, FILE_PATH_LITERAL("dir b/dir a"), 0},
+ {true, FILE_PATH_LITERAL("dir c"), 0},
+ {false, FILE_PATH_LITERAL("file 0"), 38},
+ {false, FILE_PATH_LITERAL("file 2"), 60},
+ {false, FILE_PATH_LITERAL("file 3"), 0},
+ {false, FILE_PATH_LITERAL("dir a/file 0"), 39},
+ {false, FILE_PATH_LITERAL("dir a/dir d/dir e/dir g/file 0"), 40},
+ {false, FILE_PATH_LITERAL("dir a/dir d/dir e/dir g/file 1"), 41},
+ {false, FILE_PATH_LITERAL("dir a/dir d/dir e/dir g/file 2"), 42},
+ {false, FILE_PATH_LITERAL("dir a/dir d/dir e/dir g/file 3"), 50},
+};
+
} // namespace (anonymous)
// TODO(ericu): The vast majority of this and the other FSFU subclass tests
@@ -100,6 +127,10 @@ class ObfuscatedFileSystemFileUtilTest : public testing::Test {
return obfuscated_file_system_file_util_.get();
}
+ const FilePath& test_directory() const {
+ return data_dir_.path();
+ }
+
int64 GetSize(const FilePath& path) {
int64 size;
EXPECT_TRUE(file_util::GetFileSize(path, &size));
@@ -753,3 +784,70 @@ TEST_F(ObfuscatedFileSystemFileUtilTest, TestEnumerator) {
context.reset(NewContext());
EXPECT_FALSE(ofsfu()->DirectoryExists(context.get(), dest_path));
}
+
+TEST_F(ObfuscatedFileSystemFileUtilTest, TestMigration) {
+ ScopedTempDir source_dir;
+ ASSERT_TRUE(source_dir.CreateUniqueTempDir());
+ FilePath root_path = source_dir.path().AppendASCII("chrome-pLmnMWXE7NzTFRsn");
+ ASSERT_TRUE(file_util::CreateDirectory(root_path));
+
+ for (size_t i = 0; i < arraysize(kMigrationTestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "Creating kMigrationTestPath " << i);
+ const MigrationTestCaseRecord& test_case = kMigrationTestCases[i];
+ FilePath local_src_path = root_path.Append(test_case.path);
+ if (test_case.is_directory) {
+ ASSERT_TRUE(
+ file_util::CreateDirectory(local_src_path));
+ } else {
+ base::PlatformFileError error_code;
+ bool created = false;
+ int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE;
+ base::PlatformFile file_handle =
+ base::CreatePlatformFile(
+ local_src_path, file_flags, &created, &error_code);
+ EXPECT_TRUE(created);
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error_code);
+ ASSERT_TRUE(
+ base::TruncatePlatformFile(file_handle, test_case.data_file_size));
+ EXPECT_TRUE(base::ClosePlatformFile(file_handle));
+ }
+ }
+
+ const GURL origin_url("http://example.com");
+ fileapi::FileSystemType type = kFileSystemTypeTemporary;
+ EXPECT_TRUE(ofsfu()->MigrateFromOldSandbox(origin_url, type, root_path));
+
+ FilePath new_root =
+ test_directory().AppendASCII("000").Append(
+ ofsfu()->GetDirectoryNameForType(type)).AppendASCII("Legacy");
+ for (size_t i = 0; i < arraysize(kMigrationTestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "Validating kMigrationTestPath " << i);
+ const MigrationTestCaseRecord& test_case = kMigrationTestCases[i];
+ FilePath local_data_path = new_root.Append(test_case.path);
+#if defined(OS_WIN)
+ local_data_path = local_data_path.NormalizeWindowsPathSeparators();
+#endif
+ scoped_ptr<FileSystemOperationContext> context(NewContext());
+ base::PlatformFileInfo ofsfu_file_info;
+ FilePath data_path;
+ SCOPED_TRACE(testing::Message() << "Path is " << test_case.path);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofsfu()->GetFileInfo(context.get(), FilePath(test_case.path),
+ &ofsfu_file_info, &data_path));
+ if (test_case.is_directory) {
+ EXPECT_TRUE(ofsfu_file_info.is_directory);
+ } else {
+ base::PlatformFileInfo platform_file_info;
+ SCOPED_TRACE(testing::Message() << "local_data_path is " <<
+ local_data_path.value());
+ SCOPED_TRACE(testing::Message() << "data_path is " << data_path.value());
+ ASSERT_TRUE(file_util::GetFileInfo(local_data_path, &platform_file_info));
+ EXPECT_EQ(test_case.data_file_size, platform_file_info.size);
+ EXPECT_FALSE(platform_file_info.is_directory);
+ scoped_ptr<FileSystemOperationContext> context(NewContext());
+ EXPECT_EQ(local_data_path, data_path);
+ EXPECT_EQ(platform_file_info.size, ofsfu_file_info.size);
+ EXPECT_FALSE(ofsfu_file_info.is_directory);
+ }
+ }
+}