LCOV - app.info - dom/plugins/base/nsPluginsDirUnix.cpp

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-04-21 | 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