mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-01 03:21:10 +00:00
Bug 810082 - Part 0.5 - Add script access event for CTP'd plugins r=joshmoz
This commit is contained in:
parent
8d249e9c73
commit
6e8178b713
@ -21,7 +21,7 @@ interface nsIURI;
|
||||
* This interface represents a content node that loads objects.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(a812424b-4820-4e28-96c8-dd2b69e36496)]
|
||||
[scriptable, uuid(649b8a75-8623-437f-ad30-0ac596c8452e)]
|
||||
interface nsIObjectLoadingContent : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -130,6 +130,16 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
[noscript] void syncStartPluginInstance();
|
||||
[noscript] void asyncStartPluginInstance();
|
||||
|
||||
/**
|
||||
* 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).
|
||||
|
@ -163,27 +163,31 @@ InDocCheckEvent::Run()
|
||||
}
|
||||
|
||||
/**
|
||||
* A task for firing PluginNotFound and PluginBlocklisted DOM Events.
|
||||
* Helper task for firing simple events
|
||||
*/
|
||||
class nsPluginOutdatedEvent : public nsRunnable {
|
||||
class nsSimplePluginEvent : public nsRunnable {
|
||||
public:
|
||||
nsPluginOutdatedEvent(nsIContent* aContent) : mContent(aContent) {}
|
||||
nsSimplePluginEvent(nsIContent* aContent, const nsAString &aEvent)
|
||||
: mContent(aContent),
|
||||
mEvent(aEvent)
|
||||
{}
|
||||
|
||||
~nsPluginOutdatedEvent() {}
|
||||
~nsSimplePluginEvent() {}
|
||||
|
||||
NS_IMETHOD Run();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsString mEvent;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginOutdatedEvent::Run()
|
||||
nsSimplePluginEvent::Run()
|
||||
{
|
||||
LOG(("OBJLC [%p]: nsPluginOutdatedEvent firing", mContent.get()));
|
||||
LOG(("OBJLC [%p]: nsSimplePluginEvent firing event \"%s\"", mContent.get(),
|
||||
mEvent.get()));
|
||||
nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent,
|
||||
NS_LITERAL_STRING("PluginOutdated"),
|
||||
true, true);
|
||||
mEvent, true, true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -631,6 +635,7 @@ nsObjectLoadingContent::nsObjectLoadingContent()
|
||||
, mPlayPreviewCanceled(false)
|
||||
, mIsStopping(false)
|
||||
, mIsLoading(false)
|
||||
, mScriptRequested(false)
|
||||
, mSrcStreamLoading(false) {}
|
||||
|
||||
nsObjectLoadingContent::~nsObjectLoadingContent()
|
||||
@ -748,12 +753,13 @@ nsObjectLoadingContent::InstantiatePluginInstance()
|
||||
EmptyString(), &blockState);
|
||||
if (blockState == nsIBlocklistService::STATE_OUTDATED) {
|
||||
// Fire plugin outdated event if necessary
|
||||
LOG(("OBJLC [%p]: Dispatching nsPluginOutdatedEvent for content %p\n",
|
||||
LOG(("OBJLC [%p]: Dispatching plugin outdated event for content %p\n",
|
||||
this));
|
||||
nsCOMPtr<nsIRunnable> ev = new nsPluginOutdatedEvent(thisContent);
|
||||
nsCOMPtr<nsIRunnable> ev = new nsSimplePluginEvent(thisContent,
|
||||
NS_LITERAL_STRING("PluginOutdated"));
|
||||
nsresult rv = NS_DispatchToCurrentThread(ev);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to dispatch nsPluginOutdatedEvent");
|
||||
NS_WARNING("failed to dispatch nsSimplePluginEvent");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2013,6 +2019,8 @@ nsObjectLoadingContent::UnloadObject(bool aResetState)
|
||||
mOriginalContentType.Truncate();
|
||||
}
|
||||
|
||||
mScriptRequested = false;
|
||||
|
||||
// This call should be last as it may re-enter
|
||||
StopPluginInstance();
|
||||
}
|
||||
@ -2183,6 +2191,45 @@ nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::ScriptRequestPluginInstance(bool aCallerIsContentJS,
|
||||
nsNPAPIPluginInstance **aResult)
|
||||
{
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
|
||||
*aResult = nullptr;
|
||||
|
||||
// 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 &&
|
||||
InActiveDocument(thisContent) && mType == eType_Null &&
|
||||
mFallbackType >= eFallbackClickToPlay) {
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new nsSimplePluginEvent(thisContent,
|
||||
NS_LITERAL_STRING("PluginScripted"));
|
||||
nsresult rv = NS_DispatchToCurrentThread(ev);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_NOTREACHED("failed to dispatch PluginScripted event");
|
||||
}
|
||||
mScriptRequested = true;
|
||||
} else if (mType == eType_Plugin && !mInstanceOwner &&
|
||||
nsContentUtils::IsSafeToRunScript() &&
|
||||
InActiveDocument(thisContent)) {
|
||||
// If we're configured as a plugin in an active document and it's safe to
|
||||
// run scripts right now, try spawning synchronously
|
||||
SyncStartPluginInstance();
|
||||
}
|
||||
|
||||
if (mInstanceOwner) {
|
||||
return mInstanceOwner->GetInstance(aResult);
|
||||
}
|
||||
|
||||
// Note that returning a null plugin is expected (and happens often)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::SyncStartPluginInstance()
|
||||
{
|
||||
|
@ -437,12 +437,16 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
// Protects LoadObject from re-entry
|
||||
bool mIsLoading : 1;
|
||||
|
||||
// For plugin stand-in types (click-to-play, play preview, ...) tracks
|
||||
// whether content js has tried to access the plugin script object.
|
||||
bool mScriptRequested : 1;
|
||||
|
||||
// Used to track when we might try to instantiate a plugin instance based on
|
||||
// a src data stream being delivered to this object. When this is true we
|
||||
// don't want plugin instance instantiation code to attempt to load src data
|
||||
// again or we'll deliver duplicate streams. Should be cleared when we are
|
||||
// not loading src data.
|
||||
bool mSrcStreamLoading;
|
||||
bool mSrcStreamLoading : 1;
|
||||
|
||||
|
||||
nsWeakFrame mPrintFrame;
|
||||
|
@ -9563,6 +9563,7 @@ nsHTMLSelectElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
|
||||
nsresult
|
||||
nsHTMLPluginObjElementSH::GetPluginInstanceIfSafe(nsIXPConnectWrappedNative *wrapper,
|
||||
JSObject *obj,
|
||||
JSContext *cx,
|
||||
nsNPAPIPluginInstance **_result)
|
||||
{
|
||||
*_result = nullptr;
|
||||
@ -9573,22 +9574,11 @@ nsHTMLPluginObjElementSH::GetPluginInstanceIfSafe(nsIXPConnectWrappedNative *wra
|
||||
nsCOMPtr<nsIObjectLoadingContent> objlc(do_QueryInterface(content));
|
||||
NS_ASSERTION(objlc, "Object nodes must implement nsIObjectLoadingContent");
|
||||
|
||||
nsresult rv = objlc->GetPluginInstance(_result);
|
||||
if (NS_SUCCEEDED(rv) && *_result) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If it's not safe to run script we'll only return the instance if it exists.
|
||||
// Ditto if the document is inactive.
|
||||
if (!nsContentUtils::IsSafeToRunScript() || !content->OwnerDoc()->IsActive()) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// We don't care if this actually starts the plugin or not, we just want to
|
||||
// try to start it now if possible.
|
||||
objlc->SyncStartPluginInstance();
|
||||
|
||||
return objlc->GetPluginInstance(_result);
|
||||
bool callerIsContentJS = (!xpc::AccessCheck::callerIsChrome() &&
|
||||
!xpc::AccessCheck::callerIsXBL(cx) &&
|
||||
js::IsContextRunningJS(cx));
|
||||
return objlc->ScriptRequestPluginInstance(callerIsContentJS,
|
||||
_result);
|
||||
}
|
||||
|
||||
class nsPluginProtoChainInstallRunner MOZ_FINAL : public nsIRunnable
|
||||
@ -9649,7 +9639,7 @@ nsHTMLPluginObjElementSH::SetupProtoChain(nsIXPConnectWrappedNative *wrapper,
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsresult rv = GetPluginInstanceIfSafe(wrapper, obj, getter_AddRefs(pi));
|
||||
nsresult rv = GetPluginInstanceIfSafe(wrapper, obj, cx, getter_AddRefs(pi));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!pi) {
|
||||
@ -9855,7 +9845,7 @@ nsHTMLPluginObjElementSH::Call(nsIXPConnectWrappedNative *wrapper,
|
||||
jsval *argv, jsval *vp, bool *_retval)
|
||||
{
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsresult rv = GetPluginInstanceIfSafe(wrapper, obj, getter_AddRefs(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
|
||||
@ -9922,7 +9912,7 @@ nsHTMLPluginObjElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
|
||||
// possible.
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsresult rv = GetPluginInstanceIfSafe(wrapper, obj, getter_AddRefs(pi));
|
||||
nsresult rv = GetPluginInstanceIfSafe(wrapper, obj, cx, getter_AddRefs(pi));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return nsElementSH::NewResolve(wrapper, cx, obj, id, flags, objp,
|
||||
|
@ -848,6 +848,7 @@ protected:
|
||||
|
||||
static nsresult GetPluginInstanceIfSafe(nsIXPConnectWrappedNative *aWrapper,
|
||||
JSObject *obj,
|
||||
JSContext *cx,
|
||||
nsNPAPIPluginInstance **aResult);
|
||||
|
||||
static nsresult GetPluginJSObject(JSContext *cx, JSObject *obj,
|
||||
|
Loading…
x
Reference in New Issue
Block a user