diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-15 03:20:03 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-15 03:20:03 +0000 |
commit | f698a7f22b36d056bbbfa74aaf910d8ac3b97c23 (patch) | |
tree | c21fbd8499daa68203d23e2e25a7ff16e595bd67 /webkit/fileapi | |
parent | 95249b6e92c3ac6742139f948028d7f3ec5b9dc6 (diff) | |
download | chromium_src-f698a7f22b36d056bbbfa74aaf910d8ac3b97c23.zip chromium_src-f698a7f22b36d056bbbfa74aaf910d8ac3b97c23.tar.gz chromium_src-f698a7f22b36d056bbbfa74aaf910d8ac3b97c23.tar.bz2 |
Hide the FileSystem directory under 'unpredictable' location (part 2)
BUG=58361
TEST=FileSystemPathManager.*
Review URL: http://codereview.chromium.org/3724001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62698 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
-rw-r--r-- | webkit/fileapi/file_system_path_manager.cc | 261 | ||||
-rw-r--r-- | webkit/fileapi/file_system_path_manager.h | 56 | ||||
-rw-r--r-- | webkit/fileapi/file_system_path_manager_unittest.cc | 318 | ||||
-rw-r--r-- | webkit/fileapi/file_system_types.h | 1 |
4 files changed, 495 insertions, 141 deletions
diff --git a/webkit/fileapi/file_system_path_manager.cc b/webkit/fileapi/file_system_path_manager.cc index 12c273e..05adafc 100644 --- a/webkit/fileapi/file_system_path_manager.cc +++ b/webkit/fileapi/file_system_path_manager.cc @@ -5,9 +5,9 @@ #include "webkit/fileapi/file_system_path_manager.h" #include "base/file_util.h" -#include "base/file_util_proxy.h" #include "base/rand_util.h" #include "base/logging.h" +#include "base/message_loop.h" #include "base/scoped_callback_factory.h" #include "base/stringprintf.h" #include "base/string_util.h" @@ -24,7 +24,6 @@ using WebKit::WebFileSystem; using WebKit::WebSecurityOrigin; using WebKit::WebString; -using base::FileUtilProxy; using base::PlatformFileError; namespace fileapi { @@ -35,6 +34,12 @@ const FilePath::CharType FileSystemPathManager::kFileSystemDirectory[] = const char FileSystemPathManager::kPersistentName[] = "Persistent"; const char FileSystemPathManager::kTemporaryName[] = "Temporary"; +static const FilePath::CharType kFileSystemUniqueNamePrefix[] = + FILE_PATH_LITERAL("chrome-"); +static const int kFileSystemUniqueLength = 16; +static const unsigned kFileSystemUniqueDirectoryNameLength = + kFileSystemUniqueLength + arraysize(kFileSystemUniqueNamePrefix) - 1; + namespace { // Restricted names. @@ -59,50 +64,163 @@ inline std::string FilePathStringToASCII( #endif } +FilePath::StringType CreateUniqueDirectoryName(const GURL& origin_url) { + // This can be anything but need to be unpredictable. + static const FilePath::CharType letters[] = FILE_PATH_LITERAL( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); + FilePath::StringType unique(kFileSystemUniqueNamePrefix); + for (int i = 0; i < kFileSystemUniqueLength; ++i) + unique += letters[base::RandInt(0, arraysize(letters) - 2)]; + return unique; +} + } // anonymous namespace +class FileSystemPathManager::GetFileSystemRootPathTask + : public base::RefCountedThreadSafe< + FileSystemPathManager::GetFileSystemRootPathTask> { + public: + GetFileSystemRootPathTask( + scoped_refptr<base::MessageLoopProxy> file_message_loop, + const std::string& name, + FileSystemPathManager::GetRootPathCallback* callback) + : file_message_loop_(file_message_loop), + origin_message_loop_proxy_( + base::MessageLoopProxy::CreateForCurrentThread()), + name_(name), + callback_(callback) { + } + + void Start(const GURL& origin_url, + const FilePath& origin_base_path, + bool create) { + file_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, + &GetFileSystemRootPathTask::GetFileSystemRootPathOnFileThread, + origin_url, origin_base_path, create)); + } + + private: + void GetFileSystemRootPathOnFileThread( + const GURL& origin_url, + const FilePath& base_path, + bool create) { + FilePath root; + if (ReadOriginDirectory(base_path, origin_url, &root)) { + DispatchCallbackOnCallerThread(root); + return; + } + + if (!create) { + DispatchCallbackOnCallerThread(FilePath()); + return; + } + + // Creates the root directory. + root = base_path.Append(CreateUniqueDirectoryName(origin_url)); + if (!file_util::CreateDirectory(root)) { + DispatchCallbackOnCallerThread(FilePath()); + return; + } + DispatchCallbackOnCallerThread(root); + } + + bool ReadOriginDirectory(const FilePath& base_path, + const GURL& origin_url, + FilePath* unique) { + file_util::FileEnumerator file_enum( + base_path, false /* recursive */, + file_util::FileEnumerator::DIRECTORIES, + FilePath::StringType(kFileSystemUniqueNamePrefix) + + FILE_PATH_LITERAL("*")); + FilePath current; + bool found = false; + while (!(current = file_enum.Next()).empty()) { + if (current.BaseName().value().length() != + kFileSystemUniqueDirectoryNameLength) + continue; + if (found) { + // TODO(kinuko): Should notify the user to ask for some action. + LOG(WARNING) << "Unexpectedly found more than one FileSystem " + << "directories for " << origin_url; + return false; + } + found = true; + *unique = current; + } + return !unique->empty(); + } + + void DispatchCallbackOnCallerThread(const FilePath& root_path) { + origin_message_loop_proxy_->PostTask(FROM_HERE, + NewRunnableMethod(this, &GetFileSystemRootPathTask::DispatchCallback, + root_path)); + } + + void DispatchCallback(const FilePath& root_path) { + callback_->Run(!root_path.empty(), root_path, name_); + } + + scoped_refptr<base::MessageLoopProxy> file_message_loop_; + scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_; + std::string name_; + scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback_; +}; + FileSystemPathManager::FileSystemPathManager( - const FilePath& data_path, + scoped_refptr<base::MessageLoopProxy> file_message_loop, + const FilePath& profile_path, bool is_incognito, bool allow_file_access_from_files) - : base_path_(data_path.Append(kFileSystemDirectory)), + : file_message_loop_(file_message_loop), + base_path_(profile_path.Append(kFileSystemDirectory)), is_incognito_(is_incognito), allow_file_access_from_files_(allow_file_access_from_files) { } -bool FileSystemPathManager::GetFileSystemRootPath( +void FileSystemPathManager::GetFileSystemRootPath( const GURL& origin_url, fileapi::FileSystemType type, - FilePath* root_path, std::string* name) const { - // TODO(kinuko): should return an isolated temporary file system space. - if (is_incognito_) - return false; + bool create, GetRootPathCallback* callback_ptr) { + scoped_ptr<GetRootPathCallback> callback(callback_ptr); + if (is_incognito_) { + // TODO(kinuko): return an isolated temporary directory. + callback->Run(false, FilePath(), std::string()); + return; + } - if (!IsAllowedScheme(origin_url)) - return false; + if (!IsAllowedScheme(origin_url)) { + callback->Run(false, FilePath(), std::string()); + return; + } - std::string storage_identifier = GetStorageIdentifierFromURL(origin_url); - switch (type) { - case fileapi::kFileSystemTypeTemporary: - if (root_path) - *root_path = base_path_.AppendASCII(storage_identifier) - .AppendASCII(kTemporaryName); - if (name) - *name = storage_identifier + ":" + kTemporaryName; - return true; - case fileapi::kFileSystemTypePersistent: - if (root_path) - *root_path = base_path_.AppendASCII(storage_identifier) - .AppendASCII(kPersistentName); - if (name) - *name = storage_identifier + ":" + kPersistentName; - return true; + if (type != fileapi::kFileSystemTypeTemporary && + type != fileapi::kFileSystemTypePersistent) { + LOG(WARNING) << "Unknown filesystem type is requested:" << type; + callback->Run(false, FilePath(), std::string()); + return; } - LOG(WARNING) << "Unknown filesystem type is requested:" << type; - return false; + + std::string storage_identifier = GetStorageIdentifierFromURL(origin_url); + + std::string type_string; + if (type == fileapi::kFileSystemTypeTemporary) + type_string = kTemporaryName; + else if (type == fileapi::kFileSystemTypePersistent) + type_string = kPersistentName; + DCHECK(!type_string.empty()); + + FilePath origin_base_path = base_path_.AppendASCII(storage_identifier) + .AppendASCII(type_string); + std::string name = storage_identifier + ":" + type_string; + + scoped_refptr<GetFileSystemRootPathTask> task = + new GetFileSystemRootPathTask(file_message_loop_, + name, callback.release()); + task->Start(origin_url, origin_base_path, create); } -bool FileSystemPathManager::CheckValidFileSystemPath( - const FilePath& path) const { +bool FileSystemPathManager::CrackFileSystemPath( + const FilePath& path, GURL* origin_url, FileSystemType* type, + FilePath* virtual_path) const { // Any paths that includes parent references are considered invalid. if (path.ReferencesParent()) return false; @@ -112,12 +230,12 @@ bool FileSystemPathManager::CheckValidFileSystemPath( if (!base_path_.AppendRelativePath(path, &relative)) return false; - // The relative path from the profile FileSystem path should at least - // contains two components, one for storage identifier and the other for type - + // The relative path from the profile FileSystem path should contain + // at least three components, one for storage identifier, one for type + // and one for the 'unique' part. std::vector<FilePath::StringType> components; relative.GetComponents(&components); - if (components.size() < 2) + if (components.size() < 3) return false; // The second component of the relative path to the root directory @@ -126,48 +244,42 @@ bool FileSystemPathManager::CheckValidFileSystemPath( return false; std::string ascii_type_component = FilePathStringToASCII(components[1]); - if (ascii_type_component != kPersistentName && - ascii_type_component != kTemporaryName) + FileSystemType cracked_type = kFileSystemTypeUnknown; + if (ascii_type_component == kPersistentName) + cracked_type = kFileSystemTypePersistent; + else if (ascii_type_component == kTemporaryName) + cracked_type = kFileSystemTypeTemporary; + else return false; - return true; -} + DCHECK(cracked_type != kFileSystemTypeUnknown); -bool FileSystemPathManager::GetOriginFromPath( - const FilePath& path, GURL* origin_url) { - DCHECK(origin_url); - FilePath relative; - if (!base_path_.AppendRelativePath(path, &relative)) { - // The path should be a child of the profile's FileSystem path. - return false; - } - std::vector<FilePath::StringType> components; - relative.GetComponents(&components); - if (components.size() < 2) { - // The relative path should at least contain storage identifier and type. - return false; - } - WebSecurityOrigin web_security_origin = - WebSecurityOrigin::createFromDatabaseIdentifier( - webkit_glue::FilePathStringToWebString(components[0])); - *origin_url = GURL(web_security_origin.toString()); - - // We need this work-around for file:/// URIs as - // createFromDatabaseIdentifier returns empty origin_url for them. - if (allow_file_access_from_files_ && origin_url->spec().empty() && - components[0].find(FILE_PATH_LITERAL("file")) == 0) { - *origin_url = GURL("file:///"); - return true; + // The given |path| seems valid. Populates the |origin_url|, |type| + // and |virtual_path| if they are given. + + if (origin_url) { + WebSecurityOrigin web_security_origin = + WebSecurityOrigin::createFromDatabaseIdentifier( + webkit_glue::FilePathStringToWebString(components[0])); + *origin_url = GURL(web_security_origin.toString()); + + // We need this work-around for file:/// URIs as + // createFromDatabaseIdentifier returns empty origin_url for them. + if (allow_file_access_from_files_ && origin_url->spec().empty() && + components[0].find(FILE_PATH_LITERAL("file")) == 0) + *origin_url = GURL("file:///"); } - return IsAllowedScheme(*origin_url); -} + if (type) + *type = cracked_type; -bool FileSystemPathManager::IsAllowedScheme(const GURL& url) const { - // Basically we only accept http or https. We allow file:// URLs - // only if --allow-file-access-from-files flag is given. - return url.SchemeIs("http") || url.SchemeIs("https") || - (url.SchemeIsFile() && allow_file_access_from_files_); + if (virtual_path) { + virtual_path->clear(); + for (size_t i = 3; i < components.size(); ++i) + *virtual_path = virtual_path->Append(components[i]); + } + + return true; } bool FileSystemPathManager::IsRestrictedFileName( @@ -200,6 +312,13 @@ bool FileSystemPathManager::IsRestrictedFileName( return false; } +bool FileSystemPathManager::IsAllowedScheme(const GURL& url) const { + // Basically we only accept http or https. We allow file:// URLs + // only if --allow-file-access-from-files flag is given. + return url.SchemeIs("http") || url.SchemeIs("https") || + (url.SchemeIsFile() && allow_file_access_from_files_); +} + std::string FileSystemPathManager::GetStorageIdentifierFromURL( const GURL& url) { WebKit::WebSecurityOrigin web_security_origin = diff --git a/webkit/fileapi/file_system_path_manager.h b/webkit/fileapi/file_system_path_manager.h index 505a3c1..f66c02a 100644 --- a/webkit/fileapi/file_system_path_manager.h +++ b/webkit/fileapi/file_system_path_manager.h @@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/file_path.h" +#include "base/message_loop_proxy.h" #include "base/scoped_ptr.h" #include "googleurl/src/gurl.h" #include "webkit/fileapi/file_system_types.h" @@ -17,33 +18,47 @@ namespace fileapi { class FileSystemPathManager { public: - FileSystemPathManager(const FilePath& data_path, + FileSystemPathManager(scoped_refptr<base::MessageLoopProxy> file_message_loop, + const FilePath& profile_path, bool is_incognito, bool allow_file_access_from_files); - // Returns the root path and name for the file system specified by given - // |origin_url| and |type|. Returns true if the file system is available - // for the profile and |root_path| and |name| are filled successfully. - bool GetFileSystemRootPath(const GURL& origin_url, + // Callback for GetFileSystemRootPath. + // If the request is accepted and the root filesystem for the origin exists + // the callback is called with success=true and valid root_path and name. + // If the request is accepted, |create| is specified for + // GetFileSystemRootPath, and the root directory does not exist, it creates + // a new one and calls back with success=true if the creation has succeeded. + typedef Callback3<bool /* success */, + const FilePath& /* root_path */, + const std::string& /* name */>::Type GetRootPathCallback; + + // Retrieves the root path for the given |origin_url| and |type|, and + // calls the given |callback| with the root path and name. + // If |create| is true this also creates the directory if it doesn't exist. + void GetFileSystemRootPath(const GURL& origin_url, fileapi::FileSystemType type, - FilePath* root_path, - std::string* name) const; - - // Checks if a given |path| is in the FileSystem base directory. - bool CheckValidFileSystemPath(const FilePath& path) const; - - // Retrieves the origin URL for the given |path| and populates - // |origin_url|. It returns false when the given |path| is not a - // valid filesystem path. - bool GetOriginFromPath(const FilePath& path, GURL* origin_url); + bool create, + GetRootPathCallback* callback); + + // Cracks the given |path|, retrieves the information embedded in the path + // and populates |origin_url| and |type|. Also it populates |virtual_path| + // that is a sandboxed path in the file system, i.e. the relative path to + // the file system's root path for the given origin and type. + // It returns false if the path does not conform to the expected + // filesystem path format. + bool CrackFileSystemPath(const FilePath& path, + GURL* origin_url, + FileSystemType* type, + FilePath* virtual_path) const; + + // Checks if a given |name| contains any restricted names/chars in it. + bool IsRestrictedFileName(const FilePath& filename) const; // Returns true if the given |url|'s scheme is allowed to access // filesystem. bool IsAllowedScheme(const GURL& url) const; - // Checks if a given |filename| contains any restricted names/chars in it. - bool IsRestrictedFileName(const FilePath& filename) const; - // The FileSystem directory name. static const FilePath::CharType kFileSystemDirectory[]; @@ -52,14 +67,15 @@ class FileSystemPathManager { private: class GetFileSystemRootPathTask; - friend class GetFileSystemRootPathTask; // Returns the storage identifier string for the given |url|. static std::string GetStorageIdentifierFromURL(const GURL& url); + scoped_refptr<base::MessageLoopProxy> file_message_loop_; + const FilePath base_path_; const bool is_incognito_; - bool allow_file_access_from_files_; + const bool allow_file_access_from_files_; DISALLOW_COPY_AND_ASSIGN(FileSystemPathManager); }; diff --git a/webkit/fileapi/file_system_path_manager_unittest.cc b/webkit/fileapi/file_system_path_manager_unittest.cc index 1e67c3a..1bb39f3 100644 --- a/webkit/fileapi/file_system_path_manager_unittest.cc +++ b/webkit/fileapi/file_system_path_manager_unittest.cc @@ -5,13 +5,16 @@ #include "webkit/fileapi/file_system_path_manager.h" #include "base/basictypes.h" -#include "base/file_path.h" +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/ref_counted.h" +#include "base/scoped_callback_factory.h" #include "base/scoped_ptr.h" #include "base/scoped_temp_dir.h" #include "googleurl/src/gurl.h" #include "testing/gtest/include/gtest/gtest.h" -using fileapi::FileSystemPathManager; +using namespace fileapi; namespace { @@ -22,27 +25,44 @@ namespace { #define PS "/" #endif -const FilePath::CharType kTestDataPath[] = FILE_PATH_LITERAL( - "//tmp/TestingProfilePath"); +struct RootPathTestCase { + fileapi::FileSystemType type; + const char* origin_url; + const char* expected_path; +}; const struct RootPathTest { fileapi::FileSystemType type; - bool off_the_record; const char* origin_url; - bool expect_root_path; const char* expected_path; } kRootPathTestCases[] = { - { fileapi::kFileSystemTypeTemporary, false, "http://host:1/", - true, "FileSystem" PS "http_host_1" PS "Temporary" }, - { fileapi::kFileSystemTypePersistent, false, "http://host:2/", - true, "FileSystem" PS "http_host_2" PS "Persistent" }, - { fileapi::kFileSystemTypeTemporary, true, "http://host:3/", - false, "" }, - { fileapi::kFileSystemTypePersistent, true, "http://host:4/", - false, "" }, - // We disallow file:// URIs to access filesystem. - { fileapi::kFileSystemTypeTemporary, false, "file:///some/path", false, "" }, - { fileapi::kFileSystemTypePersistent, false, "file:///some/path", false, "" }, + { fileapi::kFileSystemTypeTemporary, "http://foo:1/", + "http_foo_1" PS "Temporary" }, + { fileapi::kFileSystemTypePersistent, "http://foo:1/", + "http_foo_1" PS "Persistent" }, + { fileapi::kFileSystemTypeTemporary, "http://bar.com/", + "http_bar.com_0" PS "Temporary" }, + { fileapi::kFileSystemTypePersistent, "http://bar.com/", + "http_bar.com_0" PS "Persistent" }, + { fileapi::kFileSystemTypeTemporary, "https://foo:2/", + "https_foo_2" PS "Temporary" }, + { fileapi::kFileSystemTypePersistent, "https://foo:2/", + "https_foo_2" PS "Persistent" }, + { fileapi::kFileSystemTypeTemporary, "https://bar.com/", + "https_bar.com_0" PS "Temporary" }, + { fileapi::kFileSystemTypePersistent, "https://bar.com/", + "https_bar.com_0" PS "Persistent" }, +}; + +const struct RootPathFileURITest { + fileapi::FileSystemType type; + const char* origin_url; + const char* expected_path; +} kRootPathFileURITestCases[] = { + { fileapi::kFileSystemTypeTemporary, "file:///", + "file__0" PS "Temporary" }, + { fileapi::kFileSystemTypePersistent, "file:///", + "file__0" PS "Persistent" }, }; const struct CheckValidPathTest { @@ -59,6 +79,13 @@ const struct CheckValidPathTest { { FILE_PATH_LITERAL("a/b/../c/.."), false, }, }; +const char* const kPathToVirtualPathTestCases[] = { + "", + "a", + "a" PS "b", + "a" PS "b" PS "c", +}; + const struct IsRestrictedNameTest { FilePath::StringType name; bool expected_dangerous; @@ -132,58 +159,249 @@ const struct IsRestrictedNameTest { class FileSystemPathManagerTest : public testing::Test { public: FileSystemPathManagerTest() - : data_path_(kTestDataPath) { + : callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { + } + + void SetUp() { + data_dir_.reset(new ScopedTempDir); + data_dir_->CreateUniqueTempDir(); + ASSERT_TRUE(data_dir_->IsValid()); + root_path_callback_status_ = false; + root_path_.clear(); + file_system_name_.clear(); + } + + protected: + FileSystemPathManager* NewPathManager( + bool incognito, + bool allow_file_access) { + return new FileSystemPathManager( + base::MessageLoopProxy::CreateForCurrentThread(), + data_dir_->path(), incognito, allow_file_access); + } + + void OnGetRootPath(bool success, + const FilePath& root_path, + const std::string& name) { + root_path_callback_status_ = success; + root_path_ = root_path; + file_system_name_ = name; } - FileSystemPathManager* GetNewPathManager(bool incognito) { - path_manager_.reset(new FileSystemPathManager( - data_path_, incognito, false /* allow_file_access */)); - return path_manager_.get(); + bool GetRootPath(FileSystemPathManager* manager, + const GURL& origin_url, + fileapi::FileSystemType type, + bool create, + FilePath* root_path) { + manager->GetFileSystemRootPath(origin_url, type, create, + callback_factory_.NewCallback( + &FileSystemPathManagerTest::OnGetRootPath)); + MessageLoop::current()->RunAllPending(); + if (root_path) + *root_path = root_path_; + return root_path_callback_status_; + } + + bool CheckValidFileSystemPath(FileSystemPathManager* manager, + const FilePath& path) { + return manager->CrackFileSystemPath(path, NULL, NULL, NULL); + } + + FilePath data_path() { return data_dir_->path(); } + FilePath file_system_path() { + return data_dir_->path().Append( + FileSystemPathManager::kFileSystemDirectory); } private: - FilePath data_path_; - scoped_ptr<FileSystemPathManager> path_manager_; + scoped_ptr<ScopedTempDir> data_dir_; + base::ScopedCallbackFactory<FileSystemPathManagerTest> callback_factory_; + + bool root_path_callback_status_; + FilePath root_path_; + std::string file_system_name_; + + DISALLOW_COPY_AND_ASSIGN(FileSystemPathManagerTest); }; -TEST_F(FileSystemPathManagerTest, GetRootPath) { +TEST_F(FileSystemPathManagerTest, GetRootPathCreateAndExamine) { + std::vector<FilePath> returned_root_path( + ARRAYSIZE_UNSAFE(kRootPathTestCases)); + scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false)); + + // Create a new root directory. for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) { - SCOPED_TRACE(testing::Message() << "RootPath #" << i << " " + SCOPED_TRACE(testing::Message() << "RootPath (create) #" << i << " " << kRootPathTestCases[i].expected_path); - FileSystemPathManager* manager = GetNewPathManager( - kRootPathTestCases[i].off_the_record); + FilePath root_path; + EXPECT_TRUE(GetRootPath(manager.get(), + GURL(kRootPathTestCases[i].origin_url), + kRootPathTestCases[i].type, + true /* create */, &root_path)); + + 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)); + ASSERT_TRUE(returned_root_path.size() > i); + returned_root_path[i] = root_path; + } + + // Get the root directory with create=false and see if we get the + // same directory. + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) { + SCOPED_TRACE(testing::Message() << "RootPath (get) #" << i << " " + << kRootPathTestCases[i].expected_path); FilePath root_path; - bool result = manager->GetFileSystemRootPath( - GURL(kRootPathTestCases[i].origin_url), - kRootPathTestCases[i].type, - &root_path, NULL); - EXPECT_EQ(kRootPathTestCases[i].expect_root_path, result); - if (result) { - FilePath expected = FilePath(kTestDataPath).AppendASCII( - kRootPathTestCases[i].expected_path); - EXPECT_EQ(expected.value(), root_path.value()); - } + EXPECT_TRUE(GetRootPath(manager.get(), + GURL(kRootPathTestCases[i].origin_url), + kRootPathTestCases[i].type, + false /* create */, &root_path)); + ASSERT_TRUE(returned_root_path.size() > i); + EXPECT_EQ(returned_root_path[i].value(), root_path.value()); } } +TEST_F(FileSystemPathManagerTest, GetRootPathCreateAndExamineWithNewManager) { + std::vector<FilePath> returned_root_path( + ARRAYSIZE_UNSAFE(kRootPathTestCases)); + scoped_ptr<FileSystemPathManager> manager1(NewPathManager(false, false)); + scoped_ptr<FileSystemPathManager> manager2(NewPathManager(false, false)); + + GURL origin_url("http://foo.com:1/"); + + FilePath root_path1; + EXPECT_TRUE(GetRootPath(manager1.get(), origin_url, + kFileSystemTypeTemporary, true, &root_path1)); + FilePath root_path2; + EXPECT_TRUE(GetRootPath(manager2.get(), origin_url, + kFileSystemTypeTemporary, false, &root_path2)); + + EXPECT_EQ(root_path1.value(), root_path2.value()); +} + +TEST_F(FileSystemPathManagerTest, GetRootPathGetWithoutCreate) { + scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false)); + + // Try to get a root directory without creating. + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) { + SCOPED_TRACE(testing::Message() << "RootPath (create=false) #" << i << " " + << kRootPathTestCases[i].expected_path); + EXPECT_FALSE(GetRootPath(manager.get(), + GURL(kRootPathTestCases[i].origin_url), + kRootPathTestCases[i].type, + false /* create */, NULL)); + } +} + +TEST_F(FileSystemPathManagerTest, GetRootPathInIncognito) { + scoped_ptr<FileSystemPathManager> manager(NewPathManager( + true /* incognito */, false)); + + // Try to get a root directory. + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) { + SCOPED_TRACE(testing::Message() << "RootPath (incognito) #" << i << " " + << kRootPathTestCases[i].expected_path); + EXPECT_FALSE(GetRootPath(manager.get(), + GURL(kRootPathTestCases[i].origin_url), + kRootPathTestCases[i].type, + true /* create */, NULL)); + } +} + +TEST_F(FileSystemPathManagerTest, GetRootPathFileURI) { + scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false)); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathFileURITestCases); ++i) { + SCOPED_TRACE(testing::Message() << "RootPathFileURI (disallow) #" + << i << " " << kRootPathFileURITestCases[i].expected_path); + EXPECT_FALSE(GetRootPath(manager.get(), + GURL(kRootPathFileURITestCases[i].origin_url), + kRootPathFileURITestCases[i].type, + true /* create */, NULL)); + } +} + +TEST_F(FileSystemPathManagerTest, GetRootPathFileURIWithAllowFlag) { + scoped_ptr<FileSystemPathManager> manager(NewPathManager( + false, true /* allow_file_access_from_files */)); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathFileURITestCases); ++i) { + SCOPED_TRACE(testing::Message() << "RootPathFileURI (allow) #" + << i << " " << kRootPathFileURITestCases[i].expected_path); + FilePath root_path; + EXPECT_TRUE(GetRootPath(manager.get(), + GURL(kRootPathFileURITestCases[i].origin_url), + kRootPathFileURITestCases[i].type, + true /* create */, &root_path)); + FilePath expected = file_system_path().AppendASCII( + kRootPathFileURITestCases[i].expected_path); + EXPECT_EQ(expected.value(), root_path.DirName().value()); + EXPECT_TRUE(file_util::DirectoryExists(root_path)); + } +} + +TEST_F(FileSystemPathManagerTest, VirtualPathFromFileSystemPathTest) { + scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false)); + FilePath root_path; + EXPECT_TRUE(GetRootPath(manager.get(), GURL("http://foo.com/"), + fileapi::kFileSystemTypeTemporary, + true /* create */, &root_path)); + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kPathToVirtualPathTestCases); ++i) { + SCOPED_TRACE(testing::Message() << "PathToVirtualPath #" + << i << " " << kPathToVirtualPathTestCases[i]); + FilePath absolute_path = root_path.AppendASCII( + kPathToVirtualPathTestCases[i]); + FilePath virtual_path; + EXPECT_TRUE(manager->CrackFileSystemPath(absolute_path, NULL, NULL, + &virtual_path)); + + FilePath test_case_path; + test_case_path = test_case_path.AppendASCII( + kPathToVirtualPathTestCases[i]); + EXPECT_EQ(test_case_path.value(), virtual_path.value()); + } +} + +TEST_F(FileSystemPathManagerTest, TypeFromFileSystemPathTest) { + scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false)); + + FilePath root_path; + fileapi::FileSystemType type; + + EXPECT_TRUE(GetRootPath(manager.get(), GURL("http://foo.com/"), + fileapi::kFileSystemTypeTemporary, + true /* create */, &root_path)); + FilePath path = root_path.AppendASCII("test"); + EXPECT_TRUE(manager->CrackFileSystemPath(path, NULL, &type, NULL)); + EXPECT_EQ(fileapi::kFileSystemTypeTemporary, type); + + EXPECT_TRUE(GetRootPath(manager.get(), GURL("http://foo.com/"), + fileapi::kFileSystemTypePersistent, + true /* create */, &root_path)); + path = root_path.AppendASCII("test"); + EXPECT_TRUE(manager->CrackFileSystemPath(path, NULL, &type, NULL)); + EXPECT_EQ(fileapi::kFileSystemTypePersistent, type); +} + TEST_F(FileSystemPathManagerTest, CheckValidPath) { - FileSystemPathManager* manager = GetNewPathManager(false); + scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false)); FilePath root_path; - EXPECT_TRUE(manager->GetFileSystemRootPath( - GURL("http://foo.com/"), fileapi::kFileSystemTypePersistent, - &root_path, NULL)); + EXPECT_TRUE(GetRootPath(manager.get(), GURL("http://foo.com/"), + kFileSystemTypePersistent, true, &root_path)); // The root path must be valid, but upper directories or directories // that are not in our temporary or persistent directory must be // evaluated invalid. - EXPECT_TRUE(manager->CheckValidFileSystemPath(root_path)); - EXPECT_FALSE(manager->CheckValidFileSystemPath(root_path.DirName())); - EXPECT_FALSE(manager->CheckValidFileSystemPath( - root_path.DirName().DirName())); - EXPECT_FALSE(manager->CheckValidFileSystemPath( - root_path.DirName().AppendASCII("ArbitraryName"))); + EXPECT_TRUE(CheckValidFileSystemPath(manager.get(), root_path)); + EXPECT_FALSE(CheckValidFileSystemPath(manager.get(), root_path.DirName())); + EXPECT_FALSE(CheckValidFileSystemPath(manager.get(), + root_path.DirName().DirName())); + EXPECT_FALSE(CheckValidFileSystemPath(manager.get(), + root_path.DirName().DirName() + .AppendASCII("ArbitraryName") + .AppendASCII("chrome-dummy"))); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kCheckValidPathTestCases); ++i) { SCOPED_TRACE(testing::Message() << "CheckValidPath #" << i << " " @@ -192,12 +410,12 @@ TEST_F(FileSystemPathManagerTest, CheckValidPath) { if (!path.IsAbsolute()) path = root_path.Append(path); EXPECT_EQ(kCheckValidPathTestCases[i].expected_valid, - manager->CheckValidFileSystemPath(path)); + CheckValidFileSystemPath(manager.get(), path)); } } TEST_F(FileSystemPathManagerTest, IsRestrictedName) { - FileSystemPathManager* manager = GetNewPathManager(false); + scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false)); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kIsRestrictedNameTestCases); ++i) { SCOPED_TRACE(testing::Message() << "IsRestrictedName #" << i << " " << kIsRestrictedNameTestCases[i].name); diff --git a/webkit/fileapi/file_system_types.h b/webkit/fileapi/file_system_types.h index 5229f52..043e3a2 100644 --- a/webkit/fileapi/file_system_types.h +++ b/webkit/fileapi/file_system_types.h @@ -10,6 +10,7 @@ namespace fileapi { enum FileSystemType { kFileSystemTypeTemporary, kFileSystemTypePersistent, + kFileSystemTypeUnknown, }; } |