1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef PPAPI_SIMPLE_PS_INSTANCE_H_ 6 #define PPAPI_SIMPLE_PS_INSTANCE_H_ 7 8 #include <stdarg.h> 9 10 #include "ppapi/c/pp_instance.h" 11 #include "ppapi/c/pp_stdint.h" 12 #include "ppapi/c/ppb_core.h" 13 #include "ppapi/c/ppb_var.h" 14 #include "ppapi/c/ppb_view.h" 15 16 #include "ppapi/cpp/fullscreen.h" 17 #include "ppapi/cpp/graphics_3d_client.h" 18 #include "ppapi/cpp/instance.h" 19 #include "ppapi/cpp/message_loop.h" 20 #include "ppapi/cpp/mouse_lock.h" 21 22 #include "ppapi/utility/completion_callback_factory.h" 23 24 #include "ppapi_simple/ps_event.h" 25 #include "ppapi_simple/ps_main.h" 26 27 #include "sdk_util/thread_safe_queue.h" 28 29 typedef void (*MessageHandler_t)(const pp::Var& key, 30 const pp::Var& value, 31 void* user_data); 32 33 struct MessageHandler { 34 MessageHandler_t handler; 35 void* user_data; 36 }; 37 38 // The basic instance class which also inherits the MouseLock and 39 // Graphics3DClient interfaces. 40 class PSInstance : public pp::Instance, pp::MouseLock, pp::Graphics3DClient { 41 public: 42 // Verbosity levels, ecplicitly numbered since we pass these 43 // in from html attributes as numberic values. 44 enum Verbosity { 45 PSV_SILENT = 0, 46 PSV_ERROR = 1, 47 PSV_WARN = 2, 48 PSV_LOG = 3, 49 PSV_TRACE = 4, 50 }; 51 52 // Returns a pointer to the global instance 53 static PSInstance* GetInstance(); 54 55 PSInstance(PP_Instance inst); 56 virtual ~PSInstance(); 57 58 // Set a function which will be called on a new thread once initialized. 59 // NOTE: This must be called by the Factory, once Init is called, this 60 // function will have no effect. 61 void SetMain(PSMainFunc_t func); 62 63 // Started on Init, a thread which can be safely blocked. 64 virtual int MainThread(int argc, char* argv[]); 65 66 // Logging Functions 67 void SetVerbosity(Verbosity verbosity); 68 void Trace(const char *fmt, ...); 69 void Log(const char *fmt, ...); 70 void Warn(const char *fmt, ...); 71 void Error(const char *fmt, ...); 72 73 // Event Functions 74 void SetEnabledEvents(uint32_t mask); 75 void PostEvent(PSEventType type); 76 void PostEvent(PSEventType type, PP_Bool bool_value); 77 void PostEvent(PSEventType type, PP_Resource resource); 78 void PostEvent(PSEventType type, const PP_Var& var); 79 80 PSEvent* TryAcquireEvent(); 81 PSEvent* WaitAcquireEvent(); 82 void ReleaseEvent(PSEvent* event); 83 84 // Register a message handler for messages that arrive 85 // from JavaScript with a give names. Messages are of the 86 // form: { message_name : <value> }. 87 // 88 // PSInstance will then not generate events but instead 89 // cause the handler to be called upon message arrival. 90 // If handler is NULL then the current handler will be 91 // removed. Example usage: 92 // 93 // JavaScript: 94 // nacl_module.postMessage({'foo': 123}); 95 // 96 // C++: 97 // void MyMessageHandler(const pp::Var& key, 98 // const pp::Var& value, 99 // void* user_data) { 100 // assert(key.is_string()); 101 // assert(key.AsString() == "foo"); 102 // assert(value.is_int()); 103 // assert(value.AsInt() == 123); 104 // } 105 // ... 106 // instance_->RegisterMessageHandler("foo", &MyMessageHandler, NULL); 107 // 108 void RegisterMessageHandler(std::string message_name, 109 MessageHandler_t handler, 110 void* user_data); 111 112 // Perform exit handshake with JavaScript. 113 // This is called by _exit before the process is terminated to ensure 114 // that all messages sent prior to _exit arrive at the JavaScript side. 115 void ExitHandshake(int status); 116 117 protected: 118 typedef std::map<std::string, MessageHandler> MessageHandlerMap; 119 120 // Callback functions triggered by Pepper 121 // 122 // These functions are called on the main pepper thread, so they must 123 // not block. 124 // 125 // Called by the browser when the NaCl module is loaded and all ready to go. 126 // This function will create a new thread which will run the pseudo main. 127 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); 128 129 // Output log message to stderr if the current verbosity is set 130 // at or above the given verbosity. 131 void VALog(Verbosity verbosity, const char *fmt, va_list args); 132 133 // Called whenever the in-browser window changes size, it will pass a 134 // context change request to whichever thread is handling rendering. 135 virtual void DidChangeView(const pp::View& view); 136 137 // Called by the browser when the NaCl canvas gets or loses focus. 138 virtual void DidChangeFocus(bool has_focus); 139 140 // Called by the browser to handle the postMessage() call in Javascript. 141 virtual void HandleMessage(const pp::Var& message); 142 143 // Called by the browser to handle incoming input events. Events are Q'd 144 // and can later be processed on a sperate processing thread. 145 virtual bool HandleInputEvent(const pp::InputEvent& event); 146 147 // Called by the browser when the 3D context is lost. 148 virtual void Graphics3DContextLost(); 149 150 // Called by the browser when the mouselock is lost. 151 virtual void MouseLockLost(); 152 153 // Called by Init to processes default and embed tag arguments prior to 154 // launching the 'ppapi_main' thread. 155 virtual bool ProcessProperties(); 156 157 private: 158 static void* MainThreadThunk(void *start_info); 159 ssize_t TtyOutputHandler(const char* buf, size_t count); 160 void MessageHandlerExit(const pp::Var& message); 161 void MessageHandlerInput(const pp::Var& key, const pp::Var& message); 162 void MessageHandlerResize(const pp::Var& message); 163 void HandleResize(int width, int height); 164 165 static void HandleExitStatic(int status, void* user_data); 166 167 static ssize_t TtyOutputHandlerStatic(const char* buf, size_t count, 168 void* user_data); 169 170 /// Handle exit confirmation message from JavaScript. 171 static void MessageHandlerExitStatic(const pp::Var& key, 172 const pp::Var& message, 173 void* user_data); 174 175 /// Handle input message from JavaScript. The value is 176 /// expected to be of type string. 177 static void MessageHandlerInputStatic(const pp::Var& key, 178 const pp::Var& message, 179 void* user_data); 180 181 182 /// Handle resizs message from JavaScript. The value is 183 /// expected to be an array of 2 integers representing the 184 /// number of columns and rows in the TTY. 185 static void MessageHandlerResizeStatic(const pp::Var& key, 186 const pp::Var& message, 187 void* user_data); 188 189 protected: 190 pp::MessageLoop* main_loop_; 191 192 sdk_util::ThreadSafeQueue<PSEvent> event_queue_; 193 uint32_t events_enabled_; 194 Verbosity verbosity_; 195 196 // TTY handling 197 int tty_fd_; 198 const char* tty_prefix_; 199 MessageHandlerMap message_handlers_; 200 201 PSMainFunc_t main_cb_; 202 203 const PPB_Core* ppb_core_; 204 const PPB_Var* ppb_var_; 205 const PPB_View* ppb_view_; 206 207 // Condition variable and lock used to wait for exit confirmation from 208 // JavaScript. 209 pthread_cond_t exit_cond_; 210 pthread_mutex_t exit_lock_; 211 212 // A message to Post to JavaScript instead of exiting, or NULL if exit() 213 // should be called instead. 214 char* exit_message_; 215 }; 216 217 #endif // PPAPI_SIMPLE_PS_INSTANCE_H_ 218