OLD | NEW |
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> |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 Error("Failed to open /dev/tty.\n"); | 283 Error("Failed to open /dev/tty.\n"); |
284 } | 284 } |
285 } | 285 } |
286 | 286 |
287 RegisterMessageHandler("jspipe1", MessageHandlerInputStatic, this); | 287 RegisterMessageHandler("jspipe1", MessageHandlerInputStatic, this); |
288 RegisterMessageHandler("jspipe2", MessageHandlerInputStatic, this); | 288 RegisterMessageHandler("jspipe2", MessageHandlerInputStatic, this); |
289 RegisterMessageHandler("jspipe3", MessageHandlerInputStatic, this); | 289 RegisterMessageHandler("jspipe3", MessageHandlerInputStatic, this); |
290 | 290 |
291 exit_message_ = getenv("PS_EXIT_MESSAGE"); | 291 exit_message_ = getenv("PS_EXIT_MESSAGE"); |
292 | 292 |
293 // If PS_EXIT_MESSAGE is set in the envionment then we perform a handshake | 293 // If PS_EXIT_MESSAGE is set in the environment then we perform a handshake |
294 // with JavaScript when program exits. | 294 // with JavaScript when program exits. |
295 if (exit_message_ != NULL) | 295 if (exit_message_ != NULL) |
296 nacl_io_register_exit_handler(HandleExitStatic, this); | 296 nacl_io_register_exit_handler(HandleExitStatic, this); |
297 | 297 |
298 // Set line buffering on stdout and stderr | 298 // Set line buffering on stdout and stderr |
299 #if !defined(WIN32) | 299 #if !defined(WIN32) |
300 setvbuf(stderr, NULL, _IOLBF, 0); | 300 setvbuf(stderr, NULL, _IOLBF, 0); |
301 setvbuf(stdout, NULL, _IOLBF, 0); | 301 setvbuf(stdout, NULL, _IOLBF, 0); |
302 #endif | 302 #endif |
303 return true; | 303 return true; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 assert(message.is_string()); | 402 assert(message.is_string()); |
403 pthread_mutex_lock(&exit_lock_); | 403 pthread_mutex_lock(&exit_lock_); |
404 pthread_cond_signal(&exit_cond_); | 404 pthread_cond_signal(&exit_cond_); |
405 pthread_mutex_unlock(&exit_lock_); | 405 pthread_mutex_unlock(&exit_lock_); |
406 } | 406 } |
407 | 407 |
408 void PSInstance::MessageHandlerInput(const pp::Var& key, | 408 void PSInstance::MessageHandlerInput(const pp::Var& key, |
409 const pp::Var& message) { | 409 const pp::Var& message) { |
410 std::string key_string = key.AsString(); | 410 std::string key_string = key.AsString(); |
411 | 411 |
412 if (message.is_string() && key_string == tty_prefix_) { | |
413 std::string buffer = message.AsString(); | |
414 | |
415 // Since our message may contain null characters, we can't send it as a | |
416 // naked C string, so we package it up in this struct before sending it | |
417 // to the ioctl. | |
418 struct tioc_nacl_input_string ioctl_message; | |
419 ioctl_message.length = buffer.size(); | |
420 ioctl_message.buffer = buffer.c_str(); | |
421 int ret = ioctl(tty_fd_, TIOCNACLINPUT, &ioctl_message); | |
422 if (ret != 0 && errno != ENOTTY) { | |
423 Error("ioctl returned unexpected error: %d.\n", ret); | |
424 } | |
425 return; | |
426 } | |
427 | |
428 if (!message.is_array_buffer()) { | |
429 Error("Expected ArrayBuffer object but got: %d", message.pp_var().type); | |
430 return; | |
431 } | |
432 | |
433 const char* filename = NULL; | 412 const char* filename = NULL; |
434 if (key_string == tty_prefix_) { | 413 if (key_string == tty_prefix_) { |
435 filename = "/dev/tty"; | 414 filename = "/dev/tty"; |
436 } else if (key_string == "jspipe1") { | 415 } else if (key_string == "jspipe1") { |
437 filename = "/dev/jspipe1"; | 416 filename = "/dev/jspipe1"; |
438 } else if (key_string == "jspipe2") { | 417 } else if (key_string == "jspipe2") { |
439 filename = "/dev/jspipe2"; | 418 filename = "/dev/jspipe2"; |
440 } else if (key_string == "jspipe3") { | 419 } else if (key_string == "jspipe3") { |
441 filename = "/dev/jspipe3"; | 420 filename = "/dev/jspipe3"; |
442 } else { | 421 } else { |
443 Error("unexpected input key: %s", key_string.c_str()); | 422 Error("unexpected input key: %s", key_string.c_str()); |
444 return; | 423 return; |
445 } | 424 } |
446 | 425 |
447 int fd = open(filename, O_RDONLY); | 426 int fd = open(filename, O_RDONLY); |
448 if (fd < 0) { | 427 if (fd < 0) { |
449 Error("error opening file: %s (%s)", filename, strerror(errno)); | 428 Error("error opening file: %s (%s)", filename, strerror(errno)); |
450 return; | 429 return; |
451 } | 430 } |
452 | 431 |
453 int ret = ioctl(fd, NACL_IOC_HANDLEMESSAGE, &message.pp_var()); | 432 int ret = ioctl(fd, NACL_IOC_HANDLEMESSAGE, &message.pp_var()); |
454 if (ret != 0) { | 433 if (ret != 0) { |
455 Error("ioctl on %s failed: %d.\n", filename, ret); | 434 Error("ioctl on %s failed: %d.\n", filename, ret); |
| 435 close(fd); |
456 return; | 436 return; |
457 } | 437 } |
| 438 |
| 439 close(fd); |
458 } | 440 } |
459 | 441 |
460 void PSInstance::HandleExitStatic(int status, void* user_data) { | 442 void PSInstance::HandleExitStatic(int status, void* user_data) { |
461 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); | 443 PSInstance* instance = static_cast<PSInstance*>(user_data); |
462 instance->ExitHandshake(status); | 444 instance->ExitHandshake(status); |
463 } | 445 } |
464 | 446 |
465 void PSInstance::HandleResize(int width, int height) { | 447 void PSInstance::HandleResize(int width, int height) { |
466 struct winsize size; | 448 struct winsize size; |
467 memset(&size, 0, sizeof(size)); | 449 memset(&size, 0, sizeof(size)); |
468 size.ws_col = width; | 450 size.ws_col = width; |
469 size.ws_row = height; | 451 size.ws_row = height; |
470 ioctl(tty_fd_, TIOCSWINSZ, &size); | 452 ioctl(tty_fd_, TIOCSWINSZ, &size); |
471 } | 453 } |
472 | 454 |
473 void PSInstance::MessageHandlerResize(const pp::Var& message) { | 455 void PSInstance::MessageHandlerResize(const pp::Var& message) { |
474 assert(message.is_array()); | 456 assert(message.is_array()); |
475 pp::VarArray array(message); | 457 pp::VarArray array(message); |
476 assert(array.GetLength() == 2); | 458 assert(array.GetLength() == 2); |
477 | 459 |
478 int width = array.Get(0).AsInt(); | 460 int width = array.Get(0).AsInt(); |
479 int height = array.Get(1).AsInt(); | 461 int height = array.Get(1).AsInt(); |
480 HandleResize(width, height); | 462 HandleResize(width, height); |
481 } | 463 } |
482 | 464 |
483 ssize_t PSInstance::TtyOutputHandlerStatic(const char* buf, | 465 ssize_t PSInstance::TtyOutputHandlerStatic(const char* buf, |
484 size_t count, | 466 size_t count, |
485 void* user_data) { | 467 void* user_data) { |
486 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); | 468 PSInstance* instance = static_cast<PSInstance*>(user_data); |
487 return instance->TtyOutputHandler(buf, count); | 469 return instance->TtyOutputHandler(buf, count); |
488 } | 470 } |
489 | 471 |
490 void PSInstance::MessageHandlerExitStatic(const pp::Var& key, | 472 void PSInstance::MessageHandlerExitStatic(const pp::Var& key, |
491 const pp::Var& value, | 473 const pp::Var& value, |
492 void* user_data) { | 474 void* user_data) { |
493 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); | 475 PSInstance* instance = static_cast<PSInstance*>(user_data); |
494 instance->MessageHandlerExit(value); | 476 instance->MessageHandlerExit(value); |
495 } | 477 } |
496 | 478 |
497 void PSInstance::MessageHandlerInputStatic(const pp::Var& key, | 479 void PSInstance::MessageHandlerInputStatic(const pp::Var& key, |
498 const pp::Var& value, | 480 const pp::Var& value, |
499 void* user_data) { | 481 void* user_data) { |
500 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); | 482 PSInstance* instance = static_cast<PSInstance*>(user_data); |
501 instance->MessageHandlerInput(key, value); | 483 instance->MessageHandlerInput(key, value); |
502 } | 484 } |
503 | 485 |
504 void PSInstance::MessageHandlerResizeStatic(const pp::Var& key, | 486 void PSInstance::MessageHandlerResizeStatic(const pp::Var& key, |
505 const pp::Var& value, | 487 const pp::Var& value, |
506 void* user_data) { | 488 void* user_data) { |
507 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); | 489 PSInstance* instance = static_cast<PSInstance*>(user_data); |
508 instance->MessageHandlerResize(value); | 490 instance->MessageHandlerResize(value); |
509 } | 491 } |
510 | 492 |
511 void PSInstance::RegisterMessageHandler(std::string message_name, | 493 void PSInstance::RegisterMessageHandler(std::string message_name, |
512 MessageHandler_t handler, | 494 MessageHandler_t handler, |
513 void* user_data) { | 495 void* user_data) { |
514 Trace("registering msg handler: %s", message_name.c_str()); | 496 Trace("registering msg handler: %s", message_name.c_str()); |
515 if (handler == NULL) { | 497 if (handler == NULL) { |
516 message_handlers_.erase(message_name); | 498 message_handlers_.erase(message_name); |
517 return; | 499 return; |
518 } | 500 } |
519 | 501 |
520 MessageHandler message_handler = { handler, user_data }; | 502 MessageHandler message_handler = { handler, user_data }; |
521 message_handlers_[message_name] = message_handler; | 503 message_handlers_[message_name] = message_handler; |
522 } | 504 } |
523 | 505 |
524 void PSInstance::PostEvent(PSEventType type, const PP_Var& var) { | 506 void PSInstance::PostEvent(PSEventType type, const PP_Var& var) { |
525 assert(PSE_INSTANCE_HANDLEMESSAGE == type); | 507 assert(PSE_INSTANCE_HANDLEMESSAGE == type); |
526 | 508 |
527 pp::Var event(var); | 509 pp::Var event(var); |
528 // Legacy support for passing TTY input as a string <prefix>:<payload> | |
529 // TODO(sbc): remove this in a future release. | |
530 if (tty_fd_ >= 0 && event.is_string()) { | |
531 std::string message = event.AsString(); | |
532 size_t prefix_len = strlen(tty_prefix_); | |
533 if (message.size() > prefix_len) { | |
534 if (!strncmp(message.c_str(), tty_prefix_, prefix_len)) { | |
535 LOG_WARN("Passing TTY data using a string prefix is deprecated. " | |
536 "Use a JavaScript dictionary instead."); | |
537 MessageHandlerInput(pp::Var(message.substr(0, prefix_len)), | |
538 pp::Var(message.substr(prefix_len))); | |
539 return; | |
540 } | |
541 } | |
542 } | |
543 | 510 |
544 // If the message is a dictionary then see if it matches one | 511 // If the message is a dictionary then see if it matches one |
545 // of the specific handlers, then call that handler rather than | 512 // of the specific handlers, then call that handler rather than |
546 // queuing an event. | 513 // queuing an event. |
547 if (event.is_dictionary()) { | 514 if (event.is_dictionary()) { |
548 pp::VarDictionary dictionary(var); | 515 pp::VarDictionary dictionary(var); |
549 pp::VarArray keys = dictionary.GetKeys(); | 516 pp::VarArray keys = dictionary.GetKeys(); |
550 if (keys.GetLength() == 1) { | 517 if (keys.GetLength() == 1) { |
551 pp::Var key = keys.Get(0); | 518 pp::Var key = keys.Get(0); |
552 Trace("calling handler for: %s", key.AsString().c_str()); | 519 Trace("calling handler for: %s", key.AsString().c_str()); |
553 MessageHandlerMap::iterator iter = | 520 MessageHandlerMap::iterator iter = message_handlers_.find(key.AsString()); |
554 message_handlers_.find(key.AsString()); | |
555 if (iter != message_handlers_.end()) { | 521 if (iter != message_handlers_.end()) { |
556 MessageHandler_t handler = iter->second.handler; | 522 MessageHandler_t handler = iter->second.handler; |
557 void* user_data = iter->second.user_data; | 523 void* user_data = iter->second.user_data; |
558 handler(key, dictionary.Get(key), user_data); | 524 handler(key, dictionary.Get(key), user_data); |
559 return; | 525 return; |
560 } | 526 } |
561 } | 527 } |
562 } | 528 } |
563 | 529 |
564 PSInterfaceVar()->AddRef(var); | 530 PSInterfaceVar()->AddRef(var); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 | 603 |
638 void PSInstance::Graphics3DContextLost() { | 604 void PSInstance::Graphics3DContextLost() { |
639 Log("Graphics3DContextLost\n"); | 605 Log("Graphics3DContextLost\n"); |
640 PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST); | 606 PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST); |
641 } | 607 } |
642 | 608 |
643 void PSInstance::MouseLockLost() { | 609 void PSInstance::MouseLockLost() { |
644 Log("MouseLockLost\n"); | 610 Log("MouseLockLost\n"); |
645 PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST); | 611 PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST); |
646 } | 612 } |
OLD | NEW |