Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc

Issue 242533005: [NaCl SDK] nacl_io: Add flow control the JavaScript pipes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 <errno.h> 5 #include <errno.h>
6 #include <fcntl.h> 6 #include <fcntl.h>
7 #include <pthread.h> 7 #include <pthread.h>
8 #include <stdio.h> 8 #include <stdio.h>
9 #include <stdlib.h> 9 #include <stdlib.h>
10 #include <sys/ioctl.h> 10 #include <sys/ioctl.h>
11 #include <sys/types.h> 11 #include <sys/types.h>
12 #include <sys/stat.h> 12 #include <sys/stat.h>
13 #include <termios.h> 13 #include <termios.h>
14 14
15 #include <algorithm> 15 #include <algorithm>
16 #include <cstdlib> 16 #include <cstdlib>
17 #include <cstring> 17 #include <cstring>
18 #include <sstream> 18 #include <sstream>
19 #include <string> 19 #include <string>
20 #include <vector> 20 #include <vector>
21 21
22 #include "nacl_io/ioctl.h" 22 #include "nacl_io/ioctl.h"
23 #include "nacl_io/kernel_wrap.h" 23 #include "nacl_io/kernel_wrap.h"
24 #include "nacl_io/log.h"
24 #include "nacl_io/nacl_io.h" 25 #include "nacl_io/nacl_io.h"
25 26
26 #include "ppapi/c/ppb_var.h" 27 #include "ppapi/c/ppb_var.h"
27 28
28 #include "ppapi/cpp/input_event.h" 29 #include "ppapi/cpp/input_event.h"
29 #include "ppapi/cpp/message_loop.h" 30 #include "ppapi/cpp/message_loop.h"
30 #include "ppapi/cpp/module.h" 31 #include "ppapi/cpp/module.h"
31 #include "ppapi/cpp/rect.h" 32 #include "ppapi/cpp/rect.h"
32 #include "ppapi/cpp/size.h" 33 #include "ppapi/cpp/size.h"
33 #include "ppapi/cpp/touch_point.h" 34 #include "ppapi/cpp/touch_point.h"
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 HandleResize(cols, rows); 271 HandleResize(cols, rows);
271 } 272 }
272 } 273 }
273 else if (tty_rows || tty_cols) { 274 else if (tty_rows || tty_cols) {
274 Error("PS_TTY_ROWS and PS_TTY_COLS must be set together"); 275 Error("PS_TTY_ROWS and PS_TTY_COLS must be set together");
275 } 276 }
276 277
277 tioc_nacl_output handler; 278 tioc_nacl_output handler;
278 handler.handler = TtyOutputHandlerStatic; 279 handler.handler = TtyOutputHandlerStatic;
279 handler.user_data = this; 280 handler.user_data = this;
280 ioctl(tty_fd_, TIOCNACLOUTPUT, reinterpret_cast<char*>(&handler)); 281 ioctl(tty_fd_, TIOCNACLOUTPUT, &handler);
281 } else { 282 } else {
282 Error("Failed to open /dev/tty.\n"); 283 Error("Failed to open /dev/tty.\n");
283 } 284 }
284 } 285 }
285 286
287 RegisterMessageHandler("jspipe1", MessageHandlerInputStatic, this);
288 RegisterMessageHandler("jspipe2", MessageHandlerInputStatic, this);
289 RegisterMessageHandler("jspipe3", MessageHandlerInputStatic, this);
290
286 exit_message_ = getenv("PS_EXIT_MESSAGE"); 291 exit_message_ = getenv("PS_EXIT_MESSAGE");
287 292
288 // If PS_EXIT_MESSAGE is set in the envionment then we perform a handshake 293 // If PS_EXIT_MESSAGE is set in the envionment then we perform a handshake
289 // with JavaScript when program exits. 294 // with JavaScript when program exits.
290 if (exit_message_ != NULL) 295 if (exit_message_ != NULL)
291 nacl_io_register_exit_handler(HandleExitStatic, this); 296 nacl_io_register_exit_handler(HandleExitStatic, this);
292 297
293 // Set line buffering on stdout and stderr 298 // Set line buffering on stdout and stderr
294 #if !defined(WIN32) 299 #if !defined(WIN32)
295 setvbuf(stderr, NULL, _IOLBF, 0); 300 setvbuf(stderr, NULL, _IOLBF, 0);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 return count; 398 return count;
394 } 399 }
395 400
396 void PSInstance::MessageHandlerExit(const pp::Var& message) { 401 void PSInstance::MessageHandlerExit(const pp::Var& message) {
397 assert(message.is_string()); 402 assert(message.is_string());
398 pthread_mutex_lock(&exit_lock_); 403 pthread_mutex_lock(&exit_lock_);
399 pthread_cond_signal(&exit_cond_); 404 pthread_cond_signal(&exit_cond_);
400 pthread_mutex_unlock(&exit_lock_); 405 pthread_mutex_unlock(&exit_lock_);
401 } 406 }
402 407
403 void PSInstance::MessageHandlerInput(const pp::Var& message) { 408 void PSInstance::MessageHandlerInput(const pp::Var& key,
404 // Since our message may contain null characters, we can't send it as a 409 const pp::Var& message) {
405 // naked C string, so we package it up in this struct before sending it 410 std::string key_string = key.AsString();
406 // to the ioctl.
407 assert(message.is_string());
408 std::string buffer = message.AsString();
409 411
410 struct tioc_nacl_input_string ioctl_message; 412 // Legacy support for passing TTY data as a string, rather than a array
411 ioctl_message.length = buffer.size(); 413 // buffer. TODO(sbc): remove this in a future release.
412 ioctl_message.buffer = buffer.c_str(); 414 if (message.is_string() && key_string == tty_prefix_) {
413 int ret = 415 std::string buffer = message.AsString();
414 ioctl(tty_fd_, TIOCNACLINPUT, reinterpret_cast<char*>(&ioctl_message)); 416 Warn("Passing TTY input as a string is deprected. Please use a "
415 if (ret != 0 && errno != ENOTTY) { 417 "JavaScript ArrayBuffer instead");
416 Error("ioctl returned unexpected error: %d.\n", ret); 418
419 // Since our message may contain null characters, we can't send it as a
420 // naked C string, so we package it up in this struct before sending it
421 // to the ioctl.
422 struct tioc_nacl_input_string ioctl_message;
423 ioctl_message.length = buffer.size();
424 ioctl_message.buffer = buffer.c_str();
425 int ret =
426 ioctl(tty_fd_, TIOCNACLINPUT, &ioctl_message);
427 if (ret != 0 && errno != ENOTTY) {
428 Error("ioctl returned unexpected error: %d.\n", ret);
429 }
430 }
431
432 if (!message.is_array_buffer()) {
433 Error("Expected ArrayBuffer object but got: %d", message.pp_var().type);
434 return;
435 }
436
437 const char* filename = NULL;
438 if (key_string == tty_prefix_) {
439 filename = "/dev/tty";
440 } else if (key_string == "jspipe1") {
441 filename = "/dev/jspipe1";
442 } else if (key_string == "jspipe2") {
443 filename = "/dev/jspipe2";
444 } else if (key_string == "jspipe3") {
445 filename = "/dev/jspipe3";
446 } else {
447 Error("unexpected input key: %s", key_string.c_str());
448 return;
449 }
450
451 int fd = open(filename, O_RDONLY);
452 if (fd < 0) {
453 Error("error opening file: %s (%s)", filename, strerror(errno));
454 return;
455 }
456
457 int ret = ioctl(fd, NACL_IOC_HANDLEMESSAGE, &message.pp_var());
binji 2014/05/01 20:22:31 did you add this functionality to the ttynode?
Sam Clegg 2014/05/01 22:16:55 No. TTY still uses the legacy code above for now.
458 if (ret != 0) {
459 Error("ioctl on %s failed: %d.\n", filename, ret);
460 return;
417 } 461 }
418 } 462 }
419 463
420 void PSInstance::HandleExitStatic(int status, void* user_data) { 464 void PSInstance::HandleExitStatic(int status, void* user_data) {
421 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); 465 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data);
422 instance->ExitHandshake(status); 466 instance->ExitHandshake(status);
423 } 467 }
424 468
425 void PSInstance::HandleResize(int width, int height) { 469 void PSInstance::HandleResize(int width, int height) {
426 struct winsize size; 470 struct winsize size;
427 memset(&size, 0, sizeof(size)); 471 memset(&size, 0, sizeof(size));
428 size.ws_col = width; 472 size.ws_col = width;
429 size.ws_row = height; 473 size.ws_row = height;
430 ioctl(tty_fd_, TIOCSWINSZ, reinterpret_cast<char*>(&size)); 474 ioctl(tty_fd_, TIOCSWINSZ, &size);
431 } 475 }
432 476
433 void PSInstance::MessageHandlerResize(const pp::Var& message) { 477 void PSInstance::MessageHandlerResize(const pp::Var& message) {
434 assert(message.is_array()); 478 assert(message.is_array());
435 pp::VarArray array(message); 479 pp::VarArray array(message);
436 assert(array.GetLength() == 2); 480 assert(array.GetLength() == 2);
437 481
438 int width = array.Get(0).AsInt(); 482 int width = array.Get(0).AsInt();
439 int height = array.Get(1).AsInt(); 483 int height = array.Get(1).AsInt();
440 HandleResize(width, height); 484 HandleResize(width, height);
(...skipping 10 matching lines...) Expand all
451 const pp::Var& value, 495 const pp::Var& value,
452 void* user_data) { 496 void* user_data) {
453 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); 497 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data);
454 instance->MessageHandlerExit(value); 498 instance->MessageHandlerExit(value);
455 } 499 }
456 500
457 void PSInstance::MessageHandlerInputStatic(const pp::Var& key, 501 void PSInstance::MessageHandlerInputStatic(const pp::Var& key,
458 const pp::Var& value, 502 const pp::Var& value,
459 void* user_data) { 503 void* user_data) {
460 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); 504 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data);
461 instance->MessageHandlerInput(value); 505 instance->MessageHandlerInput(key, value);
462 } 506 }
463 507
464 void PSInstance::MessageHandlerResizeStatic(const pp::Var& key, 508 void PSInstance::MessageHandlerResizeStatic(const pp::Var& key,
465 const pp::Var& value, 509 const pp::Var& value,
466 void* user_data) { 510 void* user_data) {
467 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); 511 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data);
468 instance->MessageHandlerResize(value); 512 instance->MessageHandlerResize(value);
469 } 513 }
470 514
471 void PSInstance::RegisterMessageHandler(std::string message_name, 515 void PSInstance::RegisterMessageHandler(std::string message_name,
472 MessageHandler_t handler, 516 MessageHandler_t handler,
473 void* user_data) { 517 void* user_data) {
518 Trace("registering msg handler: %s", message_name.c_str());
474 if (handler == NULL) { 519 if (handler == NULL) {
475 message_handlers_.erase(message_name); 520 message_handlers_.erase(message_name);
476 return; 521 return;
477 } 522 }
478 523
479 MessageHandler message_handler = { handler, user_data }; 524 MessageHandler message_handler = { handler, user_data };
480 message_handlers_[message_name] = message_handler; 525 message_handlers_[message_name] = message_handler;
481 } 526 }
482 527
483 void PSInstance::PostEvent(PSEventType type, const PP_Var& var) { 528 void PSInstance::PostEvent(PSEventType type, const PP_Var& var) {
484 assert(PSE_INSTANCE_HANDLEMESSAGE == type); 529 assert(PSE_INSTANCE_HANDLEMESSAGE == type);
485 530
486 // If the user has specified a tty_prefix_, then filter out the
487 // matching message here and pass them to the tty node via
488 // ioctl() rather then adding them to the event queue.
489 pp::Var event(var); 531 pp::Var event(var);
532 // Legacy support for passing TTY input as a string <prefix>:<payload>
533 // TODO(sbc): remove this in a future release.
490 if (tty_fd_ >= 0 && event.is_string()) { 534 if (tty_fd_ >= 0 && event.is_string()) {
535 Warn("passing TTY data using a string prefix is deprected."
536 " Use a JavaScript dictionary instead.");
491 std::string message = event.AsString(); 537 std::string message = event.AsString();
492 size_t prefix_len = strlen(tty_prefix_); 538 size_t prefix_len = strlen(tty_prefix_);
493 if (message.size() > prefix_len) { 539 if (message.size() > prefix_len) {
494 if (!strncmp(message.c_str(), tty_prefix_, prefix_len)) { 540 if (!strncmp(message.c_str(), tty_prefix_, prefix_len)) {
495 MessageHandlerInput(pp::Var(message.substr(prefix_len))); 541 MessageHandlerInput(pp::Var(message.substr(0, prefix_len)),
542 pp::Var(message.substr(prefix_len)));
496 return; 543 return;
497 } 544 }
498 } 545 }
499 } 546 }
500 547
501 // If the message is a dictionary then see if it matches one 548 // If the message is a dictionary then see if it matches one
502 // of the specific handlers, then call that handler rather than 549 // of the specific handlers, then call that handler rather than
503 // queuing an event. 550 // queuing an event.
504 if (event.is_dictionary()) { 551 if (event.is_dictionary()) {
505 pp::VarDictionary dictionary(var); 552 pp::VarDictionary dictionary(var);
506 pp::VarArray keys = dictionary.GetKeys(); 553 pp::VarArray keys = dictionary.GetKeys();
507 if (keys.GetLength() == 1) { 554 if (keys.GetLength() == 1) {
508 pp::Var key = keys.Get(0); 555 pp::Var key = keys.Get(0);
556 Trace("calling handler for: %s", key.AsString().c_str());
509 MessageHandlerMap::iterator iter = 557 MessageHandlerMap::iterator iter =
510 message_handlers_.find(key.AsString()); 558 message_handlers_.find(key.AsString());
511 if (iter != message_handlers_.end()) { 559 if (iter != message_handlers_.end()) {
512 MessageHandler_t handler = iter->second.handler; 560 MessageHandler_t handler = iter->second.handler;
513 void* user_data = iter->second.user_data; 561 void* user_data = iter->second.user_data;
514 handler(key, dictionary.Get(key), user_data); 562 handler(key, dictionary.Get(key), user_data);
515 return; 563 return;
516 } 564 }
517 } 565 }
518 } 566 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 641
594 void PSInstance::Graphics3DContextLost() { 642 void PSInstance::Graphics3DContextLost() {
595 Log("Graphics3DContextLost\n"); 643 Log("Graphics3DContextLost\n");
596 PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST); 644 PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST);
597 } 645 }
598 646
599 void PSInstance::MouseLockLost() { 647 void PSInstance::MouseLockLost() {
600 Log("MouseLockLost\n"); 648 Log("MouseLockLost\n");
601 PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST); 649 PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST);
602 } 650 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698