Bug 853995 - Move plugin parameters array from nsPluginInstanceOwner to content. r=johns,jst

This commit is contained in:
Catalin Badea
2014-08-15 14:17:35 -07:00
committed by John Schoenick
parent 9a6e80a6f0
commit ab8f05696a
7 changed files with 331 additions and 600 deletions

View File

@@ -39,6 +39,7 @@ using mozilla::DefaultXDisplay;
#include "nsIAppShell.h"
#include "nsIDOMHTMLAppletElement.h"
#include "nsIObjectLoadingContent.h"
#include "nsObjectLoadingContent.h"
#include "nsAttrName.h"
#include "nsIFocusManager.h"
#include "nsFocusManager.h"
@@ -53,6 +54,7 @@ using mozilla::DefaultXDisplay;
#include "mozilla/MiscEvents.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/TextEvents.h"
#include "mozilla/dom/HTMLObjectElementBinding.h"
#include "nsContentCID.h"
#include "nsWidgetsCID.h"
@@ -88,6 +90,7 @@ using namespace mozilla::dom;
#endif
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::layers;
// special class for handeling DOM context menu events because for
@@ -280,10 +283,6 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
mWidgetVisible = true;
mPluginWindowVisible = false;
mPluginDocumentActiveState = true;
mNumCachedAttrs = 0;
mNumCachedParams = 0;
mCachedAttrParamNames = nullptr;
mCachedAttrParamValues = nullptr;
mLastMouseDownButtonType = -1;
#ifdef XP_MACOSX
@@ -306,8 +305,6 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
nsPluginInstanceOwner::~nsPluginInstanceOwner()
{
int32_t cnt;
if (mWaitingForPaint) {
// We don't care when the event is dispatched as long as it's "soon",
// since whoever needs it will be waiting for it.
@@ -317,28 +314,6 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
mObjectFrame = nullptr;
for (cnt = 0; cnt < (mNumCachedAttrs + 1 + mNumCachedParams); cnt++) {
if (mCachedAttrParamNames && mCachedAttrParamNames[cnt]) {
NS_Free(mCachedAttrParamNames[cnt]);
mCachedAttrParamNames[cnt] = nullptr;
}
if (mCachedAttrParamValues && mCachedAttrParamValues[cnt]) {
NS_Free(mCachedAttrParamValues[cnt]);
mCachedAttrParamValues[cnt] = nullptr;
}
}
if (mCachedAttrParamNames) {
NS_Free(mCachedAttrParamNames);
mCachedAttrParamNames = nullptr;
}
if (mCachedAttrParamValues) {
NS_Free(mCachedAttrParamValues);
mCachedAttrParamValues = nullptr;
}
PLUG_DeletePluginNativeWindow(mPluginWindow);
mPluginWindow = nullptr;
@@ -411,38 +386,13 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetMode(int32_t *aMode)
return rv;
}
NS_IMETHODIMP nsPluginInstanceOwner::GetAttributes(uint16_t& n,
const char*const*& names,
const char*const*& values)
void nsPluginInstanceOwner::GetAttributes(nsTArray<MozPluginParameter>& attributes)
{
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIObjectLoadingContent> content = do_QueryInterface(mContent);
nsObjectLoadingContent *loadingContent =
static_cast<nsObjectLoadingContent*>(content.get());
n = mNumCachedAttrs;
names = (const char **)mCachedAttrParamNames;
values = (const char **)mCachedAttrParamValues;
return rv;
}
NS_IMETHODIMP nsPluginInstanceOwner::GetAttribute(const char* name, const char* *result)
{
NS_ENSURE_ARG_POINTER(name);
NS_ENSURE_ARG_POINTER(result);
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
*result = nullptr;
for (int i = 0; i < mNumCachedAttrs; i++) {
if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
*result = mCachedAttrParamValues[i];
return NS_OK;
}
}
return NS_ERROR_FAILURE;
loadingContent->GetPluginAttributes(attributes);
}
NS_IMETHODIMP nsPluginInstanceOwner::GetDOMElement(nsIDOMElement* *result)
@@ -789,326 +739,13 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result)
return NS_OK;
}
NS_IMETHODIMP nsPluginInstanceOwner::GetParameters(uint16_t& n, const char*const*& names, const char*const*& values)
void nsPluginInstanceOwner::GetParameters(nsTArray<MozPluginParameter>& parameters)
{
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIObjectLoadingContent> content = do_QueryInterface(mContent);
nsObjectLoadingContent *loadingContent =
static_cast<nsObjectLoadingContent*>(content.get());
n = mNumCachedParams;
if (n) {
names = (const char **)(mCachedAttrParamNames + mNumCachedAttrs + 1);
values = (const char **)(mCachedAttrParamValues + mNumCachedAttrs + 1);
} else
names = values = nullptr;
return rv;
}
NS_IMETHODIMP nsPluginInstanceOwner::GetParameter(const char* name, const char* *result)
{
NS_ENSURE_ARG_POINTER(name);
NS_ENSURE_ARG_POINTER(result);
nsresult rv = EnsureCachedAttrParamArrays();
NS_ENSURE_SUCCESS(rv, rv);
*result = nullptr;
for (int i = mNumCachedAttrs + 1; i < (mNumCachedParams + 1 + mNumCachedAttrs); i++) {
if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
*result = mCachedAttrParamValues[i];
return NS_OK;
}
}
return NS_ERROR_FAILURE;
}
// Cache the attributes and/or parameters of our tag into a single set
// of arrays to be compatible with Netscape 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 Netscape 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");
// Convert to a 16-bit count. Subtract 3 in case we add an extra
// "src", "wmode", or "codebase" entry below.
uint32_t cattrs = mContent->GetAttrCount();
if (cattrs < 0x0000FFFC) {
mNumCachedAttrs = static_cast<uint16_t>(cattrs);
} else {
mNumCachedAttrs = 0xFFFC;
}
// Check if we are java for special codebase handling
const char* mime = nullptr;
bool isJava = NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime &&
nsPluginHost::IsJavaMIMEType(mime);
// now, we need to find all the PARAM tags that are children of us
// however, be careful 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 nsCOMArray until
// we can figure out what size to make our fixed char* array.
nsCOMArray<nsIDOMElement> ourParams;
// Get all dependent PARAM tags, even if they are not direct children.
nsCOMPtr<nsIDOMElement> mydomElement = do_QueryInterface(mContent);
NS_ENSURE_TRUE(mydomElement, NS_ERROR_NO_INTERFACE);
// Making DOM method calls can cause our frame to go away.
nsCOMPtr<nsIPluginInstanceOwner> kungFuDeathGrip(this);
nsCOMPtr<nsIDOMHTMLCollection> allParams;
NS_NAMED_LITERAL_STRING(xhtml_ns, "http://www.w3.org/1999/xhtml");
mydomElement->GetElementsByTagNameNS(xhtml_ns, NS_LITERAL_STRING("param"),
getter_AddRefs(allParams));
if (allParams) {
uint32_t numAllParams;
allParams->GetLength(&numAllParams);
for (uint32_t i = 0; i < numAllParams; i++) {
nsCOMPtr<nsIDOMNode> pnode;
allParams->Item(i, getter_AddRefs(pnode));
nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(pnode);
if (domelement) {
// Ignore params without a name attribute.
nsAutoString name;
domelement->GetAttribute(NS_LITERAL_STRING("name"), name);
if (!name.IsEmpty()) {
// Find the first object or applet parent.
nsCOMPtr<nsIDOMNode> parent;
nsCOMPtr<nsIDOMHTMLObjectElement> domobject;
nsCOMPtr<nsIDOMHTMLAppletElement> domapplet;
pnode->GetParentNode(getter_AddRefs(parent));
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) {
if (domapplet) {
parent = do_QueryInterface(domapplet);
}
else {
parent = do_QueryInterface(domobject);
}
nsCOMPtr<nsIDOMNode> mydomNode = do_QueryInterface(mydomElement);
if (parent == mydomNode) {
ourParams.AppendObject(domelement);
}
}
}
}
}
}
// Convert to a 16-bit count.
uint32_t cparams = ourParams.Count();
if (cparams < 0x0000FFFF) {
mNumCachedParams = static_cast<uint16_t>(cparams);
} else {
mNumCachedParams = 0xFFFF;
}
uint16_t numRealAttrs = mNumCachedAttrs;
// Some plugins were never written to understand the "data" attribute of the OBJECT tag.
// Real and WMP will not play unless they find a "src" attribute, see bug 152334.
// Nav 4.x would simply replace the "data" with "src". Because some plugins correctly
// look for "data", lets instead copy the "data" attribute and add another entry
// to the bottom of the array if there isn't already a "src" specified.
nsAutoString data;
if (mContent->Tag() == nsGkAtoms::object &&
!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::src) &&
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, data) &&
!data.IsEmpty()) {
mNumCachedAttrs++;
}
// "plugins.force.wmode" forces us to send a specific "wmode" parameter,
// used by flash to select a rendering mode. Common values include
// "opaque", "transparent", "windowed", "direct"
nsCString wmodeType;
nsAdoptingCString wmodePref = Preferences::GetCString("plugins.force.wmode");
if (!wmodePref.IsEmpty()) {
mNumCachedAttrs++;
wmodeType = wmodePref;
}
#if defined(XP_WIN) || defined(XP_LINUX)
// Bug 923745 - Until we support windowed mode plugins in content processes,
// force flash to use a windowless rendering mode. This hack should go away
// when bug 923746 lands. (OS X plugins always use some native widgets, so
// unfortunately this does not help there)
else if (XRE_GetProcessType() == GeckoProcessType_Content) {
mNumCachedAttrs++;
wmodeType.AssignLiteral("transparent");
}
#endif
// (Bug 738396) java has quirks in its codebase parsing, pass the
// absolute codebase URI as content sees it.
bool addCodebase = false;
nsAutoCString codebaseStr;
if (isJava) {
nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(mContent);
NS_ENSURE_TRUE(objlc, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIURI> codebaseURI;
nsresult rv = objlc->GetBaseURI(getter_AddRefs(codebaseURI));
NS_ENSURE_SUCCESS(rv, rv);
codebaseURI->GetSpec(codebaseStr);
if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::codebase)) {
mNumCachedAttrs++;
addCodebase = true;
}
}
mCachedAttrParamNames = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
NS_ENSURE_TRUE(mCachedAttrParamNames, NS_ERROR_OUT_OF_MEMORY);
mCachedAttrParamValues = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
NS_ENSURE_TRUE(mCachedAttrParamValues, NS_ERROR_OUT_OF_MEMORY);
// Some plugins (eg Flash, see bug 234675.) are actually sensitive to the
// attribute order. So we want to make sure we give the plugin the
// attributes in the order they came in in the source, to be compatible with
// other browsers. Now in HTML, the storage order is the reverse of the
// source order, while in XML and XHTML it's the same as the source order
// (see the AddAttributes functions in the HTML and XML content sinks).
int32_t start, end, increment;
if (mContent->IsHTML() &&
mContent->IsInHTMLDocument()) {
// HTML. Walk attributes in reverse order.
start = numRealAttrs - 1;
end = -1;
increment = -1;
} else {
// XHTML or XML. Walk attributes in forward order.
start = 0;
end = numRealAttrs;
increment = 1;
}
// Set to the next slot to fill in name and value cache arrays.
uint32_t nextAttrParamIndex = 0;
// Whether or not we force the wmode below while traversing
// the name/value pairs.
bool wmodeSet = false;
// Add attribute name/value pairs.
for (int32_t index = start; index != end; index += increment) {
const nsAttrName* attrName = mContent->GetAttrNameAt(index);
nsIAtom* atom = attrName->LocalName();
nsAutoString value;
mContent->GetAttr(attrName->NamespaceID(), atom, value);
nsAutoString name;
atom->ToString(name);
FixUpURLS(name, value);
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
if (!wmodeType.IsEmpty() &&
0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "wmode")) {
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType));
if (!wmodeSet) {
// We allocated space to add a wmode attr, but we don't need it now.
mNumCachedAttrs--;
wmodeSet = true;
}
} else if (isJava && 0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "codebase")) {
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseStr));
} else {
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
}
nextAttrParamIndex++;
}
// Potentially add CODEBASE attribute
if (addCodebase) {
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("codebase"));
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseStr));
nextAttrParamIndex++;
}
// Potentially add WMODE attribute.
if (!wmodeType.IsEmpty() && !wmodeSet) {
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("wmode"));
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType));
nextAttrParamIndex++;
}
// Potentially add SRC attribute.
if (!data.IsEmpty()) {
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("SRC"));
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(data);
nextAttrParamIndex++;
}
// Add PARAM and null separator.
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
#ifdef MOZ_WIDGET_ANDROID
// Flash expects an empty string on android
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING(""));
#else
mCachedAttrParamValues[nextAttrParamIndex] = nullptr;
#endif
nextAttrParamIndex++;
// Add PARAM name/value pairs.
// We may decrement mNumCachedParams below
uint16_t totalParams = mNumCachedParams;
for (uint16_t i = 0; i < totalParams; i++) {
nsIDOMElement* param = ourParams.ObjectAt(i);
if (!param) {
continue;
}
nsAutoString name;
nsAutoString value;
param->GetAttribute(NS_LITERAL_STRING("name"), name); // check for empty done above
param->GetAttribute(NS_LITERAL_STRING("value"), value);
FixUpURLS(name, 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.''
* However, do not trim consecutive spaces as in bug 122119
*/
name.Trim(" \n\r\t\b", true, true, false);
value.Trim(" \n\r\t\b", true, true, false);
if (isJava && name.EqualsIgnoreCase("codebase")) {
// We inserted normalized codebase above, don't include other versions in
// params
mNumCachedParams--;
continue;
}
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
nextAttrParamIndex++;
}
return NS_OK;
loadingContent->GetPluginParameters(parameters);
}
#ifdef XP_MACOSX
@@ -3168,19 +2805,6 @@ nsObjectFrame* nsPluginInstanceOwner::GetFrame()
return mObjectFrame;
}
// Little helper function to resolve relative URL in
// |value| for certain inputs of |name|
void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value)
{
if (name.LowerCaseEqualsLiteral("pluginspage")) {
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsAutoString newURL;
NS_MakeAbsoluteURI(newURL, value, baseURI);
if (!newURL.IsEmpty())
value = newURL;
}
}
NS_IMETHODIMP nsPluginInstanceOwner::PrivateModeChanged(bool aEnabled)
{
return mInstance ? mInstance->PrivateModeStateChanged(aEnabled) : NS_OK;