7
votes

I'm working on a standalone daemon executable that needs to load an existing third party NPAPI plugin on a host machine. What I want to do is render the generated views from the plugin to a texture/surface.

It needs to work on both Mac and Windows, but since I'm a heavy Mac user, I decided to build the Mac version first. We don't have the source code for this plugin - it's something an external vendor supplied us with - so it's a black box implementation.

On the web, the plugin works in a very similar way to flash. You embed an area in a webpage linked to a certain mimetype (i.e application/flash) and that loads the plugin, which in turn will instruct the plugin to load a certain file (think an SWF) and then render it.

What I'm doing right now is:

1. Open the library (Bundle) and extract NP_Initialize etc.
2. Call NP_Initialize -> returns the object with NPP function pointers etc
3. Call NPP_New (this calls a set of NPP functions) -> ultimately returns NPERR_NO_ERROR. 

Since NPERR_NO_ERROR is the expected response, I'm assuming these three steps were completed successfully.

During NPP_New, the plugin requests both the Cocoa Event model and the Core Animation (or alternatively, Core Graphics, if I return false for Core Animation) rendering mode.

Then I call:

4. NPP_SetWindow
5. Once the window is set, I load an online file with CURL, and call NPP_NewStream/WriteReady/Write and DestroyStream.

From what I could find in the NPAPI documentation, the NewStream/WriteStream/etc functions basically load a file into memory of the plugin, so it can be rendered.

The plugin supports both Core Animation and Core Graphics in a browser, and works fine in browsers that support NPAPI plugins.

Once I've done all of the above, I attempt to render to a texture, but I keep getting false responses back from NPP_Event function calls with a CGContextRef when in Core Graphics mode. When running in Core Animation mode, I render the texture to a bitmap using renderInContext but the entire image stays blank/transparent.

It's a long shot, but does anyone have any ideas?

1
Are there any other calls coming from the plugin into your "page"? Did you call and request the root NPObject from the plugin? There may be something the plugin is expecting that you haven't provided yettaxilian
How do I figure out what exactly I need to provide to the plugin? During NPP_New a ton of NPN functions are called from the plugin (some Get/SetValue, Invoke, Evaluate) in the “fake” browser. I return NPObjects based on my best guess of what needs to be returned. After trial and error (plugin would shutdown if the returned objects aren’t of the correct type), NPP_New eventually returns NO_ERR. I haven’t called the root NPObject from the plugin (though the plugin does request the root NPObject from the browser during NPP_New). But what would I do with that object?Charles
Ok so, I've set up a proxy plugin logger. When loading the plugin through Firefox, it seems an NPN_GetURLNotify event is received after NPP_New returns NO_ERR successfully. However, my C++ app never receives this. Do I need to set up threading or an event loop or something to capture this?Charles
It's hard to say; it could well be that the results of those calls aren't ending up being what the plugin expects, thus it doesn't work correctlytaxilian
NPAPI is poorly specified; in general, reverse-engineering what browsers do and then doing it yourself is really the only way to implement a host. Different plugins implicitly rely on specific behaviors that were probably originally quirks of one browser, but now have to be replicated everywhere (e.g., the QuickTime plugin on Mac requires initialization calls to be done in a specific order even though essentially no other plugins do).smorgan

1 Answers

2
votes

I assume you don't use this UI thread, if you do try your code in a different thread if that's the case. However, it can be related to a number of things, start with the image itself (since it is empty/transparent), this what I use:

UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [[UIScreen mainScreen] scale]);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); //after this you should see the image

The comments below are related to Mozilla CoreAnimationDrawingModel plugin

(Your black box plugin might be based on it?)

Make sure that you use Flash 10.1+ since Core Animation drawing model is not supported before that version (you loaded an SWF).

Note! If your black box plugin render using QTMovieLayer it should fail, since it's not supported with renderInContext.

Additional interesting reading about your topic (from 2010): Core Animation