1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ppapi/cpp/file_io.h" 6 7#include <string.h> // memcpy 8 9#include "ppapi/c/ppb_file_io.h" 10#include "ppapi/c/pp_errors.h" 11#include "ppapi/cpp/completion_callback.h" 12#include "ppapi/cpp/file_ref.h" 13#include "ppapi/cpp/instance_handle.h" 14#include "ppapi/cpp/module.h" 15#include "ppapi/cpp/module_impl.h" 16 17namespace pp { 18 19namespace { 20 21template <> const char* interface_name<PPB_FileIO_1_0>() { 22 return PPB_FILEIO_INTERFACE_1_0; 23} 24 25template <> const char* interface_name<PPB_FileIO_1_1>() { 26 return PPB_FILEIO_INTERFACE_1_1; 27} 28 29} // namespace 30 31FileIO::FileIO() { 32} 33 34FileIO::FileIO(const InstanceHandle& instance) { 35 if (has_interface<PPB_FileIO_1_1>()) { 36 PassRefFromConstructor(get_interface<PPB_FileIO_1_1>()->Create( 37 instance.pp_instance())); 38 } else if (has_interface<PPB_FileIO_1_0>()) { 39 PassRefFromConstructor(get_interface<PPB_FileIO_1_0>()->Create( 40 instance.pp_instance())); 41 } 42} 43 44FileIO::FileIO(const FileIO& other) 45 : Resource(other) { 46} 47 48int32_t FileIO::Open(const FileRef& file_ref, 49 int32_t open_flags, 50 const CompletionCallback& cc) { 51 if (has_interface<PPB_FileIO_1_1>()) { 52 return get_interface<PPB_FileIO_1_1>()->Open( 53 pp_resource(), file_ref.pp_resource(), open_flags, 54 cc.pp_completion_callback()); 55 } else if (has_interface<PPB_FileIO_1_0>()) { 56 return get_interface<PPB_FileIO_1_0>()->Open( 57 pp_resource(), file_ref.pp_resource(), open_flags, 58 cc.pp_completion_callback()); 59 } 60 return cc.MayForce(PP_ERROR_NOINTERFACE); 61} 62 63int32_t FileIO::Query(PP_FileInfo* result_buf, 64 const CompletionCallback& cc) { 65 if (has_interface<PPB_FileIO_1_1>()) { 66 return get_interface<PPB_FileIO_1_1>()->Query( 67 pp_resource(), result_buf, cc.pp_completion_callback()); 68 } else if (has_interface<PPB_FileIO_1_0>()) { 69 return get_interface<PPB_FileIO_1_0>()->Query( 70 pp_resource(), result_buf, cc.pp_completion_callback()); 71 } 72 return cc.MayForce(PP_ERROR_NOINTERFACE); 73} 74 75int32_t FileIO::Touch(PP_Time last_access_time, 76 PP_Time last_modified_time, 77 const CompletionCallback& cc) { 78 if (has_interface<PPB_FileIO_1_1>()) { 79 return get_interface<PPB_FileIO_1_1>()->Touch( 80 pp_resource(), last_access_time, last_modified_time, 81 cc.pp_completion_callback()); 82 } else if (has_interface<PPB_FileIO_1_0>()) { 83 return get_interface<PPB_FileIO_1_0>()->Touch( 84 pp_resource(), last_access_time, last_modified_time, 85 cc.pp_completion_callback()); 86 } 87 return cc.MayForce(PP_ERROR_NOINTERFACE); 88} 89 90int32_t FileIO::Read(int64_t offset, 91 char* buffer, 92 int32_t bytes_to_read, 93 const CompletionCallback& cc) { 94 if (has_interface<PPB_FileIO_1_1>()) { 95 return get_interface<PPB_FileIO_1_1>()->Read(pp_resource(), 96 offset, buffer, bytes_to_read, cc.pp_completion_callback()); 97 } else if (has_interface<PPB_FileIO_1_0>()) { 98 return get_interface<PPB_FileIO_1_0>()->Read(pp_resource(), 99 offset, buffer, bytes_to_read, cc.pp_completion_callback()); 100 } 101 return cc.MayForce(PP_ERROR_NOINTERFACE); 102} 103 104int32_t FileIO::Read( 105 int32_t offset, 106 int32_t max_read_length, 107 const CompletionCallbackWithOutput< std::vector<char> >& cc) { 108 if (has_interface<PPB_FileIO_1_1>()) { 109 PP_ArrayOutput array_output = cc.output(); 110 return get_interface<PPB_FileIO_1_1>()->ReadToArray(pp_resource(), 111 offset, max_read_length, &array_output, 112 cc.pp_completion_callback()); 113 } else if (has_interface<PPB_FileIO_1_0>()) { 114 // Data for our callback wrapper. The callback handler will delete it and 115 // temp_buffer. 116 CallbackData1_0* data = new CallbackData1_0; 117 data->output = cc.output(); 118 data->temp_buffer = max_read_length >= 0 ? new char[max_read_length] : NULL; 119 data->original_callback = cc.pp_completion_callback(); 120 121 // Actual returned bytes might not equals to max_read_length. We need to 122 // read to a temporary buffer first and copy later to make sure the array 123 // buffer has correct size. 124 return get_interface<PPB_FileIO_1_0>()->Read( 125 pp_resource(), offset, data->temp_buffer, max_read_length, 126 PP_MakeCompletionCallback(&CallbackConverter, data)); 127 } 128 return cc.MayForce(PP_ERROR_NOINTERFACE); 129} 130 131int32_t FileIO::Write(int64_t offset, 132 const char* buffer, 133 int32_t bytes_to_write, 134 const CompletionCallback& cc) { 135 if (has_interface<PPB_FileIO_1_1>()) { 136 return get_interface<PPB_FileIO_1_1>()->Write( 137 pp_resource(), offset, buffer, bytes_to_write, 138 cc.pp_completion_callback()); 139 } else if (has_interface<PPB_FileIO_1_0>()) { 140 return get_interface<PPB_FileIO_1_0>()->Write( 141 pp_resource(), offset, buffer, bytes_to_write, 142 cc.pp_completion_callback()); 143 } 144 return cc.MayForce(PP_ERROR_NOINTERFACE); 145} 146 147int32_t FileIO::SetLength(int64_t length, 148 const CompletionCallback& cc) { 149 if (has_interface<PPB_FileIO_1_1>()) { 150 return get_interface<PPB_FileIO_1_1>()->SetLength( 151 pp_resource(), length, cc.pp_completion_callback()); 152 } else if (has_interface<PPB_FileIO_1_0>()) { 153 return get_interface<PPB_FileIO_1_0>()->SetLength( 154 pp_resource(), length, cc.pp_completion_callback()); 155 } 156 return cc.MayForce(PP_ERROR_NOINTERFACE); 157} 158 159int32_t FileIO::Flush(const CompletionCallback& cc) { 160 if (has_interface<PPB_FileIO_1_1>()) { 161 return get_interface<PPB_FileIO_1_1>()->Flush( 162 pp_resource(), cc.pp_completion_callback()); 163 } else if (has_interface<PPB_FileIO_1_0>()) { 164 return get_interface<PPB_FileIO_1_0>()->Flush( 165 pp_resource(), cc.pp_completion_callback()); 166 } 167 return cc.MayForce(PP_ERROR_NOINTERFACE); 168} 169 170void FileIO::Close() { 171 if (has_interface<PPB_FileIO_1_1>()) 172 get_interface<PPB_FileIO_1_1>()->Close(pp_resource()); 173 else if (has_interface<PPB_FileIO_1_0>()) 174 get_interface<PPB_FileIO_1_0>()->Close(pp_resource()); 175} 176 177// static 178void FileIO::CallbackConverter(void* user_data, int32_t result) { 179 CallbackData1_0* data = static_cast<CallbackData1_0*>(user_data); 180 181 if (result >= 0) { 182 // Copy to the destination buffer owned by the callback. 183 char* buffer = static_cast<char*>(data->output.GetDataBuffer( 184 data->output.user_data, result, sizeof(char))); 185 memcpy(buffer, data->temp_buffer, result); 186 delete[] data->temp_buffer; 187 } 188 189 // Now execute the original callback. 190 PP_RunCompletionCallback(&data->original_callback, result); 191 delete data; 192} 193 194} // namespace pp 195