diff options
-rw-r--r-- | chrome/browser/file_system/file_system_dispatcher_host.cc | 223 | ||||
-rw-r--r-- | chrome/browser/file_system/file_system_dispatcher_host.h | 34 | ||||
-rw-r--r-- | chrome/common/file_system/file_system_dispatcher.cc | 3 | ||||
-rw-r--r-- | chrome/common/render_messages_params.cc | 6 | ||||
-rw-r--r-- | chrome/common/render_messages_params.h | 17 |
5 files changed, 202 insertions, 81 deletions
diff --git a/chrome/browser/file_system/file_system_dispatcher_host.cc b/chrome/browser/file_system/file_system_dispatcher_host.cc index 172217e..e7bf5d8 100644 --- a/chrome/browser/file_system/file_system_dispatcher_host.cc +++ b/chrome/browser/file_system/file_system_dispatcher_host.cc @@ -4,7 +4,9 @@ #include "chrome/browser/file_system/file_system_dispatcher_host.h" +#include "base/file_path.h" #include "base/thread.h" +#include "base/time.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_thread.h" @@ -17,6 +19,60 @@ #include "third_party/WebKit/WebKit/chromium/public/WebFileError.h" #include "webkit/glue/webkit_glue.h" +// A class to hold an ongoing openFileSystem completion task. +struct OpenFileSystemCompletionTask { + public: + static void Run( + int request_id, + int routing_id, + const std::string& name, + const FilePath& root_path, + FileSystemDispatcherHost* dispatcher_host) { + // The task is self-destructed. + new OpenFileSystemCompletionTask(request_id, routing_id, name, root_path, + dispatcher_host); + } + + void DidFinish(base::PlatformFileError error) { + if (error == base::PLATFORM_FILE_OK) + dispatcher_host_->Send( + new ViewMsg_OpenFileSystemRequest_Complete( + routing_id_, request_id_, true, UTF8ToUTF16(name_), + webkit_glue::FilePathToWebString(root_path_))); + else + dispatcher_host_->Send( + new ViewMsg_OpenFileSystemRequest_Complete( + routing_id_, request_id_, false, string16(), string16())); + delete this; + } + + private: + OpenFileSystemCompletionTask( + int request_id, + int routing_id, + const std::string& name, + const FilePath& root_path, + FileSystemDispatcherHost* dispatcher_host) + : request_id_(request_id), + routing_id_(routing_id), + name_(name), + root_path_(root_path), + dispatcher_host_(dispatcher_host), + callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { + base::FileUtilProxy::CreateDirectory( + ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE), + root_path_, false, true, callback_factory_.NewCallback( + &OpenFileSystemCompletionTask::DidFinish)); + } + + int request_id_; + int routing_id_; + std::string name_; + FilePath root_path_; + scoped_refptr<FileSystemDispatcherHost> dispatcher_host_; + base::ScopedCallbackFactory<OpenFileSystemCompletionTask> callback_factory_; +}; + FileSystemDispatcherHost::FileSystemDispatcherHost( IPC::Message::Sender* sender, FileSystemHostContext* file_system_host_context, @@ -40,6 +96,12 @@ void FileSystemDispatcherHost::Init(base::ProcessHandle process_handle) { void FileSystemDispatcherHost::Shutdown() { message_sender_ = NULL; shutdown_ = true; + + // Drop all the operations. + for (OperationsMap::const_iterator iter(&operations_); + !iter.IsAtEnd(); iter.Advance()) { + operations_.Remove(iter.GetCurrentKey()); + } } bool FileSystemDispatcherHost::OnMessageReceived( @@ -82,97 +144,134 @@ void FileSystemDispatcherHost::OnOpenFileSystem( return; } - // TODO(kinuko): creates the root directory and if it succeeds. - - Send(new ViewMsg_OpenFileSystemRequest_Complete( - params.routing_id, - params.request_id, - true, - UTF8ToUTF16(name), - webkit_glue::FilePathToWebString(root_path))); + // Run the completion task that creates the root directory and sends + // back the status code to the dispatcher. + OpenFileSystemCompletionTask::Run( + params.request_id, params.routing_id, name, root_path, this); } void FileSystemDispatcherHost::OnMove( int request_id, const string16& src_path, const string16& dest_path) { - if (!context_->CheckValidFileSystemPath( - webkit_glue::WebStringToFilePath(src_path)) || - !context_->CheckValidFileSystemPath( - webkit_glue::WebStringToFilePath(dest_path))) { - Send(new ViewMsg_FileSystem_DidFail( - request_id, WebKit::WebFileErrorSecurity)); + FilePath src_file_path = webkit_glue::WebStringToFilePath(src_path); + FilePath dest_file_path = webkit_glue::WebStringToFilePath(dest_path); + + if (!CheckValidFileSystemPath(src_file_path, request_id) || + !CheckValidFileSystemPath(dest_file_path, request_id)) return; - } - // TODO(kinuko): not implemented yet. - Send(new ViewMsg_FileSystem_DidFail( - request_id, WebKit::WebFileErrorAbort)); + GetNewOperation(request_id)->Move(src_file_path, dest_file_path); } void FileSystemDispatcherHost::OnCopy( - int request_id, - const string16& src_path, - const string16& dest_path) { - // TODO(kinuko): not implemented yet. - Send(new ViewMsg_FileSystem_DidFail( - request_id, WebKit::WebFileErrorAbort)); + int request_id, const string16& src_path, const string16& dest_path) { + FilePath src_file_path = webkit_glue::WebStringToFilePath(src_path); + FilePath dest_file_path = webkit_glue::WebStringToFilePath(dest_path); + + if (!CheckValidFileSystemPath(src_file_path, request_id) || + !CheckValidFileSystemPath(dest_file_path, request_id)) + return; + + GetNewOperation(request_id)->Copy(src_file_path, dest_file_path); } void FileSystemDispatcherHost::OnRemove( - int request_id, - const string16& path) { - // TODO(kinuko): not implemented yet. - Send(new ViewMsg_FileSystem_DidFail( - request_id, WebKit::WebFileErrorAbort)); + int request_id, const string16& path) { + FilePath file_path = webkit_glue::WebStringToFilePath(path); + if (!CheckValidFileSystemPath(file_path, request_id)) + return; + GetNewOperation(request_id)->Remove(file_path); } void FileSystemDispatcherHost::OnReadMetadata( - int request_id, - const string16& path) { - // TODO(kinuko): not implemented yet. - Send(new ViewMsg_FileSystem_DidFail( - request_id, WebKit::WebFileErrorAbort)); + int request_id, const string16& path) { + FilePath file_path = webkit_glue::WebStringToFilePath(path); + if (!CheckValidFileSystemPath(file_path, request_id)) + return; + GetNewOperation(request_id)->GetMetadata(file_path); } void FileSystemDispatcherHost::OnCreate( - int request_id, - const string16& path, - bool exclusive, - bool is_directory) { - // TODO(kinuko): not implemented yet. - Send(new ViewMsg_FileSystem_DidFail( - request_id, WebKit::WebFileErrorAbort)); + int request_id, const string16& path, bool exclusive, bool is_directory) { + FilePath file_path = webkit_glue::WebStringToFilePath(path); + if (!CheckValidFileSystemPath(file_path, request_id)) + return; + if (is_directory) + GetNewOperation(request_id)->CreateDirectory(file_path, exclusive); + else + GetNewOperation(request_id)->CreateFile(file_path, exclusive); } void FileSystemDispatcherHost::OnExists( - int request_id, - const string16& path, - bool is_directory) { - // TODO(kinuko): not implemented yet. - Send(new ViewMsg_FileSystem_DidFail( - request_id, WebKit::WebFileErrorAbort)); + int request_id, const string16& path, bool is_directory) { + FilePath file_path = webkit_glue::WebStringToFilePath(path); + if (!CheckValidFileSystemPath(file_path, request_id)) + return; + if (is_directory) + GetNewOperation(request_id)->DirectoryExists(file_path); + else + GetNewOperation(request_id)->FileExists(file_path); } void FileSystemDispatcherHost::OnReadDirectory( - int request_id, - const string16& path) { - // TODO(kinuko): not implemented yet. - Send(new ViewMsg_FileSystem_DidFail( - request_id, WebKit::WebFileErrorAbort)); + int request_id, const string16& path) { + FilePath file_path = webkit_glue::WebStringToFilePath(path); + if (!CheckValidFileSystemPath(file_path, request_id)) + return; + GetNewOperation(request_id)->ReadDirectory(file_path); } -void FileSystemDispatcherHost::Send(IPC::Message* message) { - if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) { - if (!ChromeThread::PostTask( - ChromeThread::IO, FROM_HERE, - NewRunnableMethod(this, - &FileSystemDispatcherHost::Send, - message))) - delete message; - return; - } +void FileSystemDispatcherHost::DidFail( + WebKit::WebFileError status, int request_id) { + Send(new ViewMsg_FileSystem_DidFail(request_id, status)); + operations_.Remove(request_id); +} + +void FileSystemDispatcherHost::DidSucceed(int request_id) { + Send(new ViewMsg_FileSystem_DidSucceed(request_id)); + operations_.Remove(request_id); +} + +void FileSystemDispatcherHost::DidReadMetadata( + const base::PlatformFileInfo& info, int request_id) { + Send(new ViewMsg_FileSystem_DidReadMetadata(request_id, info)); + operations_.Remove(request_id); +} +void FileSystemDispatcherHost::DidReadDirectory( + const std::vector<base::file_util_proxy::Entry>& entries, + bool has_more, int request_id) { + ViewMsg_FileSystem_DidReadDirectory_Params params; + params.request_id = request_id; + params.entries = entries; + params.has_more = has_more; + Send(new ViewMsg_FileSystem_DidReadDirectory(params)); + operations_.Remove(request_id); +} + +void FileSystemDispatcherHost::Send(IPC::Message* message) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); if (!shutdown_ && message_sender_) message_sender_->Send(message); else delete message; } + +bool FileSystemDispatcherHost::CheckValidFileSystemPath( + const FilePath& path, int request_id) { + // We may want do more checks, but for now it just checks if the given + // |path| is under the valid FileSystem root path for this host context. + if (!context_->CheckValidFileSystemPath(path)) { + Send(new ViewMsg_FileSystem_DidFail( + request_id, WebKit::WebFileErrorSecurity)); + return false; + } + return true; +} + +FileSystemOperation* FileSystemDispatcherHost::GetNewOperation( + int request_id) { + scoped_ptr<FileSystemOperation> operation( + new FileSystemOperation(request_id, this)); + operations_.AddWithID(operation.get(), request_id); + return operation.release(); +} diff --git a/chrome/browser/file_system/file_system_dispatcher_host.h b/chrome/browser/file_system/file_system_dispatcher_host.h index 320e56a..64fd73c 100644 --- a/chrome/browser/file_system/file_system_dispatcher_host.h +++ b/chrome/browser/file_system/file_system_dispatcher_host.h @@ -6,9 +6,15 @@ #define CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_DISPATCHER_HOST_H_ #include "base/basictypes.h" +#include "base/file_util.h" +#include "base/id_map.h" #include "base/nullable_string16.h" #include "base/process.h" +#include "base/platform_file.h" +#include "base/scoped_callback_factory.h" #include "base/ref_counted.h" +#include "chrome/browser/file_system/file_system_operation.h" +#include "chrome/browser/file_system/file_system_operation_client.h" #include "chrome/common/render_messages.h" class FileSystemHostContext; @@ -17,7 +23,8 @@ class Receiver; class ResourceMessageFilter; class FileSystemDispatcherHost - : public base::RefCountedThreadSafe<FileSystemDispatcherHost> { + : public base::RefCountedThreadSafe<FileSystemDispatcherHost>, + public FileSystemOperationClient { public: FileSystemDispatcherHost(IPC::Message::Sender* sender, FileSystemHostContext* file_system_host_context, @@ -56,8 +63,25 @@ class FileSystemDispatcherHost const string16& path); void Send(IPC::Message* message); + // FileSystemOperationClient methods. + virtual void DidFail(WebKit::WebFileError status, int request_id); + virtual void DidSucceed(int request_id); + virtual void DidReadMetadata( + const base::PlatformFileInfo& info, + int request_id); + virtual void DidReadDirectory( + const std::vector<base::file_util_proxy::Entry>& entries, + bool has_more, + int request_id); + private: - void Move(const string16& src, const string16& dest, int operation_id); + // Creates a new FileSystemOperation. + FileSystemOperation* GetNewOperation(int request_id); + + // Checks the validity of a given |path|. Returns true if the given |path| + // is valid as a path for FileSystem API. Otherwise it sends back a + // security error code to the dispatcher and returns false. + bool CheckValidFileSystemPath(const FilePath& path, int request_id); // The sender to be used for sending out IPC messages. IPC::Message::Sender* message_sender_; @@ -71,6 +95,12 @@ class FileSystemDispatcherHost // Used to look up permissions. scoped_refptr<HostContentSettingsMap> host_content_settings_map_; + + // Keeps ongoing file system operations. + typedef IDMap<FileSystemOperation, IDMapOwnPointer> OperationsMap; + OperationsMap operations_; + + DISALLOW_COPY_AND_ASSIGN(FileSystemDispatcherHost); }; #endif // CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_DISPATCHER_HOST_H_ diff --git a/chrome/common/file_system/file_system_dispatcher.cc b/chrome/common/file_system/file_system_dispatcher.cc index d28e244..7b0492c 100644 --- a/chrome/common/file_system/file_system_dispatcher.cc +++ b/chrome/common/file_system/file_system_dispatcher.cc @@ -127,7 +127,8 @@ void FileSystemDispatcher::DidReadDirectory( callbacks_.Remove(params.request_id); WebVector<WebFileSystemEntry> entries(params.entries.size()); for (size_t i = 0; i < params.entries.size(); ++i) { - entries[i].name = webkit_glue::FilePathToWebString(params.entries[i].name); + entries[i].name = webkit_glue::FilePathStringToWebString( + params.entries[i].name); entries[i].isDirectory = params.entries[i].is_directory; } callbacks->didReadDirectory(entries, params.has_more); diff --git a/chrome/common/render_messages_params.cc b/chrome/common/render_messages_params.cc index 734874c..6c9591f 100644 --- a/chrome/common/render_messages_params.cc +++ b/chrome/common/render_messages_params.cc @@ -1481,14 +1481,14 @@ void ParamTraits<ViewMsg_FileSystem_DidReadDirectory_Params>::Log( l->append(")"); } -void ParamTraits<ViewMsg_FileSystem_DidReadDirectory_Params::Entry>::Write( +void ParamTraits<base::file_util_proxy::Entry>::Write( Message* m, const param_type& p) { WriteParam(m, p.name); WriteParam(m, p.is_directory); } -bool ParamTraits<ViewMsg_FileSystem_DidReadDirectory_Params::Entry>::Read( +bool ParamTraits<base::file_util_proxy::Entry>::Read( const Message* m, void** iter, param_type* p) { @@ -1497,7 +1497,7 @@ bool ParamTraits<ViewMsg_FileSystem_DidReadDirectory_Params::Entry>::Read( ReadParam(m, iter, &p->is_directory); } -void ParamTraits<ViewMsg_FileSystem_DidReadDirectory_Params::Entry>::Log( +void ParamTraits<base::file_util_proxy::Entry>::Log( const param_type& p, std::string* l) { l->append("("); diff --git a/chrome/common/render_messages_params.h b/chrome/common/render_messages_params.h index 904e094..c5a38b6 100644 --- a/chrome/common/render_messages_params.h +++ b/chrome/common/render_messages_params.h @@ -11,6 +11,7 @@ #include "app/surface/transport_dib.h" #include "base/file_path.h" +#include "base/file_util_proxy.h" #include "base/ref_counted.h" #include "base/shared_memory.h" #include "base/time.h" @@ -846,18 +847,8 @@ struct ViewMsg_FileSystem_DidReadDirectory_Params { // The response should have this id. int request_id; - // TODO(kinuko): replace this with file_util_proxy's entry structure - // once it's defined. - struct Entry { - // Name of the entry. - FilePath name; - - // Indicates if the entry is directory or not. - bool is_directory; - }; - // A vector of directory entries. - std::vector<Entry> entries; + std::vector<base::file_util_proxy::Entry> entries; // Indicates if there will be more entries. bool has_more; @@ -1125,8 +1116,8 @@ struct ParamTraits<ViewMsg_FileSystem_DidReadDirectory_Params> { }; template <> -struct ParamTraits<ViewMsg_FileSystem_DidReadDirectory_Params::Entry> { - typedef ViewMsg_FileSystem_DidReadDirectory_Params::Entry param_type; +struct ParamTraits<base::file_util_proxy::Entry> { + typedef base::file_util_proxy::Entry param_type; static void Write(Message* m, const param_type& p); static bool Read(const Message* m, void** iter, param_type* p); static void Log(const param_type& p, std::string* l); |