diff options
author | ericu@chromium.org <ericu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-23 22:06:26 +0000 |
---|---|---|
committer | ericu@chromium.org <ericu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-23 22:06:26 +0000 |
commit | fcc2d5f0e4ff841a6af7cc7f5834985f833cf935 (patch) | |
tree | 98495fb543a672112124cb348a93a689dc8aa8f0 /webkit/fileapi | |
parent | e8b02e718bef710ecf69c52e19d4129c7e29d9ef (diff) | |
download | chromium_src-fcc2d5f0e4ff841a6af7cc7f5834985f833cf935.zip chromium_src-fcc2d5f0e4ff841a6af7cc7f5834985f833cf935.tar.gz chromium_src-fcc2d5f0e4ff841a6af7cc7f5834985f833cf935.tar.bz2 |
Integrated obfuscation with quota; all unit tests now pass with or without the flag that turns on obfuscation.
BUG=none
TEST=unit tests
Review URL: http://codereview.chromium.org/7057032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86351 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
-rw-r--r-- | webkit/fileapi/file_system_context.cc | 2 | ||||
-rw-r--r-- | webkit/fileapi/file_system_origin_database.cc | 11 | ||||
-rw-r--r-- | webkit/fileapi/file_system_origin_database.h | 9 | ||||
-rw-r--r-- | webkit/fileapi/file_system_origin_database_unittest.cc | 20 | ||||
-rw-r--r-- | webkit/fileapi/file_system_path_manager_unittest.cc | 19 | ||||
-rw-r--r-- | webkit/fileapi/file_system_quota_client_unittest.cc | 2 | ||||
-rw-r--r-- | webkit/fileapi/file_system_util.cc | 26 | ||||
-rw-r--r-- | webkit/fileapi/file_system_util.h | 3 | ||||
-rw-r--r-- | webkit/fileapi/obfuscated_file_system_file_util.cc | 151 | ||||
-rw-r--r-- | webkit/fileapi/obfuscated_file_system_file_util.h | 31 | ||||
-rw-r--r-- | webkit/fileapi/obfuscated_file_system_file_util_unittest.cc | 119 | ||||
-rw-r--r-- | webkit/fileapi/sandbox_mount_point_provider.cc | 131 | ||||
-rw-r--r-- | webkit/fileapi/sandbox_mount_point_provider.h | 14 | ||||
-rw-r--r-- | webkit/fileapi/sandbox_mount_point_provider_unittest.cc | 2 |
14 files changed, 391 insertions, 149 deletions
diff --git a/webkit/fileapi/file_system_context.cc b/webkit/fileapi/file_system_context.cc index ff4520a..16bf067 100644 --- a/webkit/fileapi/file_system_context.cc +++ b/webkit/fileapi/file_system_context.cc @@ -80,7 +80,7 @@ bool FileSystemContext::DeleteDataForOriginOnFileThread( // Delete the upper level directory. FilePath path_for_origin = - sandbox_provider()->GetBaseDirectoryForOrigin(origin_url); + sandbox_provider()->GetBaseDirectoryForOrigin(origin_url, false); if (!file_util::PathExists(path_for_origin)) return true; return file_util::Delete(path_for_origin, true /* recursive */); diff --git a/webkit/fileapi/file_system_origin_database.cc b/webkit/fileapi/file_system_origin_database.cc index f028cdc..ca267e8 100644 --- a/webkit/fileapi/file_system_origin_database.cc +++ b/webkit/fileapi/file_system_origin_database.cc @@ -31,6 +31,17 @@ const char* LastPathKey() { namespace fileapi { +FileSystemOriginDatabase::OriginRecord::OriginRecord() { +} + +FileSystemOriginDatabase::OriginRecord::OriginRecord( + const std::string& origin_in, const FilePath& path_in) + : origin(origin_in), path(path_in) { +} + +FileSystemOriginDatabase::OriginRecord::~OriginRecord() { +} + FileSystemOriginDatabase::FileSystemOriginDatabase(const FilePath& path) { #if defined(OS_POSIX) path_ = path.value(); diff --git a/webkit/fileapi/file_system_origin_database.h b/webkit/fileapi/file_system_origin_database.h index 1a28082..885d165 100644 --- a/webkit/fileapi/file_system_origin_database.h +++ b/webkit/fileapi/file_system_origin_database.h @@ -19,7 +19,14 @@ namespace fileapi { // the browser's FILE thread. The constructor may be used on any thread. class FileSystemOriginDatabase { public: - typedef std::pair<std::string, FilePath> OriginRecord; + struct OriginRecord { + std::string origin; + FilePath path; + + OriginRecord(); + OriginRecord(const std::string& origin, const FilePath& path); + ~OriginRecord(); + }; // Only one instance of FileSystemOriginDatabase should exist for a given path // at a given time. diff --git a/webkit/fileapi/file_system_origin_database_unittest.cc b/webkit/fileapi/file_system_origin_database_unittest.cc index b88be8e7..c34e636 100644 --- a/webkit/fileapi/file_system_origin_database_unittest.cc +++ b/webkit/fileapi/file_system_origin_database_unittest.cc @@ -145,21 +145,21 @@ TEST(FileSystemOriginDatabaseTest, ListOriginsTest) { EXPECT_TRUE(database.GetPathForOrigin(origin0, &path0)); EXPECT_TRUE(database.ListAllOrigins(&origins)); EXPECT_EQ(origins.size(), 1UL); - EXPECT_EQ(origins[0].first, origin0); - EXPECT_EQ(origins[0].second, path0); + EXPECT_EQ(origins[0].origin, origin0); + EXPECT_EQ(origins[0].path, path0); origins.clear(); EXPECT_TRUE(database.GetPathForOrigin(origin1, &path1)); EXPECT_TRUE(database.ListAllOrigins(&origins)); EXPECT_EQ(origins.size(), 2UL); - if (origins[0].first == origin0) { - EXPECT_EQ(origins[0].second, path0); - EXPECT_EQ(origins[1].first, origin1); - EXPECT_EQ(origins[1].second, path1); + if (origins[0].origin == origin0) { + EXPECT_EQ(origins[0].path, path0); + EXPECT_EQ(origins[1].origin, origin1); + EXPECT_EQ(origins[1].path, path1); } else { - EXPECT_EQ(origins[0].first, origin1); - EXPECT_EQ(origins[0].second, path1); - EXPECT_EQ(origins[1].first, origin0); - EXPECT_EQ(origins[1].second, path0); + EXPECT_EQ(origins[0].origin, origin1); + EXPECT_EQ(origins[0].path, path1); + EXPECT_EQ(origins[1].origin, origin0); + EXPECT_EQ(origins[1].path, path0); } } diff --git a/webkit/fileapi/file_system_path_manager_unittest.cc b/webkit/fileapi/file_system_path_manager_unittest.cc index 977b657..f1f9122 100644 --- a/webkit/fileapi/file_system_path_manager_unittest.cc +++ b/webkit/fileapi/file_system_path_manager_unittest.cc @@ -8,6 +8,7 @@ #include <string> #include "base/basictypes.h" +#include "base/command_line.h" // TODO(ericu): Remove this. #include "base/file_util.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_callback_factory.h" @@ -26,6 +27,9 @@ namespace fileapi { namespace { +// TODO(ericu): Remove this. +static const char kObfuscationFlag[] = "use-obfuscated-file-system"; + // PS stands for path separator. #if defined(FILE_PATH_USES_WIN_SEPARATORS) #define PS "\\" @@ -292,9 +296,13 @@ TEST_F(FileSystemPathManagerTest, GetRootPathCreateAndExamine) { true /* create */, &root_path)); if (kRootPathTestCases[i].type != fileapi::kFileSystemTypeExternal) { - FilePath expected = file_system_path().AppendASCII( - kRootPathTestCases[i].expected_path); - EXPECT_EQ(expected.value(), root_path.DirName().value()); + // TODO(ericu): Put this test back, with new expectations, when we've + // switched over to the obfuscated filesystem. + if (!CommandLine::ForCurrentProcess()->HasSwitch(kObfuscationFlag)) { + FilePath expected = file_system_path().AppendASCII( + kRootPathTestCases[i].expected_path); + EXPECT_EQ(expected.value(), root_path.DirName().value()); + } EXPECT_TRUE(file_util::DirectoryExists(root_path)); } else { // External file system root path is virtual one and does not match @@ -395,7 +403,10 @@ TEST_F(FileSystemPathManagerTest, GetRootPathFileURIWithAllowFlag) { if (kRootPathFileURITestCases[i].type != fileapi::kFileSystemTypeExternal) { FilePath expected = file_system_path().AppendASCII( kRootPathFileURITestCases[i].expected_path); - EXPECT_EQ(expected.value(), root_path.DirName().value()); + // TODO(ericu): Put this test back, with new expectations, when we've + // switched over to the obfuscated filesystem. + if (!CommandLine::ForCurrentProcess()->HasSwitch(kObfuscationFlag)) + EXPECT_EQ(expected.value(), root_path.DirName().value()); EXPECT_TRUE(file_util::DirectoryExists(root_path)); } else { EXPECT_EQ(external_file_path_root().value(), root_path.value()); diff --git a/webkit/fileapi/file_system_quota_client_unittest.cc b/webkit/fileapi/file_system_quota_client_unittest.cc index 80a745f..a98cdc6 100644 --- a/webkit/fileapi/file_system_quota_client_unittest.cc +++ b/webkit/fileapi/file_system_quota_client_unittest.cc @@ -126,7 +126,7 @@ class FileSystemQuotaClientTest : public testing::Test { // temporary and persistent filesystem. return file_system_context_->path_manager()->sandbox_provider()-> GetBaseDirectoryForOriginAndType( - GURL(origin_url), QuotaStorageTypeToFileSystemType(type)); + GURL(origin_url), QuotaStorageTypeToFileSystemType(type), true); } bool CreateFileSystemDirectory(const char* dir_name, diff --git a/webkit/fileapi/file_system_util.cc b/webkit/fileapi/file_system_util.cc index 5aa3cf2..8435a76 100644 --- a/webkit/fileapi/file_system_util.cc +++ b/webkit/fileapi/file_system_util.cc @@ -9,8 +9,12 @@ #include "base/file_path.h" #include "base/logging.h" #include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" #include "googleurl/src/gurl.h" #include "net/base/escape.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" #include "webkit/fileapi/file_system_types.h" namespace fileapi { @@ -151,4 +155,26 @@ quota::StorageType FileSystemTypeToQuotaStorageType(FileSystemType type) { } } +// TODO(kinuko): Merge these two methods (conversion methods between +// origin url <==> identifier) with the ones in the database module. +std::string GetOriginIdentifierFromURL(const GURL& url) { + WebKit::WebSecurityOrigin web_security_origin = + WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec())); + return web_security_origin.databaseIdentifier().utf8(); +} + +GURL GetOriginURLFromIdentifier(const std::string& origin_identifier) { + WebKit::WebSecurityOrigin web_security_origin = + WebKit::WebSecurityOrigin::createFromDatabaseIdentifier( + UTF8ToUTF16(origin_identifier)); + GURL origin_url(web_security_origin.toString()); + + // We need this work-around for file:/// URIs as + // createFromDatabaseIdentifier returns empty origin_url for them. + if (origin_url.spec().empty() && + origin_identifier.find("file__") == 0) + return GURL("file:///"); + return origin_url; +} + } // namespace fileapi diff --git a/webkit/fileapi/file_system_util.h b/webkit/fileapi/file_system_util.h index 6f3bdca..226b85b 100644 --- a/webkit/fileapi/file_system_util.h +++ b/webkit/fileapi/file_system_util.h @@ -33,6 +33,9 @@ FileSystemType QuotaStorageTypeToFileSystemType( quota::StorageType FileSystemTypeToQuotaStorageType(FileSystemType type); +std::string GetOriginIdentifierFromURL(const GURL& url); +GURL GetOriginURLFromIdentifier(const std::string& origin_identifier); + } // namespace fileapi #endif // WEBKIT_FILEAPI_FILE_SYSTEM_UTIL_H_ diff --git a/webkit/fileapi/obfuscated_file_system_file_util.cc b/webkit/fileapi/obfuscated_file_system_file_util.cc index 1e7c16e..b0092d9 100644 --- a/webkit/fileapi/obfuscated_file_system_file_util.cc +++ b/webkit/fileapi/obfuscated_file_system_file_util.cc @@ -5,6 +5,7 @@ #include "webkit/fileapi/obfuscated_file_system_file_util.h" #include <queue> +#include <vector> #include "base/file_util.h" #include "base/format_macros.h" @@ -18,12 +19,12 @@ #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_util.h" #include "webkit/fileapi/quota_file_util.h" #include "webkit/fileapi/sandbox_mount_point_provider.h" -// TODO(ericu): Every instance of FileSystemFileUtil in this file should switch -// to QuotaFileUtil as soon as I sort out FileSystemPathManager's and -// SandboxMountPointProvider's lookups of the root path for a filesystem. +// TODO(ericu): Make deleting an origin [or a type under the origin, if it's the +// last type] remove the origin from origin_database_ as well. namespace { const int64 kFlushDelaySeconds = 10 * 60; // 10 minutes @@ -102,7 +103,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateOrOpen( 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( + return QuotaFileUtil::GetInstance()->CreateOrOpen( context, data_path, file_flags, file_handle, created); } @@ -183,7 +184,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::GetFileInfo( 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( + return QuotaFileUtil::GetInstance()->GetFileInfo( context, data_path, file_info, platform_file_path); } @@ -330,7 +331,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CopyOrMoveFile( if (overwrite) { FilePath dest_data_path = DataPathToLocalPath(context->src_origin_url(), context->src_type(), dest_file_info.data_path); - return FileSystemFileUtil::GetInstance()->CopyOrMoveFile(context, + return QuotaFileUtil::GetInstance()->CopyOrMoveFile(context, src_data_path, dest_data_path, copy); } else { FileId dest_parent_id; @@ -351,8 +352,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CopyOrMoveFile( 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_data_path)) + QuotaFileUtil::GetInstance()->DeleteFile(context, dest_data_path)) LOG(WARNING) << "Leaked a backing file."; return base::PLATFORM_FILE_OK; } else { @@ -394,7 +394,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::DeleteFile( FilePath data_path = DataPathToLocalPath(context->src_origin_url(), context->src_type(), file_info.data_path); if (base::PLATFORM_FILE_OK != - FileSystemFileUtil::GetInstance()->DeleteFile(context, data_path)) + QuotaFileUtil::GetInstance()->DeleteFile(context, data_path)) LOG(WARNING) << "Leaked a backing file."; return base::PLATFORM_FILE_OK; } @@ -443,7 +443,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::Touch( } FilePath data_path = DataPathToLocalPath(context->src_origin_url(), context->src_type(), file_info.data_path); - return FileSystemFileUtil::GetInstance()->Touch( + return QuotaFileUtil::GetInstance()->Touch( context, data_path, last_access_time, last_modified_time); } FileId parent_id; @@ -461,7 +461,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::Touch( FilePath data_path = DataPathToLocalPath(context->src_origin_url(), context->src_type(), file_info.data_path); - return FileSystemFileUtil::GetInstance()->Touch(context, data_path, + return QuotaFileUtil::GetInstance()->Touch(context, data_path, last_access_time, last_modified_time); } @@ -474,7 +474,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::Truncate( virtual_path); if (local_path.empty()) return base::PLATFORM_FILE_ERROR_NOT_FOUND; - return FileSystemFileUtil::GetInstance()->Truncate( + return QuotaFileUtil::GetInstance()->Truncate( context, local_path, length); } @@ -603,6 +603,60 @@ class ObfuscatedFileSystemFileEnumerator FileSystemDirectoryDatabase* db_; }; +class ObfuscatedFileSystemOriginEnumerator + : public ObfuscatedFileSystemFileUtil::AbstractOriginEnumerator { + public: + typedef FileSystemOriginDatabase::OriginRecord OriginRecord; + ObfuscatedFileSystemOriginEnumerator( + FileSystemOriginDatabase* origin_database, + const FilePath& base_path) + : base_path_(base_path) { + if (origin_database) + origin_database->ListAllOrigins(&origins_); + } + + ~ObfuscatedFileSystemOriginEnumerator() {} + + // 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 GetOriginURLFromIdentifier(record.origin); + } + + // Returns the current origin's information. + virtual bool HasFileSystemType(FileSystemType type) const OVERRIDE { + if (current_.path.empty()) + return false; + FilePath::StringType type_string = + ObfuscatedFileSystemFileUtil::GetDirectoryNameForType(type); + if (type_string.empty()) { + NOTREACHED(); + return false; + } + FilePath path = base_path_.Append(current_.path).Append(type_string); + return file_util::DirectoryExists(path); + } + + private: + std::vector<OriginRecord> origins_; + OriginRecord current_; + FilePath base_path_; +}; + +ObfuscatedFileSystemFileUtil::AbstractOriginEnumerator* +ObfuscatedFileSystemFileUtil::CreateOriginEnumerator() { + std::vector<FileSystemOriginDatabase::OriginRecord> origins; + + InitOriginDatabase(false); + return new ObfuscatedFileSystemOriginEnumerator( + origin_database_.get(), file_system_directory_); +} + FileSystemFileUtil::AbstractFileEnumerator* ObfuscatedFileSystemFileUtil::CreateFileEnumerator( FileSystemOperationContext* context, @@ -633,7 +687,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile( path = path.AppendASCII(StringPrintf("%02" PRIu64, directory_number)); PlatformFileError error; - error = FileSystemFileUtil::GetInstance()->CreateDirectory( + error = QuotaFileUtil::GetInstance()->CreateDirectory( context, path, false /* exclusive */, false /* recursive */); if (base::PLATFORM_FILE_OK != error) return error; @@ -645,17 +699,17 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile( if (!source_path.empty()) { DCHECK(!file_flags); DCHECK(!handle); - error = FileSystemFileUtil::GetInstance()->CopyOrMoveFile( + error = QuotaFileUtil::GetInstance()->CopyOrMoveFile( context, source_path, path, true /* copy */); created = true; } else { if (handle) { - error = FileSystemFileUtil::GetInstance()->CreateOrOpen( + error = QuotaFileUtil::GetInstance()->CreateOrOpen( context, path, file_flags, handle, &created); // If this succeeds, we must close handle on any subsequent error. } else { DCHECK(!file_flags); // file_flags is only used by CreateOrOpen. - error = FileSystemFileUtil::GetInstance()->EnsureFileExists( + error = QuotaFileUtil::GetInstance()->EnsureFileExists( context, path, &created); } } @@ -666,7 +720,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile( NOTREACHED(); if (handle) { base::ClosePlatformFile(*handle); - FileSystemFileUtil::GetInstance()->DeleteFile(context, path); + QuotaFileUtil::GetInstance()->DeleteFile(context, path); } return base::PLATFORM_FILE_ERROR_FAILED; } @@ -675,7 +729,7 @@ PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile( if (!db->AddFileInfo(*file_info, &file_id)) { if (handle) base::ClosePlatformFile(*handle); - FileSystemFileUtil::GetInstance()->DeleteFile(context, path); + QuotaFileUtil::GetInstance()->DeleteFile(context, path); return base::PLATFORM_FILE_ERROR_FAILED; } @@ -710,32 +764,28 @@ FilePath ObfuscatedFileSystemFileUtil::GetDirectoryForOriginAndType( LOG(WARNING) << "Unknown filesystem type requested:" << type; return FilePath(); } - return origin_dir.Append(type_string); + FilePath path = origin_dir.Append(type_string); + if (!file_util::DirectoryExists(path) && + (!create || !file_util::CreateDirectory(path))) + return FilePath(); + return path; } FilePath ObfuscatedFileSystemFileUtil::GetDirectoryForOrigin( const GURL& origin, bool create) { - if (!origin_database_.get()) { - if (!create && !file_util::DirectoryExists(file_system_directory_)) { - return FilePath(); - } - if (!file_util::CreateDirectory(file_system_directory_)) { - LOG(WARNING) << "Failed to create FileSystem directory: " << - file_system_directory_.value(); - return FilePath(); - } - origin_database_.reset( - new FileSystemOriginDatabase( - file_system_directory_.AppendASCII(kOriginDatabaseName))); - } + if (!InitOriginDatabase(create)) + return FilePath(); FilePath directory_name; - // TODO(ericu): This should probably be using GetOriginIdentifierFromURL from - // sandbox_mount_point_provider.cc, instead of just using origin.spec(). - if (!create && !origin_database_->HasOriginPath(origin.spec())) + std::string id = GetOriginIdentifierFromURL(origin); + if (!create && !origin_database_->HasOriginPath(id)) + return FilePath(); + if (!origin_database_->GetPathForOrigin(id, &directory_name)) return FilePath(); - if (!origin_database_->GetPathForOrigin(origin.spec(), &directory_name)) + FilePath path = file_system_directory_.Append(directory_name); + if (!file_util::DirectoryExists(path) && + (!create || !file_util::CreateDirectory(path))) return FilePath(); - return file_system_directory_.Append(directory_name); + return path; } bool ObfuscatedFileSystemFileUtil::MigrateFromOldSandbox( @@ -800,8 +850,9 @@ bool ObfuscatedFileSystemFileUtil::MigrateFromOldSandbox( return file_util::Move(src_root, legacy_dest_dir); } +// static FilePath::StringType ObfuscatedFileSystemFileUtil::GetDirectoryNameForType( - FileSystemType type) const { + FileSystemType type) { switch (type) { case kFileSystemTypeTemporary: return kTemporaryDirectoryName; @@ -844,9 +895,7 @@ FileSystemDirectoryDatabase* ObfuscatedFileSystemFileUtil::GetDirectoryDatabase( LOG(WARNING) << "Unknown filesystem type requested:" << type; return NULL; } - // 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; + std::string key = GetOriginIdentifierFromURL(origin) + type_string; DirectoryMap::iterator iter = directories_.find(key); if (iter != directories_.end()) return iter->second; @@ -889,9 +938,7 @@ bool ObfuscatedFileSystemFileUtil::DestroyDirectoryDatabase( 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; + std::string key = GetOriginIdentifierFromURL(origin) + type_string; DirectoryMap::iterator iter = directories_.find(key); if (iter != directories_.end()) directories_.erase(iter); @@ -905,4 +952,20 @@ bool ObfuscatedFileSystemFileUtil::DestroyDirectoryDatabase( return FileSystemDirectoryDatabase::DestroyDatabase(path); } +bool ObfuscatedFileSystemFileUtil::InitOriginDatabase(bool create) { + if (!origin_database_.get()) { + if (!create && !file_util::DirectoryExists(file_system_directory_)) + return false; + if (!file_util::CreateDirectory(file_system_directory_)) { + LOG(WARNING) << "Failed to create FileSystem directory: " << + file_system_directory_.value(); + return false; + } + origin_database_.reset( + new FileSystemOriginDatabase( + file_system_directory_.AppendASCII(kOriginDatabaseName))); + } + return true; +} + } // namespace fileapi diff --git a/webkit/fileapi/obfuscated_file_system_file_util.h b/webkit/fileapi/obfuscated_file_system_file_util.h index 65e4e5f..812db522 100644 --- a/webkit/fileapi/obfuscated_file_system_file_util.h +++ b/webkit/fileapi/obfuscated_file_system_file_util.h @@ -123,15 +123,12 @@ class ObfuscatedFileSystemFileUtil : public FileSystemFileUtil, // 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. If we decide to migrate in-place, without moving old files - // that were created by LocalFileSystemFileUtil, not all backing files will - // actually be in this directory. + // subdirectories. FilePath GetDirectoryForOriginAndType( const GURL& origin, FileSystemType type, bool create); // Gets the topmost directory specific to this origin. This will - // contain both the filesystem type subdirectories. See previous comment - // about migration; TODO(ericu): implement migration and fix these comments. + // contain both the filesystem type subdirectories. FilePath GetDirectoryForOrigin(const GURL& origin, bool create); // This will migrate a filesystem from the old passthrough sandbox into the @@ -147,7 +144,28 @@ class ObfuscatedFileSystemFileUtil : public FileSystemFileUtil, bool MigrateFromOldSandbox( const GURL& origin, FileSystemType type, const FilePath& root); - FilePath::StringType GetDirectoryNameForType(FileSystemType type) const; + // TODO(ericu): This doesn't really feel like it belongs in this class. + // The previous version lives in FileSystemPathManager, but perhaps + // SandboxMountPointProvider would be better? + static FilePath::StringType GetDirectoryNameForType(FileSystemType type); + + // 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. + virtual bool HasFileSystemType(FileSystemType type) const = 0; + }; + + // 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(); protected: virtual AbstractFileEnumerator* CreateFileEnumerator( @@ -195,6 +213,7 @@ class ObfuscatedFileSystemFileUtil : public FileSystemFileUtil, void MarkUsed(); void DropDatabases(); bool DestroyDirectoryDatabase(const GURL& origin, FileSystemType type); + bool InitOriginDatabase(bool create); 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 549a542..2fbd10e 100644 --- a/webkit/fileapi/obfuscated_file_system_file_util_unittest.cc +++ b/webkit/fileapi/obfuscated_file_system_file_util_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <algorithm> #include <set> #include <string> @@ -14,6 +15,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webkit/fileapi/file_system_context.h" #include "webkit/fileapi/file_system_operation_context.h" +#include "webkit/fileapi/file_system_test_helper.h" #include "webkit/fileapi/obfuscated_file_system_file_util.h" using namespace fileapi; @@ -93,6 +95,20 @@ const MigrationTestCaseRecord kMigrationTestCases[] = { {false, FILE_PATH_LITERAL("dir a/dir d/dir e/dir g/file 3"), 50}, }; +struct OriginEnumerationTestRecord { + std::string origin_url; + bool has_temporary; + bool has_persistent; +}; + +const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = { + {"http://example.com", false, true}, + {"http://example1.com", true, false}, + {"https://example1.com", true, true}, + {"file://", false, true}, + {"http://example.com:8000", false, true}, +}; + } // namespace (anonymous) // TODO(ericu): The vast majority of this and the other FSFU subclass tests @@ -101,7 +117,10 @@ const MigrationTestCaseRecord kMigrationTestCases[] = { // implementation would need to be written per-subclass. class ObfuscatedFileSystemFileUtilTest : public testing::Test { public: - ObfuscatedFileSystemFileUtilTest() { + ObfuscatedFileSystemFileUtilTest() + : origin_(GURL("http://www.example.com")), + type_(kFileSystemTypeTemporary), + test_helper_(origin_, type_) { } void SetUp() { @@ -109,17 +128,16 @@ class ObfuscatedFileSystemFileUtilTest : public testing::Test { obfuscated_file_system_file_util_ = new ObfuscatedFileSystemFileUtil(data_dir_.path()); + test_helper_.SetUp(data_dir_.path(), + false, // incognito + false, // unlimited quota + NULL, // quota::QuotaManagerProxy + obfuscated_file_system_file_util_.get()); } FileSystemOperationContext* NewContext() { - FileSystemOperationContext *context = - new FileSystemOperationContext(NULL, NULL); - context->set_src_origin_url(GURL("http://example.com")); - context->set_dest_origin_url(GURL("http://example.com")); - context->set_src_type(kFileSystemTypeTemporary); - context->set_dest_type(kFileSystemTypeTemporary); + FileSystemOperationContext* context = test_helper_.NewOperationContext(); context->set_allowed_bytes_growth(1024 * 1024); - return context; } @@ -131,6 +149,14 @@ class ObfuscatedFileSystemFileUtilTest : public testing::Test { return data_dir_.path(); } + const GURL& origin_url() const { + return origin_; + } + + fileapi::FileSystemType type() const { + return type_; + } + int64 GetSize(const FilePath& path) { int64 size; EXPECT_TRUE(file_util::GetFileSize(path, &size)); @@ -317,6 +343,9 @@ class ObfuscatedFileSystemFileUtilTest : public testing::Test { private: ScopedTempDir data_dir_; scoped_refptr<ObfuscatedFileSystemFileUtil> obfuscated_file_system_file_util_; + GURL origin_; + fileapi::FileSystemType type_; + FileSystemTestOriginHelper test_helper_; DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileSystemFileUtilTest); }; @@ -813,13 +842,11 @@ TEST_F(ObfuscatedFileSystemFileUtilTest, TestMigration) { } } - const GURL origin_url("http://example.com"); - fileapi::FileSystemType type = kFileSystemTypeTemporary; - EXPECT_TRUE(ofsfu()->MigrateFromOldSandbox(origin_url, type, root_path)); + EXPECT_TRUE(ofsfu()->MigrateFromOldSandbox(origin_url(), type(), root_path)); FilePath new_root = test_directory().AppendASCII("000").Append( - ofsfu()->GetDirectoryNameForType(type)).AppendASCII("Legacy"); + 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]; @@ -851,3 +878,71 @@ TEST_F(ObfuscatedFileSystemFileUtilTest, TestMigration) { } } } + +TEST_F(ObfuscatedFileSystemFileUtilTest, TestOriginEnumerator) { + scoped_ptr<ObfuscatedFileSystemFileUtil::AbstractOriginEnumerator> + enumerator(ofsfu()->CreateOriginEnumerator()); + EXPECT_TRUE(enumerator.get()); + EXPECT_EQ(GURL(), enumerator->Next()); + EXPECT_FALSE(enumerator->HasFileSystemType(kFileSystemTypeTemporary)); + EXPECT_FALSE(enumerator->HasFileSystemType(kFileSystemTypePersistent)); + + std::set<GURL> origins_expected; + + for (size_t i = 0; i < arraysize(kOriginEnumerationTestRecords); ++i) { + SCOPED_TRACE(testing::Message() << + "Validating kOriginEnumerationTestRecords " << i); + const OriginEnumerationTestRecord& record = + kOriginEnumerationTestRecords[i]; + GURL origin_url(record.origin_url); + origins_expected.insert(origin_url); + if (record.has_temporary) { + scoped_ptr<FileSystemOperationContext> context(NewContext()); + context->set_src_origin_url(origin_url); + context->set_src_type(kFileSystemTypeTemporary); + bool created = false; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofsfu()->EnsureFileExists(context.get(), + FilePath().AppendASCII("file"), &created)); + EXPECT_TRUE(created); + } + if (record.has_persistent) { + scoped_ptr<FileSystemOperationContext> context(NewContext()); + context->set_src_origin_url(origin_url); + context->set_src_type(kFileSystemTypePersistent); + bool created = false; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofsfu()->EnsureFileExists(context.get(), + FilePath().AppendASCII("file"), &created)); + EXPECT_TRUE(created); + } + } + enumerator.reset(ofsfu()->CreateOriginEnumerator()); + EXPECT_TRUE(enumerator.get()); + std::set<GURL> origins_found; + GURL origin; + while (!(origin = enumerator->Next()).is_empty()) { + origins_found.insert(origin); + SCOPED_TRACE(testing::Message() << "Handling " << origin.spec()); + bool found = false; + for (size_t i = 0; !found && i < arraysize(kOriginEnumerationTestRecords); + ++i) { + const OriginEnumerationTestRecord& record = + kOriginEnumerationTestRecords[i]; + if (GURL(record.origin_url) != origin) + continue; + found = true; + EXPECT_EQ(record.has_temporary, + enumerator->HasFileSystemType(kFileSystemTypeTemporary)); + EXPECT_EQ(record.has_persistent, + enumerator->HasFileSystemType(kFileSystemTypePersistent)); + } + EXPECT_TRUE(found); + } + + std::set<GURL> diff; + std::set_symmetric_difference(origins_expected.begin(), + origins_expected.end(), origins_found.begin(), origins_found.end(), + inserter(diff, diff.begin())); + EXPECT_TRUE(diff.empty()); +} diff --git a/webkit/fileapi/sandbox_mount_point_provider.cc b/webkit/fileapi/sandbox_mount_point_provider.cc index 60f2fb4..0efd876 100644 --- a/webkit/fileapi/sandbox_mount_point_provider.cc +++ b/webkit/fileapi/sandbox_mount_point_provider.cc @@ -13,12 +13,8 @@ #include "base/rand_util.h" #include "base/string_util.h" #include "base/stringprintf.h" -#include "base/utf_string_conversions.h" #include "googleurl/src/gurl.h" #include "net/base/net_util.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" #include "webkit/fileapi/file_system_path_manager.h" #include "webkit/fileapi/file_system_types.h" #include "webkit/fileapi/file_system_usage_cache.h" @@ -63,28 +59,6 @@ inline std::string FilePathStringToASCII( #endif } -// TODO(kinuko): Merge these two methods (conversion methods between -// origin url <==> identifier) with the ones in the database module. -std::string GetOriginIdentifierFromURL(const GURL& url) { - WebKit::WebSecurityOrigin web_security_origin = - WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec())); - return web_security_origin.databaseIdentifier().utf8(); -} - -GURL GetOriginURLFromIdentifier(const std::string& origin_identifier) { - WebKit::WebSecurityOrigin web_security_origin = - WebKit::WebSecurityOrigin::createFromDatabaseIdentifier( - UTF8ToUTF16(origin_identifier)); - GURL origin_url(web_security_origin.toString()); - - // We need this work-around for file:/// URIs as - // createFromDatabaseIdentifier returns empty origin_url for them. - if (origin_url.spec().empty() && - origin_identifier.find("file__") == 0) - return GURL("file:///"); - return origin_url; -} - FilePath::StringType CreateUniqueDirectoryName(const GURL& origin_url) { // This can be anything but need to be unpredictable. static const FilePath::CharType letters[] = FILE_PATH_LITERAL( @@ -138,6 +112,28 @@ FilePath GetFileSystemRootPathOnFileThreadHelper( return root; } +class ObfuscatedOriginEnumerator + : public fileapi::SandboxMountPointProvider::OriginEnumerator { + public: + explicit ObfuscatedOriginEnumerator( + fileapi::ObfuscatedFileSystemFileUtil* file_util) { + enum_.reset(file_util->CreateOriginEnumerator()); + } + virtual ~ObfuscatedOriginEnumerator() {} + + virtual GURL Next() OVERRIDE { + return enum_->Next(); + } + + virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { + return enum_->HasFileSystemType(type); + } + + private: + scoped_ptr<fileapi::ObfuscatedFileSystemFileUtil::AbstractOriginEnumerator> + enum_; +}; + class SandboxOriginEnumerator : public fileapi::SandboxMountPointProvider::OriginEnumerator { public: @@ -150,7 +146,7 @@ class SandboxOriginEnumerator current_ = enumerator_.Next(); if (current_.empty()) return GURL(); - return GetOriginURLFromIdentifier( + return fileapi::GetOriginURLFromIdentifier( FilePathStringToASCII(current_.BaseName().value())); } @@ -265,21 +261,6 @@ class SandboxMountPointProvider::GetFileSystemRootPathTask scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback_; }; -FilePath SandboxMountPointProvider::GetFileSystemRootPathOnFileThread( - const GURL& origin_url, FileSystemType type, bool create) { - if (CommandLine::ForCurrentProcess()->HasSwitch(kObfuscationFlag)) - return sandbox_file_util_->GetDirectoryForOriginAndType( - origin_url, type, create); - - std::string name; - FilePath origin_base_path; - if (!GetOriginBasePathAndName(origin_url, &origin_base_path, type, &name)) - return FilePath(); - - return GetFileSystemRootPathOnFileThreadHelper( - origin_url, origin_base_path, create); -} - bool SandboxMountPointProvider::IsRestrictedFileName(const FilePath& filename) const { if (filename.value().empty()) @@ -320,6 +301,8 @@ std::vector<FilePath> SandboxMountPointProvider::GetRootDirectories() const { SandboxMountPointProvider::OriginEnumerator* SandboxMountPointProvider::CreateOriginEnumerator() const { + if (CommandLine::ForCurrentProcess()->HasSwitch(kObfuscationFlag)) + return new ObfuscatedOriginEnumerator(sandbox_file_util_.get()); return new SandboxOriginEnumerator(base_path_); } @@ -329,6 +312,18 @@ void SandboxMountPointProvider::ValidateFileSystemRootAndGetURL( scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback(callback_ptr); ObfuscatedFileSystemFileUtil* file_util = NULL; FilePath origin_base_path; + + if (path_manager_->is_incognito()) { + // TODO(kinuko): return an isolated temporary directory. + callback->Run(false, FilePath(), std::string()); + return; + } + + if (!path_manager_->IsAllowedScheme(origin_url)) { + callback->Run(false, FilePath(), std::string()); + return; + } + if (CommandLine::ForCurrentProcess()->HasSwitch(kObfuscationFlag)) { file_util = sandbox_file_util_.get(); } else { @@ -353,31 +348,54 @@ FilePath SandboxMountPointProvider::ValidateFileSystemRootAndGetPathOnFileThread( const GURL& origin_url, FileSystemType type, const FilePath& unused, bool create) { - return GetFileSystemRootPathOnFileThread(origin_url, type, create); + if (path_manager_->is_incognito()) + // TODO(kinuko): return an isolated temporary directory. + return FilePath(); + + if (!path_manager_->IsAllowedScheme(origin_url)) + return FilePath(); + + if (CommandLine::ForCurrentProcess()->HasSwitch(kObfuscationFlag)) + return sandbox_file_util_->GetDirectoryForOriginAndType( + origin_url, type, create); + + std::string name; + FilePath origin_base_path; + if (!GetOriginBasePathAndName(origin_url, &origin_base_path, type, &name)) + return FilePath(); + + return GetFileSystemRootPathOnFileThreadHelper( + origin_url, origin_base_path, create); } FilePath SandboxMountPointProvider::GetBaseDirectoryForOrigin( - const GURL& origin_url) const { + const GURL& origin_url, bool create) const { + if (CommandLine::ForCurrentProcess()->HasSwitch(kObfuscationFlag)) + return sandbox_file_util_->GetDirectoryForOrigin( + origin_url, create); return base_path_.AppendASCII(GetOriginIdentifierFromURL(origin_url)); } // Needed for the old way of doing things. FilePath SandboxMountPointProvider::GetBaseDirectoryForOriginAndType( - const GURL& origin_url, fileapi::FileSystemType type) const { + const GURL& origin_url, fileapi::FileSystemType type, bool create) const { + if (CommandLine::ForCurrentProcess()->HasSwitch(kObfuscationFlag)) + return sandbox_file_util_->GetDirectoryForOriginAndType( + origin_url, type, create); std::string type_string = FileSystemPathManager::GetFileSystemTypeString(type); if (type_string.empty()) { LOG(WARNING) << "Unknown filesystem type is requested:" << type; return FilePath(); } - return GetBaseDirectoryForOrigin(origin_url).AppendASCII(type_string); + return GetBaseDirectoryForOrigin(origin_url, create).AppendASCII(type_string); } bool SandboxMountPointProvider::DeleteOriginDataOnFileThread( QuotaManagerProxy* proxy, const GURL& origin_url, fileapi::FileSystemType type) { - FilePath path_for_origin = GetBaseDirectoryForOriginAndType(origin_url, - type); + FilePath path_for_origin = + GetBaseDirectoryForOriginAndType(origin_url, type, false); if (!file_util::PathExists(path_for_origin)) return true; @@ -425,7 +443,8 @@ int64 SandboxMountPointProvider::GetOriginUsageOnFileThread( const GURL& origin_url, fileapi::FileSystemType type) { DCHECK(type == fileapi::kFileSystemTypeTemporary || type == fileapi::kFileSystemTypePersistent); - FilePath base_path = GetBaseDirectoryForOriginAndType(origin_url, type); + FilePath base_path = + GetBaseDirectoryForOriginAndType(origin_url, type, false); if (!file_util::DirectoryExists(base_path)) return 0; @@ -512,16 +531,7 @@ bool SandboxMountPointProvider::GetOriginBasePathAndName( FileSystemType type, std::string* name) { -// TODO(ericu): Put the incognito and allowed scheme checks somewhere in the -// obfuscated code as well. - if (path_manager_->is_incognito()) - // TODO(kinuko): return an isolated temporary directory. - return false; - - if (!path_manager_->IsAllowedScheme(origin_url)) - return false; - - *origin_base_path = GetBaseDirectoryForOriginAndType(origin_url, type); + *origin_base_path = GetBaseDirectoryForOriginAndType(origin_url, type, false); if (origin_base_path->empty()) return false; @@ -536,7 +546,8 @@ bool SandboxMountPointProvider::GetOriginBasePathAndName( FilePath SandboxMountPointProvider::GetUsageCachePathForOriginAndType( const GURL& origin_url, fileapi::FileSystemType type) const { - FilePath base_path = GetBaseDirectoryForOriginAndType(origin_url, type); + FilePath base_path = + GetBaseDirectoryForOriginAndType(origin_url, type, false); return base_path.AppendASCII(FileSystemUsageCache::kUsageFileName); } diff --git a/webkit/fileapi/sandbox_mount_point_provider.h b/webkit/fileapi/sandbox_mount_point_provider.h index 60bd7fe..417aff8 100644 --- a/webkit/fileapi/sandbox_mount_point_provider.h +++ b/webkit/fileapi/sandbox_mount_point_provider.h @@ -96,20 +96,19 @@ class SandboxMountPointProvider // specified by |origin_url|. // (The path is similar to the origin's root path but doesn't contain // the 'unique' and 'type' part.) - // This method is portable and can be called on any thread. - // TODO(ericu) obfuscated version for quota integration. - FilePath GetBaseDirectoryForOrigin(const GURL& origin_url) const; + // This method can only be called on the file thread. + FilePath GetBaseDirectoryForOrigin(const GURL& origin_url, bool create) const; // 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 is portable and can be called on any thread. - // TODO(ericu) obfuscated version for quota integration. + // This method can only be called on the file thread. FilePath GetBaseDirectoryForOriginAndType( const GURL& origin_url, - fileapi::FileSystemType type) const; + fileapi::FileSystemType type, + bool create) const; FileSystemFileUtil* GetFileSystemFileUtil(); @@ -161,9 +160,6 @@ class SandboxMountPointProvider const GURL& origin_url, fileapi::FileSystemType type) const; - FilePath GetFileSystemRootPathOnFileThread( - const GURL& origin_url, FileSystemType type, bool create); - class GetFileSystemRootPathTask; friend class FileSystemTestOriginHelper; diff --git a/webkit/fileapi/sandbox_mount_point_provider_unittest.cc b/webkit/fileapi/sandbox_mount_point_provider_unittest.cc index 6d0b575..d657715 100644 --- a/webkit/fileapi/sandbox_mount_point_provider_unittest.cc +++ b/webkit/fileapi/sandbox_mount_point_provider_unittest.cc @@ -46,7 +46,7 @@ class SandboxMountPointProviderOriginEnumeratorTest : public testing::Test { void CreateOriginTypeDirectory(const GURL& origin, fileapi::FileSystemType type) { FilePath target = path_manager_->sandbox_provider()-> - GetBaseDirectoryForOriginAndType(origin, type); + GetBaseDirectoryForOriginAndType(origin, type, true); file_util::CreateDirectory(target); ASSERT_TRUE(file_util::DirectoryExists(target)); } |