| // Copyright 2010-2015, Google Inc. |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| // TODO(horo): Write tests. |
| |
| #include "base/pepper_file_util.h" |
| |
| #include <ppapi/c/pp_file_info.h> |
| #include <ppapi/c/ppb_file_io.h> |
| #include <ppapi/cpp/file_io.h> |
| #include <ppapi/cpp/file_ref.h> |
| #include <ppapi/cpp/file_system.h> |
| #include <ppapi/utility/completion_callback_factory.h> |
| |
| #include <set> |
| |
| #include "base/logging.h" |
| #include "base/mmap.h" |
| #include "base/mutex.h" |
| #include "base/pepper_scoped_obj.h" |
| #include "base/scoped_ptr.h" |
| #include "base/singleton.h" |
| #include "base/unnamed_event.h" |
| |
| namespace mozc { |
| namespace { |
| |
| // Base class of Pepper FileIO operator classes. |
| class PepperFileOperator { |
| public: |
| PepperFileOperator(pp::Instance *instance, pp::FileSystem *file_system) |
| : instance_(instance), |
| file_system_(file_system), |
| result_(PP_ERROR_FAILED) { |
| } |
| virtual ~PepperFileOperator() {} |
| |
| protected: |
| pp::Instance *instance_; |
| pp::FileSystem *file_system_; |
| int32_t result_; |
| UnnamedEvent event_; |
| }; |
| |
| class PepperFileReader : public PepperFileOperator { |
| public: |
| PepperFileReader(pp::Instance *instance, pp::FileSystem *file_system); |
| virtual ~PepperFileReader() {} |
| int32_t Read(const string &filename, string *buffer); |
| |
| private: |
| // Called in Read() |
| void ReadImpl(int32_t result); |
| void OnFileOpen(int32_t result); |
| void OnQuery(int32_t result); |
| void OnRead(int32_t result); |
| |
| string filename_; |
| string *buffer_; |
| int32_t bytes_to_read_; |
| int64_t offset_; |
| PP_FileInfo file_info_; |
| scoped_main_thread_destructed_object<pp::FileIO> file_io_; |
| scoped_main_thread_destructed_object<pp::FileRef> file_ref_; |
| pp::CompletionCallbackFactory<PepperFileReader> cc_factory_; |
| DISALLOW_COPY_AND_ASSIGN(PepperFileReader); |
| }; |
| |
| PepperFileReader::PepperFileReader(pp::Instance *instance, |
| pp::FileSystem *file_system) |
| : PepperFileOperator(instance, file_system), |
| buffer_(NULL), |
| bytes_to_read_(0), |
| offset_(0) { |
| cc_factory_.Initialize(this); |
| } |
| |
| int32_t PepperFileReader::Read(const string &filename, string *buffer) { |
| VLOG(2) << "PepperFileReader::Read \"" << filename << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()) |
| << "PepperFileReader::Read() can't be called in the main thread."; |
| filename_ = filename; |
| buffer_ = buffer; |
| pp::Module::Get()->core()->CallOnMainThread( |
| 0, |
| cc_factory_.NewCallback(&PepperFileReader::ReadImpl)); |
| event_.Wait(-1); |
| return result_; |
| } |
| |
| void PepperFileReader::ReadImpl(int32_t result) { |
| VLOG(2) << "PepperFileReader::ReadImpl: " << result; |
| file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); |
| file_io_.reset(new pp::FileIO(instance_)); |
| const int32_t ret = file_io_->Open( |
| *file_ref_, PP_FILEOPENFLAG_READ, |
| cc_factory_.NewCallback(&PepperFileReader::OnFileOpen)); |
| VLOG(2) << "file_io_->Open ret: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| LOG(ERROR) << "file_io_->Open error. ret: " << ret |
| << " [" << filename_ << "]"; |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } |
| |
| void PepperFileReader::OnFileOpen(int32_t result) { |
| VLOG(2) << "PepperFileReader::OnFileOpen: " << result; |
| if (result != PP_OK) { |
| LOG(ERROR) << "PepperFileReader::OnFileOpen error. ret: " << result |
| << " [" << filename_ << "]"; |
| result_ = result; |
| event_.Notify(); |
| return; |
| } |
| CHECK(file_io_.get()); |
| const int32_t ret = file_io_->Query(&file_info_, |
| cc_factory_.NewCallback(&PepperFileReader::OnQuery)); |
| VLOG(2) << "file_io_->Query ret: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| LOG(ERROR) << "file_io_->Query error. ret: " << ret |
| << " [" << filename_ << "]"; |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } |
| |
| void PepperFileReader::OnQuery(int32_t result) { |
| VLOG(2) << "PepperFileReader::OnQuery: " << result; |
| if (result != PP_OK) { |
| LOG(ERROR) << "PepperFileReader::OnQuery error. ret: " << result |
| << " [" << filename_ << "]"; |
| result_ = result; |
| event_.Notify(); |
| return; |
| } |
| bytes_to_read_ = file_info_.size; |
| VLOG(2) << " bytes_to_read_: " << bytes_to_read_; |
| offset_ = 0; |
| buffer_->resize(bytes_to_read_); |
| OnRead(0); |
| } |
| |
| void PepperFileReader::OnRead(int32_t bytes_read) { |
| VLOG(2) << "PepperFileReader::OnRead: " << bytes_read; |
| if (bytes_read < 0) { |
| LOG(ERROR) << "OnRead error. [" << filename_ << "]"; |
| result_ = bytes_read; |
| event_.Notify(); |
| return; |
| } |
| bytes_to_read_ -= bytes_read; |
| VLOG(2) << " bytes_to_read_: " << bytes_to_read_; |
| if (bytes_to_read_ == 0) { |
| result_ = PP_OK; |
| event_.Notify(); |
| return; |
| } else { |
| CHECK(file_io_.get()); |
| offset_ += bytes_read; |
| const int32_t ret = file_io_->Read( |
| offset_, &(*buffer_)[offset_], bytes_to_read_, |
| cc_factory_.NewCallback(&PepperFileReader::OnRead)); |
| VLOG(2) << "file_io_->Read ret: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| LOG(ERROR) << "file_io_->Read error. ret: " << ret |
| << " [" << filename_ << "]"; |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } |
| } |
| |
| |
| class PepperFileWriter : public PepperFileOperator { |
| public: |
| PepperFileWriter(pp::Instance *instance, pp::FileSystem *file_system); |
| virtual ~PepperFileWriter() {} |
| int32_t Write(const string &filename, const string &buffer); |
| |
| private: |
| // Called in Write() |
| void WriteImpl(int32_t result); |
| void OnFileOpen(int32_t result); |
| void OnWrite(int32_t result); |
| void OnFlush(int32_t result); |
| void OnReset(int32_t result); |
| |
| string filename_; |
| const string *buffer_; |
| int64_t offset_; |
| scoped_main_thread_destructed_object<pp::FileIO> file_io_; |
| scoped_main_thread_destructed_object<pp::FileRef> file_ref_; |
| pp::CompletionCallbackFactory<PepperFileWriter> cc_factory_; |
| DISALLOW_COPY_AND_ASSIGN(PepperFileWriter); |
| }; |
| |
| PepperFileWriter::PepperFileWriter(pp::Instance *instance, |
| pp::FileSystem *file_system) |
| : PepperFileOperator(instance, file_system), |
| buffer_(NULL), |
| offset_(0) { |
| cc_factory_.Initialize(this); |
| } |
| |
| int32_t PepperFileWriter::Write(const string &filename, const string &buffer) { |
| VLOG(2) << "PepperFileWriter::Write \"" << filename << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()) |
| << "PepperFileWriter::Write() can't be called in the main thread."; |
| filename_ = filename; |
| buffer_ = &buffer; |
| pp::Module::Get()->core()->CallOnMainThread( |
| 0, |
| cc_factory_.NewCallback(&PepperFileWriter::WriteImpl)); |
| event_.Wait(-1); |
| return result_; |
| } |
| |
| void PepperFileWriter::WriteImpl(int32_t result) { |
| VLOG(2) << "PepperFileWriter::WriteImpl: " << result; |
| file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); |
| file_io_.reset(new pp::FileIO(instance_)); |
| const int32_t ret = file_io_->Open( |
| *file_ref_, PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE, |
| cc_factory_.NewCallback(&PepperFileWriter::OnFileOpen)); |
| VLOG(2) << "file_io_->Open ret: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| LOG(ERROR) << "file_io_->Open error. ret: " << ret |
| << " [" << filename_ << "]"; |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } |
| |
| void PepperFileWriter::OnFileOpen(int32_t result) { |
| VLOG(2) << "PepperFileWriter::OnFileOpen: " << result; |
| if (result != PP_OK) { |
| LOG(ERROR) << "PepperFileWriter::OnFileOpen error. ret: " << result |
| << " [" << filename_ << "]"; |
| result_ = result; |
| event_.Notify(); |
| return; |
| } |
| CHECK(file_io_.get()); |
| const int32_t ret = file_io_->SetLength( |
| 0, cc_factory_.NewCallback(&PepperFileWriter::OnReset)); |
| VLOG(2) << "file_io_->SetLength ret: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| LOG(ERROR) << "file_io_->SetLength error. ret: " << ret |
| << " [" << filename_ << "]"; |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } |
| |
| void PepperFileWriter::OnReset(int32_t result) { |
| VLOG(2) << "PepperFileWriter::OnReset: " << result; |
| if (result != PP_OK) { |
| LOG(ERROR) << "PepperFileWriter::OnReset error. ret: " << result |
| << " [" << filename_ << "]"; |
| result_ = result; |
| event_.Notify(); |
| return; |
| } |
| CHECK(file_io_.get()); |
| offset_ = 0; |
| OnWrite(0); |
| } |
| |
| void PepperFileWriter::OnWrite(int32_t bytes_written) { |
| VLOG(2) << "PepperFileWriter::OnWrite: " << bytes_written; |
| if (bytes_written < 0) { |
| LOG(ERROR) << "WriteCallback error. [" << filename_ << "]"; |
| result_ = bytes_written; |
| event_.Notify(); |
| return; |
| } |
| CHECK(file_io_.get()); |
| offset_ += bytes_written; |
| if (offset_ == buffer_->length()) { |
| const int32_t ret = file_io_->Flush( |
| cc_factory_.NewCallback(&PepperFileWriter::OnFlush)); |
| VLOG(2) << "file_io_->Flush ret: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| LOG(ERROR) << "file_io_->Flush error. ret: " << ret |
| << " [" << filename_ << "]"; |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } else { |
| const int32_t ret = file_io_->Write( |
| offset_, &(*buffer_)[offset_], |
| buffer_->length() - offset_, |
| cc_factory_.NewCallback(&PepperFileWriter::OnWrite)); |
| VLOG(2) << "file_io_->Write ret: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| LOG(ERROR) << "file_io_->Write error. ret: " << ret |
| << " [" << filename_ << "]"; |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } |
| } |
| |
| void PepperFileWriter::OnFlush(int32_t result) { |
| VLOG(2) << "PepperFileWriter::OnFlush: " << result; |
| if (result < 0) { |
| LOG(ERROR) << "FlushCallback error. ret: " << result |
| << " [" << filename_ << "]"; |
| result_ = result; |
| event_.Notify(); |
| return; |
| } |
| result_ = PP_OK; |
| event_.Notify(); |
| return; |
| } |
| |
| class PepperFileQuerer : public PepperFileOperator { |
| public: |
| PepperFileQuerer(pp::Instance *instance, pp::FileSystem *file_system); |
| virtual ~PepperFileQuerer() {} |
| int32_t Query(const string &filename, PP_FileInfo *info); |
| |
| private: |
| // Called in Query() |
| void QueryImpl(int32_t result); |
| void OnFileOpen(int32_t result); |
| void OnQuery(int32_t result); |
| |
| string filename_; |
| PP_FileInfo file_info_; |
| scoped_main_thread_destructed_object<pp::FileIO> file_io_; |
| scoped_main_thread_destructed_object<pp::FileRef> file_ref_; |
| pp::CompletionCallbackFactory<PepperFileQuerer> cc_factory_; |
| DISALLOW_COPY_AND_ASSIGN(PepperFileQuerer); |
| }; |
| |
| PepperFileQuerer::PepperFileQuerer(pp::Instance *instance, |
| pp::FileSystem *file_system) |
| : PepperFileOperator(instance, file_system) { |
| cc_factory_.Initialize(this); |
| } |
| |
| int32_t PepperFileQuerer::Query(const string &filename, PP_FileInfo *info) { |
| VLOG(2) << "PepperFileQuerer::Query \"" << filename << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()) |
| << "PepperFileQuerer::Query() can't be called in the main thread."; |
| filename_ = filename; |
| pp::Module::Get()->core()->CallOnMainThread( |
| 0, |
| cc_factory_.NewCallback(&PepperFileQuerer::QueryImpl)); |
| event_.Wait(-1); |
| if (result_ == PP_OK) { |
| *info = file_info_; |
| } |
| return result_; |
| } |
| |
| void PepperFileQuerer::QueryImpl(int32_t result) { |
| VLOG(2) << "PepperFileQuerer::QueryImpl: " << result; |
| file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); |
| file_io_.reset(new pp::FileIO(instance_)); |
| const int32_t ret = file_io_->Open( |
| *file_ref_, PP_FILEOPENFLAG_READ, |
| cc_factory_.NewCallback(&PepperFileQuerer::OnFileOpen)); |
| VLOG(2) << "file_io_->Open ret: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| LOG(ERROR) << "file_io_->Open error. ret: " << ret |
| << " [" << filename_ << "]"; |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } |
| |
| void PepperFileQuerer::OnFileOpen(int32_t result) { |
| VLOG(2) << "PepperFileQuerer::OnFileOpen: " << result; |
| if (result != PP_OK) { |
| LOG(ERROR) << "PepperFileQuerer::OnFileOpen error. ret: " << result |
| << " [" << filename_ << "]"; |
| result_ = result; |
| event_.Notify(); |
| return; |
| } |
| CHECK(file_io_.get()); |
| const int32_t ret = file_io_->Query(&file_info_, |
| cc_factory_.NewCallback(&PepperFileQuerer::OnQuery)); |
| VLOG(2) << "file_io_->Query: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| LOG(ERROR) << "file_io_->Query error. ret: " << ret |
| << " [" << filename_ << "]"; |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } |
| |
| void PepperFileQuerer::OnQuery(int32_t result) { |
| VLOG(2) << "PepperFileQuerer::OnQuery: " << result; |
| result_ = result; |
| event_.Notify(); |
| return; |
| } |
| |
| class PepperFileRenamer : public PepperFileOperator { |
| public: |
| PepperFileRenamer(pp::Instance *instance, pp::FileSystem *file_system); |
| virtual ~PepperFileRenamer() {} |
| int32_t Rename(const string &filename, const string &new_filename); |
| |
| private: |
| // Called in Rename() |
| void RenameImpl(int32_t result); |
| void OnRename(int32_t result); |
| |
| string filename_; |
| string new_filename_; |
| scoped_main_thread_destructed_object<pp::FileRef> file_ref_; |
| scoped_main_thread_destructed_object<pp::FileRef> new_file_ref_; |
| pp::CompletionCallbackFactory<PepperFileRenamer> cc_factory_; |
| DISALLOW_COPY_AND_ASSIGN(PepperFileRenamer); |
| }; |
| |
| PepperFileRenamer::PepperFileRenamer(pp::Instance *instance, |
| pp::FileSystem *file_system) |
| : PepperFileOperator(instance, file_system) { |
| cc_factory_.Initialize(this); |
| } |
| |
| int32_t PepperFileRenamer::Rename(const string &filename, |
| const string &new_filename) { |
| VLOG(2) << "PepperFileRenamer::Rename from \"" << filename << "\"" |
| << " to \"" << new_filename << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()) |
| << "PepperFileRenamer::Rename() can't be called in the main thread."; |
| filename_ = filename; |
| new_filename_ = new_filename; |
| pp::Module::Get()->core()->CallOnMainThread( |
| 0, |
| cc_factory_.NewCallback(&PepperFileRenamer::RenameImpl)); |
| event_.Wait(-1); |
| return result_; |
| } |
| |
| void PepperFileRenamer::RenameImpl(int32_t result) { |
| VLOG(2) << "PepperFileRenamer::RenameImpl: " << result; |
| file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); |
| new_file_ref_.reset(new pp::FileRef(*file_system_, new_filename_.c_str())); |
| const int32_t ret = file_ref_->Rename( |
| *new_file_ref_, |
| cc_factory_.NewCallback(&PepperFileRenamer::OnRename)); |
| VLOG(2) << "file_ref_->Rename ret: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } |
| |
| void PepperFileRenamer::OnRename(int32_t result) { |
| VLOG(2) << "PepperFileRenamer::OnRename: " << result; |
| result_ = result; |
| event_.Notify(); |
| return; |
| } |
| |
| class PepperFileDeleter : public PepperFileOperator { |
| public: |
| PepperFileDeleter(pp::Instance *instance, pp::FileSystem *file_system); |
| virtual ~PepperFileDeleter() {} |
| int32_t Delete(const string &filename); |
| |
| private: |
| // Called in Delete() |
| void DeleteImpl(int32_t result); |
| void OnDelete(int32_t result); |
| |
| string filename_; |
| scoped_main_thread_destructed_object<pp::FileRef> file_ref_; |
| pp::CompletionCallbackFactory<PepperFileDeleter> cc_factory_; |
| DISALLOW_COPY_AND_ASSIGN(PepperFileDeleter); |
| }; |
| |
| PepperFileDeleter::PepperFileDeleter(pp::Instance *instance, |
| pp::FileSystem *file_system) |
| : PepperFileOperator(instance, file_system) { |
| cc_factory_.Initialize(this); |
| } |
| |
| int32_t PepperFileDeleter::Delete(const string &filename) { |
| VLOG(2) << "PepperFileDeleter::Delete \"" << filename << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()) |
| << "PepperFileDeleter::Delete() can't be called in the main thread."; |
| filename_ = filename; |
| pp::Module::Get()->core()->CallOnMainThread( |
| 0, |
| cc_factory_.NewCallback(&PepperFileDeleter::DeleteImpl)); |
| event_.Wait(-1); |
| return result_; |
| } |
| |
| void PepperFileDeleter::DeleteImpl(int32_t result) { |
| VLOG(2) << "PepperFileDeleter::DeleteImpl: " << result; |
| file_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); |
| const int32_t ret = file_ref_->Delete( |
| cc_factory_.NewCallback(&PepperFileDeleter::OnDelete)); |
| VLOG(2) << "file_ref_->Delete ret: " << ret; |
| if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) { |
| result_ = ret; |
| event_.Notify(); |
| return; |
| } |
| } |
| |
| void PepperFileDeleter::OnDelete(int32_t result) { |
| VLOG(2) << "PepperFileDeleter::OnDelete: " << result; |
| result_ = result; |
| event_.Notify(); |
| return; |
| } |
| |
| class PepperFileSystem : public PepperFileSystemInterface { |
| public: |
| PepperFileSystem(); |
| virtual ~PepperFileSystem(); |
| virtual bool Open(pp::Instance *instance, int64 expected_size); |
| virtual bool FileExists(const string &filename); |
| virtual bool DirectoryExists(const string &dirname); |
| virtual bool ReadBinaryFile(const string &filename, string *buffer); |
| virtual bool WriteBinaryFile(const string &filename, const string &buffer); |
| virtual bool DeleteFile(const string &filename); |
| virtual bool RenameFile(const string &from, const string &to); |
| virtual bool RegisterMmap(Mmap *mmap); |
| virtual bool UnRegisterMmap(Mmap *mmap); |
| virtual bool SyncMmapToFile(); |
| |
| private: |
| // Called in Open() |
| void OpenImpl(int32_t result, int64_t expected_size, int32_t *ret_result); |
| void OnOpen(int32_t result, int32_t *ret_result); |
| |
| scoped_main_thread_destructed_object<pp::FileSystem> file_system_; |
| pp::CompletionCallbackFactory<PepperFileSystem> cc_factory_; |
| UnnamedEvent event_; |
| pp::Instance *instance_; |
| set<Mmap*> mmap_set_; |
| Mutex mutex_; |
| DISALLOW_COPY_AND_ASSIGN(PepperFileSystem); |
| }; |
| |
| PepperFileSystem::PepperFileSystem() { |
| VLOG(2) << "PepperFileSystem::PepperFileSystem"; |
| cc_factory_.Initialize(this); |
| } |
| |
| PepperFileSystem::~PepperFileSystem() { |
| VLOG(2) << "PepperFileSystem::~PepperFileSystem"; |
| } |
| |
| bool PepperFileSystem::Open(pp::Instance *instance, int64 expected_size) { |
| VLOG(2) << "PepperFileSystem::Open"; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()) |
| << "PepperFileSystem::Open() can't be called in the main thread."; |
| CHECK(instance); |
| instance_ = instance; |
| int32_t ret_result = PP_ERROR_FAILED; |
| pp::Module::Get()->core()->CallOnMainThread( |
| 0, |
| cc_factory_.NewCallback(&PepperFileSystem::OpenImpl, |
| expected_size, |
| &ret_result)); |
| event_.Wait(-1); |
| return ret_result == PP_OK; |
| } |
| |
| void PepperFileSystem::OpenImpl(int32_t result, |
| int64_t expected_size, |
| int32_t *ret_result) { |
| VLOG(2) << "PepperFileSystem::OpenImpl"; |
| file_system_.reset( |
| new pp::FileSystem(instance_, PP_FILESYSTEMTYPE_LOCALPERSISTENT)); |
| const int32_t open_result = file_system_->Open( |
| expected_size, |
| cc_factory_.NewCallback(&PepperFileSystem::OnOpen, ret_result)); |
| VLOG(2) << "file_system_->Open ret:" << open_result; |
| if ((open_result != PP_OK_COMPLETIONPENDING) && (open_result != PP_OK)) { |
| *ret_result = open_result; |
| event_.Notify(); |
| } |
| } |
| |
| void PepperFileSystem::OnOpen(int32_t result, int32_t *ret_result) { |
| VLOG(2) << "PepperFileSystem::OnOpen: " << result; |
| CHECK(ret_result); |
| *ret_result = result; |
| event_.Notify(); |
| } |
| |
| bool PepperFileSystem::FileExists(const string &filename) { |
| VLOG(2) << "PepperFileSystem::FileExists \"" << filename << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()); |
| CHECK(file_system_.get()) << "PepperFileSystem is not initialized yet"; |
| PP_FileInfo info; |
| PepperFileQuerer querer(instance_, file_system_.get()); |
| return querer.Query(filename, &info) == PP_OK; |
| } |
| |
| bool PepperFileSystem::DirectoryExists(const string &dirname) { |
| VLOG(2) << "PepperFileSystem::DirectoryExists \"" << dirname << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()); |
| CHECK(file_system_.get()) << "PepperFileSystem is not initialized yet"; |
| PP_FileInfo info; |
| PepperFileQuerer querer(instance_, file_system_.get()); |
| const int32_t ret = querer.Query(dirname, &info); |
| if (ret != PP_OK) { |
| return false; |
| } |
| return info.type == PP_FILETYPE_DIRECTORY; |
| } |
| |
| bool PepperFileSystem::ReadBinaryFile(const string &filename, string *buffer) { |
| VLOG(2) << "PepperFileSystem::ReadBinaryFile \"" << filename << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()); |
| CHECK(file_system_.get()) << "PepperFileSystem is not initialized yet"; |
| CHECK(buffer); |
| PepperFileReader reader(instance_, file_system_.get()); |
| return reader.Read(filename, buffer) == PP_OK; |
| } |
| |
| bool PepperFileSystem::WriteBinaryFile(const string &filename, |
| const string &buffer) { |
| VLOG(2) << "PepperFileSystem::WriteBinaryFile \"" << filename << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()); |
| CHECK(file_system_.get()) << "PepperFileSystem is not initialized yet"; |
| PepperFileWriter writer(instance_, file_system_.get()); |
| return writer.Write(filename, buffer) == PP_OK; |
| } |
| |
| bool PepperFileSystem::DeleteFile(const string &filename) { |
| VLOG(2) << "PepperFileSystem::DeleteFile \"" << filename << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()); |
| CHECK(file_system_.get()) << "PepperFileSystem is not initialized yet"; |
| PepperFileDeleter deleter(instance_, file_system_.get()); |
| return deleter.Delete(filename) == PP_OK; |
| } |
| |
| bool PepperFileSystem::RenameFile(const string &from, const string &to) { |
| VLOG(2) << "PepperFileSystem::RenameFile from \"" << from << "\"" |
| << " to \"" << to << "\""; |
| CHECK(!pp::Module::Get()->core()->IsMainThread()); |
| CHECK(file_system_.get()) << "PepperFileSystem is not initialized yet"; |
| PepperFileRenamer renamer(instance_, file_system_.get()); |
| return renamer.Rename(from, to) == PP_OK; |
| } |
| |
| bool PepperFileSystem::RegisterMmap(Mmap *mmap) { |
| scoped_lock lock(&mutex_); |
| return mmap_set_.insert(mmap).second; |
| } |
| |
| bool PepperFileSystem::UnRegisterMmap(Mmap *mmap) { |
| scoped_lock lock(&mutex_); |
| return mmap_set_.erase(mmap); |
| } |
| |
| bool PepperFileSystem::SyncMmapToFile() { |
| scoped_lock lock(&mutex_); |
| for (set<Mmap*>::iterator it = mmap_set_.begin(); |
| it != mmap_set_.end(); ++it) { |
| (*it)->SyncToFile(); |
| } |
| return true; |
| } |
| |
| PepperFileSystemInterface *g_pepper_file_system = NULL; |
| |
| PepperFileSystemInterface *GetPepperFileSystem() { |
| if (g_pepper_file_system != NULL) { |
| return g_pepper_file_system; |
| } else { |
| return Singleton<PepperFileSystem>::get(); |
| } |
| } |
| } // namespace |
| |
| void PepperFileUtil::SetPepperFileSystemInterfaceForTest( |
| PepperFileSystemInterface *mock_interface) { |
| g_pepper_file_system = mock_interface; |
| } |
| |
| bool PepperFileUtil::Initialize(pp::Instance *instance, int64 expected_size) { |
| const bool result = GetPepperFileSystem()->Open(instance, expected_size); |
| if (!result) { |
| VLOG(2) << "PepperFileSystem::Open error"; |
| } |
| return result; |
| } |
| |
| bool PepperFileUtil::FileExists(const string &filename) { |
| return GetPepperFileSystem()->FileExists(filename); |
| } |
| |
| bool PepperFileUtil::DirectoryExists(const string &dirname) { |
| return GetPepperFileSystem()->DirectoryExists(dirname); |
| } |
| |
| bool PepperFileUtil::ReadBinaryFile(const string &filename, string *buffer) { |
| return GetPepperFileSystem()->ReadBinaryFile(filename, buffer); |
| } |
| |
| bool PepperFileUtil::WriteBinaryFile(const string &filename, |
| const string &buffer) { |
| DeleteFile(filename); |
| return GetPepperFileSystem()->WriteBinaryFile(filename, buffer); |
| } |
| |
| bool PepperFileUtil::DeleteFile(const string &filename) { |
| return GetPepperFileSystem()->DeleteFile(filename); |
| } |
| |
| bool PepperFileUtil::RenameFile(const string &from, const string &to) { |
| return GetPepperFileSystem()->RenameFile(from, to); |
| } |
| |
| bool PepperFileUtil::RegisterMmap(Mmap *mmap) { |
| return GetPepperFileSystem()->RegisterMmap(mmap); |
| } |
| |
| bool PepperFileUtil::UnRegisterMmap(Mmap *mmap) { |
| return GetPepperFileSystem()->UnRegisterMmap(mmap); |
| } |
| |
| bool PepperFileUtil::SyncMmapToFile() { |
| return GetPepperFileSystem()->SyncMmapToFile(); |
| } |
| |
| } // namespace mozc |