| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "nacl_io/devfs/jspipe_event_emitter.h" | 5 #include "nacl_io/devfs/jspipe_event_emitter.h" |
| 6 | 6 |
| 7 #include <assert.h> | 7 #include <assert.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <string.h> | 9 #include <string.h> |
| 10 | 10 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 if (err != 0) | 105 if (err != 0) |
| 106 ERROR("Sending ACK failed: %d\n", err.error); | 106 ERROR("Sending ACK failed: %d\n", err.error); |
| 107 } | 107 } |
| 108 | 108 |
| 109 UpdateStatus_Locked(); | 109 UpdateStatus_Locked(); |
| 110 return 0; | 110 return 0; |
| 111 } | 111 } |
| 112 | 112 |
| 113 Error JSPipeEventEmitter::SendWriteMessage(const void* buf, size_t count) { | 113 Error JSPipeEventEmitter::SendWriteMessage(const void* buf, size_t count) { |
| 114 TRACE("SendWriteMessage [%" PRIuS "] total=%" PRIuS, count, bytes_sent_); | 114 TRACE("SendWriteMessage [%" PRIuS "] total=%" PRIuS, count, bytes_sent_); |
| 115 if (!var_iface_ || !buffer_iface_) | 115 if (!var_iface_ || !buffer_iface_) { |
| 116 ERROR("Got NULL interface(s): %s%s", |
| 117 var_iface_ ? "" : "Var ", |
| 118 buffer_iface_ ? "" : "ArrayBuffer"); |
| 116 return EIO; | 119 return EIO; |
| 120 } |
| 117 | 121 |
| 118 // Copy payload data in a new ArrayBuffer | 122 // Copy payload data in a new ArrayBuffer |
| 119 PP_Var buffer = buffer_iface_->Create(count); | 123 PP_Var buffer = buffer_iface_->Create(count); |
| 120 memcpy(buffer_iface_->Map(buffer), buf, count); | 124 memcpy(buffer_iface_->Map(buffer), buf, count); |
| 121 buffer_iface_->Unmap(buffer); | 125 buffer_iface_->Unmap(buffer); |
| 122 | 126 |
| 123 Error rtn = SendMessageToJS(write_var_, buffer); | 127 Error rtn = SendMessageToJS(write_var_, buffer); |
| 124 var_iface_->Release(buffer); | 128 var_iface_->Release(buffer); |
| 125 return rtn; | 129 return rtn; |
| 126 } | 130 } |
| 127 | 131 |
| 128 Error JSPipeEventEmitter::SetName(const char* name) { | 132 Error JSPipeEventEmitter::SetName(const char* name) { |
| 129 if (var_iface_ == NULL) | 133 if (var_iface_ == NULL) { |
| 134 // No error here: many of the tests trigger this message. |
| 135 LOG_TRACE("Got NULL interface: Var"); |
| 130 return EIO; | 136 return EIO; |
| 137 } |
| 131 | 138 |
| 132 // name can only be set once | 139 // name can only be set once |
| 133 if (!name_.empty()) | 140 if (!name_.empty()) { |
| 141 LOG_ERROR("Attempting to set name more than once."); |
| 134 return EIO; | 142 return EIO; |
| 143 } |
| 135 | 144 |
| 136 // new name must not be empty | 145 // new name must not be empty |
| 137 if (!name || strlen(name) == 0) | 146 if (!name || strlen(name) == 0) { |
| 147 LOG_ERROR("Empty name is invalid."); |
| 138 return EIO; | 148 return EIO; |
| 149 } |
| 139 | 150 |
| 140 TRACE("set name: %s", name); | 151 TRACE("set name: %s", name); |
| 141 name_ = name; | 152 name_ = name; |
| 142 pipe_name_var_ = VarFromCStr(name); | 153 pipe_name_var_ = VarFromCStr(name); |
| 143 return 0; | 154 return 0; |
| 144 } | 155 } |
| 145 | 156 |
| 146 Error JSPipeEventEmitter::SendMessageToJS(PP_Var operation, PP_Var payload) { | 157 Error JSPipeEventEmitter::SendMessageToJS(PP_Var operation, PP_Var payload) { |
| 147 if (!ppapi_ || !messaging_iface_ || !var_iface_ || !dict_iface_) | 158 if (!ppapi_) { |
| 159 LOG_ERROR("ppapi_ is NULL."); |
| 148 return EIO; | 160 return EIO; |
| 161 } |
| 162 |
| 163 if (!messaging_iface_ || !var_iface_ || !dict_iface_) { |
| 164 LOG_ERROR("Got NULL interface(s): %s%s%s", |
| 165 messaging_iface_ ? "" : "Messaging ", |
| 166 dict_iface_ ? "" : "Dictionary ", |
| 167 var_iface_ ? "" : "Var"); |
| 168 return EIO; |
| 169 } |
| 149 | 170 |
| 150 // Create dict object which will be sent to JavaScript. | 171 // Create dict object which will be sent to JavaScript. |
| 151 PP_Var dict = dict_iface_->Create(); | 172 PP_Var dict = dict_iface_->Create(); |
| 152 | 173 |
| 153 // Set three keys in the dictionary: 'pipe', 'operation', and 'payload' | 174 // Set three keys in the dictionary: 'pipe', 'operation', and 'payload' |
| 154 dict_iface_->Set(dict, pipe_key_, pipe_name_var_); | 175 dict_iface_->Set(dict, pipe_key_, pipe_name_var_); |
| 155 dict_iface_->Set(dict, operation_key_, operation); | 176 dict_iface_->Set(dict, operation_key_, operation); |
| 156 dict_iface_->Set(dict, payload_key_, payload); | 177 dict_iface_->Set(dict, payload_key_, payload); |
| 157 | 178 |
| 158 // Send the dict via PostMessage | 179 // Send the dict via PostMessage |
| (...skipping 14 matching lines...) Expand all Loading... |
| 173 } | 194 } |
| 174 | 195 |
| 175 size_t JSPipeEventEmitter::HandleJSWrite(const char* data, size_t len) { | 196 size_t JSPipeEventEmitter::HandleJSWrite(const char* data, size_t len) { |
| 176 size_t out_len = input_fifo_.Write(data, len); | 197 size_t out_len = input_fifo_.Write(data, len); |
| 177 UpdateStatus_Locked(); | 198 UpdateStatus_Locked(); |
| 178 return out_len; | 199 return out_len; |
| 179 } | 200 } |
| 180 | 201 |
| 181 void JSPipeEventEmitter::HandleJSAck(size_t byte_count) { | 202 void JSPipeEventEmitter::HandleJSAck(size_t byte_count) { |
| 182 if (byte_count > bytes_sent_) { | 203 if (byte_count > bytes_sent_) { |
| 183 ERROR("HandleAck unexpected byte count: %" PRIuS, byte_count); | 204 ERROR("Unexpected byte count: %" PRIuS, byte_count); |
| 184 return; | 205 return; |
| 185 } | 206 } |
| 186 | 207 |
| 187 bytes_acked_ = byte_count; | 208 bytes_acked_ = byte_count; |
| 188 TRACE("HandleAck: %" SCNuS "/%" PRIuS, bytes_acked_, bytes_sent_); | 209 TRACE("HandleAck: %" SCNuS "/%" PRIuS, bytes_acked_, bytes_sent_); |
| 189 UpdateStatus_Locked(); | 210 UpdateStatus_Locked(); |
| 190 } | 211 } |
| 191 | 212 |
| 192 Error JSPipeEventEmitter::HandleJSWrite(struct PP_Var message) { | 213 Error JSPipeEventEmitter::HandleJSWrite(struct PP_Var message) { |
| 193 TRACE("HandleJSWrite"); | 214 TRACE("HandleJSWrite"); |
| 194 if (message.type != PP_VARTYPE_ARRAY_BUFFER) { | 215 if (message.type != PP_VARTYPE_ARRAY_BUFFER) { |
| 195 TRACE("HandleJSWrite expected ArrayBuffer but got %d.", message.type); | 216 ERROR("Expected ArrayBuffer but got %d.", message.type); |
| 196 return EINVAL; | 217 return EINVAL; |
| 197 } | 218 } |
| 198 uint32_t length; | 219 uint32_t length; |
| 199 if (buffer_iface_->ByteLength(message, &length) != PP_TRUE) | 220 if (buffer_iface_->ByteLength(message, &length) != PP_TRUE) { |
| 221 ERROR("ArrayBuffer.ByteLength returned PP_FALSE"); |
| 200 return EINVAL; | 222 return EINVAL; |
| 223 } |
| 201 | 224 |
| 202 char* buffer = (char*)buffer_iface_->Map(message); | 225 char* buffer = (char*)buffer_iface_->Map(message); |
| 203 | 226 |
| 204 // Write data to the input fifo | 227 // Write data to the input fifo |
| 205 size_t wrote = HandleJSWrite(buffer, length); | 228 size_t wrote = HandleJSWrite(buffer, length); |
| 206 buffer_iface_->Unmap(message); | 229 buffer_iface_->Unmap(message); |
| 207 if (wrote != length) { | 230 if (wrote != length) { |
| 208 LOG_ERROR("Only wrote %d of %d bytes to pipe", (int)wrote, (int)length); | 231 ERROR("Only wrote %d of %d bytes to pipe", (int)wrote, (int)length); |
| 209 return EIO; | 232 return EIO; |
| 210 } | 233 } |
| 211 TRACE("done HandleWrite: %d", length); | 234 TRACE("done HandleWrite: %d", length); |
| 212 return 0; | 235 return 0; |
| 213 } | 236 } |
| 214 | 237 |
| 215 Error JSPipeEventEmitter::HandleJSAck(PP_Var message) { | 238 Error JSPipeEventEmitter::HandleJSAck(PP_Var message) { |
| 216 if (message.type != PP_VARTYPE_INT32) { | 239 if (message.type != PP_VARTYPE_INT32) { |
| 217 TRACE("HandleAck integer object expected but got %d.", message.type); | 240 ERROR("Integer object expected but got %d.", message.type); |
| 218 return EINVAL; | 241 return EINVAL; |
| 219 } | 242 } |
| 220 HandleJSAck(message.value.as_int); | 243 HandleJSAck(message.value.as_int); |
| 221 return 0; | 244 return 0; |
| 222 } | 245 } |
| 223 | 246 |
| 224 int JSPipeEventEmitter::VarStrcmp(PP_Var a, PP_Var b) { | 247 int JSPipeEventEmitter::VarStrcmp(PP_Var a, PP_Var b) { |
| 225 uint32_t length_a = 0; | 248 uint32_t length_a = 0; |
| 226 uint32_t length_b = 0; | 249 uint32_t length_b = 0; |
| 227 const char* cstring_a = var_iface_->VarToUtf8(a, &length_a); | 250 const char* cstring_a = var_iface_->VarToUtf8(a, &length_a); |
| 228 const char* cstring_b = var_iface_->VarToUtf8(a, &length_b); | 251 const char* cstring_b = var_iface_->VarToUtf8(a, &length_b); |
| 229 std::string string_a(cstring_a, length_a); | 252 std::string string_a(cstring_a, length_a); |
| 230 std::string string_b(cstring_b, length_a); | 253 std::string string_b(cstring_b, length_a); |
| 231 return strcmp(string_a.c_str(), string_b.c_str()); | 254 return strcmp(string_a.c_str(), string_b.c_str()); |
| 232 } | 255 } |
| 233 | 256 |
| 234 Error JSPipeEventEmitter::HandleJSMessage(struct PP_Var message) { | 257 Error JSPipeEventEmitter::HandleJSMessage(struct PP_Var message) { |
| 235 Error err = 0; | 258 Error err = 0; |
| 236 if (!messaging_iface_ || !var_iface_ || !dict_iface_ || !buffer_iface_) { | 259 if (!messaging_iface_ || !var_iface_ || !dict_iface_ || !buffer_iface_) { |
| 237 TRACE("HandleJSMessage: missing PPAPI interfaces"); | 260 ERROR("Got NULL interface(s): %s%s%s%s", |
| 261 messaging_iface_ ? "" : "Messaging ", |
| 262 var_iface_ ? "" : "Var ", |
| 263 dict_iface_ ? "" : "Dictionary ", |
| 264 buffer_iface_ ? "" : "ArrayBuffer"); |
| 238 return ENOSYS; | 265 return ENOSYS; |
| 239 } | 266 } |
| 240 | 267 |
| 241 // Verify that we have an array with size two. | 268 // Verify that we have an array with size two. |
| 242 if (message.type != PP_VARTYPE_DICTIONARY) { | 269 if (message.type != PP_VARTYPE_DICTIONARY) { |
| 243 TRACE("HandleJSMessage passed non-dictionary var"); | 270 ERROR("Expected Dictionary but got %d.", message.type); |
| 244 return EINVAL; | 271 return EINVAL; |
| 245 } | 272 } |
| 246 | 273 |
| 247 #ifndef NDEBUG | 274 #ifndef NDEBUG |
| 248 PP_Var pipe_name_var = dict_iface_->Get(message, pipe_key_); | 275 PP_Var pipe_name_var = dict_iface_->Get(message, pipe_key_); |
| 249 if (VarStrcmp(pipe_name_var, pipe_name_var_)) { | 276 if (VarStrcmp(pipe_name_var, pipe_name_var_)) { |
| 250 TRACE("HandleJSMessage wrong pipe name"); | 277 ERROR("Wrong pipe name."); |
| 251 return EINVAL; | 278 return EINVAL; |
| 252 } | 279 } |
| 253 var_iface_->Release(pipe_name_var); | 280 var_iface_->Release(pipe_name_var); |
| 254 #endif | 281 #endif |
| 255 | 282 |
| 256 PP_Var operation_var = dict_iface_->Get(message, operation_key_); | 283 PP_Var operation_var = dict_iface_->Get(message, operation_key_); |
| 257 if (operation_var.type != PP_VARTYPE_STRING) { | 284 if (operation_var.type != PP_VARTYPE_STRING) { |
| 258 TRACE("HandleJSMessage invalid operation"); | 285 ERROR("Expected String but got %d.", operation_var.type); |
| 259 err = EINVAL; | 286 err = EINVAL; |
| 260 } else { | 287 } else { |
| 261 uint32_t length; | 288 uint32_t length; |
| 262 const char* operation_string; | 289 const char* operation_string; |
| 263 operation_string = var_iface_->VarToUtf8(operation_var, &length); | 290 operation_string = var_iface_->VarToUtf8(operation_var, &length); |
| 264 std::string message_type(operation_string, length); | 291 std::string message_type(operation_string, length); |
| 265 | 292 |
| 266 TRACE("HandleJSMessage %s", message_type.c_str()); | 293 TRACE("HandleJSMessage %s", message_type.c_str()); |
| 267 PP_Var payload = dict_iface_->Get(message, payload_key_); | 294 PP_Var payload = dict_iface_->Get(message, payload_key_); |
| 268 if (message_type == kOperationNameWrite) { | 295 if (message_type == kOperationNameWrite) { |
| 269 err = HandleJSWrite(payload); | 296 err = HandleJSWrite(payload); |
| 270 } else if (message_type == kOperationNameAck) { | 297 } else if (message_type == kOperationNameAck) { |
| 271 err = HandleJSAck(payload); | 298 err = HandleJSAck(payload); |
| 272 } else { | 299 } else { |
| 273 TRACE("Unknown message type: %s", message_type.c_str()); | 300 ERROR("Unknown message type: %s", message_type.c_str()); |
| 274 err = EINVAL; | 301 err = EINVAL; |
| 275 } | 302 } |
| 276 var_iface_->Release(payload); | 303 var_iface_->Release(payload); |
| 277 } | 304 } |
| 278 | 305 |
| 279 var_iface_->Release(operation_var); | 306 var_iface_->Release(operation_var); |
| 280 return err; | 307 return err; |
| 281 } | 308 } |
| 282 | 309 |
| 283 Error JSPipeEventEmitter::Write_Locked(const char* data, | 310 Error JSPipeEventEmitter::Write_Locked(const char* data, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 299 if (err != 0) | 326 if (err != 0) |
| 300 return err; | 327 return err; |
| 301 *out_bytes = len; | 328 *out_bytes = len; |
| 302 bytes_sent_ += len; | 329 bytes_sent_ += len; |
| 303 | 330 |
| 304 UpdateStatus_Locked(); | 331 UpdateStatus_Locked(); |
| 305 return 0; | 332 return 0; |
| 306 } | 333 } |
| 307 | 334 |
| 308 } // namespace nacl_io | 335 } // namespace nacl_io |
| OLD | NEW |