зеркало из https://github.com/mozilla/gecko-dev.git
Bug 851917. Get rid of the classinfo for HTMLObjectElement, HTMLEmbedElement, HTMLAppletElement, and rip out nsHTMLPluginObjElementSH. r=peterv,johns
This commit is contained in:
Родитель
8b269e0c3a
Коммит
01d3eba57a
|
@ -25,7 +25,7 @@ interface nsIURI;
|
|||
* interface to mirror this interface when changing it.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(e2ef99fe-f7d3-422f-a7b4-834e8bdde710)]
|
||||
[scriptable, uuid(24a35de3-40e4-498e-9c1b-2fd0a2d4cae5)]
|
||||
interface nsIObjectLoadingContent : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -149,16 +149,6 @@ interface nsIObjectLoadingContent : nsISupports
|
|||
*/
|
||||
[noscript] void initializeFromChannel(in nsIRequest request);
|
||||
|
||||
/**
|
||||
* Requests the plugin instance for scripting, attempting to spawn it if
|
||||
* appropriate.
|
||||
*
|
||||
* The first time content js tries to access a pre-empted plugin
|
||||
* (click-to-play or play preview), an event is dispatched.
|
||||
*/
|
||||
[noscript] nsNPAPIPluginInstancePtr
|
||||
scriptRequestPluginInstance(in bool callerIsContentJS);
|
||||
|
||||
/**
|
||||
* The URL of the data/src loaded in the object. This may be null (i.e.
|
||||
* an <embed> with no src).
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#include "nsWidgetsCID.h"
|
||||
#include "nsContentCID.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
|
||||
|
@ -2345,10 +2346,21 @@ nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::ScriptRequestPluginInstance(bool aCallerIsContentJS,
|
||||
nsresult
|
||||
nsObjectLoadingContent::ScriptRequestPluginInstance(JSContext* aCx,
|
||||
nsNPAPIPluginInstance **aResult)
|
||||
{
|
||||
// The below methods pull the cx off the stack, so make sure they match.
|
||||
//
|
||||
// NB: Sometimes there's a null cx on the stack, in which case |cx| is the
|
||||
// safe JS context. But in that case, IsCallerChrome() will return true,
|
||||
// so the ensuing expression is short-circuited.
|
||||
MOZ_ASSERT_IF(nsContentUtils::GetCurrentJSContext(),
|
||||
aCx == nsContentUtils::GetCurrentJSContext());
|
||||
bool callerIsContentJS = (!nsContentUtils::IsCallerChrome() &&
|
||||
!nsContentUtils::IsCallerXBL() &&
|
||||
js::IsContextRunningJS(aCx));
|
||||
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
|
||||
|
@ -2357,7 +2369,7 @@ nsObjectLoadingContent::ScriptRequestPluginInstance(bool aCallerIsContentJS,
|
|||
// The first time content script attempts to access placeholder content, fire
|
||||
// an event. Fallback types >= eFallbackClickToPlay are plugin-replacement
|
||||
// types, see header.
|
||||
if (aCallerIsContentJS && !mScriptRequested &&
|
||||
if (callerIsContentJS && !mScriptRequested &&
|
||||
InActiveDocument(thisContent) && mType == eType_Null &&
|
||||
mFallbackType >= eFallbackClickToPlay) {
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
|
@ -2628,27 +2640,7 @@ nsObjectLoadingContent::NotifyContentObjectWrapper()
|
|||
return;
|
||||
}
|
||||
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
||||
JSObject* canonicalPrototype = nullptr;
|
||||
if (thisContent->IsDOMBinding()) {
|
||||
canonicalPrototype =
|
||||
GetCanonicalPrototype(cx, JS_GetGlobalForObject(cx, obj));
|
||||
} else{
|
||||
nsContentUtils::XPConnect()->
|
||||
GetWrappedNativeOfNativeObject(cx, sgo->GetGlobalJSObject(), thisContent,
|
||||
NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(wrapper));
|
||||
}
|
||||
|
||||
nsHTMLPluginObjElementSH::SetupProtoChain(cx, obj, wrapper, canonicalPrototype);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
nsObjectLoadingContent::GetCanonicalPrototype(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
return nullptr;
|
||||
SetupProtoChain(cx, obj);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -2874,48 +2866,197 @@ nsObjectLoadingContent::LegacyCall(JSContext* aCx,
|
|||
return JS::UndefinedValue();
|
||||
}
|
||||
|
||||
JS::Value retval;
|
||||
bool otherRetval;
|
||||
nsresult rv =
|
||||
nsHTMLPluginObjElementSH::DoCall(nullptr, aCx, obj, args.Length(),
|
||||
args.Elements(), &retval, aThisVal,
|
||||
&otherRetval);
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return JS::UndefinedValue();
|
||||
}
|
||||
|
||||
if (!otherRetval) {
|
||||
// if there's no plugin around for this object, throw.
|
||||
if (!pi) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return JS::UndefinedValue();
|
||||
}
|
||||
|
||||
JSObject *pi_obj;
|
||||
JSObject *pi_proto;
|
||||
|
||||
rv = GetPluginJSObject(aCx, obj, pi, &pi_obj, &pi_proto);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return JS::UndefinedValue();
|
||||
}
|
||||
|
||||
if (!pi_obj) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return JS::UndefinedValue();
|
||||
}
|
||||
|
||||
JS::Value retval;
|
||||
bool ok = ::JS::Call(aCx, aThisVal, pi_obj, args.Length(),
|
||||
args.Elements(), &retval);
|
||||
if (!ok) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return JS::UndefinedValue();
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::PLUGIN_CALLED_DIRECTLY, true);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectLoadingContent::SetupProtoChain(JSContext* aCx, JSObject* aObject)
|
||||
{
|
||||
// We get called on random compartments here for some reason
|
||||
// (perhaps because WrapObject can happen on a random compartment?)
|
||||
// so make sure to enter the compartment of aObject.
|
||||
JSAutoCompartment ac(aCx, aObject);
|
||||
MOZ_ASSERT(nsCOMPtr<nsIContent>(do_QueryInterface(
|
||||
static_cast<nsIObjectLoadingContent*>(this)))->IsDOMBinding());
|
||||
if (nsContentUtils::IsSafeToRunScript()) {
|
||||
nsHTMLPluginObjElementSH::SetupProtoChain(aCx, aObject, nullptr,
|
||||
GetCanonicalPrototype(aCx,
|
||||
JS_GetGlobalForObject(aCx, aObject)));
|
||||
} else {
|
||||
|
||||
if (mType != eType_Plugin) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nsContentUtils::IsSafeToRunScript()) {
|
||||
// This may be null if the JS context is not a DOM context. That's ok, we'll
|
||||
// use the safe context from XPConnect in the runnable.
|
||||
nsCOMPtr<nsIScriptContext> scriptContext = GetScriptContextFromJSContext(aCx);
|
||||
|
||||
nsRefPtr<nsHTMLPluginObjElementSH::SetupProtoChainRunner> runner =
|
||||
new nsHTMLPluginObjElementSH::SetupProtoChainRunner(nullptr,
|
||||
scriptContext,
|
||||
this);
|
||||
nsRefPtr<SetupProtoChainRunner> runner =
|
||||
new SetupProtoChainRunner(scriptContext, this);
|
||||
nsContentUtils::AddScriptRunner(runner);
|
||||
return;
|
||||
}
|
||||
|
||||
// We get called on random compartments here for some reason
|
||||
// (perhaps because WrapObject can happen on a random compartment?)
|
||||
// so make sure to enter the compartment of aObject.
|
||||
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
JSAutoCompartment ac(aCx, aObject);
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pi) {
|
||||
// No plugin around for this object.
|
||||
return;
|
||||
}
|
||||
|
||||
JSObject *pi_obj; // XPConnect-wrapped peer object, when we get it.
|
||||
JSObject *pi_proto; // 'pi.__proto__'
|
||||
|
||||
rv = GetPluginJSObject(aCx, aObject, pi, &pi_obj, &pi_proto);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pi_obj) {
|
||||
// Didn't get a plugin instance JSObject, nothing we can do then.
|
||||
return;
|
||||
}
|
||||
|
||||
// If we got an xpconnect-wrapped plugin object, set obj's
|
||||
// prototype's prototype to the scriptable plugin.
|
||||
|
||||
JSObject *my_proto =
|
||||
GetDOMClass(aObject)->mGetProto(aCx, JS_GetGlobalForObject(aCx, aObject));
|
||||
MOZ_ASSERT(my_proto);
|
||||
|
||||
// Set 'this.__proto__' to pi
|
||||
if (!::JS_SetPrototype(aCx, aObject, pi_obj)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pi_proto && js::GetObjectClass(pi_proto) != &js::ObjectClass) {
|
||||
// The plugin wrapper has a proto that's not Object.prototype, set
|
||||
// 'pi.__proto__.__proto__' to the original 'this.__proto__'
|
||||
if (pi_proto != my_proto && !::JS_SetPrototype(aCx, pi_proto, my_proto)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// 'pi' didn't have a prototype, or pi's proto was
|
||||
// 'Object.prototype' (i.e. pi is an NPRuntime wrapped JS object)
|
||||
// set 'pi.__proto__' to the original 'this.__proto__'
|
||||
if (!::JS_SetPrototype(aCx, pi_obj, my_proto)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Before this proto dance the objects involved looked like this:
|
||||
//
|
||||
// this.__proto__.__proto__
|
||||
// ^ ^ ^
|
||||
// | | |__ Object.prototype
|
||||
// | |
|
||||
// | |__ WebIDL prototype (shared)
|
||||
// |
|
||||
// |__ WebIDL object
|
||||
//
|
||||
// pi.__proto__
|
||||
// ^ ^
|
||||
// | |__ Object.prototype or some other object
|
||||
// |
|
||||
// |__ Plugin NPRuntime JS object wrapper
|
||||
//
|
||||
// Now, after the above prototype setup the prototype chain should
|
||||
// look like this if pi.__proto__ was Object.prototype:
|
||||
//
|
||||
// this.__proto__.__proto__.__proto__
|
||||
// ^ ^ ^ ^
|
||||
// | | | |__ Object.prototype
|
||||
// | | |
|
||||
// | | |__ WebIDL prototype (shared)
|
||||
// | |
|
||||
// | |__ Plugin NPRuntime JS object wrapper
|
||||
// |
|
||||
// |__ WebIDL object
|
||||
//
|
||||
// or like this if pi.__proto__ was some other object:
|
||||
//
|
||||
// this.__proto__.__proto__.__proto__.__proto__
|
||||
// ^ ^ ^ ^ ^
|
||||
// | | | | |__ Object.prototype
|
||||
// | | | |
|
||||
// | | | |__ WebIDL prototype (shared)
|
||||
// | | |
|
||||
// | | |__ old pi.__proto__
|
||||
// | |
|
||||
// | |__ Plugin NPRuntime JS object wrapper
|
||||
// |
|
||||
// |__ WebIDL object
|
||||
//
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsObjectLoadingContent::GetPluginJSObject(JSContext *cx, JSObject *obj,
|
||||
nsNPAPIPluginInstance *plugin_inst,
|
||||
JSObject **plugin_obj,
|
||||
JSObject **plugin_proto)
|
||||
{
|
||||
*plugin_obj = nullptr;
|
||||
*plugin_proto = nullptr;
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
// NB: We need an AutoEnterCompartment because we can be called from
|
||||
// nsObjectFrame when the plugin loads after the JS object for our content
|
||||
// node has been created.
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
|
||||
if (plugin_inst) {
|
||||
plugin_inst->GetJSObject(cx, plugin_obj);
|
||||
if (*plugin_obj) {
|
||||
if (!::JS_GetPrototype(cx, *plugin_obj, plugin_proto)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2970,15 +3111,45 @@ nsObjectLoadingContent::DoNewResolve(JSContext* aCx, JSHandleObject aObject,
|
|||
{
|
||||
// We don't resolve anything; we just try to make sure we're instantiated
|
||||
|
||||
bool callerIsContentJS = (!nsContentUtils::IsCallerChrome() &&
|
||||
!nsContentUtils::IsCallerXBL() &&
|
||||
js::IsContextRunningJS(aCx));
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsresult rv = ScriptRequestPluginInstance(callerIsContentJS,
|
||||
getter_AddRefs(pi));
|
||||
nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
|
||||
if (NS_FAILED(rv)) {
|
||||
return mozilla::dom::Throw<true>(aCx, rv);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// SetupProtoChainRunner implementation
|
||||
nsObjectLoadingContent::SetupProtoChainRunner::SetupProtoChainRunner(
|
||||
nsIScriptContext* scriptContext,
|
||||
nsObjectLoadingContent* aContent)
|
||||
: mContext(scriptContext)
|
||||
, mContent(aContent)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::SetupProtoChainRunner::Run()
|
||||
{
|
||||
// XXXbz Does it really matter what JSContext we use here? Seems
|
||||
// like we could just always use the safe context....
|
||||
nsCxPusher pusher;
|
||||
JSContext* cx = mContext ? mContext->GetNativeContext()
|
||||
: nsContentUtils::GetSafeJSContext();
|
||||
pusher.Push(cx);
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
CallQueryInterface(mContent.get(), getter_AddRefs(content));
|
||||
JSObject* obj = content->GetWrapper();
|
||||
if (!obj) {
|
||||
// No need to set up our proto chain if we don't even have an object
|
||||
return NS_OK;
|
||||
}
|
||||
nsObjectLoadingContent* objectLoadingContent =
|
||||
static_cast<nsObjectLoadingContent*>(mContent.get());
|
||||
objectLoadingContent->SetupProtoChain(cx, obj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsObjectLoadingContent::SetupProtoChainRunner, nsIRunnable)
|
||||
|
||||
|
|
|
@ -136,8 +136,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
* object by placing it on the prototype chain of our element,
|
||||
* between the element itself and its most-derived DOM prototype.
|
||||
*
|
||||
* GetCanonicalPrototype returns this most-derived DOM prototype.
|
||||
*
|
||||
* SetupProtoChain handles actually inserting the plug-in
|
||||
* scriptable object into the proto chain if needed.
|
||||
*
|
||||
|
@ -145,13 +143,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
* page is looking up a property name on our object and make sure
|
||||
* that our plug-in, if any, is instantiated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the canonical prototype for this content for the given global. Only
|
||||
* returns non-null for objects that are on WebIDL bindings.
|
||||
*/
|
||||
virtual JSObject* GetCanonicalPrototype(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
// Helper for WebIDL node wrapping
|
||||
void SetupProtoChain(JSContext* aCx, JSObject* aObject);
|
||||
|
||||
|
@ -443,6 +434,34 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
*/
|
||||
nsObjectFrame* GetExistingFrame();
|
||||
|
||||
// Helper class for SetupProtoChain
|
||||
class SetupProtoChainRunner MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
SetupProtoChainRunner(nsIScriptContext* scriptContext,
|
||||
nsObjectLoadingContent* aContent);
|
||||
|
||||
NS_IMETHOD Run();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIScriptContext> mContext;
|
||||
// We store an nsIObjectLoadingContent because we can
|
||||
// unambiguously refcount that.
|
||||
nsRefPtr<nsIObjectLoadingContent> mContent;
|
||||
};
|
||||
|
||||
// Utility getter for getting our nsNPAPIPluginInstance in a safe way.
|
||||
nsresult ScriptRequestPluginInstance(JSContext* aCx,
|
||||
nsNPAPIPluginInstance** aResult);
|
||||
|
||||
// Utility method for getting our plugin JSObject
|
||||
static nsresult GetPluginJSObject(JSContext *cx, JSObject *obj,
|
||||
nsNPAPIPluginInstance *plugin_inst,
|
||||
JSObject **plugin_obj,
|
||||
JSObject **plugin_proto);
|
||||
|
||||
// The final listener for mChannel (uriloader, pluginstreamlistener, etc.)
|
||||
nsCOMPtr<nsIStreamListener> mFinalListener;
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLObjectElement)
|
|||
NS_OFFSET_AND_INTERFACE_TABLE_END
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLObjectElement,
|
||||
nsGenericHTMLFormElement)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLObjectElement)
|
||||
NS_HTML_CONTENT_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_ELEMENT_CLONE(HTMLObjectElement)
|
||||
|
||||
|
@ -463,15 +463,7 @@ HTMLObjectElement::WrapNode(JSContext* aCx, JSObject* aScope)
|
|||
return obj;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
HTMLObjectElement::GetCanonicalPrototype(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
return HTMLObjectElementBinding::GetProtoObject(aCx, aGlobal);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
DOMCI_NODE_DATA(HTMLObjectElement, mozilla::dom::HTMLObjectElement)
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Object)
|
||||
|
|
|
@ -96,8 +96,6 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLObjectElement,
|
||||
nsGenericHTMLFormElement)
|
||||
|
||||
virtual nsXPCClassInfo* GetClassInfo();
|
||||
|
||||
virtual nsIDOMNode* AsDOMNode() { return this; }
|
||||
|
||||
// Web IDL binding methods
|
||||
|
@ -246,8 +244,6 @@ private:
|
|||
virtual void SetItemValueText(const nsAString& text);
|
||||
|
||||
virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope) MOZ_OVERRIDE;
|
||||
virtual JSObject* GetCanonicalPrototype(JSContext* aCx,
|
||||
JSObject* aGlobal) MOZ_OVERRIDE;
|
||||
|
||||
bool mIsDoneAddingChildren;
|
||||
};
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(SharedObject)
|
||||
|
||||
DOMCI_DATA(HTMLAppletElement, mozilla::dom::HTMLSharedObjectElement)
|
||||
DOMCI_DATA(HTMLEmbedElement, mozilla::dom::HTMLSharedObjectElement)
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -94,18 +91,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|||
NS_IMPL_ADDREF_INHERITED(HTMLSharedObjectElement, Element)
|
||||
NS_IMPL_RELEASE_INHERITED(HTMLSharedObjectElement, Element)
|
||||
|
||||
nsIClassInfo*
|
||||
HTMLSharedObjectElement::GetClassInfoInternal()
|
||||
{
|
||||
if (mNodeInfo->Equals(nsGkAtoms::applet)) {
|
||||
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLAppletElement_id);
|
||||
}
|
||||
if (mNodeInfo->Equals(nsGkAtoms::embed)) {
|
||||
return NS_GetDOMClassInfoInstance(eDOMClassInfo_HTMLEmbedElement_id);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLSharedObjectElement)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE_AMBIGUOUS_BEGIN(HTMLSharedObjectElement,
|
||||
nsIDOMHTMLAppletElement)
|
||||
|
@ -125,7 +110,6 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLSharedObjectElement)
|
|||
NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLAppletElement, applet)
|
||||
NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLEmbedElement, embed)
|
||||
NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMGetSVGDocument, embed)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_GETTER(GetClassInfoInternal)
|
||||
NS_HTML_CONTENT_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_ELEMENT_CLONE(HTMLSharedObjectElement)
|
||||
|
@ -382,15 +366,5 @@ HTMLSharedObjectElement::WrapNode(JSContext* aCx, JSObject* aScope)
|
|||
return obj;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
HTMLSharedObjectElement::GetCanonicalPrototype(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
if (mNodeInfo->Equals(nsGkAtoms::applet)) {
|
||||
return HTMLAppletElementBinding::GetProtoObject(aCx, aGlobal);
|
||||
}
|
||||
MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::embed));
|
||||
return HTMLEmbedElementBinding::GetProtoObject(aCx, aGlobal);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -94,12 +94,6 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLSharedObjectElement,
|
||||
nsGenericHTMLElement)
|
||||
|
||||
virtual nsXPCClassInfo* GetClassInfo()
|
||||
{
|
||||
return static_cast<nsXPCClassInfo*>(GetClassInfoInternal());
|
||||
}
|
||||
nsIClassInfo* GetClassInfoInternal();
|
||||
|
||||
virtual nsIDOMNode* AsDOMNode()
|
||||
{
|
||||
return static_cast<nsIDOMHTMLAppletElement*>(this);
|
||||
|
@ -246,8 +240,6 @@ private:
|
|||
virtual void SetItemValueText(const nsAString& text);
|
||||
|
||||
virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope) MOZ_OVERRIDE;
|
||||
virtual JSObject* GetCanonicalPrototype(JSContext* aCx,
|
||||
JSObject* aGlobal) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -119,12 +119,6 @@
|
|||
// HTMLSelectElement helper includes
|
||||
#include "nsIDOMHTMLSelectElement.h"
|
||||
|
||||
// HTMLEmbed/ObjectElement helper includes
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "nsIObjectFrame.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
#include "nsIPluginHost.h"
|
||||
|
||||
#include "nsIDOMHTMLOptionElement.h"
|
||||
|
||||
// Event related includes
|
||||
|
@ -192,12 +186,9 @@
|
|||
#include "nsIDOMElementCSSInlineStyle.h"
|
||||
#include "nsIDOMLinkStyle.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMHTMLAppletElement.h"
|
||||
#include "nsIDOMHTMLCanvasElement.h"
|
||||
#include "nsIDOMHTMLEmbedElement.h"
|
||||
#include "nsIDOMHTMLIFrameElement.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIDOMHTMLObjectElement.h"
|
||||
#include "nsIDOMCSSCharsetRule.h"
|
||||
#include "nsIDOMCSSImportRule.h"
|
||||
#include "nsIDOMCSSMediaRule.h"
|
||||
|
@ -418,14 +409,6 @@ static const char kDOMStringBundleURL[] =
|
|||
((NODE_SCRIPTABLE_FLAGS & ~nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) | \
|
||||
nsIXPCScriptable::WANT_POSTCREATE)
|
||||
|
||||
#define EXTERNAL_OBJ_SCRIPTABLE_FLAGS \
|
||||
((ELEMENT_SCRIPTABLE_FLAGS & \
|
||||
~nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY) | \
|
||||
nsIXPCScriptable::WANT_POSTCREATE | \
|
||||
nsIXPCScriptable::WANT_GETPROPERTY | \
|
||||
nsIXPCScriptable::WANT_SETPROPERTY | \
|
||||
nsIXPCScriptable::WANT_CALL)
|
||||
|
||||
#define DOCUMENT_SCRIPTABLE_FLAGS \
|
||||
(NODE_SCRIPTABLE_FLAGS | \
|
||||
nsIXPCScriptable::WANT_POSTCREATE | \
|
||||
|
@ -656,10 +639,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
DOCUMENT_SCRIPTABLE_FLAGS |
|
||||
nsIXPCScriptable::WANT_GETPROPERTY)
|
||||
// HTML element classes
|
||||
NS_DEFINE_CLASSINFO_DATA(HTMLAppletElement, nsHTMLPluginObjElementSH,
|
||||
EXTERNAL_OBJ_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(HTMLEmbedElement, nsHTMLPluginObjElementSH,
|
||||
EXTERNAL_OBJ_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(HTMLFormElement, nsHTMLFormElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS |
|
||||
nsIXPCScriptable::WANT_GETPROPERTY |
|
||||
|
@ -668,8 +647,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(HTMLInputElement, nsElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(HTMLObjectElement, nsHTMLPluginObjElementSH,
|
||||
EXTERNAL_OBJ_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(HTMLSelectElement, nsHTMLSelectElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS |
|
||||
nsIXPCScriptable::WANT_SETPROPERTY |
|
||||
|
@ -1950,17 +1927,6 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(HTMLAppletElement, nsIDOMHTMLAppletElement)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLAppletElement)
|
||||
DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(HTMLEmbedElement, nsIDOMHTMLEmbedElement)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLEmbedElement)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMGetSVGDocument)
|
||||
DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(HTMLFormElement, nsIDOMHTMLFormElement)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLFormElement)
|
||||
DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
|
||||
|
@ -1978,12 +1944,6 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(HTMLObjectElement, nsIDOMHTMLObjectElement)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLObjectElement)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMGetSVGDocument)
|
||||
DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(HTMLSelectElement, nsIDOMHTMLSelectElement)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLSelectElement)
|
||||
DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
|
||||
|
@ -7372,405 +7332,6 @@ nsHTMLSelectElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// HTMLObject/EmbedElement helper
|
||||
// Keep in mind that it is OK for this to fail to return an instance. Don't return a
|
||||
// failure result unless something truly exceptional has happened.
|
||||
// static
|
||||
nsresult
|
||||
nsHTMLPluginObjElementSH::GetPluginInstanceIfSafe(nsIXPConnectWrappedNative *wrapper,
|
||||
JSObject *obj,
|
||||
JSContext *cx,
|
||||
nsNPAPIPluginInstance **_result)
|
||||
{
|
||||
*_result = nullptr;
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
if (wrapper) {
|
||||
content = do_QueryWrappedNative(wrapper, obj);
|
||||
} else {
|
||||
nsISupports* supports;
|
||||
if (XPCConvert::GetISupportsFromJSObject(obj, &supports)) {
|
||||
content = do_QueryInterface(supports);
|
||||
}
|
||||
}
|
||||
NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsIObjectLoadingContent> objlc(do_QueryInterface(content));
|
||||
NS_ASSERTION(objlc, "Object nodes must implement nsIObjectLoadingContent");
|
||||
|
||||
// The below methods pull the cx off the stack, so make sure they match.
|
||||
//
|
||||
// NB: Sometimes there's a null cx on the stack, in which case |cx| is the
|
||||
// safe JS context. But in that case, IsCallerChrome() will return true,
|
||||
// so the ensuing expression is short-circuited.
|
||||
MOZ_ASSERT_IF(nsContentUtils::GetCurrentJSContext(),
|
||||
cx == nsContentUtils::GetCurrentJSContext());
|
||||
|
||||
bool callerIsContentJS = (!nsContentUtils::IsCallerChrome() &&
|
||||
!nsContentUtils::IsCallerXBL() &&
|
||||
js::IsContextRunningJS(cx));
|
||||
return objlc->ScriptRequestPluginInstance(callerIsContentJS,
|
||||
_result);
|
||||
}
|
||||
|
||||
nsHTMLPluginObjElementSH::SetupProtoChainRunner::SetupProtoChainRunner(
|
||||
nsIXPConnectWrappedNative* aWrapper,
|
||||
nsIScriptContext* aScriptContext,
|
||||
nsObjectLoadingContent* aContent)
|
||||
: mWrapper(aWrapper)
|
||||
, mContext(aScriptContext)
|
||||
, mContent(aContent)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLPluginObjElementSH::SetupProtoChainRunner::Run()
|
||||
{
|
||||
nsCxPusher pusher;
|
||||
JSContext* cx = mContext ? mContext->GetNativeContext()
|
||||
: nsContentUtils::GetSafeJSContext();
|
||||
pusher.Push(cx);
|
||||
|
||||
JSObject* obj = nullptr;
|
||||
JSObject* canonicalProto = nullptr;
|
||||
if (mWrapper) {
|
||||
mWrapper->GetJSObject(&obj);
|
||||
NS_ASSERTION(obj, "Should never be null");
|
||||
} else {
|
||||
MOZ_ASSERT(mContent, "Must have mContent if no mWrapper");
|
||||
nsCOMPtr<nsIContent> content;
|
||||
CallQueryInterface(mContent.get(), getter_AddRefs(content));
|
||||
obj = content->GetWrapper();
|
||||
if (!obj) {
|
||||
// No need to set up our proto chain if we don't even have an object
|
||||
return NS_OK;
|
||||
}
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
canonicalProto = static_cast<nsObjectLoadingContent*>(mContent.get())->
|
||||
GetCanonicalPrototype(cx, JS_GetGlobalForObject(cx, obj));
|
||||
}
|
||||
nsHTMLPluginObjElementSH::SetupProtoChain(cx, obj, mWrapper, canonicalProto);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsHTMLPluginObjElementSH::SetupProtoChainRunner, nsIRunnable)
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsHTMLPluginObjElementSH::SetupProtoChain(JSContext *cx,
|
||||
JSObject *obj,
|
||||
nsIXPConnectWrappedNative *wrapper,
|
||||
JSObject* aCanonicalPrototype)
|
||||
{
|
||||
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
|
||||
"Shouldn't have gotten in here");
|
||||
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsresult rv = GetPluginInstanceIfSafe(wrapper, obj, cx, getter_AddRefs(pi));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!pi) {
|
||||
// No plugin around for this object.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSObject *pi_obj = nullptr; // XPConnect-wrapped peer object, when we get it.
|
||||
JSObject *pi_proto = nullptr; // 'pi.__proto__'
|
||||
|
||||
rv = GetPluginJSObject(cx, obj, pi, &pi_obj, &pi_proto);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!pi_obj) {
|
||||
// Didn't get a plugin instance JSObject, nothing we can do then.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we got an xpconnect-wrapped plugin object, set obj's
|
||||
// prototype's prototype to the scriptable plugin.
|
||||
|
||||
JSObject *my_proto = nullptr;
|
||||
|
||||
if (wrapper) {
|
||||
// Get 'this.__proto__'
|
||||
rv = wrapper->GetJSObjectPrototype(&my_proto);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
my_proto = aCanonicalPrototype;
|
||||
}
|
||||
MOZ_ASSERT(my_proto);
|
||||
|
||||
// Set 'this.__proto__' to pi
|
||||
if (!::JS_SetPrototype(cx, obj, pi_obj)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (pi_proto && JS_GetClass(pi_proto) != sObjectClass) {
|
||||
// The plugin wrapper has a proto that's not Object.prototype, set
|
||||
// 'pi.__proto__.__proto__' to the original 'this.__proto__'
|
||||
if (pi_proto != my_proto && !::JS_SetPrototype(cx, pi_proto, my_proto)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
} else {
|
||||
// 'pi' didn't have a prototype, or pi's proto was
|
||||
// 'Object.prototype' (i.e. pi is an NPRuntime wrapped JS object)
|
||||
// set 'pi.__proto__' to the original 'this.__proto__'
|
||||
if (!::JS_SetPrototype(cx, pi_obj, my_proto)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
// Before this proto dance the objects involved looked like this:
|
||||
//
|
||||
// this.__proto__.__proto__
|
||||
// ^ ^ ^
|
||||
// | | |__ Object.prototype
|
||||
// | |
|
||||
// | |__ xpc embed wrapper proto (shared)
|
||||
// |
|
||||
// |__ xpc wrapped native embed node
|
||||
//
|
||||
// pi.__proto__
|
||||
// ^ ^
|
||||
// | |__ Object.prototype
|
||||
// |
|
||||
// |__ Plugin NPRuntime JS object wrapper
|
||||
//
|
||||
// Now, after the above prototype setup the prototype chain should
|
||||
// look like this:
|
||||
//
|
||||
// this.__proto__.__proto__.__proto__
|
||||
// ^ ^ ^ ^
|
||||
// | | | |__ Object.prototype
|
||||
// | | |
|
||||
// | | |__ xpc embed wrapper proto (shared)
|
||||
// | |
|
||||
// | |__ Plugin NPRuntime JS object wrapper
|
||||
// |
|
||||
// |__ xpc wrapped native embed node
|
||||
//
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLPluginObjElementSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj)
|
||||
{
|
||||
nsresult rv = nsElementSH::PreCreate(nativeObj, cx, globalObj, parentObj);
|
||||
|
||||
// For now we don't support slim wrappers for plugins.
|
||||
return rv == NS_SUCCESS_ALLOW_SLIM_WRAPPERS ? NS_OK : rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLPluginObjElementSH::PostCreate(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj)
|
||||
{
|
||||
if (nsContentUtils::IsSafeToRunScript()) {
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
SetupProtoChain(cx, obj, wrapper);
|
||||
|
||||
// If SetupProtoChain failed then we're in real trouble. We're about to fail
|
||||
// PostCreate but it's more than likely that we handed our (now invalid)
|
||||
// wrapper to someone already. Bug 429442 is an example of the kind of crash
|
||||
// that can result from such a situation. We'll return NS_OK for the time
|
||||
// being and hope for the best.
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "SetupProtoChain failed!");
|
||||
}
|
||||
else {
|
||||
// This may be null if the JS context is not a DOM context. That's ok, we'll
|
||||
// use the safe context from XPConnect in the runnable.
|
||||
nsCOMPtr<nsIScriptContext> scriptContext = GetScriptContextFromJSContext(cx);
|
||||
|
||||
nsRefPtr<SetupProtoChainRunner> runner =
|
||||
new SetupProtoChainRunner(wrapper, scriptContext, nullptr);
|
||||
nsContentUtils::AddScriptRunner(runner);
|
||||
}
|
||||
|
||||
return nsElementSH::PostCreate(wrapper, cx, obj);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLPluginObjElementSH::PostTransplant(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj)
|
||||
{
|
||||
// Call through to PostCreate to do the prototype setup all over again. We
|
||||
// may reuse the same prototype, in which case our prototype will be a wrapped
|
||||
// version of the original.
|
||||
nsresult rv = PostCreate(wrapper, cx, obj);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Calling PostCreate during PostTransplant for plugin element failed.");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLPluginObjElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj, jsid id,
|
||||
jsval *vp, bool *_retval)
|
||||
{
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSObject *pi_obj;
|
||||
if (!::JS_GetPrototype(cx, obj, &pi_obj)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if (MOZ_UNLIKELY(!pi_obj)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSBool found = false;
|
||||
|
||||
if (!ObjectIsNativeWrapper(cx, obj)) {
|
||||
*_retval = ::JS_HasPropertyById(cx, pi_obj, id, &found);
|
||||
if (!*_retval) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
*_retval = ::JS_GetPropertyById(cx, pi_obj, id, vp);
|
||||
return *_retval ? NS_SUCCESS_I_DID_SOMETHING : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLPluginObjElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj, jsid id,
|
||||
jsval *vp, bool *_retval)
|
||||
{
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSObject *pi_obj;
|
||||
if (!::JS_GetPrototype(cx, obj, &pi_obj)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if (MOZ_UNLIKELY(!pi_obj)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSBool found = false;
|
||||
|
||||
if (!ObjectIsNativeWrapper(cx, obj)) {
|
||||
*_retval = ::JS_HasPropertyById(cx, pi_obj, id, &found);
|
||||
if (!*_retval) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
*_retval = ::JS_SetPropertyById(cx, pi_obj, id, vp);
|
||||
return *_retval ? NS_SUCCESS_I_DID_SOMETHING : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLPluginObjElementSH::Call(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj, uint32_t argc,
|
||||
jsval *argv, jsval *vp, bool *_retval)
|
||||
{
|
||||
// XPConnect passes us the XPConnect wrapper JSObject as obj, and
|
||||
// not the 'this' parameter that the JS engine passes in. Pass in
|
||||
// the real this parameter from JS (argv[-1]) here.
|
||||
return DoCall(wrapper, cx, obj, argc, argv, vp, argv[-1], _retval);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLPluginObjElementSH::DoCall(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj, uint32_t argc,
|
||||
jsval *argv, jsval *vp, jsval thisVal,
|
||||
bool *_retval)
|
||||
{
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsresult rv = GetPluginInstanceIfSafe(wrapper, obj, cx, getter_AddRefs(pi));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If obj is a native wrapper, or if there's no plugin around for
|
||||
// this object, throw.
|
||||
if (ObjectIsNativeWrapper(cx, obj) || !pi) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
JSObject *pi_obj = nullptr;
|
||||
JSObject *pi_proto = nullptr;
|
||||
|
||||
rv = GetPluginJSObject(cx, obj, pi, &pi_obj, &pi_proto);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!pi) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// XPConnect passes us the XPConnect wrapper JSObject as obj, and
|
||||
// not the 'this' parameter that the JS engine passes in. Pass in
|
||||
// the real this parameter from JS (argv[-1]) here.
|
||||
JSAutoRequest ar(cx);
|
||||
*_retval = ::JS::Call(cx, thisVal, pi_obj, argc, argv, vp);
|
||||
if (*_retval) {
|
||||
Telemetry::Accumulate(Telemetry::PLUGIN_CALLED_DIRECTLY, true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLPluginObjElementSH::GetPluginJSObject(JSContext *cx, JSObject *obj,
|
||||
nsNPAPIPluginInstance *plugin_inst,
|
||||
JSObject **plugin_obj,
|
||||
JSObject **plugin_proto)
|
||||
{
|
||||
*plugin_obj = nullptr;
|
||||
*plugin_proto = nullptr;
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
// NB: We need an AutoEnterCompartment because we can be called from
|
||||
// nsObjectFrame when the plugin loads after the JS object for our content
|
||||
// node has been created.
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
|
||||
if (plugin_inst) {
|
||||
plugin_inst->GetJSObject(cx, plugin_obj);
|
||||
if (*plugin_obj) {
|
||||
if (!::JS_GetPrototype(cx, *plugin_obj, plugin_proto)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLPluginObjElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj, jsid id,
|
||||
uint32_t flags, JSObject **objp,
|
||||
bool *_retval)
|
||||
{
|
||||
// Make sure the plugin instance is loaded and instantiated, if
|
||||
// possible.
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsresult rv = GetPluginInstanceIfSafe(wrapper, obj, cx, getter_AddRefs(pi));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return nsElementSH::NewResolve(wrapper, cx, obj, id, flags, objp,
|
||||
_retval);
|
||||
}
|
||||
|
||||
// Plugin helper
|
||||
|
||||
nsISupports*
|
||||
|
|
|
@ -765,89 +765,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
// HTMLEmbed/Object/AppletElement helper
|
||||
|
||||
class nsHTMLPluginObjElementSH : public nsElementSH
|
||||
{
|
||||
protected:
|
||||
nsHTMLPluginObjElementSH(nsDOMClassInfoData* aData)
|
||||
: nsElementSH(aData)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~nsHTMLPluginObjElementSH()
|
||||
{
|
||||
}
|
||||
|
||||
// Passing a null aWrapper is fine for WebIDL objects
|
||||
static nsresult GetPluginInstanceIfSafe(nsIXPConnectWrappedNative *aWrapper,
|
||||
JSObject *obj,
|
||||
JSContext *cx,
|
||||
nsNPAPIPluginInstance **aResult);
|
||||
|
||||
static nsresult GetPluginJSObject(JSContext *cx, JSObject *obj,
|
||||
nsNPAPIPluginInstance *plugin_inst,
|
||||
JSObject **plugin_obj,
|
||||
JSObject **plugin_proto);
|
||||
|
||||
public:
|
||||
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, uint32_t flags,
|
||||
JSObject **objp, bool *_retval);
|
||||
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj);
|
||||
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj);
|
||||
NS_IMETHOD PostTransplant(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj);
|
||||
NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, bool *_retval);
|
||||
NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, bool *_retval);
|
||||
NS_IMETHOD Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, uint32_t argc, jsval *argv, jsval *vp,
|
||||
bool *_retval);
|
||||
|
||||
|
||||
static nsresult SetupProtoChain(JSContext *cx, JSObject *obj,
|
||||
nsIXPConnectWrappedNative *wrapper = nullptr,
|
||||
JSObject *aCanonicalProto = nullptr);
|
||||
|
||||
// The actual implementation of Call. This allows the caller to
|
||||
// pass in an explicit "this" value and does not make any
|
||||
// assumptions about negative indices into argv.
|
||||
static nsresult DoCall(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, uint32_t argc, jsval *argv, jsval *vp,
|
||||
jsval thisVal, bool *_retval);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
return new nsHTMLPluginObjElementSH(aData);
|
||||
}
|
||||
|
||||
class SetupProtoChainRunner MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// wrapper can be null, but then aContent must be non-null
|
||||
SetupProtoChainRunner(nsIXPConnectWrappedNative* aWrapper,
|
||||
nsIScriptContext* aScriptContext,
|
||||
nsObjectLoadingContent* aContent);
|
||||
|
||||
NS_IMETHOD Run();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mWrapper;
|
||||
nsCOMPtr<nsIScriptContext> mContext;
|
||||
// We store an nsIObjectLoadingContent because we can
|
||||
// unambiguously refcount that.
|
||||
nsRefPtr<nsIObjectLoadingContent> mContent;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Plugin helper
|
||||
|
||||
class nsPluginSH : public nsNamedArraySH
|
||||
|
|
|
@ -45,12 +45,9 @@ DOMCI_CLASS(DeviceRotationRate)
|
|||
DOMCI_CLASS(HTMLDocument)
|
||||
|
||||
// HTML element classes
|
||||
DOMCI_CLASS(HTMLAppletElement)
|
||||
DOMCI_CLASS(HTMLEmbedElement)
|
||||
DOMCI_CLASS(HTMLFormElement)
|
||||
DOMCI_CLASS(HTMLIFrameElement)
|
||||
DOMCI_CLASS(HTMLInputElement)
|
||||
DOMCI_CLASS(HTMLObjectElement)
|
||||
DOMCI_CLASS(HTMLSelectElement)
|
||||
DOMCI_CLASS(ValidityState)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче