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  }