diff options
author | kerz@chromium.org <kerz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-20 22:19:17 +0000 |
---|---|---|
committer | kerz@chromium.org <kerz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-20 22:19:17 +0000 |
commit | eeed85c4662942e0c9e557d36fa0d26a938058e5 (patch) | |
tree | 3e6e267779cd0de15b1dfb8543e399023a4b1342 /webkit/fileapi | |
parent | fe2534f1d0294dadd3bc915982ef378906a2be57 (diff) | |
download | chromium_src-eeed85c4662942e0c9e557d36fa0d26a938058e5.zip chromium_src-eeed85c4662942e0c9e557d36fa0d26a938058e5.tar.gz chromium_src-eeed85c4662942e0c9e557d36fa0d26a938058e5.tar.bz2 |
Merge 82266 - Fixed file/directory url resolution for external mount point provider.Per Eric's request, refactored FileSystemDirURLRequestJob and FileSystemURLRequestJob classes to resolve local file system through a new operation.BUG=chromium-os:14225TEST=added new test cases to FileSystemPathManagerTest.*, added FileSystemOperationTest.TestGetLocalFilePathSuccessReview URL: http://codereview.chromium.org/6864040
TBR=zelidrag@chromium.org
Review URL: http://codereview.chromium.org/6882102
git-svn-id: svn://svn.chromium.org/chrome/branches/742/src@82372 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
30 files changed, 552 insertions, 190 deletions
diff --git a/webkit/fileapi/file_system_callback_dispatcher.cc b/webkit/fileapi/file_system_callback_dispatcher.cc index 1298979..618030b 100644 --- a/webkit/fileapi/file_system_callback_dispatcher.cc +++ b/webkit/fileapi/file_system_callback_dispatcher.cc @@ -17,4 +17,8 @@ void FileSystemCallbackDispatcher::DidOpenFile( NOTREACHED(); } +void FileSystemCallbackDispatcher::DidGetLocalPath(const FilePath& local_path) { + NOTREACHED(); +} + } // namespace fileapi diff --git a/webkit/fileapi/file_system_callback_dispatcher.h b/webkit/fileapi/file_system_callback_dispatcher.h index e2d3caa..63824ed 100644 --- a/webkit/fileapi/file_system_callback_dispatcher.h +++ b/webkit/fileapi/file_system_callback_dispatcher.h @@ -58,6 +58,11 @@ class FileSystemCallbackDispatcher { virtual void DidOpenFile( base::PlatformFile file, base::ProcessHandle peer_handle); + + // Callback for the real local platform path lookup, where possible. + // This isn't in WebFileSystemCallbacks. + virtual void DidGetLocalPath(const FilePath& local_path); + }; } // namespace fileapi diff --git a/webkit/fileapi/file_system_context.cc b/webkit/fileapi/file_system_context.cc index 205963a..7e0d62e 100644 --- a/webkit/fileapi/file_system_context.cc +++ b/webkit/fileapi/file_system_context.cc @@ -20,17 +20,21 @@ FileSystemContext::FileSystemContext( const FilePath& profile_path, bool is_incognito, bool allow_file_access, - bool unlimited_quota) + bool unlimited_quota, + FileSystemPathManager* path_manager) : file_message_loop_(file_message_loop), io_message_loop_(io_message_loop), special_storage_policy_(special_storage_policy), allow_file_access_from_files_(allow_file_access), unlimited_quota_(unlimited_quota), - path_manager_(new FileSystemPathManager( - file_message_loop, profile_path, special_storage_policy, is_incognito, - allow_file_access)), + path_manager_(path_manager), usage_tracker_(new FileSystemUsageTracker( file_message_loop, profile_path, is_incognito)) { + if (!path_manager) { + path_manager_.reset(new FileSystemPathManager( + file_message_loop, profile_path, special_storage_policy, + is_incognito, allow_file_access)); + } } FileSystemContext::~FileSystemContext() { diff --git a/webkit/fileapi/file_system_context.h b/webkit/fileapi/file_system_context.h index cb4d207..aa1804a 100644 --- a/webkit/fileapi/file_system_context.h +++ b/webkit/fileapi/file_system_context.h @@ -37,7 +37,8 @@ class FileSystemContext const FilePath& profile_path, bool is_incognito, bool allow_file_access_from_files, - bool unlimited_quota); + bool unlimited_quota, + FileSystemPathManager* path_manager); ~FileSystemContext(); // This method can be called on any thread. diff --git a/webkit/fileapi/file_system_context_unittest.cc b/webkit/fileapi/file_system_context_unittest.cc index f1fff68..30ec54e 100644 --- a/webkit/fileapi/file_system_context_unittest.cc +++ b/webkit/fileapi/file_system_context_unittest.cc @@ -47,7 +47,7 @@ scoped_refptr<FileSystemContext> NewFileSystemContext( base::MessageLoopProxy::CreateForCurrentThread(), special_storage_policy, FilePath(), false /* is_incognito */, - allow_file_access, unlimited_quota); + allow_file_access, unlimited_quota, NULL); } } // anonymous namespace diff --git a/webkit/fileapi/file_system_dir_url_request_job.cc b/webkit/fileapi/file_system_dir_url_request_job.cc index d61dac0..fb75edf 100644 --- a/webkit/fileapi/file_system_dir_url_request_job.cc +++ b/webkit/fileapi/file_system_dir_url_request_job.cc @@ -19,6 +19,8 @@ #include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/url_request/url_request.h" +#include "webkit/fileapi/file_system_callback_dispatcher.h" +#include "webkit/fileapi/file_system_operation.h" #include "webkit/fileapi/file_system_path_manager.h" #include "webkit/fileapi/file_system_util.h" @@ -29,29 +31,17 @@ using net::URLRequestStatus; namespace fileapi { FileSystemDirURLRequestJob::FileSystemDirURLRequestJob( - URLRequest* request, FileSystemPathManager* path_manager, + URLRequest* request, FileSystemContext* file_system_context, scoped_refptr<base::MessageLoopProxy> file_thread_proxy) - : URLRequestJob(request), - path_manager_(path_manager), + : FileSystemURLRequestJobBase(request, file_system_context, + file_thread_proxy), ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), - ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), - file_thread_proxy_(file_thread_proxy) { + ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)) { } FileSystemDirURLRequestJob::~FileSystemDirURLRequestJob() { } -void FileSystemDirURLRequestJob::Start() { - MessageLoop::current()->PostTask(FROM_HERE, - method_factory_.NewRunnableMethod( - &FileSystemDirURLRequestJob::StartAsync)); -} - -void FileSystemDirURLRequestJob::Kill() { - URLRequestJob::Kill(); - callback_factory_.RevokeAll(); -} - bool FileSystemDirURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size, int *bytes_read) { @@ -64,47 +54,33 @@ bool FileSystemDirURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size, return true; } -bool FileSystemDirURLRequestJob::GetMimeType(std::string* mime_type) const { - *mime_type = "text/html"; - return true; +void FileSystemDirURLRequestJob::Start() { + MessageLoop::current()->PostTask(FROM_HERE, + method_factory_.NewRunnableMethod( + &FileSystemURLRequestJobBase::StartAsync)); } -bool FileSystemDirURLRequestJob::GetCharset(std::string* charset) { - *charset = "utf-8"; - return true; +void FileSystemDirURLRequestJob::Kill() { + URLRequestJob::Kill(); + callback_factory_.RevokeAll(); } -void FileSystemDirURLRequestJob::StartAsync() { - GURL origin_url; - FileSystemType type; - if (!CrackFileSystemURL(request_->url(), &origin_url, &type, - &relative_dir_path_)) { - NotifyFailed(net::ERR_INVALID_URL); - return; - } - - path_manager_->GetFileSystemRootPath( - origin_url, type, false, // create +void FileSystemDirURLRequestJob::DidGetLocalPath( + const FilePath& local_path) { + absolute_file_path_ = local_path; + base::FileUtilProxy::ReadDirectory(file_thread_proxy_, absolute_file_path_, callback_factory_.NewCallback( - &FileSystemDirURLRequestJob::DidGetRootPath)); + &FileSystemDirURLRequestJob::DidReadDirectory)); } -void FileSystemDirURLRequestJob::DidGetRootPath(bool success, - const FilePath& root_path, - const std::string& name) { - if (!success) { - NotifyFailed(net::ERR_FILE_NOT_FOUND); - return; - } - - absolute_dir_path_ = root_path.Append(relative_dir_path_); +bool FileSystemDirURLRequestJob::GetMimeType(std::string* mime_type) const { + *mime_type = "text/html"; + return true; +} - // We assume it's a directory if we've gotten here: either the path - // ends with '/', or FileSystemDirURLRequestJob already statted it and - // found it to be a directory. - base::FileUtilProxy::ReadDirectory(file_thread_proxy_, absolute_dir_path_, - callback_factory_.NewCallback( - &FileSystemDirURLRequestJob::DidReadDirectory)); +bool FileSystemDirURLRequestJob::GetCharset(std::string* charset) { + *charset = "utf-8"; + return true; } void FileSystemDirURLRequestJob::DidReadDirectory( @@ -116,10 +92,10 @@ void FileSystemDirURLRequestJob::DidReadDirectory( } #if defined(OS_WIN) - const string16& title = relative_dir_path_.value(); + const string16& title = relative_file_path_.value(); #elif defined(OS_POSIX) const string16& title = WideToUTF16( - base::SysNativeMBToWide(relative_dir_path_.value())); + base::SysNativeMBToWide(relative_file_path_.value())); #endif data_.append(net::GetDirectoryListingHeader(ASCIIToUTF16("/") + title)); @@ -140,8 +116,4 @@ void FileSystemDirURLRequestJob::DidReadDirectory( NotifyHeadersComplete(); } -void FileSystemDirURLRequestJob::NotifyFailed(int rv) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); -} - } // namespace fileapi diff --git a/webkit/fileapi/file_system_dir_url_request_job.h b/webkit/fileapi/file_system_dir_url_request_job.h index 3c0bfbb..e9f566f 100644 --- a/webkit/fileapi/file_system_dir_url_request_job.h +++ b/webkit/fileapi/file_system_dir_url_request_job.h @@ -16,15 +16,17 @@ #include "base/platform_file.h" #include "base/task.h" #include "net/url_request/url_request_job.h" +#include "webkit/fileapi/file_system_url_request_job_base.h" namespace fileapi { -class FileSystemPathManager; +class FileSystemContext; +class FileSystemOperation; // A request job that handles reading filesystem: URLs for directories. -class FileSystemDirURLRequestJob : public net::URLRequestJob { +class FileSystemDirURLRequestJob : public FileSystemURLRequestJobBase { public: FileSystemDirURLRequestJob( - net::URLRequest* request, FileSystemPathManager* path_manager, + net::URLRequest* request, FileSystemContext* file_system_context, scoped_refptr<base::MessageLoopProxy> file_thread_proxy); // URLRequestJob methods: @@ -38,25 +40,19 @@ class FileSystemDirURLRequestJob : public net::URLRequestJob { // TODO(adamk): Implement GetResponseInfo and GetResponseCode to simulate // an HTTP response. - private: + protected: + // FileSystemURLRequestJobBase methods. + virtual void DidGetLocalPath(const FilePath& local_path); + virtual ~FileSystemDirURLRequestJob(); - void StartAsync(); - void DidGetRootPath(bool success, const FilePath& root_path, - const std::string& name); void DidReadDirectory(base::PlatformFileError error_code, const std::vector<base::FileUtilProxy::Entry>& entries); - - void NotifyFailed(int rv); + fileapi::FileSystemOperation* GetNewOperation(); std::string data_; - FilePath relative_dir_path_; - FilePath absolute_dir_path_; - FileSystemPathManager* const path_manager_; - ScopedRunnableMethodFactory<FileSystemDirURLRequestJob> method_factory_; base::ScopedCallbackFactory<FileSystemDirURLRequestJob> callback_factory_; - scoped_refptr<base::MessageLoopProxy> file_thread_proxy_; DISALLOW_COPY_AND_ASSIGN(FileSystemDirURLRequestJob); }; diff --git a/webkit/fileapi/file_system_dir_url_request_job_unittest.cc b/webkit/fileapi/file_system_dir_url_request_job_unittest.cc index 6bbd688..6b2882b 100644 --- a/webkit/fileapi/file_system_dir_url_request_job_unittest.cc +++ b/webkit/fileapi/file_system_dir_url_request_job_unittest.cc @@ -27,6 +27,7 @@ #include "net/url_request/url_request.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webkit/fileapi/file_system_context.h" #include "webkit/fileapi/file_system_path_manager.h" namespace fileapi { @@ -35,6 +36,21 @@ namespace { // We always use the TEMPORARY FileSystem in this test. static const char kFileSystemURLPrefix[] = "filesystem:http://remote/temporary/"; +class TestSpecialStoragePolicy : public quota::SpecialStoragePolicy { + public: + virtual bool IsStorageProtected(const GURL& origin) { + return false; + } + + virtual bool IsStorageUnlimited(const GURL& origin) { + return true; + } + + virtual bool IsFileHandler(const std::string& extension_id) { + return true; + } +}; + class FileSystemDirURLRequestJobTest : public testing::Test { protected: FileSystemDirURLRequestJobTest() @@ -47,11 +63,19 @@ class FileSystemDirURLRequestJobTest : public testing::Test { file_thread_proxy_ = base::MessageLoopProxy::CreateForCurrentThread(); - path_manager_.reset(new FileSystemPathManager( - file_thread_proxy_, temp_dir_.path(), - NULL, false, false)); - - path_manager_->GetFileSystemRootPath( + special_storage_policy_ = new TestSpecialStoragePolicy(); + file_system_context_ = + new FileSystemContext( + base::MessageLoopProxy::CreateForCurrentThread(), + base::MessageLoopProxy::CreateForCurrentThread(), + special_storage_policy_, + FilePath(), false /* is_incognito */, + false, true, + new FileSystemPathManager( + file_thread_proxy_, temp_dir_.path(), + NULL, false, false)); + + file_system_context_->path_manager()->ValidateFileSystemRootAndGetURL( GURL("http://remote/"), kFileSystemTypeTemporary, true, // create callback_factory_.NewCallback( &FileSystemDirURLRequestJobTest::OnGetRootPath)); @@ -80,7 +104,7 @@ class FileSystemDirURLRequestJobTest : public testing::Test { delegate_->set_quit_on_redirect(true); request_.reset(new net::URLRequest(url, delegate_.get())); job_ = new FileSystemDirURLRequestJob(request_.get(), - path_manager_.get(), + file_system_context_.get(), file_thread_proxy_); request_->Start(); @@ -110,7 +134,8 @@ class FileSystemDirURLRequestJobTest : public testing::Test { FilePath root_path_; scoped_ptr<net::URLRequest> request_; scoped_ptr<TestDelegate> delegate_; - scoped_ptr<FileSystemPathManager> path_manager_; + scoped_refptr<TestSpecialStoragePolicy> special_storage_policy_; + scoped_refptr<FileSystemContext> file_system_context_; scoped_refptr<base::MessageLoopProxy> file_thread_proxy_; MessageLoop message_loop_; diff --git a/webkit/fileapi/file_system_file_util.cc b/webkit/fileapi/file_system_file_util.cc index aadc1cb..f012a33 100644 --- a/webkit/fileapi/file_system_file_util.cc +++ b/webkit/fileapi/file_system_file_util.cc @@ -61,6 +61,14 @@ PlatformFileError FileSystemFileUtil::EnsureFileExists( return error_code; } +PlatformFileError FileSystemFileUtil::GetLocalFilePath( + FileSystemOperationContext* context, + const FilePath& virtual_path, + FilePath* local_path) { + *local_path = virtual_path; + return base::PLATFORM_FILE_OK; +} + PlatformFileError FileSystemFileUtil::GetFileInfo( FileSystemOperationContext* unused, const FilePath& file_path, diff --git a/webkit/fileapi/file_system_file_util.h b/webkit/fileapi/file_system_file_util.h index 1169d02..9e62af3 100644 --- a/webkit/fileapi/file_system_file_util.h +++ b/webkit/fileapi/file_system_file_util.h @@ -13,6 +13,7 @@ #include "base/memory/singleton.h" #include "base/platform_file.h" #include "base/tracked_objects.h" +#include "webkit/fileapi/file_system_types.h" namespace base { struct PlatformFileInfo; @@ -24,7 +25,6 @@ namespace fileapi { using base::PlatformFile; using base::PlatformFileError; - class FileSystemOperationContext; // A large part of this implementation is taken from base::FileUtilProxy. @@ -64,6 +64,14 @@ class FileSystemFileUtil { FileSystemOperationContext* context, const FilePath& file_path, bool* created); + // Maps |virtual_path| given |context| into |local_path| which represents + // physical file location on the host OS. This may not always make sense for + // all subclasses. + virtual PlatformFileError GetLocalFilePath( + FileSystemOperationContext* context, + const FilePath& virtual_path, + FilePath* local_path); + // Retrieves the information about a file. It is invalid to pass NULL for the // callback. virtual PlatformFileError GetFileInfo( diff --git a/webkit/fileapi/file_system_file_util_proxy.cc b/webkit/fileapi/file_system_file_util_proxy.cc index 06a61c4..e5f8628 100644 --- a/webkit/fileapi/file_system_file_util_proxy.cc +++ b/webkit/fileapi/file_system_file_util_proxy.cc @@ -192,6 +192,37 @@ class RelayEnsureFileExists : public MessageLoopRelay { bool created_; }; + +class RelayGetLocalPath : public MessageLoopRelay { + public: + RelayGetLocalPath( + const fileapi::FileSystemOperationContext& context, + const FilePath& virtual_path, + fileapi::FileSystemFileUtilProxy::GetLocalPathCallback* callback) + : MessageLoopRelay(context), + callback_(callback), + virtual_path_(virtual_path) { + DCHECK(callback); + } + + protected: + virtual void RunWork() { + set_error_code( + file_system_file_util()->GetLocalFilePath( + context(), virtual_path_, &local_path_)); + } + + virtual void RunCallback() { + callback_->Run(error_code(), local_path_); + delete callback_; + } + + private: + fileapi::FileSystemFileUtilProxy::GetLocalPathCallback* callback_; + FilePath virtual_path_; + FilePath local_path_; +}; + class RelayGetFileInfo : public MessageLoopRelay { public: RelayGetFileInfo( @@ -437,8 +468,17 @@ bool FileSystemFileUtilProxy::EnsureFileExists( context, message_loop_proxy, file_path, callback)); } -// Retrieves the information about a file. It is invalid to pass NULL for the -// callback. +// static +bool FileSystemFileUtilProxy::GetLocalPath( + const FileSystemOperationContext& context, + scoped_refptr<MessageLoopProxy> message_loop_proxy, + const FilePath& virtual_path, + GetLocalPathCallback* callback) { + return Start(FROM_HERE, message_loop_proxy, + new RelayGetLocalPath(context, virtual_path, callback)); +} + +// static bool FileSystemFileUtilProxy::GetFileInfo( const FileSystemOperationContext& context, scoped_refptr<MessageLoopProxy> message_loop_proxy, diff --git a/webkit/fileapi/file_system_file_util_proxy.h b/webkit/fileapi/file_system_file_util_proxy.h index de4b320..e376314 100644 --- a/webkit/fileapi/file_system_file_util_proxy.h +++ b/webkit/fileapi/file_system_file_util_proxy.h @@ -40,6 +40,9 @@ class FileSystemFileUtilProxy { const PlatformFileInfo& /* file_info */, const FilePath& /* platform_path, where possible */ >::Type GetFileInfoCallback; + typedef Callback2<PlatformFileError /* error code */, + const FilePath& /* local_path, where possible */ + >::Type GetLocalPathCallback; typedef base::FileUtilProxy::ReadDirectoryCallback ReadDirectoryCallback; // Creates or opens a file with the given flags. It is invalid to pass NULL @@ -74,6 +77,13 @@ class FileSystemFileUtilProxy { const FilePath& file_path, EnsureFileExistsCallback* callback); + // Maps virtual file patch to its local physical location. + static bool GetLocalPath( + const FileSystemOperationContext& context, + scoped_refptr<MessageLoopProxy> message_loop_proxy, + const FilePath& virtual_path, + GetLocalPathCallback* callback); + // Retrieves the information about a file. It is invalid to pass NULL for the // callback. static bool GetFileInfo( diff --git a/webkit/fileapi/file_system_mount_point_provider.h b/webkit/fileapi/file_system_mount_point_provider.h index e331991..50e0d39 100644 --- a/webkit/fileapi/file_system_mount_point_provider.h +++ b/webkit/fileapi/file_system_mount_point_provider.h @@ -29,7 +29,7 @@ class FileSystemMountPointProvider { // 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. - virtual void GetFileSystemRootPath( + virtual void ValidateFileSystemRootAndGetURL( const GURL& origin_url, FileSystemType type, bool create, @@ -37,7 +37,7 @@ class FileSystemMountPointProvider { // Like GetFileSystemRootPath, but synchronous, and can be called only while // running on the file thread. - virtual FilePath GetFileSystemRootPathOnFileThread( + virtual FilePath ValidateFileSystemRootAndGetPathOnFileThread( const GURL& origin_url, FileSystemType type, const FilePath& virtual_path, @@ -67,6 +67,10 @@ class ExternalFileSystemMountPointProvider // Revoke file access from extension identified with |extension_id|. virtual void RevokeAccessForExtension( const std::string& extension_id) = 0; + // Adds a new mount point. + virtual void AddMountPoint(FilePath mount_point) = 0; + // Remove a mount point. + virtual void RemoveMountPoint(FilePath mount_point) = 0; }; } // namespace fileapi diff --git a/webkit/fileapi/file_system_operation.cc b/webkit/fileapi/file_system_operation.cc index 15f8955..046a16f 100644 --- a/webkit/fileapi/file_system_operation.cc +++ b/webkit/fileapi/file_system_operation.cc @@ -60,7 +60,7 @@ void FileSystemOperation::OpenFileSystem( // create an unpredictable directory name. Without that, we could lazily // create the root later on the first filesystem write operation, and just // return GetFileSystemRootURI() here. - file_system_context()->path_manager()->GetFileSystemRootPath( + file_system_context()->path_manager()->ValidateFileSystemRootAndGetURL( origin_url, type, create, callback_factory_.NewCallback(&FileSystemOperation::DidGetRootPath)); } @@ -232,6 +232,27 @@ void FileSystemOperation::FileExists(const GURL& path) { &FileSystemOperation::DidFileExists)); } +void FileSystemOperation::GetLocalPath(const GURL& path) { +#ifndef NDEBUG + DCHECK(kOperationNone == pending_operation_); + pending_operation_ = kOperationGetLocalPath; +#endif + + FilePath virtual_path; + GURL origin_url; + FileSystemType type; + if (!VerifyFileSystemPathForRead(path, &origin_url, &type, &virtual_path)) { + delete this; + return; + } + file_system_operation_context_.set_src_origin_url(origin_url); + file_system_operation_context_.set_src_type(type); + FileSystemFileUtilProxy::GetLocalPath( + file_system_operation_context_, + proxy_, virtual_path, callback_factory_.NewCallback( + &FileSystemOperation::DidGetLocalPath)); +} + void FileSystemOperation::GetMetadata(const GURL& path) { #ifndef NDEBUG DCHECK(kOperationNone == pending_operation_); @@ -531,6 +552,16 @@ void FileSystemOperation::DidFileExists( delete this; } +void FileSystemOperation::DidGetLocalPath( + base::PlatformFileError rv, + const FilePath& local_path) { + if (rv == base::PLATFORM_FILE_OK) + dispatcher_->DidGetLocalPath(local_path); + else + dispatcher_->DidFail(rv); + delete this; +} + void FileSystemOperation::DidGetMetadata( base::PlatformFileError rv, const base::PlatformFileInfo& file_info, @@ -623,7 +654,7 @@ bool FileSystemOperation::VerifyFileSystemPathForRead( // We may want do more checks, but for now it just checks if the given // URL is valid. if (!CrackFileSystemURL(path, origin_url, type, virtual_path)) { - dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); + dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_INVALID_URL); return false; } if (!file_system_context()->path_manager()->IsAccessAllowed( @@ -660,7 +691,7 @@ bool FileSystemOperation::VerifyFileSystemPathForWrite( } if (!CrackFileSystemURL(path, origin_url, type, virtual_path)) { - dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); + dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_INVALID_URL); return false; } if (!file_system_context()->path_manager()->IsAccessAllowed( diff --git a/webkit/fileapi/file_system_operation.h b/webkit/fileapi/file_system_operation.h index c726403..654b596 100644 --- a/webkit/fileapi/file_system_operation.h +++ b/webkit/fileapi/file_system_operation.h @@ -84,6 +84,7 @@ class FileSystemOperation { const GURL& path, int file_flags, base::ProcessHandle peer_handle); + void GetLocalPath(const GURL& path); // Try to cancel the current operation [we support cancelling write or // truncate only]. Report failure for the current operation, then tell the @@ -138,6 +139,8 @@ class FileSystemOperation { base::PlatformFileError rv, base::PassPlatformFile file, bool created); + void DidGetLocalPath(base::PlatformFileError rv, + const FilePath& local_path); // Helper for Write(). void OnFileOpenedForWrite( @@ -194,6 +197,7 @@ class FileSystemOperation { kOperationTruncate, kOperationTouchFile, kOperationOpenFile, + kOperationGetLocalPath, kOperationCancel, }; diff --git a/webkit/fileapi/file_system_operation_unittest.cc b/webkit/fileapi/file_system_operation_unittest.cc index 292104b..934504d 100644 --- a/webkit/fileapi/file_system_operation_unittest.cc +++ b/webkit/fileapi/file_system_operation_unittest.cc @@ -4,14 +4,19 @@ #include "webkit/fileapi/file_system_operation.h" +#include "base/file_util.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_temp_dir.h" #include "base/message_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/fileapi/file_system_callback_dispatcher.h" +#include "webkit/fileapi/file_system_context.h" #include "webkit/fileapi/file_system_file_util.h" +#include "webkit/fileapi/file_system_mount_point_provider.h" #include "webkit/fileapi/file_system_operation.h" +#include "webkit/fileapi/file_system_path_manager.h" +#include "webkit/fileapi/file_system_util.h" namespace fileapi { @@ -39,6 +44,8 @@ class FileSystemOperationTest : public testing::Test { FileSystemOperation* operation(); + void set_local_path(const FilePath& path) { local_path_ = path; } + const FilePath& local_path() const { return local_path_; } void set_status(int status) { status_ = status; } int status() const { return status_; } void set_info(const base::PlatformFileInfo& info) { info_ = info; } @@ -70,6 +77,7 @@ class FileSystemOperationTest : public testing::Test { int status_; base::PlatformFileInfo info_; FilePath path_; + FilePath local_path_; std::vector<base::FileUtilProxy::Entry> entries_; DISALLOW_COPY_AND_ASSIGN(FileSystemOperationTest); @@ -87,6 +95,11 @@ class MockDispatcher : public FileSystemCallbackDispatcher { test_->set_status(kFileOperationSucceeded); } + virtual void DidGetLocalPath(const FilePath& local_path) { + test_->set_local_path(local_path); + test_->set_status(kFileOperationSucceeded); + } + virtual void DidReadMetadata( const base::PlatformFileInfo& info, const FilePath& platform_path) { @@ -126,6 +139,7 @@ FileSystemOperation* FileSystemOperationTest::operation() { GURL origin_url("fake://fake.foo/"); operation->file_system_operation_context()->set_src_origin_url(origin_url); operation->file_system_operation_context()->set_dest_origin_url(origin_url); + return operation; } @@ -610,6 +624,22 @@ TEST_F(FileSystemOperationTest, TestExistsAndMetadataSuccess) { EXPECT_EQ(file, path()); } +TEST_F(FileSystemOperationTest, TestGetLocalFilePathSuccess) { + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + operation()->GetLocalPath(URLForPath(dir.path())); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, status()); + EXPECT_EQ(local_path().value(), dir.path().value()); + + FilePath file; + file_util::CreateTemporaryFileInDir(dir.path(), &file); + operation()->GetLocalPath(URLForPath(file)); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, status()); + EXPECT_EQ(local_path().value(), file.value()); +} + TEST_F(FileSystemOperationTest, TestTypeMismatchErrors) { ScopedTempDir dir; ASSERT_TRUE(dir.CreateUniqueTempDir()); diff --git a/webkit/fileapi/file_system_operation_write_unittest.cc b/webkit/fileapi/file_system_operation_write_unittest.cc index c387f4a..b6389a4 100644 --- a/webkit/fileapi/file_system_operation_write_unittest.cc +++ b/webkit/fileapi/file_system_operation_write_unittest.cc @@ -115,6 +115,10 @@ class MockDispatcher : public FileSystemCallbackDispatcher { ADD_FAILURE(); } + virtual void DidGetLocalPath(const FilePath& local_path) { + ADD_FAILURE(); + } + virtual void DidReadMetadata( const base::PlatformFileInfo& info, const FilePath& platform_path) { diff --git a/webkit/fileapi/file_system_path_manager.cc b/webkit/fileapi/file_system_path_manager.cc index cefdab8..898a5fa 100644 --- a/webkit/fileapi/file_system_path_manager.cc +++ b/webkit/fileapi/file_system_path_manager.cc @@ -54,19 +54,19 @@ FileSystemPathManager::FileSystemPathManager( FileSystemPathManager::~FileSystemPathManager() {} -void FileSystemPathManager::GetFileSystemRootPath( +void FileSystemPathManager::ValidateFileSystemRootAndGetURL( const GURL& origin_url, fileapi::FileSystemType type, bool create, GetRootPathCallback* callback_ptr) { switch (type) { case kFileSystemTypeTemporary: case kFileSystemTypePersistent: - sandbox_provider_->GetFileSystemRootPath( + sandbox_provider_->ValidateFileSystemRootAndGetURL( origin_url, type, create, callback_ptr); break; case kFileSystemTypeExternal: if (external_provider_.get()) { - external_provider_->GetFileSystemRootPath( + external_provider_->ValidateFileSystemRootAndGetURL( origin_url, type, create, callback_ptr); } else { callback_ptr->Run(false, FilePath(), std::string()); @@ -79,18 +79,18 @@ void FileSystemPathManager::GetFileSystemRootPath( } } -FilePath FileSystemPathManager::GetFileSystemRootPathOnFileThread( +FilePath FileSystemPathManager::ValidateFileSystemRootAndGetPathOnFileThread( const GURL& origin_url, FileSystemType type, const FilePath& virtual_path, bool create) { switch (type) { case kFileSystemTypeTemporary: case kFileSystemTypePersistent: - return sandbox_provider_->GetFileSystemRootPathOnFileThread( + return sandbox_provider_->ValidateFileSystemRootAndGetPathOnFileThread( origin_url, type, virtual_path, create); break; case kFileSystemTypeExternal: return external_provider_.get() ? - external_provider_->GetFileSystemRootPathOnFileThread( + external_provider_->ValidateFileSystemRootAndGetPathOnFileThread( origin_url, type, virtual_path, create) : FilePath(); case kFileSystemTypeUnknown: diff --git a/webkit/fileapi/file_system_path_manager.h b/webkit/fileapi/file_system_path_manager.h index f914a7d..1dc86a9 100644 --- a/webkit/fileapi/file_system_path_manager.h +++ b/webkit/fileapi/file_system_path_manager.h @@ -55,15 +55,15 @@ class FileSystemPathManager { // 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. - virtual void GetFileSystemRootPath(const GURL& origin_url, - FileSystemType type, - bool create, - FileSystemPathManager::GetRootPathCallback* - callback); + virtual void ValidateFileSystemRootAndGetURL( + const GURL& origin_url, + FileSystemType type, + bool create, + FileSystemPathManager::GetRootPathCallback* callback); // Like GetFileSystemRootPath, but synchronous, and can be called only while // running on the file thread. - virtual FilePath GetFileSystemRootPathOnFileThread( + virtual FilePath ValidateFileSystemRootAndGetPathOnFileThread( const GURL& origin_url, FileSystemType type, const FilePath& virtual_path, diff --git a/webkit/fileapi/file_system_path_manager_unittest.cc b/webkit/fileapi/file_system_path_manager_unittest.cc index dbdef10..e36a97e 100644 --- a/webkit/fileapi/file_system_path_manager_unittest.cc +++ b/webkit/fileapi/file_system_path_manager_unittest.cc @@ -15,6 +15,8 @@ #include "base/memory/scoped_temp_dir.h" #include "base/message_loop.h" #include "base/message_loop_proxy.h" +#include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" #include "googleurl/src/gurl.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/fileapi/file_system_util.h" @@ -59,19 +61,26 @@ const struct RootPathTest { "https_bar.com_0" PS "Temporary" }, { fileapi::kFileSystemTypePersistent, "https://bar.com/", "https_bar.com_0" PS "Persistent" }, +#if defined(OS_CHROMEOS) + { fileapi::kFileSystemTypeExternal, "chrome-extension://foo/", + "chrome-extension__0" PS "External" }, +#endif }; const struct RootPathFileURITest { fileapi::FileSystemType type; const char* origin_url; const char* expected_path; + const char* virtual_path; } kRootPathFileURITestCases[] = { { fileapi::kFileSystemTypeTemporary, "file:///", - "file__0" PS "Temporary" }, + "file__0" PS "Temporary", NULL }, { fileapi::kFileSystemTypePersistent, "file:///", - "file__0" PS "Persistent" }, - // TODO(zelidrag): Add fileapi::kFileSystemTypeLocal test cases here once - // we fix ChromeOS build of this test. + "file__0" PS "Persistent", NULL }, +#if defined(OS_CHROMEOS) + { fileapi::kFileSystemTypeExternal, "chrome-extension://foo/", + "chrome-extension__0" PS "External", "testing" }, +#endif }; const struct CheckValidPathTest { @@ -163,6 +172,16 @@ const struct IsRestrictedNameTest { { FILE_PATH_LITERAL("|ab"), true, }, }; +FilePath UTF8ToFilePath(const std::string& str) { + FilePath::StringType result; +#if defined(OS_POSIX) + result = base::SysWideToNativeMB(UTF8ToWide(str)); +#elif defined(OS_WIN) + result = UTF8ToUTF16(str); +#endif + return FilePath(result); +} + class TestSpecialStoragePolicy : public quota::SpecialStoragePolicy { public: virtual bool IsStorageProtected(const GURL& origin) { @@ -197,18 +216,24 @@ class FileSystemPathManagerTest : public testing::Test { FileSystemPathManager* NewPathManager( bool incognito, bool allow_file_access) { - return new FileSystemPathManager( + FileSystemPathManager* manager = new FileSystemPathManager( base::MessageLoopProxy::CreateForCurrentThread(), data_dir_.path(), scoped_refptr<quota::SpecialStoragePolicy>( new TestSpecialStoragePolicy()), incognito, allow_file_access); +#if defined(OS_CHROMEOS) + fileapi::ExternalFileSystemMountPointProvider* ext_provider = + manager->external_provider(); + ext_provider->AddMountPoint(FilePath("/tmp/testing")); +#endif + return manager; } void OnGetRootPath(bool success, - const FilePath& root_path, - const std::string& name) { + const FilePath& root_path, + const std::string& name) { root_path_callback_status_ = success; root_path_ = root_path; file_system_name_ = name; @@ -219,7 +244,7 @@ class FileSystemPathManagerTest : public testing::Test { fileapi::FileSystemType type, bool create, FilePath* root_path) { - manager->GetFileSystemRootPath(origin_url, type, create, + manager->ValidateFileSystemRootAndGetURL(origin_url, type, create, callback_factory_.NewCallback( &FileSystemPathManagerTest::OnGetRootPath)); MessageLoop::current()->RunAllPending(); @@ -233,6 +258,12 @@ class FileSystemPathManagerTest : public testing::Test { return data_dir_.path().Append( SandboxMountPointProvider::kFileSystemDirectory); } + FilePath external_file_system_path() { + return UTF8ToFilePath(std::string(fileapi::kExternalDir)); + } + FilePath external_file_path_root() { + return UTF8ToFilePath(std::string("/tmp")); + } private: ScopedTempDir data_dir_; @@ -261,10 +292,17 @@ TEST_F(FileSystemPathManagerTest, GetRootPathCreateAndExamine) { 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)); + if (kRootPathTestCases[i].type != fileapi::kFileSystemTypeExternal) { + 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 + // anything from the actual file system. + EXPECT_EQ(external_file_system_path().value(), + root_path.value()); + } ASSERT_TRUE(returned_root_path.size() > i); returned_root_path[i] = root_path; } @@ -355,10 +393,14 @@ TEST_F(FileSystemPathManagerTest, GetRootPathFileURIWithAllowFlag) { 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)); + if (kRootPathFileURITestCases[i].type != fileapi::kFileSystemTypeExternal) { + 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)); + } else { + EXPECT_EQ(external_file_path_root().value(), root_path.value()); + } } } diff --git a/webkit/fileapi/file_system_url_request_job.cc b/webkit/fileapi/file_system_url_request_job.cc index 81f6939..6b4732a 100644 --- a/webkit/fileapi/file_system_url_request_job.cc +++ b/webkit/fileapi/file_system_url_request_job.cc @@ -50,18 +50,17 @@ static net::HttpResponseHeaders* CreateHttpResponseHeaders() { } FileSystemURLRequestJob::FileSystemURLRequestJob( - URLRequest* request, FileSystemPathManager* path_manager, + URLRequest* request, FileSystemContext* file_system_context, scoped_refptr<base::MessageLoopProxy> file_thread_proxy) - : URLRequestJob(request), - path_manager_(path_manager), + : FileSystemURLRequestJobBase(request, file_system_context, + file_thread_proxy), + ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), + ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), ALLOW_THIS_IN_INITIALIZER_LIST( io_callback_(this, &FileSystemURLRequestJob::DidRead)), stream_(NULL), is_directory_(false), - remaining_bytes_(0), - ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), - ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), - file_thread_proxy_(file_thread_proxy) { + remaining_bytes_(0) { } FileSystemURLRequestJob::~FileSystemURLRequestJob() { @@ -82,7 +81,6 @@ void FileSystemURLRequestJob::Kill() { stream_->Close(); stream_.reset(NULL); } - URLRequestJob::Kill(); callback_factory_.RevokeAll(); } @@ -148,6 +146,12 @@ void FileSystemURLRequestJob::SetExtraRequestHeaders( } } +void FileSystemURLRequestJob::DidGetLocalPath(const FilePath& local_path) { + absolute_file_path_ = local_path; + base::FileUtilProxy::GetFileInfo(file_thread_proxy_, absolute_file_path_, + callback_factory_.NewCallback(&FileSystemURLRequestJob::DidResolve)); +} + void FileSystemURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { if (response_info_.get()) *info = *response_info_; @@ -159,34 +163,6 @@ int FileSystemURLRequestJob::GetResponseCode() const { return URLRequestJob::GetResponseCode(); } -void FileSystemURLRequestJob::StartAsync() { - GURL origin_url; - FileSystemType type; - if (!CrackFileSystemURL(request_->url(), &origin_url, &type, - &relative_file_path_)) { - NotifyFailed(net::ERR_INVALID_URL); - return; - } - - path_manager_->GetFileSystemRootPath( - origin_url, type, false, // create - callback_factory_.NewCallback(&FileSystemURLRequestJob::DidGetRootPath)); -} - -void FileSystemURLRequestJob::DidGetRootPath(bool success, - const FilePath& root_path, - const std::string& name) { - if (!success) { - NotifyFailed(net::ERR_FILE_NOT_FOUND); - return; - } - - absolute_file_path_ = root_path.Append(relative_file_path_); - - base::FileUtilProxy::GetFileInfo(file_thread_proxy_, absolute_file_path_, - callback_factory_.NewCallback(&FileSystemURLRequestJob::DidResolve)); -} - void FileSystemURLRequestJob::DidResolve(base::PlatformFileError error_code, const base::PlatformFileInfo& file_info) { // We may have been orphaned... @@ -231,6 +207,9 @@ void FileSystemURLRequestJob::DidOpen(base::PlatformFileError error_code, byte_range_.first_byte_position() + 1; DCHECK_GE(remaining_bytes_, 0); + // TODO(adamk): Please remove this ScopedAllowIO once we support async seek on + // FileStream. + base::ThreadRestrictions::ScopedAllowIO allow_io; // Do the seek at the beginning of the request. if (remaining_bytes_ > 0 && byte_range_.first_byte_position() != 0 && @@ -278,8 +257,4 @@ bool FileSystemURLRequestJob::IsRedirectResponse(GURL* location, return false; } -void FileSystemURLRequestJob::NotifyFailed(int rv) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); -} - } // namespace fileapi diff --git a/webkit/fileapi/file_system_url_request_job.h b/webkit/fileapi/file_system_url_request_job.h index 6d0f6e3..dd3c45c 100644 --- a/webkit/fileapi/file_system_url_request_job.h +++ b/webkit/fileapi/file_system_url_request_job.h @@ -17,6 +17,7 @@ #include "net/base/completion_callback.h" #include "net/http/http_byte_range.h" #include "net/url_request/url_request_job.h" +#include "webkit/fileapi/file_system_url_request_job_base.h" class GURL; @@ -25,13 +26,13 @@ class FileStream; } namespace fileapi { -class FileSystemPathManager; +class FileSystemContext; // A request job that handles reading filesystem: URLs -class FileSystemURLRequestJob : public net::URLRequestJob { +class FileSystemURLRequestJob : public FileSystemURLRequestJobBase { public: FileSystemURLRequestJob( - net::URLRequest* request, FileSystemPathManager* path_manager, + net::URLRequest* request, FileSystemContext* file_system_context, scoped_refptr<base::MessageLoopProxy> file_thread_proxy); // URLRequestJob methods: @@ -46,35 +47,27 @@ class FileSystemURLRequestJob : public net::URLRequestJob { // FilterContext methods (via URLRequestJob): virtual bool GetMimeType(std::string* mime_type) const; + protected: + // FileSystemURLRequestJobBase methods. + virtual void DidGetLocalPath(const FilePath& local_path); + private: virtual ~FileSystemURLRequestJob(); - void StartAsync(); - void DidGetRootPath(bool success, const FilePath& root_path, - const std::string& name); void DidResolve(base::PlatformFileError error_code, const base::PlatformFileInfo& file_info); void DidOpen(base::PlatformFileError error_code, base::PassPlatformFile file, bool created); void DidRead(int result); - void NotifyFailed(int rv); - - FilePath relative_file_path_; - FilePath absolute_file_path_; - FileSystemPathManager* const path_manager_; - + ScopedRunnableMethodFactory<FileSystemURLRequestJob> method_factory_; + base::ScopedCallbackFactory<FileSystemURLRequestJob> callback_factory_; net::CompletionCallbackImpl<FileSystemURLRequestJob> io_callback_; scoped_ptr<net::FileStream> stream_; bool is_directory_; scoped_ptr<net::HttpResponseInfo> response_info_; - - net::HttpByteRange byte_range_; int64 remaining_bytes_; - - ScopedRunnableMethodFactory<FileSystemURLRequestJob> method_factory_; - base::ScopedCallbackFactory<FileSystemURLRequestJob> callback_factory_; - scoped_refptr<base::MessageLoopProxy> file_thread_proxy_; + net::HttpByteRange byte_range_; DISALLOW_COPY_AND_ASSIGN(FileSystemURLRequestJob); }; diff --git a/webkit/fileapi/file_system_url_request_job_base.cc b/webkit/fileapi/file_system_url_request_job_base.cc new file mode 100644 index 0000000..d5c71b8 --- /dev/null +++ b/webkit/fileapi/file_system_url_request_job_base.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "webkit/fileapi/file_system_url_request_job_base.h" + +#include "base/message_loop.h" +#include "net/base/net_errors.h" +#include "net/url_request/url_request.h" + +using net::URLRequest; +using net::URLRequestJob; +using net::URLRequestStatus; + +namespace fileapi { + +class LocalPathCallbackDispatcher : public FileSystemCallbackDispatcher { + public: + explicit LocalPathCallbackDispatcher( + FileSystemURLRequestJobBase* request) + : request_(request), + io_loop_(base::MessageLoopProxy::CreateForCurrentThread()) { + DCHECK(request_); + } + + // fileapi::FileSystemCallbackDispatcher overrides. + virtual void DidSucceed() OVERRIDE { + NOTREACHED(); + } + + virtual void DidGetLocalPath(const FilePath& local_path) { + io_loop_->PostTask(FROM_HERE, + NewRunnableMethod(request_, + &FileSystemURLRequestJobBase::OnGetLocalPath, + local_path)); + } + + virtual void DidReadMetadata(const base::PlatformFileInfo& info, + const FilePath& unused) OVERRIDE { + NOTREACHED(); + } + + virtual void DidReadDirectory( + const std::vector<base::FileUtilProxy::Entry>& entries, + bool has_more) OVERRIDE { + NOTREACHED(); + } + + virtual void DidWrite(int64 bytes, bool complete) OVERRIDE { + NOTREACHED(); + } + + virtual void DidOpenFileSystem(const std::string& name, + const GURL& root_path) OVERRIDE { + NOTREACHED(); + } + + virtual void DidFail(base::PlatformFileError error_code) OVERRIDE { + io_loop_->PostTask(FROM_HERE, + NewRunnableMethod(request_, + &FileSystemURLRequestJobBase::RespondFailedOnIOThread, + error_code)); + } + + private: + FileSystemURLRequestJobBase* request_; + scoped_refptr<base::MessageLoopProxy> io_loop_; + DISALLOW_COPY_AND_ASSIGN(LocalPathCallbackDispatcher); +}; + +FileSystemURLRequestJobBase::FileSystemURLRequestJobBase( + URLRequest* request, FileSystemContext* file_system_context, + scoped_refptr<base::MessageLoopProxy> file_thread_proxy) + : URLRequestJob(request), + file_system_context_(file_system_context), + file_thread_proxy_(file_thread_proxy) { +} + +FileSystemOperation* FileSystemURLRequestJobBase::GetNewOperation() { + LocalPathCallbackDispatcher* dispatcher = + new LocalPathCallbackDispatcher(this); + FileSystemOperation* operation = new FileSystemOperation( + dispatcher, + file_thread_proxy_, + file_system_context_, + NULL); + return operation; +} + +void FileSystemURLRequestJobBase::StartAsync() { + GetNewOperation()->GetLocalPath(request_->url()); +} + +void FileSystemURLRequestJobBase::RespondFailedOnIOThread(int error_code) { + int rv = net::ERR_FILE_NOT_FOUND; + if (error_code == base::PLATFORM_FILE_ERROR_INVALID_URL) + rv = net::ERR_INVALID_URL; + NotifyFailed(rv); +} + +void FileSystemURLRequestJobBase::NotifyFailed(int rv) { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); +} + +void FileSystemURLRequestJobBase::OnGetLocalPath( + const FilePath& local_path) { + DidGetLocalPath(local_path); +} + +} // namespace fileapi diff --git a/webkit/fileapi/file_system_url_request_job_base.h b/webkit/fileapi/file_system_url_request_job_base.h new file mode 100644 index 0000000..72cc1d2 --- /dev/null +++ b/webkit/fileapi/file_system_url_request_job_base.h @@ -0,0 +1,48 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_BASE_H_ +#define WEBKIT_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_BASE_H_ +#pragma once + +#include "base/file_path.h" +#include "base/message_loop_proxy.h" +#include "net/url_request/url_request_job.h" +#include "webkit/fileapi/file_system_callback_dispatcher.h" +#include "webkit/fileapi/file_system_context.h" +#include "webkit/fileapi/file_system_operation.h" + +namespace fileapi { + +// A base class for request jobs that handle reading filesystem: URLs for +// files and directories. +class FileSystemURLRequestJobBase : public net::URLRequestJob { + public: + FileSystemURLRequestJobBase( + net::URLRequest* request, FileSystemContext* file_system_context, + scoped_refptr<base::MessageLoopProxy> file_thread_proxy); + + void StartAsync(); + + protected: + virtual void DidGetLocalPath(const FilePath& local_path) = 0 ; + + void NotifyFailed(int rv); + void RespondFailedOnIOThread(int error_code); + FileSystemOperation* GetNewOperation(); + + FilePath relative_file_path_; + FilePath absolute_file_path_; + scoped_refptr<FileSystemContext> file_system_context_; + scoped_refptr<base::MessageLoopProxy> file_thread_proxy_; + + private: + friend class LocalPathCallbackDispatcher; + void OnGetLocalPath(const FilePath& local_path); + DISALLOW_COPY_AND_ASSIGN(FileSystemURLRequestJobBase); +}; + +} // namespace fileapi + +#endif // WEBKIT_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_BASE_H_ diff --git a/webkit/fileapi/file_system_url_request_job_unittest.cc b/webkit/fileapi/file_system_url_request_job_unittest.cc index 18b74e0..62e6d8f 100644 --- a/webkit/fileapi/file_system_url_request_job_unittest.cc +++ b/webkit/fileapi/file_system_url_request_job_unittest.cc @@ -31,6 +31,7 @@ #include "net/url_request/url_request.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webkit/fileapi/file_system_context.h" #include "webkit/fileapi/file_system_path_manager.h" namespace fileapi { @@ -55,6 +56,21 @@ void FillBuffer(char* buffer, size_t len) { } } +class TestSpecialStoragePolicy : public quota::SpecialStoragePolicy { + public: + virtual bool IsStorageProtected(const GURL& origin) { + return false; + } + + virtual bool IsStorageUnlimited(const GURL& origin) { + return true; + } + + virtual bool IsFileHandler(const std::string& extension_id) { + return true; + } +}; + class FileSystemURLRequestJobTest : public testing::Test { protected: FileSystemURLRequestJobTest() @@ -65,13 +81,21 @@ class FileSystemURLRequestJobTest : public testing::Test { virtual void SetUp() { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + special_storage_policy_ = new TestSpecialStoragePolicy(); // We use the main thread so that we can get the root path synchronously. // TODO(adamk): Run this on the FILE thread we've created as well. - path_manager_.reset(new FileSystemPathManager( - base::MessageLoopProxy::CreateForCurrentThread(), - temp_dir_.path(), NULL, false, false)); - - path_manager_->GetFileSystemRootPath( + file_system_context_ = + new FileSystemContext( + base::MessageLoopProxy::CreateForCurrentThread(), + base::MessageLoopProxy::CreateForCurrentThread(), + special_storage_policy_, + FilePath(), false /* is_incognito */, + false, true, + new FileSystemPathManager( + base::MessageLoopProxy::CreateForCurrentThread(), + temp_dir_.path(), NULL, false, false)); + + file_system_context_->path_manager()->ValidateFileSystemRootAndGetURL( GURL("http://remote/"), kFileSystemTypeTemporary, true, // create callback_factory_.NewCallback( &FileSystemURLRequestJobTest::OnGetRootPath)); @@ -107,7 +131,9 @@ class FileSystemURLRequestJobTest : public testing::Test { request_.reset(new net::URLRequest(url, delegate_.get())); if (headers) request_->SetExtraRequestHeaders(*headers); - job_ = new FileSystemURLRequestJob(request_.get(), path_manager_.get(), + job_ = new FileSystemURLRequestJob( + request_.get(), + file_system_context_.get(), base::MessageLoopProxy::CreateForCurrentThread()); request_->Start(); @@ -138,8 +164,8 @@ class FileSystemURLRequestJobTest : public testing::Test { FilePath origin_root_path_; scoped_ptr<net::URLRequest> request_; scoped_ptr<TestDelegate> delegate_; - scoped_ptr<FileSystemPathManager> path_manager_; - + scoped_refptr<TestSpecialStoragePolicy> special_storage_policy_; + scoped_refptr<FileSystemContext> file_system_context_; MessageLoop message_loop_; base::ScopedCallbackFactory<FileSystemURLRequestJobTest> callback_factory_; diff --git a/webkit/fileapi/local_file_system_file_util.cc b/webkit/fileapi/local_file_system_file_util.cc index 068a052..7dad5b1 100644 --- a/webkit/fileapi/local_file_system_file_util.cc +++ b/webkit/fileapi/local_file_system_file_util.cc @@ -44,6 +44,20 @@ PlatformFileError LocalFileSystemFileUtil::EnsureFileExists( context, local_path, created); } +PlatformFileError LocalFileSystemFileUtil::GetLocalFilePath( + FileSystemOperationContext* context, + const FilePath& virtual_path, + FilePath* local_path) { + FilePath path = + GetLocalPath(context, context->src_origin_url(), context->src_type(), + virtual_path); + if (path.empty()) + return base::PLATFORM_FILE_ERROR_NOT_FOUND; + + *local_path = path; + return base::PLATFORM_FILE_OK; +} + PlatformFileError LocalFileSystemFileUtil::GetFileInfo( FileSystemOperationContext* context, const FilePath& file_path, @@ -170,7 +184,8 @@ FilePath LocalFileSystemFileUtil::GetLocalPath( FileSystemType type, const FilePath& virtual_path) { FilePath root = context->file_system_context()->path_manager()-> - GetFileSystemRootPathOnFileThread(origin_url, type, virtual_path, false); + ValidateFileSystemRootAndGetPathOnFileThread(origin_url, type, + virtual_path, false); if (root.empty()) return FilePath(); return root.Append(virtual_path); diff --git a/webkit/fileapi/local_file_system_file_util.h b/webkit/fileapi/local_file_system_file_util.h index 3e5855a..7e484aa 100644 --- a/webkit/fileapi/local_file_system_file_util.h +++ b/webkit/fileapi/local_file_system_file_util.h @@ -49,9 +49,14 @@ class LocalFileSystemFileUtil : public FileSystemFileUtil { FileSystemOperationContext* context, const FilePath& file_path, bool* created); + virtual PlatformFileError GetLocalFilePath( + FileSystemOperationContext* context, + const FilePath& virtual_file, + FilePath* local_path); + virtual PlatformFileError GetFileInfo( FileSystemOperationContext* context, - const FilePath& file_, + const FilePath& file, base::PlatformFileInfo* file_info, FilePath* platform_file); diff --git a/webkit/fileapi/sandbox_mount_point_provider.cc b/webkit/fileapi/sandbox_mount_point_provider.cc index 5e80296..51954ce 100644 --- a/webkit/fileapi/sandbox_mount_point_provider.cc +++ b/webkit/fileapi/sandbox_mount_point_provider.cc @@ -220,7 +220,7 @@ std::vector<FilePath> SandboxMountPointProvider::GetRootDirectories() const { return std::vector<FilePath>(); } -void SandboxMountPointProvider::GetFileSystemRootPath( +void SandboxMountPointProvider::ValidateFileSystemRootAndGetURL( const GURL& origin_url, fileapi::FileSystemType type, bool create, FileSystemPathManager::GetRootPathCallback* callback_ptr) { scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback(callback_ptr); @@ -239,7 +239,8 @@ void SandboxMountPointProvider::GetFileSystemRootPath( task->Start(origin_url, origin_base_path, create); }; -FilePath SandboxMountPointProvider::GetFileSystemRootPathOnFileThread( +FilePath +SandboxMountPointProvider::ValidateFileSystemRootAndGetPathOnFileThread( const GURL& origin_url, FileSystemType type, const FilePath& unused, bool create) { FilePath origin_base_path; diff --git a/webkit/fileapi/sandbox_mount_point_provider.h b/webkit/fileapi/sandbox_mount_point_provider.h index 51a9414..6f8cff8 100644 --- a/webkit/fileapi/sandbox_mount_point_provider.h +++ b/webkit/fileapi/sandbox_mount_point_provider.h @@ -37,7 +37,7 @@ class SandboxMountPointProvider : public FileSystemMountPointProvider { // 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. - virtual void GetFileSystemRootPath( + virtual void ValidateFileSystemRootAndGetURL( const GURL& origin_url, FileSystemType type, bool create, @@ -45,7 +45,7 @@ class SandboxMountPointProvider : public FileSystemMountPointProvider { // Like GetFileSystemRootPath, but synchronous, and can be called only while // running on the file thread. - virtual FilePath GetFileSystemRootPathOnFileThread( + virtual FilePath ValidateFileSystemRootAndGetPathOnFileThread( const GURL& origin_url, FileSystemType type, const FilePath& unused, diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi index ca25491..70de6fc 100644 --- a/webkit/fileapi/webkit_fileapi.gypi +++ b/webkit/fileapi/webkit_fileapi.gypi @@ -34,6 +34,8 @@ 'file_system_types.h', 'file_system_url_request_job.cc', 'file_system_url_request_job.h', + 'file_system_url_request_job_base.cc', + 'file_system_url_request_job_base.h', 'file_system_usage_tracker.cc', 'file_system_usage_tracker.h', 'file_system_util.cc', |