Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Static Public Member Functions | Static Protected Member Functions | Protected Attributes | Static Protected Attributes
ns4xPlugin Class Reference

A 5.0 wrapper for a 4.x style plugin. More...

#include <ns4xPlugin.h>

Inheritance diagram for ns4xPlugin:
Inheritance graph
[legend]
Collaboration diagram for ns4xPlugin:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 ns4xPlugin (NPPluginFuncs *callbacks, PRLibrary *aLibrary, NP_PLUGINSHUTDOWN aShutdown, nsIServiceManagerObsolete *serviceMgr)
virtual ~ns4xPlugin (void)
NS_DECL_ISUPPORTS NS_IMETHOD CreateInstance (nsISupports *aOuter, REFNSIID aIID, void **aResult)
NS_IMETHOD LockFactory (PRBool aLock)
NS_IMETHOD CreatePluginInstance (nsISupports *aOuter, REFNSIID aIID, const char *aPluginMIMEType, void **aResult)
 Creates a new plugin instance, based on a MIME type.
NS_IMETHOD Initialize (void)
NS_IMETHOD Shutdown (void)
NS_IMETHOD GetMIMEDescription (const char **resultingDesc)
NS_IMETHOD GetValue (nsPluginVariable variable, void *value)
void createPluginInstance (in nsISupports aOuter, in nsIIDRef aIID, in string aPluginMIMEType,[retval, iid_is(aIID)] out nsQIResult aResult)
 Creates a new plugin instance, based on a MIME type.
void initialize ()
 Initializes the plugin and will be called before any new instances are created.
void shutdown ()
 Called when the browser is done with the plugin factory, or when the plugin is disabled by the user.
void getMIMEDescription (out constCharPtr aMIMEDescription)
 Returns the MIME description for the plugin.
void getValue (in nsPluginVariable aVariable, in voidPtr aValue)
 Returns the value of a variable associated with the plugin.
void createInstance (in nsISupports aOuter, in nsIIDRef iid,[retval, iid_is(iid)] out nsQIResult result)
 Creates an instance of a component.
void lockFactory (in PRBool lock)
 LockFactory provides the client a way to keep the component in memory until it is finished with it.

Static Public Member Functions

static nsresult CreatePlugin (nsIServiceManagerObsolete *aServiceMgr, const char *aFileName, const char *aFullPath, PRLibrary *aLibrary, nsIPlugin **aResult)
 A static factory method for constructing 4.x plugins.

Static Protected Member Functions

static void CheckClassInitialized (void)
 Ensures that the static CALLBACKS is properly initialized.

Protected Attributes

NPPluginFuncs fCallbacks
 The plugin-side callbacks that the browser calls.
PRLibraryfLibrary
NP_PLUGINSHUTDOWN fShutdownEntry

Static Protected Attributes

static NPNetscapeFuncs CALLBACKS
 The browser-side callbacks that a 4.x-style plugin calls.

Detailed Description

A 5.0 wrapper for a 4.x style plugin.

Definition at line 96 of file ns4xPlugin.h.


Constructor & Destructor Documentation

ns4xPlugin::ns4xPlugin ( NPPluginFuncs callbacks,
PRLibrary aLibrary,
NP_PLUGINSHUTDOWN  aShutdown,
nsIServiceManagerObsolete serviceMgr 
)

Definition at line 423 of file ns4xPlugin.cpp.

{
  memset((void*) &fCallbacks, 0, sizeof(fCallbacks));
  fLibrary = nsnull;

#if defined(XP_WIN) || defined(XP_OS2)
  // On Windows (and Mac) we need to keep a direct reference to the
  // fCallbacks and NOT just copy the struct. See Bugzilla 85334

  NP_GETENTRYPOINTS pfnGetEntryPoints =
    (NP_GETENTRYPOINTS)PR_FindSymbol(aLibrary, "NP_GetEntryPoints");

  if (!pfnGetEntryPoints)
    return;

  fCallbacks.size = sizeof(fCallbacks);

  nsresult result = pfnGetEntryPoints(&fCallbacks);
  NS_ASSERTION( NS_OK == result,"Failed to get callbacks");

  NS_ASSERTION(HIBYTE(fCallbacks.version) >= NP_VERSION_MAJOR,
               "callback version is less than NP version");

  fShutdownEntry = (NP_PLUGINSHUTDOWN)PR_FindSymbol(aLibrary, "NP_Shutdown");
#elif defined(XP_MACOSX)
#ifdef BROKEN_PLUGIN_HACK
#warning BROKEN_PLUGIN_HACK is in use, enjoy your Flash movies!
  // This is a private NSPR struct.  Define it here because it's necessary
  // to restrict the hack to plugins that need it, and the only way to do
  // that is to examine the bundle that was loaded.  I feel comfortable doing
  // this because BROKEN_PLUGIN_HACK is a hack anyway, and it's not intended
  // to be long-lived.
  struct myPRLibrary {
    char*                     name;
    PRLibrary*                next;
    int                       refCount;
    const PRStaticLinkTable*  staticTable;
    CFragConnectionID         connection;
    CFBundleRef               bundle;
    Ptr                       main;
    CFMutableDictionaryRef    wrappers;
    const struct mach_header* image;
  };

  // brokenPlugin indicates whether the plugin needs to be worked around
  // because it doesn't adhere to the API used on x86.
  PRBool brokenPlugin = PR_FALSE;

  // Identify the broken plugin by a variety of attributes.
  // Further inspection will be done before applying any workarounds.
  struct myPRLibrary *prLibrary = (struct myPRLibrary*) aLibrary;

  if (prLibrary->name && prLibrary->bundle) {
    CFStringRef bundleIdentifier = ::CFBundleGetIdentifier(prLibrary->bundle);
    CFStringRef bundleShortVersion =
      (CFStringRef) ::CFBundleGetValueForInfoDictionaryKey(prLibrary->bundle,
                      CFSTR("CFBundleShortVersionString"));

    if (!strcmp(prLibrary->name,
                "/Library/Internet Plug-Ins/Flash Player.plugin") &&
        ::CFBundleGetVersionNumber(prLibrary->bundle) == 0x1018011 &&
        bundleIdentifier &&
        ::CFStringCompare(bundleIdentifier,
                          CFSTR("com.macromedia.Flash Player.plugin"),
                          0) == kCFCompareEqualTo &&
        bundleShortVersion &&
        ::CFStringCompare(bundleShortVersion,
                          CFSTR("8.0.17"),
                          0) == kCFCompareEqualTo) {
      // Macromedia Flash Player plugin, version 8.0.17, bundle version 1.0.1f17
      brokenPlugin = PR_TRUE;
    }
  }
#endif /* BROKEN_PLUGIN_HACK */

  // call into the entry point
  NP_MAIN pfnMain = (NP_MAIN) PR_FindSymbol(aLibrary, "main");

  if (pfnMain == NULL)
    return;

  NPP_ShutdownUPP pfnShutdown;
  NPPluginFuncs np_callbacks;
  memset((void*) &np_callbacks, 0, sizeof(np_callbacks));
  np_callbacks.size = sizeof(np_callbacks);
  NPError error;

  NS_TRY_SAFE_CALL_RETURN(error,
                          CallNPP_MainEntryProc(pfnMain,
                                                &(ns4xPlugin::CALLBACKS),
                                                &np_callbacks,
                                                &pfnShutdown),
                          aLibrary, nsnull);

#ifdef BROKEN_PLUGIN_HACK
  // The broken plugin has wrapped NPN callback function pointers in PPC
  // TVector glue as though they were pointers to CFM TVectors.  When the
  // x86 attempts to execute the PPC glue, it will of course fail.
  //
  // What's done here is a bit unorthodox.  I'm going to locate the
  // TVector glue that the plugin created from ns4xPlugin::CALLBACKS by
  // peeking into its symbol table, then I'm going to dissect the PPC
  // machine code to get the target addresses and produce x86 machine code.
  // The x86 code overwrites the PPC code in the plugin's jump table.
  // The replacement code is of course executable.  I know I can do this,
  // because the broken plugin builds its table of TVector glue based on
  // what the sample NPAPI plugin does.
  //
  // Watch this.
  if (brokenPlugin) {
    PRUint32 glueFixed = 0;

    // Locate the table that the plugin filled with TVector glue.
    PRUint8* pluginsGlueTable = (PRUint8*)
      ::CFBundleGetDataPointerForName(prLibrary->bundle,
                                      CFSTR("gNetscapeFuncsGlueTable"));

    if (pluginsGlueTable) {
      // The table contains 40 entries.  Each entry is TVector glue of 6
      // 4-byte words (24 bytes total).  See gPluginFuncsGlueTable in
      // mozilla/modules/plugin/samples/default/mac/npmac.cpp .  That table
      // accomodates 23 entries, inspection in the debugger teaches that the
      // broken plugin's table is 40 entries long.
      for (PRUint32 i = 0 ; i < 40 ; i++) {
        PRUint32* gluePPC = (PRUint32*) (pluginsGlueTable + 24 * i);

        // Only translate entries that are actually stored as TVector glue.
        // There are other ways to write the glue for PPC, but this is the
        // de facto standard, and it's what the broken plugin uses.  The
        // PPC code means:
        //   lis   r12,        hi16(address) ; pointer to tvector embedded
        //   ori   r12,   r12, lo16(address) ;   as immediate params in glue
        //   lwz    r0, 0(r12)               ; get pc from tvector
        //   lwz    r2, 4(r12)               ; get rtoc from tvector
        //   mtctr  r0
        //   bctr                            ; jump to new pc
        if ( (*gluePPC    & 0xffff0000) == 0x3d800000 &&
            (*(gluePPC+1) & 0xffff0000) == 0x618c0000 &&
             *(gluePPC+2)               == 0x800c0000 &&
             *(gluePPC+3)               == 0x804c0004 &&
             *(gluePPC+4)               == 0x7c0903a6 &&
             *(gluePPC+5)               == 0x4e800420) {
          // Determine the actual address of the function by stripping the
          // TVector glue.  |address| is a usable function pointer.  Making
          // it a pointer to an 8-bit quantity keeps the math below simple.
          PRUint8* address = (PRUint8*) ((*gluePPC) << 16 |
                                         *(gluePPC+1) & 0xffff);

          // Build an x86 JMP instruction to jump to the desired function,
          // and replace the TVector glue with it.  Opcode 0xe9 is a
          // jump relative to the next instruction.  Total instruction length
          // is 5 bytes (in 32-bit operand-size mode).  If base is address
          // 0xfece5 and the target function is at address 0xc0ffee, then
          // the instruction placed at base, byte for byte, should be:
          //   0xfece5: 0xe9 0x04 0x13 0xb1 0x00: jmp 0xc0ffee
          PRUint8* glueX86 = (PRUint8*) gluePPC;
          *glueX86 = 0xe9;

          PRInt32* offset = (PRInt32*) (glueX86+1);
          *offset = (address - (glueX86 + 5));

          // PPC TVector glue is big compared to the x86 JMP.  Clean up the
          // rest of the space in the table entry.  Opcode 0x90 is NOP,
          // instruction length 1 byte.  This permits clean disassembly of
          // the entire memory region corresponding to the table.
          memset(glueX86+5, 0x90, 19);

          glueFixed++;
        }
      }
    }

    if (!glueFixed) {
      // This plugin wasn't broken after all.  Avoid applying the callback
      // dereferencing workarounds (TV2FP).
      brokenPlugin = PR_FALSE;
    }
  }
#endif /* BROKEN_PLUGIN_HACK */

  NPP_PLUGIN_LOG(PLUGIN_LOG_BASIC,
                 ("NPP MainEntryProc called: return=%d\n",error));

  if (error != NPERR_NO_ERROR)
    return;

  // version is a uint16 so cast to int to avoid an invalid
  // comparison due to limited range of the data type
  int cb_version = np_callbacks.version;
  if ((cb_version >> 8) < NP_VERSION_MAJOR)
    return;

  // wrap all plugin entry points tvectors as mach-o callable function
  // pointers.
  fCallbacks.size = sizeof(fCallbacks);
  fCallbacks.version = np_callbacks.version;
  fCallbacks.newp = (NPP_NewUPP) TV2FP(np_callbacks.newp);
  fCallbacks.destroy = (NPP_DestroyUPP) TV2FP(np_callbacks.destroy);
  fCallbacks.setwindow = (NPP_SetWindowUPP) TV2FP(np_callbacks.setwindow);
  fCallbacks.newstream = (NPP_NewStreamUPP) TV2FP(np_callbacks.newstream);
  fCallbacks.destroystream =
    (NPP_DestroyStreamUPP) TV2FP(np_callbacks.destroystream);
  fCallbacks.asfile = (NPP_StreamAsFileUPP) TV2FP(np_callbacks.asfile);
  fCallbacks.writeready = (NPP_WriteReadyUPP) TV2FP(np_callbacks.writeready);
  fCallbacks.write = (NPP_WriteUPP) TV2FP(np_callbacks.write);
  fCallbacks.print = (NPP_PrintUPP) TV2FP(np_callbacks.print);
  fCallbacks.event = (NPP_HandleEventUPP) TV2FP(np_callbacks.event);
  fCallbacks.urlnotify = (NPP_URLNotifyUPP) TV2FP(np_callbacks.urlnotify);
  fCallbacks.getvalue = (NPP_GetValueUPP) TV2FP(np_callbacks.getvalue);
  fCallbacks.setvalue = (NPP_SetValueUPP) TV2FP(np_callbacks.setvalue);
  fShutdownEntry = (NP_PLUGINSHUTDOWN) TV2FP(pfnShutdown);
#else // for everyone else
  memcpy((void*) &fCallbacks, (void*) callbacks, sizeof(fCallbacks));
  fShutdownEntry = aShutdown;
#endif

  fLibrary = aLibrary;
}

Here is the call graph for this function:

Here is the caller graph for this function:

ns4xPlugin::~ns4xPlugin ( void  ) [virtual]

Definition at line 646 of file ns4xPlugin.cpp.

{
  //reset the callbacks list
#if defined(XP_MACOSX) && defined(__POWERPC__)
  // release all wrapped plugin entry points.
  if (fCallbacks.newp)
    free((void *)fCallbacks.newp);
  if (fCallbacks.destroy)
    free((void *)fCallbacks.destroy);
  if (fCallbacks.setwindow)
    free((void *)fCallbacks.setwindow);
  if (fCallbacks.newstream)
    free((void *)fCallbacks.newstream);
  if (fCallbacks.asfile)
    free((void *)fCallbacks.asfile);
  if (fCallbacks.writeready)
    free((void *)fCallbacks.writeready);
  if (fCallbacks.write)
    free((void *)fCallbacks.write);
  if (fCallbacks.print)
    free((void *)fCallbacks.print);
  if (fCallbacks.event)
    free((void *)fCallbacks.event);
  if (fCallbacks.urlnotify)
    free((void *)fCallbacks.urlnotify);
  if (fCallbacks.getvalue)
    free((void *)fCallbacks.getvalue);
  if (fCallbacks.setvalue)
    free((void *)fCallbacks.setvalue);
#endif
  memset((void*) &fCallbacks, 0, sizeof(fCallbacks));
}

Here is the call graph for this function:


Member Function Documentation

void ns4xPlugin::CheckClassInitialized ( void  ) [static, protected]

Ensures that the static CALLBACKS is properly initialized.

Definition at line 274 of file ns4xPlugin.cpp.

{
  static PRBool initialized = FALSE;

  if (initialized)
    return;

  // XXX It'd be nice to make this const and initialize it statically...
  CALLBACKS.size = sizeof(CALLBACKS);
  CALLBACKS.version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;

  CALLBACKS.geturl =
    NewNPN_GetURLProc(FP2TV(_geturl));

  CALLBACKS.posturl =
    NewNPN_PostURLProc(FP2TV(_posturl));

  CALLBACKS.requestread =
    NewNPN_RequestReadProc(FP2TV(_requestread));

  CALLBACKS.newstream =
    NewNPN_NewStreamProc(FP2TV(_newstream));

  CALLBACKS.write =
    NewNPN_WriteProc(FP2TV(_write));

  CALLBACKS.destroystream =
    NewNPN_DestroyStreamProc(FP2TV(_destroystream));

  CALLBACKS.status =
    NewNPN_StatusProc(FP2TV(_status));

  CALLBACKS.uagent =
    NewNPN_UserAgentProc(FP2TV(_useragent));

  CALLBACKS.memalloc =
    NewNPN_MemAllocProc(FP2TV(_memalloc));

  CALLBACKS.memfree =
    NewNPN_MemFreeProc(FP2TV(_memfree));

  CALLBACKS.memflush =
    NewNPN_MemFlushProc(FP2TV(_memflush));

  CALLBACKS.reloadplugins =
    NewNPN_ReloadPluginsProc(FP2TV(_reloadplugins));

#ifdef OJI
  CALLBACKS.getJavaEnv =
    NewNPN_GetJavaEnvProc(FP2TV(_getJavaEnv));

  CALLBACKS.getJavaPeer =
    NewNPN_GetJavaPeerProc(FP2TV(_getJavaPeer));
#endif

  CALLBACKS.geturlnotify =
    NewNPN_GetURLNotifyProc(FP2TV(_geturlnotify));

  CALLBACKS.posturlnotify =
    NewNPN_PostURLNotifyProc(FP2TV(_posturlnotify));

  CALLBACKS.getvalue =
    NewNPN_GetValueProc(FP2TV(_getvalue));

  CALLBACKS.setvalue =
    NewNPN_SetValueProc(FP2TV(_setvalue));

  CALLBACKS.invalidaterect =
    NewNPN_InvalidateRectProc(FP2TV(_invalidaterect));

  CALLBACKS.invalidateregion =
    NewNPN_InvalidateRegionProc(FP2TV(_invalidateregion));

  CALLBACKS.forceredraw =
    NewNPN_ForceRedrawProc(FP2TV(_forceredraw));

  CALLBACKS.getstringidentifier =
    NewNPN_GetStringIdentifierProc(FP2TV(_getstringidentifier));

  CALLBACKS.getstringidentifiers =
    NewNPN_GetStringIdentifiersProc(FP2TV(_getstringidentifiers));

  CALLBACKS.getintidentifier =
    NewNPN_GetIntIdentifierProc(FP2TV(_getintidentifier));

  CALLBACKS.identifierisstring =
    NewNPN_IdentifierIsStringProc(FP2TV(_identifierisstring));

  CALLBACKS.utf8fromidentifier =
    NewNPN_UTF8FromIdentifierProc(FP2TV(_utf8fromidentifier));

  CALLBACKS.intfromidentifier =
    NewNPN_IntFromIdentifierProc(FP2TV(_intfromidentifier));

  CALLBACKS.createobject =
    NewNPN_CreateObjectProc(FP2TV(_createobject));

  CALLBACKS.retainobject =
    NewNPN_RetainObjectProc(FP2TV(_retainobject));

  CALLBACKS.releaseobject =
    NewNPN_ReleaseObjectProc(FP2TV(_releaseobject));

  CALLBACKS.invoke =
    NewNPN_InvokeProc(FP2TV(_invoke));

  CALLBACKS.invokeDefault =
    NewNPN_InvokeDefaultProc(FP2TV(_invokeDefault));

  CALLBACKS.evaluate =
    NewNPN_EvaluateProc(FP2TV(_evaluate));

  CALLBACKS.getproperty =
    NewNPN_GetPropertyProc(FP2TV(_getproperty));

  CALLBACKS.setproperty =
    NewNPN_SetPropertyProc(FP2TV(_setproperty));

  CALLBACKS.removeproperty =
    NewNPN_RemovePropertyProc(FP2TV(_removeproperty));

  CALLBACKS.hasproperty =
    NewNPN_HasPropertyProc(FP2TV(_hasproperty));

  CALLBACKS.hasmethod =
    NewNPN_HasMethodProc(FP2TV(_hasmethod));

  CALLBACKS.releasevariantvalue =
    NewNPN_ReleaseVariantValueProc(FP2TV(_releasevariantvalue));

  CALLBACKS.setexception =
    NewNPN_SetExceptionProc(FP2TV(_setexception));

  CALLBACKS.pushpopupsenabledstate =
    NewNPN_PushPopupsEnabledStateProc(FP2TV(_pushpopupsenabledstate));

  CALLBACKS.poppopupsenabledstate =
    NewNPN_PopPopupsEnabledStateProc(FP2TV(_poppopupsenabledstate));

  initialized = TRUE;

  NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,("NPN callbacks initialized\n"));
}

Here is the caller graph for this function:

void nsIFactory::createInstance ( in nsISupports  aOuter,
in nsIIDRef  iid,
[retval, iid_is(iid)] out nsQIResult  result 
) [inherited]

Creates an instance of a component.

Parameters:
aOuterPointer to a component that wishes to be aggregated in the resulting instance. This will be nsnull if no aggregation is requested.
iidThe IID of the interface being requested in the component which is being currently created.
result[out] Pointer to the newly created instance, if successful.
Returns:
NS_OK - Component successfully created and the interface being requested was successfully returned in result. NS_NOINTERFACE - Interface not accessible. NS_ERROR_NO_AGGREGATION - if an 'outer' object is supplied, but the component is not aggregatable. NS_ERROR* - Method failure.
nsresult ns4xPlugin::CreateInstance ( nsISupports *  aOuter,
REFNSIID  aIID,
void **  aResult 
)

Definition at line 953 of file ns4xPlugin.cpp.

{
  if (aResult == NULL)
    return NS_ERROR_NULL_POINTER;

  *aResult = NULL;

  // XXX This is suspicuous!
  nsRefPtr<ns4xPluginInstance> inst =
    new ns4xPluginInstance(&fCallbacks, fLibrary);

  if (!inst)
    return NS_ERROR_OUT_OF_MEMORY;

  return inst->QueryInterface(aIID, aResult);
}

Here is the caller graph for this function:

nsresult ns4xPlugin::CreatePlugin ( nsIServiceManagerObsolete aServiceMgr,
const char *  aFileName,
const char *  aFullPath,
PRLibrary aLibrary,
nsIPlugin **  aResult 
) [static]

A static factory method for constructing 4.x plugins.

CreatePlugin()

Constructs and initializes an ns4xPlugin object, and returns it in result.

Definition at line 699 of file ns4xPlugin.cpp.

{
  CheckClassInitialized();

#if defined(XP_UNIX) && !defined(XP_MACOSX)

  ns4xPlugin *plptr;

  NPPluginFuncs callbacks;
  memset((void*) &callbacks, 0, sizeof(callbacks));
  callbacks.size = sizeof(callbacks);

  NP_PLUGINSHUTDOWN pfnShutdown =
    (NP_PLUGINSHUTDOWN)PR_FindSymbol(aLibrary, "NP_Shutdown");

  // create the new plugin handler
  *aResult = plptr =
    new ns4xPlugin(&callbacks, aLibrary, pfnShutdown, aServiceMgr);

  if (*aResult == NULL)
    return NS_ERROR_OUT_OF_MEMORY;

  NS_ADDREF(*aResult);

  if (!aFileName) //do not call NP_Initialize in this case, bug 74938
    return NS_OK;

  // we must init here because the plugin may call NPN functions
  // when we call into the NP_Initialize entry point - NPN functions
  // require that mBrowserManager be set up
  plptr->Initialize();

  NP_PLUGINUNIXINIT pfnInitialize =
    (NP_PLUGINUNIXINIT)PR_FindSymbol(aLibrary, "NP_Initialize");

  if (pfnInitialize == NULL)
    return NS_ERROR_UNEXPECTED; // XXX Right error?

  if (pfnInitialize(&(ns4xPlugin::CALLBACKS),&callbacks) != NS_OK)
    return NS_ERROR_UNEXPECTED;

  // now copy function table back to ns4xPlugin instance
  memcpy((void*) &(plptr->fCallbacks), (void*)&callbacks, sizeof(callbacks));
#endif

#ifdef XP_WIN
  // Note: on Windows, we must use the fCallback because plugins may
  // change the function table. The Shockwave installer makes changes
  // in the table while running
  *aResult = new ns4xPlugin(nsnull, aLibrary, nsnull, aServiceMgr);

  if (*aResult == NULL)
    return NS_ERROR_OUT_OF_MEMORY;

  NS_ADDREF(*aResult);

  // we must init here because the plugin may call NPN functions
  // when we call into the NP_Initialize entry point - NPN functions
  // require that mBrowserManager be set up
  if (NS_FAILED((*aResult)->Initialize())) {
    NS_RELEASE(*aResult);
    return NS_ERROR_FAILURE;
  }

  // the NP_Initialize entry point was misnamed as NP_PluginInit,
  // early in plugin project development.  Its correct name is
  // documented now, and new developers expect it to work.  However,
  // I don't want to break the plugins already in the field, so
  // we'll accept either name

  NP_PLUGININIT pfnInitialize =
    (NP_PLUGININIT)PR_FindSymbol(aLibrary, "NP_Initialize");

  if (!pfnInitialize)
    pfnInitialize = (NP_PLUGININIT)PR_FindSymbol(aLibrary, "NP_PluginInit");

  if (pfnInitialize == NULL)
    return NS_ERROR_UNEXPECTED; // XXX Right error?

  if (pfnInitialize(&(ns4xPlugin::CALLBACKS)) != NS_OK)
    return NS_ERROR_UNEXPECTED;
#endif

#ifdef XP_OS2
  // create the new plugin handler
  *aResult = new ns4xPlugin(nsnull, aLibrary, nsnull, aServiceMgr);

  if (*aResult == NULL)
    return NS_ERROR_OUT_OF_MEMORY;

  NS_ADDREF(*aResult);

  // we must init here because the plugin may call NPN functions
  // when we call into the NP_Initialize entry point - NPN functions
  // require that mBrowserManager be set up
  if (NS_FAILED((*aResult)->Initialize())) {
    NS_RELEASE(*aResult);
    return NS_ERROR_FAILURE;
  }

  // the NP_Initialize entry point was misnamed as NP_PluginInit,
  // early in plugin project development.  Its correct name is
  // documented now, and new developers expect it to work.  However,
  // I don't want to break the plugins already in the field, so
  // we'll accept either name

  NP_PLUGININIT pfnInitialize =
    (NP_PLUGININIT)PR_FindSymbol(aLibrary, "NP_Initialize");

  if (!pfnInitialize)
    pfnInitialize = (NP_PLUGININIT)PR_FindSymbol(aLibrary, "NP_PluginInit");

  if (pfnInitialize == NULL)
    return NS_ERROR_UNEXPECTED; // XXX Right error?

  // Fixes problem where the OS/2 native multimedia plugins weren't
  // working on mozilla though did work on 4.x.  Problem is that they
  // expect the current working directory to be the plugins dir.
  // Since these plugins are no longer maintained and they represent
  // the majority of the OS/2 plugin contingency, we'll have to make
  // them work here.

#define MAP_DISKNUM_TO_LETTER(n) ('A' + (n - 1))
#define MAP_LETTER_TO_DISKNUM(c) (toupper(c)-'A'+1)

  unsigned long origDiskNum, pluginDiskNum, logicalDisk;

  char pluginPath[CCHMAXPATH], origPath[CCHMAXPATH];
  strcpy(pluginPath, aFileName);
  char* slash = strrchr(pluginPath, '\\');
  *slash = '\0';

  DosQueryCurrentDisk( &origDiskNum, &logicalDisk );
  pluginDiskNum = MAP_LETTER_TO_DISKNUM(pluginPath[0]);

  origPath[0] = MAP_DISKNUM_TO_LETTER(origDiskNum);
  origPath[1] = ':';
  origPath[2] = '\\';

  ULONG len = CCHMAXPATH-3;
  APIRET rc = DosQueryCurrentDir(0, &origPath[3], &len);
  NS_ASSERTION(NO_ERROR == rc,"DosQueryCurrentDir failed");

  BOOL bChangedDir = FALSE;
  BOOL bChangedDisk = FALSE;
  if (pluginDiskNum != origDiskNum) {
    rc = DosSetDefaultDisk(pluginDiskNum);
    NS_ASSERTION(NO_ERROR == rc,"DosSetDefaultDisk failed");
    bChangedDisk = TRUE;
  }

  if (stricmp(origPath, pluginPath) != 0) {
    rc = DosSetCurrentDir(pluginPath);
    NS_ASSERTION(NO_ERROR == rc,"DosSetCurrentDir failed");
    bChangedDir = TRUE;
  }

  nsresult rv = pfnInitialize(&(ns4xPlugin::CALLBACKS));

  if (bChangedDisk) {
    rc= DosSetDefaultDisk(origDiskNum);
    NS_ASSERTION(NO_ERROR == rc,"DosSetDefaultDisk failed");
  }
  if (bChangedDir) {
    rc = DosSetCurrentDir(origPath);
    NS_ASSERTION(NO_ERROR == rc,"DosSetCurrentDir failed");
  }

  if (!NS_SUCCEEDED(rv)) {
    return NS_ERROR_UNEXPECTED;
  }
#endif

#if defined(XP_MACOSX)
  short appRefNum = ::CurResFile();
  short pluginRefNum;

  nsCOMPtr<nsILocalFile> pluginPath;
  NS_NewNativeLocalFile(nsDependentCString(aFullPath), PR_TRUE,
                        getter_AddRefs(pluginPath));

  nsPluginFile pluginFile(pluginPath);
  pluginRefNum = pluginFile.OpenPluginResource();
  if (pluginRefNum == -1)
    return NS_ERROR_FAILURE;

  ns4xPlugin* plugin = new ns4xPlugin(nsnull, aLibrary, nsnull, aServiceMgr);
  if (plugin == NULL)
    return NS_ERROR_OUT_OF_MEMORY;

  ::UseResFile(appRefNum);
  *aResult = plugin;

  NS_ADDREF(*aResult);
  if (NS_FAILED((*aResult)->Initialize())) {
    NS_RELEASE(*aResult);
    return NS_ERROR_FAILURE;
  }

  plugin->SetPluginRefNum(pluginRefNum);
#endif  // XP_MACOSX

#ifdef XP_BEOS
  // I just copied UNIX version.
  // Makoto Hamanaka <VYA04230@nifty.com>

  ns4xPlugin *plptr;

  NPPluginFuncs callbacks;
  memset((void*) &callbacks, 0, sizeof(callbacks));
  callbacks.size = sizeof(callbacks);

  NP_PLUGINSHUTDOWN pfnShutdown =
    (NP_PLUGINSHUTDOWN)PR_FindSymbol(aLibrary, "NP_Shutdown");

  // create the new plugin handler
  *aResult = plptr =
    new ns4xPlugin(&callbacks, aLibrary, pfnShutdown, aServiceMgr);

  if (*aResult == NULL)
    return NS_ERROR_OUT_OF_MEMORY;

  NS_ADDREF(*aResult);

  // we must init here because the plugin may call NPN functions
  // when we call into the NP_Initialize entry point - NPN functions
  // require that mBrowserManager be set up
  plptr->Initialize();

  NP_PLUGINUNIXINIT pfnInitialize =
    (NP_PLUGINUNIXINIT)PR_FindSymbol(aLibrary, "NP_Initialize");

  if (pfnInitialize == NULL)
    return NS_ERROR_FAILURE;

  if (pfnInitialize(&(ns4xPlugin::CALLBACKS),&callbacks) != NS_OK)
    return NS_ERROR_FAILURE;

  // now copy function table back to ns4xPlugin instance
  memcpy((void*) &(plptr->fCallbacks), (void*)&callbacks, sizeof(callbacks));
#endif

  return NS_OK;
}

Here is the call graph for this function:

void nsIPlugin::createPluginInstance ( in nsISupports  aOuter,
in nsIIDRef  aIID,
in string  aPluginMIMEType,
[retval, iid_is(aIID)] out nsQIResult  aResult 
) [inherited]

Creates a new plugin instance, based on a MIME type.

This allows different impelementations to be created depending on the specified MIME type.

NS_METHOD ns4xPlugin::CreatePluginInstance ( nsISupports *  aOuter,
REFNSIID  aIID,
const char *  aPluginMIMEType,
void **  aResult 
)

Creates a new plugin instance, based on a MIME type.

This allows different impelementations to be created depending on the specified MIME type.

Definition at line 983 of file ns4xPlugin.cpp.

{
  return CreateInstance(aOuter, aIID, aResult);
}

Here is the call graph for this function:

void nsIPlugin::getMIMEDescription ( out constCharPtr  aMIMEDescription) [inherited]

Returns the MIME description for the plugin.

The MIME description is a colon-separated string containg the plugin MIME type, plugin data file extension, and plugin name, e.g.:

"application/x-simple-plugin:smp:Simple LiveConnect Sample Plug-in"

(Corresponds to NPP_GetMIMEDescription.)

Parameters:
aMIMEDescription- the resulting MIME description
Returns:
- NS_OK if this operation was successful
nsresult ns4xPlugin::GetMIMEDescription ( const char **  resultingDesc)

Definition at line 1030 of file ns4xPlugin.cpp.

{
  const char* (*npGetMIMEDescription)() =
    (const char* (*)()) PR_FindSymbol(fLibrary, "NP_GetMIMEDescription");

  *resultingDesc = npGetMIMEDescription ? npGetMIMEDescription() : "";

  PLUGIN_LOG(PLUGIN_LOG_NORMAL,
             ("ns4xPlugin::GetMIMEDescription called: this=%p, result=%s\n",
              this, *resultingDesc));

  return NS_OK;
}

Here is the call graph for this function:

nsresult ns4xPlugin::GetValue ( nsPluginVariable  variable,
void value 
)

Definition at line 1047 of file ns4xPlugin.cpp.

{
  PLUGIN_LOG(PLUGIN_LOG_NORMAL,
  ("ns4xPlugin::GetValue called: this=%p, variable=%d\n", this, variable));

  NPError (*npGetValue)(void*, nsPluginVariable, void*) =
    (NPError (*)(void*, nsPluginVariable, void*)) PR_FindSymbol(fLibrary,
                                                                "NP_GetValue");

  if (npGetValue && NPERR_NO_ERROR == npGetValue(nsnull, variable, value)) {
    return NS_OK;
  }

  return NS_ERROR_FAILURE;
}

Here is the call graph for this function:

void nsIPlugin::getValue ( in nsPluginVariable  aVariable,
in voidPtr  aValue 
) [inherited]

Returns the value of a variable associated with the plugin.

(Corresponds to NPP_GetValue.)

Parameters:
aVariable- the plugin variable to get
aValue- the address of where to store the resulting value
Returns:
- NS_OK if this operation was successful
void nsIPlugin::initialize ( ) [inherited]

Initializes the plugin and will be called before any new instances are created.

It is passed browserInterfaces on which QueryInterface may be used to obtain an nsIPluginManager, and other interfaces.

Parameters:
browserInterfaces- an object that allows access to other browser interfaces via QueryInterface
Returns:
- NS_OK if this operation was successful

Definition at line 992 of file ns4xPlugin.cpp.

{
  if (nsnull == fLibrary)
    return NS_ERROR_FAILURE;
  return NS_OK;
}

Here is the caller graph for this function:

void nsIFactory::lockFactory ( in PRBool  lock) [inherited]

LockFactory provides the client a way to keep the component in memory until it is finished with it.

The client can call LockFactory(PR_TRUE) to lock the factory and LockFactory(PR_FALSE) to release the factory.

Parameters:
lock- Must be PR_TRUE or PR_FALSE
Returns:
NS_OK - If the lock operation was successful. NS_ERROR* - Method failure.

Definition at line 974 of file ns4xPlugin.cpp.

{
  // Not implemented in simplest case.
  return NS_OK;
}
void nsIPlugin::shutdown ( ) [inherited]

Called when the browser is done with the plugin factory, or when the plugin is disabled by the user.

(Corresponds to NPP_Shutdown.)

Returns:
- NS_OK if this operation was successful

Definition at line 1002 of file ns4xPlugin.cpp.

{
  NPP_PLUGIN_LOG(PLUGIN_LOG_BASIC,
                 ("NPP Shutdown to be called: this=%p\n", this));

  if (nsnull != fShutdownEntry) {
#if defined(XP_MACOSX)
    CallNPP_ShutdownProc(fShutdownEntry);
    ::CloseResFile(fPluginRefNum);
#else
    NS_TRY_SAFE_CALL_VOID(fShutdownEntry(), fLibrary, nsnull);
#endif

#if defined(XP_MACOSX) && defined(__POWERPC__)
    // release the wrapped plugin function.
    free((void *)fShutdownEntry);
#endif
    fShutdownEntry = nsnull;
  }

  PLUGIN_LOG(PLUGIN_LOG_NORMAL,
             ("4xPlugin Shutdown done, this=%p", this));
  return NS_OK;
}

Member Data Documentation

The browser-side callbacks that a 4.x-style plugin calls.

Definition at line 177 of file ns4xPlugin.h.

The plugin-side callbacks that the browser calls.

One set of plugin callbacks for each plugin.

Definition at line 169 of file ns4xPlugin.h.

Definition at line 170 of file ns4xPlugin.h.

NP_PLUGINSHUTDOWN ns4xPlugin::fShutdownEntry [protected]

Definition at line 172 of file ns4xPlugin.h.


The documentation for this class was generated from the following files: