Netscape-style plug-ins are programmed in C, and, provided that you are building in Mach-O form, can be developed and debugged with Xcode.
The scripting capabilities of Netscape-style plug-ins are provided by extensions onto the original plug-in specification. They allow a browser (through JavaScript) to access and control elements of the plug-in and its content, and allow the plug-in to access the enclosing web page and its content through the plug-in script interface.
When a plug-in is loaded, the browser calls the NPP_GetValue
callback in your plug-in, which returns a retained NPObject
structure that represent your plug-in. This NPObject
structure contains an pointer to an NPClass
structure. The NPClass
structure contains a series of callbacks that define the interface between the plug-in and the scripting environment. The NPObject
instance represents an instance of that plug-in that can then be used by the scripting environment.
If you want your plug-in to be scriptable, you need to return the appropriate retained NPObject
by reference in your NPP_GetValue
callback function.
Note: In current versions of WebKit and all non-WebKit-based browsers, you must retain the NPObject
instance upon return by doing the following:
browser->retainobject((NPObject*)obj); |
A good demonstration of accessing plug-ins from JavaScript, as well as all the other concepts in creating a Netscape plug-in, can be found at:
/Developer/Examples/WebKit/NetscapeMoviePlugIn |
on a computer running Mac OS X v10.5 or earlier.
Safari 4.0 provides two new drawing models: Core Graphics (Quartz 2D) and Core Animation (only in Mac OS X v10.5 and later). These drawing modes are strongly recommended going forwards, and if you move your plug-in to contain a 64-bit slice, that slice must use these drawing models. (See “Transitioning a Netscape-Style Plug-in to 64-bit” for more information.)
Most of the effort in using these drawing models comes from learning Core Graphics and Core Animation themselves. To learn about Core Graphics, read Quartz 2D Programming Guide. To learn about Core Animation, read Core Animation Programming Guide.
Once you understand how to draw things using Core Graphics or Core Animation, you can enable these drawing models in your NPP_New
function as follows:
Add support in your code for the Cocoa event model. Core Graphics and Core Animation are not supported when using the Carbon event model.
Check to see if the host browser supports the drawing model with the following code:
NPBool supportsCG = false; |
NPError error = browser->getvalue(instance, |
NPNVsupportsCoreGraphicsBool, |
&supportsCG); |
Set the browser drawing model with the following code:
if (err == NPERR_NO_ERROR && supportsCG) { |
error = browser->setvalue(instance, |
NPNVpluginDrawingModel, |
(void *)NPDrawingModelCoreGraphics); |
if (err == NPERR_NO_ERROR && supportsCG) { |
/* Set state flags as needed to |
tell your own code to use Core Graphics |
drawing in the future. */ |
} |
} |
After you have done these two things, the browser fills the window
field of the NPWindow
structure with an NP_CGContext
structure. This structure contains two fields, context
and window
, which are defined as follows:
typedef struct NP_CGContext |
{ |
CGContextRef context; |
WindowRef window; |
} NP_CGContext; |
The context
value is a Core Graphics drawing context suitable for Quartz 2D drawing. For more information on how to use this context, read Quartz 2D Programming Guide. The window is a reference to an NSWindow
object.
To obtain the bounds for your plug-in’s drawing region, do the following in your NPP_SetWindow
callback:
NPError setwindow_cb(NPP instance, NPWindow* npw) { |
... |
NP_CGContext *npcontext = npw.window; |
CGContextRef context = npcontext.context; |
CGRect boundingBox = CGContextGetClipBoundingBox(context); |
... |
The Core Animation model is similar, but reversed. If you set you set NPNVpluginDrawingModel
to NPDrawingModelCoreAnimation
, your NPN_GetValue
callback must provide a retained Core Animation layer to the browser when it queries the NPPVpluginCoreAnimationLayer
variable.
As with the Core graphics model, you can find out if the browser supports the Core Animation drawing model by checking the value of the NPNVsupportsCoreAnimationBool
variable. For example:
NPBool supportsCA = false; |
NPError error = browser->getvalue(instance, |
NPNVsupportsCoreAnimationBool, |
&supportsCA); |
Beginning in Mac OS X v10.6, on 64-bit-capable computers, Netscape-style plug-ins execute in an out-of-process fashion. This means that each Netscape-style plug-in gets its own process separate from the application process. This design applies to all Netscape-style plug-ins. It does not apply to WebKit plug-ins, nor at present to WebKit-based applications when running in 32-bit mode.
Out-of-process execution is used for several reasons:
Stability—crashes in plug-ins no longer crash the entire browser.
Security—vulnerabilities in a plug-in can't read or alter data or code in other plug-ins or in the application itself.
For your plug-in to work correctly in this new environment, you may need to make some changes to your code, depending on how it interacts with the rest of the system beyond the browser.
Avoid direct data structure access. If you directly access application data structures (menus, other windows, etc.), your plug-in will fail. All access to browser data structures should be performed through approved APIs. If no API exists, file a bug and request that one be added.
Draw when asked. Your plug-in must respond to drawRect
event.
Draw only when asked. Any drawing your plug-in performs within the graphics context that Safari provides should take place in response to an update
event (Carbon event model) or a drawRect
event (Cocoa event model). The behavior of drawing performed at other times is undefined.
To provide support for animation, video, and other drawing outside the context of update
or drawRect
events, you should move your code to use the Core Animation drawing model, described in “Core Graphics and Core Animation Drawing Models.”
Get all events through the plug-in API. Because keyboard and mouse events are happening in a different process, if you use Carbon or Cocoa calls to obtain data from the event stream, you will not receive any events.
It is safe to use Carbon or Cocoa calls to obtain global system state information that is outside the scope of the event stream, such as mouse position, modifier keys, and other similar information.
Use platform APIs sparingly. Wherever possible, you should use new plug-in APIs to do what you need. If no such APIs exist, file bugs requesting them.
The plug-in API provides additional APIs for scheduling timers, opening contextual pop-up menus, and so on.
Avoid creating windows. The intent is for plug-ins to operate within the browser window. Although some plug-ins have historically done so, creating windows in your plug-in is not recommended. If you need to maintain separate windows, you should consider starting a separate application.
Beginning in Snow Leopard, Safari is moving to a 64-bit process. This section describes how to adapt a Netscape-style plug-in so that it works when compiled as a 64-bit plug-in. It describes only the changes specific to Netscape-style plug-ins, providing links to other documents for general 64-bit porting information.
Before you begin, do the following:
If your plug-in is built using PEF (CFM) compilers (CodeWarrior, for example), you must move to a modern toolchain that generates Mach-O binaries. There are no 64-bit compilers available that support PEF. The easiest way to do this is to transition your project to Xcode. For more information, read Porting CodeWarrior Projects to Xcode.
You must convert your GUI code from Carbon to Cocoa (or other graphical APIs that are supported in a 64-bit environment). For more information on supported and unsupported Carbon APIs, read 64-Bit Guide for Carbon Developers. Then, read Cocoa Fundamentals Guide to get started learning Cocoa. The preferred APIs for drawing are described further in “Core Graphics and Core Animation Drawing Models.”
If your plug-in uses any Cocoa APIs, read 64-Bit Transition Guide for Cocoa to learn what other Cocoa-specific changes you need to make to this code.
Read 64-Bit Transition Guide to learn about 64-bit changes that apply to all software written in C-based languages.
Once you have read these documents, you need to make a few additional changes specific to Netscape-style plug-ins (at least when compiling 64-bit versions of your plug-in). These changes are as follows:
Use Cocoa Events. In a 64-bit environment, you must convert your code to use the Cocoa event model because the Carbon event model is not supported. This requires several changes:
Use the NPCocoaEvent
data type with the Cocoa event model instead of the NPEvent
data type. The NPCocoaEvent
data type provides neatly broken out fields containing various pieces of information about the event, and is fairly self-explanatory.
Disable the Carbon model test code (including the test to see if the Carbon model is supported) when compiling for 64-bit by wrapping the relevant code with the #ifndef __LP64__
and #endif
C preprocessor directives.
The NPEventModelCarbon
constant (for use with the NPNVpluginEventModel
variable) and the NPNVsupportsCarbonBool
constant (for use with NPN_GetValue
) are not defined at all in a 64-bit environment. By using the C preprocessor directives above, you prevent the compiler itself from ever seeing the intervening lines of code, thus avoiding a compile failure.
Bring up your Cocoa event model code in 32-bit first. This makes it possible to test the Cocoa event code in isolation without having to worry about bugs specific to the 64-bit environment.
Do not remove your Carbon event model code, however. Although the Cocoa event model is supported in 32-bit WebKit beginning in Mac OS X v10.6, it may not be supported in other browsers that use Netscape-style plug-ins, nor in earlier versions of WebKit.
For maximum backwards compatibility and cross-browser compatibility, you should check the NPNVsupportsCarbonBool
and NPNVsupportsCocoaBool
variable using NPN_GetValue
to determine which event models the browser supports. If the browser supports both event models, you should use the Cocoa event model. Otherwise, use the Carbon event model.
For testing purposes, simply hard-wire your test to always use the Cocoa event model.
Replace QuickDraw. The QuickDraw drawing model is not supported. You must rewrite any QuickDraw code using another drawing model such as the Core Graphics or Core Animation drawing modes.
As a result, the NPDrawingModelQuickDraw
constant (for use with the NPNVpluginDrawingModel
variable) and the NPNVsupportsQuickDrawBool
constant (for use with the NPN_GetValue
function) are not defined. Thus, any code that tests for the availability of the QuickDraw drawing model must be wrapped with #ifdef __LP64__
and #endif
C preprocessor directives.
Note: You can take the same approach to replacing QuickDraw code that you too with the Carbon event model—deploy first on 32-bit using a test to see which models are supported, temporarily tweak that test to report that QuickDraw isn’t available (for testing purposes), then test and deploy your new drawing code on 32-bit. Use C preprocessor directives to skip the test entirely when compiling 64-bit so that only the Core Graphics or Core Animation drawing model code is seen by the compiler.
Similarly, the NPQDRegion
and NP_Port
data types are not defined.
In the NP_CGContext
data type, the window
field may be either a WindowRef
instance or an NSWindow
instance in 32-bit WebKit depending on the drawing model chosen. Because Carbon drawing APIs are not supported, these fields always contain an NSWindow
instance in 64-bit WebKit.
For more information about the Core Graphics and Core Animation drawing models, see “Core Graphics and Core Animation Drawing Models.”
Once you have accounted for these differences, you should be ready to compile your plug-in with a 64-bit slice. For more information on compiling code for 64-bit, fixing truncation bugs, and various other relevant topics, read 64-Bit Transition Guide for Cocoa and 64-Bit Transition Guide.
Last updated: 2009-03-13