ps_instance.cc revision 558790d6acca3451cf3a6b497803a5f07d0bec58
1c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul// Use of this source code is governed by a BSD-style license that can be
3c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul// found in the LICENSE file.
4c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
5c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <errno.h>
6c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <fcntl.h>
7c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <pthread.h>
8c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <stdio.h>
9c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <stdlib.h>
10c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <sys/types.h>
11c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <sys/stat.h>
12c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
13c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <algorithm>
14c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <cstdlib>
15c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <cstring>
16c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <sstream>
17c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <string>
18c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include <vector>
19c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
20c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "nacl_io/ioctl.h"
21c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "nacl_io/kernel_wrap.h"
22c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "nacl_io/nacl_io.h"
23c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
24c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi/c/ppb_var.h"
25c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
26c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi/cpp/input_event.h"
27c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi/cpp/message_loop.h"
28c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi/cpp/module.h"
29c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi/cpp/rect.h"
30c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi/cpp/size.h"
31c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi/cpp/touch_point.h"
32f2c023291a1f2887294d2aac504f8b82857ad092Brian Paul#include "ppapi/cpp/var.h"
33c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
34c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi_simple/ps_event.h"
35c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi_simple/ps_instance.h"
36c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi_simple/ps_interface.h"
37c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#include "ppapi_simple/ps_main.h"
38c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
39c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#if defined(WIN32)
40c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#define open _open
41c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#define dup2 _dup2
42c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#endif
43c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
44c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulstatic PSInstance* s_InstanceObject = NULL;
45c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
46c9e5671691289006e9b1152d6ce20200a83010c2Brian PaulPSInstance* PSInstance::GetInstance() {
47c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  return s_InstanceObject;
4834a61c66fd1b625a5606b795d192a49632ff1787Keith Whitwell}
49c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
5034a61c66fd1b625a5606b795d192a49632ff1787Keith Whitwellstruct StartInfo {
515ab1d0aceaffbf872d7f8ebea2a6655e25bf2390Brian Paul  PSInstance* inst_;
52c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  uint32_t argc_;
53c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  char** argv_;
54ff3a52643d323626f32a9f1c14464a9501e6494dBrian Paul};
55c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
56c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
57c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul// The starting point for 'main'.  We create this thread to hide the real
58c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul// main pepper thread which must never be blocked.
59c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid* PSInstance::MainThreadThunk(void *info) {
60d25080074f2da1ebc47cdfb5c3491740a57ec03fChia-I Wu  s_InstanceObject->Trace("Got MainThreadThunk.\n");
61c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  StartInfo* si = static_cast<StartInfo*>(info);
62c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  si->inst_->main_loop_ = new pp::MessageLoop(si->inst_);
63c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  si->inst_->main_loop_->AttachToCurrentThread();
64c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
65c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  int ret = si->inst_->MainThread(si->argc_, si->argv_);
66c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  for (uint32_t i = 0; i < si->argc_; i++) {
67c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    delete[] si->argv_[i];
68c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
69c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  delete[] si->argv_;
70c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  delete si;
71c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
72c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // Exit the entire process once the 'main' thread returns.
73c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // The error code will be available to javascript via
74c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // the exitcode paramater of the crash event.
75c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  exit(ret);
76c132e2b1db855b3c33d8b879c4a986011d631d43Brian Paul  return NULL;
77c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
78c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
79c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul// The default implementation supports running a 'C' main.
80c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulint PSInstance::MainThread(int argc, char *argv[]) {
81c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  if (!main_cb_) {
82c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    Error("No main defined.\n");
8355e341c4c2e5a6f3475a8a3e6389b904f99a6d1aBrian Paul    return 0;
84c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
8511ebfd22bb451f86a492254b77c90aeb011f8d9aBrian Paul
86ba2a55ccd61d9fa5565640faefb64fd6fb0e70abBrian Paul  Trace("Starting MAIN.\n");
87c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  int ret = main_cb_(argc, argv);
8810db6c2d81506bb8cc5165d07b01e93d3830978dBrian Paul  Log("Main thread returned with %d.\n", ret);
89c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  return ret;
90ae1fdc15238498bf025d0f0be7337e2f9dda455fBrian Paul}
91c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
92808c424b673de109babc608ec74b34f0738ed906Brian PaulPSInstance::PSInstance(PP_Instance instance)
93c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    : pp::Instance(instance),
94c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      pp::MouseLock(this),
952c3785159574e6c8640b6af3ce2ef561d095f324Brian Paul      pp::Graphics3DClient(this),
96c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      main_loop_(NULL),
97c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      events_enabled_(PSE_NONE),
98c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      verbosity_(PSV_WARN),
99c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      fd_tty_(-1) {
100c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // Set the single Instance object
101c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  s_InstanceObject = this;
102c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
103c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#ifdef NACL_SDK_DEBUG
104c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  SetVerbosity(PSV_LOG);
105f37070bab6af350caec905ea7658e9241042b6ccIan Romanick#endif
106f37070bab6af350caec905ea7658e9241042b6ccIan Romanick
107f37070bab6af350caec905ea7658e9241042b6ccIan Romanick  RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
1082cf44390d1e819f23e1d7ceb3199276c9148c647Chia-I Wu                     PP_INPUTEVENT_CLASS_KEYBOARD |
109c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul                     PP_INPUTEVENT_CLASS_WHEEL |
110cc289e22213c5f5fe72602ce81db992bc8f7b1adChia-I Wu                     PP_INPUTEVENT_CLASS_TOUCH);
111cc289e22213c5f5fe72602ce81db992bc8f7b1adChia-I Wu}
112cc289e22213c5f5fe72602ce81db992bc8f7b1adChia-I Wu
113cc289e22213c5f5fe72602ce81db992bc8f7b1adChia-I WuPSInstance::~PSInstance() {}
114559d124ed3f2070c73c5cb9c3b506ddd9cfaeb02José Fonseca
115559d124ed3f2070c73c5cb9c3b506ddd9cfaeb02José Fonsecavoid PSInstance::SetMain(PSMainFunc_t main) {
1161741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  main_cb_ = main;
1171741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg}
1181741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg
1191741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsbergbool PSInstance::Init(uint32_t arg,
1201741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg                      const char* argn[],
1211741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg                      const char* argv[]) {
1221741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  StartInfo* si = new StartInfo;
1231741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg
1241741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  si->inst_ = this;
1251741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  si->argc_ = 1;
1261741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  si->argv_ = new char *[arg+1];
1271741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  si->argv_[0] = NULL;
1281741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg
1291741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  // Process embed attributes into the environment.
1301741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  // Converted the attribute names to uppercase as environment variables are
1311741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  // case sensitive but are almost universally uppercase in practice.
1321741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  for (uint32_t i = 0; i < arg; i++) {
1331741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg    std::string key = argn[i];
1341741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg    std::transform(key.begin(), key.end(), key.begin(), toupper);
1351741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg    setenv(key.c_str(), argv[i], 1);
1361741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  }
1371741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg
1381741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  // Set a default value for SRC.
1391741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  setenv("SRC", "NMF?", 0);
1401741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  // Use the src tag name if ARG0 is not explicitly specified.
1411741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  setenv("ARG0", getenv("SRC"), 0);
1421741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg
1431741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  // Walk ARG0..ARGn populating argv until an argument is missing.
1441741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg  for (;;) {
1451741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg    std::ostringstream arg_stream;
1461741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg    arg_stream << "ARG" << si->argc_;
1471741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg    std::string arg_name = arg_stream.str();
1481741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg    const char* next_arg = getenv(arg_name.c_str());
1491741ddb747ca0be284315adb4b6fe67ddf292d03Kristian Høgsberg    if (NULL == next_arg)
150c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      break;
151559d124ed3f2070c73c5cb9c3b506ddd9cfaeb02José Fonseca
152559d124ed3f2070c73c5cb9c3b506ddd9cfaeb02José Fonseca    char* value = new char[strlen(next_arg) + 1];
153c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    strcpy(value, next_arg);
154c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    si->argv_[si->argc_++] = value;
155c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
156c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
157c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  PSInterfaceInit();
158c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  bool props_processed = ProcessProperties();
159c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
160c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // Log arg values only once ProcessProperties has been
161c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // called so that the ps_verbosity attribute will be in
162c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // effect.
163c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  for (uint32_t i = 0; i < arg; i++) {
164fa416106307dc193e2133aa6a29b9bcfc91f8b39Kristian Høgsberg    if (argv[i]) {
165fa416106307dc193e2133aa6a29b9bcfc91f8b39Kristian Høgsberg      Trace("attribs[%d] '%s=%s'\n", i, argn[i], argv[i]);
166c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    } else {
167fa416106307dc193e2133aa6a29b9bcfc91f8b39Kristian Høgsberg      Trace("attribs[%d] '%s'\n", i, argn[i]);
168fa416106307dc193e2133aa6a29b9bcfc91f8b39Kristian Høgsberg    }
169fa416106307dc193e2133aa6a29b9bcfc91f8b39Kristian Høgsberg  }
170fa416106307dc193e2133aa6a29b9bcfc91f8b39Kristian Høgsberg
171fa416106307dc193e2133aa6a29b9bcfc91f8b39Kristian Høgsberg  for (uint32_t i = 0; i < si->argc_; i++) {
172fa416106307dc193e2133aa6a29b9bcfc91f8b39Kristian Høgsberg    Trace("argv[%d] '%s'\n", i, si->argv_[i]);
173c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
174c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
175c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  if (!props_processed) {
176c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    Warn("Skipping create thread.\n");
177c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    return false;
178c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
179c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
180c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  pthread_t main_thread;
181c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  int ret = pthread_create(&main_thread, NULL, MainThreadThunk, si);
182c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  Trace("Created thread: %d.\n", ret);
183c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  return ret == 0;
184c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
185c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
18634a61c66fd1b625a5606b795d192a49632ff1787Keith Whitwell// Processes the properties set at compile time via the
187c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul// initialization macro, or via dynamically set embed attributes
18834a61c66fd1b625a5606b795d192a49632ff1787Keith Whitwell// through instance DidCreate.
18934a61c66fd1b625a5606b795d192a49632ff1787Keith Whitwellbool PSInstance::ProcessProperties() {
190c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // Set default values
191c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  setenv("PS_STDIN", "/dev/stdin", 0);
192c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  setenv("PS_STDOUT", "/dev/stdout", 0);
193c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  setenv("PS_STDERR", "/dev/console3", 0);
194c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
195c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // Reset verbosity if passed in
196c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  const char* verbosity = getenv("PS_VERBOSITY");
197c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  if (verbosity) SetVerbosity(static_cast<Verbosity>(atoi(verbosity)));
198c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
199c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // Enable NaCl IO to map STDIN, STDOUT, and STDERR
200c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  nacl_io_init_ppapi(PSGetInstanceId(), PSGetInterface);
201c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  int fd0 = open(getenv("PS_STDIN"), O_RDONLY);
202c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  dup2(fd0, 0);
203c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
204c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  int fd1 = open(getenv("PS_STDOUT"), O_WRONLY);
205c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  dup2(fd1, 1);
206c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
207c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  int fd2 = open(getenv("PS_STDERR"), O_WRONLY);
208c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  dup2(fd2, 2);
209c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
210c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  const char* tty_prefix = getenv("PS_TTY_PREFIX");
211c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  if (tty_prefix) {
212c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    fd_tty_ = open("/dev/tty", O_WRONLY);
213c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    if (fd_tty_ >= 0) {
214c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      ioctl(fd_tty_, TIOCNACLPREFIX, const_cast<char*>(tty_prefix));
215c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    } else {
216c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      Error("Failed to open /dev/tty.\n");
217c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    }
218c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
219c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
220c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // Set line buffering on stdout and stderr
221c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul#if !defined(WIN32)
222a833ff0f53da6e365d917bb0081d909a809b6ec1Chia-I Wu  setvbuf(stderr, NULL, _IOLBF, 0);
223a833ff0f53da6e365d917bb0081d909a809b6ec1Chia-I Wu  setvbuf(stdout, NULL, _IOLBF, 0);
224a73ba2d31b87e974f6846a8aaced704634f6f657Chia-I Wu#endif
225a833ff0f53da6e365d917bb0081d909a809b6ec1Chia-I Wu  return true;
226c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
227c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
228c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::SetVerbosity(Verbosity verbosity) {
229c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  verbosity_ = verbosity;
230c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
231c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
232c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::VALog(Verbosity verbosity, const char *fmt, va_list args) {
233c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  if (verbosity <= verbosity_) {
234c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    fprintf(stderr, "ps: ");
23567a2a4e901367418a5c28e7b0963bf9c0c4762baChia-I Wu    vfprintf(stderr, fmt, args);
23667a2a4e901367418a5c28e7b0963bf9c0c4762baChia-I Wu  }
237301a510092859d2e214d64f4ac2ebe03d591c64bChia-I Wu}
23867a2a4e901367418a5c28e7b0963bf9c0c4762baChia-I Wu
239c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::Trace(const char *fmt, ...) {
240c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_list ap;
241c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_start(ap, fmt);
242c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  VALog(PSV_TRACE, fmt, ap);
243c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_end(ap);
244c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
245c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
246c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::Log(const char *fmt, ...) {
247c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_list ap;
248c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_start(ap, fmt);
249c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  VALog(PSV_LOG, fmt, ap);
250c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_end(ap);
251c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
252c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
253c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::Warn(const char *fmt, ...) {
254c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_list ap;
255c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_start(ap, fmt);
256c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  VALog(PSV_WARN, fmt, ap);
257c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_end(ap);
258c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
259c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
260c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::Error(const char *fmt, ...) {
261c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_list ap;
262c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_start(ap, fmt);
263c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  VALog(PSV_ERROR, fmt, ap);
264c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  va_end(ap);
265c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
266c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
267c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::SetEnabledEvents(uint32_t mask) {
268c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  events_enabled_ = mask;
269c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
270c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
271c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::PostEvent(PSEventType type) {
272aefa1f6ab1d9267b223b06ae205ab34c8e0d7c02Chia-I Wu  assert(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST == type ||
273aefa1f6ab1d9267b223b06ae205ab34c8e0d7c02Chia-I Wu         PSE_MOUSELOCK_MOUSELOCKLOST == type);
274aefa1f6ab1d9267b223b06ae205ab34c8e0d7c02Chia-I Wu
275c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  if (events_enabled_ & type) {
276dbb8fb8de9a9deca0ae22015e4680f4e631d6d32Chia-I Wu    PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
277dbb8fb8de9a9deca0ae22015e4680f4e631d6d32Chia-I Wu    memset(env, 0, sizeof(*env));
278dbb8fb8de9a9deca0ae22015e4680f4e631d6d32Chia-I Wu    env->type = type;
27934a61c66fd1b625a5606b795d192a49632ff1787Keith Whitwell    event_queue_.Enqueue(env);
280c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
281c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
282c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
283c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::PostEvent(PSEventType type, PP_Bool bool_value) {
2842b36db496d34c60a3f987fa88d52bf5684713240Chia-I Wu  assert(PSE_INSTANCE_DIDCHANGEFOCUS == type);
2852b36db496d34c60a3f987fa88d52bf5684713240Chia-I Wu
286d25080074f2da1ebc47cdfb5c3491740a57ec03fChia-I Wu  if (events_enabled_ & type) {
2872b36db496d34c60a3f987fa88d52bf5684713240Chia-I Wu    PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
288c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    memset(env, 0, sizeof(*env));
289c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    env->type = type;
290c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    env->as_bool = bool_value;
291c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    event_queue_.Enqueue(env);
292c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
293c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
29434a61c66fd1b625a5606b795d192a49632ff1787Keith Whitwell
295cc95de82e5939586771d478e662cb458bbc42c20Chia-I Wuvoid PSInstance::PostEvent(PSEventType type, PP_Resource resource) {
29634a61c66fd1b625a5606b795d192a49632ff1787Keith Whitwell  assert(PSE_INSTANCE_HANDLEINPUT == type ||
297c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul         PSE_INSTANCE_DIDCHANGEVIEW == type);
298c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
299c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  if (events_enabled_ & type) {
300c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    if (resource) {
301c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      PSInterfaceCore()->AddRefResource(resource);
302c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    }
303c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
304c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    memset(env, 0, sizeof(*env));
305c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    env->type = type;
306c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    env->as_resource = resource;
307c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    event_queue_.Enqueue(env);
308c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
309c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
310c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
311c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::PostEvent(PSEventType type, const PP_Var& var) {
312c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  assert(PSE_INSTANCE_HANDLEMESSAGE == type);
313c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
314c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // If the user has specified a tty_prefix_ (using ioctl), then we'll give the
315c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // tty node a chance to vacuum up any messages beginning with that prefix. If
316c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // the message does not start with the prefix, the ioctl call will return
317c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  // ENOENT and we'll pass the message through to the event queue.
318c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  if (fd_tty_ >= 0 && var.type == PP_VARTYPE_STRING) {
319c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    uint32_t message_len;
320c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    const char* message = PSInterfaceVar()->VarToUtf8(var, &message_len);
321c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    std::string message_str(message, message + message_len);
322c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
323c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    // Since our message may contain null characters, we can't send it as a
324c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    // naked C string, so we package it up in this struct before sending it
325c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    // to the ioctl.
326c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    struct tioc_nacl_input_string ioctl_message;
327c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    ioctl_message.length = message_len;
328c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    ioctl_message.buffer = message_str.data();
329c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    int ret =
330c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      ioctl(fd_tty_, TIOCNACLINPUT, reinterpret_cast<char*>(&ioctl_message));
331c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    if (ret != 0 && errno != ENOTTY) {
332c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      Error("ioctl returned unexpected error: %d.\n", ret);
333c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    }
334c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
335c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    return;
336c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
337c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
338c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  if (events_enabled_ & type) {
339c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    PSInterfaceVar()->AddRef(var);
34034a61c66fd1b625a5606b795d192a49632ff1787Keith Whitwell    PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
341cb4f24e51d0f4f4b867b2c01ed26d2a5ce73aeabChia-I Wu    memset(env, 0, sizeof(*env));
3425a1e25afac8eac5df1c0c9d3165b9812f54909a6Chia-I Wu    env->type = type;
343cab7ea03688ec73dd71c0b969f2db30cabeb713cChia-I Wu    env->as_var = var;
344c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    event_queue_.Enqueue(env);
345c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
346c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
347c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
348c9e5671691289006e9b1152d6ce20200a83010c2Brian PaulPSEvent* PSInstance::TryAcquireEvent() {
349c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  return event_queue_.Dequeue(false);
350c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
351c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
352c9e5671691289006e9b1152d6ce20200a83010c2Brian PaulPSEvent* PSInstance::WaitAcquireEvent() {
353c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  return event_queue_.Dequeue(true);
354c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
355c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
356c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::ReleaseEvent(PSEvent* event) {
357c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  if (event) {
358c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    switch(event->type) {
359c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      case PSE_INSTANCE_HANDLEMESSAGE:
360c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul        PSInterfaceVar()->Release(event->as_var);
361c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul        break;
362c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      case PSE_INSTANCE_HANDLEINPUT:
363c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      case PSE_INSTANCE_DIDCHANGEVIEW:
364c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul        if (event->as_resource) {
365c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul          PSInterfaceCore()->ReleaseResource(event->as_resource);
366c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul        }
367c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul        break;
368c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul      default:
369c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul        break;
370c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    }
371c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul    free(event);
372c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  }
373c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
374c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
375c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::HandleMessage(const pp::Var& message) {
376c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  Trace("Got Message\n");
377c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  PostEvent(PSE_INSTANCE_HANDLEMESSAGE, message.pp_var());
378c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
379c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
380c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulbool PSInstance::HandleInputEvent(const pp::InputEvent& event) {
381c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  PostEvent(PSE_INSTANCE_HANDLEINPUT, event.pp_resource());
382c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  return true;
383c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
384c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
385c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::DidChangeView(const pp::View& view) {
386c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  pp::Size new_size = view.GetRect().size();
387c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  Log("Got View change: %d,%d\n", new_size.width(), new_size.height());
388c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  PostEvent(PSE_INSTANCE_DIDCHANGEVIEW, view.pp_resource());
389c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
390c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
391c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::DidChangeFocus(bool focus) {
392c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  Log("Got Focus change: %s\n", focus ? "FOCUS ON" : "FOCUS OFF");
393c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  PostEvent(PSE_INSTANCE_DIDCHANGEFOCUS, focus ? PP_TRUE : PP_FALSE);
394c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
395c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
396c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::Graphics3DContextLost() {
397c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  Log("Graphics3DContextLost\n");
398c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST);
399c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
400c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul
401c9e5671691289006e9b1152d6ce20200a83010c2Brian Paulvoid PSInstance::MouseLockLost() {
402c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  Log("MouseLockLost\n");
403c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul  PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST);
404c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul}
405c9e5671691289006e9b1152d6ce20200a83010c2Brian Paul