<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ColonelPanic &#187; safari</title>
	<atom:link href="http://colonelpanic.net/tag/safari/feed/" rel="self" type="application/rss+xml" />
	<link>http://colonelpanic.net</link>
	<description>Dumping our corps so you don&#039;t have to</description>
	<lastBuildDate>Mon, 30 Jan 2012 17:50:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Building a firefox plugin – part one</title>
		<link>http://colonelpanic.net/2009/03/building-a-firefox-plugin-part-one/</link>
		<comments>http://colonelpanic.net/2009/03/building-a-firefox-plugin-part-one/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 20:05:53 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Browser Plugin Development]]></category>
		<category><![CDATA[NPAPI]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[npruntime]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[safari]]></category>

		<guid isPermaLink="false">http://colonelpanic.net/?p=42</guid>
		<description><![CDATA[Note: For a better way to create a Browser Plugin (that will work on all browsers, not just NPAPI), check out the FireBreath project. Getting help: For a better place to ask NPAPI-related questions, check out the FireBreath Forums. Yes, there is a forum there for NPAPI plugins that don&#8217;t use FireBreath as well. Introduction [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Note: </strong>For a better way to create a Browser Plugin (that will work on all browsers, not just NPAPI), check out the <a href="http://www.firebreath.org">FireBreath project</a>.</p>
<p><strong>Getting help: </strong>For a better place to ask NPAPI-related questions, check out the <a href="http://forum.firebreath.org">FireBreath Forums</a>. Yes, there is a forum there for NPAPI plugins that don&#8217;t use FireBreath as well.</p>
<h2>Introduction</h2>
<p>I have now been researching and working on a cross-platform browser plugin for several months.  By far my greatest frustration throughout this process has been the significant lack of documentation on the subject.  So, with the creation of this site, I wish to create a small series that will hopefully provide assistance to other poor developers who are trying to break into this strangely secretive field =]</p>
<p>I&#8217;m not going to be able to cover everything in one post (for time reasons if nothing else).  How fast I get the rest of the posts done may depend in large part on whether or not anyone seems to be reading them and what requests are made in the comments =]</p>
<h3>Plugin architecture</h3>
<p>In these articles I plan to focus on the basic requirements for creating an NPAPI (Netscape Plugin) style plugin, which is used by most (if not all) plugin-supporting open browsers, including: Apple Internet Plugins on Mac (Firefox, Safari, probably others); Firefox (and all other gecko-based browsers), Opera, Safari, and Chrome on windows, and at least firefox on linux.  I haven&#8217;t yet implemented a plugin on linux, but most of the same principles should apply.</p>
<p><span id="more-42"></span>Because of the minor differences between platforms, I will first cover the architecture as it is used in Windows, and then in a later post I will cover the differences between windows and other platforms, such as Mac and Linux.</p>
<h3>Plugin API vs Scripting API</h3>
<p>When I first began developing browser plugins, I failed to understand the difference between the scripting API and the plugin API.  They are closely related, of course, but they serve different purposes.</p>
<p>The <em>Scripting API</em> is used to provide methods callable from javascript, while the <em>Browser API</em> provides the interface for hosting the plugin itself in the browser.</p>
<h4>NPAPI</h4>
<p>You can find the Mozilla documentation for plugins here:</p>
<p><a title="Gecko Plugin API Reference" href="https://developer.mozilla.org/en/Gecko_Plugin_API_Reference" target="_blank">https://developer.mozilla.org/en/Gecko_Plugin_API_Reference</a></p>
<p>For history of the NPAPI (Netscape Plugin API), see the <a title="NPAPI on Wikipedia" href="http://en.wikipedia.org/wiki/NPAPI" target="_blank">Wikipedia page: http://en.wikipedia.org/wiki/NPAPI</a></p>
<h2>What makes up an NPAPI browser plugin?</h2>
<p>A NPAPI browser plugin is, at it&#8217;s core, simply a DLL with a few specific entry points.  Each of these entry points is only called once by the browser for all instances of your plugin on a given page.  They are listed here in the order they should be called:</p>
<ul>
<li><a title="Gecko API reference" href="https://developer.mozilla.org/Talk:En/Gecko_Plugin_API_Reference/Plug-in_Side_Plug-in_API">NP_GetEntryPoints</a> &#8211; Called immediately after the plugin is loaded and is used by the browser (no longer just netscape) to get pointers to all of the API functions that the browser might need to call.</li>
<li><a title="Gecko NPAPI reference: NP_Initialize" href="https://developer.mozilla.org/En/NP_Initialize">NP_Initialize</a> &#8211; Provides global initialization of your plugin.</li>
<li><a title="Gecko NPAPI reference: NP_Shutdown" href="https://developer.mozilla.org/En/NP_Shutdown" target="_blank">NP_Shutdown</a> &#8211; Provides global deinitialization of your plug-in.</li>
</ul>
<p>It is important to note that since these entrypoints are specific to NPAPI, there is no reason you can&#8217;t have a NPAPI plugin inside a DLL that also provides other services (like, for example, an ActiveX plugin).</p>
<p>Since these three entrypoints provide the core of the NPAPI architecture, it is worth our time to look at them a little more closely.</p>
<h3>NP_GetEntryPoints</h3>
<div class="wp_syntax">
<div class="code">
<pre class="cpp" style="font-family:monospace;">NPError WINAPI NP_GetEntryPoints<span style="color: #008000;">&#40;</span>NPPluginFuncs<span style="color: #000040;">*</span> pFuncs<span style="color: #008000;">&#41;</span></pre>
</div>
</div>
<p>This is undoubtedly the most important of the three to understand.  Because of this, it shocks me that the only actual useful documentation I have found for this method so far is found in <a title="Web Programming Unleashed" href="http://www.webbasedprogramming.com/Web-Programming-Unleashed/ch32.htm" target="_blank">an old, but still mostly accurate web-book</a> written who-knows-when by Zan Oliphant.</p>
<p>While not as straightforward as the other two entrypoint functions, NP_GetEntryPoints is nonetheless relatively straightforward.  As you can see from the above function prototype, NP_GetEntryPoints takes a pointer to the NPPluginFuncs structure:</p>
<div class="wp_syntax">
<div class="code">
<pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">typedef</span> <span style="color: #0000ff;">struct</span> _NPPluginFuncs <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">uint16</span> size<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">uint16</span> version<span style="color: #008080;">;</span>
    NPP_NewUPP newp<span style="color: #008080;">;</span>
    NPP_DestroyUPP destroy<span style="color: #008080;">;</span>
    NPP_SetWindowUPP setwindow<span style="color: #008080;">;</span>
    NPP_NewStreamUPP newstream<span style="color: #008080;">;</span>
    NPP_DestroyStreamUPP destroystream<span style="color: #008080;">;</span>
    NPP_StreamAsFileUPP asfile<span style="color: #008080;">;</span>
    NPP_WriteReadyUPP writeready<span style="color: #008080;">;</span>
    NPP_WriteUPP write<span style="color: #008080;">;</span>
    NPP_PrintUPP print<span style="color: #008080;">;</span>
    NPP_HandleEventUPP event<span style="color: #008080;">;</span>
    NPP_URLNotifyUPP urlnotify<span style="color: #008080;">;</span>
    JRIGlobalRef javaClass<span style="color: #008080;">;</span>
    NPP_GetValueUPP getvalue<span style="color: #008080;">;</span>
    NPP_SetValueUPP setvalue<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span> NPPluginFuncs<span style="color: #008080;">;</span></pre>
</div>
</div>
<p>UPP in each of these type names stands for &#8220;Universal Proc Pointer&#8221;, which is essentially just a function pointer that the Gecko SDK uses in conjunction with a CallUniversalProc macro for all of its function pointer needs.  For more information, grep the Gecko SDK.</p>
<p>These function pointers basically tell the browser how to interact with your plugin.  Notice the naming convention here: NPP_* for all plugin functions.  There are also NPN_* functions that we will see later, and these are functions that the plugin can call on the browser.  They will be given to us in the NP_Initialize call.</p>
<p>So, the primary purpose of the NP_GetEntryPoints function is to give the browser pointers to all of the functions that it needs to call when creating or interacting with your plugin.</p>
<p>Here is a quick overview of the NPP plugin functions that your plugin must provide (and give addresses to when NP_GetEntryPoints is called).  This table is copied from <a title="A Quick Look at the Plug-In API Methods (Zan Oliphant)" href="http://docs.rinet.ru/Plugi/ch8.htm#AQuickLookatthePlugInAPIMethods">Zan Oliphant&#8217;s book</a> and updated to reflect the current practices and Gecko SDK 1.8:</p>
<table style="height: 304px;" border="1" width="539" bordercolor="#000000">
<tbody>
<tr>
<td><em>API Name</em></td>
<td width="322"><em>Description</em></td>
</tr>
<tr>
<td width="186"><a title="NPP_New API doc" href="https://developer.mozilla.org/En/NPP_New" target="_blank"><tt><span style="font-family: Courier;">NPP_New</span></tt></a></td>
<td width="322">Creates a new instance of a plug-in.</td>
</tr>
<tr>
<td width="186"><a title="NPP_Destroy API doc" href="https://developer.mozilla.org/En/NPP_Destroy" target="_blank"><tt><span style="font-family: Courier;">NPP_Destroy</span></tt></a></td>
<td width="322">Deletes an instance of a plug-in.</td>
</tr>
<tr>
<td width="186"><a title="NPP_SetWindow API doc" href="https://developer.mozilla.org/En/NPP_SetWindow" target="_blank"><tt><span style="font-family: Courier;">NPP_SetWindow</span></tt></a></td>
<td width="322">Tells the plug-in when a window is created, moved, sized, or destroyed.</td>
</tr>
<tr>
<td width="186"><a title="NPP_NewStream API doc" href="https://developer.mozilla.org/En/NPP_NewStream" target="_blank"><tt><span style="font-family: Courier;">NPP_NewStream</span></tt></a></td>
<td width="322">Notifies a plug-in instance of a new data stream.</td>
</tr>
<tr>
<td width="186"><a title="NPP_DestroyStream API Doc" href="https://developer.mozilla.org/En/NPP_DestroyStream" target="_blank"><tt><span style="font-family: Courier;">NPP_DestroyStream</span></tt></a></td>
<td width="322">Tells the plug-in that a stream is about to be closed or destroyed.</td>
</tr>
<tr>
<td width="186"><a title="NPP_StreamAsFile API Doc" href="https://developer.mozilla.org/En/NPP_StreamAsFile" target="_blank"><tt><span style="font-family: Courier;">NPP_StreamAsFile</span></tt></a></td>
<td width="322">Provides a local file name for the data from a stream.</td>
</tr>
<tr>
<td width="186"><a title="NPP_WriteReady API doc" href="https://developer.mozilla.org/En/NPP_WriteReady" target="_blank"><tt><span style="font-family: Courier;">NPP_WriteReady</span></tt></a></td>
<td width="322">Determines whether a plug-in is ready for data (and the maximum number of bytes it is prepared to accept).</td>
</tr>
<tr>
<td width="186"><a title="NPP_Write API doc" href="https://developer.mozilla.org/En/NPP_Write" target="_blank"><tt><span style="font-family: Courier;">NPP_Write</span></tt></a></td>
<td width="322">Called to write/deliver data to a plug-in.  The docs note that this might be better named &#8220;NPP_DataArrived&#8221;.</td>
</tr>
<tr>
<td width="186"><a title="NPP_Print API doc" href="https://developer.mozilla.org/En/NPP_Print" target="_blank"><tt><span style="font-family: Courier;">NPP_Print</span></tt></a></td>
<td width="322">Requests a platform-specific print operation for an embedded or full-screen plug-in.</td>
</tr>
<tr>
<td width="186"><a title="NPP_HandleEvent" href="https://developer.mozilla.org/En/NPP_HandleEvent" target="_blank"><tt><span style="font-family: Courier;">NPP_HandleEvent</span></tt></a></td>
<td width="322">Event handler, currently only used by Windowed plugins on Mac OS; windowless plugins on all platforms use this.</td>
</tr>
<tr>
<td width="186"><a title="NPP_URLNotify API doc" href="https://developer.mozilla.org/En/NPP_URLNotify" target="_blank"><tt><span style="font-family: Courier;">NPP_URLNotify</span></tt></a></td>
<td width="322">Notifies the completion of a URL request.</td>
</tr>
<tr>
<td width="186"><tt><span style="font-family: Courier;">NPP_GetJavaClass</span></tt></td>
<td width="322">Deprecated / No longer used. Set to NULL</td>
</tr>
<tr>
<td width="186"><a title="NPP_GetValue API doc" href="https://developer.mozilla.org/En/NPP_GetValue" target="_blank"><tt><span style="font-family: Courier;">NPP_GetValue</span></tt></a></td>
<td width="322">Called to query the plugin for information (also used to get an instance of a NPObject/Scriptable Plugin)</td>
</tr>
<tr>
<td width="186"><a title="NPP_SetValue API doc" href="https://developer.mozilla.org/En/NPP_SetValue" target="_blank"><tt><span style="font-family: Courier;">NPP_SetValue</span></tt></a></td>
<td width="322">This call is used to inform plugins of variable information controlled by the browser.</td>
</tr>
</tbody>
</table>
<p>We will talk more about the specifics of how each of these functions works later.</p>
<h3>NP_Initialize</h3>
<div class="wp_syntax">
<div class="code">
<pre class="cpp" style="font-family:monospace;">NPError WINAPI NP_Initialize<span style="color: #008000;">&#40;</span>NPNetscapeFuncs <span style="color: #000040;">*</span>aNPNFuncs<span style="color: #008000;">&#41;</span> <span style="color: #666666;">// Windows</span>
<span style="color: #666666;">// -or-</span>
NPError NP_Initialize<span style="color: #008000;">&#40;</span>NPNetscapeFuncs <span style="color: #000040;">*</span>aNPNFuncs, NPPluginFuncs <span style="color: #000040;">*</span>aNPPFuncs<span style="color: #008000;">&#41;</span> <span style="color: #666666;">// Linux</span></pre>
</div>
</div>
<p>As noted in the <a title="NP_Initialize API doc" href="https://developer.mozilla.org/En/NP_Initialize" target="_blank">documentation</a>, NP_Initialize provides global initialization for a plug-in.  The API reference is a little confusing in that it claims that NP_Initialize is actually the first function called by the browser.  The reason for this is that on linux, there aparently is no NP_GetEntryPoints call; instead, the NPPluginFuncs struct is passed into the NP_Initialize function to be filled out.</p>
<p>Since this isn&#8217;t confusing enough, on Mac they have replaced both of these functions with a single &#8220;main&#8221; function that not only gets passed both function pointer structures (one with the browser functions and one to be filled out with plugin functions) but also is given a shutdown function pointer to be filled out with the address to the NP_Shutdown function.</p>
<p>Because of these discrepancies, I recommend that you write a separate function for filling out the NPPluginFuncs structure so that it can be called from any of the various init functions.</p>
<p>The NPNetscapeFuncs structure that is passed in is the complement to the NPPluginFuncs structure that we have discussed previously.  As might be guessed from the name, the NPNetscapeFuncs structure contains pointers to browser functions that can be called by the plugin.  There are a lot more of these, and we will discuss more about how to use them next time.</p>
<p>For now, take a look at the structure to get a general idea of what is there.  I&#8217;ve added comments on some of the more common function calls.</p>
<div class="wp_syntax">
<div class="code">
<pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">typedef</span> <span style="color: #0000ff;">struct</span> _NPNetscapeFuncs <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">uint16</span> size<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">uint16</span> version<span style="color: #008080;">;</span> <span style="color: #666666;">// Newer versions may have additional fields added to the end</span>
    NPN_GetURLUPP geturl<span style="color: #008080;">;</span> <span style="color: #666666;">// Make a GET request for a URL either to the window or another stream</span>
    NPN_PostURLUPP posturl<span style="color: #008080;">;</span> <span style="color: #666666;">// Make a POST request for a URL either to the window or another stream</span>
    NPN_RequestReadUPP requestread<span style="color: #008080;">;</span>
    NPN_NewStreamUPP newstream<span style="color: #008080;">;</span>
    NPN_WriteUPP write<span style="color: #008080;">;</span>
    NPN_DestroyStreamUPP destroystream<span style="color: #008080;">;</span>
    NPN_StatusUPP status<span style="color: #008080;">;</span>
    NPN_UserAgentUPP uagent<span style="color: #008080;">;</span>
    NPN_MemAllocUPP memalloc<span style="color: #008080;">;</span> <span style="color: #666666;">// Allocates memory from the browser's memory space</span>
    NPN_MemFreeUPP memfree<span style="color: #008080;">;</span> <span style="color: #666666;">// Frees memory from the browser's memory space</span>
    NPN_MemFlushUPP memflush<span style="color: #008080;">;</span>
    NPN_ReloadPluginsUPP reloadplugins<span style="color: #008080;">;</span>
    NPN_GetJavaEnvUPP getJavaEnv<span style="color: #008080;">;</span>
    NPN_GetJavaPeerUPP getJavaPeer<span style="color: #008080;">;</span>
    NPN_GetURLNotifyUPP geturlnotify<span style="color: #008080;">;</span> <span style="color: #666666;">// Async call to get a URL</span>
    NPN_PostURLNotifyUPP posturlnotify<span style="color: #008080;">;</span> <span style="color: #666666;">// Async call to post a URL</span>
    NPN_GetValueUPP getvalue<span style="color: #008080;">;</span> <span style="color: #666666;">// Get information from the browser</span>
    NPN_SetValueUPP setvalue<span style="color: #008080;">;</span> <span style="color: #666666;">// Set information about the plugin that the browser controls</span>
    NPN_InvalidateRectUPP invalidaterect<span style="color: #008080;">;</span>
    NPN_InvalidateRegionUPP invalidateregion<span style="color: #008080;">;</span>
    NPN_ForceRedrawUPP forceredraw<span style="color: #008080;">;</span>
    NPN_GetStringIdentifierUPP getstringidentifier<span style="color: #008080;">;</span> <span style="color: #666666;">// Get a NPIdentifier for a given string</span>
    NPN_GetStringIdentifiersUPP getstringidentifiers<span style="color: #008080;">;</span>
    NPN_GetIntIdentifierUPP getintidentifier<span style="color: #008080;">;</span>
    NPN_IdentifierIsStringUPP identifierisstring<span style="color: #008080;">;</span>
    NPN_UTF8FromIdentifierUPP utf8fromidentifier<span style="color: #008080;">;</span> <span style="color: #666666;">// Get a string from a NPIdentifier</span>
    NPN_IntFromIdentifierUPP intfromidentifier<span style="color: #008080;">;</span>
    NPN_CreateObjectUPP createobject<span style="color: #008080;">;</span> <span style="color: #666666;">// Create an instance of a NPObject</span>
    NPN_RetainObjectUPP retainobject<span style="color: #008080;">;</span> <span style="color: #666666;">// Increment the reference count of a NPObject</span>
    NPN_ReleaseObjectUPP releaseobject<span style="color: #008080;">;</span> <span style="color: #666666;">// Decrement the reference count of a NPObject</span>
    NPN_InvokeUPP invoke<span style="color: #008080;">;</span> <span style="color: #666666;">// Invoke a method on a NPObject</span>
    NPN_InvokeDefaultUPP invokeDefault<span style="color: #008080;">;</span> <span style="color: #666666;">// Invoke the default method on a NPObject</span>
    NPN_EvaluateUPP evaluate<span style="color: #008080;">;</span> <span style="color: #666666;">// Evaluate javascript in the scope of a NPObject</span>
    NPN_GetPropertyUPP getproperty<span style="color: #008080;">;</span> <span style="color: #666666;">// Get a property on a NPObject</span>
    NPN_SetPropertyUPP setproperty<span style="color: #008080;">;</span> <span style="color: #666666;">// Set a property on a NPObject</span>
    NPN_RemovePropertyUPP removeproperty<span style="color: #008080;">;</span> <span style="color: #666666;">// Remove a property from a NPObject</span>
    NPN_HasPropertyUPP hasproperty<span style="color: #008080;">;</span> <span style="color: #666666;">// Returns true if the given NPObject has the given property</span>
    NPN_HasMethodUPP hasmethod<span style="color: #008080;">;</span> <span style="color: #666666;">// Returns true if the given NPObject has the given Method</span>
    NPN_ReleaseVariantValueUPP releasevariantvalue<span style="color: #008080;">;</span> <span style="color: #666666;">// Release a MNVariant (free memory)</span>
    NPN_SetExceptionUPP setexception<span style="color: #008080;">;</span>
    NPN_PushPopupsEnabledStateUPP pushpopupsenabledstate<span style="color: #008080;">;</span>
    NPN_PopPopupsEnabledStateUPP poppopupsenabledstate<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span> NPNetscapeFuncs<span style="color: #008080;">;</span></pre>
</div>
</div>
<p>In addition to saving the function pointers given so that browser calls can be made, any memory that is to be shared by all instances of your browser plugin should be initialized here.</p>
<h3>NP_Shutdown</h3>
<p>This is the simplest of the three entrypoints.  Free any shared memory and release any shared resources.  This is called when the browser has already destroyed all instances of your plugin (by calling <a title="NPP_Destroy API doc" href="https://developer.mozilla.org/En/NPP_Destroy" target="_blank">NPP_Destroy</a>) and does not expect to create any more in the near future.</p>
<h2>Next Time</h2>
<p>Next time we will go into greater detail on implementing the NPP functions and also cover some of the most commonly used NPN functions.</p>
<p><a title="Building a firefox plugin - part one" href="http://colonelpanic.net/2009/03/building-a-firefox-plugin-part-one/">Building a firefox plugin &#8211; part one</a></p>
<p><a title="Building a firefox plugin - part two" href="http://colonelpanic.net/2009/05/building-a-firefox-plugin-part-two/">Building a firefox plugin &#8211; part two</a></p>
<p><a title="Building a firefox plugin - part three" href="http://colonelpanic.net/2009/08/building-a-firefox-plugin-part-three/">Building a firefox plugin &#8211; part three</a></p>
<p><a title="Building a firefox plugin - part four" href="http://colonelpanic.net/2011/07/building-a-firefox-plugin-part-four/">Building a firefox plugin &#8211; part four</a></p>
<h2>Getting more help</h2>
<p><strong>Update May 14, 2011:</strong> Many people have been asking questions in the comments; while I don&#8217;t mind that, it would probably be more useful if you ask your question on <a href="http://forum.firebreath.org">the FireBreath forums</a>. There is a forum there for those just using NPAPI as well!</p>
]]></content:encoded>
			<wfw:commentRss>http://colonelpanic.net/2009/03/building-a-firefox-plugin-part-one/feed/</wfw:commentRss>
		<slash:comments>99</slash:comments>
		</item>
	</channel>
</rss>

