зеркало из https://github.com/mozilla/gecko-dev.git
Bug 90268: Change plugin instance ownership from layout to content. r=roc r=bsmedberg
This commit is contained in:
Родитель
e3bd9f545e
Коммит
bfed8cb272
|
@ -1712,6 +1712,13 @@ public:
|
|||
const nsAString& aClasses,
|
||||
nsIDOMNodeList** aReturn);
|
||||
|
||||
/**
|
||||
* Returns the widget for this document if there is one. Looks at all ancestor
|
||||
* documents to try to find a widget, so for example this can still find a
|
||||
* widget for documents in display:none frames that have no presentation.
|
||||
*/
|
||||
static nsIWidget *WidgetForDocument(nsIDocument *aDoc);
|
||||
|
||||
/**
|
||||
* Returns a layer manager to use for the given document. Basically we
|
||||
* look up the document hierarchy for the first document which has
|
||||
|
|
|
@ -51,7 +51,7 @@ interface nsIDOMClientRect;
|
|||
/**
|
||||
* This interface represents a content node that loads objects.
|
||||
*/
|
||||
[scriptable, uuid(e5330f90-91a3-41d7-b29e-af38a23a6602)]
|
||||
[scriptable, uuid(6D8914C7-0E22-4452-8962-11B69BBE84D7)]
|
||||
interface nsIObjectLoadingContent : nsISupports
|
||||
{
|
||||
const unsigned long TYPE_LOADING = 0;
|
||||
|
@ -86,24 +86,6 @@ interface nsIObjectLoadingContent : nsISupports
|
|||
*/
|
||||
[noscript] readonly attribute nsNPAPIPluginInstancePtr pluginInstance;
|
||||
|
||||
/**
|
||||
* Makes sure that a frame for this object exists, and that the plugin is
|
||||
* instantiated. This method does nothing if the type is not #TYPE_PLUGIN.
|
||||
* There is no guarantee that there will be a frame after this method is
|
||||
* called; for example, the node may have a display:none style. If plugin
|
||||
* instantiation is possible, it will be done synchronously by this method,
|
||||
* and the plugin instance will be returned. A success return value does not
|
||||
* necessarily mean that the instance is nonnull.
|
||||
*
|
||||
* This is a noscript method because it is internal and will go away once
|
||||
* plugin loading moves to content.
|
||||
*
|
||||
* @note If there is an error instantiating the plugin, this method will
|
||||
* trigger fallback to replacement content, and the type will change (and
|
||||
* this method will return a failure code)
|
||||
*/
|
||||
[noscript] nsNPAPIPluginInstancePtr ensureInstantiation();
|
||||
|
||||
/**
|
||||
* Tells the content about an associated object frame.
|
||||
* This can be called multiple times for different frames.
|
||||
|
@ -113,6 +95,8 @@ interface nsIObjectLoadingContent : nsISupports
|
|||
*/
|
||||
[noscript] void hasNewFrame(in nsIObjectFrame aFrame);
|
||||
|
||||
[noscript] void disconnectFrame();
|
||||
|
||||
/**
|
||||
* If this object is in going to be printed, this method
|
||||
* returns the nsIObjectFrame object which should be used when
|
||||
|
@ -131,4 +115,9 @@ interface nsIObjectLoadingContent : nsISupports
|
|||
* click-to-play plugins feature.
|
||||
*/
|
||||
void playPlugin();
|
||||
|
||||
[noscript] void stopPluginInstance();
|
||||
|
||||
[noscript] void syncStartPluginInstance();
|
||||
[noscript] void asyncStartPluginInstance();
|
||||
};
|
||||
|
|
|
@ -5845,9 +5845,8 @@ nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
|
|||
}
|
||||
}
|
||||
|
||||
static already_AddRefed<LayerManager>
|
||||
LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
|
||||
bool* aAllowRetaining)
|
||||
nsIWidget *
|
||||
nsContentUtils::WidgetForDocument(nsIDocument *aDoc)
|
||||
{
|
||||
nsIDocument* doc = aDoc;
|
||||
nsIDocument* displayDoc = doc->GetDisplayDocument();
|
||||
|
@ -5882,15 +5881,7 @@ LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
|
|||
if (rootView) {
|
||||
nsIView* displayRoot = nsIViewManager::GetDisplayRootFor(rootView);
|
||||
if (displayRoot) {
|
||||
nsIWidget* widget = displayRoot->GetNearestWidget(nsnull);
|
||||
if (widget) {
|
||||
nsRefPtr<LayerManager> manager =
|
||||
widget->
|
||||
GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT :
|
||||
nsIWidget::LAYER_MANAGER_CURRENT,
|
||||
aAllowRetaining);
|
||||
return manager.forget();
|
||||
}
|
||||
return displayRoot->GetNearestWidget(nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5899,6 +5890,22 @@ LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
static already_AddRefed<LayerManager>
|
||||
LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
|
||||
bool* aAllowRetaining)
|
||||
{
|
||||
nsIWidget *widget = nsContentUtils::WidgetForDocument(aDoc);
|
||||
if (widget) {
|
||||
nsRefPtr<LayerManager> manager =
|
||||
widget->GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT :
|
||||
nsIWidget::LAYER_MANAGER_CURRENT,
|
||||
aAllowRetaining);
|
||||
return manager.forget();
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
already_AddRefed<LayerManager>
|
||||
nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
|
||||
{
|
||||
|
|
|
@ -176,6 +176,7 @@
|
|||
#include "nsIDOMPageTransitionEvent.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
#ifdef MOZ_MEDIA
|
||||
#include "nsHTMLMediaElement.h"
|
||||
#endif // MOZ_MEDIA
|
||||
|
@ -3755,6 +3756,11 @@ NotifyActivityChanged(nsIContent *aContent, void *aUnused)
|
|||
mediaElem->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
#endif
|
||||
nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aContent));
|
||||
if (objectLoadingContent) {
|
||||
nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
|
||||
olc->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "nsImageLoadingContent.h"
|
||||
#include "jsgc.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -566,15 +567,20 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_MEDIA
|
||||
if (wasRegistered && oldDoc != newDoc) {
|
||||
#ifdef MOZ_MEDIA
|
||||
nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aNode));
|
||||
if (domMediaElem) {
|
||||
nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aNode);
|
||||
mediaElem->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aNode));
|
||||
if (objectLoadingContent) {
|
||||
nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
|
||||
olc->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// nsImageLoadingContent needs to know when its document changes
|
||||
if (oldDoc != newDoc) {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -53,11 +53,15 @@
|
|||
#include "nsIObjectLoadingContent.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
#include "nsIThreadInternal.h"
|
||||
|
||||
class nsAsyncInstantiateEvent;
|
||||
class nsStopPluginRunnable;
|
||||
class AutoNotifier;
|
||||
class AutoFallback;
|
||||
class AutoSetInstantiatingToFalse;
|
||||
class nsObjectFrame;
|
||||
|
||||
enum PluginSupportState {
|
||||
ePluginUnsupported, // The plugin is not supported (e.g. not installed)
|
||||
|
@ -97,6 +101,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
friend class AutoNotifier;
|
||||
friend class AutoFallback;
|
||||
friend class AutoSetInstantiatingToFalse;
|
||||
friend class nsStopPluginRunnable;
|
||||
friend class nsAsyncInstantiateEvent;
|
||||
|
||||
public:
|
||||
// This enum's values must be the same as the constants on
|
||||
|
@ -139,6 +145,14 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
{
|
||||
mNetworkCreated = aNetworkCreated;
|
||||
}
|
||||
|
||||
// Can flush layout.
|
||||
nsresult InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI);
|
||||
|
||||
void NotifyOwnerDocumentActivityChanged();
|
||||
|
||||
bool SrcStreamLoadInitiated() { return mSrcStreamLoadInitiated; };
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Load the object from the given URI.
|
||||
|
@ -227,7 +241,13 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
nsCycleCollectionTraversalCallback &cb);
|
||||
|
||||
void CreateStaticClone(nsObjectLoadingContent* aDest) const;
|
||||
|
||||
static void DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, bool aDelayedStop);
|
||||
|
||||
private:
|
||||
|
||||
void NotifyContentObjectWrapper();
|
||||
|
||||
/**
|
||||
* Check whether the given request represents a successful load.
|
||||
*/
|
||||
|
@ -288,25 +308,10 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
|
||||
|
||||
/**
|
||||
* Gets the frame that's associated with this content node in
|
||||
* presentation 0. Always returns null if the node doesn't currently
|
||||
* have a frame.
|
||||
*
|
||||
* @param aFlush When eFlushContent will flush content notifications
|
||||
* before returning a non-null value.
|
||||
* When eFlushLayout will flush layout and content
|
||||
* notifications before returning a non-null value.
|
||||
* When eDontFlush will never flush.
|
||||
*
|
||||
* eFlushLayout is needed in some cases by plug-ins to ensure
|
||||
* that NPP_SetWindow() gets called (from nsObjectFrame::DidReflow).
|
||||
* Gets the frame that's associated with this content node.
|
||||
* Does not flush.
|
||||
*/
|
||||
enum FlushType {
|
||||
eFlushContent,
|
||||
eFlushLayout,
|
||||
eDontFlush
|
||||
};
|
||||
nsIObjectFrame* GetExistingFrame(FlushType aFlushType);
|
||||
nsObjectFrame* GetExistingFrame();
|
||||
|
||||
/**
|
||||
* Handle being blocked by a content policy. aStatus is the nsresult
|
||||
|
@ -316,22 +321,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
void HandleBeingBlockedByContentPolicy(nsresult aStatus,
|
||||
PRInt16 aRetval);
|
||||
|
||||
/**
|
||||
* Checks if we have a frame that's ready for instantiation, and
|
||||
* if so, calls Instantiate(). Note that this can cause the frame
|
||||
* to be deleted while we're instantiating the plugin.
|
||||
*/
|
||||
nsresult TryInstantiate(const nsACString& aMIMEType, nsIURI* aURI);
|
||||
|
||||
/**
|
||||
* Instantiates the plugin. This differs from
|
||||
* GetFrame()->Instantiate() in that it ensures that the URI will
|
||||
* be non-null, and that a MIME type will be passed. Note that
|
||||
* this can cause the frame to be deleted while we're
|
||||
* instantiating the plugin.
|
||||
*/
|
||||
nsresult Instantiate(nsIObjectFrame* aFrame, const nsACString& aMIMEType, nsIURI* aURI);
|
||||
|
||||
/**
|
||||
* Get the plugin support state for the given content node and MIME type.
|
||||
* This is used for purposes of determining whether to fire PluginNotFound
|
||||
|
@ -414,13 +403,16 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
// This is used for click-to-play plugins.
|
||||
bool mShouldPlay : 1;
|
||||
|
||||
// Used to indicate that a stream for a src/data attribute has been
|
||||
// initiated so that we don't do it twice.
|
||||
bool mSrcStreamLoadInitiated;
|
||||
|
||||
// A specific state that caused us to fallback
|
||||
PluginSupportState mFallbackReason;
|
||||
|
||||
nsWeakFrame mPrintFrame;
|
||||
|
||||
friend class nsAsyncInstantiateEvent;
|
||||
nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
#include "sampler.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -146,20 +147,13 @@ PluginStreamListener::SetupPlugin()
|
|||
// nsObjectFrame does that at the end of reflow.
|
||||
shell->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
nsIFrame* frame = embed->GetPrimaryFrame();
|
||||
if (!frame) {
|
||||
mPluginDoc->AllowNormalInstantiation();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIObjectFrame* objFrame = do_QueryFrame(frame);
|
||||
if (!objFrame) {
|
||||
mPluginDoc->AllowNormalInstantiation();
|
||||
nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(embed));
|
||||
if (!olc) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsresult rv = objFrame->Instantiate(mPluginDoc->GetType().get(),
|
||||
mDocument->nsIDocument::GetDocumentURI());
|
||||
nsObjectLoadingContent* olcc = static_cast<nsObjectLoadingContent*>(olc.get());
|
||||
nsresult rv = olcc->InstantiatePluginInstance(mPluginDoc->GetType().get(),
|
||||
mDocument->nsIDocument::GetDocumentURI());
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -357,7 +351,7 @@ PluginDocument::Print()
|
|||
nsIObjectFrame* objectFrame =
|
||||
do_QueryFrame(mPluginContent->GetPrimaryFrame());
|
||||
if (objectFrame) {
|
||||
nsCOMPtr<nsNPAPIPluginInstance> pi;
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
objectFrame->GetPluginInstance(getter_AddRefs(pi));
|
||||
if (pi) {
|
||||
NPPrint npprint;
|
||||
|
|
|
@ -9559,7 +9559,8 @@ nsHTMLSelectElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
|
||||
|
||||
// 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,
|
||||
|
@ -9574,36 +9575,21 @@ nsHTMLPluginObjElementSH::GetPluginInstanceIfSafe(nsIXPConnectWrappedNative *wra
|
|||
nsCOMPtr<nsIObjectLoadingContent> objlc(do_QueryInterface(content));
|
||||
NS_ASSERTION(objlc, "Object nodes must implement nsIObjectLoadingContent");
|
||||
|
||||
// If it's not safe to run script we'll only return the instance if it
|
||||
// exists.
|
||||
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.
|
||||
if (!nsContentUtils::IsSafeToRunScript()) {
|
||||
return objlc->GetPluginInstance(_result);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Make sure that there is a plugin
|
||||
return objlc->EnsureInstantiation(_result);
|
||||
}
|
||||
// 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();
|
||||
|
||||
// Check if proto is already in obj's prototype chain.
|
||||
|
||||
static bool
|
||||
IsObjInProtoChain(JSContext *cx, JSObject *obj, JSObject *proto)
|
||||
{
|
||||
JSObject *o = obj;
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
while (o) {
|
||||
JSObject *p = ::JS_GetPrototype(cx, o);
|
||||
|
||||
if (p == proto) {
|
||||
return true;
|
||||
}
|
||||
|
||||
o = p;
|
||||
}
|
||||
|
||||
return false;
|
||||
return objlc->GetPluginInstance(_result);
|
||||
}
|
||||
|
||||
class nsPluginProtoChainInstallRunner : public nsIRunnable
|
||||
|
@ -9685,20 +9671,9 @@ nsHTMLPluginObjElementSH::SetupProtoChain(nsIXPConnectWrappedNative *wrapper,
|
|||
|
||||
if (!pi_obj) {
|
||||
// Didn't get a plugin instance JSObject, nothing we can do then.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (IsObjInProtoChain(cx, obj, pi_obj)) {
|
||||
// We must have re-entered ::PostCreate() from nsObjectFrame()
|
||||
// (through the EnsureInstantiation() call in
|
||||
// GetPluginInstanceIfSafe()), this means that we've already done what
|
||||
// we're about to do in this function so we can just return here.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// If we got an xpconnect-wrapped plugin object, set obj's
|
||||
// prototype's prototype to the scriptable plugin.
|
||||
|
||||
|
|
|
@ -532,7 +532,7 @@ nsDummyJavaPluginOwner::GetWindow(NPWindow *&aWindow)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDummyJavaPluginOwner::SetWindow()
|
||||
nsDummyJavaPluginOwner::CallSetWindow()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -144,5 +144,5 @@ interface nsIPluginInstanceOwner : nsISupports
|
|||
/**
|
||||
* Call NPP_SetWindow on the plugin.
|
||||
*/
|
||||
void setWindow();
|
||||
void callSetWindow();
|
||||
};
|
||||
|
|
|
@ -93,7 +93,6 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
|
|||
#endif
|
||||
mRunning(NOT_STARTED),
|
||||
mWindowless(false),
|
||||
mWindowlessLocal(false),
|
||||
mTransparent(false),
|
||||
mCached(false),
|
||||
mUsesDOMForCursor(false),
|
||||
|
@ -686,12 +685,6 @@ NPError nsNPAPIPluginInstance::SetWindowless(bool aWindowless)
|
|||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError nsNPAPIPluginInstance::SetWindowlessLocal(bool aWindowlessLocal)
|
||||
{
|
||||
mWindowlessLocal = aWindowlessLocal;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError nsNPAPIPluginInstance::SetTransparent(bool aTransparent)
|
||||
{
|
||||
mTransparent = aTransparent;
|
||||
|
|
|
@ -135,8 +135,6 @@ public:
|
|||
|
||||
NPError SetWindowless(bool aWindowless);
|
||||
|
||||
NPError SetWindowlessLocal(bool aWindowlessLocal);
|
||||
|
||||
NPError SetTransparent(bool aTransparent);
|
||||
|
||||
NPError SetWantsAllNetworkStreams(bool aWantsAllNetworkStreams);
|
||||
|
@ -244,7 +242,6 @@ protected:
|
|||
// these are used to store the windowless properties
|
||||
// which the browser will later query
|
||||
bool mWindowless;
|
||||
bool mWindowlessLocal;
|
||||
bool mTransparent;
|
||||
bool mCached;
|
||||
bool mUsesDOMForCursor;
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
#include "nsContentErrors.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
@ -939,10 +940,10 @@ nsPluginHost::GetPluginTempDir(nsIFile **aDir)
|
|||
}
|
||||
|
||||
nsresult nsPluginHost::InstantiatePluginForChannel(nsIChannel* aChannel,
|
||||
nsIPluginInstanceOwner* aOwner,
|
||||
nsObjectLoadingContent* aContent,
|
||||
nsIStreamListener** aListener)
|
||||
{
|
||||
NS_PRECONDITION(aChannel && aOwner,
|
||||
NS_PRECONDITION(aChannel && aContent,
|
||||
"Invalid arguments to InstantiatePluginForChannel");
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
|
||||
|
@ -955,8 +956,8 @@ nsresult nsPluginHost::InstantiatePluginForChannel(nsIChannel* aChannel,
|
|||
uri->GetAsciiSpec(urlSpec);
|
||||
|
||||
PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
|
||||
("nsPluginHost::InstantiatePluginForChannel Begin owner=%p, url=%s\n",
|
||||
aOwner, urlSpec.get()));
|
||||
("nsPluginHost::InstantiatePluginForChannel Begin content=%p, url=%s\n",
|
||||
aContent, urlSpec.get()));
|
||||
|
||||
PR_LogFlush();
|
||||
}
|
||||
|
@ -965,12 +966,13 @@ nsresult nsPluginHost::InstantiatePluginForChannel(nsIChannel* aChannel,
|
|||
// Note that we're not setting up a plugin instance here; the stream
|
||||
// listener's OnStartRequest will handle doing that.
|
||||
|
||||
return NewEmbeddedPluginStreamListener(uri, aOwner, nsnull, aListener);
|
||||
return NewEmbeddedPluginStreamListener(uri, aContent, nsnull, aListener);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPluginHost::InstantiateEmbeddedPlugin(const char *aMimeType, nsIURI* aURL,
|
||||
nsIPluginInstanceOwner* aOwner)
|
||||
nsObjectLoadingContent *aContent,
|
||||
nsPluginInstanceOwner** aOwner)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOwner);
|
||||
|
||||
|
@ -980,29 +982,41 @@ nsPluginHost::InstantiateEmbeddedPlugin(const char *aMimeType, nsIURI* aURL,
|
|||
aURL->GetAsciiSpec(urlSpec);
|
||||
|
||||
PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
|
||||
("nsPluginHost::InstantiateEmbeddedPlugin Begin mime=%s, owner=%p, url=%s\n",
|
||||
aMimeType, aOwner, urlSpec.get()));
|
||||
("nsPluginHost::InstantiateEmbeddedPlugin Begin mime=%s, url=%s\n",
|
||||
aMimeType, urlSpec.get()));
|
||||
|
||||
PR_LogFlush();
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<nsPluginInstanceOwner> instanceOwner = new nsPluginInstanceOwner();
|
||||
if (!instanceOwner) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> ourContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(aContent));
|
||||
nsresult rv = instanceOwner->Init(ourContent);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPluginTagInfo> pti;
|
||||
rv = instanceOwner->QueryInterface(kIPluginTagInfoIID, getter_AddRefs(pti));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsPluginTagType tagType;
|
||||
|
||||
rv = aOwner->QueryInterface(kIPluginTagInfoIID, getter_AddRefs(pti));
|
||||
|
||||
if (rv != NS_OK)
|
||||
return rv;
|
||||
|
||||
rv = pti->GetTagType(&tagType);
|
||||
|
||||
if ((rv != NS_OK) || !((tagType == nsPluginTagType_Embed)
|
||||
|| (tagType == nsPluginTagType_Applet)
|
||||
|| (tagType == nsPluginTagType_Object))) {
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (tagType != nsPluginTagType_Embed &&
|
||||
tagType != nsPluginTagType_Applet &&
|
||||
tagType != nsPluginTagType_Object) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Security checks. Can't do security checks without a URI - hopefully the plugin
|
||||
// will take care of that.
|
||||
if (aURL) {
|
||||
|
@ -1012,7 +1026,7 @@ nsPluginHost::InstantiateEmbeddedPlugin(const char *aMimeType, nsIURI* aURL,
|
|||
return rv; // Better fail if we can't do security checks
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
aOwner->GetDocument(getter_AddRefs(doc));
|
||||
instanceOwner->GetDocument(getter_AddRefs(doc));
|
||||
if (!doc)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
|
@ -1060,97 +1074,118 @@ nsPluginHost::InstantiateEmbeddedPlugin(const char *aMimeType, nsIURI* aURL,
|
|||
|
||||
// if we don't have a MIME type at this point, we still have one more chance by
|
||||
// opening the stream and seeing if the server hands one back
|
||||
if (!aMimeType)
|
||||
return bCanHandleInternally ? NewEmbeddedPluginStream(aURL, aOwner, nsnull) : NS_ERROR_FAILURE;
|
||||
|
||||
rv = SetUpPluginInstance(aMimeType, aURL, aOwner);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
if (!aMimeType) {
|
||||
if (bCanHandleInternally && !aContent->SrcStreamLoadInitiated()) {
|
||||
NewEmbeddedPluginStream(aURL, aContent, nsnull);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = SetUpPluginInstance(aMimeType, aURL, instanceOwner);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> instance;
|
||||
rv = aOwner->GetInstance(getter_AddRefs(instance));
|
||||
// if we have a failure error, it means we found a plugin for the mimetype,
|
||||
// but we had a problem with the entry point
|
||||
if (rv == NS_ERROR_FAILURE)
|
||||
rv = instanceOwner->GetInstance(getter_AddRefs(instance));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (instance) {
|
||||
aOwner->CreateWidget();
|
||||
instanceOwner->CreateWidget();
|
||||
|
||||
// If we've got a native window, the let the plugin know about it.
|
||||
aOwner->SetWindow();
|
||||
instanceOwner->CallSetWindow();
|
||||
|
||||
// create an initial stream with data
|
||||
// don't make the stream if it's a java applet or we don't have SRC or DATA attribute
|
||||
bool havedata = false;
|
||||
|
||||
nsCOMPtr<nsIPluginTagInfo> pti(do_QueryInterface(aOwner, &rv));
|
||||
|
||||
if (pti) {
|
||||
const char *value;
|
||||
havedata = NS_SUCCEEDED(pti->GetAttribute("SRC", &value));
|
||||
// no need to check for "data" as it would have been converted to "src"
|
||||
// no need to check for "data" as it would have been converted to "src"
|
||||
const char *value;
|
||||
bool havedata = NS_SUCCEEDED(pti->GetAttribute("SRC", &value));
|
||||
if (havedata && !isJava && bCanHandleInternally && !aContent->SrcStreamLoadInitiated()) {
|
||||
NewEmbeddedPluginStream(aURL, nsnull, instance.get());
|
||||
}
|
||||
|
||||
if (havedata && !isJava && bCanHandleInternally)
|
||||
rv = NewEmbeddedPluginStream(aURL, aOwner, instance.get());
|
||||
}
|
||||
|
||||
// At this point we consider instantiation to be successful. Do not return an error.
|
||||
instanceOwner.forget(aOwner);
|
||||
|
||||
#ifdef PLUGIN_LOGGING
|
||||
nsCAutoString urlSpec2;
|
||||
if (aURL != nsnull) aURL->GetAsciiSpec(urlSpec2);
|
||||
|
||||
PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
|
||||
("nsPluginHost::InstantiateEmbeddedPlugin Finished mime=%s, rv=%d, owner=%p, url=%s\n",
|
||||
aMimeType, rv, aOwner, urlSpec2.get()));
|
||||
("nsPluginHost::InstantiateEmbeddedPlugin Finished mime=%s, rv=%d, url=%s\n",
|
||||
aMimeType, rv, urlSpec2.get()));
|
||||
|
||||
PR_LogFlush();
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginHost::InstantiateFullPagePlugin(const char *aMimeType,
|
||||
nsIURI* aURI,
|
||||
nsIPluginInstanceOwner *aOwner,
|
||||
nsObjectLoadingContent *aContent,
|
||||
nsPluginInstanceOwner **aOwner,
|
||||
nsIStreamListener **aStreamListener)
|
||||
{
|
||||
#ifdef PLUGIN_LOGGING
|
||||
nsCAutoString urlSpec;
|
||||
aURI->GetSpec(urlSpec);
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("nsPluginHost::InstantiateFullPagePlugin Begin mime=%s, owner=%p, url=%s\n",
|
||||
aMimeType, aOwner, urlSpec.get()));
|
||||
("nsPluginHost::InstantiateFullPagePlugin Begin mime=%s, url=%s\n",
|
||||
aMimeType, urlSpec.get()));
|
||||
#endif
|
||||
|
||||
nsresult rv = SetUpPluginInstance(aMimeType, aURI, aOwner);
|
||||
|
||||
if (NS_OK == rv) {
|
||||
nsRefPtr<nsNPAPIPluginInstance> instance;
|
||||
aOwner->GetInstance(getter_AddRefs(instance));
|
||||
|
||||
NPWindow* win = nsnull;
|
||||
aOwner->GetWindow(win);
|
||||
|
||||
if (win && instance) {
|
||||
aOwner->CreateWidget();
|
||||
|
||||
// If we've got a native window, the let the plugin know about it.
|
||||
aOwner->SetWindow();
|
||||
|
||||
rv = NewFullPagePluginStream(aURI, instance.get(), aStreamListener);
|
||||
|
||||
// If we've got a native window, the let the plugin know about it.
|
||||
aOwner->SetWindow();
|
||||
}
|
||||
nsRefPtr<nsPluginInstanceOwner> instanceOwner = new nsPluginInstanceOwner();
|
||||
if (!instanceOwner) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("nsPluginHost::InstantiateFullPagePlugin End mime=%s, rv=%d, owner=%p, url=%s\n",
|
||||
aMimeType, rv, aOwner, urlSpec.get()));
|
||||
nsCOMPtr<nsIContent> ourContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(aContent));
|
||||
nsresult rv = instanceOwner->Init(ourContent);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
rv = SetUpPluginInstance(aMimeType, aURI, instanceOwner);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> instance;
|
||||
instanceOwner->GetInstance(getter_AddRefs(instance));
|
||||
if (!instance) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NPWindow* win = nsnull;
|
||||
instanceOwner->GetWindow(win);
|
||||
if (!win) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Set up any widget that might be required.
|
||||
instanceOwner->CreateWidget();
|
||||
instanceOwner->CallSetWindow();
|
||||
|
||||
rv = NewFullPagePluginStream(aURI, instance.get(), aStreamListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Call SetWindow again in case something changed.
|
||||
instanceOwner->CallSetWindow();
|
||||
|
||||
instanceOwner.forget(aOwner);
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("nsPluginHost::InstantiateFullPagePlugin End mime=%s, rv=%d, url=%s\n",
|
||||
aMimeType, rv, urlSpec.get()));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsPluginTag*
|
||||
|
@ -3265,7 +3300,7 @@ nsPluginHost::StopPluginInstance(nsNPAPIPluginInstance* aInstance)
|
|||
}
|
||||
|
||||
nsresult nsPluginHost::NewEmbeddedPluginStreamListener(nsIURI* aURL,
|
||||
nsIPluginInstanceOwner *aOwner,
|
||||
nsObjectLoadingContent *aContent,
|
||||
nsNPAPIPluginInstance* aInstance,
|
||||
nsIStreamListener** aListener)
|
||||
{
|
||||
|
@ -3283,11 +3318,12 @@ nsresult nsPluginHost::NewEmbeddedPluginStreamListener(nsIURI* aURL,
|
|||
// so the listener can set up the instance later after
|
||||
// we've determined the mimetype of the stream
|
||||
if (aInstance)
|
||||
rv = listener->InitializeEmbedded(aURL, aInstance);
|
||||
else if (aOwner != nsnull)
|
||||
rv = listener->InitializeEmbedded(aURL, nsnull, aOwner);
|
||||
rv = listener->InitializeEmbedded(aURL, aInstance, nsnull);
|
||||
else if (aContent)
|
||||
rv = listener->InitializeEmbedded(aURL, nsnull, aContent);
|
||||
else
|
||||
rv = NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
NS_ADDREF(*aListener = listener);
|
||||
|
||||
|
@ -3296,18 +3332,21 @@ nsresult nsPluginHost::NewEmbeddedPluginStreamListener(nsIURI* aURL,
|
|||
|
||||
// Called by InstantiateEmbeddedPlugin()
|
||||
nsresult nsPluginHost::NewEmbeddedPluginStream(nsIURI* aURL,
|
||||
nsIPluginInstanceOwner *aOwner,
|
||||
nsObjectLoadingContent *aContent,
|
||||
nsNPAPIPluginInstance* aInstance)
|
||||
{
|
||||
NS_ASSERTION(!aContent || !aInstance, "Don't pass both content and an instance to NewEmbeddedPluginStream!");
|
||||
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
nsresult rv = NewEmbeddedPluginStreamListener(aURL, aOwner, aInstance,
|
||||
nsresult rv = NewEmbeddedPluginStreamListener(aURL, aContent, aInstance,
|
||||
getter_AddRefs(listener));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
if (aOwner) {
|
||||
rv = aOwner->GetDocument(getter_AddRefs(doc));
|
||||
if (NS_SUCCEEDED(rv) && doc) {
|
||||
if (aContent) {
|
||||
nsCOMPtr<nsIContent> aIContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(aContent));
|
||||
doc = aIContent->GetDocument();
|
||||
if (doc) {
|
||||
loadGroup = doc->GetDocumentLoadGroup();
|
||||
}
|
||||
}
|
||||
|
@ -3720,12 +3759,6 @@ nsPluginHost::NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow)
|
|||
return PLUG_NewPluginNativeWindow(aPluginNativeWindow);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPluginHost::DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
|
||||
{
|
||||
return PLUG_DeletePluginNativeWindow(aPluginNativeWindow);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPluginHost::InstantiateDummyJavaPlugin(nsIPluginInstanceOwner *aOwner)
|
||||
{
|
||||
|
|
|
@ -69,6 +69,8 @@ class nsIComponentManager;
|
|||
class nsIFile;
|
||||
class nsIChannel;
|
||||
class nsPluginNativeWindow;
|
||||
class nsObjectLoadingContent;
|
||||
class nsPluginInstanceOwner;
|
||||
|
||||
#if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
|
||||
#define MAC_CARBON_PLUGINS
|
||||
|
@ -112,7 +114,7 @@ public:
|
|||
nsresult Destroy();
|
||||
nsresult LoadPlugins();
|
||||
nsresult InstantiatePluginForChannel(nsIChannel* aChannel,
|
||||
nsIPluginInstanceOwner* aOwner,
|
||||
nsObjectLoadingContent* aContent,
|
||||
nsIStreamListener** aListener);
|
||||
nsresult SetUpPluginInstance(const char *aMimeType,
|
||||
nsIURI *aURL,
|
||||
|
@ -152,7 +154,6 @@ public:
|
|||
char **outPostData, PRUint32 *outPostDataLen);
|
||||
nsresult CreateTempFileToPost(const char *aPostDataURL, nsIFile **aTmpFile);
|
||||
nsresult NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow);
|
||||
nsresult DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow);
|
||||
nsresult InstantiateDummyJavaPlugin(nsIPluginInstanceOwner *aOwner);
|
||||
|
||||
void AddIdleTimeTarget(nsIPluginInstanceOwner* objectFrame, bool isVisible);
|
||||
|
@ -222,11 +223,13 @@ public:
|
|||
// The last argument should be false if we already have an in-flight stream
|
||||
// and don't need to set up a new stream.
|
||||
nsresult InstantiateEmbeddedPlugin(const char *aMimeType, nsIURI* aURL,
|
||||
nsIPluginInstanceOwner* aOwner);
|
||||
nsObjectLoadingContent *aContent,
|
||||
nsPluginInstanceOwner** aOwner);
|
||||
|
||||
nsresult InstantiateFullPagePlugin(const char *aMimeType,
|
||||
nsIURI* aURI,
|
||||
nsIPluginInstanceOwner *aOwner,
|
||||
nsObjectLoadingContent *aContent,
|
||||
nsPluginInstanceOwner **aOwner,
|
||||
nsIStreamListener **aStreamListener);
|
||||
|
||||
// Does not accept NULL and should never fail.
|
||||
|
@ -239,12 +242,12 @@ private:
|
|||
TrySetUpPluginInstance(const char *aMimeType, nsIURI *aURL, nsIPluginInstanceOwner *aOwner);
|
||||
|
||||
nsresult
|
||||
NewEmbeddedPluginStreamListener(nsIURI* aURL, nsIPluginInstanceOwner *aOwner,
|
||||
NewEmbeddedPluginStreamListener(nsIURI* aURL, nsObjectLoadingContent *aContent,
|
||||
nsNPAPIPluginInstance* aInstance,
|
||||
nsIStreamListener** aListener);
|
||||
|
||||
nsresult
|
||||
NewEmbeddedPluginStream(nsIURI* aURL, nsIPluginInstanceOwner *aOwner, nsNPAPIPluginInstance* aInstance);
|
||||
NewEmbeddedPluginStream(nsIURI* aURL, nsObjectLoadingContent *aContent, nsNPAPIPluginInstance* aInstance);
|
||||
|
||||
nsresult
|
||||
NewFullPagePluginStream(nsIURI* aURI,
|
||||
|
|
|
@ -94,9 +94,11 @@ using mozilla::DefaultXDisplay;
|
|||
#include "nsFocusManager.h"
|
||||
#include "nsIDOMDragEvent.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
|
||||
#include "nsContentCID.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
|
||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
@ -185,7 +187,7 @@ nsPluginInstanceOwner::NotifyPaintWaiter(nsDisplayListBuilder* aBuilder)
|
|||
#ifdef XP_MACOSX
|
||||
static void DrawPlugin(ImageContainer* aContainer, void* aPluginInstanceOwner)
|
||||
{
|
||||
nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetOwner();
|
||||
nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetFrame();
|
||||
if (frame) {
|
||||
frame->UpdateImageLayer(aContainer, gfxRect(0,0,0,0));
|
||||
}
|
||||
|
@ -257,7 +259,14 @@ bool
|
|||
nsPluginInstanceOwner::UseAsyncRendering()
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
|
||||
if (mUseAsyncRendering) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsRefPtr<ImageContainer> container;
|
||||
if (mObjectFrame) {
|
||||
container = mObjectFrame->GetImageContainer();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool useAsyncRendering;
|
||||
|
@ -274,7 +283,13 @@ nsPluginInstanceOwner::UseAsyncRendering()
|
|||
#endif
|
||||
);
|
||||
|
||||
return result;
|
||||
#ifdef XP_MACOSX
|
||||
if (result) {
|
||||
mUseAsyncRendering = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIntSize
|
||||
|
@ -292,14 +307,16 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
|
|||
// create nsPluginNativeWindow object, it is derived from NPWindow
|
||||
// struct and allows to manipulate native window procedure
|
||||
nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
|
||||
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (pluginHost)
|
||||
pluginHost->NewPluginNativeWindow(&mPluginWindow);
|
||||
mPluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (mPluginHost)
|
||||
mPluginHost->NewPluginNativeWindow(&mPluginWindow);
|
||||
else
|
||||
mPluginWindow = nsnull;
|
||||
|
||||
mObjectFrame = nsnull;
|
||||
mContent = nsnull;
|
||||
mTagText = nsnull;
|
||||
mWidgetCreationComplete = false;
|
||||
#ifdef XP_MACOSX
|
||||
memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext));
|
||||
#ifndef NP_NO_QUICKDRAW
|
||||
|
@ -318,7 +335,6 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
|
|||
mNumCachedParams = 0;
|
||||
mCachedAttrParamNames = nsnull;
|
||||
mCachedAttrParamValues = nsnull;
|
||||
mDestroyWidget = false;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#ifndef NP_NO_QUICKDRAW
|
||||
|
@ -326,6 +342,7 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
|
|||
#else
|
||||
mEventModel = NPEventModelCocoa;
|
||||
#endif
|
||||
mUseAsyncRendering = false;
|
||||
#endif
|
||||
|
||||
mWaitingForPaint = false;
|
||||
|
@ -380,13 +397,8 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
|
|||
mTagText = nsnull;
|
||||
}
|
||||
|
||||
// clean up plugin native window object
|
||||
nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
|
||||
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (pluginHost) {
|
||||
pluginHost->DeletePluginNativeWindow(mPluginWindow);
|
||||
mPluginWindow = nsnull;
|
||||
}
|
||||
PLUG_DeletePluginNativeWindow(mPluginWindow);
|
||||
mPluginWindow = nsnull;
|
||||
|
||||
if (mInstance) {
|
||||
mInstance->InvalidateOwner();
|
||||
|
@ -490,14 +502,29 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
|
|||
void *aHeadersData,
|
||||
PRUint32 aHeadersDataLen)
|
||||
{
|
||||
NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(mContent, NS_ERROR_NULL_POINTER);
|
||||
|
||||
if (mContent->IsEditable()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument *doc = mContent->GetCurrentDoc();
|
||||
if (!doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsIPresShell *presShell = doc->GetShell();
|
||||
if (!presShell) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsPresContext *presContext = presShell->GetPresContext();
|
||||
if (!presContext) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// the container of the pres context will give us the link handler
|
||||
nsCOMPtr<nsISupports> container = mObjectFrame->PresContext()->GetContainer();
|
||||
nsCOMPtr<nsISupports> container = presContext->GetContainer();
|
||||
NS_ENSURE_TRUE(container,NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsILinkHandler> lh = do_QueryInterface(container);
|
||||
NS_ENSURE_TRUE(lh, NS_ERROR_FAILURE);
|
||||
|
@ -745,12 +772,6 @@ NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(PRInt32 eventModel)
|
|||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginInstanceOwner::SetWindow()
|
||||
{
|
||||
NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_NULL_POINTER);
|
||||
return mObjectFrame->CallSetWindow(false);
|
||||
}
|
||||
|
||||
NPError nsPluginInstanceOwner::ShowNativeContextMenu(NPMenu* menu, void* event)
|
||||
{
|
||||
if (!menu || !event)
|
||||
|
@ -1092,7 +1113,6 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
|||
!mCachedAttrParamNames,
|
||||
"re-cache of attrs/params not implemented! use the DOM "
|
||||
"node directy instead");
|
||||
NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// Convert to a 16-bit count. Subtract 2 in case we add an extra
|
||||
// "src" or "wmode" entry below.
|
||||
|
@ -1165,9 +1185,6 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
|||
}
|
||||
}
|
||||
|
||||
// We're done with DOM method calls now. Make sure we still have a frame.
|
||||
NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Convert to a 16-bit count.
|
||||
PRUint32 cparams = ourParams.Count();
|
||||
if (cparams < 0x0000FFFF) {
|
||||
|
@ -2730,75 +2747,20 @@ nsPluginInstanceOwner::Destroy()
|
|||
#endif
|
||||
|
||||
if (mWidget) {
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
||||
if (pluginWidget)
|
||||
pluginWidget->SetPluginInstanceOwner(nsnull);
|
||||
if (mPluginWindow) {
|
||||
mPluginWindow->SetPluginWidget(nsnull);
|
||||
}
|
||||
|
||||
if (mDestroyWidget)
|
||||
mWidget->Destroy();
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
||||
if (pluginWidget) {
|
||||
pluginWidget->SetPluginInstanceOwner(nsnull);
|
||||
}
|
||||
mWidget->Destroy();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare to stop
|
||||
*/
|
||||
void
|
||||
nsPluginInstanceOwner::PrepareToStop(bool aDelayedStop)
|
||||
{
|
||||
// Drop image reference because the child may destroy the surface after we return.
|
||||
nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
|
||||
if (container) {
|
||||
#ifdef XP_MACOSX
|
||||
nsRefPtr<Image> image = container->GetCurrentImage();
|
||||
if (image && (image->GetFormat() == Image::MAC_IO_SURFACE) && mObjectFrame) {
|
||||
// Undo what we did to the current image in SetCurrentImage().
|
||||
MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image.get());
|
||||
oglImage->SetUpdateCallback(nsnull, nsnull);
|
||||
oglImage->SetDestroyCallback(nsnull);
|
||||
// If we have a current image here, its destructor hasn't yet been
|
||||
// called, so OnDestroyImage() can't yet have been called. So we need
|
||||
// to do ourselves what OnDestroyImage() would have done.
|
||||
NS_RELEASE_THIS();
|
||||
}
|
||||
#endif
|
||||
container->SetCurrentImage(nsnull);
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) || defined(MOZ_X11)
|
||||
if (aDelayedStop && mWidget) {
|
||||
// To delay stopping a plugin we need to reparent the plugin
|
||||
// so that we can safely tear down the
|
||||
// plugin after its frame (and view) is gone.
|
||||
|
||||
// Also hide and disable the widget to avoid it from appearing in
|
||||
// odd places after reparenting it, but before it gets destroyed.
|
||||
mWidget->Show(false);
|
||||
mWidget->Enable(false);
|
||||
|
||||
// Reparent the plugins native window. This relies on the widget
|
||||
// and plugin et al not holding any other references to its
|
||||
// parent.
|
||||
mWidget->SetParent(nsnull);
|
||||
|
||||
mDestroyWidget = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
RemovePluginView();
|
||||
#endif
|
||||
|
||||
// Unregister scroll position listeners
|
||||
for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(f);
|
||||
if (sf) {
|
||||
sf->RemoveScrollPositionListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Paints are handled differently, so we just simulate an update event.
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
@ -3206,25 +3168,24 @@ void nsPluginInstanceOwner::CancelTimer()
|
|||
}
|
||||
#endif
|
||||
|
||||
nsresult nsPluginInstanceOwner::Init(nsPresContext* aPresContext,
|
||||
nsObjectFrame* aFrame,
|
||||
nsIContent* aContent)
|
||||
nsresult nsPluginInstanceOwner::Init(nsIContent* aContent)
|
||||
{
|
||||
mLastEventloopNestingLevel = GetEventloopNestingLevel();
|
||||
|
||||
mObjectFrame = aFrame;
|
||||
mContent = aContent;
|
||||
|
||||
nsWeakFrame weakFrame(aFrame);
|
||||
|
||||
// Some plugins require a specific sequence of shutdown and startup when
|
||||
// a page is reloaded. Shutdown happens usually when the last instance
|
||||
// is destroyed. Here we make sure the plugin instance in the old
|
||||
// document is destroyed before we try to create the new one.
|
||||
aPresContext->EnsureVisible();
|
||||
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
// Get a frame, don't reflow. If a reflow was necessary it should have been
|
||||
// done at a higher level than this (content).
|
||||
nsIFrame* frame = aContent->GetPrimaryFrame();
|
||||
nsIObjectFrame* iObjFrame = do_QueryFrame(frame);
|
||||
nsObjectFrame* objFrame = static_cast<nsObjectFrame*>(iObjFrame);
|
||||
if (objFrame) {
|
||||
SetFrame(objFrame);
|
||||
// Some plugins require a specific sequence of shutdown and startup when
|
||||
// a page is reloaded. Shutdown happens usually when the last instance
|
||||
// is destroyed. Here we make sure the plugin instance in the old
|
||||
// document is destroyed before we try to create the new one.
|
||||
objFrame->PresContext()->EnsureVisible();
|
||||
}
|
||||
|
||||
// register context menu listener
|
||||
|
@ -3267,16 +3228,6 @@ nsresult nsPluginInstanceOwner::Init(nsPresContext* aPresContext,
|
|||
#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
|
||||
mContent->AddEventListener(NS_LITERAL_STRING("text"), this, true);
|
||||
#endif
|
||||
|
||||
// Register scroll position listeners
|
||||
// We need to register a scroll position listener on every scrollable
|
||||
// frame up to the top
|
||||
for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(f);
|
||||
if (sf) {
|
||||
sf->AddScrollPositionListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3318,88 +3269,95 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
|
|||
{
|
||||
NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
// Can't call this twice!
|
||||
if (mWidget) {
|
||||
NS_WARNING("Trying to create a plugin widget twice!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool windowless = false;
|
||||
mInstance->IsWindowless(&windowless);
|
||||
if (!windowless && !nsIWidget::UsePuppetWidgets()) {
|
||||
// Try to get a parent widget, on some platforms widget creation will fail without
|
||||
// a parent.
|
||||
nsCOMPtr<nsIWidget> parentWidget;
|
||||
nsIDocument *doc = nsnull;
|
||||
if (mContent) {
|
||||
doc = mContent->OwnerDoc();
|
||||
parentWidget = nsContentUtils::WidgetForDocument(doc);
|
||||
}
|
||||
|
||||
mWidget = do_CreateInstance(kWidgetCID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsWidgetInitData initData;
|
||||
initData.mWindowType = eWindowType_plugin;
|
||||
initData.mUnicode = false;
|
||||
initData.clipChildren = true;
|
||||
initData.clipSiblings = true;
|
||||
rv = mWidget->Create(parentWidget.get(), nsnull, nsIntRect(0,0,0,0),
|
||||
nsnull, nsnull, &initData);
|
||||
if (NS_FAILED(rv)) {
|
||||
mWidget->Destroy();
|
||||
mWidget = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
mWidget->EnableDragDrop(true);
|
||||
mWidget->Show(false);
|
||||
mWidget->Enable(false);
|
||||
}
|
||||
|
||||
if (mObjectFrame) {
|
||||
if (!mWidget) {
|
||||
bool windowless = false;
|
||||
mInstance->IsWindowless(&windowless);
|
||||
nsIDocument *doc = mContent ? mContent->OwnerDoc() : nsnull;
|
||||
// always create widgets in Twips, not pixels
|
||||
nsPresContext* context = mObjectFrame->PresContext();
|
||||
rv = mObjectFrame->CreateWidget(context->DevPixelsToAppUnits(mPluginWindow->width),
|
||||
context->DevPixelsToAppUnits(mPluginWindow->height),
|
||||
windowless);
|
||||
if (NS_OK == rv) {
|
||||
mWidget = mObjectFrame->GetWidget();
|
||||
// NULL widget is fine, will result in windowless setup.
|
||||
mObjectFrame->PrepForDrawing(mWidget);
|
||||
}
|
||||
|
||||
if (true == windowless) {
|
||||
mPluginWindow->type = NPWindowTypeDrawable;
|
||||
if (windowless) {
|
||||
mPluginWindow->type = NPWindowTypeDrawable;
|
||||
|
||||
// this needs to be a HDC according to the spec, but I do
|
||||
// not see the right way to release it so let's postpone
|
||||
// passing HDC till paint event when it is really
|
||||
// needed. Change spec?
|
||||
mPluginWindow->window = nsnull;
|
||||
// this needs to be a HDC according to the spec, but I do
|
||||
// not see the right way to release it so let's postpone
|
||||
// passing HDC till paint event when it is really
|
||||
// needed. Change spec?
|
||||
mPluginWindow->window = nsnull;
|
||||
#ifdef MOZ_X11
|
||||
// Fill in the display field.
|
||||
NPSetWindowCallbackStruct* ws_info =
|
||||
static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
|
||||
ws_info->display = DefaultXDisplay();
|
||||
|
||||
nsCAutoString description;
|
||||
GetPluginDescription(description);
|
||||
NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
|
||||
mFlash10Quirks = StringBeginsWith(description, flash10Head);
|
||||
// Fill in the display field.
|
||||
NPSetWindowCallbackStruct* ws_info =
|
||||
static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
|
||||
ws_info->display = DefaultXDisplay();
|
||||
|
||||
nsCAutoString description;
|
||||
GetPluginDescription(description);
|
||||
NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
|
||||
mFlash10Quirks = StringBeginsWith(description, flash10Head);
|
||||
#endif
|
||||
|
||||
// Changing to windowless mode changes the NPWindow geometry.
|
||||
mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
|
||||
} else if (mWidget) {
|
||||
nsIWidget* parent = mWidget->GetParent();
|
||||
NS_ASSERTION(parent, "Plugin windows must not be toplevel");
|
||||
// Set the plugin window to have an empty cliprect. The cliprect
|
||||
// will be reset when nsRootPresContext::UpdatePluginGeometry
|
||||
// runs later. The plugin window does need to have the correct
|
||||
// size here. GetEmptyClipConfiguration will probably give it the
|
||||
// size, but just in case we haven't been reflowed or something, set
|
||||
// the size explicitly.
|
||||
nsAutoTArray<nsIWidget::Configuration,1> configuration;
|
||||
mObjectFrame->GetEmptyClipConfiguration(&configuration);
|
||||
if (configuration.Length() > 0) {
|
||||
configuration[0].mBounds.width = mPluginWindow->width;
|
||||
configuration[0].mBounds.height = mPluginWindow->height;
|
||||
}
|
||||
parent->ConfigureChildren(configuration);
|
||||
|
||||
// mPluginWindow->type is used in |GetPluginPort| so it must
|
||||
// be initialized first
|
||||
mPluginWindow->type = NPWindowTypeWindow;
|
||||
mPluginWindow->window = GetPluginPortFromWidget();
|
||||
|
||||
} else if (mWidget) {
|
||||
// mPluginWindow->type is used in |GetPluginPort| so it must
|
||||
// be initialized first
|
||||
mPluginWindow->type = NPWindowTypeWindow;
|
||||
mPluginWindow->window = GetPluginPortFromWidget();
|
||||
#ifdef MAC_CARBON_PLUGINS
|
||||
// start the idle timer.
|
||||
StartTimer(true);
|
||||
// start the idle timer.
|
||||
StartTimer(true);
|
||||
#endif
|
||||
|
||||
// tell the plugin window about the widget
|
||||
mPluginWindow->SetPluginWidget(mWidget);
|
||||
|
||||
// tell the widget about the current plugin instance owner.
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
||||
if (pluginWidget)
|
||||
pluginWidget->SetPluginInstanceOwner(this);
|
||||
}
|
||||
}
|
||||
// tell the plugin window about the widget
|
||||
mPluginWindow->SetPluginWidget(mWidget);
|
||||
|
||||
// tell the widget about the current plugin instance owner.
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
||||
if (pluginWidget) {
|
||||
pluginWidget->SetPluginInstanceOwner(this);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
mWidgetCreationComplete = true;
|
||||
|
||||
void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost* aHost)
|
||||
{
|
||||
mPluginHost = static_cast<nsPluginHost*>(aHost);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Mac specific code to fix up the port location and clipping region
|
||||
|
@ -3505,7 +3463,12 @@ void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
|
|||
mPluginWindow->clipRect.right != oldClipRect.right ||
|
||||
mPluginWindow->clipRect.bottom != oldClipRect.bottom)
|
||||
{
|
||||
CallSetWindow();
|
||||
if (UseAsyncRendering()) {
|
||||
mInstance->AsyncSetWindow(mPluginWindow);
|
||||
}
|
||||
else {
|
||||
mPluginWindow->CallSetWindow(mInstance);
|
||||
}
|
||||
mPluginPortChanged = false;
|
||||
#ifdef MAC_CARBON_PLUGINS
|
||||
// if the clipRect is of size 0, make the null timer fire less often
|
||||
|
@ -3519,7 +3482,12 @@ void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
|
|||
}
|
||||
#endif
|
||||
} else if (mPluginPortChanged) {
|
||||
CallSetWindow();
|
||||
if (UseAsyncRendering()) {
|
||||
mInstance->AsyncSetWindow(mPluginWindow);
|
||||
}
|
||||
else {
|
||||
mPluginWindow->CallSetWindow(mInstance);
|
||||
}
|
||||
mPluginPortChanged = false;
|
||||
}
|
||||
|
||||
|
@ -3561,7 +3529,7 @@ nsPluginInstanceOwner::HidePluginWindow()
|
|||
mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
|
||||
mPluginWindow->clipRect.right = mPluginWindow->clipRect.left;
|
||||
mWidgetVisible = false;
|
||||
if (mAsyncHidePluginWindow) {
|
||||
if (UseAsyncRendering()) {
|
||||
mInstance->AsyncSetWindow(mPluginWindow);
|
||||
} else {
|
||||
mInstance->SetWindow(mPluginWindow);
|
||||
|
@ -3631,19 +3599,98 @@ nsPluginInstanceOwner::UpdateDocumentActiveState(bool aIsActive)
|
|||
}
|
||||
#endif // XP_MACOSX
|
||||
|
||||
void
|
||||
NS_IMETHODIMP
|
||||
nsPluginInstanceOwner::CallSetWindow()
|
||||
{
|
||||
if (!mInstance)
|
||||
return;
|
||||
|
||||
if (UseAsyncRendering()) {
|
||||
mAsyncHidePluginWindow = true;
|
||||
mInstance->AsyncSetWindow(mPluginWindow);
|
||||
} else {
|
||||
mAsyncHidePluginWindow = false;
|
||||
mInstance->SetWindow(mPluginWindow);
|
||||
if (mObjectFrame) {
|
||||
mObjectFrame->CallSetWindow(false);
|
||||
} else if (mInstance) {
|
||||
if (UseAsyncRendering()) {
|
||||
mInstance->AsyncSetWindow(mPluginWindow);
|
||||
} else {
|
||||
mInstance->SetWindow(mPluginWindow);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
|
||||
{
|
||||
// Don't do anything if the frame situation hasn't changed.
|
||||
if (mObjectFrame == aFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Deal with things that depend on whether or not we used to have a frame.
|
||||
if (mObjectFrame) {
|
||||
// We have an old frame.
|
||||
// Drop image reference because the child may destroy the surface after we return.
|
||||
nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
|
||||
if (container) {
|
||||
#ifdef XP_MACOSX
|
||||
nsRefPtr<Image> image = container->GetCurrentImage();
|
||||
if (image && (image->GetFormat() == Image::MAC_IO_SURFACE) && mObjectFrame) {
|
||||
// Undo what we did to the current image in SetCurrentImage().
|
||||
MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image.get());
|
||||
oglImage->SetUpdateCallback(nsnull, nsnull);
|
||||
oglImage->SetDestroyCallback(nsnull);
|
||||
// If we have a current image here, its destructor hasn't yet been
|
||||
// called, so OnDestroyImage() can't yet have been called. So we need
|
||||
// to do ourselves what OnDestroyImage() would have done.
|
||||
NS_RELEASE_THIS();
|
||||
}
|
||||
#endif
|
||||
container->SetCurrentImage(nsnull);
|
||||
}
|
||||
|
||||
// If we had an old frame and we're not going to have a new one then
|
||||
// we should unregister for some things.
|
||||
if (!aFrame) {
|
||||
// Unregister scroll position listeners
|
||||
for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(f);
|
||||
if (sf) {
|
||||
sf->RemoveScrollPositionListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the old frame isn't holding a reference to us.
|
||||
mObjectFrame->SetInstanceOwner(nsnull);
|
||||
} else {
|
||||
if (aFrame) {
|
||||
// We didn't have an object frame before but we do now!
|
||||
// We need to register a scroll position listener on every scrollable
|
||||
// frame up to the top
|
||||
for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(f);
|
||||
if (sf) {
|
||||
sf->AddScrollPositionListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Swap in the new frame (or no frame)
|
||||
mObjectFrame = aFrame;
|
||||
|
||||
// Set up a new frame
|
||||
if (mObjectFrame) {
|
||||
mObjectFrame->SetInstanceOwner(this);
|
||||
// Can only call PrepForDrawing on an object frame once. Don't do it here unless
|
||||
// widget creation is complete. Doesn't matter if we actually have a widget.
|
||||
if (mWidgetCreationComplete) {
|
||||
mObjectFrame->PrepForDrawing(mWidget);
|
||||
}
|
||||
mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
|
||||
mObjectFrame->Invalidate(mObjectFrame->GetContentRectRelativeToSelf());
|
||||
}
|
||||
}
|
||||
|
||||
nsObjectFrame* nsPluginInstanceOwner::GetFrame()
|
||||
{
|
||||
return mObjectFrame;
|
||||
}
|
||||
|
||||
// Little helper function to resolve relative URL in
|
||||
|
|
|
@ -135,9 +135,7 @@ public:
|
|||
#endif
|
||||
|
||||
nsresult Destroy();
|
||||
|
||||
void PrepareToStop(bool aDelayedStop);
|
||||
|
||||
|
||||
#ifdef XP_WIN
|
||||
void Paint(const RECT& aDirty, HDC aDC);
|
||||
#elif defined(XP_MACOSX)
|
||||
|
@ -164,14 +162,11 @@ public:
|
|||
|
||||
//locals
|
||||
|
||||
nsresult Init(nsPresContext* aPresContext, nsObjectFrame* aFrame,
|
||||
nsIContent* aContent);
|
||||
nsresult Init(nsIContent* aContent);
|
||||
|
||||
void* GetPluginPortFromWidget();
|
||||
void ReleasePluginPort(void* pluginPort);
|
||||
|
||||
void SetPluginHost(nsIPluginHost* aHost);
|
||||
|
||||
|
||||
nsEventStatus ProcessEvent(const nsGUIEvent & anEvent);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
@ -210,16 +205,10 @@ public:
|
|||
void UpdateWindowVisibility(bool aVisible);
|
||||
void UpdateDocumentActiveState(bool aIsActive);
|
||||
#endif // XP_MACOSX
|
||||
void CallSetWindow();
|
||||
|
||||
void SetOwner(nsObjectFrame *aOwner)
|
||||
{
|
||||
mObjectFrame = aOwner;
|
||||
}
|
||||
nsObjectFrame* GetOwner() {
|
||||
return mObjectFrame;
|
||||
}
|
||||
|
||||
|
||||
void SetFrame(nsObjectFrame *aFrame);
|
||||
nsObjectFrame* GetFrame();
|
||||
|
||||
PRUint32 GetLastEventloopNestingLevel() const {
|
||||
return mLastEventloopNestingLevel;
|
||||
}
|
||||
|
@ -318,10 +307,11 @@ private:
|
|||
|
||||
nsPluginNativeWindow *mPluginWindow;
|
||||
nsRefPtr<nsNPAPIPluginInstance> mInstance;
|
||||
nsObjectFrame *mObjectFrame; // owns nsPluginInstanceOwner
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsObjectFrame *mObjectFrame;
|
||||
nsIContent *mContent; // WEAK, content owns us
|
||||
nsCString mDocumentBase;
|
||||
char *mTagText;
|
||||
bool mWidgetCreationComplete;
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
nsRefPtr<nsPluginHost> mPluginHost;
|
||||
|
||||
|
@ -357,10 +347,7 @@ private:
|
|||
#endif
|
||||
bool mPluginWindowVisible;
|
||||
bool mPluginDocumentActiveState;
|
||||
|
||||
// If true, destroy the widget on destruction. Used when plugin stop
|
||||
// is being delayed to a safer point in time.
|
||||
bool mDestroyWidget;
|
||||
|
||||
PRUint16 mNumCachedAttrs;
|
||||
PRUint16 mNumCachedParams;
|
||||
char **mCachedAttrParamNames;
|
||||
|
@ -368,6 +355,11 @@ private:
|
|||
|
||||
#ifdef XP_MACOSX
|
||||
NPEventModel mEventModel;
|
||||
// This is a hack! UseAsyncRendering() can incorrectly return false
|
||||
// when we don't have an object frame (possible as of bug 90268).
|
||||
// We hack around this by always returning true if we've ever
|
||||
// returned true.
|
||||
bool mUseAsyncRendering;
|
||||
#endif
|
||||
|
||||
// pointer to wrapper for nsIDOMContextMenuListener
|
||||
|
|
|
@ -386,7 +386,7 @@ nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL,
|
|||
*/
|
||||
nsresult nsPluginStreamListenerPeer::InitializeEmbedded(nsIURI *aURL,
|
||||
nsNPAPIPluginInstance* aInstance,
|
||||
nsIPluginInstanceOwner *aOwner)
|
||||
nsObjectLoadingContent *aContent)
|
||||
{
|
||||
#ifdef PLUGIN_LOGGING
|
||||
nsCAutoString urlSpec;
|
||||
|
@ -404,7 +404,7 @@ nsresult nsPluginStreamListenerPeer::InitializeEmbedded(nsIURI *aURL,
|
|||
NS_ASSERTION(mPluginInstance == nsnull, "nsPluginStreamListenerPeer::InitializeEmbedded mPluginInstance != nsnull");
|
||||
mPluginInstance = aInstance;
|
||||
} else {
|
||||
mOwner = aOwner;
|
||||
mContent = aContent;
|
||||
}
|
||||
|
||||
mPendingRequests = 1;
|
||||
|
@ -577,17 +577,6 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
|
|||
}
|
||||
}
|
||||
|
||||
// do a little sanity check to make sure our frame isn't gone
|
||||
// by getting the tag type and checking for an error, we can determine if
|
||||
// the frame is gone
|
||||
if (mOwner) {
|
||||
nsCOMPtr<nsIPluginTagInfo> pti = do_QueryInterface(mOwner);
|
||||
NS_ENSURE_TRUE(pti, NS_ERROR_FAILURE);
|
||||
nsPluginTagType tagType;
|
||||
if (NS_FAILED(pti->GetTagType(&tagType)))
|
||||
return NS_ERROR_FAILURE; // something happened to our object frame, so bail!
|
||||
}
|
||||
|
||||
// Get the notification callbacks from the channel and save it as
|
||||
// week ref we'll use it in nsPluginStreamInfo::RequestRead() when
|
||||
// we'll create channel for byte range request.
|
||||
|
@ -642,37 +631,21 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
|
|||
|
||||
PR_LogFlush();
|
||||
#endif
|
||||
|
||||
NPWindow* window = nsnull;
|
||||
|
||||
// if we don't have an nsNPAPIPluginInstance (mPluginInstance), it means
|
||||
// we weren't able to load a plugin previously because we
|
||||
// didn't have the mimetype. Now that we do (aContentType),
|
||||
// we'll try again with SetUpPluginInstance()
|
||||
// which is called by InstantiateEmbeddedPlugin()
|
||||
// NOTE: we don't want to try again if we didn't get the MIME type this time
|
||||
|
||||
if (!mPluginInstance && mOwner && !aContentType.IsEmpty()) {
|
||||
nsRefPtr<nsNPAPIPluginInstance> pluginInstRefPtr;
|
||||
mOwner->GetInstance(getter_AddRefs(pluginInstRefPtr));
|
||||
mPluginInstance = pluginInstRefPtr.get();
|
||||
|
||||
mOwner->GetWindow(window);
|
||||
if (!mPluginInstance && window) {
|
||||
nsRefPtr<nsPluginHost> pluginHost = dont_AddRef(nsPluginHost::GetInst());
|
||||
rv = pluginHost->SetUpPluginInstance(aContentType.get(), aURL, mOwner);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mOwner->GetInstance(getter_AddRefs(pluginInstRefPtr));
|
||||
mPluginInstance = pluginInstRefPtr.get();
|
||||
if (mPluginInstance) {
|
||||
mOwner->CreateWidget();
|
||||
// If we've got a native window, the let the plugin know about it.
|
||||
mOwner->SetWindow();
|
||||
}
|
||||
// If we don't have an instance yet it means we weren't able to load
|
||||
// a plugin previously because we didn't have the mimetype. Try again
|
||||
// if we have a mime type now.
|
||||
if (!mPluginInstance && mContent && !aContentType.IsEmpty()) {
|
||||
nsObjectLoadingContent *olc = static_cast<nsObjectLoadingContent*>(mContent.get());
|
||||
rv = olc->InstantiatePluginInstance(aContentType.get(), aURL.get());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = olc->GetPluginInstance(getter_AddRefs(mPluginInstance));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set up the stream listener...
|
||||
rv = SetUpStreamListener(request, aURL);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -869,7 +842,7 @@ nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request,
|
|||
window->window = widget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
|
||||
}
|
||||
#endif
|
||||
owner->SetWindow();
|
||||
owner->CallSetWindow();
|
||||
}
|
||||
|
||||
mSeekable = false;
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
|
||||
class nsIChannel;
|
||||
|
||||
|
@ -113,7 +114,7 @@ public:
|
|||
|
||||
nsresult InitializeEmbedded(nsIURI *aURL,
|
||||
nsNPAPIPluginInstance* aInstance,
|
||||
nsIPluginInstanceOwner *aOwner = nsnull);
|
||||
nsObjectLoadingContent *aContent);
|
||||
|
||||
nsresult InitializeFullPage(nsIURI* aURL, nsNPAPIPluginInstance *aInstance);
|
||||
|
||||
|
@ -130,7 +131,7 @@ private:
|
|||
|
||||
nsCOMPtr<nsIURI> mURL;
|
||||
nsCString mURLSpec; // Have to keep this member because GetURL hands out char*
|
||||
nsCOMPtr<nsIPluginInstanceOwner> mOwner;
|
||||
nsCOMPtr<nsIObjectLoadingContent> mContent;
|
||||
nsRefPtr<nsNPAPIPluginStreamListener> mPStreamListener;
|
||||
|
||||
// Set to true if we request failed (like with a HTTP response of 404)
|
||||
|
|
|
@ -105,6 +105,10 @@ _MOCHITEST_FILES = \
|
|||
test_NPPVpluginWantsAllNetworkStreams.html \
|
||||
test_npruntime_npnsetexception.html \
|
||||
test_NPNVdocumentOrigin.html \
|
||||
test_instance_re-parent.html \
|
||||
test_instance_unparent1.html \
|
||||
test_instance_unparent2.html \
|
||||
test_instance_unparent3.html \
|
||||
$(NULL)
|
||||
|
||||
# test_plugin_scroll_painting.html \ bug 596491
|
||||
|
@ -129,6 +133,7 @@ _MOCHICHROME_FILES = \
|
|||
|
||||
ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
|
||||
_MOCHITEST_FILES += \
|
||||
test_instance_re-parent-windowed.html \
|
||||
test_visibility.html \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test re-parentinging an instance's DOM node</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="startTest()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="div1">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200" wmode="window"></embed>
|
||||
</div>
|
||||
<div id="div2">
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var destroyed = false;
|
||||
function onDestroy() {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
var exceptionThrown = false;
|
||||
|
||||
var p = document.getElementById('plugin1');
|
||||
var d1 = document.getElementById('div1');
|
||||
var d2 = document.getElementById('div2');
|
||||
|
||||
p.startWatchingInstanceCount();
|
||||
p.callOnDestroy(onDestroy);
|
||||
|
||||
try {
|
||||
d1.removeChild(p);
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
is(exceptionThrown, false, "Testing for exception after removeChild.");
|
||||
|
||||
try {
|
||||
d2.appendChild(p);
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
is(exceptionThrown, false, "Testing for exception after appendChild.");
|
||||
|
||||
is(destroyed, false, "No instances should have been destroyed at this point.");
|
||||
is(p.getInstanceCount(), 0, "No new instances should have been created at this point.");
|
||||
|
||||
p.stopWatchingInstanceCount();
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,86 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test re-parentinging an instance's DOM node</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="runTests()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="div1">
|
||||
<!-- This embed has to have a "src" attribute. Part of this test involves seeing if we
|
||||
properly restart plugins that have been added back to a document without a change
|
||||
in URL. Not re-loading an object when the URL hasn't changed is a shortcut used for
|
||||
some object types. Without a URL, this won't be tested. -->
|
||||
<embed id="plugin1" src="loremipsum.txt" type="application/x-test" width="200" height="200"></embed>
|
||||
</div>
|
||||
<div id="div2">
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var exceptionThrown = false;
|
||||
var p = document.getElementById('plugin1');
|
||||
var d1 = document.getElementById('div1');
|
||||
var d2 = document.getElementById('div2');
|
||||
|
||||
var destroyed = false;
|
||||
function onDestroy() {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
function testsFinished() {
|
||||
p.stopWatchingInstanceCount();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function continueTests2() {
|
||||
try {
|
||||
is(p.getInstanceCount(), 1, "One new instance should have been created at this point.");
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
is(exceptionThrown, false, "Testing for exception getting instance count from plugin.");
|
||||
|
||||
testsFinished();
|
||||
}
|
||||
|
||||
function continueTests1() {
|
||||
// Adding to the document will kick off the plugin load. Need to have a timeout
|
||||
// before we can safely call into it.
|
||||
d2.appendChild(p);
|
||||
setTimeout('continueTests2();', 0);
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
// First tests involve moving the instance from one div to another.
|
||||
p.startWatchingInstanceCount();
|
||||
p.callOnDestroy(onDestroy);
|
||||
|
||||
try {
|
||||
d1.removeChild(p);
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
is(exceptionThrown, false, "Testing for exception after removeChild.");
|
||||
|
||||
try {
|
||||
d2.appendChild(p);
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
is(exceptionThrown, false, "Testing for exception after appendChild.");
|
||||
|
||||
is(destroyed, false, "No instances should have been destroyed at this point.");
|
||||
is(p.getInstanceCount(), 0, "No new instances should have been created at this point.");
|
||||
|
||||
// Now remove the instance from the document and let it die.
|
||||
d2.removeChild(p);
|
||||
setTimeout('continueTests1();', 0);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test removing an instance's DOM node</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="startTest()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="div1">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var destroyed = false;
|
||||
function onDestroy() {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
function checkPluginAlreadyDestroyed() {
|
||||
is(destroyed, true, "Plugin instance should have been destroyed.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
var p1 = document.getElementById('plugin1');
|
||||
var d1 = document.getElementById('div1');
|
||||
|
||||
p1.callOnDestroy(onDestroy);
|
||||
|
||||
setTimeout(checkPluginAlreadyDestroyed, 0);
|
||||
|
||||
d1.removeChild(p1);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test removing an instance's DOM node</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="startTest()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="div1">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
|
||||
</div>
|
||||
|
||||
<div id="div2">
|
||||
<div id="div3">
|
||||
<embed id="plugin2" type="application/x-test" width="200" height="200"></embed>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var destroyed = false;
|
||||
function onDestroy() {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
function checkPluginAlreadyDestroyed() {
|
||||
is(destroyed, true, "Plugin instance should have been destroyed.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
var p1 = document.getElementById('plugin1');
|
||||
var d1 = document.getElementById('div1');
|
||||
|
||||
p1.callOnDestroy(onDestroy);
|
||||
|
||||
setTimeout(checkPluginAlreadyDestroyed, 0);
|
||||
|
||||
// Get two parent check events to run.
|
||||
d1.removeChild(p1);
|
||||
d1.appendChild(p1);
|
||||
d1.removeChild(p1);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test removing an instance's DOM node</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="startTest()">
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="div1">
|
||||
<div id="div2">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
|
||||
</div<
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var destroyed = false;
|
||||
function onDestroy() {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
function checkPluginAlreadyDestroyed() {
|
||||
is(destroyed, true, "Plugin instance should have been destroyed.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
var p1 = document.getElementById('plugin1');
|
||||
var d1 = document.getElementById('div1');
|
||||
var d2 = document.getElementById('div2');
|
||||
|
||||
p1.callOnDestroy(onDestroy);
|
||||
|
||||
setTimeout(checkPluginAlreadyDestroyed, 0);
|
||||
|
||||
d1.removeChild(d2);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -7,8 +7,9 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) =
|
|||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-1.html border-padding-1-ref.html # bug 629430
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-2.html border-padding-2-ref.html # bug 629430
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) skip-if(Android) == border-padding-3.html border-padding-3-ref.html # bug 629430
|
||||
random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html # bug 567367
|
||||
random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html
|
||||
# The following two "pluginproblemui-direction" tests are unreliable on all platforms. They should be re-written or replaced.
|
||||
#random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html # bug 567367
|
||||
#random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html
|
||||
fails-if(!haveTestPlugin) == plugin-canvas-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) == plugin-transform-alpha-zindex.html div-alpha-zindex.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-busy-alpha-zindex.html div-alpha-zindex.html
|
||||
|
|
|
@ -7277,10 +7277,9 @@ PresShell::RemoveOverrideStyleSheet(nsIStyleSheet *aSheet)
|
|||
static void
|
||||
FreezeElement(nsIContent *aContent, void * /* unused */)
|
||||
{
|
||||
nsIFrame *frame = aContent->GetPrimaryFrame();
|
||||
nsIObjectFrame *objectFrame = do_QueryFrame(frame);
|
||||
if (objectFrame) {
|
||||
objectFrame->StopPlugin();
|
||||
nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(aContent));
|
||||
if (olc) {
|
||||
olc->StopPluginInstance();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7358,10 +7357,9 @@ PresShell::FireOrClearDelayedEvents(bool aFireEvents)
|
|||
static void
|
||||
ThawElement(nsIContent *aContent, void *aShell)
|
||||
{
|
||||
nsCOMPtr<nsIObjectLoadingContent> objlc(do_QueryInterface(aContent));
|
||||
if (objlc) {
|
||||
nsRefPtr<nsNPAPIPluginInstance> inst;
|
||||
objlc->EnsureInstantiation(getter_AddRefs(inst));
|
||||
nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(aContent));
|
||||
if (olc) {
|
||||
olc->AsyncStartPluginInstance();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,42 +54,6 @@ public:
|
|||
|
||||
NS_IMETHOD GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance) = 0;
|
||||
|
||||
/**
|
||||
* Instantiate a plugin for a channel, returning a stream listener for the
|
||||
* data.
|
||||
*
|
||||
* @note Calling this method can delete the frame, so don't assume
|
||||
* the frame is alive after this call returns.
|
||||
*/
|
||||
virtual nsresult Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamListener) = 0;
|
||||
|
||||
/**
|
||||
* @note Calling this method can delete the frame, so don't assume
|
||||
* the frame is alive after this call returns.
|
||||
*/
|
||||
virtual void TryNotifyContentObjectWrapper() = 0;
|
||||
|
||||
/**
|
||||
* Instantiate a plugin that loads the data itself.
|
||||
* @param aMimeType Type of the plugin to instantiate. May be null.
|
||||
* @param aURI URI of the plugin data. May be null.
|
||||
* @note Only one of aURI and aMimeType may be null.
|
||||
* If aURI is null, aMimeType must not be the empty string.
|
||||
* @note XXX this method is here only temporarily, until plugins are loaded
|
||||
* from content.
|
||||
*
|
||||
* @note Calling this method can delete the frame, so don't assume
|
||||
* the frame is alive after this call returns.
|
||||
*/
|
||||
virtual nsresult Instantiate(const char* aMimeType, nsIURI* aURI) = 0;
|
||||
|
||||
/**
|
||||
* Stops and unloads the plugin. Makes the frame ready to receive another
|
||||
* Instantiate() call. It is safe to call this method even when no plugin
|
||||
* is currently active in this frame.
|
||||
*/
|
||||
virtual void StopPlugin() = 0;
|
||||
|
||||
/**
|
||||
* Get the native widget for the plugin, if any.
|
||||
*/
|
||||
|
|
|
@ -323,17 +323,11 @@ NS_IMETHODIMP nsObjectFrame::GetPluginPort(HWND *aPort)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectFrame::Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* aPrevInFlow)
|
||||
{
|
||||
NS_PRECONDITION(aContent, "How did that happen?");
|
||||
mPreventInstantiation =
|
||||
(aContent->GetCurrentDoc()->GetDisplayDocument() != nsnull);
|
||||
|
||||
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
||||
("Initializing nsObjectFrame %p for content %p\n", this, aContent));
|
||||
|
||||
|
@ -345,25 +339,17 @@ nsObjectFrame::Init(nsIContent* aContent,
|
|||
void
|
||||
nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
||||
{
|
||||
NS_ASSERTION(!mPreventInstantiation ||
|
||||
(mContent && mContent->GetCurrentDoc()->GetDisplayDocument()),
|
||||
"about to crash due to bug 136927");
|
||||
|
||||
// we need to finish with the plugin before native window is destroyed
|
||||
// doing this in the destructor is too late.
|
||||
StopPluginInternal(true);
|
||||
|
||||
// StopPluginInternal might have disowned the widget; if it has,
|
||||
// mWidget will be null.
|
||||
if (mWidget) {
|
||||
mInnerView->DetachWidgetEventHandler(mWidget);
|
||||
mWidget->Destroy();
|
||||
}
|
||||
// Tell content owner of the instance to disconnect its frame.
|
||||
nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
|
||||
NS_ASSERTION(objContent, "Why not an object loading content?");
|
||||
objContent->DisconnectFrame();
|
||||
|
||||
if (mBackgroundSink) {
|
||||
mBackgroundSink->Destroy();
|
||||
}
|
||||
|
||||
SetInstanceOwner(nsnull);
|
||||
|
||||
nsObjectFrameSuper::DestroyFrom(aDestructRoot);
|
||||
}
|
||||
|
||||
|
@ -398,20 +384,14 @@ nsObjectFrame::GetFrameName(nsAString& aResult) const
|
|||
#endif
|
||||
|
||||
nsresult
|
||||
nsObjectFrame::CreateWidget(nscoord aWidth,
|
||||
nscoord aHeight,
|
||||
bool aViewOnly)
|
||||
nsObjectFrame::PrepForDrawing(nsIWidget *aWidget)
|
||||
{
|
||||
mWidget = aWidget;
|
||||
|
||||
nsIView* view = GetView();
|
||||
NS_ASSERTION(view, "Object frames must have views");
|
||||
if (!view) {
|
||||
return NS_OK; //XXX why OK? MMP
|
||||
}
|
||||
|
||||
bool needsWidget = !aViewOnly;
|
||||
bool canCreateWidget = !nsIWidget::UsePuppetWidgets();
|
||||
if (needsWidget && !canCreateWidget) {
|
||||
NS_WARNING("Can't use native widgets, and can't hand a plugins a PuppetWidget");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
|
@ -419,9 +399,6 @@ nsObjectFrame::CreateWidget(nscoord aWidth,
|
|||
// XXX is the above comment correct?
|
||||
viewMan->SetViewVisibility(view, nsViewVisibility_kHide);
|
||||
|
||||
nsRefPtr<nsDeviceContext> dx;
|
||||
viewMan->GetDeviceContext(*getter_AddRefs(dx));
|
||||
|
||||
//this is ugly. it was ripped off from didreflow(). MMP
|
||||
// Position and size view relative to its parent, not relative to our
|
||||
// parent frame (our parent frame may not have a view).
|
||||
|
@ -439,12 +416,12 @@ nsObjectFrame::CreateWidget(nscoord aWidth,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (needsWidget && !mWidget && canCreateWidget) {
|
||||
if (mWidget) {
|
||||
// XXX this breaks plugins in popups ... do we care?
|
||||
nsIWidget* parentWidget =
|
||||
rpc->PresShell()->FrameManager()->GetRootFrame()->GetNearestWidget();
|
||||
if (!parentWidget)
|
||||
nsIWidget* parentWidget = rpc->PresShell()->FrameManager()->GetRootFrame()->GetNearestWidget();
|
||||
if (!parentWidget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mInnerView = viewMan->CreateView(GetContentRectRelativeToSelf(), view);
|
||||
if (!mInnerView) {
|
||||
|
@ -453,48 +430,37 @@ nsObjectFrame::CreateWidget(nscoord aWidth,
|
|||
}
|
||||
viewMan->InsertChild(view, mInnerView, nsnull, true);
|
||||
|
||||
nsresult rv;
|
||||
mWidget = do_CreateInstance(kWidgetCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
mWidget->SetParent(parentWidget);
|
||||
mWidget->Show(true);
|
||||
mWidget->Enable(true);
|
||||
|
||||
nsWidgetInitData initData;
|
||||
initData.mWindowType = eWindowType_plugin;
|
||||
initData.mUnicode = false;
|
||||
initData.clipChildren = true;
|
||||
initData.clipSiblings = true;
|
||||
// We want mWidget to be able to deliver events to us, especially on
|
||||
// Mac where events to the plugin are routed through Gecko. So we
|
||||
// allow the view to attach its event handler to mWidget even though
|
||||
// mWidget isn't the view's designated widget.
|
||||
// Set the plugin window to have an empty cliprect. The cliprect
|
||||
// will be reset when nsRootPresContext::UpdatePluginGeometry
|
||||
// runs later. The plugin window does need to have the correct
|
||||
// size here. GetEmptyClipConfiguration will probably give it the
|
||||
// size, but just in case we haven't been reflowed or something, set
|
||||
// the size explicitly.
|
||||
nsAutoTArray<nsIWidget::Configuration,1> configuration;
|
||||
GetEmptyClipConfiguration(&configuration);
|
||||
NS_ASSERTION(configuration.Length() > 0, "Empty widget configuration array!");
|
||||
configuration[0].mBounds.width = mRect.width;
|
||||
configuration[0].mBounds.height = mRect.height;
|
||||
parentWidget->ConfigureChildren(configuration);
|
||||
|
||||
nsRefPtr<nsDeviceContext> dx;
|
||||
viewMan->GetDeviceContext(*getter_AddRefs(dx));
|
||||
EVENT_CALLBACK eventHandler = mInnerView->AttachWidgetEventHandler(mWidget);
|
||||
rv = mWidget->Create(parentWidget, nsnull, nsIntRect(0,0,0,0),
|
||||
eventHandler, dx, &initData);
|
||||
if (NS_FAILED(rv)) {
|
||||
mWidget->Destroy();
|
||||
mWidget = nsnull;
|
||||
return rv;
|
||||
}
|
||||
mWidget->SetEventCallback(eventHandler, dx);
|
||||
|
||||
mWidget->EnableDragDrop(true);
|
||||
|
||||
// If this frame has an ancestor with a widget which is not
|
||||
// the root prescontext's widget, then this plugin should not be
|
||||
// displayed, so don't show the widget. If we show the widget, the
|
||||
// plugin may appear in the main window. In Web content this would
|
||||
// only happen with a plugin in a XUL popup.
|
||||
if (parentWidget == GetNearestWidget()) {
|
||||
mWidget->Show(true);
|
||||
#ifdef XP_MACOSX
|
||||
// On Mac, we need to invalidate ourselves since even windowed
|
||||
// plugins are painted through Thebes and we need to ensure
|
||||
// the Thebes layer containing the plugin is updated.
|
||||
// On Mac, we need to invalidate ourselves since even windowed
|
||||
// plugins are painted through Thebes and we need to ensure
|
||||
// the Thebes layer containing the plugin is updated.
|
||||
if (parentWidget == GetNearestWidget()) {
|
||||
Invalidate(GetContentRectRelativeToSelf());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mWidget) {
|
||||
rpc->RegisterPluginForGeometryUpdates(this);
|
||||
rpc->RequestUpdatePluginGeometry(this);
|
||||
|
||||
|
@ -525,6 +491,9 @@ nsObjectFrame::CreateWidget(nscoord aWidth,
|
|||
}
|
||||
#endif
|
||||
} else {
|
||||
// Changing to windowless mode changes the NPWindow geometry.
|
||||
FixupWindow(GetContentRectRelativeToSelf().Size());
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
rpc->RegisterPluginForGeometryUpdates(this);
|
||||
rpc->RequestUpdatePluginGeometry(this);
|
||||
|
@ -535,7 +504,14 @@ nsObjectFrame::CreateWidget(nscoord aWidth,
|
|||
viewMan->SetViewVisibility(view, nsViewVisibility_kShow);
|
||||
}
|
||||
|
||||
return (needsWidget && !canCreateWidget) ? NS_ERROR_NOT_AVAILABLE : NS_OK;
|
||||
#ifdef ACCESSIBILITY
|
||||
nsAccessibilityService* accService = nsIPresShell::AccService();
|
||||
if (accService) {
|
||||
accService->RecreateAccessible(PresContext()->PresShell(), mContent);
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#define EMBED_DEF_WIDTH 240
|
||||
|
@ -694,51 +670,6 @@ nsObjectFrame::ReflowCallbackCanceled()
|
|||
mReflowCallbackPosted = false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsObjectFrame::InstantiatePlugin(nsPluginHost* aPluginHost,
|
||||
const char* aMimeType,
|
||||
nsIURI* aURI)
|
||||
{
|
||||
SAMPLE_LABEL("nsObjectFrame", "InstantiatePlugin");
|
||||
NS_ASSERTION(mPreventInstantiation,
|
||||
"Instantiation should be prevented here!");
|
||||
|
||||
// If you add early return(s), be sure to balance this call to
|
||||
// appShell->SuspendNative() with additional call(s) to
|
||||
// appShell->ReturnNative().
|
||||
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
||||
if (appShell) {
|
||||
appShell->SuspendNative();
|
||||
}
|
||||
|
||||
NS_ASSERTION(mContent, "We should have a content node.");
|
||||
|
||||
nsIDocument* doc = mContent->OwnerDoc();
|
||||
nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(doc));
|
||||
bool fullPageMode = false;
|
||||
if (pDoc) {
|
||||
pDoc->GetWillHandleInstantiation(&fullPageMode);
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
if (fullPageMode) { /* full-page mode */
|
||||
nsCOMPtr<nsIStreamListener> stream;
|
||||
rv = aPluginHost->InstantiateFullPagePlugin(aMimeType, aURI, mInstanceOwner, getter_AddRefs(stream));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
pDoc->SetStreamListener(stream);
|
||||
} else { /* embedded mode */
|
||||
rv = aPluginHost->InstantiateEmbeddedPlugin(aMimeType, aURI, mInstanceOwner);
|
||||
}
|
||||
|
||||
// Note that |this| may very well be destroyed already!
|
||||
|
||||
if (appShell) {
|
||||
appShell->ResumeNative();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectFrame::FixupWindow(const nsSize& aSize)
|
||||
{
|
||||
|
@ -848,6 +779,40 @@ nsObjectFrame::CallSetWindow(bool aCheckIsHidden)
|
|||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectFrame::SetInstanceOwner(nsPluginInstanceOwner* aOwner)
|
||||
{
|
||||
mInstanceOwner = aOwner;
|
||||
if (!mInstanceOwner) {
|
||||
nsRootPresContext* rpc = PresContext()->GetRootPresContext();
|
||||
if (rpc) {
|
||||
if (mWidget) {
|
||||
if (mInnerView) {
|
||||
mInnerView->DetachWidgetEventHandler(mWidget);
|
||||
}
|
||||
|
||||
rpc->UnregisterPluginForGeometryUpdates(this);
|
||||
// Make sure the plugin is hidden in case an update of plugin geometry
|
||||
// hasn't happened since this plugin became hidden.
|
||||
nsIWidget* parent = mWidget->GetParent();
|
||||
if (parent) {
|
||||
nsTArray<nsIWidget::Configuration> configurations;
|
||||
this->GetEmptyClipConfiguration(&configurations);
|
||||
parent->ConfigureChildren(configurations);
|
||||
|
||||
mWidget->Show(false);
|
||||
mWidget->Enable(false);
|
||||
mWidget->SetParent(nsnull);
|
||||
}
|
||||
} else {
|
||||
#ifndef XP_MACOSX
|
||||
rpc->UnregisterPluginForGeometryUpdates(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsObjectFrame::IsFocusable(PRInt32 *aTabIndex, bool aWithMouse)
|
||||
{
|
||||
|
@ -2130,404 +2095,11 @@ nsObjectFrame::GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance)
|
|||
{
|
||||
*aPluginInstance = nsnull;
|
||||
|
||||
if (!mInstanceOwner)
|
||||
return NS_OK;
|
||||
|
||||
return mInstanceOwner->GetInstance(aPluginInstance);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsObjectFrame::PrepareInstanceOwner()
|
||||
{
|
||||
nsWeakFrame weakFrame(this);
|
||||
|
||||
// First, have to stop any possibly running plugins.
|
||||
StopPluginInternal(false);
|
||||
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mInstanceOwner, "Must not have an instance owner here");
|
||||
|
||||
mInstanceOwner = new nsPluginInstanceOwner();
|
||||
|
||||
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
||||
("Created new instance owner %p for frame %p\n", mInstanceOwner.get(),
|
||||
this));
|
||||
|
||||
// Note, |this| may very well be gone after this call.
|
||||
return mInstanceOwner->Init(PresContext(), this, GetContent());
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsObjectFrame::Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamListener)
|
||||
{
|
||||
SAMPLE_LABEL("plugin", "nsObjectFrame::Instantiate");
|
||||
if (mPreventInstantiation) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Note: If PrepareInstanceOwner() returns an error, |this| may very
|
||||
// well be deleted already.
|
||||
nsresult rv = PrepareInstanceOwner();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &rv));
|
||||
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mInstanceOwner->SetPluginHost(pluginHostCOM);
|
||||
|
||||
// This must be done before instantiating the plugin
|
||||
FixupWindow(GetContentRectRelativeToSelf().Size());
|
||||
|
||||
// Ensure we redraw when a plugin is instantiated
|
||||
Invalidate(GetContentRectRelativeToSelf());
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
|
||||
NS_ASSERTION(!mPreventInstantiation, "Say what?");
|
||||
mPreventInstantiation = true;
|
||||
rv = pluginHost->InstantiatePluginForChannel(aChannel, mInstanceOwner, aStreamListener);
|
||||
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mPreventInstantiation,
|
||||
"Instantiation should still be prevented!");
|
||||
mPreventInstantiation = false;
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
nsAccessibilityService* accService = nsIPresShell::AccService();
|
||||
if (accService) {
|
||||
accService->RecreateAccessible(PresContext()->PresShell(), mContent);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsObjectFrame::Instantiate(const char* aMimeType, nsIURI* aURI)
|
||||
{
|
||||
SAMPLE_LABEL("plugin", "nsObjectFrame::Instantiate");
|
||||
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
||||
("nsObjectFrame::Instantiate(%s) called on frame %p\n", aMimeType,
|
||||
this));
|
||||
|
||||
if (mPreventInstantiation) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXXbz can aMimeType ever actually be null here? If not, either
|
||||
// the callers are wrong (and passing "" instead of null) or we can
|
||||
// remove the codepaths dealing with null aMimeType in
|
||||
// InstantiateEmbeddedPlugin.
|
||||
NS_ASSERTION(aMimeType || aURI, "Need a type or a URI!");
|
||||
|
||||
// Note: If PrepareInstanceOwner() returns an error, |this| may very
|
||||
// well be deleted already.
|
||||
nsresult rv = PrepareInstanceOwner();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
|
||||
// This must be done before instantiating the plugin
|
||||
FixupWindow(GetContentRectRelativeToSelf().Size());
|
||||
|
||||
// Ensure we redraw when a plugin is instantiated
|
||||
Invalidate(GetContentRectRelativeToSelf());
|
||||
|
||||
// get the nsIPluginHost service
|
||||
nsCOMPtr<nsIPluginHost> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
mInstanceOwner->SetPluginHost(pluginHost);
|
||||
|
||||
NS_ASSERTION(!mPreventInstantiation, "Say what?");
|
||||
mPreventInstantiation = true;
|
||||
|
||||
rv = InstantiatePlugin(static_cast<nsPluginHost*>(pluginHost.get()), aMimeType, aURI);
|
||||
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// finish up
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
TryNotifyContentObjectWrapper();
|
||||
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
CallSetWindow();
|
||||
}
|
||||
|
||||
NS_ASSERTION(mPreventInstantiation,
|
||||
"Instantiation should still be prevented!");
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
nsAccessibilityService* accService = nsIPresShell::AccService();
|
||||
if (accService) {
|
||||
accService->RecreateAccessible(PresContext()->PresShell(), mContent);
|
||||
}
|
||||
#endif
|
||||
|
||||
mPreventInstantiation = false;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectFrame::TryNotifyContentObjectWrapper()
|
||||
{
|
||||
nsRefPtr<nsNPAPIPluginInstance> inst;
|
||||
mInstanceOwner->GetInstance(getter_AddRefs(inst));
|
||||
if (inst) {
|
||||
// The plugin may have set up new interfaces; we need to mess with our JS
|
||||
// wrapper. Note that we DO NOT want to call this if there is no plugin
|
||||
// instance! That would just reenter Instantiate(), trying to create
|
||||
// said plugin instance.
|
||||
NotifyContentObjectWrapper();
|
||||
}
|
||||
}
|
||||
|
||||
class nsStopPluginRunnable : public nsRunnable, public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
nsStopPluginRunnable(nsPluginInstanceOwner *aInstanceOwner)
|
||||
: mInstanceOwner(aInstanceOwner)
|
||||
{
|
||||
NS_ASSERTION(aInstanceOwner, "need an owner");
|
||||
}
|
||||
|
||||
// nsRunnable
|
||||
NS_IMETHOD Run();
|
||||
|
||||
// nsITimerCallback
|
||||
NS_IMETHOD Notify(nsITimer *timer);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsStopPluginRunnable, nsRunnable, nsITimerCallback)
|
||||
|
||||
#if defined(XP_WIN)
|
||||
static const char*
|
||||
GetMIMEType(nsNPAPIPluginInstance *aPluginInstance)
|
||||
{
|
||||
if (aPluginInstance) {
|
||||
const char* mime = nsnull;
|
||||
if (NS_SUCCEEDED(aPluginInstance->GetMIMEType(&mime)) && mime)
|
||||
return mime;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
#endif // XP_WIN
|
||||
|
||||
static bool
|
||||
DoDelayedStop(nsPluginInstanceOwner *aInstanceOwner, bool aDelayedStop)
|
||||
{
|
||||
#if (MOZ_PLATFORM_MAEMO==5)
|
||||
// Don't delay stop on Maemo/Hildon (bug 530739).
|
||||
if (aDelayedStop && aInstanceOwner->MatchPluginName("Shockwave Flash"))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// Don't delay stopping QuickTime (bug 425157), Flip4Mac (bug 426524),
|
||||
// XStandard (bug 430219), CMISS Zinc (bug 429604).
|
||||
if (aDelayedStop
|
||||
#if !(defined XP_WIN || defined MOZ_X11)
|
||||
&& !aInstanceOwner->MatchPluginName("QuickTime")
|
||||
&& !aInstanceOwner->MatchPluginName("Flip4Mac")
|
||||
&& !aInstanceOwner->MatchPluginName("XStandard plugin")
|
||||
&& !aInstanceOwner->MatchPluginName("CMISS Zinc Plugin")
|
||||
#endif
|
||||
) {
|
||||
nsCOMPtr<nsIRunnable> evt = new nsStopPluginRunnable(aInstanceOwner);
|
||||
NS_DispatchToCurrentThread(evt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, bool aDelayedStop)
|
||||
{
|
||||
SAMPLE_LABEL("plugin", "DoStopPlugin");
|
||||
nsRefPtr<nsNPAPIPluginInstance> inst;
|
||||
aInstanceOwner->GetInstance(getter_AddRefs(inst));
|
||||
if (inst) {
|
||||
NPWindow *win;
|
||||
aInstanceOwner->GetWindow(win);
|
||||
nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
|
||||
nsRefPtr<nsNPAPIPluginInstance> nullinst;
|
||||
|
||||
if (window)
|
||||
window->CallSetWindow(nullinst);
|
||||
else
|
||||
inst->SetWindow(nsnull);
|
||||
|
||||
if (DoDelayedStop(aInstanceOwner, aDelayedStop))
|
||||
return;
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
aInstanceOwner->HidePluginWindow();
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIPluginHost> pluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
|
||||
NS_ASSERTION(pluginHost, "Without a pluginHost, how can we have an instance to destroy?");
|
||||
static_cast<nsPluginHost*>(pluginHost.get())->StopPluginInstance(inst);
|
||||
|
||||
// the frame is going away along with its widget so tell the
|
||||
// window to forget its widget too
|
||||
if (window)
|
||||
window->SetPluginWidget(nsnull);
|
||||
}
|
||||
|
||||
aInstanceOwner->Destroy();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStopPluginRunnable::Notify(nsITimer *aTimer)
|
||||
{
|
||||
return Run();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStopPluginRunnable::Run()
|
||||
{
|
||||
SAMPLE_LABEL("plugin", "nsStopPluginRunnable::Run");
|
||||
// InitWithCallback calls Release before AddRef so we need to hold a
|
||||
// strong ref on 'this' since we fall through to this scope if it fails.
|
||||
nsCOMPtr<nsITimerCallback> kungFuDeathGrip = this;
|
||||
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
||||
if (appShell) {
|
||||
PRUint32 currentLevel = 0;
|
||||
appShell->GetEventloopNestingLevel(¤tLevel);
|
||||
if (currentLevel > mInstanceOwner->GetLastEventloopNestingLevel()) {
|
||||
if (!mTimer)
|
||||
mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (mTimer) {
|
||||
// Fire 100ms timer to try to tear down this plugin as quickly as
|
||||
// possible once the nesting level comes back down.
|
||||
nsresult rv = mTimer->InitWithCallback(this, 100, nsITimer::TYPE_ONE_SHOT);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
NS_ERROR("Failed to setup a timer to stop the plugin later (at a safe "
|
||||
"time). Stopping the plugin now, this might crash.");
|
||||
}
|
||||
}
|
||||
|
||||
mTimer = nsnull;
|
||||
|
||||
DoStopPlugin(mInstanceOwner, false);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectFrame::StopPlugin()
|
||||
{
|
||||
bool delayedStop = false;
|
||||
#ifdef XP_WIN
|
||||
nsRefPtr<nsNPAPIPluginInstance> inst;
|
||||
if (mInstanceOwner)
|
||||
mInstanceOwner->GetInstance(getter_AddRefs(inst));
|
||||
if (inst) {
|
||||
// Delayed stop for Real plugin only; see bug 420886, 426852.
|
||||
const char* pluginType = ::GetMIMEType(inst);
|
||||
delayedStop = strcmp(pluginType, "audio/x-pn-realaudio-plugin") == 0;
|
||||
}
|
||||
#endif
|
||||
StopPluginInternal(delayedStop);
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectFrame::StopPluginInternal(bool aDelayedStop)
|
||||
{
|
||||
if (!mInstanceOwner) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRootPresContext* rpc = PresContext()->GetRootPresContext();
|
||||
if (!rpc) {
|
||||
NS_ASSERTION(PresContext()->PresShell()->IsFrozen(),
|
||||
"unable to unregister the plugin frame");
|
||||
}
|
||||
else if (mWidget) {
|
||||
rpc->UnregisterPluginForGeometryUpdates(this);
|
||||
|
||||
// Make sure the plugin is hidden in case an update of plugin geometry
|
||||
// hasn't happened since this plugin became hidden.
|
||||
nsIWidget* parent = mWidget->GetParent();
|
||||
if (parent) {
|
||||
nsTArray<nsIWidget::Configuration> configurations;
|
||||
GetEmptyClipConfiguration(&configurations);
|
||||
parent->ConfigureChildren(configurations);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifndef XP_MACOSX
|
||||
rpc->UnregisterPluginForGeometryUpdates(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Transfer the reference to the instance owner onto the stack so
|
||||
// that if we do end up re-entering this code, or if we unwind back
|
||||
// here witha deleted frame (this), we can still continue to stop
|
||||
// the plugin. Note that due to that, the ordering of the code in
|
||||
// this function is extremely important.
|
||||
|
||||
nsRefPtr<nsPluginInstanceOwner> owner;
|
||||
owner.swap(mInstanceOwner);
|
||||
|
||||
// Make sure that our windowless rect has been zeroed out, so if we
|
||||
// get reinstantiated we'll send the right messages to the plug-in.
|
||||
mWindowlessRect.SetEmpty();
|
||||
|
||||
bool oldVal = mPreventInstantiation;
|
||||
mPreventInstantiation = true;
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
|
||||
#if defined(XP_WIN) || defined(MOZ_X11)
|
||||
if (aDelayedStop && mWidget) {
|
||||
// If we're asked to do a delayed stop it means we're stopping the
|
||||
// plugin because we're destroying the frame. In that case, disown
|
||||
// the widget.
|
||||
mInnerView->DetachWidgetEventHandler(mWidget);
|
||||
mWidget = nsnull;
|
||||
}
|
||||
#endif
|
||||
|
||||
// From this point on, |this| could have been deleted, so don't
|
||||
// touch it!
|
||||
owner->PrepareToStop(aDelayedStop);
|
||||
|
||||
DoStopPlugin(owner, aDelayedStop);
|
||||
|
||||
// If |this| is still alive, reset mPreventInstantiation.
|
||||
if (weakFrame.IsAlive()) {
|
||||
NS_ASSERTION(mPreventInstantiation,
|
||||
"Instantiation should still be prevented!");
|
||||
|
||||
mPreventInstantiation = oldVal;
|
||||
}
|
||||
|
||||
// Break relationship between frame and plugin instance owner
|
||||
owner->SetOwner(nsnull);
|
||||
return mInstanceOwner->GetInstance(aPluginInstance);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -2561,43 +2133,6 @@ nsObjectFrame::SetIsDocumentActive(bool aIsActive)
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectFrame::NotifyContentObjectWrapper()
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = mContent->GetDocument();
|
||||
if (!doc)
|
||||
return;
|
||||
|
||||
nsIScriptGlobalObject *sgo = doc->GetScriptGlobalObject();
|
||||
if (!sgo)
|
||||
return;
|
||||
|
||||
nsIScriptContext *scx = sgo->GetContext();
|
||||
if (!scx)
|
||||
return;
|
||||
|
||||
JSContext *cx = scx->GetNativeContext();
|
||||
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
||||
nsContentUtils::XPConnect()->
|
||||
GetWrappedNativeOfNativeObject(cx, sgo->GetGlobalJSObject(), mContent,
|
||||
NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(wrapper));
|
||||
|
||||
if (!wrapper) {
|
||||
// Nothing to do here if there's no wrapper for mContent. The proto
|
||||
// chain will be fixed appropriately when the wrapper is created.
|
||||
return;
|
||||
}
|
||||
|
||||
JSObject *obj = nsnull;
|
||||
nsresult rv = wrapper->GetJSObject(&obj);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
nsHTMLPluginObjElementSH::SetupProtoChain(wrapper, cx, obj);
|
||||
}
|
||||
|
||||
// static
|
||||
nsIObjectFrame *
|
||||
nsObjectFrame::GetNextObjectFrame(nsPresContext* aPresContext, nsIFrame* aRoot)
|
||||
|
|
|
@ -40,10 +40,6 @@
|
|||
#ifndef nsObjectFrame_h___
|
||||
#define nsObjectFrame_h___
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
#include "nsIObjectFrame.h"
|
||||
#include "nsFrame.h"
|
||||
|
@ -124,19 +120,8 @@ public:
|
|||
virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
|
||||
|
||||
NS_METHOD GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance);
|
||||
virtual nsresult Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamListener);
|
||||
virtual nsresult Instantiate(const char* aMimeType, nsIURI* aURI);
|
||||
virtual void TryNotifyContentObjectWrapper();
|
||||
virtual void StopPlugin();
|
||||
virtual void SetIsDocumentActive(bool aIsActive);
|
||||
|
||||
/*
|
||||
* Stop a plugin instance. If aDelayedStop is true, the plugin will
|
||||
* be stopped at a later point when it's safe to do so (i.e. not
|
||||
* while destroying the frame tree). Delayed stopping is only
|
||||
* implemented on Win32 for now.
|
||||
*/
|
||||
void StopPluginInternal(bool aDelayedStop);
|
||||
virtual void SetIsDocumentActive(bool aIsActive);
|
||||
|
||||
NS_IMETHOD GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor);
|
||||
|
||||
|
@ -163,7 +148,7 @@ public:
|
|||
#endif
|
||||
|
||||
//local methods
|
||||
nsresult CreateWidget(nscoord aWidth, nscoord aHeight, bool aViewOnly);
|
||||
nsresult PrepForDrawing(nsIWidget *aWidget);
|
||||
|
||||
// for a given aRoot, this walks the frame tree looking for the next outFrame
|
||||
static nsIObjectFrame* GetNextObjectFrame(nsPresContext* aPresContext,
|
||||
|
@ -209,6 +194,19 @@ public:
|
|||
|
||||
nsIWidget* GetWidget() { return mWidget; }
|
||||
|
||||
/**
|
||||
* Adjust the plugin's idea of its size, using aSize as its new size.
|
||||
* (aSize must be in twips)
|
||||
*/
|
||||
void FixupWindow(const nsSize& aSize);
|
||||
|
||||
/*
|
||||
* Sets up the plugin window and calls SetWindow on the plugin.
|
||||
*/
|
||||
nsresult CallSetWindow(bool aCheckIsHidden = true);
|
||||
|
||||
void SetInstanceOwner(nsPluginInstanceOwner* aOwner);
|
||||
|
||||
protected:
|
||||
nsObjectFrame(nsStyleContext* aContext);
|
||||
virtual ~nsObjectFrame();
|
||||
|
@ -219,21 +217,6 @@ protected:
|
|||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
|
||||
nsresult InstantiatePlugin(nsPluginHost* aPluginHost,
|
||||
const char* aMimetype,
|
||||
nsIURI* aURL);
|
||||
|
||||
/**
|
||||
* Adjust the plugin's idea of its size, using aSize as its new size.
|
||||
* (aSize must be in twips)
|
||||
*/
|
||||
void FixupWindow(const nsSize& aSize);
|
||||
|
||||
/**
|
||||
* Sets up the plugin window and calls SetWindow on the plugin.
|
||||
*/
|
||||
nsresult CallSetWindow(bool aCheckIsHidden = true);
|
||||
|
||||
bool IsFocusable(PRInt32 *aTabIndex = nsnull, bool aWithMouse = false);
|
||||
|
||||
// check attributes and optionally CSS to see if we should display anything
|
||||
|
@ -242,8 +225,6 @@ protected:
|
|||
bool IsOpaque() const;
|
||||
bool IsTransparentMode() const;
|
||||
|
||||
void NotifyContentObjectWrapper();
|
||||
|
||||
nsIntPoint GetWindowOriginInPixels(bool aWindowless);
|
||||
|
||||
static void PaintPrintPlugin(nsIFrame* aFrame,
|
||||
|
@ -255,12 +236,6 @@ protected:
|
|||
nsRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect, const nsRect& aPluginRect);
|
||||
|
||||
/**
|
||||
* Makes sure that mInstanceOwner is valid and without a current plugin
|
||||
* instance. Essentially, this prepares the frame to receive a new plugin.
|
||||
*/
|
||||
NS_HIDDEN_(nsresult) PrepareInstanceOwner();
|
||||
|
||||
/**
|
||||
* Get the widget geometry for the plugin. aRegion is in some appunits
|
||||
* coordinate system whose origin is device-pixel-aligned (if possible),
|
||||
|
@ -291,8 +266,8 @@ private:
|
|||
private:
|
||||
nsString mEventType;
|
||||
};
|
||||
|
||||
nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
|
||||
|
||||
nsPluginInstanceOwner* mInstanceOwner; // WEAK
|
||||
nsIView* mInnerView;
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
nsIntRect mWindowlessRect;
|
||||
|
@ -302,11 +277,6 @@ private:
|
|||
*/
|
||||
PluginBackgroundSink* mBackgroundSink;
|
||||
|
||||
// For assertions that make it easier to determine if a crash is due
|
||||
// to the underlying problem described in bug 136927, and to prevent
|
||||
// reentry into instantiation.
|
||||
bool mPreventInstantiation;
|
||||
|
||||
bool mReflowCallbackPosted;
|
||||
|
||||
// A reference to the ImageContainer which contains the current frame
|
||||
|
|
|
@ -157,7 +157,12 @@ NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
|
|||
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace)
|
||||
{
|
||||
NS_ASSERTION(inView, "Must have a native view to convert coordinates.");
|
||||
// Plugins don't always have a view/frame. It would be odd to ask for a point conversion
|
||||
// without a view, so we'll warn about it, but it's technically OK.
|
||||
if (!inView) {
|
||||
NS_WARNING("Must have a native view to convert coordinates.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Caller has to want a result.
|
||||
if (!destX && !destY)
|
||||
|
|
|
@ -118,8 +118,9 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
|
|||
#endif
|
||||
|
||||
#define NS_IWIDGET_IID \
|
||||
{ 0xba20ac65, 0xb2a6, 0x4052, \
|
||||
{ 0xa4, 0xcb, 0x65, 0x40, 0xf8, 0x87, 0x9c, 0x55 } }
|
||||
{ 0x3fa36ce2, 0x472d, 0x4bff, \
|
||||
{ 0xb1, 0xe4, 0xc3, 0xe3, 0x19, 0x24, 0xa1, 0xe4 } }
|
||||
|
||||
/*
|
||||
* Window shadow styles
|
||||
* Also used for the -moz-window-shadow CSS property
|
||||
|
@ -478,6 +479,14 @@ class nsIWidget : public nsISupports {
|
|||
nsWidgetInitData *aInitData = nsnull,
|
||||
bool aForceUseIWidgetParent = false) = 0;
|
||||
|
||||
/**
|
||||
* Set the event callback for a widget. If a device context is not
|
||||
* provided then the existing device context will remain, it will
|
||||
* not be nulled out.
|
||||
*/
|
||||
NS_IMETHOD SetEventCallback(EVENT_CALLBACK aEventFunction,
|
||||
nsDeviceContext *aContext) = 0;
|
||||
|
||||
/**
|
||||
* Attach to a top level widget.
|
||||
*
|
||||
|
|
|
@ -262,6 +262,23 @@ nsBaseWidget::CreateChild(const nsIntRect &aRect,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseWidget::SetEventCallback(EVENT_CALLBACK aEventFunction,
|
||||
nsDeviceContext *aContext)
|
||||
{
|
||||
NS_ASSERTION(aEventFunction, "Must have valid event callback!");
|
||||
|
||||
mEventCallback = aEventFunction;
|
||||
|
||||
if (aContext) {
|
||||
NS_IF_RELEASE(mContext);
|
||||
mContext = aContext;
|
||||
NS_ADDREF(mContext);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Attach a view to our widget which we'll send events to.
|
||||
NS_IMETHODIMP
|
||||
nsBaseWidget::AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction,
|
||||
|
|
|
@ -179,6 +179,7 @@ public:
|
|||
nsDeviceContext *aContext,
|
||||
nsWidgetInitData *aInitData = nsnull,
|
||||
bool aForceUseIWidgetParent = false);
|
||||
NS_IMETHOD SetEventCallback(EVENT_CALLBACK aEventFunction, nsDeviceContext *aContext);
|
||||
NS_IMETHOD AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction, nsDeviceContext *aContext);
|
||||
virtual ViewWrapper* GetAttachedViewPtr();
|
||||
NS_IMETHOD SetAttachedViewPtr(ViewWrapper* aViewWrapper);
|
||||
|
|
Загрузка…
Ссылка в новой задаче