NPAPI Plugin sample for Firefox


I recently got started on a project that had a NPAPI/XPCOM component that implements a custom control to be used in a  web page to demonstrate the companies technology.  I rewrote the control to get rid of the XPCOM api which opened up the compatibility of the control to include Google chrome and other NPAPI supported browsers.  In rewriting the control I wanted to start from a clean foundation for the new pure NPAPI plugin.  I decided to write this blog entry because it is really hard to find a NPAPI code sample that is up to date, and complete enough so you can build it and continue the job at hand.  I found an old code sample from Mozilla, npruntime.  I choose this sample because it was the most similar in structure to the original plugin that I was rewriting.

I found this blog entry that covers what you need to do, but no complete source code sample is provided that provides a complete sample that you can compile and run.  Despite that deficiency the blog is really quite good at explaining the basic concepts behind the NPAPI run time and I highly recommend that you read it.  building-a-Firefox-plugin.  Once you understand the concepts behind NPAPI and the requirements for the plugin, we can get started building the control.

Prerequisites:

the NPRuntime sample

np_entry.cpp

A NPAPI plugin exposes 3 functions from the component that used by the browser to load the plugin.

  • NP_Initialize() – When a plugin is loaded by the browser, NP_Initialize() is called by the browser.  A pointer to an array of function pointers is passed to the plugin.  This array of function pointers contain all of the functions that your plugin can call to interact with the browser and the loaded webpage.
  • NP_GetEntryPoints() – Like NP_Initialize(), this function initializes a table of function pointers that the browser uses to call into your plugin.  These functions are used to identify the exposed properties and methods used by the script in the loaded page.
  • NP_Shutdown() – This function is called when a browser unloads a plugin.  This is your last chance to clean up your resources before the plugin is shutdown.

npn_gate.cpp

This source file implements the plugins implementation of the NPAPI entrypoints exposed from the browser.  This file contains helper functions that wrap the function pointers passed in by the browser for your use.  There is no hard requirement to use these functions, but calling these methods is recommended becasue they do some error checking and parameter validation that helps to build robust plugin code with out relying on exception processing.

npp_gate.cpp

This source file contains the implmentation of the NPAPI entrypoints exposed by the plugin.  NPAPI defines a set of functions that each plugin needs to implment.  This is the main entry point to the scriptable plugin.  From this point in the source code you create you main plugin object that in turn manages the scriptable object passed back to the calling browser.  The Npruntime sample code leaves many of these functions empty with no implementation.  Enough code has been implemented within this source file to manage the main plugin object along with the creation of objects, windows and event handlers.

plugin.cpp/h

The Plugin.* source files contain the class definitions for the plugin object at the native OS layer through the scriptable object code that is exposed within the DOM.  These sources contain several classes used to construct the scriptable JavaScript object that you use within your script.

NPIdentifier’s description and purpose

A NPIdentifier is a unique ID assigned by the browser and should be unique for the life of the plugin instance.  These identifiers are used for everything that is represented in the DOM.  In otherwords, you can request specific DOM elements by type or “id” attribute.  NPIdentifiers are also used to declare methods and properties exposed by the scriptable object.  NPIdentifiers can also be used to access the DOM by requesting an ID for a known HTML tag or by using the id or name attribute of the HTML tag you want to examine.  The lifetime of these identifiers is open to debate and  you should expect to encounter different lifetime behavior on different browsers.

CPlugin

The CPlugin class is the parent class in the NPAPI plugin.  The first step in creating a new plugin instance is to create a new instance of the CPlugin class.  this class instance manages the scriptable interface between the browser and the natvie code implmented within the plugin.  This class also contains any native platform support for the plugin.

class CPlugin
{
private:
  // this is the NPAPI instance of the plugin loaded in the browser
  NPP m_pNPInstance;

#ifdef XP_WIN
  HWND m_hWnd;
#endif

  // the main window for the browser
  NPWindow * m_Window;

  // a stream object for sending data streams to and from scipt running in the browser.
  NPStream * m_pNPStream;
  NPBool m_bInitialized;

  // a pointer to the scriptable object exposed via NPAPI to the browser.
  NPObject *m_pScriptableObject;

public:
  char m_String[128];

public:
  CPlugin(NPP pNPInstance);
  ~CPlugin();

  NPBool init(NPWindow* pNPWindow);
  void shut();
  NPBool isInitialized();

  int16 handleEvent(void* event);

  void showVersion();
  void clear();
  void getVersion(char* *aVersion);

  NPObject *GetScriptableObject();
};

ScriptablePluginObjectBase

The ScriptablePluginObjectBase class acts as the proxy between your plugin implementation and the calling browser.  The class has static and non-static methods.  The scriptable classes derived off this class implement the virtual functions while the static functions call into the scriptable plugin class passed into the method by the caller.

class ScriptablePluginObjectBase : public NPObject
{
public:
  ScriptablePluginObjectBase(NPP npp)
    : mNpp(npp)
  {
  }

  virtual ~ScriptablePluginObjectBase()
  {
  }

  // Virtual NPObject hooks called through this base class. Override
  // as you see fit.
  virtual void Invalidate();
  virtual bool HasMethod(NPIdentifier name);
  virtual bool Invoke(NPIdentifier name, const NPVariant *args,
                      uint32_t argCount, NPVariant *result);
  virtual bool InvokeDefault(const NPVariant *args, uint32_t argCount,
                             NPVariant *result);
  virtual bool HasProperty(NPIdentifier name);
  virtual bool GetProperty(NPIdentifier name, NPVariant *result);
  virtual bool SetProperty(NPIdentifier name, const NPVariant *value);
  virtual bool RemoveProperty(NPIdentifier name);
  virtual bool Enumerate(NPIdentifier **identifier, uint32_t *count);
  virtual bool Construct(const NPVariant *args, uint32_t argCount,
                         NPVariant *result);

public:
  static void _Deallocate(NPObject *npobj);
  static void _Invalidate(NPObject *npobj);
  static bool _HasMethod(NPObject *npobj, NPIdentifier name);
  static bool _Invoke(NPObject *npobj, NPIdentifier name,
                      const NPVariant *args, uint32_t argCount,
                      NPVariant *result);
  static bool _InvokeDefault(NPObject *npobj, const NPVariant *args,
                             uint32_t argCount, NPVariant *result);
  static bool _HasProperty(NPObject * npobj, NPIdentifier name);
  static bool _GetProperty(NPObject *npobj, NPIdentifier name,
                           NPVariant *result);
  static bool _SetProperty(NPObject *npobj, NPIdentifier name,
                           const NPVariant *value);
  static bool _RemoveProperty(NPObject *npobj, NPIdentifier name);
  static bool _Enumerate(NPObject *npobj, NPIdentifier **identifier,
                         uint32_t *count);
  static bool _Construct(NPObject *npobj, const NPVariant *args,
                         uint32_t argCount, NPVariant *result);

protected:
  NPP mNpp;
};

ConstructablePluginObject

The npruntime sample provides several samples embedded within the source code.  One part of the sample involves returning an object as a property of the plugin.  The object returned to the script has no implementation, so you can’t do much with it without playing around with the code.  To get this returned object functional within JavaScript, you need to implement the rest of the ScriptablePlubinObjectBase interface to define properties and methods for the object as we do with the ScriptablePluginObject class.

class ConstructablePluginObject : public ScriptablePluginObjectBase
{
public:
  ConstructablePluginObject(NPP npp)
    : ScriptablePluginObjectBase(npp)
  {
  }

  virtual bool Construct(const NPVariant *args, uint32_t argCount,
                         NPVariant *result);
};

ScriptablePluginObject

The scriptable plugin object class contains the implementation of the NPAPI plugin.  A NPAPI plugin can contain tain properties and methods, each identified by a NPIdentifier assigned by the browser.  Each time a piece of script running in the browser accesses a property or method of a plugin, the browser will query the plugin to see if it has this property or method.  If the plugin contains the method, Invoke() is called.  If the plugin contains the property, GetProperty() or SetProperty() is called depending on the operation in the script.  If the scriptable object represents a method, such as a callback or constructor call, then InvokeDefault() is called.

class ScriptablePluginObject : public ScriptablePluginObjectBase
{
public:
  ScriptablePluginObject(NPP npp)
    : ScriptablePluginObjectBase(npp)
  {
  }

  virtual bool HasMethod(NPIdentifier name);
  virtual bool HasProperty(NPIdentifier name);
  virtual bool GetProperty(NPIdentifier name, NPVariant *result);
  virtual bool Invoke(NPIdentifier name, const NPVariant *args,
                      uint32_t argCount, NPVariant *result);
  virtual bool InvokeDefault(const NPVariant *args, uint32_t argCount,
                             NPVariant *result);
};

The implementation of your plugin will be contained with the ScriptablePluginObject or a similar class.  Within this class we use NPIdentifiers to retrieve unique IDs for each of the tag elements we want to access in the DOM.

// Declare NPIdentifiers to be used as id tags for the elements we need to access.
static NPIdentifier sFoo_id;             // the sample method
static NPIdentifier sBar_id;             // a simple property
static NPIdentifier sPluginType_id;      // an object property.
static NPIdentifier sDocument_id;        // the id for the DOM object
static NPIdentifier sBody_id;            // the id of the tag
static NPIdentifier sCreateElement_id;   // An id used to create the new div tag elements.
static NPIdentifier sCreateTextNode_id;  // The id for the text in the new tag
static NPIdentifier sAppendChild_id;     // the id to identify the insert location of the new div tag.
static NPObject *sWindowObj;             // the main browser window object.

ScriptablePluginObject::ScriptablePluginObject(NPP npp) : ScriptablePluginObjectBase(npp)
{
    // Get the instance of the browser window object
    NPN_GetValue(npp, NPNVWindowNPObject, &sWindowObj);

    // initialize a temporary npid.
    NPIdentifier n = NPN_GetStringIdentifier("foof");

    // setup the properties for the plugin.  These id's are unique to the plugin and assigned
    // by the browser. npids can be eiter properties or methods.
    sFoo_id = NPN_GetStringIdentifier("foo");
    sBar_id = NPN_GetStringIdentifier("bar");

    // define some npids for HTML elements that we commonly use.
    sDocument_id = NPN_GetStringIdentifier("document");
    sBody_id = NPN_GetStringIdentifier("body");

    // these are the element npid used to create new elements to be appended to the dom
    sCreateElement_id = NPN_GetStringIdentifier("createElement");
    sCreateTextNode_id = NPN_GetStringIdentifier("createTextNode");

    // used to append to the loaded dom
    sAppendChild_id = NPN_GetStringIdentifier("appendChild");

    // required: used in the construction of the plugin
    sPluginType_id = NPN_GetStringIdentifier("PluginType");

}

Each time a plugin is accessed by the browser, HasMethod() and HasProperty() are invoked to determine if the method or property are supported by the plugin.  Within your plugin scriptable code you need to implement each of these methods in order for scriptable access to your plugin.  Using the NPIdentifiers you created earlier, you compare the NPIdentifer sent into your assigned identifers.  If there is a match, you return true, otherwise return false to indicate to the browser that you do not support the identifier sent into the methods.

bool ScriptablePluginObject::HasMethod(NPIdentifier name)
{
    return name == sFoo_id;
}

bool ScriptablePluginObject::HasProperty(NPIdentifier name)
{
    return (name == sBar_id || name == sPluginType_id);
}

bool ScriptablePluginObject::GetProperty(NPIdentifier name, NPVariant *result)
{
    VOID_TO_NPVARIANT(*result);

    if (name == sBar_id)
    {
        static int a = 17;

        INT32_TO_NPVARIANT(a, *result);

        a += 5;
        return true;
    }

    if (name == sPluginType_id) {
        NPObject *myobj =  NPN_CreateObject(mNpp, GET_NPOBJECT_CLASS(ConstructablePluginObject));
        if (!myobj) {
            return false;
        }

        OBJECT_TO_NPVARIANT(myobj, *result);

        return true;
    }

    return true;
}

The only part that is notable about GetProperty() and SetProperty() in this sample is how you implement a read only variable. By omitting the sPluginType_id identifier, we can control the access rights to the property. In this case, we setup the sPluginType_id as a read only variable.

bool ScriptablePluginObject::SetProperty(NPIdentifier name, const NPVariant *value)
{
    if (name == sBar_id) {
        printf ("bar set\n");
        return true;
    }

    return false;
}

If the browser calls a method on your scriptable object, then internally the browser invokes the function through a call to Invoke().  When calling a methods it will be nessesary to extract all the command line arguments into their proper data types. Unlike XPCOM, the programmer has no control over how arguments are converted and passed to the method. This forces the developer to query to the type of argument wrapped in the NPVariant before extracting the real values.

bool ScriptablePluginObject::Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result)
{
    if (name == sFoo_id) {
        printf ("foo called!\n");

        // get the main document from the window object.
        NPVariant docv;
        NPN_GetProperty(mNpp, sWindowObj, sDocument_id, &docv);

        // convert the variant into a NPObject
        NPObject *doc = NPVARIANT_TO_OBJECT(docv);

        // insert a DIV tag into the document
        NPVariant strv;
        // create the element.
        NPUTF8 *putf8Str = (NPUTF8 *)NPN_MemAlloc(strlen("div")+1);
        strncpy(putf8Str, "div", strlen("div"));

        STRINGZ_TO_NPVARIANT(putf8Str, strv);

        // Create the div tag object that will be inserted into the DOM.
        NPVariant divv;
        NPN_Invoke(mNpp, doc, sCreateElement_id, &strv, 1, &divv);

        // now put some text into the div tag
        // first create the string.
        putf8Str = (NPUTF8 *)NPN_MemAlloc(strlen("I'm created by a plugin!")+1);
        strncpy(putf8Str, "I'm created by a plugin!", strlen("I'm created by a plugin!"));
        STRINGZ_TO_NPVARIANT(putf8Str, strv);

        // now insert it into the DIV tag we just added.
        NPVariant textv;
        NPN_Invoke(mNpp, doc, sCreateTextNode_id, &strv, 1, &textv);

        NPVariant v;
        NPN_Invoke(mNpp, NPVARIANT_TO_OBJECT(divv), sAppendChild_id, &textv, 1, &v);
        NPN_ReleaseVariantValue(&v);
        NPN_ReleaseVariantValue(&textv);

        // now insert the DIV tag into the body of the loaded HTML document.
        NPVariant bodyv;

        // get the body element as a NPObject
        NPN_GetProperty(mNpp, doc, sBody_id, &bodyv);

        // Append the new div tag into the DOM
        NPN_Invoke(mNpp, NPVARIANT_TO_OBJECT(bodyv), sAppendChild_id, &divv, 1, &v);
        NPN_ReleaseVariantValue(&v);
        NPN_ReleaseVariantValue(&divv);
        NPN_ReleaseVariantValue(&bodyv);

        NPN_ReleaseVariantValue(&docv);

        // allocate a return value as a string.
        NPUTF8 *putf8RetStr = (NPUTF8 *)NPN_MemAlloc(strlen("foo return val")+1);
        strncpy(putf8RetStr, "foo return val", strlen("foo return val"));
        STRINGZ_TO_NPVARIANT(putf8RetStr, *result);
        return PR_TRUE;
    }

    return PR_FALSE;
}

The InvokeDefault() method is badly named.  This method is invoked if the object represented by the NPObject is a function.  This allows you to expose a method to JavaScript via NPAPI.  By calling InvokeDefault() on any NPObject will either invoke the object as a function or as the class constructor for the object.

bool ScriptablePluginObject::InvokeDefault(const NPVariant *args, uint32_t argCount, NPVariant *result)
{
    printf ("ScriptablePluginObject default method called!\n");

    // this is crashing because we are not using the correct memory heap.
    // Any string or object allocated for a return value MUST be allocated off
    // the browser's heap.
    //STRINGZ_TO_NPVARIANT(strdup("default method return val"), *result);

    NPUTF8 *putf8RetStr = (NPUTF8 *)NPN_MemAlloc(strlen("default method return val")+1);
    strncpy(putf8RetStr, "default method return val", strlen("default method return val"));
    STRINGZ_TO_NPVARIANT(putf8RetStr, *result);

    return PR_TRUE;
}

other files

  • nprt.def - a standard windows definition file used to define the exported functions from the DLL.
  • nprt.rc – the windows resource file for this sample.
  • resource.h – the windows resource file for this sample.
  • test.html – a test page for the sample.
  • makefile.in – the Mozilla makefile for the project if you build it within the Mozilla projecct.

building the project

On the Mozilla developer site you can find references to a very old sample npruntime which will serve as a basis for this code sample.  You can find the NPRuntime code here, and the documentation to setup a visual studio project is here.  Follow these steps exactly and you will have a project ready to build.

If you try to build the project at this point, it will fail with errors.  As the Mozilla and Gecko SDK’s have evolved, this sample has not been kept up to date which is disapointing.

To fix the problems you will need to do the following:

  • change integer types (int16, int32, uint16, uint32) to use the new modern prototypes (int16_t, int32_t, uint16_t, and uint32_t).  As Gecko eveolved, the data types changed.  The sample code was never updated and won’t compile without these changes.
  • change headers.  The old header “npupp.h” has been replaced by “npfunctions.h”.  Mozilla – Bug 455458 covers the change to these headers.  This was done back in 2008 with Gecko 2.0 (FireFox 4).
  • fix property setter method.  There is a bug with the sample code when you process a property and set a value.
  • debugging with Firefox:  attach the debugger to the app “plugin_container.exe” and this will let you debug your code within visual studio.  Be careful!  if you take too long, firefox will think the plugin crashed and kill the app and end your session.
  • Debugging with Chrome:  This is alot like debugging with IE.  Chrome lauches a new Chrome process to contain the plugin, so you need to figure out which process belongs to the plugin and attach the debugger to that process.

installing the plugin

Historically, plugins have been loaded by placing the NPAPI dll into a known location on the path.  If you placed the DLL within a sub-folder called “plugins” the calling browser will load the plugin from that location.  The key is the plugins folder must be located in the same folder where the calling process was launched.  You can load this sample by creating a folder called “plugins” in the installed location for Firefox, and then it will be loaded when you re-launch the browser.  This was ok with older operating systems, but  a modern operating system should require you to install to a unique location.  For Firefox and Chrome, this requires an external installer since we have to modify the registry.

Installing a NPAPI plugin on Firefox

If you want to install a plugin to a custom folder path, we need to add some registry keys that the browser will use to locate the plugin.  For more information on how the browser finds plugins, you can read that here: How Mozilla finds plugins.

HKEY_LOCAL_MACHINE\SOFTWARE\MozillaPlugins\*\Path
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\MozillaPlugins\*\Path

If you look at the loaded plugins like QuickTime, Silverlight, and flash, all of those plugins use the registry to install the plugin location.  This allows you to place the plugin in a custom path for the browser to search when looking for plugins to load  The documentation on Mozilla is a little  out of date, for 64 bit windows, you need to use the following registry key path

In the HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\MozillaPlugins registry path, you need to create a new key that contains a specific format @<vendor>/<application name>,version=<app version number>.  Inside this key we need 4 string values

  1. Path – The absolute path to the NPAPI plugin installed location. Beware of some limitations.  With Firefox, if the control is not built with Unicode enabled, then the path cannot contain spaces in the path to the control or it will not load.  If you build the control with multi-byte character support the path variable cannot contain spaces and should conform to the obsolete 8.3 file naming standards to insure correct operation.  Chrome is not affected by this issue.
  2. ProductName – the name of the product
  3. Vendor – the company or individual who authored the control.
  4. Version – installed version number.

that’s it!  your plugin is now registered with Firefox.  Below is a sample of what the registry keys should look like.  There is a problem with this approach in that the registry key is located in the HKEY_LOCAL_MACHINE key.  This means that you will need administrative privlidges to install the plugin.  For this reason, you can’t download a plugin and you will need an external installer like NSIS to create a proper windows installer executable.

 Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\MozillaPlugins\@conedogers.com/npruntime,version=1.0.0.2] "Path"="C:\\dev\\mozilla\\npruntime\\Debug\\npruntime.dll" "ProductName"="npruntime" "Vendor"="conedogers" "Version"="1.0.0.2"

When you get to this point, you should be able to open Firefox and on the installed plugins page under tools|Add-ons – Plugins tab you should see the plugin in the list of installed plugins.  If you see the plugin listed, then you can open the test page to see the control run.

Conclusion

When you get the code running you will have everything you need to implement a modern NPAPI control.  A copy of the source code that I have used to create this blog is available for download off of gitHub.  NPAPI is an old technology that has found new life in the browser world.  It can be cumbersome and there are many runtime issues that I have run into while devloping plugins for Firefox using NPAPI.  XPCom was almost easier, but then again, I know how COM objects work in Windows, so XPCOM is easy for me to work with.

The code is released under the original Mozilla license.

Source code download via gitHub: https://github.com/chrisDwarner/npruntimeSampleCode

git: git://github.com/chrisDwarner/npruntimeSampleCode.git

About these ads

32 thoughts on “NPAPI Plugin sample for Firefox

  1. This is the perfect webpage for anyone who really wants to find out about this topic.

    You understand so much its almost tough to argue with you (not that I actually would want to…HaHa).
    You definitely put a new spin on a topic that has been written
    about for a long time. Wonderful stuff, just great!

  2. Crisw52,

    All NPAPI sample plugin i came across just did not work on windows. Could you or some one else provide a compiled version of your plugin to be able to test it. I have VS 2003 only.

    I have compiled several plugins similar to yours, it gets loaded in by the browser but NP_GetEntryPoints is never called. It apears in about:plugins as it should. CRT runtime is statically linked, no external dependencies, so no runtime errors.

    I would like to know if it really works…

    There are good info here if this plugin works.

    • Alex,

      My sample uses the latest windows prerequisites from Mozilla. Mozilla build requirements for windows Visual Studio 2003 is no longer supported. You need a minimum version of Visual Studio 2005 or above to build this sample.

      If you want to try and build this sample with Visual studio 2003, you can try to build using the old mozilla build system, but I doubt that the plugin will load in a modern Firefox release.

      you can find information on how to build with the older Mozilla build system here: Mozilla build prerequisites using cygwin

      • chrisw52,
        It does not explain why ff 17.00 is not able to run plugins for 3.x and older on my jurassic dell with xp SP2.
        Anyway, can you provide the binaries to test it on my ff 17.00?

      • Alex, if you are running XP sp2, I would seriously consider upgrading to a new machine if that is possible. If not, please at least upgrade to XP SP3. That has some important security fixes as in, it introduced a small measure of security to XP which it never had before. Windows XP SP3 download

      • chrisw52,

        Thank you, but you did not answer the question, would you provide 32 bit binary to confirm your sample works?

        I cannot apply SP3, it breaks everything else. That is why i am running FF 17.00.
        The new platform is for the BUILD, and i just want to have a short path to check if it works before i try compiling this.

      • I Cannot provide a win32 binary that will work on that windows machine (win XP SP2). I do not have a development environment setup to build those older plugins.

        There were significant changes to Gecko between 1.9.2 release (Firefox 3.x) and Gecko 2.0 (Firefox 4) that make it very difficult to support the older Firefox (pre-Gecko 2). Support for XPCOM was dropped, extensions were moved out of process from the main browser thread for stability and improved security, the JavaScript install scripts were replaced with an XPI install manifest, so a plugin written for FF3 will not install on FF17.

        If you want to fully support FF3, you need a special project that includes a Mozilla build system with Gecko 1.9.2 installed. You will also need to target the source code to handle the older Gecko SDK. String and memory management routines and strategies have changed between Gecko 1.9.2 and Gecko 2.0.

        There were enough changes to the Plugin API for me to drop support for Gecko 1.9.2. For the scope of the article and the NPAPI plugin development that I do professionally, it was not worth the effort to support FF3.x browsers.

      • chrisw52,

        Perhaps i have expressed myself wrong, i have asked the sample in binary to test it on FF 17.00 on my Win XP, not binary compatible with older versions, no XPCOM.
        Just rebuild your sample and target it to 32 bit, would you be kind to do it?

        Your sample can prove i am doing something wrong, failed to register it correctly or missed something else.

        Thank you anyway.

      • Ah, ok..

        Make sure the registry settings are correct. this is the recommended method for detecting plugins according to Mozilla. You need to make sure that where you install the sample, that is has no spaces in the absolute path to the installed plugin location.
        I have encountered this problem when the plugin was compiled without UNICODE enabled. However, in your case, UNICODE itself has changed a bit since win XP SP2 was released. In Windows Vista, UNICODE was revamped and modernized, so I am not sure what effect that will have in Windows XP sp2. The best thing I can recommend is build the sample without UNICODE enabled, and then install the sample to a DOS compatible path (no spaces).

        for windows XP it should look something like this:
        [HKEY_LOCAL_MACHINE\SOFTWARE\MozillaPlugins\@conedogers.com/npruntime,version=1.0.0.2] “Path”=”C:\\dev\\mozilla\\npruntime\\Debug\\npruntime.dll” “ProductName”=”npruntime” “Vendor”=”conedogers” “Version”=”1.0.0.2″

        The problem here is you are attempting to build with an unsupported compiler. I do not know what affect that will have on runtime calls (and the differences) between FireFox 17 and the sample build built with VS 2003; or if there are any issues at all.

        Another item to check would be to load the NPruntime.dll in depends.exe. Dependency walker is a great utility that will list all the dependent files needed by the DLL or exe. You can download it here off CNET: Dependency walker

        If there are any missing DLL’s on the windows XP SP2, dependency walker should identify them.

        I can’t think of anything else off the top of my head.

    • There are no real plugins to prevent hackers. Any security provided by a Npapi plugin would only protect you in your current browsing session, so a plugin will not prevent a hacker from getting access to your computer. A plugin can be used to warn you about potential sites that might contain harmful webpages. Most modern browsers support this kind of functionality internally and that is the most secure.

      If you are using Internet explorer, Symantec and MCafee both make plugins and toolbars that provided advanced protections against these types of webpages. If you are on Firefox, then you can use the Adblock plus plugin to block the links to these harmful sites.

      I am not sure what is available on google chrome or other 3rd party browsers.

  3. I have been surfing on-line more than three hours nowadays, yet I never discovered
    any interesting article like yours. It’s pretty worth sufficient for me. In my opinion, if all web owners and bloggers made good content as you probably did, the internet will be a lot more helpful than ever before.

  4. Pingback: Visual Studio project settings for NPAPI projects | conedogers

  5. thanks for the nice article …
    i am writing a NPAPI plugin for that i am using NPSIMPLE sample code from google chrome. i have to get the DOM of web page opened in the chrome browser. My plugin solution also includes background.html file. which when i open in chrome browser calls a method in NPAPI plugin. so my plugin can get the URL of this file. now i want to read the DOM structure of this File.

    i have few questions:

    1.) when a new page is opened in browser by user how i have to embed my plugin to that page and get the DOM of that page?

    2.)whenever a new tab is opened how can i get the notification in My plugin?

    3.)How to get the DOM mutation notification to my plugin?

    4.)Does NPAPI provides API to get the DOM mutation notification or Content Script is the only option? if content script is the only option then how to establish communication between plugin and content_script?

    i am trying to get this answers as well. any help greatly appreciated…

    thanks in advance…

    • 1) Within chrome, you have some options on how/when your NPAPI plugin is loaded. To insert your plugin into each loaded page is not really needed. Instead, load the plugin into a chrome extension. Extensions are built with JavaScript, so load the plugin into your extension instead. Then you insert JavaScript hooks into each page, leveraging chrome extensions to do that. That is a blog post in itself…

      2) You have partly answered the question with the first question. You really can’t be notified. An extension should be able to determine when a tab is opened, and pass that event to your plugin.

      3) DOM mutation notifications will have to be processed in Chrome and you will have to build your own notification scheme for informing the plugin. If you can get the plugin loaded in the extension, then this should be fairly straight forward.

      4) Lol! remember NPAPI is very old… JavaScript objects or JSON/Ajax/XML parsing was still a black art when NPAPI was developed. Like I said in the answer to question one, the key is to get the plugin loaded inside a Chrome extension. In a nutshell, you want an extension that managed a persistent background page. http://developer.chrome.com/extensions/overview.html

  6. Hello there, just became aware of your blog through Google, and found that
    it is truly informative. I will be grateful if you continue this in future.
    A lot of people will be benefited from your writing.
    Cheers!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s