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