| // Copyright 2013 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 "ppapi/proxy/file_ref_resource.h" |
| |
| #include "ppapi/c/pp_directory_entry.h" |
| #include "ppapi/c/pp_instance.h" |
| #include "ppapi/c/pp_resource.h" |
| #include "ppapi/proxy/ppapi_messages.h" |
| #include "ppapi/shared_impl/array_writer.h" |
| #include "ppapi/shared_impl/file_ref_util.h" |
| #include "ppapi/shared_impl/resource.h" |
| #include "ppapi/shared_impl/resource_tracker.h" |
| #include "ppapi/shared_impl/var.h" |
| #include "ppapi/thunk/enter.h" |
| #include "ppapi/thunk/ppb_file_system_api.h" |
| |
| namespace ppapi { |
| namespace proxy { |
| |
| FileRefResource::FileRefResource( |
| Connection connection, |
| PP_Instance instance, |
| const FileRefCreateInfo& create_info) |
| : PluginResource(connection, instance), |
| create_info_(create_info), |
| file_system_resource_(create_info.file_system_plugin_resource) { |
| if (uses_internal_paths()) { |
| // If path ends with a slash, then normalize it away unless path is |
| // the root path. |
| int path_size = create_info_.internal_path.size(); |
| if (path_size > 1 && create_info_.internal_path.at(path_size - 1) == '/') |
| create_info_.internal_path.erase(path_size - 1, 1); |
| |
| path_var_ = new StringVar(create_info_.internal_path); |
| create_info_.display_name = GetNameForInternalFilePath( |
| create_info_.internal_path); |
| } else { |
| DCHECK(!create_info_.display_name.empty()); |
| } |
| name_var_ = new StringVar(create_info_.display_name); |
| |
| if (create_info_.browser_pending_host_resource_id != 0 && |
| create_info_.renderer_pending_host_resource_id != 0) { |
| AttachToPendingHost(BROWSER, create_info_.browser_pending_host_resource_id); |
| AttachToPendingHost(RENDERER, |
| create_info_.renderer_pending_host_resource_id); |
| } else { |
| CHECK_EQ(0, create_info_.browser_pending_host_resource_id); |
| CHECK_EQ(0, create_info_.renderer_pending_host_resource_id); |
| CHECK(uses_internal_paths()); |
| SendCreate(BROWSER, PpapiHostMsg_FileRef_CreateForFileAPI( |
| create_info.file_system_plugin_resource, |
| create_info.internal_path)); |
| SendCreate(RENDERER, PpapiHostMsg_FileRef_CreateForFileAPI( |
| create_info.file_system_plugin_resource, |
| create_info.internal_path)); |
| } |
| } |
| |
| FileRefResource::~FileRefResource() { |
| } |
| |
| // static |
| PP_Resource FileRefResource::CreateFileRef( |
| Connection connection, |
| PP_Instance instance, |
| const FileRefCreateInfo& create_info) { |
| // If we have a valid file_system resource, ensure that its type matches that |
| // of the fs_type parameter. |
| if (create_info.file_system_plugin_resource != 0) { |
| thunk::EnterResourceNoLock<thunk::PPB_FileSystem_API> enter( |
| create_info.file_system_plugin_resource, true); |
| if (enter.failed()) |
| return 0; |
| if (enter.object()->GetType() != create_info.file_system_type) { |
| NOTREACHED() << "file system type mismatch with resource"; |
| return 0; |
| } |
| } |
| |
| if (create_info.file_system_type == PP_FILESYSTEMTYPE_LOCALPERSISTENT || |
| create_info.file_system_type == PP_FILESYSTEMTYPE_LOCALTEMPORARY) { |
| if (!IsValidInternalPath(create_info.internal_path)) |
| return 0; |
| } |
| return (new FileRefResource(connection, |
| instance, |
| create_info))->GetReference(); |
| } |
| |
| thunk::PPB_FileRef_API* FileRefResource::AsPPB_FileRef_API() { |
| return this; |
| } |
| |
| PP_FileSystemType FileRefResource::GetFileSystemType() const { |
| return create_info_.file_system_type; |
| } |
| |
| PP_Var FileRefResource::GetName() const { |
| return name_var_->GetPPVar(); |
| } |
| |
| PP_Var FileRefResource::GetPath() const { |
| if (!uses_internal_paths()) |
| return PP_MakeUndefined(); |
| return path_var_->GetPPVar(); |
| } |
| |
| PP_Resource FileRefResource::GetParent() { |
| if (!uses_internal_paths()) |
| return 0; |
| |
| size_t pos = create_info_.internal_path.rfind('/'); |
| CHECK(pos != std::string::npos); |
| if (pos == 0) |
| pos++; |
| std::string parent_path = create_info_.internal_path.substr(0, pos); |
| |
| ppapi::FileRefCreateInfo parent_info; |
| parent_info.file_system_type = create_info_.file_system_type; |
| parent_info.internal_path = parent_path; |
| parent_info.display_name = GetNameForInternalFilePath(parent_path); |
| parent_info.file_system_plugin_resource = |
| create_info_.file_system_plugin_resource; |
| |
| return (new FileRefResource(connection(), |
| pp_instance(), |
| parent_info))->GetReference(); |
| } |
| |
| int32_t FileRefResource::MakeDirectory( |
| int32_t make_directory_flags, |
| scoped_refptr<TrackedCallback> callback) { |
| Call<PpapiPluginMsg_FileRef_MakeDirectoryReply>( |
| BROWSER, |
| PpapiHostMsg_FileRef_MakeDirectory(make_directory_flags), |
| base::Bind(&FileRefResource::RunTrackedCallback, this, callback)); |
| return PP_OK_COMPLETIONPENDING; |
| } |
| |
| int32_t FileRefResource::Touch(PP_Time last_access_time, |
| PP_Time last_modified_time, |
| scoped_refptr<TrackedCallback> callback) { |
| Call<PpapiPluginMsg_FileRef_TouchReply>( |
| BROWSER, |
| PpapiHostMsg_FileRef_Touch(last_access_time, |
| last_modified_time), |
| base::Bind(&FileRefResource::RunTrackedCallback, this, callback)); |
| return PP_OK_COMPLETIONPENDING; |
| } |
| |
| int32_t FileRefResource::Delete(scoped_refptr<TrackedCallback> callback) { |
| Call<PpapiPluginMsg_FileRef_DeleteReply>( |
| BROWSER, |
| PpapiHostMsg_FileRef_Delete(), |
| base::Bind(&FileRefResource::RunTrackedCallback, this, callback)); |
| return PP_OK_COMPLETIONPENDING; |
| } |
| |
| int32_t FileRefResource::Rename(PP_Resource new_file_ref, |
| scoped_refptr<TrackedCallback> callback) { |
| Call<PpapiPluginMsg_FileRef_RenameReply>( |
| BROWSER, |
| PpapiHostMsg_FileRef_Rename(new_file_ref), |
| base::Bind(&FileRefResource::RunTrackedCallback, this, callback)); |
| return PP_OK_COMPLETIONPENDING; |
| } |
| |
| int32_t FileRefResource::Query(PP_FileInfo* info, |
| scoped_refptr<TrackedCallback> callback) { |
| if (info == NULL) |
| return PP_ERROR_BADARGUMENT; |
| |
| Call<PpapiPluginMsg_FileRef_QueryReply>( |
| BROWSER, |
| PpapiHostMsg_FileRef_Query(), |
| base::Bind(&FileRefResource::OnQueryReply, this, info, callback)); |
| return PP_OK_COMPLETIONPENDING; |
| } |
| |
| int32_t FileRefResource::ReadDirectoryEntries( |
| const PP_ArrayOutput& output, |
| scoped_refptr<TrackedCallback> callback) { |
| Call<PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply>( |
| BROWSER, |
| PpapiHostMsg_FileRef_ReadDirectoryEntries(), |
| base::Bind(&FileRefResource::OnDirectoryEntriesReply, |
| this, output, callback)); |
| return PP_OK_COMPLETIONPENDING; |
| } |
| |
| const FileRefCreateInfo& FileRefResource::GetCreateInfo() const { |
| return create_info_; |
| } |
| |
| PP_Var FileRefResource::GetAbsolutePath() { |
| if (!absolute_path_var_.get()) { |
| std::string absolute_path; |
| int32_t result = SyncCall<PpapiPluginMsg_FileRef_GetAbsolutePathReply>( |
| BROWSER, PpapiHostMsg_FileRef_GetAbsolutePath(), &absolute_path); |
| if (result != PP_OK) |
| return PP_MakeUndefined(); |
| absolute_path_var_ = new StringVar(absolute_path); |
| } |
| return absolute_path_var_->GetPPVar(); |
| } |
| |
| void FileRefResource::RunTrackedCallback( |
| scoped_refptr<TrackedCallback> callback, |
| const ResourceMessageReplyParams& params) { |
| if (TrackedCallback::IsPending(callback)) |
| callback->Run(params.result()); |
| } |
| |
| void FileRefResource::OnQueryReply( |
| PP_FileInfo* out_info, |
| scoped_refptr<TrackedCallback> callback, |
| const ResourceMessageReplyParams& params, |
| const PP_FileInfo& info) { |
| if (!TrackedCallback::IsPending(callback)) |
| return; |
| |
| if (params.result() == PP_OK) |
| *out_info = info; |
| callback->Run(params.result()); |
| } |
| |
| void FileRefResource::OnDirectoryEntriesReply( |
| const PP_ArrayOutput& output, |
| scoped_refptr<TrackedCallback> callback, |
| const ResourceMessageReplyParams& params, |
| const std::vector<ppapi::FileRefCreateInfo>& infos, |
| const std::vector<PP_FileType>& file_types) { |
| if (!TrackedCallback::IsPending(callback)) |
| return; |
| |
| if (params.result() == PP_OK) { |
| ArrayWriter writer(output); |
| if (!writer.is_valid()) { |
| callback->Run(PP_ERROR_BADARGUMENT); |
| return; |
| } |
| |
| std::vector<PP_DirectoryEntry> entries; |
| for (size_t i = 0; i < infos.size(); ++i) { |
| PP_DirectoryEntry entry; |
| entry.file_ref = FileRefResource::CreateFileRef(connection(), |
| pp_instance(), |
| infos[i]); |
| entry.file_type = file_types[i]; |
| entries.push_back(entry); |
| } |
| |
| writer.StoreVector(entries); |
| } |
| callback->Run(params.result()); |
| } |
| |
| bool FileRefResource::uses_internal_paths() const { |
| return (create_info_.file_system_type != PP_FILESYSTEMTYPE_EXTERNAL) || |
| !create_info_.internal_path.empty(); |
| } |
| |
| } // namespace proxy |
| } // namespace ppapi |