Asynchronous callback invocation from a worker thread


#1

Hi,

My browser plugin application needs to be able to call a javascript function asynchronously from a Juce::Thread’s run() method.

This can’t be done with a simple var::call() function because NPN_Invoke () calls are only valid on the browser thread so I have hacked the Juce wrapper code to call an asynchronous version of invokeMethod(). It seems to work OK but unfortunately it replaces the existing invokeMethod() functionality so its not by any means a patch that can be merged into the main repository yet. I’m not familiar enough with the Juce architecture to implement this properly and I also haven’t had a look at how to implement this for the ActiveX/IE case yet.

As it stands its quite useful though so I was wondering if someone could give me a hand completing this as its quite a useful functionality to have.

Thanks,
Aaron

[code]— a/plugin/wrapper/juce_NPAPI_GlueCode.cpp
+++ b/plugin/wrapper/juce_NPAPI_GlueCode.cpp
@@ -611,7 +611,45 @@ public:
return browser.hasmethod (npp, source, getIdentifierFromString (methodName));
}

  • const var invokeMethod (const var::identifier& methodName,
  •   struct AsyncCallbackData
    
  •   {
    
  •           DynamicObjectWrappingNPObject *obj;
    
  •           var::identifier methodName;
    
  •           var *parameters;
    
  •           int numParameters;
    
  •   };
    
  •   bool asyncInvokeMethod(const var::identifier& methodName, const var* parameters, int numParameters)
    
  •   {
    
  •           if(browser.version < NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL)
    
  •                   return false;
    
  •           AsyncCallbackData *data = new AsyncCallbackData;
    
  •           data->obj = new DynamicObjectWrappingNPObject(*this);
    
  •           data->obj->incReferenceCount();
    
  •           data->methodName = methodName;
    
  •           data->numParameters = numParameters;
    
  •           data->parameters = new var[numParameters];
    
  •           browser.pluginthreadasynccall(npp, DynamicObjectWrappingNPObject::asyncThreadCallback, data);
    
  •           return true;
    
  •   }
    
  •   static void asyncThreadCallback(void *userdata)
    
  •   {
    
  •           AsyncCallbackData *data = (AsyncCallbackData *)userdata;
    
  •           data->obj->invokeMethodX(data->methodName, data->parameters, data->numParameters);
    
  •           data->obj->decReferenceCount();
    
  •           delete [] data->parameters;
    
  •           delete data;
    
  •   }
    
  •   const var invokeMethod (const var::identifier& methodName, const var* parameters, int numParameters)
    
  •   {
    
  •           asyncInvokeMethod(methodName, parameters, numParameters);
    
  •           return var();
    
  •   }
    
  • const var invokeMethodX (const var::identifier& methodName,
    const var* parameters,
    int numParameters)
    {
    [/code]

#2

Why not use an ASyncUpdater, or MessageManager::callFunctionOnMessageThread, or post a CallbackMessage to invoke your function, rather than trying to change the browser wrapper stuff?


#3

All good ideas but I need to trigger JavaScript callbacks, not C++ ones. These need to be initiated on the browser message thread. In NPAPI version 19+ the NPAPI_PluginThreadAsyncCall function can be used to request execution of a function on this thread for this very purpose but support doesn’t seem to be designed into Juce for that right now.

On Mac OSX, this function exists in the 10.6 WebKit framework header files but I suspect it would work in Safari versions below Snow Leopard. On PC, Firefox 3+, Opera, Chrome, Safari, all support it.

The Google O3D guys told me once they use POST_MESSAGE to achieve the same end in ActiveX plugins.


#4

All the suggestions I made were things you could use to make a JS callback on the message thread. You’d simply make your call when the event or message arrives.


#5

Nice! I didn’t expect that to work!

I see you’re adding yourself to message handler chain on Win32 and do platform specific alternatives for the other platforms. Do you know if this will work on 64-bit Safari? I know Juce can’t render to that particular browser due to the plugin sandbox implementation.


#6

In 64-bit safari, AFAIK, everything should work apart from the graphics.