mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Separate plugin tag code from the plugin host. b=533371 r=jst
This commit is contained in:
parent
0ce7b2a2ba
commit
a2cdef8b23
@ -57,6 +57,7 @@ CPPSRCS = \
|
||||
nsPluginHost.cpp \
|
||||
nsPluginModule.cpp \
|
||||
nsJSNPRuntime.cpp \
|
||||
nsPluginTags.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH), BeOS)
|
||||
|
@ -92,7 +92,6 @@
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsXPCOMCID.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
|
||||
// for the dialog
|
||||
@ -226,8 +225,6 @@ PRLogModuleInfo* nsPluginLogging::gPluginLog = nsnull;
|
||||
|
||||
#define MAGIC_REQUEST_CONTEXT 0x01020304
|
||||
|
||||
nsresult PostPluginUnloadEvent(PRLibrary * aLibrary);
|
||||
|
||||
static nsPluginInstanceTagList *gActivePluginList;
|
||||
|
||||
#ifdef CALL_SAFETY_ON
|
||||
@ -309,619 +306,6 @@ NS_IMETHODIMP nsPluginDocReframeEvent::Run() {
|
||||
return mDocs->Clear();
|
||||
}
|
||||
|
||||
nsPluginInstanceTag::nsPluginInstanceTag(nsPluginTag* aPluginTag,
|
||||
nsIPluginInstance* aInstance,
|
||||
const char * url,
|
||||
PRBool aDefaultPlugin)
|
||||
{
|
||||
mNext = nsnull;
|
||||
mPluginTag = aPluginTag;
|
||||
|
||||
mURL = PL_strdup(url);
|
||||
mInstance = aInstance;
|
||||
if (aInstance)
|
||||
NS_ADDREF(aInstance);
|
||||
mXPConnected = PR_FALSE;
|
||||
mDefaultPlugin = aDefaultPlugin;
|
||||
mStopped = PR_FALSE;
|
||||
mllStopTime = LL_ZERO;
|
||||
}
|
||||
|
||||
nsPluginInstanceTag::~nsPluginInstanceTag()
|
||||
{
|
||||
mPluginTag = nsnull;
|
||||
if (mInstance) {
|
||||
nsCOMPtr<nsIPluginInstanceOwner> owner;
|
||||
mInstance->GetOwner(getter_AddRefs(owner));
|
||||
if (owner)
|
||||
owner->SetInstance(nsnull);
|
||||
mInstance->InvalidateOwner();
|
||||
|
||||
NS_RELEASE(mInstance);
|
||||
}
|
||||
PL_strfree(mURL);
|
||||
}
|
||||
|
||||
void nsPluginInstanceTag::setStopped(PRBool stopped)
|
||||
{
|
||||
mStopped = stopped;
|
||||
if (mStopped) // plugin instance is told to stop
|
||||
mllStopTime = PR_Now();
|
||||
else
|
||||
mllStopTime = LL_ZERO;
|
||||
}
|
||||
|
||||
nsPluginInstanceTagList::nsPluginInstanceTagList()
|
||||
{
|
||||
mFirst = nsnull;
|
||||
mLast = nsnull;
|
||||
mCount = 0;
|
||||
}
|
||||
|
||||
nsPluginInstanceTagList::~nsPluginInstanceTagList()
|
||||
{
|
||||
if (!mFirst)
|
||||
return;
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void nsPluginInstanceTagList::shutdown()
|
||||
{
|
||||
if (!mFirst)
|
||||
return;
|
||||
|
||||
for (nsPluginInstanceTag * plugin = mFirst; plugin != nsnull;) {
|
||||
nsPluginInstanceTag * next = plugin->mNext;
|
||||
remove(plugin);
|
||||
plugin = next;
|
||||
}
|
||||
mFirst = nsnull;
|
||||
mLast = nsnull;
|
||||
}
|
||||
|
||||
PRInt32 nsPluginInstanceTagList::add(nsPluginInstanceTag * plugin)
|
||||
{
|
||||
if (!mFirst) {
|
||||
mFirst = plugin;
|
||||
mLast = plugin;
|
||||
mFirst->mNext = nsnull;
|
||||
}
|
||||
else {
|
||||
mLast->mNext = plugin;
|
||||
mLast = plugin;
|
||||
}
|
||||
mLast->mNext = nsnull;
|
||||
mCount++;
|
||||
return mCount;
|
||||
}
|
||||
|
||||
PRBool nsPluginInstanceTagList::IsLastInstance(nsPluginInstanceTag * plugin)
|
||||
{
|
||||
if (!plugin)
|
||||
return PR_FALSE;
|
||||
|
||||
if (!plugin->mPluginTag)
|
||||
return PR_FALSE;
|
||||
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if ((p->mPluginTag == plugin->mPluginTag) && (p != plugin))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool nsPluginInstanceTagList::remove(nsPluginInstanceTag * plugin)
|
||||
{
|
||||
if (!mFirst)
|
||||
return PR_FALSE;
|
||||
|
||||
nsPluginInstanceTag * prev = nsnull;
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (p == plugin) {
|
||||
PRBool lastInstance = IsLastInstance(p);
|
||||
|
||||
if (p == mFirst)
|
||||
mFirst = p->mNext;
|
||||
else
|
||||
prev->mNext = p->mNext;
|
||||
|
||||
if (prev && !prev->mNext)
|
||||
mLast = prev;
|
||||
|
||||
if (lastInstance) {
|
||||
nsRefPtr<nsPluginTag> pluginTag = p->mPluginTag;
|
||||
|
||||
delete p;
|
||||
|
||||
if (pluginTag) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool unloadPluginsASAP = PR_FALSE;
|
||||
rv = pref->GetBoolPref("plugins.unloadASAP", &unloadPluginsASAP);
|
||||
if (NS_SUCCEEDED(rv) && unloadPluginsASAP)
|
||||
pluginTag->TryUnloadPlugin();
|
||||
} else {
|
||||
NS_ASSERTION(pluginTag, "pluginTag was not set, plugin not shutdown");
|
||||
}
|
||||
} else {
|
||||
delete p;
|
||||
}
|
||||
|
||||
mCount--;
|
||||
return PR_TRUE;
|
||||
}
|
||||
prev = p;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// This method terminates all running instances of plugins and collects their
|
||||
// documents to be returned through an array. This method is used
|
||||
// when we are shutting down or when a plugins.refresh(1) happens.
|
||||
// If aPluginTag is given, then only that plugin is terminated
|
||||
void nsPluginInstanceTagList::stopRunning(nsISupportsArray* aReloadDocs,
|
||||
nsPluginTag* aPluginTag)
|
||||
{
|
||||
if (!mFirst)
|
||||
return;
|
||||
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (!p->mStopped && p->mInstance &&
|
||||
(!aPluginTag || aPluginTag == p->mPluginTag)) {
|
||||
p->mInstance->SetWindow(nsnull);
|
||||
p->mInstance->Stop();
|
||||
p->setStopped(PR_TRUE);
|
||||
|
||||
// If we've been passed an array to return, lets collect all our documents,
|
||||
// removing duplicates. These will be reframed (embedded) or reloaded (full-page) later
|
||||
// to kickstart our instances.
|
||||
if (aReloadDocs && p->mInstance) {
|
||||
nsCOMPtr<nsIPluginInstanceOwner> owner;
|
||||
p->mInstance->GetOwner(getter_AddRefs(owner));
|
||||
if (owner) {
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
owner->GetDocument(getter_AddRefs(doc));
|
||||
if (doc && aReloadDocs->IndexOf(doc) == -1) // don't allow for duplicates
|
||||
aReloadDocs->AppendElement(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsPluginInstanceTagList::removeAllStopped()
|
||||
{
|
||||
if (!mFirst)
|
||||
return;
|
||||
|
||||
nsPluginInstanceTag * next = nsnull;
|
||||
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull;) {
|
||||
next = p->mNext;
|
||||
|
||||
if (p->mStopped)
|
||||
remove(p);
|
||||
|
||||
p = next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsPluginInstanceTag * nsPluginInstanceTagList::find(nsIPluginInstance* instance)
|
||||
{
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (p->mInstance == instance)
|
||||
return p;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsPluginInstanceTag * nsPluginInstanceTagList::find(const char * mimetype)
|
||||
{
|
||||
PRBool defaultplugin = (PL_strcmp(mimetype, "*") == 0);
|
||||
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
// give it some special treatment for the default plugin first
|
||||
// because we cannot tell the default plugin by asking instance for a mime type
|
||||
if (defaultplugin && p->mDefaultPlugin)
|
||||
return p;
|
||||
|
||||
if (!p->mInstance)
|
||||
continue;
|
||||
|
||||
const char* mt;
|
||||
nsresult rv = p->mInstance->GetMIMEType(&mt);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
if (PL_strcasecmp(mt, mimetype) == 0)
|
||||
return p;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsPluginInstanceTag * nsPluginInstanceTagList::findStopped(const char * url)
|
||||
{
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (!PL_strcmp(url, p->mURL) && p->mStopped)
|
||||
return p;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRUint32 nsPluginInstanceTagList::getStoppedCount()
|
||||
{
|
||||
PRUint32 stoppedCount = 0;
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (p->mStopped)
|
||||
stoppedCount++;
|
||||
}
|
||||
return stoppedCount;
|
||||
}
|
||||
|
||||
nsPluginInstanceTag * nsPluginInstanceTagList::findOldestStopped()
|
||||
{
|
||||
nsPluginInstanceTag * res = nsnull;
|
||||
PRInt64 llTime = LL_MAXINT;
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (!p->mStopped)
|
||||
continue;
|
||||
|
||||
if (LL_CMP(p->mllStopTime, <, llTime)) {
|
||||
llTime = p->mllStopTime;
|
||||
res = p;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline char* new_str(const char* str)
|
||||
{
|
||||
if (str == nsnull)
|
||||
return nsnull;
|
||||
|
||||
char* result = new char[strlen(str) + 1];
|
||||
if (result != nsnull)
|
||||
return strcpy(result, str);
|
||||
return result;
|
||||
}
|
||||
|
||||
nsPluginTag::nsPluginTag(nsPluginTag* aPluginTag)
|
||||
: mPluginHost(nsnull),
|
||||
mName(aPluginTag->mName),
|
||||
mDescription(aPluginTag->mDescription),
|
||||
mVariants(aPluginTag->mVariants),
|
||||
mMimeTypeArray(nsnull),
|
||||
mMimeDescriptionArray(aPluginTag->mMimeDescriptionArray),
|
||||
mExtensionsArray(nsnull),
|
||||
mLibrary(nsnull),
|
||||
mCanUnloadLibrary(PR_TRUE),
|
||||
mXPConnected(PR_FALSE),
|
||||
mIsJavaPlugin(aPluginTag->mIsJavaPlugin),
|
||||
mIsNPRuntimeEnabledJavaPlugin(aPluginTag->mIsNPRuntimeEnabledJavaPlugin),
|
||||
mFileName(aPluginTag->mFileName),
|
||||
mFullPath(aPluginTag->mFullPath),
|
||||
mVersion(aPluginTag->mVersion),
|
||||
mLastModifiedTime(0),
|
||||
mFlags(NS_PLUGIN_FLAG_ENABLED)
|
||||
{
|
||||
if (aPluginTag->mMimeTypeArray != nsnull) {
|
||||
mMimeTypeArray = new char*[mVariants];
|
||||
for (int i = 0; i < mVariants; i++)
|
||||
mMimeTypeArray[i] = new_str(aPluginTag->mMimeTypeArray[i]);
|
||||
}
|
||||
|
||||
if (aPluginTag->mExtensionsArray != nsnull) {
|
||||
mExtensionsArray = new char*[mVariants];
|
||||
for (int i = 0; i < mVariants; i++)
|
||||
mExtensionsArray[i] = new_str(aPluginTag->mExtensionsArray[i]);
|
||||
}
|
||||
}
|
||||
|
||||
nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo)
|
||||
: mPluginHost(nsnull),
|
||||
mName(aPluginInfo->fName),
|
||||
mDescription(aPluginInfo->fDescription),
|
||||
mVariants(aPluginInfo->fVariantCount),
|
||||
mMimeTypeArray(nsnull),
|
||||
mExtensionsArray(nsnull),
|
||||
mLibrary(nsnull),
|
||||
#ifdef XP_MACOSX
|
||||
mCanUnloadLibrary(!aPluginInfo->fBundle),
|
||||
#else
|
||||
mCanUnloadLibrary(PR_TRUE),
|
||||
#endif
|
||||
mXPConnected(PR_FALSE),
|
||||
mIsJavaPlugin(PR_FALSE),
|
||||
mIsNPRuntimeEnabledJavaPlugin(PR_FALSE),
|
||||
mFileName(aPluginInfo->fFileName),
|
||||
mFullPath(aPluginInfo->fFullPath),
|
||||
mVersion(aPluginInfo->fVersion),
|
||||
mLastModifiedTime(0),
|
||||
mFlags(NS_PLUGIN_FLAG_ENABLED)
|
||||
{
|
||||
if (aPluginInfo->fMimeTypeArray != nsnull) {
|
||||
mMimeTypeArray = new char*[mVariants];
|
||||
for (int i = 0; i < mVariants; i++) {
|
||||
if (mIsJavaPlugin && aPluginInfo->fMimeTypeArray[i] &&
|
||||
strcmp(aPluginInfo->fMimeTypeArray[i],
|
||||
"application/x-java-vm-npruntime") == 0) {
|
||||
mIsNPRuntimeEnabledJavaPlugin = PR_TRUE;
|
||||
|
||||
// Stop processing here, any mimetypes after the magic "I'm a
|
||||
// NPRuntime enabled Java plugin" mimetype will be ignored.
|
||||
mVariants = i;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mMimeTypeArray[i] = new_str(aPluginInfo->fMimeTypeArray[i]);
|
||||
if (nsPluginHost::IsJavaMIMEType(mMimeTypeArray[i]))
|
||||
mIsJavaPlugin = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (aPluginInfo->fMimeDescriptionArray != nsnull) {
|
||||
for (int i = 0; i < mVariants; i++) {
|
||||
// we should cut off the list of suffixes which the mime
|
||||
// description string may have, see bug 53895
|
||||
// it is usually in form "some description (*.sf1, *.sf2)"
|
||||
// so we can search for the opening round bracket
|
||||
char cur = '\0';
|
||||
char pre = '\0';
|
||||
char * p = PL_strrchr(aPluginInfo->fMimeDescriptionArray[i], '(');
|
||||
if (p && (p != aPluginInfo->fMimeDescriptionArray[i])) {
|
||||
if ((p - 1) && *(p - 1) == ' ') {
|
||||
pre = *(p - 1);
|
||||
*(p - 1) = '\0';
|
||||
} else {
|
||||
cur = *p;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
}
|
||||
mMimeDescriptionArray.AppendElement(
|
||||
aPluginInfo->fMimeDescriptionArray[i]);
|
||||
// restore the original string
|
||||
if (cur != '\0')
|
||||
*p = cur;
|
||||
if (pre != '\0')
|
||||
*(p - 1) = pre;
|
||||
}
|
||||
} else {
|
||||
mMimeDescriptionArray.SetLength(mVariants);
|
||||
}
|
||||
|
||||
if (aPluginInfo->fExtensionArray != nsnull) {
|
||||
mExtensionsArray = new char*[mVariants];
|
||||
for (int i = 0; i < mVariants; i++)
|
||||
mExtensionsArray[i] = new_str(aPluginInfo->fExtensionArray[i]);
|
||||
}
|
||||
|
||||
EnsureMembersAreUTF8();
|
||||
}
|
||||
|
||||
nsPluginTag::nsPluginTag(const char* aName,
|
||||
const char* aDescription,
|
||||
const char* aFileName,
|
||||
const char* aFullPath,
|
||||
const char* aVersion,
|
||||
const char* const* aMimeTypes,
|
||||
const char* const* aMimeDescriptions,
|
||||
const char* const* aExtensions,
|
||||
PRInt32 aVariants,
|
||||
PRInt64 aLastModifiedTime,
|
||||
PRBool aCanUnload,
|
||||
PRBool aArgsAreUTF8)
|
||||
: mPluginHost(nsnull),
|
||||
mName(aName),
|
||||
mDescription(aDescription),
|
||||
mVariants(aVariants),
|
||||
mMimeTypeArray(nsnull),
|
||||
mExtensionsArray(nsnull),
|
||||
mLibrary(nsnull),
|
||||
mCanUnloadLibrary(aCanUnload),
|
||||
mXPConnected(PR_FALSE),
|
||||
mIsJavaPlugin(PR_FALSE),
|
||||
mIsNPRuntimeEnabledJavaPlugin(PR_FALSE),
|
||||
mFileName(aFileName),
|
||||
mFullPath(aFullPath),
|
||||
mVersion(aVersion),
|
||||
mLastModifiedTime(aLastModifiedTime),
|
||||
mFlags(0) // Caller will read in our flags from cache
|
||||
{
|
||||
if (aVariants) {
|
||||
mMimeTypeArray = new char*[mVariants];
|
||||
mExtensionsArray = new char*[mVariants];
|
||||
|
||||
for (PRInt32 i = 0; i < aVariants; ++i) {
|
||||
if (mIsJavaPlugin && aMimeTypes[i] &&
|
||||
strcmp(aMimeTypes[i], "application/x-java-vm-npruntime") == 0) {
|
||||
mIsNPRuntimeEnabledJavaPlugin = PR_TRUE;
|
||||
|
||||
// Stop processing here, any mimetypes after the magic "I'm a
|
||||
// NPRuntime enabled Java plugin" mimetype will be ignored.
|
||||
mVariants = i;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mMimeTypeArray[i] = new_str(aMimeTypes[i]);
|
||||
mMimeDescriptionArray.AppendElement(aMimeDescriptions[i]);
|
||||
mExtensionsArray[i] = new_str(aExtensions[i]);
|
||||
if (nsPluginHost::IsJavaMIMEType(mMimeTypeArray[i]))
|
||||
mIsJavaPlugin = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aArgsAreUTF8)
|
||||
EnsureMembersAreUTF8();
|
||||
}
|
||||
|
||||
nsPluginTag::~nsPluginTag()
|
||||
{
|
||||
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
|
||||
|
||||
if (mMimeTypeArray) {
|
||||
for (int i = 0; i < mVariants; i++)
|
||||
delete[] mMimeTypeArray[i];
|
||||
|
||||
delete[] (mMimeTypeArray);
|
||||
mMimeTypeArray = nsnull;
|
||||
}
|
||||
|
||||
if (mExtensionsArray) {
|
||||
for (int i = 0; i < mVariants; i++)
|
||||
delete[] mExtensionsArray[i];
|
||||
|
||||
delete[] (mExtensionsArray);
|
||||
mExtensionsArray = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsPluginTag, nsIPluginTag)
|
||||
|
||||
static nsresult ConvertToUTF8(nsIUnicodeDecoder *aUnicodeDecoder,
|
||||
nsAFlatCString& aString)
|
||||
{
|
||||
PRInt32 numberOfBytes = aString.Length();
|
||||
PRInt32 outUnicodeLen;
|
||||
nsAutoString buffer;
|
||||
nsresult rv = aUnicodeDecoder->GetMaxLength(aString.get(), numberOfBytes,
|
||||
&outUnicodeLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!EnsureStringLength(buffer, outUnicodeLen))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = aUnicodeDecoder->Convert(aString.get(), &numberOfBytes,
|
||||
buffer.BeginWriting(), &outUnicodeLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
buffer.SetLength(outUnicodeLen);
|
||||
CopyUTF16toUTF8(buffer, aString);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginTag::EnsureMembersAreUTF8()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIPlatformCharset> pcs =
|
||||
do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIUnicodeDecoder> decoder;
|
||||
nsCOMPtr<nsICharsetConverterManager> ccm =
|
||||
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString charset;
|
||||
rv = pcs->GetCharset(kPlatformCharsetSel_FileName, charset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!charset.LowerCaseEqualsLiteral("utf-8")) {
|
||||
rv = ccm->GetUnicodeDecoderRaw(charset.get(), getter_AddRefs(decoder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ConvertToUTF8(decoder, mFileName);
|
||||
ConvertToUTF8(decoder, mFullPath);
|
||||
}
|
||||
|
||||
// The description of the plug-in and the various MIME type descriptions
|
||||
// should be encoded in the standard plain text file encoding for this system.
|
||||
// XXX should we add kPlatformCharsetSel_PluginResource?
|
||||
rv = pcs->GetCharset(kPlatformCharsetSel_PlainTextInFile, charset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!charset.LowerCaseEqualsLiteral("utf-8")) {
|
||||
rv = ccm->GetUnicodeDecoderRaw(charset.get(), getter_AddRefs(decoder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ConvertToUTF8(decoder, mName);
|
||||
ConvertToUTF8(decoder, mDescription);
|
||||
for (PRUint32 i = 0; i < mMimeDescriptionArray.Length(); ++i) {
|
||||
ConvertToUTF8(decoder, mMimeDescriptionArray[i]);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsPluginTag::SetHost(nsPluginHost * aHost)
|
||||
{
|
||||
mPluginHost = aHost;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetDescription(nsACString& aDescription)
|
||||
{
|
||||
aDescription = mDescription;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetFilename(nsACString& aFileName)
|
||||
{
|
||||
aFileName = mFileName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetVersion(nsACString& aVersion)
|
||||
{
|
||||
aVersion = mVersion;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetName(nsACString& aName)
|
||||
{
|
||||
aName = mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetDisabled(PRBool* aDisabled)
|
||||
{
|
||||
*aDisabled = !HasFlag(NS_PLUGIN_FLAG_ENABLED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::SetDisabled(PRBool aDisabled)
|
||||
{
|
||||
if (HasFlag(NS_PLUGIN_FLAG_ENABLED) == !aDisabled)
|
||||
return NS_OK;
|
||||
|
||||
if (aDisabled)
|
||||
UnMark(NS_PLUGIN_FLAG_ENABLED);
|
||||
else
|
||||
Mark(NS_PLUGIN_FLAG_ENABLED);
|
||||
|
||||
mPluginHost->UpdatePluginInfo(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetBlocklisted(PRBool* aBlocklisted)
|
||||
{
|
||||
*aBlocklisted = HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::SetBlocklisted(PRBool aBlocklisted)
|
||||
{
|
||||
if (HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED) == aBlocklisted)
|
||||
return NS_OK;
|
||||
|
||||
if (aBlocklisted)
|
||||
Mark(NS_PLUGIN_FLAG_BLOCKLISTED);
|
||||
else
|
||||
UnMark(NS_PLUGIN_FLAG_BLOCKLISTED);
|
||||
|
||||
mPluginHost->UpdatePluginInfo(nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// helper struct for asynchronous handling of plugin unloading
|
||||
class nsPluginUnloadEvent : public nsRunnable {
|
||||
public:
|
||||
@ -946,7 +330,7 @@ NS_IMETHODIMP nsPluginUnloadEvent::Run()
|
||||
}
|
||||
|
||||
// unload plugin asynchronously if possible, otherwise just unload now
|
||||
nsresult PostPluginUnloadEvent(PRLibrary* aLibrary)
|
||||
nsresult nsPluginHost::PostPluginUnloadEvent(PRLibrary* aLibrary)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> ev = new nsPluginUnloadEvent(aLibrary);
|
||||
if (ev && NS_SUCCEEDED(NS_DispatchToCurrentThread(ev)))
|
||||
@ -958,99 +342,6 @@ nsresult PostPluginUnloadEvent(PRLibrary* aLibrary)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void nsPluginTag::TryUnloadPlugin()
|
||||
{
|
||||
if (mEntryPoint) {
|
||||
mEntryPoint->Shutdown();
|
||||
mEntryPoint = nsnull;
|
||||
}
|
||||
|
||||
// before we unload check if we are allowed to, see bug #61388
|
||||
if (mLibrary && mCanUnloadLibrary) {
|
||||
// NPAPI plugins can be unloaded now if they don't use XPConnect
|
||||
if (!mXPConnected) {
|
||||
// unload the plugin asynchronously by posting a PLEvent
|
||||
PostPluginUnloadEvent(mLibrary);
|
||||
}
|
||||
else {
|
||||
// add library to the unused library list to handle it later
|
||||
if (mPluginHost)
|
||||
mPluginHost->AddUnusedLibrary(mLibrary);
|
||||
}
|
||||
}
|
||||
|
||||
// we should zero it anyway, it is going to be unloaded by
|
||||
// CleanUnsedLibraries before we need to call the library
|
||||
// again so the calling code should not be fooled and reload
|
||||
// the library fresh
|
||||
mLibrary = nsnull;
|
||||
|
||||
// Remove mime types added to the category manager
|
||||
// only if we were made 'active' by setting the host
|
||||
if (mPluginHost) {
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
|
||||
}
|
||||
}
|
||||
|
||||
void nsPluginTag::Mark(PRUint32 mask)
|
||||
{
|
||||
PRBool wasEnabled = IsEnabled();
|
||||
mFlags |= mask;
|
||||
// Update entries in the category manager if necessary.
|
||||
if (mPluginHost && wasEnabled != IsEnabled()) {
|
||||
if (wasEnabled)
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
|
||||
else
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginRegister);
|
||||
}
|
||||
}
|
||||
|
||||
void nsPluginTag::UnMark(PRUint32 mask)
|
||||
{
|
||||
PRBool wasEnabled = IsEnabled();
|
||||
mFlags &= ~mask;
|
||||
// Update entries in the category manager if necessary.
|
||||
if (mPluginHost && wasEnabled != IsEnabled()) {
|
||||
if (wasEnabled)
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
|
||||
else
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginRegister);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool nsPluginTag::HasFlag(PRUint32 flag)
|
||||
{
|
||||
return (mFlags & flag) != 0;
|
||||
}
|
||||
|
||||
PRUint32 nsPluginTag::Flags()
|
||||
{
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
PRBool nsPluginTag::IsEnabled()
|
||||
{
|
||||
return HasFlag(NS_PLUGIN_FLAG_ENABLED) && !HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
|
||||
}
|
||||
|
||||
PRBool nsPluginTag::Equals(nsPluginTag *aPluginTag)
|
||||
{
|
||||
NS_ENSURE_TRUE(aPluginTag, PR_FALSE);
|
||||
|
||||
if ((!mName.Equals(aPluginTag->mName)) ||
|
||||
(!mDescription.Equals(aPluginTag->mDescription)) ||
|
||||
(mVariants != aPluginTag->mVariants))
|
||||
return PR_FALSE;
|
||||
|
||||
if (mVariants && mMimeTypeArray && aPluginTag->mMimeTypeArray) {
|
||||
for (PRInt32 i = 0; i < mVariants; i++) {
|
||||
if (PL_strcmp(mMimeTypeArray[i], aPluginTag->mMimeTypeArray[i]) != 0)
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
class nsPluginStreamListenerPeer;
|
||||
|
||||
class nsPluginStreamInfo : public nsINPAPIPluginStreamInfo
|
||||
@ -3345,80 +2636,6 @@ nsresult nsPluginHost::AddInstanceToActiveList(nsCOMPtr<nsIPlugin> aPlugin,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginTag::RegisterWithCategoryManager(PRBool aOverrideInternalTypes,
|
||||
nsPluginTag::nsRegisterType aType)
|
||||
{
|
||||
if (!mMimeTypeArray)
|
||||
return;
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("nsPluginTag::RegisterWithCategoryManager plugin=%s, removing = %s\n",
|
||||
mFileName.get(), aType == ePluginUnregister ? "yes" : "no"));
|
||||
|
||||
nsCOMPtr<nsICategoryManager> catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
|
||||
if (!catMan)
|
||||
return;
|
||||
|
||||
const char *contractId = "@mozilla.org/content/plugin/document-loader-factory;1";
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (!psvc)
|
||||
return; // NS_ERROR_OUT_OF_MEMORY
|
||||
|
||||
// A preference controls whether or not the full page plugin is disabled for
|
||||
// a particular type. The string must be in the form:
|
||||
// type1,type2,type3,type4
|
||||
// Note: need an actual interface to control this and subsequent disabling
|
||||
// (and other plugin host settings) so applications can reliably disable
|
||||
// plugins - without relying on implementation details such as prefs/category
|
||||
// manager entries.
|
||||
nsXPIDLCString overrideTypes;
|
||||
psvc->GetCharPref("plugin.disable_full_page_plugin_for_types", getter_Copies(overrideTypes));
|
||||
nsCAutoString overrideTypesFormatted;
|
||||
overrideTypesFormatted.Assign(',');
|
||||
overrideTypesFormatted += overrideTypes;
|
||||
overrideTypesFormatted.Append(',');
|
||||
|
||||
nsACString::const_iterator start, end;
|
||||
for (int i = 0; i < mVariants; i++) {
|
||||
if (aType == ePluginUnregister) {
|
||||
nsXPIDLCString value;
|
||||
if (NS_SUCCEEDED(catMan->GetCategoryEntry("Gecko-Content-Viewers",
|
||||
mMimeTypeArray[i],
|
||||
getter_Copies(value)))) {
|
||||
// Only delete the entry if a plugin registered for it
|
||||
if (strcmp(value, contractId) == 0) {
|
||||
catMan->DeleteCategoryEntry("Gecko-Content-Viewers",
|
||||
mMimeTypeArray[i],
|
||||
PR_TRUE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
overrideTypesFormatted.BeginReading(start);
|
||||
overrideTypesFormatted.EndReading(end);
|
||||
|
||||
nsDependentCString mimeType(mMimeTypeArray[i]);
|
||||
nsCAutoString commaSeparated;
|
||||
commaSeparated.Assign(',');
|
||||
commaSeparated += mimeType;
|
||||
commaSeparated.Append(',');
|
||||
if (!FindInReadable(commaSeparated, start, end)) {
|
||||
catMan->AddCategoryEntry("Gecko-Content-Viewers",
|
||||
mMimeTypeArray[i],
|
||||
contractId,
|
||||
PR_FALSE, /* persist: broken by bug 193031 */
|
||||
aOverrideInternalTypes, /* replace if we're told to */
|
||||
nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NOISY,
|
||||
("nsPluginTag::RegisterWithCategoryManager mime=%s, plugin=%s\n",
|
||||
mMimeTypeArray[i], mFileName.get()));
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginHost::SetUpPluginInstance(const char *aMimeType,
|
||||
nsIURI *aURL,
|
||||
nsIPluginInstanceOwner *aOwner)
|
||||
|
@ -60,134 +60,17 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsPluginTags.h"
|
||||
|
||||
class nsNPAPIPlugin;
|
||||
class nsIComponentManager;
|
||||
class nsIFile;
|
||||
class nsIChannel;
|
||||
class nsPluginHost;
|
||||
|
||||
// Remember that flags are written out to pluginreg.dat, be careful
|
||||
// changing their meaning.
|
||||
#define NS_PLUGIN_FLAG_ENABLED 0x0001 // is this plugin enabled?
|
||||
// no longer used 0x0002 // reuse only if regenerating pluginreg.dat
|
||||
#define NS_PLUGIN_FLAG_FROMCACHE 0x0004 // this plugintag info was loaded from cache
|
||||
#define NS_PLUGIN_FLAG_UNWANTED 0x0008 // this is an unwanted plugin
|
||||
#define NS_PLUGIN_FLAG_BLOCKLISTED 0x0010 // this is a blocklisted plugin
|
||||
|
||||
#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
|
||||
#define MAC_CARBON_PLUGINS
|
||||
#endif
|
||||
|
||||
// A linked-list of plugin information that is used for instantiating plugins
|
||||
// and reflecting plugin information into JavaScript.
|
||||
class nsPluginTag : public nsIPluginTag
|
||||
{
|
||||
public:
|
||||
enum nsRegisterType {
|
||||
ePluginRegister,
|
||||
ePluginUnregister
|
||||
};
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPLUGINTAG
|
||||
|
||||
nsPluginTag(nsPluginTag* aPluginTag);
|
||||
nsPluginTag(nsPluginInfo* aPluginInfo);
|
||||
nsPluginTag(const char* aName,
|
||||
const char* aDescription,
|
||||
const char* aFileName,
|
||||
const char* aFullPath,
|
||||
const char* aVersion,
|
||||
const char* const* aMimeTypes,
|
||||
const char* const* aMimeDescriptions,
|
||||
const char* const* aExtensions,
|
||||
PRInt32 aVariants,
|
||||
PRInt64 aLastModifiedTime = 0,
|
||||
PRBool aCanUnload = PR_TRUE,
|
||||
PRBool aArgsAreUTF8 = PR_FALSE);
|
||||
~nsPluginTag();
|
||||
|
||||
void SetHost(nsPluginHost * aHost);
|
||||
void TryUnloadPlugin();
|
||||
void Mark(PRUint32 mask);
|
||||
void UnMark(PRUint32 mask);
|
||||
PRBool HasFlag(PRUint32 flag);
|
||||
PRUint32 Flags();
|
||||
PRBool Equals(nsPluginTag* aPluginTag);
|
||||
PRBool IsEnabled();
|
||||
void RegisterWithCategoryManager(PRBool aOverrideInternalTypes,
|
||||
nsRegisterType aType = ePluginRegister);
|
||||
|
||||
nsRefPtr<nsPluginTag> mNext;
|
||||
nsPluginHost *mPluginHost;
|
||||
nsCString mName; // UTF-8
|
||||
nsCString mDescription; // UTF-8
|
||||
PRInt32 mVariants;
|
||||
char **mMimeTypeArray;
|
||||
nsTArray<nsCString> mMimeDescriptionArray; // UTF-8
|
||||
char **mExtensionsArray;
|
||||
PRLibrary *mLibrary;
|
||||
nsCOMPtr<nsIPlugin> mEntryPoint;
|
||||
PRPackedBool mCanUnloadLibrary;
|
||||
PRPackedBool mXPConnected;
|
||||
PRPackedBool mIsJavaPlugin;
|
||||
PRPackedBool mIsNPRuntimeEnabledJavaPlugin;
|
||||
nsCString mFileName; // UTF-8
|
||||
nsCString mFullPath; // UTF-8
|
||||
nsCString mVersion; // UTF-8
|
||||
PRInt64 mLastModifiedTime;
|
||||
private:
|
||||
PRUint32 mFlags;
|
||||
|
||||
nsresult EnsureMembersAreUTF8();
|
||||
};
|
||||
|
||||
struct nsPluginInstanceTag
|
||||
{
|
||||
nsPluginInstanceTag* mNext;
|
||||
char* mURL;
|
||||
nsRefPtr<nsPluginTag> mPluginTag;
|
||||
nsIPluginInstance* mInstance;
|
||||
PRTime mllStopTime;
|
||||
PRPackedBool mStopped;
|
||||
PRPackedBool mDefaultPlugin;
|
||||
PRPackedBool mXPConnected;
|
||||
// Array holding all opened stream listeners for this entry
|
||||
nsCOMPtr <nsISupportsArray> mStreams;
|
||||
|
||||
nsPluginInstanceTag(nsPluginTag* aPluginTag,
|
||||
nsIPluginInstance* aInstance,
|
||||
const char * url,
|
||||
PRBool aDefaultPlugin);
|
||||
~nsPluginInstanceTag();
|
||||
|
||||
void setStopped(PRBool stopped);
|
||||
};
|
||||
|
||||
class nsPluginInstanceTagList
|
||||
{
|
||||
public:
|
||||
nsPluginInstanceTag *mFirst;
|
||||
nsPluginInstanceTag *mLast;
|
||||
PRInt32 mCount;
|
||||
|
||||
nsPluginInstanceTagList();
|
||||
~nsPluginInstanceTagList();
|
||||
|
||||
void shutdown();
|
||||
PRBool add(nsPluginInstanceTag *plugin);
|
||||
PRBool remove(nsPluginInstanceTag *plugin);
|
||||
nsPluginInstanceTag *find(nsIPluginInstance *instance);
|
||||
nsPluginInstanceTag *find(const char *mimetype);
|
||||
nsPluginInstanceTag *findStopped(const char *url);
|
||||
PRUint32 getStoppedCount();
|
||||
nsPluginInstanceTag *findOldestStopped();
|
||||
void removeAllStopped();
|
||||
void stopRunning(nsISupportsArray *aReloadDocs, nsPluginTag *aPluginTag);
|
||||
PRBool IsLastInstance(nsPluginInstanceTag *plugin);
|
||||
};
|
||||
|
||||
class nsPluginHost : public nsIPluginHost,
|
||||
public nsIObserver,
|
||||
public nsITimerCallback,
|
||||
@ -274,6 +157,8 @@ public:
|
||||
|
||||
static nsresult GetPrompt(nsIPluginInstanceOwner *aOwner, nsIPrompt **aPrompt);
|
||||
|
||||
static nsresult PostPluginUnloadEvent(PRLibrary* aLibrary);
|
||||
|
||||
void AddIdleTimeTarget(nsIPluginInstanceOwner* objectFrame, PRBool isVisible);
|
||||
void RemoveIdleTimeTarget(nsIPluginInstanceOwner* objectFrame);
|
||||
|
||||
|
842
modules/plugin/base/src/nsPluginTags.cpp
Normal file
842
modules/plugin/base/src/nsPluginTags.cpp
Normal file
@ -0,0 +1,842 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sean Echevarria <sean@beatnik.com>
|
||||
* Håkan Waara <hwaara@chello.se>
|
||||
* Josh Aas <josh@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsPluginTags.h"
|
||||
|
||||
#include "prlink.h"
|
||||
#include "plstr.h"
|
||||
#include "nsIPluginInstanceOwner.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsPluginsDir.h"
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsPluginLogging.h"
|
||||
#include "nsICategoryManager.h"
|
||||
|
||||
inline char* new_str(const char* str)
|
||||
{
|
||||
if (str == nsnull)
|
||||
return nsnull;
|
||||
|
||||
char* result = new char[strlen(str) + 1];
|
||||
if (result != nsnull)
|
||||
return strcpy(result, str);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* nsPluginTag */
|
||||
|
||||
nsPluginTag::nsPluginTag(nsPluginTag* aPluginTag)
|
||||
: mPluginHost(nsnull),
|
||||
mName(aPluginTag->mName),
|
||||
mDescription(aPluginTag->mDescription),
|
||||
mVariants(aPluginTag->mVariants),
|
||||
mMimeTypeArray(nsnull),
|
||||
mMimeDescriptionArray(aPluginTag->mMimeDescriptionArray),
|
||||
mExtensionsArray(nsnull),
|
||||
mLibrary(nsnull),
|
||||
mCanUnloadLibrary(PR_TRUE),
|
||||
mXPConnected(PR_FALSE),
|
||||
mIsJavaPlugin(aPluginTag->mIsJavaPlugin),
|
||||
mIsNPRuntimeEnabledJavaPlugin(aPluginTag->mIsNPRuntimeEnabledJavaPlugin),
|
||||
mFileName(aPluginTag->mFileName),
|
||||
mFullPath(aPluginTag->mFullPath),
|
||||
mVersion(aPluginTag->mVersion),
|
||||
mLastModifiedTime(0),
|
||||
mFlags(NS_PLUGIN_FLAG_ENABLED)
|
||||
{
|
||||
if (aPluginTag->mMimeTypeArray != nsnull) {
|
||||
mMimeTypeArray = new char*[mVariants];
|
||||
for (int i = 0; i < mVariants; i++)
|
||||
mMimeTypeArray[i] = new_str(aPluginTag->mMimeTypeArray[i]);
|
||||
}
|
||||
|
||||
if (aPluginTag->mExtensionsArray != nsnull) {
|
||||
mExtensionsArray = new char*[mVariants];
|
||||
for (int i = 0; i < mVariants; i++)
|
||||
mExtensionsArray[i] = new_str(aPluginTag->mExtensionsArray[i]);
|
||||
}
|
||||
}
|
||||
|
||||
nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo)
|
||||
: mPluginHost(nsnull),
|
||||
mName(aPluginInfo->fName),
|
||||
mDescription(aPluginInfo->fDescription),
|
||||
mVariants(aPluginInfo->fVariantCount),
|
||||
mMimeTypeArray(nsnull),
|
||||
mExtensionsArray(nsnull),
|
||||
mLibrary(nsnull),
|
||||
#ifdef XP_MACOSX
|
||||
mCanUnloadLibrary(!aPluginInfo->fBundle),
|
||||
#else
|
||||
mCanUnloadLibrary(PR_TRUE),
|
||||
#endif
|
||||
mXPConnected(PR_FALSE),
|
||||
mIsJavaPlugin(PR_FALSE),
|
||||
mIsNPRuntimeEnabledJavaPlugin(PR_FALSE),
|
||||
mFileName(aPluginInfo->fFileName),
|
||||
mFullPath(aPluginInfo->fFullPath),
|
||||
mVersion(aPluginInfo->fVersion),
|
||||
mLastModifiedTime(0),
|
||||
mFlags(NS_PLUGIN_FLAG_ENABLED)
|
||||
{
|
||||
if (aPluginInfo->fMimeTypeArray != nsnull) {
|
||||
mMimeTypeArray = new char*[mVariants];
|
||||
for (int i = 0; i < mVariants; i++) {
|
||||
if (mIsJavaPlugin && aPluginInfo->fMimeTypeArray[i] &&
|
||||
strcmp(aPluginInfo->fMimeTypeArray[i],
|
||||
"application/x-java-vm-npruntime") == 0) {
|
||||
mIsNPRuntimeEnabledJavaPlugin = PR_TRUE;
|
||||
|
||||
// Stop processing here, any mimetypes after the magic "I'm a
|
||||
// NPRuntime enabled Java plugin" mimetype will be ignored.
|
||||
mVariants = i;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mMimeTypeArray[i] = new_str(aPluginInfo->fMimeTypeArray[i]);
|
||||
if (nsPluginHost::IsJavaMIMEType(mMimeTypeArray[i]))
|
||||
mIsJavaPlugin = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (aPluginInfo->fMimeDescriptionArray != nsnull) {
|
||||
for (int i = 0; i < mVariants; i++) {
|
||||
// we should cut off the list of suffixes which the mime
|
||||
// description string may have, see bug 53895
|
||||
// it is usually in form "some description (*.sf1, *.sf2)"
|
||||
// so we can search for the opening round bracket
|
||||
char cur = '\0';
|
||||
char pre = '\0';
|
||||
char * p = PL_strrchr(aPluginInfo->fMimeDescriptionArray[i], '(');
|
||||
if (p && (p != aPluginInfo->fMimeDescriptionArray[i])) {
|
||||
if ((p - 1) && *(p - 1) == ' ') {
|
||||
pre = *(p - 1);
|
||||
*(p - 1) = '\0';
|
||||
} else {
|
||||
cur = *p;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
}
|
||||
mMimeDescriptionArray.AppendElement(
|
||||
aPluginInfo->fMimeDescriptionArray[i]);
|
||||
// restore the original string
|
||||
if (cur != '\0')
|
||||
*p = cur;
|
||||
if (pre != '\0')
|
||||
*(p - 1) = pre;
|
||||
}
|
||||
} else {
|
||||
mMimeDescriptionArray.SetLength(mVariants);
|
||||
}
|
||||
|
||||
if (aPluginInfo->fExtensionArray != nsnull) {
|
||||
mExtensionsArray = new char*[mVariants];
|
||||
for (int i = 0; i < mVariants; i++)
|
||||
mExtensionsArray[i] = new_str(aPluginInfo->fExtensionArray[i]);
|
||||
}
|
||||
|
||||
EnsureMembersAreUTF8();
|
||||
}
|
||||
|
||||
nsPluginTag::nsPluginTag(const char* aName,
|
||||
const char* aDescription,
|
||||
const char* aFileName,
|
||||
const char* aFullPath,
|
||||
const char* aVersion,
|
||||
const char* const* aMimeTypes,
|
||||
const char* const* aMimeDescriptions,
|
||||
const char* const* aExtensions,
|
||||
PRInt32 aVariants,
|
||||
PRInt64 aLastModifiedTime,
|
||||
PRBool aCanUnload,
|
||||
PRBool aArgsAreUTF8)
|
||||
: mPluginHost(nsnull),
|
||||
mName(aName),
|
||||
mDescription(aDescription),
|
||||
mVariants(aVariants),
|
||||
mMimeTypeArray(nsnull),
|
||||
mExtensionsArray(nsnull),
|
||||
mLibrary(nsnull),
|
||||
mCanUnloadLibrary(aCanUnload),
|
||||
mXPConnected(PR_FALSE),
|
||||
mIsJavaPlugin(PR_FALSE),
|
||||
mIsNPRuntimeEnabledJavaPlugin(PR_FALSE),
|
||||
mFileName(aFileName),
|
||||
mFullPath(aFullPath),
|
||||
mVersion(aVersion),
|
||||
mLastModifiedTime(aLastModifiedTime),
|
||||
mFlags(0) // Caller will read in our flags from cache
|
||||
{
|
||||
if (aVariants) {
|
||||
mMimeTypeArray = new char*[mVariants];
|
||||
mExtensionsArray = new char*[mVariants];
|
||||
|
||||
for (PRInt32 i = 0; i < aVariants; ++i) {
|
||||
if (mIsJavaPlugin && aMimeTypes[i] &&
|
||||
strcmp(aMimeTypes[i], "application/x-java-vm-npruntime") == 0) {
|
||||
mIsNPRuntimeEnabledJavaPlugin = PR_TRUE;
|
||||
|
||||
// Stop processing here, any mimetypes after the magic "I'm a
|
||||
// NPRuntime enabled Java plugin" mimetype will be ignored.
|
||||
mVariants = i;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mMimeTypeArray[i] = new_str(aMimeTypes[i]);
|
||||
mMimeDescriptionArray.AppendElement(aMimeDescriptions[i]);
|
||||
mExtensionsArray[i] = new_str(aExtensions[i]);
|
||||
if (nsPluginHost::IsJavaMIMEType(mMimeTypeArray[i]))
|
||||
mIsJavaPlugin = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aArgsAreUTF8)
|
||||
EnsureMembersAreUTF8();
|
||||
}
|
||||
|
||||
nsPluginTag::~nsPluginTag()
|
||||
{
|
||||
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
|
||||
|
||||
if (mMimeTypeArray) {
|
||||
for (int i = 0; i < mVariants; i++)
|
||||
delete[] mMimeTypeArray[i];
|
||||
|
||||
delete[] (mMimeTypeArray);
|
||||
mMimeTypeArray = nsnull;
|
||||
}
|
||||
|
||||
if (mExtensionsArray) {
|
||||
for (int i = 0; i < mVariants; i++)
|
||||
delete[] mExtensionsArray[i];
|
||||
|
||||
delete[] (mExtensionsArray);
|
||||
mExtensionsArray = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsPluginTag, nsIPluginTag)
|
||||
|
||||
static nsresult ConvertToUTF8(nsIUnicodeDecoder *aUnicodeDecoder,
|
||||
nsAFlatCString& aString)
|
||||
{
|
||||
PRInt32 numberOfBytes = aString.Length();
|
||||
PRInt32 outUnicodeLen;
|
||||
nsAutoString buffer;
|
||||
nsresult rv = aUnicodeDecoder->GetMaxLength(aString.get(), numberOfBytes,
|
||||
&outUnicodeLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!EnsureStringLength(buffer, outUnicodeLen))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = aUnicodeDecoder->Convert(aString.get(), &numberOfBytes,
|
||||
buffer.BeginWriting(), &outUnicodeLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
buffer.SetLength(outUnicodeLen);
|
||||
CopyUTF16toUTF8(buffer, aString);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginTag::EnsureMembersAreUTF8()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIPlatformCharset> pcs =
|
||||
do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIUnicodeDecoder> decoder;
|
||||
nsCOMPtr<nsICharsetConverterManager> ccm =
|
||||
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString charset;
|
||||
rv = pcs->GetCharset(kPlatformCharsetSel_FileName, charset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!charset.LowerCaseEqualsLiteral("utf-8")) {
|
||||
rv = ccm->GetUnicodeDecoderRaw(charset.get(), getter_AddRefs(decoder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ConvertToUTF8(decoder, mFileName);
|
||||
ConvertToUTF8(decoder, mFullPath);
|
||||
}
|
||||
|
||||
// The description of the plug-in and the various MIME type descriptions
|
||||
// should be encoded in the standard plain text file encoding for this system.
|
||||
// XXX should we add kPlatformCharsetSel_PluginResource?
|
||||
rv = pcs->GetCharset(kPlatformCharsetSel_PlainTextInFile, charset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!charset.LowerCaseEqualsLiteral("utf-8")) {
|
||||
rv = ccm->GetUnicodeDecoderRaw(charset.get(), getter_AddRefs(decoder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ConvertToUTF8(decoder, mName);
|
||||
ConvertToUTF8(decoder, mDescription);
|
||||
for (PRUint32 i = 0; i < mMimeDescriptionArray.Length(); ++i) {
|
||||
ConvertToUTF8(decoder, mMimeDescriptionArray[i]);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsPluginTag::SetHost(nsPluginHost * aHost)
|
||||
{
|
||||
mPluginHost = aHost;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetDescription(nsACString& aDescription)
|
||||
{
|
||||
aDescription = mDescription;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetFilename(nsACString& aFileName)
|
||||
{
|
||||
aFileName = mFileName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetVersion(nsACString& aVersion)
|
||||
{
|
||||
aVersion = mVersion;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetName(nsACString& aName)
|
||||
{
|
||||
aName = mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetDisabled(PRBool* aDisabled)
|
||||
{
|
||||
*aDisabled = !HasFlag(NS_PLUGIN_FLAG_ENABLED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::SetDisabled(PRBool aDisabled)
|
||||
{
|
||||
if (HasFlag(NS_PLUGIN_FLAG_ENABLED) == !aDisabled)
|
||||
return NS_OK;
|
||||
|
||||
if (aDisabled)
|
||||
UnMark(NS_PLUGIN_FLAG_ENABLED);
|
||||
else
|
||||
Mark(NS_PLUGIN_FLAG_ENABLED);
|
||||
|
||||
mPluginHost->UpdatePluginInfo(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetBlocklisted(PRBool* aBlocklisted)
|
||||
{
|
||||
*aBlocklisted = HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::SetBlocklisted(PRBool aBlocklisted)
|
||||
{
|
||||
if (HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED) == aBlocklisted)
|
||||
return NS_OK;
|
||||
|
||||
if (aBlocklisted)
|
||||
Mark(NS_PLUGIN_FLAG_BLOCKLISTED);
|
||||
else
|
||||
UnMark(NS_PLUGIN_FLAG_BLOCKLISTED);
|
||||
|
||||
mPluginHost->UpdatePluginInfo(nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginTag::RegisterWithCategoryManager(PRBool aOverrideInternalTypes,
|
||||
nsPluginTag::nsRegisterType aType)
|
||||
{
|
||||
if (!mMimeTypeArray)
|
||||
return;
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("nsPluginTag::RegisterWithCategoryManager plugin=%s, removing = %s\n",
|
||||
mFileName.get(), aType == ePluginUnregister ? "yes" : "no"));
|
||||
|
||||
nsCOMPtr<nsICategoryManager> catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
|
||||
if (!catMan)
|
||||
return;
|
||||
|
||||
const char *contractId = "@mozilla.org/content/plugin/document-loader-factory;1";
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (!psvc)
|
||||
return; // NS_ERROR_OUT_OF_MEMORY
|
||||
|
||||
// A preference controls whether or not the full page plugin is disabled for
|
||||
// a particular type. The string must be in the form:
|
||||
// type1,type2,type3,type4
|
||||
// Note: need an actual interface to control this and subsequent disabling
|
||||
// (and other plugin host settings) so applications can reliably disable
|
||||
// plugins - without relying on implementation details such as prefs/category
|
||||
// manager entries.
|
||||
nsXPIDLCString overrideTypes;
|
||||
psvc->GetCharPref("plugin.disable_full_page_plugin_for_types", getter_Copies(overrideTypes));
|
||||
nsCAutoString overrideTypesFormatted;
|
||||
overrideTypesFormatted.Assign(',');
|
||||
overrideTypesFormatted += overrideTypes;
|
||||
overrideTypesFormatted.Append(',');
|
||||
|
||||
nsACString::const_iterator start, end;
|
||||
for (int i = 0; i < mVariants; i++) {
|
||||
if (aType == ePluginUnregister) {
|
||||
nsXPIDLCString value;
|
||||
if (NS_SUCCEEDED(catMan->GetCategoryEntry("Gecko-Content-Viewers",
|
||||
mMimeTypeArray[i],
|
||||
getter_Copies(value)))) {
|
||||
// Only delete the entry if a plugin registered for it
|
||||
if (strcmp(value, contractId) == 0) {
|
||||
catMan->DeleteCategoryEntry("Gecko-Content-Viewers",
|
||||
mMimeTypeArray[i],
|
||||
PR_TRUE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
overrideTypesFormatted.BeginReading(start);
|
||||
overrideTypesFormatted.EndReading(end);
|
||||
|
||||
nsDependentCString mimeType(mMimeTypeArray[i]);
|
||||
nsCAutoString commaSeparated;
|
||||
commaSeparated.Assign(',');
|
||||
commaSeparated += mimeType;
|
||||
commaSeparated.Append(',');
|
||||
if (!FindInReadable(commaSeparated, start, end)) {
|
||||
catMan->AddCategoryEntry("Gecko-Content-Viewers",
|
||||
mMimeTypeArray[i],
|
||||
contractId,
|
||||
PR_FALSE, /* persist: broken by bug 193031 */
|
||||
aOverrideInternalTypes, /* replace if we're told to */
|
||||
nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NOISY,
|
||||
("nsPluginTag::RegisterWithCategoryManager mime=%s, plugin=%s\n",
|
||||
mMimeTypeArray[i], mFileName.get()));
|
||||
}
|
||||
}
|
||||
|
||||
void nsPluginTag::Mark(PRUint32 mask)
|
||||
{
|
||||
PRBool wasEnabled = IsEnabled();
|
||||
mFlags |= mask;
|
||||
// Update entries in the category manager if necessary.
|
||||
if (mPluginHost && wasEnabled != IsEnabled()) {
|
||||
if (wasEnabled)
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
|
||||
else
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginRegister);
|
||||
}
|
||||
}
|
||||
|
||||
void nsPluginTag::UnMark(PRUint32 mask)
|
||||
{
|
||||
PRBool wasEnabled = IsEnabled();
|
||||
mFlags &= ~mask;
|
||||
// Update entries in the category manager if necessary.
|
||||
if (mPluginHost && wasEnabled != IsEnabled()) {
|
||||
if (wasEnabled)
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
|
||||
else
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginRegister);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool nsPluginTag::HasFlag(PRUint32 flag)
|
||||
{
|
||||
return (mFlags & flag) != 0;
|
||||
}
|
||||
|
||||
PRUint32 nsPluginTag::Flags()
|
||||
{
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
PRBool nsPluginTag::IsEnabled()
|
||||
{
|
||||
return HasFlag(NS_PLUGIN_FLAG_ENABLED) && !HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
|
||||
}
|
||||
|
||||
PRBool nsPluginTag::Equals(nsPluginTag *aPluginTag)
|
||||
{
|
||||
NS_ENSURE_TRUE(aPluginTag, PR_FALSE);
|
||||
|
||||
if ((!mName.Equals(aPluginTag->mName)) ||
|
||||
(!mDescription.Equals(aPluginTag->mDescription)) ||
|
||||
(mVariants != aPluginTag->mVariants))
|
||||
return PR_FALSE;
|
||||
|
||||
if (mVariants && mMimeTypeArray && aPluginTag->mMimeTypeArray) {
|
||||
for (PRInt32 i = 0; i < mVariants; i++) {
|
||||
if (PL_strcmp(mMimeTypeArray[i], aPluginTag->mMimeTypeArray[i]) != 0)
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void nsPluginTag::TryUnloadPlugin()
|
||||
{
|
||||
if (mEntryPoint) {
|
||||
mEntryPoint->Shutdown();
|
||||
mEntryPoint = nsnull;
|
||||
}
|
||||
|
||||
// before we unload check if we are allowed to, see bug #61388
|
||||
if (mLibrary && mCanUnloadLibrary) {
|
||||
// NPAPI plugins can be unloaded now if they don't use XPConnect
|
||||
if (!mXPConnected) {
|
||||
// unload the plugin asynchronously by posting a PLEvent
|
||||
nsPluginHost::PostPluginUnloadEvent(mLibrary);
|
||||
}
|
||||
else {
|
||||
// add library to the unused library list to handle it later
|
||||
if (mPluginHost)
|
||||
mPluginHost->AddUnusedLibrary(mLibrary);
|
||||
}
|
||||
}
|
||||
|
||||
// we should zero it anyway, it is going to be unloaded by
|
||||
// CleanUnsedLibraries before we need to call the library
|
||||
// again so the calling code should not be fooled and reload
|
||||
// the library fresh
|
||||
mLibrary = nsnull;
|
||||
|
||||
// Remove mime types added to the category manager
|
||||
// only if we were made 'active' by setting the host
|
||||
if (mPluginHost) {
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
|
||||
}
|
||||
}
|
||||
|
||||
/* nsPluginInstanceTag */
|
||||
|
||||
nsPluginInstanceTag::nsPluginInstanceTag(nsPluginTag* aPluginTag,
|
||||
nsIPluginInstance* aInstance,
|
||||
const char * url,
|
||||
PRBool aDefaultPlugin)
|
||||
{
|
||||
mNext = nsnull;
|
||||
mPluginTag = aPluginTag;
|
||||
|
||||
mURL = PL_strdup(url);
|
||||
mInstance = aInstance;
|
||||
if (aInstance)
|
||||
NS_ADDREF(aInstance);
|
||||
mXPConnected = PR_FALSE;
|
||||
mDefaultPlugin = aDefaultPlugin;
|
||||
mStopped = PR_FALSE;
|
||||
mllStopTime = LL_ZERO;
|
||||
}
|
||||
|
||||
nsPluginInstanceTag::~nsPluginInstanceTag()
|
||||
{
|
||||
mPluginTag = nsnull;
|
||||
if (mInstance) {
|
||||
nsCOMPtr<nsIPluginInstanceOwner> owner;
|
||||
mInstance->GetOwner(getter_AddRefs(owner));
|
||||
if (owner)
|
||||
owner->SetInstance(nsnull);
|
||||
mInstance->InvalidateOwner();
|
||||
|
||||
NS_RELEASE(mInstance);
|
||||
}
|
||||
PL_strfree(mURL);
|
||||
}
|
||||
|
||||
void nsPluginInstanceTag::setStopped(PRBool stopped)
|
||||
{
|
||||
mStopped = stopped;
|
||||
if (mStopped) // plugin instance is told to stop
|
||||
mllStopTime = PR_Now();
|
||||
else
|
||||
mllStopTime = LL_ZERO;
|
||||
}
|
||||
|
||||
/* nsPluginInstanceTagList */
|
||||
|
||||
nsPluginInstanceTagList::nsPluginInstanceTagList()
|
||||
{
|
||||
mFirst = nsnull;
|
||||
mLast = nsnull;
|
||||
mCount = 0;
|
||||
}
|
||||
|
||||
nsPluginInstanceTagList::~nsPluginInstanceTagList()
|
||||
{
|
||||
if (!mFirst)
|
||||
return;
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void nsPluginInstanceTagList::shutdown()
|
||||
{
|
||||
if (!mFirst)
|
||||
return;
|
||||
|
||||
for (nsPluginInstanceTag * plugin = mFirst; plugin != nsnull;) {
|
||||
nsPluginInstanceTag * next = plugin->mNext;
|
||||
remove(plugin);
|
||||
plugin = next;
|
||||
}
|
||||
mFirst = nsnull;
|
||||
mLast = nsnull;
|
||||
}
|
||||
|
||||
PRInt32 nsPluginInstanceTagList::add(nsPluginInstanceTag * plugin)
|
||||
{
|
||||
if (!mFirst) {
|
||||
mFirst = plugin;
|
||||
mLast = plugin;
|
||||
mFirst->mNext = nsnull;
|
||||
}
|
||||
else {
|
||||
mLast->mNext = plugin;
|
||||
mLast = plugin;
|
||||
}
|
||||
mLast->mNext = nsnull;
|
||||
mCount++;
|
||||
return mCount;
|
||||
}
|
||||
|
||||
PRBool nsPluginInstanceTagList::IsLastInstance(nsPluginInstanceTag * plugin)
|
||||
{
|
||||
if (!plugin)
|
||||
return PR_FALSE;
|
||||
|
||||
if (!plugin->mPluginTag)
|
||||
return PR_FALSE;
|
||||
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if ((p->mPluginTag == plugin->mPluginTag) && (p != plugin))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool nsPluginInstanceTagList::remove(nsPluginInstanceTag * plugin)
|
||||
{
|
||||
if (!mFirst)
|
||||
return PR_FALSE;
|
||||
|
||||
nsPluginInstanceTag * prev = nsnull;
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (p == plugin) {
|
||||
PRBool lastInstance = IsLastInstance(p);
|
||||
|
||||
if (p == mFirst)
|
||||
mFirst = p->mNext;
|
||||
else
|
||||
prev->mNext = p->mNext;
|
||||
|
||||
if (prev && !prev->mNext)
|
||||
mLast = prev;
|
||||
|
||||
if (lastInstance) {
|
||||
nsRefPtr<nsPluginTag> pluginTag = p->mPluginTag;
|
||||
|
||||
delete p;
|
||||
|
||||
if (pluginTag) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool unloadPluginsASAP = PR_FALSE;
|
||||
rv = pref->GetBoolPref("plugins.unloadASAP", &unloadPluginsASAP);
|
||||
if (NS_SUCCEEDED(rv) && unloadPluginsASAP)
|
||||
pluginTag->TryUnloadPlugin();
|
||||
} else {
|
||||
NS_ASSERTION(pluginTag, "pluginTag was not set, plugin not shutdown");
|
||||
}
|
||||
} else {
|
||||
delete p;
|
||||
}
|
||||
|
||||
mCount--;
|
||||
return PR_TRUE;
|
||||
}
|
||||
prev = p;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// This method terminates all running instances of plugins and collects their
|
||||
// documents to be returned through an array. This method is used
|
||||
// when we are shutting down or when a plugins.refresh(1) happens.
|
||||
// If aPluginTag is given, then only that plugin is terminated
|
||||
void nsPluginInstanceTagList::stopRunning(nsISupportsArray* aReloadDocs,
|
||||
nsPluginTag* aPluginTag)
|
||||
{
|
||||
if (!mFirst)
|
||||
return;
|
||||
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (!p->mStopped && p->mInstance &&
|
||||
(!aPluginTag || aPluginTag == p->mPluginTag)) {
|
||||
p->mInstance->SetWindow(nsnull);
|
||||
p->mInstance->Stop();
|
||||
p->setStopped(PR_TRUE);
|
||||
|
||||
// If we've been passed an array to return, lets collect all our documents,
|
||||
// removing duplicates. These will be reframed (embedded) or reloaded (full-page) later
|
||||
// to kickstart our instances.
|
||||
if (aReloadDocs && p->mInstance) {
|
||||
nsCOMPtr<nsIPluginInstanceOwner> owner;
|
||||
p->mInstance->GetOwner(getter_AddRefs(owner));
|
||||
if (owner) {
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
owner->GetDocument(getter_AddRefs(doc));
|
||||
if (doc && aReloadDocs->IndexOf(doc) == -1) // don't allow for duplicates
|
||||
aReloadDocs->AppendElement(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsPluginInstanceTagList::removeAllStopped()
|
||||
{
|
||||
if (!mFirst)
|
||||
return;
|
||||
|
||||
nsPluginInstanceTag * next = nsnull;
|
||||
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull;) {
|
||||
next = p->mNext;
|
||||
|
||||
if (p->mStopped)
|
||||
remove(p);
|
||||
|
||||
p = next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsPluginInstanceTag * nsPluginInstanceTagList::find(nsIPluginInstance* instance)
|
||||
{
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (p->mInstance == instance)
|
||||
return p;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsPluginInstanceTag * nsPluginInstanceTagList::find(const char * mimetype)
|
||||
{
|
||||
PRBool defaultplugin = (PL_strcmp(mimetype, "*") == 0);
|
||||
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
// give it some special treatment for the default plugin first
|
||||
// because we cannot tell the default plugin by asking instance for a mime type
|
||||
if (defaultplugin && p->mDefaultPlugin)
|
||||
return p;
|
||||
|
||||
if (!p->mInstance)
|
||||
continue;
|
||||
|
||||
const char* mt;
|
||||
nsresult rv = p->mInstance->GetMIMEType(&mt);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
if (PL_strcasecmp(mt, mimetype) == 0)
|
||||
return p;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsPluginInstanceTag * nsPluginInstanceTagList::findStopped(const char * url)
|
||||
{
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (!PL_strcmp(url, p->mURL) && p->mStopped)
|
||||
return p;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRUint32 nsPluginInstanceTagList::getStoppedCount()
|
||||
{
|
||||
PRUint32 stoppedCount = 0;
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (p->mStopped)
|
||||
stoppedCount++;
|
||||
}
|
||||
return stoppedCount;
|
||||
}
|
||||
|
||||
nsPluginInstanceTag * nsPluginInstanceTagList::findOldestStopped()
|
||||
{
|
||||
nsPluginInstanceTag * res = nsnull;
|
||||
PRInt64 llTime = LL_MAXINT;
|
||||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (!p->mStopped)
|
||||
continue;
|
||||
|
||||
if (LL_CMP(p->mllStopTime, <, llTime)) {
|
||||
llTime = p->mllStopTime;
|
||||
res = p;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
172
modules/plugin/base/src/nsPluginTags.h
Normal file
172
modules/plugin/base/src/nsPluginTags.h
Normal file
@ -0,0 +1,172 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Josh Aas <josh@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsPluginTags_h_
|
||||
#define nsPluginTags_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPluginTag.h"
|
||||
#include "nsIPlugin.h"
|
||||
#include "nsIPluginInstance.h"
|
||||
#include "nsISupportsArray.h"
|
||||
|
||||
class nsPluginHost;
|
||||
struct PRLibrary;
|
||||
struct nsPluginInfo;
|
||||
|
||||
// Remember that flags are written out to pluginreg.dat, be careful
|
||||
// changing their meaning.
|
||||
#define NS_PLUGIN_FLAG_ENABLED 0x0001 // is this plugin enabled?
|
||||
// no longer used 0x0002 // reuse only if regenerating pluginreg.dat
|
||||
#define NS_PLUGIN_FLAG_FROMCACHE 0x0004 // this plugintag info was loaded from cache
|
||||
#define NS_PLUGIN_FLAG_UNWANTED 0x0008 // this is an unwanted plugin
|
||||
#define NS_PLUGIN_FLAG_BLOCKLISTED 0x0010 // this is a blocklisted plugin
|
||||
|
||||
// A linked-list of plugin information that is used for instantiating plugins
|
||||
// and reflecting plugin information into JavaScript.
|
||||
class nsPluginTag : public nsIPluginTag
|
||||
{
|
||||
public:
|
||||
enum nsRegisterType {
|
||||
ePluginRegister,
|
||||
ePluginUnregister
|
||||
};
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPLUGINTAG
|
||||
|
||||
nsPluginTag(nsPluginTag* aPluginTag);
|
||||
nsPluginTag(nsPluginInfo* aPluginInfo);
|
||||
nsPluginTag(const char* aName,
|
||||
const char* aDescription,
|
||||
const char* aFileName,
|
||||
const char* aFullPath,
|
||||
const char* aVersion,
|
||||
const char* const* aMimeTypes,
|
||||
const char* const* aMimeDescriptions,
|
||||
const char* const* aExtensions,
|
||||
PRInt32 aVariants,
|
||||
PRInt64 aLastModifiedTime = 0,
|
||||
PRBool aCanUnload = PR_TRUE,
|
||||
PRBool aArgsAreUTF8 = PR_FALSE);
|
||||
~nsPluginTag();
|
||||
|
||||
void SetHost(nsPluginHost * aHost);
|
||||
void TryUnloadPlugin();
|
||||
void Mark(PRUint32 mask);
|
||||
void UnMark(PRUint32 mask);
|
||||
PRBool HasFlag(PRUint32 flag);
|
||||
PRUint32 Flags();
|
||||
PRBool Equals(nsPluginTag* aPluginTag);
|
||||
PRBool IsEnabled();
|
||||
void RegisterWithCategoryManager(PRBool aOverrideInternalTypes,
|
||||
nsRegisterType aType = ePluginRegister);
|
||||
|
||||
nsRefPtr<nsPluginTag> mNext;
|
||||
nsPluginHost *mPluginHost;
|
||||
nsCString mName; // UTF-8
|
||||
nsCString mDescription; // UTF-8
|
||||
PRInt32 mVariants;
|
||||
char **mMimeTypeArray;
|
||||
nsTArray<nsCString> mMimeDescriptionArray; // UTF-8
|
||||
char **mExtensionsArray;
|
||||
PRLibrary *mLibrary;
|
||||
nsCOMPtr<nsIPlugin> mEntryPoint;
|
||||
PRPackedBool mCanUnloadLibrary;
|
||||
PRPackedBool mXPConnected;
|
||||
PRPackedBool mIsJavaPlugin;
|
||||
PRPackedBool mIsNPRuntimeEnabledJavaPlugin;
|
||||
nsCString mFileName; // UTF-8
|
||||
nsCString mFullPath; // UTF-8
|
||||
nsCString mVersion; // UTF-8
|
||||
PRInt64 mLastModifiedTime;
|
||||
private:
|
||||
PRUint32 mFlags;
|
||||
|
||||
nsresult EnsureMembersAreUTF8();
|
||||
};
|
||||
|
||||
struct nsPluginInstanceTag
|
||||
{
|
||||
nsPluginInstanceTag* mNext;
|
||||
char* mURL;
|
||||
nsRefPtr<nsPluginTag> mPluginTag;
|
||||
nsIPluginInstance* mInstance;
|
||||
PRTime mllStopTime;
|
||||
PRPackedBool mStopped;
|
||||
PRPackedBool mDefaultPlugin;
|
||||
PRPackedBool mXPConnected;
|
||||
// Array holding all opened stream listeners for this entry
|
||||
nsCOMPtr <nsISupportsArray> mStreams;
|
||||
|
||||
nsPluginInstanceTag(nsPluginTag* aPluginTag,
|
||||
nsIPluginInstance* aInstance,
|
||||
const char * url,
|
||||
PRBool aDefaultPlugin);
|
||||
~nsPluginInstanceTag();
|
||||
|
||||
void setStopped(PRBool stopped);
|
||||
};
|
||||
|
||||
class nsPluginInstanceTagList
|
||||
{
|
||||
public:
|
||||
nsPluginInstanceTag *mFirst;
|
||||
nsPluginInstanceTag *mLast;
|
||||
PRInt32 mCount;
|
||||
|
||||
nsPluginInstanceTagList();
|
||||
~nsPluginInstanceTagList();
|
||||
|
||||
void shutdown();
|
||||
PRBool add(nsPluginInstanceTag *plugin);
|
||||
PRBool remove(nsPluginInstanceTag *plugin);
|
||||
nsPluginInstanceTag *find(nsIPluginInstance *instance);
|
||||
nsPluginInstanceTag *find(const char *mimetype);
|
||||
nsPluginInstanceTag *findStopped(const char *url);
|
||||
PRUint32 getStoppedCount();
|
||||
nsPluginInstanceTag *findOldestStopped();
|
||||
void removeAllStopped();
|
||||
void stopRunning(nsISupportsArray *aReloadDocs, nsPluginTag *aPluginTag);
|
||||
PRBool IsLastInstance(nsPluginInstanceTag *plugin);
|
||||
};
|
||||
|
||||
#endif // nsPluginTags_h_
|
Loading…
Reference in New Issue
Block a user