Chromium Code Reviews| 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/types.h> | 11 #include <sys/types.h> |
| 11 #include <sys/stat.h> | 12 #include <sys/stat.h> |
| 12 | 13 |
| 13 #include <algorithm> | 14 #include <algorithm> |
| 14 #include <cstdlib> | 15 #include <cstdlib> |
| 15 #include <cstring> | 16 #include <cstring> |
| 16 #include <sstream> | 17 #include <sstream> |
| 17 #include <string> | 18 #include <string> |
| 18 #include <vector> | 19 #include <vector> |
| 19 | 20 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 return ret; | 90 return ret; |
| 90 } | 91 } |
| 91 | 92 |
| 92 PSInstance::PSInstance(PP_Instance instance) | 93 PSInstance::PSInstance(PP_Instance instance) |
| 93 : pp::Instance(instance), | 94 : pp::Instance(instance), |
| 94 pp::MouseLock(this), | 95 pp::MouseLock(this), |
| 95 pp::Graphics3DClient(this), | 96 pp::Graphics3DClient(this), |
| 96 main_loop_(NULL), | 97 main_loop_(NULL), |
| 97 events_enabled_(PSE_NONE), | 98 events_enabled_(PSE_NONE), |
| 98 verbosity_(PSV_WARN), | 99 verbosity_(PSV_WARN), |
| 99 fd_tty_(-1) { | 100 tty_fd_(-1) { |
|
binji
2013/08/22 18:09:36
init tty_prefix_ and tty_resize_ to NULL?
Sam Clegg
2013/08/22 19:52:25
Done.
| |
| 100 // Set the single Instance object | 101 // Set the single Instance object |
| 101 s_InstanceObject = this; | 102 s_InstanceObject = this; |
| 102 | 103 |
| 103 #ifdef NACL_SDK_DEBUG | 104 #ifdef NACL_SDK_DEBUG |
| 104 SetVerbosity(PSV_LOG); | 105 SetVerbosity(PSV_LOG); |
| 105 #endif | 106 #endif |
| 106 | 107 |
| 107 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | | 108 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | |
| 108 PP_INPUTEVENT_CLASS_KEYBOARD | | 109 PP_INPUTEVENT_CLASS_KEYBOARD | |
| 109 PP_INPUTEVENT_CLASS_WHEEL | | 110 PP_INPUTEVENT_CLASS_WHEEL | |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 nacl_io_init_ppapi(PSGetInstanceId(), PSGetInterface); | 201 nacl_io_init_ppapi(PSGetInstanceId(), PSGetInterface); |
| 201 int fd0 = open(getenv("PS_STDIN"), O_RDONLY); | 202 int fd0 = open(getenv("PS_STDIN"), O_RDONLY); |
| 202 dup2(fd0, 0); | 203 dup2(fd0, 0); |
| 203 | 204 |
| 204 int fd1 = open(getenv("PS_STDOUT"), O_WRONLY); | 205 int fd1 = open(getenv("PS_STDOUT"), O_WRONLY); |
| 205 dup2(fd1, 1); | 206 dup2(fd1, 1); |
| 206 | 207 |
| 207 int fd2 = open(getenv("PS_STDERR"), O_WRONLY); | 208 int fd2 = open(getenv("PS_STDERR"), O_WRONLY); |
| 208 dup2(fd2, 2); | 209 dup2(fd2, 2); |
| 209 | 210 |
| 210 const char* tty_prefix = getenv("PS_TTY_PREFIX"); | 211 tty_prefix_ = getenv("PS_TTY_PREFIX"); |
| 211 if (tty_prefix) { | 212 if (tty_prefix_) { |
| 212 fd_tty_ = open("/dev/tty", O_WRONLY); | 213 tty_fd_ = open("/dev/tty", O_WRONLY); |
| 213 if (fd_tty_ >= 0) { | 214 if (tty_fd_ >= 0) { |
| 214 ioctl(fd_tty_, TIOCNACLPREFIX, const_cast<char*>(tty_prefix)); | 215 RegisterMessageHandler(tty_prefix_, MessageHandlerInputStatic, this); |
| 216 tty_resize_ = getenv("PS_TTY_RESIZE"); | |
| 217 if (tty_resize_) | |
|
binji
2013/08/22 18:09:36
tty_resize_ is only used in this function, does it
Sam Clegg
2013/08/22 19:52:25
Done.
| |
| 218 RegisterMessageHandler(tty_resize_, MessageHandlerResizeStatic, this); | |
| 219 | |
| 220 char* handler = reinterpret_cast<char*>(TtyOutputHandlerStatic); | |
| 221 ioctl(tty_fd_, TIOCNACLOUTPUT, handler); | |
| 215 } else { | 222 } else { |
| 216 Error("Failed to open /dev/tty.\n"); | 223 Error("Failed to open /dev/tty.\n"); |
| 217 } | 224 } |
| 218 } | 225 } |
| 219 | 226 |
| 220 // Set line buffering on stdout and stderr | 227 // Set line buffering on stdout and stderr |
| 221 #if !defined(WIN32) | 228 #if !defined(WIN32) |
| 222 setvbuf(stderr, NULL, _IOLBF, 0); | 229 setvbuf(stderr, NULL, _IOLBF, 0); |
| 223 setvbuf(stdout, NULL, _IOLBF, 0); | 230 setvbuf(stdout, NULL, _IOLBF, 0); |
| 224 #endif | 231 #endif |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 303 if (resource) { | 310 if (resource) { |
| 304 PSInterfaceCore()->AddRefResource(resource); | 311 PSInterfaceCore()->AddRefResource(resource); |
| 305 } | 312 } |
| 306 PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent)); | 313 PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent)); |
| 307 memset(env, 0, sizeof(*env)); | 314 memset(env, 0, sizeof(*env)); |
| 308 env->type = type; | 315 env->type = type; |
| 309 env->as_resource = resource; | 316 env->as_resource = resource; |
| 310 event_queue_.Enqueue(env); | 317 event_queue_.Enqueue(env); |
| 311 } | 318 } |
| 312 | 319 |
| 320 void PSInstance::MessageHandlerInput(const pp::Var& message) { | |
| 321 // Since our message may contain null characters, we can't send it as a | |
| 322 // naked C string, so we package it up in this struct before sending it | |
| 323 // to the ioctl. | |
| 324 assert(message.is_string()); | |
| 325 std::string buffer = message.AsString(); | |
| 326 | |
| 327 struct tioc_nacl_input_string ioctl_message; | |
| 328 ioctl_message.length = buffer.size(); | |
| 329 ioctl_message.buffer = buffer.c_str(); | |
| 330 int ret = | |
| 331 ioctl(tty_fd_, TIOCNACLINPUT, reinterpret_cast<char*>(&ioctl_message)); | |
| 332 if (ret != 0 && errno != ENOTTY) { | |
| 333 Error("ioctl returned unexpected error: %d.\n", ret); | |
| 334 } | |
| 335 } | |
| 336 | |
| 337 int PSInstance::TtyOutputHandlerStatic(const char* buf, int count) { | |
| 338 return PSInstance::GetInstance()->TtyOutputHandler(buf, count); | |
| 339 } | |
| 340 | |
| 341 int PSInstance::TtyOutputHandler(const char* buf, int count) { | |
| 342 // We prepend the prefix_ to the data in buf, then package it up | |
| 343 // and post it as a message to javascript. | |
| 344 const char* data = static_cast<const char*>(buf); | |
| 345 std::string message = tty_prefix_; | |
| 346 message.append(data, count); | |
| 347 PostMessage(pp::Var(message)); | |
| 348 return count; | |
| 349 } | |
| 350 | |
| 351 void PSInstance::MessageHandlerInputStatic(const pp::Var& key, | |
| 352 const pp::Var& value, | |
| 353 void* user_data) { | |
| 354 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); | |
| 355 instance->MessageHandlerInput(value); | |
| 356 } | |
| 357 | |
| 358 void PSInstance::MessageHandlerResizeStatic(const pp::Var& key, | |
|
binji
2013/08/22 18:09:36
nit: the ordering of functions here is strange, I'
Sam Clegg
2013/08/22 19:52:25
Done.
| |
| 359 const pp::Var& value, | |
| 360 void* user_data) { | |
| 361 PSInstance* instance = reinterpret_cast<PSInstance*>(user_data); | |
| 362 instance->MessageHandlerResize(value); | |
| 363 } | |
| 364 | |
| 365 void PSInstance::MessageHandlerResize(const pp::Var& message) { | |
| 366 assert(message.is_array()); | |
|
binji
2013/08/22 18:09:36
document this message somewhere in the header?
va
Sam Clegg
2013/08/22 19:52:25
Done.
| |
| 367 pp::VarArray array(message); | |
| 368 assert(array.GetLength() == 2); | |
| 369 | |
| 370 struct winsize size; | |
| 371 memset(&size, 0, sizeof(size)); | |
| 372 size.ws_col = array.Get(0).AsInt(); | |
| 373 size.ws_row = array.Get(1).AsInt(); | |
| 374 ioctl(tty_fd_, TIOCSWINSZ, reinterpret_cast<char*>(&size)); | |
| 375 } | |
| 376 | |
| 377 void PSInstance::RegisterMessageHandler(std::string message_name, | |
| 378 MessageHandler_t handler, | |
| 379 void* user_data) { | |
| 380 if (handler == NULL) { | |
| 381 message_handlers_.erase(message_name); | |
| 382 return; | |
| 383 } | |
| 384 | |
| 385 MessageHandler message_handler = { handler, user_data }; | |
| 386 message_handlers_[message_name] = message_handler; | |
| 387 } | |
| 388 | |
| 313 void PSInstance::PostEvent(PSEventType type, const PP_Var& var) { | 389 void PSInstance::PostEvent(PSEventType type, const PP_Var& var) { |
| 314 assert(PSE_INSTANCE_HANDLEMESSAGE == type); | 390 assert(PSE_INSTANCE_HANDLEMESSAGE == type); |
| 315 | 391 |
| 316 // If the user has specified a tty_prefix_ (using ioctl), then we'll give the | 392 // If the user has specified a tty_prefix_, then filter out the |
| 317 // tty node a chance to vacuum up any messages beginning with that prefix. If | 393 // matching message here and pass them to the tty node via |
| 318 // the message does not start with the prefix, the ioctl call will return | 394 // ioctl() rather then adding them to the even queue. |
|
binji
2013/08/22 18:09:36
sp: event
Sam Clegg
2013/08/22 19:52:25
Done.
| |
| 319 // ENOENT and we'll pass the message through to the event queue. | 395 pp::Var event(var); |
| 320 if (fd_tty_ >= 0 && var.type == PP_VARTYPE_STRING) { | 396 if (tty_fd_ >= 0 && event.is_string()) { |
| 321 uint32_t message_len; | 397 std::string message = event.AsString(); |
| 322 const char* message = PSInterfaceVar()->VarToUtf8(var, &message_len); | 398 size_t prefix_len = strlen(tty_prefix_); |
| 323 std::string message_str(message, message + message_len); | 399 if (message.size() > prefix_len) { |
| 400 if (!strncmp(message.c_str(), tty_prefix_, prefix_len)) { | |
| 401 MessageHandlerInput(pp::Var(message.substr(prefix_len))); | |
| 402 return; | |
| 403 } | |
| 404 } | |
| 405 } | |
| 324 | 406 |
| 325 // Since our message may contain null characters, we can't send it as a | 407 // If the message is a dictionary then see if it matches one |
| 326 // naked C string, so we package it up in this struct before sending it | 408 // of the specific handlers, then call that handler rather than |
| 327 // to the ioctl. | 409 // queuing an event. |
| 328 struct tioc_nacl_input_string ioctl_message; | 410 if (tty_fd_ >= 0 && event.is_dictionary()) { |
| 329 ioctl_message.length = message_len; | 411 pp::VarDictionary dictionary(var); |
| 330 ioctl_message.buffer = message_str.data(); | 412 pp::VarArray keys = dictionary.GetKeys(); |
| 331 int ret = | 413 if (keys.GetLength() == 1) { |
| 332 ioctl(fd_tty_, TIOCNACLINPUT, reinterpret_cast<char*>(&ioctl_message)); | 414 pp::Var key = keys.Get(0); |
| 333 if (ret != 0 && errno != ENOTTY) { | 415 std::map<std::string, MessageHandler>::iterator iter = |
|
binji
2013/08/22 18:09:36
I find that this is a bit more readable if you mak
Sam Clegg
2013/08/22 19:52:25
Done.
| |
| 334 Error("ioctl returned unexpected error: %d.\n", ret); | 416 message_handlers_.find(key.AsString()); |
| 417 if (iter != message_handlers_.end()) { | |
| 418 MessageHandler_t handler = iter->second.handler; | |
| 419 void* user_data = iter->second.user_data; | |
| 420 handler(key, dictionary.Get(key), user_data); | |
| 421 return; | |
| 422 } | |
| 335 } | 423 } |
| 336 | |
| 337 return; | |
| 338 } | 424 } |
| 339 | 425 |
| 340 PSInterfaceVar()->AddRef(var); | 426 PSInterfaceVar()->AddRef(var); |
| 341 PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent)); | 427 PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent)); |
| 342 memset(env, 0, sizeof(*env)); | 428 memset(env, 0, sizeof(*env)); |
| 343 env->type = type; | 429 env->type = type; |
| 344 env->as_var = var; | 430 env->as_var = var; |
| 345 event_queue_.Enqueue(env); | 431 event_queue_.Enqueue(env); |
| 346 } | 432 } |
| 347 | 433 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 413 | 499 |
| 414 void PSInstance::Graphics3DContextLost() { | 500 void PSInstance::Graphics3DContextLost() { |
| 415 Log("Graphics3DContextLost\n"); | 501 Log("Graphics3DContextLost\n"); |
| 416 PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST); | 502 PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST); |
| 417 } | 503 } |
| 418 | 504 |
| 419 void PSInstance::MouseLockLost() { | 505 void PSInstance::MouseLockLost() { |
| 420 Log("MouseLockLost\n"); | 506 Log("MouseLockLost\n"); |
| 421 PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST); | 507 PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST); |
| 422 } | 508 } |
| OLD | NEW |