LCOV - code coverage report
Current view: top level - dom/plugins/base - nsPluginsDirUnix.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 1 98 1.0 %
Date: 2017-07-14 16:53:18 Functions: 2 9 22.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13