зеркало из https://github.com/mozilla/gecko-dev.git
Fixing bug 64755. Moving code around to make plugins instantiated from an <object> tag be scriptable. r=pollmann@netscape.com, sr=hyatt@netscape.com
This commit is contained in:
Родитель
d3f443c44a
Коммит
15cb2acddd
|
@ -94,6 +94,15 @@
|
|||
#include "nsIBindingManager.h"
|
||||
#include "nsIXBLBinding.h"
|
||||
|
||||
#include "nsObjectFrame.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "xptinfo.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
#include "nsIPluginInstance.h"
|
||||
#include "nsIScriptablePlugin.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsIParser.h"
|
||||
#include "nsParserCIID.h"
|
||||
#include "nsIHTMLContentSink.h"
|
||||
|
@ -102,7 +111,207 @@
|
|||
|
||||
#include "nsIPref.h" // Used by the temp pref, should be removed!
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetPluginInstance(nsIPluginInstance** aPluginInstance)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPluginInstance);
|
||||
*aPluginInstance = nsnull;
|
||||
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
|
||||
if (mDocument) {
|
||||
// Make sure the presentation is up-to-date
|
||||
result = mDocument->FlushPendingNotifications();
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
GetPresContext(this, getter_AddRefs(context));
|
||||
if (!context) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
context->GetShell(getter_AddRefs(shell));
|
||||
if (!shell) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFrame* frame = nsnull;
|
||||
shell->GetPrimaryFrameFor(this, &frame);
|
||||
if (!frame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> type;
|
||||
|
||||
frame->GetFrameType(getter_AddRefs(type));
|
||||
|
||||
if (type.get() == nsLayoutAtoms::objectFrame) {
|
||||
// XXX We could have created an interface for this, but Troy
|
||||
// preferred the ugliness of a static cast to the weight of
|
||||
// a new interface.
|
||||
|
||||
nsObjectFrame* objectFrame = NS_STATIC_CAST(nsObjectFrame*, frame);
|
||||
|
||||
return objectFrame->GetPluginInstance(*aPluginInstance);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* For plugins, we want to expose both attributes of the plugin tag
|
||||
* and any scriptable methods that the plugin itself exposes. To do
|
||||
* this, we get the plugin object itself (the XPCOM object) and wrap
|
||||
* it as a scriptable object via xpconnect. We then set the original
|
||||
* node element, which exposes the DOM node methods, as the javascript
|
||||
* prototype object of that object. Then we get both sets of methods, and
|
||||
* plugin methods can potentially override DOM methods.
|
||||
*/
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetPluginScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject)
|
||||
{
|
||||
if (mDOMSlots && mDOMSlots->mScriptObject)
|
||||
return nsGenericElement::GetScriptObject(aContext, aScriptObject);
|
||||
|
||||
nsresult rv;
|
||||
*aScriptObject = nsnull;
|
||||
|
||||
// Get the JS object corresponding to this dom node. This will become
|
||||
// the javascript prototype object of the object we eventually reflect to the
|
||||
// DOM.
|
||||
JSObject* elementObject = nsnull;
|
||||
rv = nsGenericElement::GetScriptObject(aContext, (void**)&elementObject);
|
||||
if (NS_FAILED(rv) || !elementObject)
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIPluginInstance> pi;
|
||||
GetPluginInstance(getter_AddRefs(pi));
|
||||
|
||||
// If GetPluginInstance() returns nsnull it most likely means
|
||||
// there's no frame for this element yet, in that case we return the
|
||||
// script object for the element but we don't cache it so that the
|
||||
// next call can get the correct script object if the plugin
|
||||
// instance is available at the next call.
|
||||
if (!pi) {
|
||||
if (mDocument) {
|
||||
// Since we're resetting the script object to null we'll remove the
|
||||
// reference to it so that we won't add the same named reference
|
||||
// again the next time someone requests the script object.
|
||||
aContext->RemoveReference((void *)&mDOMSlots->mScriptObject,
|
||||
mDOMSlots->mScriptObject);
|
||||
}
|
||||
|
||||
SetScriptObject(nsnull);
|
||||
|
||||
*aScriptObject = elementObject;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check if the plugin object has the nsIScriptablePlugin
|
||||
// interface, describing how to expose it to JavaScript. Given this
|
||||
// interface, use it to get the scriptable peer object (possibly the
|
||||
// plugin object itself) and the scriptable interface to expose it
|
||||
// with
|
||||
nsIID scriptableInterface;
|
||||
nsCOMPtr<nsISupports> scriptablePeer;
|
||||
if (NS_SUCCEEDED(rv) && pi) {
|
||||
nsCOMPtr<nsIScriptablePlugin> spi(do_QueryInterface(pi, &rv));
|
||||
if (NS_SUCCEEDED(rv) && spi) {
|
||||
nsIID *scriptableInterfacePtr = nsnull;
|
||||
rv = spi->GetScriptableInterface(&scriptableInterfacePtr);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && scriptableInterfacePtr) {
|
||||
rv = spi->GetScriptablePeer(getter_AddRefs(scriptablePeer));
|
||||
|
||||
scriptableInterface = *scriptableInterfacePtr;
|
||||
|
||||
nsMemory::Free(scriptableInterfacePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) || !scriptablePeer) {
|
||||
// Fall back to returning the element object.
|
||||
*aScriptObject = elementObject;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Wrap it.
|
||||
JSObject* interfaceObject; // XPConnect-wrapped peer object, when we get it.
|
||||
JSContext *cx = (JSContext *)aContext->GetNativeContext();
|
||||
nsCOMPtr<nsIXPConnect> xpc =
|
||||
do_GetService(nsIXPConnect::GetCID());
|
||||
if (cx && xpc) {
|
||||
JSObject* parentObject = JS_GetParent(cx, elementObject);
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
if (NS_SUCCEEDED(xpc->WrapNative(cx, parentObject,
|
||||
scriptablePeer, scriptableInterface,
|
||||
getter_AddRefs(holder))) && holder &&
|
||||
NS_SUCCEEDED(holder->GetJSObject(&interfaceObject)) &&
|
||||
interfaceObject) {
|
||||
*aScriptObject = interfaceObject;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got an xpconnect-wrapped plugin object, set its' prototype to the
|
||||
// element object.
|
||||
if (!*aScriptObject || !JS_SetPrototype(cx, interfaceObject,
|
||||
elementObject)) {
|
||||
*aScriptObject = elementObject; // fall back
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Cache it.
|
||||
SetScriptObject(*aScriptObject);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Allow access to arbitrary XPCOM interfaces supported by the plugin
|
||||
// via a pluginObject.nsISomeInterface notation.
|
||||
PRBool
|
||||
nsGenericHTMLElement::GetPluginProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp)
|
||||
{
|
||||
if (JSVAL_IS_STRING(aID)) {
|
||||
PRBool retval = PR_FALSE;
|
||||
char* cString = JS_GetStringBytes(JS_ValueToString(aContext, aID));
|
||||
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim =
|
||||
dont_AddRef(XPTI_GetInterfaceInfoManager());
|
||||
nsCOMPtr<nsIXPConnect> xpc =
|
||||
do_GetService(nsIXPConnect::GetCID());
|
||||
|
||||
if (iim && xpc) {
|
||||
nsIID* iid;
|
||||
if (NS_SUCCEEDED(iim->GetIIDForName(cString, &iid)) && iid) {
|
||||
nsCOMPtr<nsIPluginInstance> pi;
|
||||
if (NS_SUCCEEDED(GetPluginInstance(getter_AddRefs(pi))) && pi) {
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
JSObject* ifaceObj;
|
||||
|
||||
if (NS_SUCCEEDED(xpc->WrapNative(aContext, aObj, pi, *iid,
|
||||
getter_AddRefs(holder))) &&
|
||||
holder && NS_SUCCEEDED(holder->GetJSObject(&ifaceObj)) &&
|
||||
ifaceObj) {
|
||||
*aVp = OBJECT_TO_JSVAL(ifaceObj);
|
||||
retval = PR_TRUE;
|
||||
}
|
||||
}
|
||||
nsMemory::Free(iid);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nsGenericElement::GetProperty(aContext, aObj, aID, aVp);
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class nsDOMCSSAttributeDeclaration : public nsDOMCSSDeclaration
|
||||
|
|
|
@ -54,6 +54,7 @@ class nsIURI;
|
|||
class nsIFormControlFrame;
|
||||
class nsIForm;
|
||||
class nsIPresState;
|
||||
class nsIPluginInstance;
|
||||
|
||||
class nsGenericHTMLElement : public nsGenericElement {
|
||||
public:
|
||||
|
@ -334,6 +335,14 @@ public:
|
|||
static PRBool InNavQuirksMode(nsIDocument* aDoc);
|
||||
|
||||
nsIHTMLAttributes* mAttributes;
|
||||
|
||||
protected:
|
||||
nsresult GetPluginInstance(nsIPluginInstance** aPluginInstance);
|
||||
|
||||
nsresult GetPluginScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject);
|
||||
PRBool GetPluginProperty(JSContext *aContext, JSObject *aObj, jsval aID,
|
||||
jsval *aVp);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -19,32 +19,12 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIScriptObjectOwner.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIDOMHTMLEmbedElement.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsIMutableStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsObjectFrame.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsObjectFrame.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsMemory.h"
|
||||
#include "xptinfo.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
#include "nsIPluginInstance.h"
|
||||
#include "nsIScriptablePlugin.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMHTMLEmbedElement.h"
|
||||
|
||||
|
||||
class nsHTMLEmbedElement : public nsGenericHTMLLeafElement,
|
||||
public nsIDOMHTMLEmbedElement
|
||||
|
@ -68,10 +48,6 @@ public:
|
|||
// nsIDOMHTMLEmbedElement
|
||||
NS_DECL_IDOMHTMLEMBEDELEMENT
|
||||
|
||||
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject);
|
||||
virtual PRBool GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp);
|
||||
NS_IMETHOD StringToAttribute(nsIAtom* aAttribute,
|
||||
const nsAReadableString& aValue,
|
||||
nsHTMLValue& aResult);
|
||||
|
@ -84,8 +60,13 @@ public:
|
|||
nsMapAttributesFunc& aMapFunc) const;
|
||||
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
|
||||
|
||||
protected:
|
||||
nsresult GetPluginInstance(nsIPluginInstance** aPluginInstance);
|
||||
// nsIScriptObjectOwner
|
||||
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject);
|
||||
|
||||
// nsIJSScriptObject
|
||||
virtual PRBool GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp);
|
||||
};
|
||||
|
||||
nsresult
|
||||
|
@ -247,219 +228,18 @@ nsHTMLEmbedElement::SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const
|
|||
|
||||
/***************************************************************************/
|
||||
|
||||
// This is cribbed from nsHTMLImageElement::GetImageFrame.
|
||||
|
||||
nsresult
|
||||
nsHTMLEmbedElement::GetPluginInstance(nsIPluginInstance** aPluginInstance)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPluginInstance);
|
||||
*aPluginInstance = nsnull;
|
||||
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
|
||||
if (mDocument) {
|
||||
// Make sure the presentation is up-to-date
|
||||
result = mDocument->FlushPendingNotifications();
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = GetPresContext(this, getter_AddRefs(context));
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = context->GetShell(getter_AddRefs(shell));
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIFrame* frame;
|
||||
result = shell->GetPrimaryFrameFor(this, &frame);
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
nsCOMPtr<nsIAtom> type;
|
||||
|
||||
frame->GetFrameType(getter_AddRefs(type));
|
||||
|
||||
if (type.get() == nsLayoutAtoms::objectFrame) {
|
||||
// XXX We could have created an interface for this, but Troy
|
||||
// preferred the ugliness of a static cast to the weight of
|
||||
// a new interface.
|
||||
|
||||
nsObjectFrame* objectFrame = NS_STATIC_CAST(nsObjectFrame*, frame);
|
||||
|
||||
return objectFrame->GetPluginInstance(*aPluginInstance);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*
|
||||
* For plugins, we want to expose both attributes of the plugin tag
|
||||
* and any scriptable methods that the plugin itself exposes. To do
|
||||
* this, we get the plugin object itself (the XPCOM object) and wrap
|
||||
* it as a scriptable object via xpconnect. We then set the original
|
||||
* node element, which exposes the DOM node methods, as the javascript
|
||||
* prototype object of that object. Then we get both sets of methods, and
|
||||
* plugin methods can potentially override DOM methods.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEmbedElement::GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject)
|
||||
{
|
||||
if (mDOMSlots && mDOMSlots->mScriptObject)
|
||||
return nsGenericHTMLLeafElement::GetScriptObject(aContext, aScriptObject);
|
||||
|
||||
nsresult rv;
|
||||
*aScriptObject = nsnull;
|
||||
|
||||
// Get the JS object corresponding to this dom node. This will become
|
||||
// the javascript prototype object of the object we eventually reflect to the
|
||||
// DOM.
|
||||
JSObject* elementObject = nsnull;
|
||||
rv = nsGenericHTMLLeafElement::GetScriptObject(aContext,
|
||||
(void**)&elementObject);
|
||||
if (NS_FAILED(rv) || !elementObject)
|
||||
return rv;
|
||||
|
||||
// Flush pending reflows to ensure the plugin is instansiated, assuming
|
||||
// it's visible
|
||||
if (mDocument) {
|
||||
mDocument->FlushPendingNotifications();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPluginInstance> pi;
|
||||
rv = GetPluginInstance(getter_AddRefs(pi));
|
||||
|
||||
// If GetPluginInstance() fails it means there's no frame for this element
|
||||
// yet, in that case we return the script object for the element but we
|
||||
// don't cache it so that the next call can get the correct script object
|
||||
// if the plugin instance is available at the next call.
|
||||
if (NS_FAILED(rv)) {
|
||||
if (mDocument) {
|
||||
// Since we're resetting the script object to null we'll remove the
|
||||
// reference to it so that we won't add the same named reference
|
||||
// again the next time someone requests the script object.
|
||||
aContext->RemoveReference((void *)&mDOMSlots->mScriptObject,
|
||||
mDOMSlots->mScriptObject);
|
||||
}
|
||||
|
||||
SetScriptObject(nsnull);
|
||||
|
||||
*aScriptObject = elementObject;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check if the plugin object has the nsIScriptablePlugin
|
||||
// interface, describing how to expose it to JavaScript. Given this
|
||||
// interface, use it to get the scriptable peer object (possibly the
|
||||
// plugin object itself) and the scriptable interface to expose it
|
||||
// with
|
||||
nsIID scriptableInterface;
|
||||
nsCOMPtr<nsISupports> scriptablePeer;
|
||||
if (NS_SUCCEEDED(rv) && pi) {
|
||||
nsCOMPtr<nsIScriptablePlugin> spi(do_QueryInterface(pi, &rv));
|
||||
if (NS_SUCCEEDED(rv) && spi) {
|
||||
nsIID *scriptableInterfacePtr = nsnull;
|
||||
rv = spi->GetScriptableInterface(&scriptableInterfacePtr);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && scriptableInterfacePtr) {
|
||||
rv = spi->GetScriptablePeer(getter_AddRefs(scriptablePeer));
|
||||
|
||||
scriptableInterface = *scriptableInterfacePtr;
|
||||
|
||||
nsMemory::Free(scriptableInterfacePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) || !scriptablePeer) {
|
||||
// Fall back to returning the element object.
|
||||
*aScriptObject = elementObject;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Wrap it.
|
||||
JSObject* interfaceObject; // XPConnect-wrapped peer object, when we get it.
|
||||
JSContext *cx = (JSContext *)aContext->GetNativeContext();
|
||||
nsCOMPtr<nsIXPConnect> xpc =
|
||||
do_GetService(nsIXPConnect::GetCID());
|
||||
if (cx && xpc) {
|
||||
JSObject* parentObject = JS_GetParent(cx, elementObject);
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
if (NS_SUCCEEDED(xpc->WrapNative(cx, parentObject,
|
||||
scriptablePeer, scriptableInterface,
|
||||
getter_AddRefs(holder))) && holder &&
|
||||
NS_SUCCEEDED(holder->GetJSObject(&interfaceObject)) && interfaceObject) {
|
||||
*aScriptObject = interfaceObject;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got an xpconnect-wrapped plugin object, set its' prototype to the
|
||||
// element object.
|
||||
if (!*aScriptObject || !JS_SetPrototype(cx, interfaceObject,
|
||||
elementObject)) {
|
||||
*aScriptObject = elementObject; // fall back
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Cache it.
|
||||
SetScriptObject(*aScriptObject);
|
||||
|
||||
return NS_OK;
|
||||
return GetPluginScriptObject(aContext, aScriptObject);
|
||||
}
|
||||
|
||||
// Allow access to arbitrary XPCOM interfaces supported by the plugin
|
||||
// via a pluginObject.nsISomeInterface notation.
|
||||
PRBool
|
||||
PRBool
|
||||
nsHTMLEmbedElement::GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp)
|
||||
{
|
||||
if (JSVAL_IS_STRING(aID)) {
|
||||
PRBool retval = PR_FALSE;
|
||||
char* cString = JS_GetStringBytes(JS_ValueToString(aContext, aID));
|
||||
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim =
|
||||
dont_AddRef(XPTI_GetInterfaceInfoManager());
|
||||
nsCOMPtr<nsIXPConnect> xpc =
|
||||
do_GetService(nsIXPConnect::GetCID());
|
||||
|
||||
if (iim && xpc) {
|
||||
nsIID* iid;
|
||||
if (NS_SUCCEEDED(iim->GetIIDForName(cString, &iid)) && iid) {
|
||||
nsCOMPtr<nsIPluginInstance> pi;
|
||||
if (NS_SUCCEEDED(GetPluginInstance(getter_AddRefs(pi))) && pi) {
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
JSObject* ifaceObj;
|
||||
|
||||
if (NS_SUCCEEDED(xpc->WrapNative(aContext, aObj, pi, *iid,
|
||||
getter_AddRefs(holder))) && holder &&
|
||||
NS_SUCCEEDED(holder->GetJSObject(&ifaceObj)) && ifaceObj) {
|
||||
*aVp = OBJECT_TO_JSVAL(ifaceObj);
|
||||
retval = PR_TRUE;
|
||||
}
|
||||
}
|
||||
nsMemory::Free(iid);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nsGenericHTMLLeafElement::GetProperty(aContext, aObj, aID, aVp);
|
||||
return GetPluginProperty(aContext, aObj, aID, aVp);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
|
|
@ -20,16 +20,9 @@
|
|||
* Contributor(s):
|
||||
*/
|
||||
#include "nsIDOMHTMLObjectElement.h"
|
||||
#include "nsIScriptObjectOwner.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsIMutableStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsDOMError.h"
|
||||
|
||||
|
||||
|
@ -66,6 +59,14 @@ public:
|
|||
NS_IMETHOD GetMappedAttributeImpact(const nsIAtom* aAttribute,
|
||||
PRInt32& aHint) const;
|
||||
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
|
||||
|
||||
// nsIScriptObjectOwner
|
||||
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject);
|
||||
|
||||
// nsIJSScriptObject
|
||||
virtual PRBool GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp);
|
||||
};
|
||||
|
||||
nsresult
|
||||
|
@ -266,3 +267,17 @@ nsHTMLObjectElement::SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLObjectElement::GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject)
|
||||
{
|
||||
return GetPluginScriptObject(aContext, aScriptObject);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLObjectElement::GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp)
|
||||
{
|
||||
return GetPluginProperty(aContext, aObj, aID, aVp);
|
||||
}
|
||||
|
|
|
@ -20,16 +20,9 @@
|
|||
* Contributor(s):
|
||||
*/
|
||||
#include "nsIDOMHTMLObjectElement.h"
|
||||
#include "nsIScriptObjectOwner.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsIMutableStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsDOMError.h"
|
||||
|
||||
|
||||
|
@ -66,6 +59,14 @@ public:
|
|||
NS_IMETHOD GetMappedAttributeImpact(const nsIAtom* aAttribute,
|
||||
PRInt32& aHint) const;
|
||||
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
|
||||
|
||||
// nsIScriptObjectOwner
|
||||
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject);
|
||||
|
||||
// nsIJSScriptObject
|
||||
virtual PRBool GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp);
|
||||
};
|
||||
|
||||
nsresult
|
||||
|
@ -266,3 +267,17 @@ nsHTMLObjectElement::SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLObjectElement::GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject)
|
||||
{
|
||||
return GetPluginScriptObject(aContext, aScriptObject);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLObjectElement::GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp)
|
||||
{
|
||||
return GetPluginProperty(aContext, aObj, aID, aVp);
|
||||
}
|
||||
|
|
|
@ -94,6 +94,15 @@
|
|||
#include "nsIBindingManager.h"
|
||||
#include "nsIXBLBinding.h"
|
||||
|
||||
#include "nsObjectFrame.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "xptinfo.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
#include "nsIPluginInstance.h"
|
||||
#include "nsIScriptablePlugin.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsIParser.h"
|
||||
#include "nsParserCIID.h"
|
||||
#include "nsIHTMLContentSink.h"
|
||||
|
@ -102,7 +111,207 @@
|
|||
|
||||
#include "nsIPref.h" // Used by the temp pref, should be removed!
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetPluginInstance(nsIPluginInstance** aPluginInstance)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPluginInstance);
|
||||
*aPluginInstance = nsnull;
|
||||
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
|
||||
if (mDocument) {
|
||||
// Make sure the presentation is up-to-date
|
||||
result = mDocument->FlushPendingNotifications();
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
GetPresContext(this, getter_AddRefs(context));
|
||||
if (!context) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
context->GetShell(getter_AddRefs(shell));
|
||||
if (!shell) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFrame* frame = nsnull;
|
||||
shell->GetPrimaryFrameFor(this, &frame);
|
||||
if (!frame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> type;
|
||||
|
||||
frame->GetFrameType(getter_AddRefs(type));
|
||||
|
||||
if (type.get() == nsLayoutAtoms::objectFrame) {
|
||||
// XXX We could have created an interface for this, but Troy
|
||||
// preferred the ugliness of a static cast to the weight of
|
||||
// a new interface.
|
||||
|
||||
nsObjectFrame* objectFrame = NS_STATIC_CAST(nsObjectFrame*, frame);
|
||||
|
||||
return objectFrame->GetPluginInstance(*aPluginInstance);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* For plugins, we want to expose both attributes of the plugin tag
|
||||
* and any scriptable methods that the plugin itself exposes. To do
|
||||
* this, we get the plugin object itself (the XPCOM object) and wrap
|
||||
* it as a scriptable object via xpconnect. We then set the original
|
||||
* node element, which exposes the DOM node methods, as the javascript
|
||||
* prototype object of that object. Then we get both sets of methods, and
|
||||
* plugin methods can potentially override DOM methods.
|
||||
*/
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetPluginScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject)
|
||||
{
|
||||
if (mDOMSlots && mDOMSlots->mScriptObject)
|
||||
return nsGenericElement::GetScriptObject(aContext, aScriptObject);
|
||||
|
||||
nsresult rv;
|
||||
*aScriptObject = nsnull;
|
||||
|
||||
// Get the JS object corresponding to this dom node. This will become
|
||||
// the javascript prototype object of the object we eventually reflect to the
|
||||
// DOM.
|
||||
JSObject* elementObject = nsnull;
|
||||
rv = nsGenericElement::GetScriptObject(aContext, (void**)&elementObject);
|
||||
if (NS_FAILED(rv) || !elementObject)
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIPluginInstance> pi;
|
||||
GetPluginInstance(getter_AddRefs(pi));
|
||||
|
||||
// If GetPluginInstance() returns nsnull it most likely means
|
||||
// there's no frame for this element yet, in that case we return the
|
||||
// script object for the element but we don't cache it so that the
|
||||
// next call can get the correct script object if the plugin
|
||||
// instance is available at the next call.
|
||||
if (!pi) {
|
||||
if (mDocument) {
|
||||
// Since we're resetting the script object to null we'll remove the
|
||||
// reference to it so that we won't add the same named reference
|
||||
// again the next time someone requests the script object.
|
||||
aContext->RemoveReference((void *)&mDOMSlots->mScriptObject,
|
||||
mDOMSlots->mScriptObject);
|
||||
}
|
||||
|
||||
SetScriptObject(nsnull);
|
||||
|
||||
*aScriptObject = elementObject;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check if the plugin object has the nsIScriptablePlugin
|
||||
// interface, describing how to expose it to JavaScript. Given this
|
||||
// interface, use it to get the scriptable peer object (possibly the
|
||||
// plugin object itself) and the scriptable interface to expose it
|
||||
// with
|
||||
nsIID scriptableInterface;
|
||||
nsCOMPtr<nsISupports> scriptablePeer;
|
||||
if (NS_SUCCEEDED(rv) && pi) {
|
||||
nsCOMPtr<nsIScriptablePlugin> spi(do_QueryInterface(pi, &rv));
|
||||
if (NS_SUCCEEDED(rv) && spi) {
|
||||
nsIID *scriptableInterfacePtr = nsnull;
|
||||
rv = spi->GetScriptableInterface(&scriptableInterfacePtr);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && scriptableInterfacePtr) {
|
||||
rv = spi->GetScriptablePeer(getter_AddRefs(scriptablePeer));
|
||||
|
||||
scriptableInterface = *scriptableInterfacePtr;
|
||||
|
||||
nsMemory::Free(scriptableInterfacePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) || !scriptablePeer) {
|
||||
// Fall back to returning the element object.
|
||||
*aScriptObject = elementObject;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Wrap it.
|
||||
JSObject* interfaceObject; // XPConnect-wrapped peer object, when we get it.
|
||||
JSContext *cx = (JSContext *)aContext->GetNativeContext();
|
||||
nsCOMPtr<nsIXPConnect> xpc =
|
||||
do_GetService(nsIXPConnect::GetCID());
|
||||
if (cx && xpc) {
|
||||
JSObject* parentObject = JS_GetParent(cx, elementObject);
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
if (NS_SUCCEEDED(xpc->WrapNative(cx, parentObject,
|
||||
scriptablePeer, scriptableInterface,
|
||||
getter_AddRefs(holder))) && holder &&
|
||||
NS_SUCCEEDED(holder->GetJSObject(&interfaceObject)) &&
|
||||
interfaceObject) {
|
||||
*aScriptObject = interfaceObject;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got an xpconnect-wrapped plugin object, set its' prototype to the
|
||||
// element object.
|
||||
if (!*aScriptObject || !JS_SetPrototype(cx, interfaceObject,
|
||||
elementObject)) {
|
||||
*aScriptObject = elementObject; // fall back
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Cache it.
|
||||
SetScriptObject(*aScriptObject);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Allow access to arbitrary XPCOM interfaces supported by the plugin
|
||||
// via a pluginObject.nsISomeInterface notation.
|
||||
PRBool
|
||||
nsGenericHTMLElement::GetPluginProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp)
|
||||
{
|
||||
if (JSVAL_IS_STRING(aID)) {
|
||||
PRBool retval = PR_FALSE;
|
||||
char* cString = JS_GetStringBytes(JS_ValueToString(aContext, aID));
|
||||
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim =
|
||||
dont_AddRef(XPTI_GetInterfaceInfoManager());
|
||||
nsCOMPtr<nsIXPConnect> xpc =
|
||||
do_GetService(nsIXPConnect::GetCID());
|
||||
|
||||
if (iim && xpc) {
|
||||
nsIID* iid;
|
||||
if (NS_SUCCEEDED(iim->GetIIDForName(cString, &iid)) && iid) {
|
||||
nsCOMPtr<nsIPluginInstance> pi;
|
||||
if (NS_SUCCEEDED(GetPluginInstance(getter_AddRefs(pi))) && pi) {
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
JSObject* ifaceObj;
|
||||
|
||||
if (NS_SUCCEEDED(xpc->WrapNative(aContext, aObj, pi, *iid,
|
||||
getter_AddRefs(holder))) &&
|
||||
holder && NS_SUCCEEDED(holder->GetJSObject(&ifaceObj)) &&
|
||||
ifaceObj) {
|
||||
*aVp = OBJECT_TO_JSVAL(ifaceObj);
|
||||
retval = PR_TRUE;
|
||||
}
|
||||
}
|
||||
nsMemory::Free(iid);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nsGenericElement::GetProperty(aContext, aObj, aID, aVp);
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class nsDOMCSSAttributeDeclaration : public nsDOMCSSDeclaration
|
||||
|
|
|
@ -54,6 +54,7 @@ class nsIURI;
|
|||
class nsIFormControlFrame;
|
||||
class nsIForm;
|
||||
class nsIPresState;
|
||||
class nsIPluginInstance;
|
||||
|
||||
class nsGenericHTMLElement : public nsGenericElement {
|
||||
public:
|
||||
|
@ -334,6 +335,14 @@ public:
|
|||
static PRBool InNavQuirksMode(nsIDocument* aDoc);
|
||||
|
||||
nsIHTMLAttributes* mAttributes;
|
||||
|
||||
protected:
|
||||
nsresult GetPluginInstance(nsIPluginInstance** aPluginInstance);
|
||||
|
||||
nsresult GetPluginScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject);
|
||||
PRBool GetPluginProperty(JSContext *aContext, JSObject *aObj, jsval aID,
|
||||
jsval *aVp);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -19,32 +19,12 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIScriptObjectOwner.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIDOMHTMLEmbedElement.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsIMutableStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsObjectFrame.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsObjectFrame.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsMemory.h"
|
||||
#include "xptinfo.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
#include "nsIPluginInstance.h"
|
||||
#include "nsIScriptablePlugin.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMHTMLEmbedElement.h"
|
||||
|
||||
|
||||
class nsHTMLEmbedElement : public nsGenericHTMLLeafElement,
|
||||
public nsIDOMHTMLEmbedElement
|
||||
|
@ -68,10 +48,6 @@ public:
|
|||
// nsIDOMHTMLEmbedElement
|
||||
NS_DECL_IDOMHTMLEMBEDELEMENT
|
||||
|
||||
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject);
|
||||
virtual PRBool GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp);
|
||||
NS_IMETHOD StringToAttribute(nsIAtom* aAttribute,
|
||||
const nsAReadableString& aValue,
|
||||
nsHTMLValue& aResult);
|
||||
|
@ -84,8 +60,13 @@ public:
|
|||
nsMapAttributesFunc& aMapFunc) const;
|
||||
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
|
||||
|
||||
protected:
|
||||
nsresult GetPluginInstance(nsIPluginInstance** aPluginInstance);
|
||||
// nsIScriptObjectOwner
|
||||
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject);
|
||||
|
||||
// nsIJSScriptObject
|
||||
virtual PRBool GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp);
|
||||
};
|
||||
|
||||
nsresult
|
||||
|
@ -247,219 +228,18 @@ nsHTMLEmbedElement::SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const
|
|||
|
||||
/***************************************************************************/
|
||||
|
||||
// This is cribbed from nsHTMLImageElement::GetImageFrame.
|
||||
|
||||
nsresult
|
||||
nsHTMLEmbedElement::GetPluginInstance(nsIPluginInstance** aPluginInstance)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPluginInstance);
|
||||
*aPluginInstance = nsnull;
|
||||
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
|
||||
if (mDocument) {
|
||||
// Make sure the presentation is up-to-date
|
||||
result = mDocument->FlushPendingNotifications();
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = GetPresContext(this, getter_AddRefs(context));
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = context->GetShell(getter_AddRefs(shell));
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIFrame* frame;
|
||||
result = shell->GetPrimaryFrameFor(this, &frame);
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
nsCOMPtr<nsIAtom> type;
|
||||
|
||||
frame->GetFrameType(getter_AddRefs(type));
|
||||
|
||||
if (type.get() == nsLayoutAtoms::objectFrame) {
|
||||
// XXX We could have created an interface for this, but Troy
|
||||
// preferred the ugliness of a static cast to the weight of
|
||||
// a new interface.
|
||||
|
||||
nsObjectFrame* objectFrame = NS_STATIC_CAST(nsObjectFrame*, frame);
|
||||
|
||||
return objectFrame->GetPluginInstance(*aPluginInstance);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*
|
||||
* For plugins, we want to expose both attributes of the plugin tag
|
||||
* and any scriptable methods that the plugin itself exposes. To do
|
||||
* this, we get the plugin object itself (the XPCOM object) and wrap
|
||||
* it as a scriptable object via xpconnect. We then set the original
|
||||
* node element, which exposes the DOM node methods, as the javascript
|
||||
* prototype object of that object. Then we get both sets of methods, and
|
||||
* plugin methods can potentially override DOM methods.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEmbedElement::GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject)
|
||||
{
|
||||
if (mDOMSlots && mDOMSlots->mScriptObject)
|
||||
return nsGenericHTMLLeafElement::GetScriptObject(aContext, aScriptObject);
|
||||
|
||||
nsresult rv;
|
||||
*aScriptObject = nsnull;
|
||||
|
||||
// Get the JS object corresponding to this dom node. This will become
|
||||
// the javascript prototype object of the object we eventually reflect to the
|
||||
// DOM.
|
||||
JSObject* elementObject = nsnull;
|
||||
rv = nsGenericHTMLLeafElement::GetScriptObject(aContext,
|
||||
(void**)&elementObject);
|
||||
if (NS_FAILED(rv) || !elementObject)
|
||||
return rv;
|
||||
|
||||
// Flush pending reflows to ensure the plugin is instansiated, assuming
|
||||
// it's visible
|
||||
if (mDocument) {
|
||||
mDocument->FlushPendingNotifications();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPluginInstance> pi;
|
||||
rv = GetPluginInstance(getter_AddRefs(pi));
|
||||
|
||||
// If GetPluginInstance() fails it means there's no frame for this element
|
||||
// yet, in that case we return the script object for the element but we
|
||||
// don't cache it so that the next call can get the correct script object
|
||||
// if the plugin instance is available at the next call.
|
||||
if (NS_FAILED(rv)) {
|
||||
if (mDocument) {
|
||||
// Since we're resetting the script object to null we'll remove the
|
||||
// reference to it so that we won't add the same named reference
|
||||
// again the next time someone requests the script object.
|
||||
aContext->RemoveReference((void *)&mDOMSlots->mScriptObject,
|
||||
mDOMSlots->mScriptObject);
|
||||
}
|
||||
|
||||
SetScriptObject(nsnull);
|
||||
|
||||
*aScriptObject = elementObject;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check if the plugin object has the nsIScriptablePlugin
|
||||
// interface, describing how to expose it to JavaScript. Given this
|
||||
// interface, use it to get the scriptable peer object (possibly the
|
||||
// plugin object itself) and the scriptable interface to expose it
|
||||
// with
|
||||
nsIID scriptableInterface;
|
||||
nsCOMPtr<nsISupports> scriptablePeer;
|
||||
if (NS_SUCCEEDED(rv) && pi) {
|
||||
nsCOMPtr<nsIScriptablePlugin> spi(do_QueryInterface(pi, &rv));
|
||||
if (NS_SUCCEEDED(rv) && spi) {
|
||||
nsIID *scriptableInterfacePtr = nsnull;
|
||||
rv = spi->GetScriptableInterface(&scriptableInterfacePtr);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && scriptableInterfacePtr) {
|
||||
rv = spi->GetScriptablePeer(getter_AddRefs(scriptablePeer));
|
||||
|
||||
scriptableInterface = *scriptableInterfacePtr;
|
||||
|
||||
nsMemory::Free(scriptableInterfacePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) || !scriptablePeer) {
|
||||
// Fall back to returning the element object.
|
||||
*aScriptObject = elementObject;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Wrap it.
|
||||
JSObject* interfaceObject; // XPConnect-wrapped peer object, when we get it.
|
||||
JSContext *cx = (JSContext *)aContext->GetNativeContext();
|
||||
nsCOMPtr<nsIXPConnect> xpc =
|
||||
do_GetService(nsIXPConnect::GetCID());
|
||||
if (cx && xpc) {
|
||||
JSObject* parentObject = JS_GetParent(cx, elementObject);
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
if (NS_SUCCEEDED(xpc->WrapNative(cx, parentObject,
|
||||
scriptablePeer, scriptableInterface,
|
||||
getter_AddRefs(holder))) && holder &&
|
||||
NS_SUCCEEDED(holder->GetJSObject(&interfaceObject)) && interfaceObject) {
|
||||
*aScriptObject = interfaceObject;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got an xpconnect-wrapped plugin object, set its' prototype to the
|
||||
// element object.
|
||||
if (!*aScriptObject || !JS_SetPrototype(cx, interfaceObject,
|
||||
elementObject)) {
|
||||
*aScriptObject = elementObject; // fall back
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Cache it.
|
||||
SetScriptObject(*aScriptObject);
|
||||
|
||||
return NS_OK;
|
||||
return GetPluginScriptObject(aContext, aScriptObject);
|
||||
}
|
||||
|
||||
// Allow access to arbitrary XPCOM interfaces supported by the plugin
|
||||
// via a pluginObject.nsISomeInterface notation.
|
||||
PRBool
|
||||
PRBool
|
||||
nsHTMLEmbedElement::GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp)
|
||||
{
|
||||
if (JSVAL_IS_STRING(aID)) {
|
||||
PRBool retval = PR_FALSE;
|
||||
char* cString = JS_GetStringBytes(JS_ValueToString(aContext, aID));
|
||||
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim =
|
||||
dont_AddRef(XPTI_GetInterfaceInfoManager());
|
||||
nsCOMPtr<nsIXPConnect> xpc =
|
||||
do_GetService(nsIXPConnect::GetCID());
|
||||
|
||||
if (iim && xpc) {
|
||||
nsIID* iid;
|
||||
if (NS_SUCCEEDED(iim->GetIIDForName(cString, &iid)) && iid) {
|
||||
nsCOMPtr<nsIPluginInstance> pi;
|
||||
if (NS_SUCCEEDED(GetPluginInstance(getter_AddRefs(pi))) && pi) {
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
JSObject* ifaceObj;
|
||||
|
||||
if (NS_SUCCEEDED(xpc->WrapNative(aContext, aObj, pi, *iid,
|
||||
getter_AddRefs(holder))) && holder &&
|
||||
NS_SUCCEEDED(holder->GetJSObject(&ifaceObj)) && ifaceObj) {
|
||||
*aVp = OBJECT_TO_JSVAL(ifaceObj);
|
||||
retval = PR_TRUE;
|
||||
}
|
||||
}
|
||||
nsMemory::Free(iid);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nsGenericHTMLLeafElement::GetProperty(aContext, aObj, aID, aVp);
|
||||
return GetPluginProperty(aContext, aObj, aID, aVp);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
|
|
@ -20,16 +20,9 @@
|
|||
* Contributor(s):
|
||||
*/
|
||||
#include "nsIDOMHTMLObjectElement.h"
|
||||
#include "nsIScriptObjectOwner.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsIMutableStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsDOMError.h"
|
||||
|
||||
|
||||
|
@ -66,6 +59,14 @@ public:
|
|||
NS_IMETHOD GetMappedAttributeImpact(const nsIAtom* aAttribute,
|
||||
PRInt32& aHint) const;
|
||||
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
|
||||
|
||||
// nsIScriptObjectOwner
|
||||
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject);
|
||||
|
||||
// nsIJSScriptObject
|
||||
virtual PRBool GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp);
|
||||
};
|
||||
|
||||
nsresult
|
||||
|
@ -266,3 +267,17 @@ nsHTMLObjectElement::SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLObjectElement::GetScriptObject(nsIScriptContext* aContext,
|
||||
void** aScriptObject)
|
||||
{
|
||||
return GetPluginScriptObject(aContext, aScriptObject);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLObjectElement::GetProperty(JSContext *aContext, JSObject *aObj,
|
||||
jsval aID, jsval *aVp)
|
||||
{
|
||||
return GetPluginProperty(aContext, aObj, aID, aVp);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче