LCOV - code coverage report
Current view: directory - dom/plugins/base - nsPluginsDirUnix.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 186 79 42.5 %
Date: 2012-06-02 Functions: 11 6 54.5 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Alex Musil
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsNPAPIPlugin.h"
      40                 : #include "nsNPAPIPluginInstance.h"
      41                 : #include "nsIMemory.h"
      42                 : #include "nsIPluginStreamListener.h"
      43                 : #include "nsPluginsDir.h"
      44                 : #include "nsPluginsDirUtils.h"
      45                 : #include "prmem.h"
      46                 : #include "prenv.h"
      47                 : #include "prerror.h"
      48                 : #include <sys/stat.h>
      49                 : #include "nsString.h"
      50                 : #include "nsILocalFile.h"
      51                 : #include "nsIPrefBranch.h"
      52                 : #include "nsIPrefService.h"
      53                 : 
      54                 : #define LOCAL_PLUGIN_DLL_SUFFIX ".so"
      55                 : #if defined(__hpux)
      56                 : #define DEFAULT_X11_PATH "/usr/lib/X11R6/"
      57                 : #undef LOCAL_PLUGIN_DLL_SUFFIX
      58                 : #define LOCAL_PLUGIN_DLL_SUFFIX ".sl"
      59                 : #define LOCAL_PLUGIN_DLL_ALT_SUFFIX ".so"
      60                 : #elif defined(_AIX)
      61                 : #define DEFAULT_X11_PATH "/usr/lib"
      62                 : #define LOCAL_PLUGIN_DLL_ALT_SUFFIX ".a"
      63                 : #elif defined(SOLARIS)
      64                 : #define DEFAULT_X11_PATH "/usr/openwin/lib/"
      65                 : #elif defined(LINUX)
      66                 : #define DEFAULT_X11_PATH "/usr/X11R6/lib/"
      67                 : #elif defined(__APPLE__)
      68                 : #define DEFAULT_X11_PATH "/usr/X11R6/lib"
      69                 : #undef LOCAL_PLUGIN_DLL_SUFFIX
      70                 : #define LOCAL_PLUGIN_DLL_SUFFIX ".dylib"
      71                 : #define LOCAL_PLUGIN_DLL_ALT_SUFFIX ".so"
      72                 : #else
      73                 : #define DEFAULT_X11_PATH ""
      74                 : #endif
      75                 : 
      76                 : #if defined(MOZ_WIDGET_GTK2)
      77                 : 
      78                 : #define PLUGIN_MAX_LEN_OF_TMP_ARR 512
      79                 : 
      80               0 : static void DisplayPR_LoadLibraryErrorMessage(const char *libName)
      81                 : {
      82               0 :     char errorMsg[PLUGIN_MAX_LEN_OF_TMP_ARR] = "Cannot get error from NSPR.";
      83               0 :     if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
      84               0 :         PR_GetErrorText(errorMsg);
      85                 : 
      86                 :     fprintf(stderr, "LoadPlugin: failed to initialize shared library %s [%s]\n",
      87               0 :         libName, errorMsg);
      88               0 : }
      89                 : 
      90               0 : static void SearchForSoname(const char* name, char** soname)
      91                 : {
      92               0 :     if (!(name && soname))
      93               0 :         return;
      94               0 :     PRDir *fdDir = PR_OpenDir(DEFAULT_X11_PATH);
      95               0 :     if (!fdDir)
      96               0 :         return;       
      97                 : 
      98               0 :     int n = PL_strlen(name);
      99                 :     PRDirEntry *dirEntry;
     100               0 :     while ((dirEntry = PR_ReadDir(fdDir, PR_SKIP_BOTH))) {
     101               0 :         if (!PL_strncmp(dirEntry->name, name, n)) {
     102               0 :             if (dirEntry->name[n] == '.' && dirEntry->name[n+1] && !dirEntry->name[n+2]) {
     103                 :                 // name.N, wild guess this is what we need
     104               0 :                 char out[PLUGIN_MAX_LEN_OF_TMP_ARR] = DEFAULT_X11_PATH;
     105               0 :                 PL_strcat(out, dirEntry->name);
     106               0 :                 *soname = PL_strdup(out);
     107               0 :                break;
     108                 :             }
     109                 :         }
     110                 :     }
     111                 : 
     112               0 :     PR_CloseDir(fdDir);
     113                 : }
     114                 : 
     115               0 : static bool LoadExtraSharedLib(const char *name, char **soname, bool tryToGetSoname)
     116                 : {
     117               0 :     bool ret = true;
     118                 :     PRLibSpec tempSpec;
     119                 :     PRLibrary *handle;
     120               0 :     tempSpec.type = PR_LibSpec_Pathname;
     121               0 :     tempSpec.value.pathname = name;
     122               0 :     handle = PR_LoadLibraryWithFlags(tempSpec, PR_LD_NOW|PR_LD_GLOBAL);
     123               0 :     if (!handle) {
     124               0 :         ret = false;
     125               0 :         DisplayPR_LoadLibraryErrorMessage(name);
     126               0 :         if (tryToGetSoname) {
     127               0 :             SearchForSoname(name, soname);
     128               0 :             if (*soname) {
     129               0 :                 ret = LoadExtraSharedLib((const char *) *soname, NULL, false);
     130                 :             }
     131                 :         }
     132                 :     }
     133               0 :     return ret;
     134                 : }
     135                 : 
     136                 : #define PLUGIN_MAX_NUMBER_OF_EXTRA_LIBS 32
     137                 : #define PREF_PLUGINS_SONAME "plugin.soname.list"
     138                 : #if defined(SOLARIS) || defined(HPUX)
     139                 : #define DEFAULT_EXTRA_LIBS_LIST "libXt" LOCAL_PLUGIN_DLL_SUFFIX ":libXext" LOCAL_PLUGIN_DLL_SUFFIX ":libXm" LOCAL_PLUGIN_DLL_SUFFIX
     140                 : #else
     141                 : #define DEFAULT_EXTRA_LIBS_LIST "libXt" LOCAL_PLUGIN_DLL_SUFFIX ":libXext" LOCAL_PLUGIN_DLL_SUFFIX
     142                 : #endif
     143                 : /*
     144                 :  this function looks for
     145                 :  user_pref("plugin.soname.list", "/usr/X11R6/lib/libXt.so.6:libXext.so");
     146                 :  in user's pref.js
     147                 :  and loads all libs in specified order
     148                 : */
     149                 : 
     150               0 : static void LoadExtraSharedLibs()
     151                 : {
     152                 :     // check out if user's prefs.js has libs name
     153                 :     nsresult res;
     154               0 :     nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &res));
     155               0 :     if (NS_SUCCEEDED(res) && (prefs != nsnull)) {
     156               0 :         char *sonameList = NULL;
     157               0 :         bool prefSonameListIsSet = true;
     158               0 :         res = prefs->GetCharPref(PREF_PLUGINS_SONAME, &sonameList);
     159               0 :         if (!sonameList) {
     160                 :             // pref is not set, lets use hardcoded list
     161               0 :             prefSonameListIsSet = false;
     162               0 :             sonameList = PL_strdup(DEFAULT_EXTRA_LIBS_LIST);
     163                 :         }
     164               0 :         if (sonameList) {
     165               0 :             char *arrayOfLibs[PLUGIN_MAX_NUMBER_OF_EXTRA_LIBS] = {0};
     166               0 :             int numOfLibs = 0;
     167                 :             char *nextToken;
     168               0 :             char *p = nsCRT::strtok(sonameList,":",&nextToken);
     169               0 :             if (p) {
     170               0 :                 while (p && numOfLibs < PLUGIN_MAX_NUMBER_OF_EXTRA_LIBS) {
     171               0 :                     arrayOfLibs[numOfLibs++] = p;
     172               0 :                     p = nsCRT::strtok(nextToken,":",&nextToken);
     173                 :                 }
     174                 :             } else // there is just one lib
     175               0 :                 arrayOfLibs[numOfLibs++] = sonameList;
     176                 : 
     177               0 :             char sonameListToSave[PLUGIN_MAX_LEN_OF_TMP_ARR] = "";
     178               0 :             for (int i=0; i<numOfLibs; i++) {
     179                 :                 // trim out head/tail white spaces (just in case)
     180               0 :                 bool head = true;
     181               0 :                 p = arrayOfLibs[i];
     182               0 :                 while (*p) {
     183               0 :                     if (*p == ' ' || *p == '\t') {
     184               0 :                         if (head) {
     185               0 :                             arrayOfLibs[i] = ++p;
     186                 :                         } else {
     187               0 :                             *p = 0;
     188                 :                         }
     189                 :                     } else {
     190               0 :                         head = false;
     191               0 :                         p++;
     192                 :                     }
     193                 :                 }
     194               0 :                 if (!arrayOfLibs[i][0]) {
     195               0 :                     continue; // null string
     196                 :                 }
     197               0 :                 bool tryToGetSoname = true;
     198               0 :                 if (PL_strchr(arrayOfLibs[i], '/')) {
     199                 :                     //assuming it's real name, try to stat it
     200                 :                     struct stat st;
     201               0 :                     if (stat((const char*) arrayOfLibs[i], &st)) {
     202                 :                         //get just a file name
     203               0 :                         arrayOfLibs[i] = PL_strrchr(arrayOfLibs[i], '/') + 1;
     204                 :                     } else
     205               0 :                         tryToGetSoname = false;
     206                 :                 }
     207               0 :                 char *soname = NULL;
     208               0 :                 if (LoadExtraSharedLib(arrayOfLibs[i], &soname, tryToGetSoname)) {
     209                 :                     //construct soname's list to save in prefs
     210               0 :                     p = soname ? soname : arrayOfLibs[i];
     211                 :                     int n = PLUGIN_MAX_LEN_OF_TMP_ARR -
     212               0 :                         (PL_strlen(sonameListToSave) + PL_strlen(p));
     213               0 :                     if (n > 0) {
     214               0 :                         PL_strcat(sonameListToSave, p);
     215               0 :                         PL_strcat(sonameListToSave,":");
     216                 :                     }
     217               0 :                     if (soname) {
     218               0 :                         PL_strfree(soname); // it's from strdup
     219                 :                     }
     220               0 :                     if (numOfLibs > 1)
     221               0 :                         arrayOfLibs[i][PL_strlen(arrayOfLibs[i])] = ':'; //restore ":" in sonameList
     222                 :                 }
     223                 :             }
     224                 : 
     225                 :             // Check whether sonameListToSave is a empty String, Bug: 329205
     226               0 :             if (sonameListToSave[0]) 
     227               0 :                 for (p = &sonameListToSave[PL_strlen(sonameListToSave) - 1]; *p == ':'; p--)
     228               0 :                     *p = 0; //delete tail ":" delimiters
     229                 : 
     230               0 :             if (!prefSonameListIsSet || PL_strcmp(sonameList, sonameListToSave)) {
     231                 :                 // if user specified some bogus soname I overwrite it here,
     232                 :                 // otherwise it'll decrease performance by calling popen() in SearchForSoname
     233                 :                 // every time for each bogus name
     234               0 :                 prefs->SetCharPref(PREF_PLUGINS_SONAME, (const char *)sonameListToSave);
     235                 :             }
     236               0 :             PL_strfree(sonameList);
     237                 :         }
     238                 :     }
     239               0 : }
     240                 : #endif //MOZ_WIDGET_GTK2
     241                 : 
     242                 : /* nsPluginsDir implementation */
     243                 : 
     244             173 : bool nsPluginsDir::IsPluginFile(nsIFile* file)
     245                 : {
     246             346 :     nsCAutoString filename;
     247             173 :     if (NS_FAILED(file->GetNativeLeafName(filename)))
     248               0 :         return false;
     249                 : 
     250                 : #ifdef ANDROID
     251                 :     // It appears that if you load
     252                 :     // 'libstagefright_honeycomb.so' on froyo, or
     253                 :     // 'libstagefright_froyo.so' on honeycomb, we will abort.
     254                 :     // Since these are just helper libs, we can ignore.
     255                 :     const char *cFile = filename.get();
     256                 :     if (strstr(cFile, "libstagefright") != NULL)
     257                 :         return false;
     258                 : #endif
     259                 : 
     260             346 :     NS_NAMED_LITERAL_CSTRING(dllSuffix, LOCAL_PLUGIN_DLL_SUFFIX);
     261             346 :     if (filename.Length() > dllSuffix.Length() &&
     262             173 :         StringEndsWith(filename, dllSuffix))
     263             173 :         return true;
     264                 :     
     265                 : #ifdef LOCAL_PLUGIN_DLL_ALT_SUFFIX
     266                 :     NS_NAMED_LITERAL_CSTRING(dllAltSuffix, LOCAL_PLUGIN_DLL_ALT_SUFFIX);
     267                 :     if (filename.Length() > dllAltSuffix.Length() &&
     268                 :         StringEndsWith(filename, dllAltSuffix))
     269                 :         return true;
     270                 : #endif
     271               0 :     return false;
     272                 : }
     273                 : 
     274                 : /* nsPluginFile implementation */
     275                 : 
     276             173 : nsPluginFile::nsPluginFile(nsIFile* file)
     277             173 : : mPlugin(file)
     278                 : {
     279             173 : }
     280                 : 
     281             173 : nsPluginFile::~nsPluginFile()
     282                 : {
     283             346 : }
     284                 : 
     285             173 : nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary)
     286                 : {
     287                 :     PRLibSpec libSpec;
     288             173 :     libSpec.type = PR_LibSpec_Pathname;
     289             173 :     bool exists = false;
     290             173 :     mPlugin->Exists(&exists);
     291             173 :     if (!exists)
     292               0 :         return NS_ERROR_FILE_NOT_FOUND;
     293                 : 
     294                 :     nsresult rv;
     295             346 :     nsCAutoString path;
     296             173 :     rv = mPlugin->GetNativePath(path);
     297             173 :     if (NS_FAILED(rv))
     298               0 :         return rv;
     299                 : 
     300             173 :     libSpec.value.pathname = path.get();
     301                 : 
     302                 : #if defined(MOZ_WIDGET_GTK2)
     303                 : 
     304                 :     // Normally, Mozilla isn't linked against libXt and libXext
     305                 :     // since it's a Gtk/Gdk application.  On the other hand,
     306                 :     // legacy plug-ins expect the libXt and libXext symbols
     307                 :     // to already exist in the global name space.  This plug-in
     308                 :     // wrapper is linked against libXt and libXext, but since
     309                 :     // we never call on any of these libraries, plug-ins still
     310                 :     // fail to resolve Xt symbols when trying to do a dlopen
     311                 :     // at runtime.  Explicitly opening Xt/Xext into the global
     312                 :     // namespace before attempting to load the plug-in seems to
     313                 :     // work fine.
     314                 : 
     315                 : 
     316                 : #if defined(SOLARIS) || defined(HPUX)
     317                 :     // Acrobat/libXm: Lazy resolving might cause crash later (bug 211587)
     318                 :     *outLibrary = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW);
     319                 :     pLibrary = *outLibrary;
     320                 : #else
     321                 :     // Some dlopen() doesn't recover from a failed PR_LD_NOW (bug 223744)
     322             173 :     *outLibrary = PR_LoadLibraryWithFlags(libSpec, 0);
     323             173 :     pLibrary = *outLibrary;
     324                 : #endif
     325             173 :     if (!pLibrary) {
     326               0 :         LoadExtraSharedLibs();
     327                 :         // try reload plugin once more
     328               0 :         *outLibrary = PR_LoadLibraryWithFlags(libSpec, 0);
     329               0 :         pLibrary = *outLibrary;
     330               0 :         if (!pLibrary) {
     331               0 :             DisplayPR_LoadLibraryErrorMessage(libSpec.value.pathname);
     332               0 :             return NS_ERROR_FAILURE;
     333                 :         }
     334                 :     }
     335                 : #else
     336                 :     *outLibrary = PR_LoadLibraryWithFlags(libSpec, 0);
     337                 :     pLibrary = *outLibrary;
     338                 : #endif  // MOZ_WIDGET_GTK2
     339                 : 
     340                 : #ifdef NS_DEBUG
     341                 :     printf("LoadPlugin() %s returned %lx\n", 
     342             173 :            libSpec.value.pathname, (unsigned long)pLibrary);
     343                 : #endif
     344                 :     
     345             173 :     return NS_OK;
     346                 : }
     347                 : 
     348             173 : nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info, PRLibrary **outLibrary)
     349                 : {
     350             173 :     *outLibrary = nsnull;
     351                 : 
     352             173 :     info.fVersion = nsnull;
     353                 : 
     354                 :     // Sadly we have to load the library for this to work.
     355             173 :     nsresult rv = LoadPlugin(outLibrary);
     356             173 :     if (NS_FAILED(rv))
     357               0 :         return rv;
     358                 :   
     359                 :     const char* (*npGetPluginVersion)() =
     360             173 :         (const char* (*)()) PR_FindFunctionSymbol(pLibrary, "NP_GetPluginVersion");
     361             173 :     if (npGetPluginVersion) {
     362             173 :         info.fVersion = PL_strdup(npGetPluginVersion());
     363                 :     }
     364                 : 
     365                 :     const char* (*npGetMIMEDescription)() =
     366             173 :         (const char* (*)()) PR_FindFunctionSymbol(pLibrary, "NP_GetMIMEDescription");
     367             173 :     if (!npGetMIMEDescription) {
     368               0 :         return NS_ERROR_FAILURE;
     369                 :     }
     370                 : 
     371             173 :     const char* mimedescr = npGetMIMEDescription();
     372             173 :     if (!mimedescr) {
     373               0 :         return NS_ERROR_FAILURE;
     374                 :     }
     375                 : 
     376             173 :     rv = ParsePluginMimeDescription(mimedescr, info);
     377             173 :     if (NS_FAILED(rv)) {
     378               0 :         return rv;
     379                 :     }
     380                 : 
     381             346 :     nsCAutoString path;
     382             173 :     if (NS_FAILED(rv = mPlugin->GetNativePath(path)))
     383               0 :         return rv;
     384             173 :     info.fFullPath = PL_strdup(path.get());
     385                 : 
     386             346 :     nsCAutoString fileName;
     387             173 :     if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName)))
     388               0 :         return rv;
     389             173 :     info.fFileName = PL_strdup(fileName.get());
     390                 : 
     391             173 :     NP_GetValueFunc npGetValue = (NP_GetValueFunc)PR_FindFunctionSymbol(pLibrary, "NP_GetValue");
     392             173 :     if (!npGetValue) {
     393               0 :         return NS_ERROR_FAILURE;
     394                 :     }
     395                 : 
     396             173 :     const char *name = NULL;
     397             173 :     npGetValue(NULL, NPPVpluginNameString, &name);
     398             173 :     if (name) {
     399             173 :         info.fName = PL_strdup(name);
     400                 :     }
     401                 :     else {
     402               0 :         info.fName = PL_strdup(fileName.get());
     403                 :     }
     404                 : 
     405             173 :     const char *description = NULL;
     406             173 :     npGetValue(NULL, NPPVpluginDescriptionString, &description);
     407             173 :     if (description) {
     408             173 :         info.fDescription = PL_strdup(description);
     409                 :     }
     410                 :     else {
     411               0 :         info.fDescription = PL_strdup("");
     412                 :     }
     413                 : 
     414             173 :     return NS_OK;
     415                 : }
     416                 : 
     417             173 : nsresult nsPluginFile::FreePluginInfo(nsPluginInfo& info)
     418                 : {
     419             173 :     if (info.fName != nsnull)
     420             173 :         PL_strfree(info.fName);
     421                 : 
     422             173 :     if (info.fDescription != nsnull)
     423             173 :         PL_strfree(info.fDescription);
     424                 : 
     425             346 :     for (PRUint32 i = 0; i < info.fVariantCount; i++) {
     426             173 :         if (info.fMimeTypeArray[i] != nsnull)
     427             173 :             PL_strfree(info.fMimeTypeArray[i]);
     428                 : 
     429             173 :         if (info.fMimeDescriptionArray[i] != nsnull)
     430             173 :             PL_strfree(info.fMimeDescriptionArray[i]);
     431                 : 
     432             173 :         if (info.fExtensionArray[i] != nsnull)
     433             173 :             PL_strfree(info.fExtensionArray[i]);
     434                 :     }
     435                 : 
     436             173 :     PR_FREEIF(info.fMimeTypeArray);
     437             173 :     PR_FREEIF(info.fMimeDescriptionArray);
     438             173 :     PR_FREEIF(info.fExtensionArray);
     439                 : 
     440             173 :     if (info.fFullPath != nsnull)
     441             173 :         PL_strfree(info.fFullPath);
     442                 : 
     443             173 :     if (info.fFileName != nsnull)
     444             173 :         PL_strfree(info.fFileName);
     445                 : 
     446             173 :     if (info.fVersion != nsnull)
     447             173 :         PL_strfree(info.fVersion);
     448                 : 
     449             173 :     return NS_OK;
     450                 : }

Generated by: LCOV version 1.7