| // Copyright 2016 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 "fake_ppapi/fake_file_io_interface.h" |
| |
| #include <ppapi/c/pp_completion_callback.h> |
| #include <ppapi/c/pp_errors.h> |
| |
| #include "gtest/gtest.h" |
| |
| #include "fake_ppapi/fake_core_interface.h" |
| #include "fake_ppapi/fake_filesystem.h" |
| #include "fake_ppapi/fake_node.h" |
| #include "fake_ppapi/fake_util.h" |
| |
| namespace { |
| |
| class FakeFileIoResource : public FakeResource { |
| public: |
| FakeFileIoResource() : node(NULL), open_flags(0) {} |
| static const char* classname() { return "FakeFileIoResource"; } |
| |
| FakeNode* node; // Weak reference. |
| int32_t open_flags; |
| }; |
| |
| } // namespace |
| |
| FakeFileIoInterface::FakeFileIoInterface(FakeCoreInterface* core_interface) |
| : core_interface_(core_interface) {} |
| |
| PP_Resource FakeFileIoInterface::Create(PP_Resource) { |
| return CREATE_RESOURCE(core_interface_->resource_manager(), |
| FakeFileIoResource, new FakeFileIoResource); |
| } |
| |
| int32_t FakeFileIoInterface::Open(PP_Resource file_io, |
| PP_Resource file_ref, |
| int32_t open_flags, |
| PP_CompletionCallback callback) { |
| FakeFileIoResource* file_io_resource = |
| core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io); |
| if (file_io_resource == NULL) |
| return PP_ERROR_BADRESOURCE; |
| |
| bool flag_write = !!(open_flags & PP_FILEOPENFLAG_WRITE); |
| bool flag_create = !!(open_flags & PP_FILEOPENFLAG_CREATE); |
| bool flag_truncate = !!(open_flags & PP_FILEOPENFLAG_TRUNCATE); |
| bool flag_exclusive = !!(open_flags & PP_FILEOPENFLAG_EXCLUSIVE); |
| bool flag_append = !!(open_flags & PP_FILEOPENFLAG_APPEND); |
| |
| if ((flag_append && flag_write) || (flag_truncate && !flag_write)) |
| return PP_ERROR_BADARGUMENT; |
| |
| FakeFileRefResource* file_ref_resource = |
| core_interface_->resource_manager()->Get<FakeFileRefResource>(file_ref); |
| |
| if (file_ref_resource == NULL) |
| return PP_ERROR_BADRESOURCE; |
| |
| const FakeFilesystem::Path& path = file_ref_resource->path; |
| FakeFilesystem* filesystem = file_ref_resource->filesystem; |
| FakeNode* node = filesystem->GetNode(path); |
| bool node_exists = node != NULL; |
| |
| if (!node_exists) { |
| if (!flag_create) |
| return RunCompletionCallback(&callback, PP_ERROR_FILENOTFOUND); |
| |
| bool result = filesystem->AddEmptyFile(path, &node); |
| EXPECT_EQ(true, result); |
| } else { |
| if (flag_create && flag_exclusive) |
| return RunCompletionCallback(&callback, PP_ERROR_FILEEXISTS); |
| } |
| |
| file_io_resource->node = node; |
| file_io_resource->open_flags = open_flags; |
| |
| if (flag_truncate) |
| return RunCompletionCallback(&callback, node->SetLength(0)); |
| |
| return RunCompletionCallback(&callback, PP_OK); |
| } |
| |
| int32_t FakeFileIoInterface::Query(PP_Resource file_io, |
| PP_FileInfo* info, |
| PP_CompletionCallback callback) { |
| FakeFileIoResource* file_io_resource = |
| core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io); |
| if (file_io_resource == NULL) |
| return PP_ERROR_BADRESOURCE; |
| |
| if (!file_io_resource->node) |
| return RunCompletionCallback(&callback, PP_ERROR_FAILED); |
| |
| file_io_resource->node->GetInfo(info); |
| return RunCompletionCallback(&callback, PP_OK); |
| } |
| |
| int32_t FakeFileIoInterface::Read(PP_Resource file_io, |
| int64_t offset, |
| char* buffer, |
| int32_t bytes_to_read, |
| PP_CompletionCallback callback) { |
| FakeFileIoResource* file_io_resource = |
| core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io); |
| |
| if (file_io_resource == NULL) |
| return PP_ERROR_BADRESOURCE; |
| |
| if (bytes_to_read < 0) |
| return RunCompletionCallback(&callback, PP_ERROR_FAILED); |
| |
| if ((file_io_resource->open_flags & PP_FILEOPENFLAG_READ) != |
| PP_FILEOPENFLAG_READ) { |
| return RunCompletionCallback(&callback, PP_ERROR_NOACCESS); |
| } |
| |
| if (!file_io_resource->node) |
| return RunCompletionCallback(&callback, PP_ERROR_FAILED); |
| |
| int32_t result = file_io_resource->node->Read(offset, buffer, bytes_to_read); |
| |
| return RunCompletionCallback(&callback, result); |
| } |
| |
| int32_t FakeFileIoInterface::Write(PP_Resource file_io, |
| int64_t offset, |
| const char* buffer, |
| int32_t bytes_to_write, |
| PP_CompletionCallback callback) { |
| FakeFileIoResource* file_io_resource = |
| core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io); |
| if (file_io_resource == NULL) |
| return PP_ERROR_BADRESOURCE; |
| |
| if ((file_io_resource->open_flags & PP_FILEOPENFLAG_WRITE) != |
| PP_FILEOPENFLAG_WRITE) { |
| return RunCompletionCallback(&callback, PP_ERROR_NOACCESS); |
| } |
| |
| if (!file_io_resource->node) |
| return RunCompletionCallback(&callback, PP_ERROR_FAILED); |
| |
| int32_t result; |
| if ((file_io_resource->open_flags & PP_FILEOPENFLAG_APPEND) == |
| PP_FILEOPENFLAG_APPEND) { |
| result = file_io_resource->node->Append(buffer, bytes_to_write); |
| } else { |
| result = file_io_resource->node->Write(offset, buffer, bytes_to_write); |
| } |
| |
| return RunCompletionCallback(&callback, result); |
| } |
| |
| int32_t FakeFileIoInterface::SetLength(PP_Resource file_io, |
| int64_t length, |
| PP_CompletionCallback callback) { |
| FakeFileIoResource* file_io_resource = |
| core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io); |
| if (file_io_resource == NULL) |
| return PP_ERROR_BADRESOURCE; |
| |
| if ((file_io_resource->open_flags & PP_FILEOPENFLAG_WRITE) != |
| PP_FILEOPENFLAG_WRITE) { |
| return RunCompletionCallback(&callback, PP_ERROR_NOACCESS); |
| } |
| |
| if (!file_io_resource->node) |
| return RunCompletionCallback(&callback, PP_ERROR_FAILED); |
| |
| int32_t result = file_io_resource->node->SetLength(length); |
| return RunCompletionCallback(&callback, result); |
| } |
| |
| int32_t FakeFileIoInterface::Flush(PP_Resource file_io, |
| PP_CompletionCallback callback) { |
| FakeFileIoResource* file_io_resource = |
| core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io); |
| if (file_io_resource == NULL) |
| return PP_ERROR_BADRESOURCE; |
| |
| if (!file_io_resource->node) |
| return RunCompletionCallback(&callback, PP_ERROR_FAILED); |
| |
| return RunCompletionCallback(&callback, PP_OK); |
| } |
| |
| void FakeFileIoInterface::Close(PP_Resource file_io) { |
| FakeFileIoResource* file_io_resource = |
| core_interface_->resource_manager()->Get<FakeFileIoResource>(file_io); |
| |
| if (file_io_resource == NULL) |
| return; |
| |
| file_io_resource->node = NULL; |
| file_io_resource->open_flags = 0; |
| } |