Fixing the way we pass attributes and parameters to plugins, bug 103940 r=av sr=beard

This commit is contained in:
peterlubczynski%netscape.com 2001-12-11 15:53:07 +00:00
Родитель 742f7d9a11
Коммит 99254c4720
3 изменённых файлов: 440 добавлений и 649 удалений

Просмотреть файл

@ -73,6 +73,9 @@
#include "nsIDocShellTreeOwner.h"
#include "nsIWebBrowserChrome.h"
#include "nsIDOMElement.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMHTMLObjectElement.h"
#include "nsIDOMHTMLAppletElement.h"
#include "nsContentPolicyUtils.h"
#include "nsIDOMWindow.h"
#include "nsIDOMMouseListener.h"
@ -283,12 +286,6 @@ private:
nsPluginWindow mPluginWindow;
nsIPluginInstance *mInstance;
nsObjectFrame *mOwner;
PRInt32 mNumAttrs;
char **mAttrNames;
char **mAttrVals;
PRInt32 mNumParams;
char **mParamNames;
char **mParamVals;
char *mDocumentBase;
char *mTagText;
nsIWidget *mWidget;
@ -296,10 +293,16 @@ private:
nsCOMPtr<nsITimer> mPluginTimer;
nsIPluginHost *mPluginHost;
PRPackedBool mContentFocused;
PRUint16 mNumCachedAttrs;
PRUint16 mNumCachedParams;
char **mCachedAttrParamNames;
char **mCachedAttrParamValues;
nsresult DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent);
nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent);
nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
nsresult EnsureCachedAttrParamArrays();
};
// Mac specific code to fix up port position and clip during paint
@ -1929,18 +1932,16 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
memset(&mPluginWindow, 0, sizeof(mPluginWindow));
mInstance = nsnull;
mOwner = nsnull;
mNumAttrs = 0;
mAttrNames = nsnull;
mAttrVals = nsnull;
mWidget = nsnull;
mContext = nsnull;
mNumParams = 0;
mParamNames = nsnull;
mParamVals = nsnull;
mDocumentBase = nsnull;
mTagText = nsnull;
mPluginHost = nsnull;
mContentFocused = PR_FALSE;
mNumCachedAttrs = 0;
mNumCachedParams = 0;
mCachedAttrParamNames = nsnull;
mCachedAttrParamValues = nsnull;
}
nsPluginInstanceOwner::~nsPluginInstanceOwner()
@ -1956,68 +1957,34 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
NS_IF_RELEASE(mPluginHost);
mOwner = nsnull;
for (cnt = 0; cnt < mNumAttrs; cnt++)
{
if ((nsnull != mAttrNames) && (nsnull != mAttrNames[cnt]))
{
PR_Free(mAttrNames[cnt]);
mAttrNames[cnt] = nsnull;
for (cnt = 0; cnt < (mNumCachedAttrs + 1 + mNumCachedParams); cnt++) {
if ((nsnull != mCachedAttrParamNames) && (nsnull != mCachedAttrParamNames[cnt])) {
PR_Free(mCachedAttrParamNames[cnt]);
mCachedAttrParamNames[cnt] = nsnull;
}
if ((nsnull != mAttrVals) && (nsnull != mAttrVals[cnt]))
{
PR_Free(mAttrVals[cnt]);
mAttrVals[cnt] = nsnull;
if ((nsnull != mCachedAttrParamValues) && (nsnull != mCachedAttrParamValues[cnt])) {
PR_Free(mCachedAttrParamValues[cnt]);
mCachedAttrParamValues[cnt] = nsnull;
}
}
if (nsnull != mAttrNames)
{
PR_Free(mAttrNames);
mAttrNames = nsnull;
if (nsnull != mCachedAttrParamNames) {
PR_Free(mCachedAttrParamNames);
mCachedAttrParamNames = nsnull;
}
if (nsnull != mAttrVals)
{
PR_Free(mAttrVals);
mAttrVals = nsnull;
if (nsnull != mCachedAttrParamValues) {
PR_Free(mCachedAttrParamValues);
mCachedAttrParamValues = nsnull;
}
for (cnt = 0; cnt < mNumParams; cnt++)
{
if ((nsnull != mParamNames) && (nsnull != mParamNames[cnt]))
{
PR_Free(mParamNames[cnt]);
mParamNames[cnt] = nsnull;
}
if ((nsnull != mParamVals) && (nsnull != mParamVals[cnt]))
{
PR_Free(mParamVals[cnt]);
mParamVals[cnt] = nsnull;
}
}
if (nsnull != mParamNames)
{
PR_Free(mParamNames);
mParamNames = nsnull;
}
if (nsnull != mParamVals)
{
PR_Free(mParamVals);
mParamVals = nsnull;
}
if (nsnull != mDocumentBase)
{
if (nsnull != mDocumentBase) {
nsCRT::free(mDocumentBase);
mDocumentBase = nsnull;
}
if (nsnull != mTagText)
{
if (nsnull != mTagText) {
nsCRT::free(mTagText);
mTagText = nsnull;
}
@ -2063,90 +2030,12 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetAttributes(PRUint16& n,
const char*const*& names,
const char*const*& values)
{
nsresult rv;
nsIContent* iContent;
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
if ((nsnull == mAttrNames) && (nsnull != mOwner)) {
rv = mOwner->GetContent(&iContent);
if (NS_SUCCEEDED(rv)) {
PRInt32 count;
if (NS_SUCCEEDED(iContent->GetAttrCount(count))) {
PRInt32 index;
mAttrNames = (char **)PR_Calloc(sizeof(char *) * count, 1);
mAttrVals = (char **)PR_Calloc(sizeof(char *) * count, 1);
mNumAttrs = 0;
if ((nsnull != mAttrNames) && (nsnull != mAttrVals)) {
for (index = 0; index < count; index++) {
PRInt32 nameSpaceID;
nsCOMPtr<nsIAtom> atom;
nsCOMPtr<nsIAtom> prefix;
iContent->GetAttrNameAt(index, nameSpaceID,
*getter_AddRefs(atom),
*getter_AddRefs(prefix));
nsAutoString value;
if (NS_CONTENT_ATTR_HAS_VALUE ==
iContent->GetAttr(nameSpaceID, atom, value)) {
nsAutoString name;
atom->ToString(name);
/* Changing to ToNewUTF8String addressing 17169, 39789
mAttrNames[mNumAttrs] = (char *)PR_Malloc(name.Length() + 1);
mAttrVals[mNumAttrs] = (char *)PR_Malloc(value.Length() + 1);
if ((nsnull != mAttrNames[mNumAttrs]) &&
(nsnull != mAttrVals[mNumAttrs]))
{
name.ToCString(mAttrNames[mNumAttrs], name.Length() + 1);
value.ToCString(mAttrVals[mNumAttrs], value.Length() + 1);
mNumAttrs++;
}
else
{
if (nsnull != mAttrNames[mNumAttrs])
{
PR_Free(mAttrNames[mNumAttrs]);
mAttrNames[mNumAttrs] = nsnull;
}
if (nsnull != mAttrVals[mNumAttrs])
{
PR_Free(mAttrVals[mNumAttrs]);
mAttrVals[mNumAttrs] = nsnull;
}
}
*/
mAttrNames[mNumAttrs] = ToNewUTF8String(name);
mAttrVals[mNumAttrs] = ToNewUTF8String(value);
mNumAttrs++;
}
}
}
else {
rv = NS_ERROR_OUT_OF_MEMORY;
if (nsnull != mAttrVals) {
PR_Free(mAttrVals);
mAttrVals = nsnull;
}
if (nsnull != mAttrNames) {
PR_Free(mAttrNames);
mAttrNames = nsnull;
}
}
}
NS_RELEASE(iContent);
}
}
else {
rv = NS_OK;
}
n = mNumAttrs;
names = (const char **)mAttrNames;
values = (const char **)mAttrVals;
n = mNumCachedAttrs;
names = (const char **)mCachedAttrParamNames;
values = (const char **)mCachedAttrParamValues;
return rv;
}
@ -2155,18 +2044,15 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetAttribute(const char* name, const char*
{
NS_ENSURE_ARG_POINTER(name);
NS_ENSURE_ARG_POINTER(result);
if (nsnull == mAttrNames) {
PRUint16 numattrs;
const char * const *names, * const *vals;
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
GetAttributes(numattrs, names, vals);
}
*result = nsnull;
*result = NULL;
for (int i = 0; i < mNumAttrs; i++) {
if (0 == PL_strcasecmp(mAttrNames[i], name)) {
*result = mAttrVals[i];
for (int i = 0; i < mNumCachedAttrs; i++) {
if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
*result = mCachedAttrParamValues[i];
return NS_OK;
}
}
@ -2527,148 +2413,16 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetTagText(const char* *result)
NS_IMETHODIMP nsPluginInstanceOwner::GetParameters(PRUint16& n, const char*const*& names, const char*const*& values)
{
nsresult rv = NS_ERROR_FAILURE;
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
if ((nsnull == mParamNames) && (nsnull != mOwner))
{
nsIContent *cont;
// make sure we have at least one param tag because embed's don't have any
if (!mNumCachedParams)
return NS_ERROR_FAILURE;
mOwner->GetContent(&cont);
if (nsnull != cont)
{
PRBool haskids = PR_FALSE;
cont->CanContainChildren(haskids);
if (PR_TRUE == haskids)
{
PRInt32 numkids, idx, numparams = 0;
cont->ChildCount(numkids);
//first pass, count number of param tags...
for (idx = 0; idx < numkids; idx++)
{
nsIContent *kid;
cont->ChildAt(idx, kid);
if (nsnull != kid)
{
nsIAtom *atom;
kid->GetTag(atom);
if (nsnull != atom)
{
if (atom == nsHTMLAtoms::param)
numparams++;
NS_RELEASE(atom);
}
NS_RELEASE(kid);
}
}
if (numparams > 0)
{
//now we need to create arrays
//representing the parameter name/value pairs...
mParamNames = (char **)PR_Calloc(sizeof(char *) * numparams, 1);
mParamVals = (char **)PR_Calloc(sizeof(char *) * numparams, 1);
if ((nsnull != mParamNames) && (nsnull != mParamVals))
{
for (idx = 0; idx < numkids; idx++)
{
nsIContent *kid;
cont->ChildAt(idx, kid);
if (nsnull != kid)
{
nsIAtom *atom;
kid->GetTag(atom);
if (nsnull != atom)
{
if (atom == nsHTMLAtoms::param)
{
nsAutoString val, name;
//add param to list...
if ((NS_CONTENT_ATTR_HAS_VALUE == kid->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::name, name)) &&
(NS_CONTENT_ATTR_HAS_VALUE == kid->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::value, val)))
{
/* Changing to ToNewUTF8String addressing 17169, 39789
mParamNames[mNumParams] = (char *)PR_Malloc(name.Length() + 1);
mParamVals[mNumParams] = (char *)PR_Malloc(val.Length() + 1);
if ((nsnull != mParamNames[mNumParams]) &&
(nsnull != mParamVals[mNumParams]))
{
name.ToCString(mParamNames[mNumParams], name.Length() + 1);
val.ToCString(mParamVals[mNumParams], val.Length() + 1);
mNumParams++;
}
else
{
if (nsnull != mParamNames[mNumParams])
{
PR_Free(mParamNames[mNumParams]);
mParamNames[mNumParams] = nsnull;
}
if (nsnull != mParamVals[mNumParams])
{
PR_Free(mParamVals[mNumParams]);
mParamVals[mNumParams] = nsnull;
}
}
*/
/* According to the HTML 4.01 spec, at
* http://www.w3.org/TR/html4/types.html#type-cdata
* ''User agents may ignore leading and trailing
* white space in CDATA attribute values (e.g., "
* myval " may be interpreted as "myval"). Authors
* should not declare attribute values with
* leading or trailing white space.''
*/
name.CompressWhitespace();
val.CompressWhitespace();
mParamNames[mNumParams] = ToNewUTF8String(name);
mParamVals[mNumParams] = ToNewUTF8String(val);
mNumParams++;
}
}
NS_RELEASE(atom);
}
}
NS_RELEASE(kid);
}
}
}
}
rv = NS_OK;
NS_RELEASE(cont);
}
}
n = mNumParams;
names = (const char **)mParamNames;
values = (const char **)mParamVals;
n = mNumCachedParams;
names = (const char **)(mCachedAttrParamNames + mNumCachedAttrs + 1);
values = (const char **)(mCachedAttrParamValues + mNumCachedAttrs + 1);
return rv;
}
@ -2677,32 +2431,20 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetParameter(const char* name, const char*
{
NS_ENSURE_ARG_POINTER(name);
NS_ENSURE_ARG_POINTER(result);
nsresult rv;
PRInt32 count;
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
if (nsnull == mParamNames)
{
PRUint16 numattrs;
const char * const *names, * const *vals;
*result = nsnull;
rv = GetParameters(numattrs, names, vals);
}
for (count = 0; count < mNumParams; count++)
{
if (0 == PL_strcasecmp(mParamNames[count], name))
{
*result = mParamVals[count];
break;
for (int i = mNumCachedAttrs + 1; i < (mNumCachedParams + 1 + mNumCachedAttrs); i++) {
if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
*result = mCachedAttrParamValues[i];
return NS_OK;
}
}
if (count >= mNumParams) {
*result = "";
rv = NS_ERROR_FAILURE;
}
return rv;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsPluginInstanceOwner::GetDocumentBase(const char* *result)
@ -3000,6 +2742,155 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetMayScript(PRBool *result)
return NS_OK;
}
// Cache the attributes and/or parameters of our tag into a single set of arrays
// to be compatible with 4.x. The attributes go first, followed by a PARAM/null and
// then any PARAM tags. Also, hold the cached array around for the duration
// of the life of the instance because 4.x did. See bug 111008.
nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
{
if (mCachedAttrParamValues)
return NS_OK;
NS_PRECONDITION((((mNumCachedAttrs + mNumCachedParams) == 0) && !mCachedAttrParamNames),
"re-cache of attrs/params not implemented! use the DOM node directy instead");
NS_ENSURE_TRUE(mOwner, NS_ERROR_NULL_POINTER);
// first, we need to find out how much we need to allocate for our arrays
// count up attributes
mNumCachedAttrs = 0;
nsCOMPtr<nsIContent> content;
nsresult rv = mOwner->GetContent(getter_AddRefs(content));
NS_ENSURE_TRUE(content, rv);
rv = content->GetAttrCount((PRInt32&)mNumCachedAttrs); // signed 32 bits to unsigned 16 bits conversion
NS_ENSURE_SUCCESS(rv, rv);
// now, we need to find all the PARAM tags that are children of us
// however, be carefull NOT to include any PARAMs that don't have us as a direct
// parent. For nested object (or applet) tags, be sure to only round up the
// param tags that coorespond with THIS instance. And also, weed out any bogus
// tags that may get in the way, see bug 39609. Then, with any param tag that meet our
// qualification, temporarly cache them in an nsISupportsArray until we can figure out
// what size to make our fixed char* array.
mNumCachedParams = 0;
nsCOMPtr<nsISupportsArray> ourParams;
rv = NS_NewISupportsArray(getter_AddRefs(ourParams));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> mydomNode = do_QueryInterface(content);
NS_ENSURE_TRUE(mydomNode, NS_ERROR_NO_INTERFACE);
// use the DOM to get us ALL our dependant PARAM tags, even if not ours
nsCOMPtr<nsIDOMElement> mydomElement = do_QueryInterface(mydomNode);
NS_ENSURE_TRUE(mydomElement, NS_ERROR_NO_INTERFACE);
nsCOMPtr<nsIDOMNodeList> allParams;
mydomElement->GetElementsByTagName(NS_LITERAL_STRING("PARAM"), getter_AddRefs(allParams));
if (allParams) {
PRUint32 numAllParams;
allParams->GetLength(&numAllParams);
// loop through every so called dependant PARAM tag to check if it "belongs" to us
for (PRUint32 i = 0; i < numAllParams; i++) {
nsCOMPtr<nsIDOMNode> pnode;
allParams->Item(i, getter_AddRefs(pnode));
if (pnode) {
nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(pnode);
if (domelement) {
// let's NOT count up param tags that don't have a name attribute
nsAutoString name;
domelement->GetAttribute(NS_LITERAL_STRING("name"), name);
if (name.Length() > 0) {
nsCOMPtr<nsIDOMNode> parent;
nsCOMPtr<nsIDOMHTMLObjectElement> domobject;
nsCOMPtr<nsIDOMHTMLAppletElement> domapplet;
pnode->GetParentNode(getter_AddRefs(parent));
// walk up the parents of this PARAM until we find an object (or applet) tag
while (!(domobject || domapplet) && parent) {
domobject = do_QueryInterface(parent);
domapplet = do_QueryInterface(parent);
nsCOMPtr<nsIDOMNode> temp;
parent->GetParentNode(getter_AddRefs(temp));
parent = temp;
}
if (domapplet || domobject) {
parent = domapplet ? do_QueryInterface(domapplet) : do_QueryInterface(domobject);
// now check to see if this PARAM's parent is us. if so, cache it for later
if (parent.get() == mydomNode.get()) {
nsCOMPtr<nsISupports> sup = do_QueryInterface(pnode);
NS_ASSERTION(sup, "lame! DOM node does doesn't QI to nsISupports");
ourParams->AppendElement(sup);
}
}
}
}
}
}
}
ourParams->Count((PRUint32*)&mNumCachedParams); // unsigned 32 bits to unsigned 16 bits conversion
// now lets make the arrays
mCachedAttrParamNames = (char **)PR_Calloc(sizeof(char *) * (mNumCachedAttrs + 1 + mNumCachedParams), 1);
NS_ENSURE_TRUE(mCachedAttrParamNames, NS_ERROR_OUT_OF_MEMORY);
mCachedAttrParamValues = (char **)PR_Calloc(sizeof(char *) * (mNumCachedAttrs + 1 + mNumCachedParams), 1);
NS_ENSURE_TRUE(mCachedAttrParamValues, NS_ERROR_OUT_OF_MEMORY);
// let's fill in our attributes
PRInt16 c = 0;
for (PRInt16 index = 0; index < mNumCachedAttrs; index++) {
PRInt32 nameSpaceID;
nsCOMPtr<nsIAtom> atom;
nsCOMPtr<nsIAtom> prefix;
content->GetAttrNameAt(index, nameSpaceID,
*getter_AddRefs(atom),
*getter_AddRefs(prefix));
nsAutoString value;
if (NS_CONTENT_ATTR_NOT_THERE != content->GetAttr(nameSpaceID, atom, value)) {
nsAutoString name;
atom->ToString(name);
mCachedAttrParamNames [c] = ToNewUTF8String(name);
mCachedAttrParamValues[c] = ToNewUTF8String(value);
c++;
}
}
// add our PARAM and null seperator
mCachedAttrParamNames [mNumCachedAttrs + 1] = "PARAM";
mCachedAttrParamValues[mNumCachedAttrs + 1] = nsnull;
// now fill in the PARAM name/value pairs from the cached DOM nodes
c = 0;
for (PRInt16 idx = 0; idx < mNumCachedParams; idx++) {
nsCOMPtr<nsISupports> sup = ourParams->ElementAt(idx);
if (sup) {
nsCOMPtr<nsIDOMElement> param = do_QueryInterface(sup);
if (param) {
nsAutoString name;
nsAutoString value;
param->GetAttribute(NS_LITERAL_STRING("name"), name); // check for empty done above
param->GetAttribute(NS_LITERAL_STRING("value"), value);
/*
* According to the HTML 4.01 spec, at
* http://www.w3.org/TR/html4/types.html#type-cdata
* ''User agents may ignore leading and trailing
* white space in CDATA attribute values (e.g., "
* myval " may be interpreted as "myval"). Authors
* should not declare attribute values with
* leading or trailing white space.''
*/
name.CompressWhitespace(); // XXX right function?
value.CompressWhitespace();
mCachedAttrParamNames [mNumCachedAttrs + 1 + c] = ToNewUTF8String(name);
mCachedAttrParamValues[mNumCachedAttrs + 1 + c] = ToNewUTF8String(value);
c++; // rules!
}
}
}
return NS_OK;
}
// Here's where we forward events to plugins.
#ifdef XP_MAC

Просмотреть файл

@ -73,6 +73,9 @@
#include "nsIDocShellTreeOwner.h"
#include "nsIWebBrowserChrome.h"
#include "nsIDOMElement.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMHTMLObjectElement.h"
#include "nsIDOMHTMLAppletElement.h"
#include "nsContentPolicyUtils.h"
#include "nsIDOMWindow.h"
#include "nsIDOMMouseListener.h"
@ -283,12 +286,6 @@ private:
nsPluginWindow mPluginWindow;
nsIPluginInstance *mInstance;
nsObjectFrame *mOwner;
PRInt32 mNumAttrs;
char **mAttrNames;
char **mAttrVals;
PRInt32 mNumParams;
char **mParamNames;
char **mParamVals;
char *mDocumentBase;
char *mTagText;
nsIWidget *mWidget;
@ -296,10 +293,16 @@ private:
nsCOMPtr<nsITimer> mPluginTimer;
nsIPluginHost *mPluginHost;
PRPackedBool mContentFocused;
PRUint16 mNumCachedAttrs;
PRUint16 mNumCachedParams;
char **mCachedAttrParamNames;
char **mCachedAttrParamValues;
nsresult DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent);
nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent);
nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
nsresult EnsureCachedAttrParamArrays();
};
// Mac specific code to fix up port position and clip during paint
@ -1929,18 +1932,16 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
memset(&mPluginWindow, 0, sizeof(mPluginWindow));
mInstance = nsnull;
mOwner = nsnull;
mNumAttrs = 0;
mAttrNames = nsnull;
mAttrVals = nsnull;
mWidget = nsnull;
mContext = nsnull;
mNumParams = 0;
mParamNames = nsnull;
mParamVals = nsnull;
mDocumentBase = nsnull;
mTagText = nsnull;
mPluginHost = nsnull;
mContentFocused = PR_FALSE;
mNumCachedAttrs = 0;
mNumCachedParams = 0;
mCachedAttrParamNames = nsnull;
mCachedAttrParamValues = nsnull;
}
nsPluginInstanceOwner::~nsPluginInstanceOwner()
@ -1956,68 +1957,34 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
NS_IF_RELEASE(mPluginHost);
mOwner = nsnull;
for (cnt = 0; cnt < mNumAttrs; cnt++)
{
if ((nsnull != mAttrNames) && (nsnull != mAttrNames[cnt]))
{
PR_Free(mAttrNames[cnt]);
mAttrNames[cnt] = nsnull;
for (cnt = 0; cnt < (mNumCachedAttrs + 1 + mNumCachedParams); cnt++) {
if ((nsnull != mCachedAttrParamNames) && (nsnull != mCachedAttrParamNames[cnt])) {
PR_Free(mCachedAttrParamNames[cnt]);
mCachedAttrParamNames[cnt] = nsnull;
}
if ((nsnull != mAttrVals) && (nsnull != mAttrVals[cnt]))
{
PR_Free(mAttrVals[cnt]);
mAttrVals[cnt] = nsnull;
if ((nsnull != mCachedAttrParamValues) && (nsnull != mCachedAttrParamValues[cnt])) {
PR_Free(mCachedAttrParamValues[cnt]);
mCachedAttrParamValues[cnt] = nsnull;
}
}
if (nsnull != mAttrNames)
{
PR_Free(mAttrNames);
mAttrNames = nsnull;
if (nsnull != mCachedAttrParamNames) {
PR_Free(mCachedAttrParamNames);
mCachedAttrParamNames = nsnull;
}
if (nsnull != mAttrVals)
{
PR_Free(mAttrVals);
mAttrVals = nsnull;
if (nsnull != mCachedAttrParamValues) {
PR_Free(mCachedAttrParamValues);
mCachedAttrParamValues = nsnull;
}
for (cnt = 0; cnt < mNumParams; cnt++)
{
if ((nsnull != mParamNames) && (nsnull != mParamNames[cnt]))
{
PR_Free(mParamNames[cnt]);
mParamNames[cnt] = nsnull;
}
if ((nsnull != mParamVals) && (nsnull != mParamVals[cnt]))
{
PR_Free(mParamVals[cnt]);
mParamVals[cnt] = nsnull;
}
}
if (nsnull != mParamNames)
{
PR_Free(mParamNames);
mParamNames = nsnull;
}
if (nsnull != mParamVals)
{
PR_Free(mParamVals);
mParamVals = nsnull;
}
if (nsnull != mDocumentBase)
{
if (nsnull != mDocumentBase) {
nsCRT::free(mDocumentBase);
mDocumentBase = nsnull;
}
if (nsnull != mTagText)
{
if (nsnull != mTagText) {
nsCRT::free(mTagText);
mTagText = nsnull;
}
@ -2063,90 +2030,12 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetAttributes(PRUint16& n,
const char*const*& names,
const char*const*& values)
{
nsresult rv;
nsIContent* iContent;
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
if ((nsnull == mAttrNames) && (nsnull != mOwner)) {
rv = mOwner->GetContent(&iContent);
if (NS_SUCCEEDED(rv)) {
PRInt32 count;
if (NS_SUCCEEDED(iContent->GetAttrCount(count))) {
PRInt32 index;
mAttrNames = (char **)PR_Calloc(sizeof(char *) * count, 1);
mAttrVals = (char **)PR_Calloc(sizeof(char *) * count, 1);
mNumAttrs = 0;
if ((nsnull != mAttrNames) && (nsnull != mAttrVals)) {
for (index = 0; index < count; index++) {
PRInt32 nameSpaceID;
nsCOMPtr<nsIAtom> atom;
nsCOMPtr<nsIAtom> prefix;
iContent->GetAttrNameAt(index, nameSpaceID,
*getter_AddRefs(atom),
*getter_AddRefs(prefix));
nsAutoString value;
if (NS_CONTENT_ATTR_HAS_VALUE ==
iContent->GetAttr(nameSpaceID, atom, value)) {
nsAutoString name;
atom->ToString(name);
/* Changing to ToNewUTF8String addressing 17169, 39789
mAttrNames[mNumAttrs] = (char *)PR_Malloc(name.Length() + 1);
mAttrVals[mNumAttrs] = (char *)PR_Malloc(value.Length() + 1);
if ((nsnull != mAttrNames[mNumAttrs]) &&
(nsnull != mAttrVals[mNumAttrs]))
{
name.ToCString(mAttrNames[mNumAttrs], name.Length() + 1);
value.ToCString(mAttrVals[mNumAttrs], value.Length() + 1);
mNumAttrs++;
}
else
{
if (nsnull != mAttrNames[mNumAttrs])
{
PR_Free(mAttrNames[mNumAttrs]);
mAttrNames[mNumAttrs] = nsnull;
}
if (nsnull != mAttrVals[mNumAttrs])
{
PR_Free(mAttrVals[mNumAttrs]);
mAttrVals[mNumAttrs] = nsnull;
}
}
*/
mAttrNames[mNumAttrs] = ToNewUTF8String(name);
mAttrVals[mNumAttrs] = ToNewUTF8String(value);
mNumAttrs++;
}
}
}
else {
rv = NS_ERROR_OUT_OF_MEMORY;
if (nsnull != mAttrVals) {
PR_Free(mAttrVals);
mAttrVals = nsnull;
}
if (nsnull != mAttrNames) {
PR_Free(mAttrNames);
mAttrNames = nsnull;
}
}
}
NS_RELEASE(iContent);
}
}
else {
rv = NS_OK;
}
n = mNumAttrs;
names = (const char **)mAttrNames;
values = (const char **)mAttrVals;
n = mNumCachedAttrs;
names = (const char **)mCachedAttrParamNames;
values = (const char **)mCachedAttrParamValues;
return rv;
}
@ -2155,18 +2044,15 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetAttribute(const char* name, const char*
{
NS_ENSURE_ARG_POINTER(name);
NS_ENSURE_ARG_POINTER(result);
if (nsnull == mAttrNames) {
PRUint16 numattrs;
const char * const *names, * const *vals;
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
GetAttributes(numattrs, names, vals);
}
*result = nsnull;
*result = NULL;
for (int i = 0; i < mNumAttrs; i++) {
if (0 == PL_strcasecmp(mAttrNames[i], name)) {
*result = mAttrVals[i];
for (int i = 0; i < mNumCachedAttrs; i++) {
if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
*result = mCachedAttrParamValues[i];
return NS_OK;
}
}
@ -2527,148 +2413,16 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetTagText(const char* *result)
NS_IMETHODIMP nsPluginInstanceOwner::GetParameters(PRUint16& n, const char*const*& names, const char*const*& values)
{
nsresult rv = NS_ERROR_FAILURE;
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
if ((nsnull == mParamNames) && (nsnull != mOwner))
{
nsIContent *cont;
// make sure we have at least one param tag because embed's don't have any
if (!mNumCachedParams)
return NS_ERROR_FAILURE;
mOwner->GetContent(&cont);
if (nsnull != cont)
{
PRBool haskids = PR_FALSE;
cont->CanContainChildren(haskids);
if (PR_TRUE == haskids)
{
PRInt32 numkids, idx, numparams = 0;
cont->ChildCount(numkids);
//first pass, count number of param tags...
for (idx = 0; idx < numkids; idx++)
{
nsIContent *kid;
cont->ChildAt(idx, kid);
if (nsnull != kid)
{
nsIAtom *atom;
kid->GetTag(atom);
if (nsnull != atom)
{
if (atom == nsHTMLAtoms::param)
numparams++;
NS_RELEASE(atom);
}
NS_RELEASE(kid);
}
}
if (numparams > 0)
{
//now we need to create arrays
//representing the parameter name/value pairs...
mParamNames = (char **)PR_Calloc(sizeof(char *) * numparams, 1);
mParamVals = (char **)PR_Calloc(sizeof(char *) * numparams, 1);
if ((nsnull != mParamNames) && (nsnull != mParamVals))
{
for (idx = 0; idx < numkids; idx++)
{
nsIContent *kid;
cont->ChildAt(idx, kid);
if (nsnull != kid)
{
nsIAtom *atom;
kid->GetTag(atom);
if (nsnull != atom)
{
if (atom == nsHTMLAtoms::param)
{
nsAutoString val, name;
//add param to list...
if ((NS_CONTENT_ATTR_HAS_VALUE == kid->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::name, name)) &&
(NS_CONTENT_ATTR_HAS_VALUE == kid->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::value, val)))
{
/* Changing to ToNewUTF8String addressing 17169, 39789
mParamNames[mNumParams] = (char *)PR_Malloc(name.Length() + 1);
mParamVals[mNumParams] = (char *)PR_Malloc(val.Length() + 1);
if ((nsnull != mParamNames[mNumParams]) &&
(nsnull != mParamVals[mNumParams]))
{
name.ToCString(mParamNames[mNumParams], name.Length() + 1);
val.ToCString(mParamVals[mNumParams], val.Length() + 1);
mNumParams++;
}
else
{
if (nsnull != mParamNames[mNumParams])
{
PR_Free(mParamNames[mNumParams]);
mParamNames[mNumParams] = nsnull;
}
if (nsnull != mParamVals[mNumParams])
{
PR_Free(mParamVals[mNumParams]);
mParamVals[mNumParams] = nsnull;
}
}
*/
/* According to the HTML 4.01 spec, at
* http://www.w3.org/TR/html4/types.html#type-cdata
* ''User agents may ignore leading and trailing
* white space in CDATA attribute values (e.g., "
* myval " may be interpreted as "myval"). Authors
* should not declare attribute values with
* leading or trailing white space.''
*/
name.CompressWhitespace();
val.CompressWhitespace();
mParamNames[mNumParams] = ToNewUTF8String(name);
mParamVals[mNumParams] = ToNewUTF8String(val);
mNumParams++;
}
}
NS_RELEASE(atom);
}
}
NS_RELEASE(kid);
}
}
}
}
rv = NS_OK;
NS_RELEASE(cont);
}
}
n = mNumParams;
names = (const char **)mParamNames;
values = (const char **)mParamVals;
n = mNumCachedParams;
names = (const char **)(mCachedAttrParamNames + mNumCachedAttrs + 1);
values = (const char **)(mCachedAttrParamValues + mNumCachedAttrs + 1);
return rv;
}
@ -2677,32 +2431,20 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetParameter(const char* name, const char*
{
NS_ENSURE_ARG_POINTER(name);
NS_ENSURE_ARG_POINTER(result);
nsresult rv;
PRInt32 count;
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
if (nsnull == mParamNames)
{
PRUint16 numattrs;
const char * const *names, * const *vals;
*result = nsnull;
rv = GetParameters(numattrs, names, vals);
}
for (count = 0; count < mNumParams; count++)
{
if (0 == PL_strcasecmp(mParamNames[count], name))
{
*result = mParamVals[count];
break;
for (int i = mNumCachedAttrs + 1; i < (mNumCachedParams + 1 + mNumCachedAttrs); i++) {
if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
*result = mCachedAttrParamValues[i];
return NS_OK;
}
}
if (count >= mNumParams) {
*result = "";
rv = NS_ERROR_FAILURE;
}
return rv;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsPluginInstanceOwner::GetDocumentBase(const char* *result)
@ -3000,6 +2742,155 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetMayScript(PRBool *result)
return NS_OK;
}
// Cache the attributes and/or parameters of our tag into a single set of arrays
// to be compatible with 4.x. The attributes go first, followed by a PARAM/null and
// then any PARAM tags. Also, hold the cached array around for the duration
// of the life of the instance because 4.x did. See bug 111008.
nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
{
if (mCachedAttrParamValues)
return NS_OK;
NS_PRECONDITION((((mNumCachedAttrs + mNumCachedParams) == 0) && !mCachedAttrParamNames),
"re-cache of attrs/params not implemented! use the DOM node directy instead");
NS_ENSURE_TRUE(mOwner, NS_ERROR_NULL_POINTER);
// first, we need to find out how much we need to allocate for our arrays
// count up attributes
mNumCachedAttrs = 0;
nsCOMPtr<nsIContent> content;
nsresult rv = mOwner->GetContent(getter_AddRefs(content));
NS_ENSURE_TRUE(content, rv);
rv = content->GetAttrCount((PRInt32&)mNumCachedAttrs); // signed 32 bits to unsigned 16 bits conversion
NS_ENSURE_SUCCESS(rv, rv);
// now, we need to find all the PARAM tags that are children of us
// however, be carefull NOT to include any PARAMs that don't have us as a direct
// parent. For nested object (or applet) tags, be sure to only round up the
// param tags that coorespond with THIS instance. And also, weed out any bogus
// tags that may get in the way, see bug 39609. Then, with any param tag that meet our
// qualification, temporarly cache them in an nsISupportsArray until we can figure out
// what size to make our fixed char* array.
mNumCachedParams = 0;
nsCOMPtr<nsISupportsArray> ourParams;
rv = NS_NewISupportsArray(getter_AddRefs(ourParams));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> mydomNode = do_QueryInterface(content);
NS_ENSURE_TRUE(mydomNode, NS_ERROR_NO_INTERFACE);
// use the DOM to get us ALL our dependant PARAM tags, even if not ours
nsCOMPtr<nsIDOMElement> mydomElement = do_QueryInterface(mydomNode);
NS_ENSURE_TRUE(mydomElement, NS_ERROR_NO_INTERFACE);
nsCOMPtr<nsIDOMNodeList> allParams;
mydomElement->GetElementsByTagName(NS_LITERAL_STRING("PARAM"), getter_AddRefs(allParams));
if (allParams) {
PRUint32 numAllParams;
allParams->GetLength(&numAllParams);
// loop through every so called dependant PARAM tag to check if it "belongs" to us
for (PRUint32 i = 0; i < numAllParams; i++) {
nsCOMPtr<nsIDOMNode> pnode;
allParams->Item(i, getter_AddRefs(pnode));
if (pnode) {
nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(pnode);
if (domelement) {
// let's NOT count up param tags that don't have a name attribute
nsAutoString name;
domelement->GetAttribute(NS_LITERAL_STRING("name"), name);
if (name.Length() > 0) {
nsCOMPtr<nsIDOMNode> parent;
nsCOMPtr<nsIDOMHTMLObjectElement> domobject;
nsCOMPtr<nsIDOMHTMLAppletElement> domapplet;
pnode->GetParentNode(getter_AddRefs(parent));
// walk up the parents of this PARAM until we find an object (or applet) tag
while (!(domobject || domapplet) && parent) {
domobject = do_QueryInterface(parent);
domapplet = do_QueryInterface(parent);
nsCOMPtr<nsIDOMNode> temp;
parent->GetParentNode(getter_AddRefs(temp));
parent = temp;
}
if (domapplet || domobject) {
parent = domapplet ? do_QueryInterface(domapplet) : do_QueryInterface(domobject);
// now check to see if this PARAM's parent is us. if so, cache it for later
if (parent.get() == mydomNode.get()) {
nsCOMPtr<nsISupports> sup = do_QueryInterface(pnode);
NS_ASSERTION(sup, "lame! DOM node does doesn't QI to nsISupports");
ourParams->AppendElement(sup);
}
}
}
}
}
}
}
ourParams->Count((PRUint32*)&mNumCachedParams); // unsigned 32 bits to unsigned 16 bits conversion
// now lets make the arrays
mCachedAttrParamNames = (char **)PR_Calloc(sizeof(char *) * (mNumCachedAttrs + 1 + mNumCachedParams), 1);
NS_ENSURE_TRUE(mCachedAttrParamNames, NS_ERROR_OUT_OF_MEMORY);
mCachedAttrParamValues = (char **)PR_Calloc(sizeof(char *) * (mNumCachedAttrs + 1 + mNumCachedParams), 1);
NS_ENSURE_TRUE(mCachedAttrParamValues, NS_ERROR_OUT_OF_MEMORY);
// let's fill in our attributes
PRInt16 c = 0;
for (PRInt16 index = 0; index < mNumCachedAttrs; index++) {
PRInt32 nameSpaceID;
nsCOMPtr<nsIAtom> atom;
nsCOMPtr<nsIAtom> prefix;
content->GetAttrNameAt(index, nameSpaceID,
*getter_AddRefs(atom),
*getter_AddRefs(prefix));
nsAutoString value;
if (NS_CONTENT_ATTR_NOT_THERE != content->GetAttr(nameSpaceID, atom, value)) {
nsAutoString name;
atom->ToString(name);
mCachedAttrParamNames [c] = ToNewUTF8String(name);
mCachedAttrParamValues[c] = ToNewUTF8String(value);
c++;
}
}
// add our PARAM and null seperator
mCachedAttrParamNames [mNumCachedAttrs + 1] = "PARAM";
mCachedAttrParamValues[mNumCachedAttrs + 1] = nsnull;
// now fill in the PARAM name/value pairs from the cached DOM nodes
c = 0;
for (PRInt16 idx = 0; idx < mNumCachedParams; idx++) {
nsCOMPtr<nsISupports> sup = ourParams->ElementAt(idx);
if (sup) {
nsCOMPtr<nsIDOMElement> param = do_QueryInterface(sup);
if (param) {
nsAutoString name;
nsAutoString value;
param->GetAttribute(NS_LITERAL_STRING("name"), name); // check for empty done above
param->GetAttribute(NS_LITERAL_STRING("value"), value);
/*
* According to the HTML 4.01 spec, at
* http://www.w3.org/TR/html4/types.html#type-cdata
* ''User agents may ignore leading and trailing
* white space in CDATA attribute values (e.g., "
* myval " may be interpreted as "myval"). Authors
* should not declare attribute values with
* leading or trailing white space.''
*/
name.CompressWhitespace(); // XXX right function?
value.CompressWhitespace();
mCachedAttrParamNames [mNumCachedAttrs + 1 + c] = ToNewUTF8String(name);
mCachedAttrParamValues[mNumCachedAttrs + 1 + c] = ToNewUTF8String(value);
c++; // rules!
}
}
}
return NS_OK;
}
// Here's where we forward events to plugins.
#ifdef XP_MAC

Просмотреть файл

@ -796,36 +796,45 @@ NS_IMETHODIMP ns4xPluginInstance::Stop(void)
////////////////////////////////////////////////////////////////////////
nsresult ns4xPluginInstance::InitializePlugin(nsIPluginInstancePeer* peer)
{
NS_ENSURE_ARG_POINTER(peer);
mPeer = peer;
nsCOMPtr<nsIPluginTagInfo2> taginfo = do_QueryInterface(mPeer);
NS_ENSURE_TRUE(taginfo, NS_ERROR_NO_INTERFACE);
nsPluginTagType tagtype;
nsresult rv = taginfo->GetTagType(&tagtype);
NS_ENSURE_SUCCESS(rv, rv);
PRUint16 count = 0;
const char* const* names = nsnull;
const char* const* values = nsnull;
nsresult rv;
NPError error;
rv = taginfo->GetAttributes(count, names, values);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(peer != NULL, "null peer");
mPeer = peer;
nsCOMPtr<nsIPluginTagInfo2> taginfo = do_QueryInterface(mPeer, &rv);
if (NS_SUCCEEDED(rv))
{
nsPluginTagType tagtype;
taginfo->GetTagType(&tagtype);
if (tagtype == nsPluginTagType_Embed)
taginfo->GetAttributes(count, names, values);
else // nsPluginTagType_Object
taginfo->GetParameters(count, names, values);
// nsPluginTagType_Object or Applet may also have PARAM tags
// Note: The arrays handed back by GetParameters() are
// crafted specially to be directly behind the arrays from GetAtributes()
// with a null entry as a seperator. This is for 4.x backwards compatibility!
// see bug 111008 for details
if (tagtype != nsPluginTagType_Embed) {
PRUint16 pcount = 0;
const char* const* pnames = nsnull;
const char* const* pvalues = nsnull;
if (NS_SUCCEEDED(taginfo->GetParameters(pcount, pnames, pvalues))) {
NS_ASSERTION(nsnull == values[count+1], "attribute/parameter array not setup correctly for 4.x plugins");
count += ++pcount; //if it's all setup correctly, then all we need is to change the count
}
}
if (fCallbacks->newp == nsnull)
return NS_ERROR_FAILURE; // XXX right error?
NS_ENSURE_TRUE(fCallbacks->newp, NS_ERROR_FAILURE);
// XXX Note that the NPPluginType_* enums were crafted to be
// backward compatible...
nsPluginMode mode;
nsMIMEType mimetype;
NPError error;
mPeer->GetMode(&mode);
mPeer->GetMIMEType(&mimetype);