github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/runtime/ppapi/callbacks_nacl.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ppapi 6 7 import ( 8 "sync" 9 "syscall" 10 11 "fmt" 12 ) 13 14 var ( 15 ppNullCompletionCallback pp_CompletionCallback 16 17 ppapiInst Instance 18 didCreateArgs map[string]string 19 handlers InstanceHandlers 20 21 numInstances int 22 23 // Instance table. 24 instanceLock sync.Mutex 25 26 deferredCallbacks []func() 27 ) 28 29 // InstanceHandlers contains handlers that you must implement in your application. 30 type InstanceHandlers interface { 31 // DidCreate() is a creation handler that is called when a new instance is created. 32 // 33 // This function is called for each instantiation on the page, corresponding 34 // to one <embed> tag on the page. 35 // 36 // Generally you would handle this call by initializing the information your 37 // module associates with an instance and creating a mapping from the given 38 // PP_Instance handle to this data. The PP_Instance handle will be used in 39 // subsequent calls to identify which instance the call pertains to. 40 // 41 // It's possible for more than one instance to be created in a single 42 // module. This means that you may get more than one OnCreate without an 43 // OnDestroy in between, and should be prepared to maintain multiple states 44 // associated with each instance. 45 // 46 // If this function reports a failure (by returning false), the instance 47 // will be deleted. 48 DidCreate(args map[string]string) bool 49 50 // DidDestroy is an instance destruction handler. 51 // 52 // This function is called in many cases (see below) when a module instance 53 // is destroyed. It will be called even if DidCreate() returned failure. 54 // 55 // Generally you will handle this call by deallocating the tracking 56 // information and the Instance you created in the DidCreate 57 // call. You can also free resources associated with this instance but this 58 // isn't required; all resources associated with the deleted instance will 59 // be automatically freed when this function returns. 60 // 61 // The instance identifier will still be valid during this call, so the 62 // module can perform cleanup-related tasks. Once this function returns, the 63 // Instance handle will be invalid. This means that you can't do any 64 // asynchronous operations like network requests, file writes or messaging 65 // from this function since they will be immediately canceled. 66 // 67 // Note: This function will always be skipped on untrusted (Native Client) 68 // implementations. This function may be skipped on trusted implementations 69 // in certain circumstances when Chrome does "fast shutdown" of a web 70 // page. Fast shutdown will happen in some cases when all module instances 71 // are being deleted, and no cleanup functions will be called. The module 72 // will just be unloaded and the process terminated. 73 DidDestroy() 74 75 // DidChangeView is called when the position, size, or other view attributes 76 // of the instance has changed. 77 DidChangeView(view View) 78 79 // DidChangeFocus is called when an instance has gained or lost focus. 80 // 81 // Having focus means that keyboard events will be sent to the instance. An 82 // instance's default condition is that it will not have focus. 83 // 84 // The focus flag takes into account both browser tab and window focus as well 85 // as focus of the plugin element on the page. In order to be deemed to have 86 // focus, the browser window must be topmost, the tab must be selected in the 87 // window, and the instance must be the focused element on the page. 88 // 89 // Note:Clicks on instances will give focus only if you handle the click 90 // event. Return true from HandleInputEvent in PPP_InputEvent (or use unfiltered 91 // events) to signal that the click event was handled. Otherwise, the browser 92 // will bubble the event and give focus to the element on the page that actually 93 // did end up consuming it. If you're not getting focus, check to make sure 94 // you're either requesting them via RequestInputEvents() (which implicitly 95 // marks all input events as consumed) or via RequestFilteringInputEvents() and 96 // returning true from your event handler. 97 DidChangeFocus(has_focus bool) 98 99 // HandleDocumentLoad is called after initialize for a full-frame instance 100 // that was instantiated based on the MIME type of a DOMWindow navigation. 101 // 102 // This situation only applies to modules that are pre-registered to handle 103 // certain MIME types. If you haven't specifically registered to handle a 104 // MIME type or aren't positive this applies to you, your implementation of 105 // this function can just return PP_FALSE. 106 // 107 // The given url_loader corresponds to a PPB_URLLoader instance that is 108 // already opened. Its response headers may be queried using 109 // PPB_URLLoader::GetResponseInfo. The reference count for the URL loader is 110 // not incremented automatically on behalf of the module. You need to 111 // increment the reference count yourself if you are going to keep a 112 // reference to it. 113 // 114 // This method returns PP_FALSE if the module cannot handle the data. In 115 // response to this method, the module should call ReadResponseBody() to 116 // read the incoming data. HandleDocumentLoad(url_loader Resource) bool 117 HandleDocumentLoad(url_loader Resource) bool 118 119 // HandleInputEvent is the function for receiving input events from the browser. 120 // 121 // In order to receive input events, you must register for them by calling 122 // PPB_InputEvent.RequestInputEvents() or RequestFilteringInputEvents(). By 123 // default, no events are delivered. 124 // 125 // If the event was handled, it will not be forwarded to the default 126 // handlers in the web page. If it was not handled, it may be dispatched to 127 // a default handler. So it is important that an instance respond accurately 128 // with whether event propagation should continue. 129 // 130 // Event propagation also controls focus. If you handle an event like a 131 // mouse event, typically the instance will be given focus. Returning false 132 // from a filtered event handler or not registering for an event type means 133 // that the click will be given to a lower part of the page and your 134 // instance will not receive focus. This allows an instance to be partially 135 // transparent, where clicks on the transparent areas will behave like 136 // clicks to the underlying page. 137 // 138 // In general, you should try to keep input event handling short. Especially 139 // for filtered input events, the browser or page may be blocked waiting for 140 // you to respond. 141 // 142 // The caller of this function will maintain a reference to the input event 143 // resource during this call. Unless you take a reference to the resource to 144 // hold it for later, you don't need to release it. 145 // 146 // Note: If you're not receiving input events, make sure you register for 147 // the event classes you want by calling RequestInputEvents or 148 // RequestFilteringInputEvents. If you're still not receiving keyboard input 149 // events, make sure you're returning true (or using a non-filtered event 150 // handler) for mouse events. Otherwise, the instance will not receive focus 151 // and keyboard events will not be sent. 152 HandleInputEvent(event InputEvent) bool 153 154 // Graphics3DContextLost is called when the OpenGL ES window is invalidated 155 // and needs to be repainted. 156 Graphics3DContextLost() 157 158 // HandleMessage is a function that the browser calls when PostMessage() is 159 // invoked on the DOM element for the module instance in JavaScript. 160 // 161 // Note that PostMessage() in the JavaScript interface is asynchronous, 162 // meaning JavaScript execution will not be blocked while HandleMessage() is 163 // processing the message. 164 // 165 // When converting JavaScript arrays, any object properties whose name is 166 // not an array index are ignored. When passing arrays and objects, the 167 // entire reference graph will be converted and transferred. If the 168 // reference graph has cycles, the message will not be sent and an error 169 // will be logged to the console. 170 // 171 // The following JavaScript code invokes HandleMessage, passing the module 172 // instance on which it was invoked, with message being a string PP_Var 173 // containing "Hello world!" 174 // 175 // Example: 176 // 177 // <body> 178 // <object id="plugin" 179 // type="application/x-ppapi-postMessage-example"/> 180 // <script type="text/javascript"> 181 // document.getElementById('plugin').postMessage("Hello world!"); 182 // </script> 183 // </body> 184 HandleMessage(message Var) 185 186 // MouseLockLost is called when the instance loses the mouse lock, such as 187 // when the user presses the ESC key. 188 MouseLockLost() 189 } 190 191 // deferOrHandleCallback calls a callback or defers it if configureCallbackHandlers 192 // has not yet been called. 193 func deferOrHandleCallback(f func()) { 194 instanceLock.Lock() 195 if handlers != nil { 196 instanceLock.Unlock() 197 f() 198 } else { 199 deferredCallbacks = append(deferredCallbacks, f) 200 instanceLock.Unlock() 201 } 202 } 203 204 // configureCallbackHandlers is called when the user calls Init() 205 // (after the rest of the callbacks are set up). It sets the callback handlers 206 // and calls any deferred callbacks. 207 func configureCallbackHandlers(factory func(inst Instance) InstanceHandlers) InstanceHandlers { 208 fmt.Printf("Starting create instance handlers...") 209 h := factory(ppapiInst) 210 211 instanceLock.Lock() 212 handlers = h 213 callbacks := deferredCallbacks 214 deferredCallbacks = nil 215 instanceLock.Unlock() 216 217 handlers.DidCreate(didCreateArgs) 218 for _, f := range callbacks { 219 f() 220 } 221 fmt.Printf("Exiting create instance handlers...") 222 return handlers 223 } 224 225 // Called from C. This is called when PPAPI is ready. 226 func ppp_did_create(id pp_Instance, argc int32, argn, argv *[1 << 16]*byte) pp_Bool { 227 instanceLock.Lock() 228 numInstances++ 229 if numInstances > 1 { 230 panic("Only a single instance is currently supported") 231 } 232 ppapiInst = makeInstance(id) 233 didCreateArgs = make(map[string]string) 234 for i := int32(0); i < argc; i++ { 235 didCreateArgs[gostring(argn[i])] = gostring(argv[i]) 236 } 237 var syscallImpl = PPAPISyscallImpl{ppapiInst} 238 stdout.impl = syscallImpl 239 stderr.impl = syscallImpl 240 241 init_fds() 242 syscall.SetImplementation(syscallImpl) 243 instanceLock.Unlock() 244 return ppTrue 245 } 246 247 // Called from C. 248 func ppp_did_destroy(id pp_Instance) { 249 syscall.Write(1, []byte("CALLBACK ppp_did_destroy")) 250 deferOrHandleCallback(func() { 251 instanceLock.Lock() 252 oldHandlers := handlers 253 handlers = nil 254 numInstances-- 255 instanceLock.Unlock() 256 oldHandlers.DidDestroy() 257 }) 258 } 259 260 // Called from C. 261 func ppp_did_change_view(id pp_Instance, view pp_Resource) { 262 syscall.Write(1, []byte("CALLBACK ppp_did_change_view")) 263 deferOrHandleCallback(func() { 264 handlers.DidChangeView(makeView(view)) 265 }) 266 } 267 268 // Called from C. 269 func ppp_did_change_focus(id pp_Instance, hasFocus pp_Bool) { 270 syscall.Write(1, []byte("CALLBACK ppp_did_change_focus")) 271 deferOrHandleCallback(func() { 272 handlers.DidChangeFocus(fromPPBool(hasFocus)) 273 }) 274 } 275 276 // Called from C. 277 func ppp_handle_document_load(id pp_Instance, urlLoader pp_Resource) pp_Bool { 278 syscall.Write(1, []byte("CALLBACK ppp_handle_document_load: %v %v")) 279 result := ppTrue 280 deferOrHandleCallback(func() { 281 ok := handlers.HandleDocumentLoad(makeResource(urlLoader)) 282 result = toPPBool(ok) 283 }) 284 return result 285 } 286 287 // Called from C. 288 func ppp_handle_input_event(id pp_Instance, event pp_Resource) pp_Bool { 289 syscall.Write(1, []byte("CALLBACK ppp_handle_input_event")) 290 result := ppTrue 291 deferOrHandleCallback(func() { 292 ok := handlers.HandleInputEvent(makeInputEvent(event)) 293 result = toPPBool(ok) 294 }) 295 return result 296 } 297 298 // Called from C. 299 func ppp_graphics3d_context_lost(id pp_Instance) { 300 syscall.Write(1, []byte("CALLBACK ppp_graphics3d_context_lost")) 301 deferOrHandleCallback(func() { 302 handlers.Graphics3DContextLost() 303 }) 304 } 305 306 // Called from C. 307 func ppp_handle_message(id pp_Instance, msg pp_Var) { 308 syscall.Write(1, []byte("CALLBACK ppp_handle_message")) 309 deferOrHandleCallback(func() { 310 handlers.HandleMessage(makeVar(msg)) 311 }) 312 } 313 314 // Called from C. 315 func ppp_mouse_lock_lost(id pp_Instance) { 316 syscall.Write(1, []byte("CALLBACK ppp_mouse_lock_lost")) 317 deferOrHandleCallback(func() { 318 handlers.MouseLockLost() 319 }) 320 }