mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 13:58:49 +00:00
6de8a0f12d
Compared with what Pale Moon had for Solaris originally, this is mostly the same zero point I started patching from, but I've made the following changes here after reviewing all this initial code I never looked at closely before. 1. In package-manifest.in for both Basilisk and Pale Moon, I've made the SPARC code for libfreebl not interefere with the x86 code, use the proper build flags, and also updated it to allow a SPARC64 build which is more likely to be used than the 32-bit SPARC code we had there. 2. See Mozilla bug #832272 and the old rules.mk patch from around Firefox 30 in oracle/solaris-userland. I believe they screwed up NSINSTALL on Solaris when they were trying to streamline the NSS buildsystem, because they started having unexplained issues with it around that time after Firefox 22 that they never properly resolved until Mozilla began building NSS with gyp files. I'm actually not even sure how relevant the thing they broke actually is to Solaris at this point, bug 665509 is so old it predates Firefox itself and goes back to the Mozilla suite days. I believe $(INSTALL) -t was wrong, and they meant $(NSINSTALL) -t because that makes more sense and is closer to what was there originally. It's what they have for WINNT, and it's possible a fix more like that could serve for Solaris as well. Alternatively, we could get rid of all these half-broken Makefiles and start building NSS with gyp files like Mozilla did. 3. I've completely cut out support for the Sun compiler and taken into account the reality that everyone builds Firefox (and therefore its forks) with GCC now on Solaris. This alone helped clean up a lot of the uglier parts of the code. 4. I've updated all remaining SOLARIS build flags to the newer XP_SOLARIS, because the SOLARIS flag is no longer set when building Solaris. 5. I've confirmed the workaround in gtxFontconfigFonts.cpp is no longer necessary. The Solaris people got impatient about implementing a half-baked patch for a fontconfig feature that wasn't ready yet back in 2009, and somehow convinced Mozilla to patch their software to work around it when really they should have just fixed or removed their broken fontconfig patch. The feature they wanted has since been implemented properly, and no version of Solaris still uses the broken patch that required this fix. If anyone had ever properly audited this code, it would have been removed a long time ago.
412 lines
13 KiB
C++
412 lines
13 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nsNPAPIPlugin.h"
|
|
#include "nsNPAPIPluginInstance.h"
|
|
#include "nsIMemory.h"
|
|
#include "nsPluginsDir.h"
|
|
#include "nsPluginsDirUtils.h"
|
|
#include "prmem.h"
|
|
#include "prenv.h"
|
|
#include "prerror.h"
|
|
#include "prio.h"
|
|
#include <sys/stat.h>
|
|
#include "nsString.h"
|
|
#include "nsIFile.h"
|
|
#include "nsIPrefBranch.h"
|
|
#include "nsIPrefService.h"
|
|
|
|
#define LOCAL_PLUGIN_DLL_SUFFIX ".so"
|
|
#if defined(XP_SOLARIS)
|
|
#define DEFAULT_X11_PATH "/usr/openwin/lib"
|
|
#elif defined(LINUX)
|
|
#define DEFAULT_X11_PATH "/usr/X11R6/lib/"
|
|
#elif defined(__APPLE__)
|
|
#define DEFAULT_X11_PATH "/usr/X11R6/lib"
|
|
#undef LOCAL_PLUGIN_DLL_SUFFIX
|
|
#define LOCAL_PLUGIN_DLL_SUFFIX ".dylib"
|
|
#define LOCAL_PLUGIN_DLL_ALT_SUFFIX ".so"
|
|
#else
|
|
#define DEFAULT_X11_PATH ""
|
|
#endif
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
|
|
|
#define PLUGIN_MAX_LEN_OF_TMP_ARR 512
|
|
|
|
static void DisplayPR_LoadLibraryErrorMessage(const char *libName)
|
|
{
|
|
char errorMsg[PLUGIN_MAX_LEN_OF_TMP_ARR] = "Cannot get error from NSPR.";
|
|
if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
|
|
PR_GetErrorText(errorMsg);
|
|
|
|
fprintf(stderr, "LoadPlugin: failed to initialize shared library %s [%s]\n",
|
|
libName, errorMsg);
|
|
}
|
|
|
|
static void SearchForSoname(const char* name, char** soname)
|
|
{
|
|
if (!(name && soname))
|
|
return;
|
|
PRDir *fdDir = PR_OpenDir(DEFAULT_X11_PATH);
|
|
if (!fdDir)
|
|
return;
|
|
|
|
int n = strlen(name);
|
|
PRDirEntry *dirEntry;
|
|
while ((dirEntry = PR_ReadDir(fdDir, PR_SKIP_BOTH))) {
|
|
if (!PL_strncmp(dirEntry->name, name, n)) {
|
|
if (dirEntry->name[n] == '.' && dirEntry->name[n+1] && !dirEntry->name[n+2]) {
|
|
// name.N, wild guess this is what we need
|
|
char out[PLUGIN_MAX_LEN_OF_TMP_ARR] = DEFAULT_X11_PATH;
|
|
PL_strcat(out, dirEntry->name);
|
|
*soname = PL_strdup(out);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
PR_CloseDir(fdDir);
|
|
}
|
|
|
|
static bool LoadExtraSharedLib(const char *name, char **soname, bool tryToGetSoname)
|
|
{
|
|
bool ret = true;
|
|
PRLibSpec tempSpec;
|
|
PRLibrary *handle;
|
|
tempSpec.type = PR_LibSpec_Pathname;
|
|
tempSpec.value.pathname = name;
|
|
handle = PR_LoadLibraryWithFlags(tempSpec, PR_LD_NOW|PR_LD_GLOBAL);
|
|
if (!handle) {
|
|
ret = false;
|
|
DisplayPR_LoadLibraryErrorMessage(name);
|
|
if (tryToGetSoname) {
|
|
SearchForSoname(name, soname);
|
|
if (*soname) {
|
|
ret = LoadExtraSharedLib((const char *) *soname, nullptr, false);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#define PLUGIN_MAX_NUMBER_OF_EXTRA_LIBS 32
|
|
#define PREF_PLUGINS_SONAME "plugin.soname.list"
|
|
#if defined (XP_SOLARIS)
|
|
#define DEFAULT_EXTRA_LIBS_LIST "libXt" LOCAL_PLUGIN_DLL_SUFFIX ":libXext" LOCAL_PLUGIN_DLL_SUFFIX ":libXm" LOCAL_PLUGIN_DLL_SUFFIX
|
|
#else
|
|
#define DEFAULT_EXTRA_LIBS_LIST "libXt" LOCAL_PLUGIN_DLL_SUFFIX ":libXext" LOCAL_PLUGIN_DLL_SUFFIX
|
|
#endif
|
|
/*
|
|
this function looks for
|
|
user_pref("plugin.soname.list", "/usr/X11R6/lib/libXt.so.6:libXext.so");
|
|
in user's pref.js
|
|
and loads all libs in specified order
|
|
*/
|
|
|
|
static void LoadExtraSharedLibs()
|
|
{
|
|
// check out if user's prefs.js has libs name
|
|
nsresult res;
|
|
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &res));
|
|
if (NS_SUCCEEDED(res) && (prefs != nullptr)) {
|
|
char *sonameList = nullptr;
|
|
bool prefSonameListIsSet = true;
|
|
res = prefs->GetCharPref(PREF_PLUGINS_SONAME, &sonameList);
|
|
if (!sonameList) {
|
|
// pref is not set, lets use hardcoded list
|
|
prefSonameListIsSet = false;
|
|
sonameList = PL_strdup(DEFAULT_EXTRA_LIBS_LIST);
|
|
}
|
|
if (sonameList) {
|
|
char *arrayOfLibs[PLUGIN_MAX_NUMBER_OF_EXTRA_LIBS] = {0};
|
|
int numOfLibs = 0;
|
|
char *nextToken;
|
|
char *p = nsCRT::strtok(sonameList,":",&nextToken);
|
|
if (p) {
|
|
while (p && numOfLibs < PLUGIN_MAX_NUMBER_OF_EXTRA_LIBS) {
|
|
arrayOfLibs[numOfLibs++] = p;
|
|
p = nsCRT::strtok(nextToken,":",&nextToken);
|
|
}
|
|
} else // there is just one lib
|
|
arrayOfLibs[numOfLibs++] = sonameList;
|
|
|
|
char sonameListToSave[PLUGIN_MAX_LEN_OF_TMP_ARR] = "";
|
|
for (int i=0; i<numOfLibs; i++) {
|
|
// trim out head/tail white spaces (just in case)
|
|
bool head = true;
|
|
p = arrayOfLibs[i];
|
|
while (*p) {
|
|
if (*p == ' ' || *p == '\t') {
|
|
if (head) {
|
|
arrayOfLibs[i] = ++p;
|
|
} else {
|
|
*p = 0;
|
|
}
|
|
} else {
|
|
head = false;
|
|
p++;
|
|
}
|
|
}
|
|
if (!arrayOfLibs[i][0]) {
|
|
continue; // null string
|
|
}
|
|
bool tryToGetSoname = true;
|
|
if (PL_strchr(arrayOfLibs[i], '/')) {
|
|
//assuming it's real name, try to stat it
|
|
struct stat st;
|
|
if (stat((const char*) arrayOfLibs[i], &st)) {
|
|
//get just a file name
|
|
arrayOfLibs[i] = PL_strrchr(arrayOfLibs[i], '/') + 1;
|
|
} else
|
|
tryToGetSoname = false;
|
|
}
|
|
char *soname = nullptr;
|
|
if (LoadExtraSharedLib(arrayOfLibs[i], &soname, tryToGetSoname)) {
|
|
//construct soname's list to save in prefs
|
|
p = soname ? soname : arrayOfLibs[i];
|
|
int n = PLUGIN_MAX_LEN_OF_TMP_ARR -
|
|
(strlen(sonameListToSave) + strlen(p));
|
|
if (n > 0) {
|
|
PL_strcat(sonameListToSave, p);
|
|
PL_strcat(sonameListToSave,":");
|
|
}
|
|
if (soname) {
|
|
PL_strfree(soname); // it's from strdup
|
|
}
|
|
if (numOfLibs > 1)
|
|
arrayOfLibs[i][strlen(arrayOfLibs[i])] = ':'; //restore ":" in sonameList
|
|
}
|
|
}
|
|
|
|
// Check whether sonameListToSave is a empty String, Bug: 329205
|
|
if (sonameListToSave[0])
|
|
for (p = &sonameListToSave[strlen(sonameListToSave) - 1]; *p == ':'; p--)
|
|
*p = 0; //delete tail ":" delimiters
|
|
|
|
if (!prefSonameListIsSet || PL_strcmp(sonameList, sonameListToSave)) {
|
|
// if user specified some bogus soname I overwrite it here,
|
|
// otherwise it'll decrease performance by calling popen() in SearchForSoname
|
|
// every time for each bogus name
|
|
prefs->SetCharPref(PREF_PLUGINS_SONAME, (const char *)sonameListToSave);
|
|
}
|
|
PL_strfree(sonameList);
|
|
}
|
|
}
|
|
}
|
|
#endif //MOZ_WIDGET_GTK == 2
|
|
|
|
/* nsPluginsDir implementation */
|
|
|
|
bool nsPluginsDir::IsPluginFile(nsIFile* file)
|
|
{
|
|
nsAutoCString filename;
|
|
if (NS_FAILED(file->GetNativeLeafName(filename)))
|
|
return false;
|
|
|
|
#ifdef ANDROID
|
|
// It appears that if you load
|
|
// 'libstagefright_honeycomb.so' on froyo, or
|
|
// 'libstagefright_froyo.so' on honeycomb, we will abort.
|
|
// Since these are just helper libs, we can ignore.
|
|
const char *cFile = filename.get();
|
|
if (strstr(cFile, "libstagefright") != nullptr)
|
|
return false;
|
|
#endif
|
|
|
|
NS_NAMED_LITERAL_CSTRING(dllSuffix, LOCAL_PLUGIN_DLL_SUFFIX);
|
|
if (filename.Length() > dllSuffix.Length() &&
|
|
StringEndsWith(filename, dllSuffix))
|
|
return true;
|
|
|
|
#ifdef LOCAL_PLUGIN_DLL_ALT_SUFFIX
|
|
NS_NAMED_LITERAL_CSTRING(dllAltSuffix, LOCAL_PLUGIN_DLL_ALT_SUFFIX);
|
|
if (filename.Length() > dllAltSuffix.Length() &&
|
|
StringEndsWith(filename, dllAltSuffix))
|
|
return true;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
/* nsPluginFile implementation */
|
|
|
|
nsPluginFile::nsPluginFile(nsIFile* file)
|
|
: mPlugin(file)
|
|
{
|
|
}
|
|
|
|
nsPluginFile::~nsPluginFile()
|
|
{
|
|
}
|
|
|
|
nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary)
|
|
{
|
|
PRLibSpec libSpec;
|
|
libSpec.type = PR_LibSpec_Pathname;
|
|
bool exists = false;
|
|
mPlugin->Exists(&exists);
|
|
if (!exists)
|
|
return NS_ERROR_FILE_NOT_FOUND;
|
|
|
|
nsresult rv;
|
|
nsAutoCString path;
|
|
rv = mPlugin->GetNativePath(path);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
libSpec.value.pathname = path.get();
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
|
|
|
// Normally, Mozilla isn't linked against libXt and libXext
|
|
// since it's a Gtk/Gdk application. On the other hand,
|
|
// legacy plug-ins expect the libXt and libXext symbols
|
|
// to already exist in the global name space. This plug-in
|
|
// wrapper is linked against libXt and libXext, but since
|
|
// we never call on any of these libraries, plug-ins still
|
|
// fail to resolve Xt symbols when trying to do a dlopen
|
|
// at runtime. Explicitly opening Xt/Xext into the global
|
|
// namespace before attempting to load the plug-in seems to
|
|
// work fine.
|
|
#if defined(XP_SOLARIS)
|
|
// Acrobat/libXm: Lazy resolving might cause crash later (bug 211587)
|
|
*outLibrary = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW);
|
|
pLibrary = *outLibrary;
|
|
#else
|
|
// Some dlopen() doesn't recover from a failed PR_LD_NOW (bug 223744)
|
|
*outLibrary = PR_LoadLibraryWithFlags(libSpec, 0);
|
|
pLibrary = *outLibrary;
|
|
#endif
|
|
if (!pLibrary) {
|
|
LoadExtraSharedLibs();
|
|
// try reload plugin once more
|
|
*outLibrary = PR_LoadLibraryWithFlags(libSpec, 0);
|
|
pLibrary = *outLibrary;
|
|
if (!pLibrary) {
|
|
DisplayPR_LoadLibraryErrorMessage(libSpec.value.pathname);
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
}
|
|
#else
|
|
*outLibrary = PR_LoadLibraryWithFlags(libSpec, 0);
|
|
pLibrary = *outLibrary;
|
|
#endif // MOZ_WIDGET_GTK == 2
|
|
|
|
#ifdef DEBUG
|
|
printf("LoadPlugin() %s returned %lx\n",
|
|
libSpec.value.pathname, (unsigned long)pLibrary);
|
|
#endif
|
|
|
|
if (!pLibrary) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info, PRLibrary **outLibrary)
|
|
{
|
|
*outLibrary = nullptr;
|
|
|
|
info.fVersion = nullptr;
|
|
|
|
// Sadly we have to load the library for this to work.
|
|
nsresult rv = LoadPlugin(outLibrary);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
const char* (*npGetPluginVersion)() =
|
|
(const char* (*)()) PR_FindFunctionSymbol(pLibrary, "NP_GetPluginVersion");
|
|
if (npGetPluginVersion) {
|
|
info.fVersion = PL_strdup(npGetPluginVersion());
|
|
}
|
|
|
|
const char* (*npGetMIMEDescription)() =
|
|
(const char* (*)()) PR_FindFunctionSymbol(pLibrary, "NP_GetMIMEDescription");
|
|
if (!npGetMIMEDescription) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
const char* mimedescr = npGetMIMEDescription();
|
|
if (!mimedescr) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
rv = ParsePluginMimeDescription(mimedescr, info);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsAutoCString path;
|
|
if (NS_FAILED(rv = mPlugin->GetNativePath(path)))
|
|
return rv;
|
|
info.fFullPath = PL_strdup(path.get());
|
|
|
|
nsAutoCString fileName;
|
|
if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName)))
|
|
return rv;
|
|
info.fFileName = PL_strdup(fileName.get());
|
|
|
|
NP_GetValueFunc npGetValue = (NP_GetValueFunc)PR_FindFunctionSymbol(pLibrary, "NP_GetValue");
|
|
if (!npGetValue) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
const char *name = nullptr;
|
|
npGetValue(nullptr, NPPVpluginNameString, &name);
|
|
if (name) {
|
|
info.fName = PL_strdup(name);
|
|
}
|
|
else {
|
|
info.fName = PL_strdup(fileName.get());
|
|
}
|
|
|
|
const char *description = nullptr;
|
|
npGetValue(nullptr, NPPVpluginDescriptionString, &description);
|
|
if (description) {
|
|
info.fDescription = PL_strdup(description);
|
|
}
|
|
else {
|
|
info.fDescription = PL_strdup("");
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsPluginFile::FreePluginInfo(nsPluginInfo& info)
|
|
{
|
|
if (info.fName != nullptr)
|
|
PL_strfree(info.fName);
|
|
|
|
if (info.fDescription != nullptr)
|
|
PL_strfree(info.fDescription);
|
|
|
|
for (uint32_t i = 0; i < info.fVariantCount; i++) {
|
|
if (info.fMimeTypeArray[i] != nullptr)
|
|
PL_strfree(info.fMimeTypeArray[i]);
|
|
|
|
if (info.fMimeDescriptionArray[i] != nullptr)
|
|
PL_strfree(info.fMimeDescriptionArray[i]);
|
|
|
|
if (info.fExtensionArray[i] != nullptr)
|
|
PL_strfree(info.fExtensionArray[i]);
|
|
}
|
|
|
|
PR_FREEIF(info.fMimeTypeArray);
|
|
PR_FREEIF(info.fMimeDescriptionArray);
|
|
PR_FREEIF(info.fExtensionArray);
|
|
|
|
if (info.fFullPath != nullptr)
|
|
PL_strfree(info.fFullPath);
|
|
|
|
if (info.fFileName != nullptr)
|
|
PL_strfree(info.fFileName);
|
|
|
|
if (info.fVersion != nullptr)
|
|
PL_strfree(info.fVersion);
|
|
|
|
return NS_OK;
|
|
}
|