Simplify code for exposing plugin file names vs. full path. Second landing. b=488181 r/sr=jst,bz
authorJosh Aas <joshmoz@gmail.com>
Wed, 10 Jun 2009 16:47:49 -0400
changeset 29020 8fce20dd0cbec23dd2c703f9206155abd3163463
parent 29019 524477378eb1639b10f545d80ed47c6f84380cf7
child 29024 59eabbd69bc1eab9161e9e54ab4e8da7e548af37
push idunknown
push userunknown
push dateunknown
bugs488181
milestone1.9.2a1pre
Simplify code for exposing plugin file names vs. full path. Second landing. b=488181 r/sr=jst,bz
dom/locales/en-US/chrome/plugins.properties
modules/plugin/base/src/nsNPAPIPlugin.cpp
modules/plugin/base/src/nsNPAPIPlugin.h
modules/plugin/base/src/nsPluginHostImpl.cpp
modules/plugin/base/src/nsPluginHostImpl.h
modules/plugin/base/src/nsPluginsDirBeOS.cpp
modules/plugin/base/src/nsPluginsDirOS2.cpp
modules/plugin/base/src/nsPluginsDirUnix.cpp
modules/plugin/base/src/nsPluginsDirWin.cpp
modules/plugin/test/unit/test_bug455213.js
toolkit/content/plugins.html
--- a/dom/locales/en-US/chrome/plugins.properties
+++ b/dom/locales/en-US/chrome/plugins.properties
@@ -2,16 +2,16 @@
 #    Those strings are inserted into an HTML page, so you all HTML characters
 #    have to be escaped in a way that they show up correctly in HTML!
 
 title_label=About Plugins
 installedplugins_label=Installed plugins
 nopluginsareinstalled_label=No plugins are installed
 findmore_label=Find more information about browser plugins at
 installhelp_label=Help for installing plugins is available from
-filename_label=File name:
+file_label=File:
 version_label=Version:
 mimetype_label=MIME Type
 description_label=Description
 suffixes_label=Suffixes
 enabled_label=Enabled
 yes_label=Yes
 no_label=No
--- a/modules/plugin/base/src/nsNPAPIPlugin.cpp
+++ b/modules/plugin/base/src/nsNPAPIPlugin.cpp
@@ -348,18 +348,18 @@ void
 nsNPAPIPlugin::SetPluginRefNum(short aRefNum)
 {
   fPluginRefNum = aRefNum;
 }
 #endif
 
 // Creates the nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin (not instance).
 nsresult
-nsNPAPIPlugin::CreatePlugin(const char* aFileName, const char* aFullPath,
-                            PRLibrary* aLibrary, nsIPlugin** aResult)
+nsNPAPIPlugin::CreatePlugin(const char* aFilePath, PRLibrary* aLibrary,
+                            nsIPlugin** aResult)
 {
   CheckClassInitialized();
 
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
   nsNPAPIPlugin *plptr;
 
   NPPluginFuncs callbacks;
   memset((void*) &callbacks, 0, sizeof(callbacks));
@@ -372,17 +372,18 @@ nsNPAPIPlugin::CreatePlugin(const char* 
   *aResult = plptr =
     new nsNPAPIPlugin(&callbacks, aLibrary, pfnShutdown);
 
   if (*aResult == NULL)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult);
 
-  if (!aFileName) //do not call NP_Initialize in this case, bug 74938
+  // Do not initialize if the file path is NULL.
+  if (!aFilePath)
     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 =
@@ -458,17 +459,17 @@ nsNPAPIPlugin::CreatePlugin(const char* 
   // 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);
+  strcpy(pluginPath, aFilePath);
   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] = ':';
@@ -508,17 +509,17 @@ nsNPAPIPlugin::CreatePlugin(const char* 
   }
 #endif
 
 #if defined(XP_MACOSX)
   short appRefNum = ::CurResFile();
   short pluginRefNum;
 
   nsCOMPtr<nsILocalFile> pluginPath;
-  NS_NewNativeLocalFile(nsDependentCString(aFullPath), PR_TRUE,
+  NS_NewNativeLocalFile(nsDependentCString(aFilePath), PR_TRUE,
                         getter_AddRefs(pluginPath));
 
   nsPluginFile pluginFile(pluginPath);
   pluginRefNum = pluginFile.OpenPluginResource();
 
   nsNPAPIPlugin* plugin = new nsNPAPIPlugin(nsnull, aLibrary, nsnull);
   ::UseResFile(appRefNum);
   if (!plugin)
--- a/modules/plugin/base/src/nsNPAPIPlugin.h
+++ b/modules/plugin/base/src/nsNPAPIPlugin.h
@@ -80,20 +80,19 @@ public:
   nsNPAPIPlugin(NPPluginFuncs* callbacks, PRLibrary* aLibrary,
                 NP_PLUGINSHUTDOWN aShutdown);
   virtual ~nsNPAPIPlugin(void);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIFACTORY
   NS_DECL_NSIPLUGIN
 
-  // Constructs and initializes an nsNPAPIPlugin object
-  static nsresult CreatePlugin(const char* aFileName,
-                               const char* aFullPath,
-                               PRLibrary* aLibrary,
+  // Constructs and initializes an nsNPAPIPlugin object. A NULL file path
+  // will prevent this from calling NP_Initialize.
+  static nsresult CreatePlugin(const char* aFilePath, PRLibrary* aLibrary,
                                nsIPlugin** aResult);
 #ifdef XP_MACOSX
   void SetPluginRefNum(short aRefNum);
 #endif
 
 protected:
   // Ensures that the static CALLBACKS is properly initialized
   static void CheckClassInitialized(void);
--- a/modules/plugin/base/src/nsPluginHostImpl.cpp
+++ b/modules/plugin/base/src/nsPluginHostImpl.cpp
@@ -184,18 +184,19 @@
 // 0.03 changed name, description and mime desc from string to bytes, bug 108246
 // 0.04 added new mime entry point on Mac, bug 113464
 // 0.05 added new entry point check for the default plugin, bug 132430
 // 0.06 strip off suffixes in mime description strings, bug 53895
 // 0.07 changed nsIRegistry to flat file support for caching plugins info
 // 0.08 mime entry point on MachO, bug 137535
 // 0.09 the file encoding is changed to UTF-8, bug 420285
 // 0.10 added plugin versions on appropriate platforms, bug 427743
+// 0.11 file name and full path fields now store expected values on all platforms, bug 488181
 // The current plugin registry version (and the maximum version we know how to read)
-static const char *kPluginRegistryVersion = "0.10";
+static const char *kPluginRegistryVersion = "0.11";
 // The minimum registry version we know how to read
 static const char *kMinimumRegistryVersion = "0.9";
 
 // CID's && IID's
 static NS_DEFINE_IID(kIPluginInstanceIID, NS_IPLUGININSTANCE_IID);
 static NS_DEFINE_CID(kPluginCID, NS_PLUGIN_CID);
 static NS_DEFINE_IID(kIPluginTagInfo2IID, NS_IPLUGINTAGINFO2_IID);
 static const char kDirectoryServiceContractID[] = "@mozilla.org/file/directory_service;1";
@@ -3697,21 +3698,21 @@ nsPluginHostImpl::TrySetUpPluginInstance
     // if we don't have an extension or no plugin for this extension,
     // return failure as there is nothing more we can do
     if (fileExtension.IsEmpty() ||
         !(pluginTag = FindPluginEnabledForExtension(fileExtension.get(),
                                                     mimetype))) {
       return NS_ERROR_FAILURE;
     }
   }
-  else
+  else {
     mimetype = aMimeType;
+  }
 
   NS_ASSERTION(pluginTag, "Must have plugin tag here!");
-  PRBool isJavaPlugin = pluginTag->mIsJavaPlugin;
 
   nsCAutoString contractID(
           NS_LITERAL_CSTRING(NS_INLINE_PLUGIN_CONTRACTID_PREFIX) +
           nsDependentCString(mimetype));
 
   GetPluginFactory(mimetype, getter_AddRefs(plugin));
 
   instance = do_CreateInstance(contractID.get(), &result);
@@ -3719,17 +3720,17 @@ nsPluginHostImpl::TrySetUpPluginInstance
   // couldn't create an XPCOM plugin, try to create wrapper for a
   // legacy plugin
   if (NS_FAILED(result)) {
     if (plugin) {
 #if defined(XP_WIN) && !defined(WINCE)
       static BOOL firstJavaPlugin = FALSE;
       BOOL restoreOrigDir = FALSE;
       char origDir[_MAX_PATH];
-      if (isJavaPlugin && !firstJavaPlugin) {
+      if (pluginTag->mIsJavaPlugin && !firstJavaPlugin) {
         DWORD dw = ::GetCurrentDirectory(_MAX_PATH, origDir);
         NS_ASSERTION(dw <= _MAX_PATH, "Falied to obtain the current directory, which may leads to incorrect class laoding");
         nsCOMPtr<nsIFile> binDirectory;
         result = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
                                         getter_AddRefs(binDirectory));
 
         if (NS_SUCCEEDED(result)) {
           nsCAutoString path;
@@ -3990,43 +3991,24 @@ public:
     return NS_OK;
   }
 
   NS_METHOD GetFilename(nsAString& aFilename)
   {
     PRBool bShowPath;
     nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (prefService &&
-        NS_SUCCEEDED(prefService->GetBoolPref("plugin.expose_full_path",&bShowPath)) &&
+        NS_SUCCEEDED(prefService->GetBoolPref("plugin.expose_full_path", &bShowPath)) &&
         bShowPath) {
-      // only show the full path if people have set the pref,
-      // the default should not reveal path information (bug 88183)
-#if defined(XP_MACOSX)
       CopyUTF8toUTF16(mPluginTag.mFullPath, aFilename);
-#else
+    } else {
       CopyUTF8toUTF16(mPluginTag.mFileName, aFilename);
-#endif
-      return NS_OK;
     }
 
-    nsAutoString spec;
-    if (!mPluginTag.mFullPath.IsEmpty()) {
-#if !defined(XP_MACOSX)
-      NS_ERROR("Only MAC should be using nsPluginTag::mFullPath!");
-#endif
-      CopyUTF8toUTF16(mPluginTag.mFullPath, spec);
-    } else {
-      CopyUTF8toUTF16(mPluginTag.mFileName, spec);
-    }
-
-    nsCString leafName;
-    nsCOMPtr<nsILocalFile> pluginPath;
-    NS_NewLocalFile(spec, PR_TRUE, getter_AddRefs(pluginPath));
-
-    return pluginPath->GetLeafName(aFilename);
+    return NS_OK;
   }
 
   NS_METHOD GetVersion(nsAString& aVersion)
   {
     CopyUTF8toUTF16(mPluginTag.mVersion, aVersion);
     return NS_OK;
   }
 
@@ -4319,35 +4301,31 @@ static nsresult CreateNPAPIPlugin(nsISer
   nsCOMPtr <nsIPlatformCharset> pcs =
     do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCAutoString charset;
   rv = pcs->GetCharset(kPlatformCharsetSel_FileName, charset);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCAutoString fileName, fullPath;
+  nsCAutoString fullPath;
   if (!charset.LowerCaseEqualsLiteral("utf-8")) {
     nsCOMPtr<nsIUnicodeEncoder> encoder;
     nsCOMPtr<nsICharsetConverterManager> ccm =
       do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = ccm->GetUnicodeEncoderRaw(charset.get(), getter_AddRefs(encoder));
     NS_ENSURE_SUCCESS(rv, rv);
-    rv = ConvertToNative(encoder, aPluginTag->mFileName, fileName);
-    NS_ENSURE_SUCCESS(rv, rv);
     rv = ConvertToNative(encoder, aPluginTag->mFullPath, fullPath);
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
-    fileName = aPluginTag->mFileName;
     fullPath = aPluginTag->mFullPath;
   }
 
-  return nsNPAPIPlugin::CreatePlugin(fileName.get(),
-                                     fullPath.get(),
+  return nsNPAPIPlugin::CreatePlugin(fullPath.get(),
                                      aPluginTag->mLibrary,
                                      aOutNPAPIPlugnin);
 }
 
 NS_IMETHODIMP nsPluginHostImpl::GetPluginFactory(const char *aMimeType, nsIPlugin** aPlugin)
 {
   nsresult rv = NS_ERROR_FAILURE;
   *aPlugin = NULL;
@@ -4366,24 +4344,20 @@ NS_IMETHODIMP nsPluginHostImpl::GetPlugi
     aMimeType, pluginTag->mFileName.get()));
 
 #ifdef NS_DEBUG
     if (aMimeType && !pluginTag->mFileName.IsEmpty())
       printf("For %s found plugin %s\n", aMimeType, pluginTag->mFileName.get());
 #endif
 
     if (!pluginTag->mLibrary) { // if we haven't done this yet
-     nsCOMPtr<nsILocalFile> file = do_CreateInstance("@mozilla.org/file/local;1");
-#if !defined(XP_MACOSX)
-      file->InitWithPath(NS_ConvertUTF8toUTF16(pluginTag->mFileName));
-#else
       if (pluginTag->mFullPath.IsEmpty())
         return NS_ERROR_FAILURE;
+      nsCOMPtr<nsILocalFile> file = do_CreateInstance("@mozilla.org/file/local;1");
       file->InitWithPath(NS_ConvertUTF8toUTF16(pluginTag->mFullPath));
-#endif
       nsPluginFile pluginFile(file);
       PRLibrary* pluginLibrary = NULL;
 
       if (pluginFile.LoadPlugin(pluginLibrary) != NS_OK || pluginLibrary == NULL)
         return NS_ERROR_FAILURE;
 
       // remove from unused lib list, if it is there
       if (mUnusedLibraries.Contains(pluginLibrary))
@@ -4536,17 +4510,17 @@ PRBool nsPluginHostImpl::IsDuplicatePlug
 
   // we do not have it at all, return false
   return PR_FALSE;
 }
 
 // Structure for collecting plugin files found during directory scanning
 struct pluginFileinDirectory
 {
-  nsString mFilename;
+  nsString mFilePath;
   PRInt64  mModTime;
 
   pluginFileinDirectory()
   {
     mModTime = LL_ZERO;
   }
 };
 
@@ -4555,28 +4529,28 @@ struct pluginFileinDirectory
 
 NS_SPECIALIZE_TEMPLATE
 class nsDefaultComparator<pluginFileinDirectory, pluginFileinDirectory>
 {
   public:
   PRBool Equals(const pluginFileinDirectory& aA,
                 const pluginFileinDirectory& aB) const {
     if (aA.mModTime == aB.mModTime &&
-        Compare(aA.mFilename, aB.mFilename,
+        Compare(aA.mFilePath, aB.mFilePath,
                 nsCaseInsensitiveStringComparator()) == 0)
       return PR_TRUE;
     else
       return PR_FALSE;
   }
   PRBool LessThan(const pluginFileinDirectory& aA,
                   const pluginFileinDirectory& aB) const {
     if (aA.mModTime < aB.mModTime)
       return PR_TRUE;
     else if(aA.mModTime == aB.mModTime)
-      return Compare(aA.mFilename, aB.mFilename,
+      return Compare(aA.mFilePath, aB.mFilePath,
                      nsCaseInsensitiveStringComparator()) < 0;
     else
       return PR_FALSE;
   }
 };
 
 typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void);
 
@@ -4668,35 +4642,35 @@ nsresult nsPluginHostImpl::ScanPluginsDi
       if (!item)
         return NS_ERROR_OUT_OF_MEMORY;
 
       // Get file mod time
       PRInt64 fileModTime = LL_ZERO;
       dirEntry->GetLastModifiedTime(&fileModTime);
 
       item->mModTime = fileModTime;
-      item->mFilename = filePath;
+      item->mFilePath = filePath;
     }
   } // end round of up of plugin files
 
   // now sort the array by file modification time or by filename, if equal
   // put newer plugins first to weed out dups and catch upgrades, see bug 119966
   pluginFilesArray.Sort();
 
   // finally, go through the array, looking at each entry and continue processing it
   for (PRUint32 i = 0; i < pluginFilesArray.Length(); i++) {
     pluginFileinDirectory &pfd = pluginFilesArray[i];
     nsCOMPtr <nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
     nsCOMPtr <nsILocalFile> localfile = do_QueryInterface(file);
-    localfile->InitWithPath(pfd.mFilename);
+    localfile->InitWithPath(pfd.mFilePath);
     PRInt64 fileModTime = pfd.mModTime;
 
     // Look for it in our cache
     nsRefPtr<nsPluginTag> pluginTag;
-    RemoveCachedPluginsInfo(NS_ConvertUTF16toUTF8(pfd.mFilename).get(),
+    RemoveCachedPluginsInfo(NS_ConvertUTF16toUTF8(pfd.mFilePath).get(),
                             getter_AddRefs(pluginTag));
 
     PRBool enabled = PR_TRUE;
     PRBool seenBefore = PR_FALSE;
     if (pluginTag) {
       seenBefore = PR_TRUE;
       // If plugin changed, delete cachedPluginTag and don't use cache
       if (LL_NE(fileModTime, pluginTag->mLastModifiedTime)) {
@@ -5351,40 +5325,69 @@ nsPluginHostImpl::ReadPluginInfo()
     return rv;
 
   // Registry v0.10 and upwards includes the plugin version field
   PRBool regHasVersion = NS_CompareVersions(values[1], "0.10") >= 0;
 
   if (!ReadSectionHeader(reader, "PLUGINS"))
     return rv;
 
+#if defined(XP_MACOSX)
+  PRBool hasFullPathInFileNameField = PR_FALSE;
+#else
+  PRBool hasFullPathInFileNameField = (NS_CompareVersions(values[1], "0.11") < 0);
+#endif
+
   while (reader.NextLine()) {
-    const char *filename = reader.LinePtr();
-    if (!reader.NextLine())
-      return rv;
-
-    const char *fullpath = reader.LinePtr();
-    if (!reader.NextLine())
-      return rv;
+    const char *filename;
+    const char *fullpath;
+    nsCAutoString derivedFileName;
+    
+    if (hasFullPathInFileNameField) {
+      fullpath = reader.LinePtr();
+      if (!reader.NextLine())
+        return rv;
+      // try to derive a file name from the full path
+      if (fullpath) {
+        nsCOMPtr<nsILocalFile> file = do_CreateInstance("@mozilla.org/file/local;1");
+        file->InitWithNativePath(nsDependentCString(fullpath));
+        file->GetNativeLeafName(derivedFileName);
+        filename = derivedFileName.get();
+      } else {
+        filename = NULL;
+      }
+
+      // skip the next line, useless in this version
+      if (!reader.NextLine())
+        return rv;
+    } else {
+      filename = reader.LinePtr();
+      if (!reader.NextLine())
+        return rv;
+
+      fullpath = reader.LinePtr();
+      if (!reader.NextLine())
+        return rv;
+    }
 
     const char *version;
     if (regHasVersion) {
       version = reader.LinePtr();
       if (!reader.NextLine())
         return rv;
     } else {
       version = "0";
     }
 
     // lastModifiedTimeStamp|canUnload|tag.mFlag
     if (reader.ParseLine(values, 3) != 3)
       return rv;
 
     // If this is an old plugin registry mark this plugin tag to be refreshed
-    PRInt64 lastmod = vdiff == 0 ? nsCRT::atoll(values[0]) : -1;
+    PRInt64 lastmod = (vdiff == 0) ? nsCRT::atoll(values[0]) : -1;
     PRBool canunload = atoi(values[1]);
     PRUint32 tagflag = atoi(values[2]);
     if (!reader.NextLine())
       return rv;
 
     const char *description = reader.LinePtr();
     if (!reader.NextLine())
       return rv;
@@ -5430,17 +5433,17 @@ nsPluginHostImpl::ReadPluginInfo()
         delete [] heapalloced;
       }
       return rv;
     }
 
     nsRefPtr<nsPluginTag> tag = new nsPluginTag(name,
       description,
       filename,
-      (*fullpath ? fullpath : 0), // we have to pass 0 prt if it's empty str
+      fullpath,
       version,
       (const char* const*)mimetypes,
       (const char* const*)mimedescriptions,
       (const char* const*)extensions,
       mimetypecount, lastmod, canunload, PR_TRUE);
     if (heapalloced)
       delete [] heapalloced;
 
@@ -5460,27 +5463,23 @@ nsPluginHostImpl::ReadPluginInfo()
     tag->mNext = mCachedPlugins;
     mCachedPlugins = tag;
 
   }
   return NS_OK;
 }
 
 void
-nsPluginHostImpl::RemoveCachedPluginsInfo(const char *filename, nsPluginTag **result)
+nsPluginHostImpl::RemoveCachedPluginsInfo(const char *filePath, nsPluginTag **result)
 {
   nsRefPtr<nsPluginTag> prev;
   nsRefPtr<nsPluginTag> tag = mCachedPlugins;
   while (tag)
   {
-    // compare filename or else the mFullPath if it exists. Mac seems to use
-    // mFullPath for fullpath and mFileName for just the leafname of fullpath.
-    // On win and unix, mFullPath is never used and mFileName is contains the
-    // full pathname. All this should move to using nsIFile.
-    if (tag->mFileName.Equals(filename) || tag->mFullPath.Equals(filename)) {
+    if (tag->mFullPath.Equals(filePath)) {
       // Found it. Remove it from our list
       if (prev)
         prev->mNext = tag->mNext;
       else
         mCachedPlugins = tag->mNext;
       tag->mNext = nsnull;
       *result = tag;
       NS_ADDREF(*result);
--- a/modules/plugin/base/src/nsPluginHostImpl.h
+++ b/modules/plugin/base/src/nsPluginHostImpl.h
@@ -392,19 +392,19 @@ private:
   PRBool IsRunningPlugin(nsPluginTag * plugin);
 
   // Stores all plugins info into the registry
   nsresult WritePluginInfo();
 
   // Loads all cached plugins info into mCachedPlugins
   nsresult ReadPluginInfo();
 
-  // Given a filename, returns the plugins info from our cache
+  // Given a file path, returns the plugins info from our cache
   // and removes it from the cache.
-  void RemoveCachedPluginsInfo(const char *filename,
+  void RemoveCachedPluginsInfo(const char *filePath,
                                nsPluginTag **result);
 
   //checks if the list already have the same plugin as given
   nsPluginTag* HaveSamePlugin(nsPluginTag * aPluginTag);
 
   // checks if given plugin is a duplicate of what we already have
   // in the plugin list but found in some different place
   PRBool IsDuplicatePlugin(nsPluginTag * aPluginTag);
--- a/modules/plugin/base/src/nsPluginsDirBeOS.cpp
+++ b/modules/plugin/base/src/nsPluginsDirBeOS.cpp
@@ -159,22 +159,26 @@ typedef char* (*BeOS_Plugin_GetMIMEDescr
 
 
 /**
  * Obtains all of the information currently available for this plugin.
  */
 nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info)
 {
     info.fVersion = nsnull;
-    nsCAutoString fpath;
-    nsresult rv = mPlugin->GetNativePath(fpath);
-    if (NS_OK != rv) {
+
+    nsCAutoString fullPath;
+    if (NS_FAILED(rv = mPlugin->GetNativePath(fullPath)))
         return rv;
-    }
-    const char *path = fpath.get();
+
+    nsCAutoString fileName;
+    if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName)))
+        return rv;
+
+    const char *path = fullPath.get();
     int i;
 
 #ifdef NS_PLUGIN_BEOS_DEBUG
     printf("nsPluginFile::GetPluginInfo() an attempt to load MIME String\n");
     printf("path = <%s>\n", path);
 #endif
 
     // get supported mime types
@@ -238,18 +242,18 @@ nsresult nsPluginFile::GetPluginInfo(nsP
         info.fDescription = ToNewCString(NS_ConvertUTF8toUTF16(vinfo.long_info));
     } else {
         // use filename as its name
         info.fName = GetFileName(path);
         info.fDescription = PL_strdup("");
     }
 
     info.fVariantCount = types_num;
-    info.fFileName = PL_strdup(path);
-
+    info.fFullPath = PL_strdup(fullPath.get());
+    info.fFileName = PL_strdup(fileName.get());
 
 #ifdef NS_PLUGIN_BEOS_DEBUG
     printf("info.fFileName = %s\n", info.fFileName);
     printf("info.fName = %s\n", info.fName);
     printf("info.fDescription = %s\n", info.fDescription);
 #endif
 
     return NS_OK;
@@ -273,16 +277,19 @@ nsresult nsPluginFile::FreePluginInfo(ns
         if (info.fExtensionArray[i])
             PL_strfree(info.fExtensionArray[i]);
     }
 
     PR_FREEIF(info.fMimeTypeArray);
     PR_FREEIF(info.fMimeDescriptionArray);
     PR_FREEIF(info.fExtensionArray);
 
+    if (info.fFullPath)
+        PL_strfree(info.fFullPath);
+
     if (info.fFileName)
         PL_strfree(info.fFileName);
 
     if (info.fVersion)
         PL_strfree(info.fVersion);
 
     return NS_OK;
 }
--- a/modules/plugin/base/src/nsPluginsDirOS2.cpp
+++ b/modules/plugin/base/src/nsPluginsDirOS2.cpp
@@ -209,26 +209,30 @@ nsresult nsPluginFile::LoadPlugin( PRLib
 
     outLibrary = PR_LoadLibrary(temp.get());
     return outLibrary == nsnull ? NS_ERROR_FAILURE : NS_OK;
 }
 
 // Obtains all of the information currently available for this plugin.
 nsresult nsPluginFile::GetPluginInfo( nsPluginInfo &info)
 {
-   nsresult   rc = NS_ERROR_FAILURE;
+   nsresult   rv = NS_ERROR_FAILURE;
    HMODULE    hPlug = 0; // Need a HMODULE to query resource statements
    char       failure[ CCHMAXPATH] = "";
    APIRET     ret;
 
-   const char* path;
-   nsCAutoString temp;
-   mPlugin->GetNativePath(temp);
-   path = temp.get();
-   ret = DosLoadModule( failure, CCHMAXPATH, path, &hPlug);
+   nsCAutoString path;
+   if (NS_FAILED(rv = mPlugin->GetNativePath(path)))
+     return rv;
+
+   nsCAutoString fileName;
+   if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName)))
+     return rv;
+
+   ret = DosLoadModule( failure, CCHMAXPATH, path.get(), &hPlug);
    info.fVersion = nsnull;
 
    while( ret == NO_ERROR)
    {
       info.fName = LoadRCDATAString( hPlug, NS_INFO_ProductName);
 
       info.fVersion = LoadRCDATAVersion( hPlug, NS_INFO_ProductVersion);
 
@@ -250,33 +254,37 @@ nsresult nsPluginFile::GetPluginInfo( ns
       if( info.fMimeTypeArray == nsnull) break;
 
       info.fMimeDescriptionArray = MakeStringArray(info.fVariantCount, mimeDescription);
       if( nsnull == info.fMimeDescriptionArray) break;
 
       info.fExtensionArray = MakeStringArray(info.fVariantCount, extensions);
       if( nsnull == info.fExtensionArray) break;
 
-      info.fFileName = PL_strdup(path);
+      info.fFullPath = PL_strdup(path.get());
+      info.fFileName = PL_strdup(fileName.get());
 
-      rc = NS_OK;
+      rv = NS_OK;
       break;
    }
 
    if( 0 != hPlug)
       DosFreeModule( hPlug);
 
-   return rc;
+   return rv;
 }
 
 nsresult nsPluginFile::FreePluginInfo(nsPluginInfo& info)
 {
    if(info.fName != nsnull)
      PL_strfree(info.fName);
- 
+
+   if(info.fFullPath != nsnull)
+     PL_strfree(info.fFullPath);
+
    if(info.fFileName != nsnull)
      PL_strfree(info.fFileName);
  
    if(info.fVersion != nsnull)
      PL_strfree(info.fVersion);
  
    if(info.fDescription != nsnull)
      PL_strfree(info.fDescription);
--- a/modules/plugin/base/src/nsPluginsDirUnix.cpp
+++ b/modules/plugin/base/src/nsPluginsDirUnix.cpp
@@ -429,79 +429,87 @@ nsresult nsPluginFile::LoadPlugin(PRLibr
 }
 
 /**
  * Obtains all of the information currently available for this plugin.
  */
 nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info)
 {
     nsresult rv;
-    const char* mimedescr = 0, *name = 0, *description = 0;
 
     // No, this doesn't leak. GetGlobalServiceManager() doesn't addref
     // it's out pointer. Maybe it should.
     nsIServiceManagerObsolete* mgr;
     nsServiceManager::GetGlobalServiceManager((nsIServiceManager**)&mgr);
 
     nsFactoryProc nsGetFactory =
         (nsFactoryProc) PR_FindFunctionSymbol(pLibrary, "NSGetFactory");
 
     nsCOMPtr<nsIPlugin> plugin;
 
     info.fVersion = nsnull;
     if (nsGetFactory) {
-        // It's an almost-new-style plugin. The "truly new" plugins
-        // are just XPCOM components, but there are some Mozilla
-        // Classic holdovers that live in the plugins directory but
-        // implement nsIPlugin and the factory stuff.
+        // This is an XPCOM plugin.
         static NS_DEFINE_CID(kPluginCID, NS_PLUGIN_CID);
 
         nsCOMPtr<nsIFactory> factory;
         rv = nsGetFactory(mgr, kPluginCID, nsnull, nsnull, 
 			  getter_AddRefs(factory));
 
         if (NS_FAILED(rv)) {
             // HACK: The symbol lookup for "NSGetFactory" mistakenly returns
             // a reference to an unrelated function when we have an NPAPI
             // plugin linked to libxul.so.  Give this plugin another shot as
-            // an NPAPI plugin
-            rv = nsNPAPIPlugin::CreatePlugin(0, 0, pLibrary, getter_AddRefs(plugin));
+            // an NPAPI plugin.
+            // Passing NULL for a file path will prevent a call to NP_Initialize.
+            rv = nsNPAPIPlugin::CreatePlugin(NULL, pLibrary, getter_AddRefs(plugin));
             if (NS_FAILED(rv))
                 return rv;
         } else {
             plugin = do_QueryInterface(factory);
         }
     } else {
-        // It's old sk00l
-        // if fileName parameter == 0 nsNPAPIPlugin::CreatePlugin() will not call NP_Initialize()
-        rv = nsNPAPIPlugin::CreatePlugin(0, 0, pLibrary, getter_AddRefs(plugin));
+        // This is an NPAPI plugin.
+        // Passing NULL for a file path will prevent a call to NP_Initialize.
+        rv = nsNPAPIPlugin::CreatePlugin(NULL, pLibrary, getter_AddRefs(plugin));
         if (NS_FAILED(rv)) return rv;
     }
 
     if (plugin) {
         const char* (*npGetPluginVersion)() =
           (const char* (*)()) PR_FindFunctionSymbol(pLibrary, "NP_GetPluginVersion");
         if (npGetPluginVersion)
             info.fVersion = PL_strdup(npGetPluginVersion());
 
+        const char *mimedescr = NULL;
         plugin->GetMIMEDescription(&mimedescr);
 #ifdef NS_DEBUG
         printf("GetMIMEDescription() returned \"%s\"\n", mimedescr);
 #endif
         if (NS_FAILED(rv = ParsePluginMimeDescription(mimedescr, info)))
             return rv;
-        nsCAutoString filename;
-        if (NS_FAILED(rv = mPlugin->GetNativePath(filename)))
+
+        nsCAutoString path;
+        if (NS_FAILED(rv = mPlugin->GetNativePath(path)))
             return rv;
-        info.fFileName = PL_strdup(filename.get());
+        info.fFullPath = PL_strdup(path.get());
+
+        nsCAutoString fileName;
+        if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName)))
+          return rv;
+        info.fFileName = PL_strdup(fileName.get());
+
+        const char *name = NULL;
         plugin->GetValue(nsPluginVariable_NameString, &name);
-        if (!name)
-            name = PL_strrchr(info.fFileName, '/') + 1;
-        info.fName = PL_strdup(name);
+        if (name)
+          info.fName = PL_strdup(name);
+        else
+          info.fName = PL_strdup(fileName.get());
 
+        const char *description = NULL;
         plugin->GetValue(nsPluginVariable_DescriptionString, &description);
         if (!description)
             description = "";
         info.fDescription = PL_strdup(description);
     }
     return NS_OK;
 }
 
@@ -524,16 +532,19 @@ nsresult nsPluginFile::FreePluginInfo(ns
         if (info.fExtensionArray[i] != nsnull)
             PL_strfree(info.fExtensionArray[i]);
     }
 
     PR_FREEIF(info.fMimeTypeArray);
     PR_FREEIF(info.fMimeDescriptionArray);
     PR_FREEIF(info.fExtensionArray);
 
+    if (info.fFullPath != nsnull)
+        PL_strfree(info.fFullPath);
+
     if (info.fFileName != nsnull)
         PL_strfree(info.fFileName);
 
     if (info.fVersion != nsnull)
         PL_strfree(info.fVersion);
 
     return NS_OK;
 }
--- a/modules/plugin/base/src/nsPluginsDirWin.cpp
+++ b/modules/plugin/base/src/nsPluginsDirWin.cpp
@@ -258,34 +258,39 @@ nsresult nsPluginFile::LoadPlugin(PRLibr
   return NS_OK;
 }
 
 /**
  * Obtains all of the information currently available for this plugin.
  */
 nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info)
 {
-  nsresult res = NS_OK;
+  nsresult rv = NS_OK;
   DWORD zerome, versionsize;
   TCHAR* verbuf = nsnull;
 
   const TCHAR* path;
 
   if (!mPlugin)
     return NS_ERROR_NULL_POINTER;
 
-  nsCAutoString temp;
-  mPlugin->GetNativePath(temp);
+  nsCAutoString fullPath;
+  if (NS_FAILED(rv = mPlugin->GetNativePath(fullPath)))
+    return rv;
+
+  nsCAutoString fileName;
+  if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName)))
+    return rv;
 
 #ifdef UNICODE
-  NS_ConvertASCIItoUTF16 temp2(temp);
-  path = temp2.get();
+  NS_ConvertASCIItoUTF16 utf16Path(fullPath);
+  path = utf16Path.get();
   versionsize = ::GetFileVersionInfoSizeW((TCHAR*)path, &zerome);
 #else
-  path = temp.get();
+  path = fullPath.get();
   versionsize = ::GetFileVersionInfoSize((TCHAR*)path, &zerome);
 #endif
 
   if (versionsize > 0)
     verbuf = (TCHAR*)PR_Malloc(versionsize);
   if (!verbuf)
     return NS_ERROR_OUT_OF_MEMORY;
 
@@ -301,30 +306,31 @@ nsresult nsPluginFile::GetPluginInfo(nsP
     char *mimeType = GetKeyValue(verbuf, TEXT("\\StringFileInfo\\040904E4\\MIMEType"));
     char *mimeDescription = GetKeyValue(verbuf, TEXT("\\StringFileInfo\\040904E4\\FileOpenName"));
     char *extensions = GetKeyValue(verbuf, TEXT("\\StringFileInfo\\040904E4\\FileExtents"));
 
     info.fVariantCount = CalculateVariantCount(mimeType);
     info.fMimeTypeArray = MakeStringArray(info.fVariantCount, mimeType);
     info.fMimeDescriptionArray = MakeStringArray(info.fVariantCount, mimeDescription);
     info.fExtensionArray = MakeStringArray(info.fVariantCount, extensions);
-    info.fFileName = PL_strdup(temp.get());
+    info.fFullPath = PL_strdup(fullPath.get());
+    info.fFileName = PL_strdup(fileName.get());
     info.fVersion = GetVersion(verbuf);
 
     PL_strfree(mimeType);
     PL_strfree(mimeDescription);
     PL_strfree(extensions);
   }
   else {
-    res = NS_ERROR_FAILURE;
+    rv = NS_ERROR_FAILURE;
   }
 
   PR_Free(verbuf);
 
-  return res;
+  return rv;
 }
 
 nsresult nsPluginFile::FreePluginInfo(nsPluginInfo& info)
 {
   if (info.fName)
     PL_strfree(info.fName);
 
   if (info.fDescription)
@@ -334,16 +340,19 @@ nsresult nsPluginFile::FreePluginInfo(ns
     FreeStringArray(info.fVariantCount, info.fMimeTypeArray);
 
   if (info.fMimeDescriptionArray)
     FreeStringArray(info.fVariantCount, info.fMimeDescriptionArray);
 
   if (info.fExtensionArray)
     FreeStringArray(info.fVariantCount, info.fExtensionArray);
 
+  if (info.fFullPath)
+    PL_strfree(info.fFullPath);
+
   if (info.fFileName)
     PL_strfree(info.fFileName);
 
   if (info.fVersion)
     PR_smprintf_free(info.fVersion);
 
   ZeroMemory((void *)&info, sizeof(info));
 
--- a/modules/plugin/test/unit/test_bug455213.js
+++ b/modules/plugin/test/unit/test_bug455213.js
@@ -37,16 +37,25 @@
  */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 const NS_APP_USER_PROFILE_50_DIR      = "ProfD";
 const NS_APP_PROFILE_DIR_STARTUP      = "ProfDS";
 
+// v0.9 registry field meanings are different on Mac OS X
+const CWD = do_get_cwd();
+function checkOS(os) {
+  const nsILocalFile_ = "nsILocalFile" + os;
+  return nsILocalFile_ in Components.interfaces &&
+         CWD instanceof Components.interfaces[nsILocalFile_];
+}
+const isMac = checkOS("Mac");
+
 // Plugin registry uses different field delimeters on different platforms
 var DELIM = ":";
 if ("@mozilla.org/windows-registry-key;1" in Components.classes)
   DELIM = "|";
 
 var gProfD;
 var gDirSvc = Cc["@mozilla.org/file/directory_service;1"].
              getService(Ci.nsIProperties);
@@ -150,18 +159,23 @@ function get_test_plugintag() {
 function run_test() {
   createProfileFolder();
   var file = get_test_plugin();
   if (!file)
     do_throw("Plugin library not found");
 
   // Write out a 0.9 version registry that marks the test plugin as disabled
   var registry = "";
-  registry += file.leafName + DELIM + "$\n";
-  registry += file.path + DELIM + "$\n";
+  if (isMac) {
+    registry += file.leafName + DELIM + "$\n";
+    registry += file.path + DELIM + "$\n";
+  } else {
+    registry += file.path + DELIM + "$\n";
+    registry += DELIM + "$\n";
+  }
   registry += file.lastModifiedTime + DELIM + "0" + DELIM + "0" + DELIM + "$\n";
   registry += "Plug-in for testing purposes." + DELIM + "$\n";
   registry += "Test Plug-in" + DELIM + "$\n";
   registry += "1\n";
   registry += "0" + DELIM + "application/x-test" + DELIM + "Test mimetype" +
               DELIM + "tst" + DELIM + "$\n";
   write_registry("0.9", registry);
 
--- a/toolkit/content/plugins.html
+++ b/toolkit/content/plugins.html
@@ -111,17 +111,17 @@
     var plugin = navigator.plugins[i];
 
     if (plugin)
     {
       document.write("<h2 class=\"plugname\">");
       document.write(plugin.name);
       document.writeln("<\/h2>");
 
-      document.writeln("<dl><dd><span class=\"label\">" + pluginsbundle.GetStringFromName("filename_label") + "<\/span> ");
+      document.writeln("<dl><dd><span class=\"label\">" + pluginsbundle.GetStringFromName("file_label") + "<\/span> ");
       document.write(plugin.filename);
       document.writeln("<\/dd><dd><span class=\"label\">" + pluginsbundle.GetStringFromName("version_label") + "<\/span> ");
       document.write(plugin.version);
       document.writeln("<\/dd><dd>");
       document.write(plugin.description);
       document.writeln("<\/dd><\/dl>");
 
       document.writeln("<table border=\"1\" class=\"contenttable\">");