mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Backed out changeset 33031c875984. Bug 90268. r=josh
This commit is contained in:
parent
3b6b37ef98
commit
3fa80a3ea0
@ -1662,13 +1662,6 @@ 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(6D8914C7-0E22-4452-8962-11B69BBE84D7)]
|
||||
[scriptable, uuid(107e8048-d00f-4711-bd21-97184ccae0b1)]
|
||||
interface nsIObjectLoadingContent : nsISupports
|
||||
{
|
||||
const unsigned long TYPE_LOADING = 0;
|
||||
@ -86,6 +86,24 @@ 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.
|
||||
@ -95,8 +113,6 @@ 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
|
||||
@ -109,8 +125,4 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
in AString pluginDumpID,
|
||||
in AString browserDumpID,
|
||||
in boolean submittedCrashReport);
|
||||
|
||||
[noscript] void stopPluginInstance();
|
||||
|
||||
[noscript] void startPluginInstance();
|
||||
};
|
||||
|
@ -5516,8 +5516,9 @@ nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
|
||||
}
|
||||
}
|
||||
|
||||
nsIWidget *
|
||||
nsContentUtils::WidgetForDocument(nsIDocument *aDoc)
|
||||
static already_AddRefed<LayerManager>
|
||||
LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
|
||||
bool* aAllowRetaining)
|
||||
{
|
||||
nsIDocument* doc = aDoc;
|
||||
nsIDocument* displayDoc = doc->GetDisplayDocument();
|
||||
@ -5552,27 +5553,19 @@ nsContentUtils::WidgetForDocument(nsIDocument *aDoc)
|
||||
if (rootView) {
|
||||
nsIView* displayRoot = nsIViewManager::GetDisplayRootFor(rootView);
|
||||
if (displayRoot) {
|
||||
return displayRoot->GetNearestWidget(nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static already_AddRefed<LayerManager>
|
||||
LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
|
||||
bool* aAllowRetaining)
|
||||
{
|
||||
nsIWidget *widget = nsContentUtils::WidgetForDocument(aDoc);
|
||||
nsIWidget* widget = displayRoot->GetNearestWidget(nsnull);
|
||||
if (widget) {
|
||||
nsRefPtr<LayerManager> manager =
|
||||
widget->GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT :
|
||||
widget->
|
||||
GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT :
|
||||
nsIWidget::LAYER_MANAGER_CURRENT,
|
||||
aAllowRetaining);
|
||||
return manager.forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
@ -173,7 +173,6 @@
|
||||
#include "nsIDOMPageTransitionEvent.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
#ifdef MOZ_MEDIA
|
||||
#include "nsHTMLMediaElement.h"
|
||||
#endif // MOZ_MEDIA
|
||||
@ -3748,11 +3747,6 @@ 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
|
||||
|
@ -66,7 +66,6 @@
|
||||
#include "jsobj.h"
|
||||
#include "jsgc.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
@ -576,20 +575,15 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
|
||||
}
|
||||
}
|
||||
|
||||
if (wasRegistered && oldDoc != newDoc) {
|
||||
#ifdef MOZ_MEDIA
|
||||
if (wasRegistered && oldDoc != newDoc) {
|
||||
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) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,15 +53,11 @@
|
||||
#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)
|
||||
@ -100,8 +96,6 @@ 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
|
||||
@ -144,16 +138,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
{
|
||||
mNetworkCreated = aNetworkCreated;
|
||||
}
|
||||
|
||||
// Both "InstantiatePluginInstance" methods can flush layout.
|
||||
nsresult InstantiatePluginInstance(nsIChannel* aChannel,
|
||||
nsIStreamListener** aStreamListener);
|
||||
nsresult InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI);
|
||||
|
||||
void NotifyOwnerDocumentActivityChanged();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Load the object from the given URI.
|
||||
* @param aURI The URI to load.
|
||||
@ -241,14 +226,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
nsCycleCollectionTraversalCallback &cb);
|
||||
|
||||
void CreateStaticClone(nsObjectLoadingContent* aDest) const;
|
||||
|
||||
static void DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop);
|
||||
|
||||
private:
|
||||
|
||||
void TryNotifyContentObjectWrapper();
|
||||
void NotifyContentObjectWrapper();
|
||||
|
||||
/**
|
||||
* Check whether the given request represents a successful load.
|
||||
*/
|
||||
@ -327,7 +305,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
eFlushLayout,
|
||||
eDontFlush
|
||||
};
|
||||
nsObjectFrame* GetExistingFrame(FlushType aFlushType);
|
||||
nsIObjectFrame* GetExistingFrame(FlushType aFlushType);
|
||||
|
||||
/**
|
||||
* Handle being blocked by a content policy. aStatus is the nsresult
|
||||
@ -337,6 +315,22 @@ 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
|
||||
@ -420,7 +414,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
|
||||
nsWeakFrame mPrintFrame;
|
||||
|
||||
nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
|
||||
friend class nsAsyncInstantiateEvent;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -47,7 +47,6 @@
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -145,12 +144,19 @@ PluginStreamListener::SetupPlugin()
|
||||
// nsObjectFrame does that at the end of reflow.
|
||||
shell->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(embed));
|
||||
if (!olc) {
|
||||
nsIFrame* frame = embed->GetPrimaryFrame();
|
||||
if (!frame) {
|
||||
mPluginDoc->AllowNormalInstantiation();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIObjectFrame* objFrame = do_QueryFrame(frame);
|
||||
if (!objFrame) {
|
||||
mPluginDoc->AllowNormalInstantiation();
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
nsObjectLoadingContent* olcc = static_cast<nsObjectLoadingContent*>(olc.get());
|
||||
nsresult rv = olcc->InstantiatePluginInstance(mPluginDoc->GetType().get(),
|
||||
|
||||
nsresult rv = objFrame->Instantiate(mPluginDoc->GetType().get(),
|
||||
mDocument->nsIDocument::GetDocumentURI());
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
@ -349,7 +355,7 @@ PluginDocument::Print()
|
||||
nsIObjectFrame* objectFrame =
|
||||
do_QueryFrame(mPluginContent->GetPrimaryFrame());
|
||||
if (objectFrame) {
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsCOMPtr<nsNPAPIPluginInstance> pi;
|
||||
objectFrame->GetPluginInstance(getter_AddRefs(pi));
|
||||
if (pi) {
|
||||
NPPrint npprint;
|
||||
|
@ -9234,9 +9234,16 @@ 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.
|
||||
if (!nsContentUtils::IsSafeToRunScript()) {
|
||||
return objlc->GetPluginInstance(_result);
|
||||
}
|
||||
|
||||
// Make sure that there is a plugin
|
||||
return objlc->EnsureInstantiation(_result);
|
||||
}
|
||||
|
||||
// Check if proto is already in obj's prototype chain.
|
||||
|
||||
static PRBool
|
||||
@ -9338,9 +9345,20 @@ 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.
|
||||
|
||||
|
@ -80,6 +80,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
|
||||
#endif
|
||||
mRunning(NOT_STARTED),
|
||||
mWindowless(PR_FALSE),
|
||||
mWindowlessLocal(PR_FALSE),
|
||||
mTransparent(PR_FALSE),
|
||||
mUsesDOMForCursor(PR_FALSE),
|
||||
mInPluginInitCall(PR_FALSE),
|
||||
@ -659,6 +660,12 @@ NPError nsNPAPIPluginInstance::SetWindowless(PRBool aWindowless)
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError nsNPAPIPluginInstance::SetWindowlessLocal(PRBool aWindowlessLocal)
|
||||
{
|
||||
mWindowlessLocal = aWindowlessLocal;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError nsNPAPIPluginInstance::SetTransparent(PRBool aTransparent)
|
||||
{
|
||||
mTransparent = aTransparent;
|
||||
|
@ -124,6 +124,8 @@ public:
|
||||
|
||||
NPError SetWindowless(PRBool aWindowless);
|
||||
|
||||
NPError SetWindowlessLocal(PRBool aWindowlessLocal);
|
||||
|
||||
NPError SetTransparent(PRBool aTransparent);
|
||||
|
||||
NPError SetWantsAllNetworkStreams(PRBool aWantsAllNetworkStreams);
|
||||
@ -212,6 +214,7 @@ protected:
|
||||
// these are used to store the windowless properties
|
||||
// which the browser will later query
|
||||
PRPackedBool mWindowless;
|
||||
PRPackedBool mWindowlessLocal;
|
||||
PRPackedBool mTransparent;
|
||||
PRPackedBool mUsesDOMForCursor;
|
||||
|
||||
|
@ -3656,6 +3656,12 @@ nsPluginHost::NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow)
|
||||
return PLUG_NewPluginNativeWindow(aPluginNativeWindow);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPluginHost::DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
|
||||
{
|
||||
return PLUG_DeletePluginNativeWindow(aPluginNativeWindow);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPluginHost::InstantiateDummyJavaPlugin(nsIPluginInstanceOwner *aOwner)
|
||||
{
|
||||
|
@ -148,6 +148,7 @@ 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, PRBool isVisible);
|
||||
|
@ -99,7 +99,6 @@ using mozilla::DefaultXDisplay;
|
||||
static NS_DEFINE_CID(kRangeCID, NS_RANGE_CID);
|
||||
|
||||
#include "nsWidgetsCID.h"
|
||||
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
|
||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
|
||||
#ifdef XP_WIN
|
||||
@ -178,7 +177,7 @@ nsPluginInstanceOwner::NotifyPaintWaiter(nsDisplayListBuilder* aBuilder)
|
||||
#ifdef XP_MACOSX
|
||||
static void DrawPlugin(ImageContainer* aContainer, void* aPluginInstanceOwner)
|
||||
{
|
||||
nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetFrame();
|
||||
nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetOwner();
|
||||
if (frame) {
|
||||
frame->UpdateImageLayer(aContainer, gfxRect(0,0,0,0));
|
||||
}
|
||||
@ -285,16 +284,14 @@ 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);
|
||||
mPluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (mPluginHost)
|
||||
mPluginHost->NewPluginNativeWindow(&mPluginWindow);
|
||||
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (pluginHost)
|
||||
pluginHost->NewPluginNativeWindow(&mPluginWindow);
|
||||
else
|
||||
mPluginWindow = nsnull;
|
||||
|
||||
mObjectFrame = nsnull;
|
||||
mContent = nsnull;
|
||||
mTagText = nsnull;
|
||||
mWidgetCreationComplete = PR_FALSE;
|
||||
#ifdef XP_MACOSX
|
||||
memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext));
|
||||
#ifndef NP_NO_QUICKDRAW
|
||||
@ -313,6 +310,7 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
|
||||
mNumCachedParams = 0;
|
||||
mCachedAttrParamNames = nsnull;
|
||||
mCachedAttrParamValues = nsnull;
|
||||
mDestroyWidget = PR_FALSE;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#ifndef NP_NO_QUICKDRAW
|
||||
@ -369,8 +367,13 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
|
||||
mTagText = nsnull;
|
||||
}
|
||||
|
||||
PLUG_DeletePluginNativeWindow(mPluginWindow);
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (mInstance) {
|
||||
mInstance->InvalidateOwner();
|
||||
@ -1105,6 +1108,7 @@ 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.
|
||||
@ -1177,6 +1181,9 @@ 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) {
|
||||
@ -2448,15 +2455,70 @@ nsPluginInstanceOwner::Destroy()
|
||||
|
||||
if (mWidget) {
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
||||
if (pluginWidget) {
|
||||
if (pluginWidget)
|
||||
pluginWidget->SetPluginInstanceOwner(nsnull);
|
||||
}
|
||||
|
||||
if (mDestroyWidget)
|
||||
mWidget->Destroy();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare to stop
|
||||
*/
|
||||
void
|
||||
nsPluginInstanceOwner::PrepareToStop(PRBool 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(PR_FALSE);
|
||||
mWidget->Enable(PR_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 = PR_TRUE;
|
||||
}
|
||||
#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
|
||||
@ -2792,19 +2854,25 @@ void nsPluginInstanceOwner::CancelTimer()
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult nsPluginInstanceOwner::Init(nsObjectFrame* aFrame, nsIContent* aContent)
|
||||
nsresult nsPluginInstanceOwner::Init(nsPresContext* aPresContext,
|
||||
nsObjectFrame* aFrame,
|
||||
nsIContent* aContent)
|
||||
{
|
||||
mLastEventloopNestingLevel = GetEventloopNestingLevel();
|
||||
|
||||
mObjectFrame = aFrame;
|
||||
mContent = aContent;
|
||||
|
||||
if (aFrame) {
|
||||
SetFrame(aFrame);
|
||||
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.
|
||||
aFrame->PresContext()->EnsureVisible();
|
||||
aPresContext->EnsureVisible();
|
||||
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// register context menu listener
|
||||
@ -2845,6 +2913,16 @@ nsresult nsPluginInstanceOwner::Init(nsObjectFrame* aFrame, nsIContent* aContent
|
||||
mContent->AddEventListener(NS_LITERAL_STRING("draggesture"), this, PR_TRUE);
|
||||
mContent->AddEventListener(NS_LITERAL_STRING("dragend"), this, PR_TRUE);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -2887,55 +2965,20 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (mObjectFrame) {
|
||||
if (!mWidget) {
|
||||
PRBool windowless = PR_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;
|
||||
if (mContent) {
|
||||
nsIDocument *doc = mContent->GetOwnerDoc();
|
||||
if (doc) {
|
||||
parentWidget = nsContentUtils::WidgetForDocument(doc);
|
||||
}
|
||||
}
|
||||
|
||||
mWidget = do_CreateInstance(kWidgetCID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
// 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();
|
||||
|
||||
nsWidgetInitData initData;
|
||||
initData.mWindowType = eWindowType_plugin;
|
||||
initData.mUnicode = PR_FALSE;
|
||||
initData.clipChildren = PR_TRUE;
|
||||
initData.clipSiblings = PR_TRUE;
|
||||
rv = mWidget->Create(parentWidget.get(), nsnull, nsIntRect(0,0,0,0),
|
||||
nsnull, nsnull, nsnull, nsnull, &initData);
|
||||
if (NS_FAILED(rv)) {
|
||||
mWidget->Destroy();
|
||||
mWidget = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
mWidget->EnableDragDrop(PR_TRUE);
|
||||
mWidget->Show(PR_FALSE);
|
||||
mWidget->Enable(PR_FALSE);
|
||||
}
|
||||
|
||||
if (mObjectFrame) {
|
||||
// This has to be called even if we don't have a widget! The object
|
||||
// frame will do windowless setup.
|
||||
mObjectFrame->SetWidget(mWidget);
|
||||
}
|
||||
|
||||
if (windowless) {
|
||||
if (PR_TRUE == windowless) {
|
||||
mPluginWindow->type = NPWindowTypeDrawable;
|
||||
|
||||
// this needs to be a HDC according to the spec, but I do
|
||||
@ -2954,7 +2997,26 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
|
||||
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;
|
||||
@ -2970,14 +3032,19 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
|
||||
|
||||
// tell the widget about the current plugin instance owner.
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
||||
if (pluginWidget) {
|
||||
if (pluginWidget)
|
||||
pluginWidget->SetPluginInstanceOwner(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mWidgetCreationComplete = PR_TRUE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost* aHost)
|
||||
{
|
||||
mPluginHost = static_cast<nsPluginHost*>(aHost);
|
||||
}
|
||||
|
||||
// Mac specific code to fix up the port location and clipping region
|
||||
@ -3221,85 +3288,6 @@ nsPluginInstanceOwner::CallSetWindow()
|
||||
}
|
||||
}
|
||||
|
||||
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 SetWidget on an object frame once. Don't do it here unless
|
||||
// widget creation is complete. Whether or not one was actually created and
|
||||
// mWidget is NULL is irrelevant.
|
||||
if (mWidgetCreationComplete) {
|
||||
mObjectFrame->SetWidget(mWidget);
|
||||
}
|
||||
mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
|
||||
mObjectFrame->Invalidate(mObjectFrame->GetContentRectRelativeToSelf());
|
||||
}
|
||||
}
|
||||
|
||||
nsObjectFrame* nsPluginInstanceOwner::GetFrame()
|
||||
{
|
||||
return mObjectFrame;
|
||||
}
|
||||
|
||||
// Little helper function to resolve relative URL in
|
||||
// |value| for certain inputs of |name|
|
||||
void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value)
|
||||
|
@ -133,6 +133,8 @@ public:
|
||||
|
||||
nsresult Destroy();
|
||||
|
||||
void PrepareToStop(PRBool aDelayedStop);
|
||||
|
||||
#ifdef XP_WIN
|
||||
void Paint(const RECT& aDirty, HDC aDC);
|
||||
#elif defined(XP_MACOSX)
|
||||
@ -159,11 +161,14 @@ public:
|
||||
|
||||
//locals
|
||||
|
||||
nsresult Init(nsObjectFrame* aFrame, nsIContent* aContent);
|
||||
nsresult Init(nsPresContext* aPresContext, nsObjectFrame* aFrame,
|
||||
nsIContent* aContent);
|
||||
|
||||
void* GetPluginPortFromWidget();
|
||||
void ReleasePluginPort(void* pluginPort);
|
||||
|
||||
void SetPluginHost(nsIPluginHost* aHost);
|
||||
|
||||
nsEventStatus ProcessEvent(const nsGUIEvent & anEvent);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
@ -203,8 +208,13 @@ public:
|
||||
#endif // XP_MACOSX
|
||||
void CallSetWindow();
|
||||
|
||||
void SetFrame(nsObjectFrame *aFrame);
|
||||
nsObjectFrame* GetFrame();
|
||||
void SetOwner(nsObjectFrame *aOwner)
|
||||
{
|
||||
mObjectFrame = aOwner;
|
||||
}
|
||||
nsObjectFrame* GetOwner() {
|
||||
return mObjectFrame;
|
||||
}
|
||||
|
||||
PRUint32 GetLastEventloopNestingLevel() const {
|
||||
return mLastEventloopNestingLevel;
|
||||
@ -298,11 +308,10 @@ private:
|
||||
|
||||
nsPluginNativeWindow *mPluginWindow;
|
||||
nsRefPtr<nsNPAPIPluginInstance> mInstance;
|
||||
nsObjectFrame *mObjectFrame;
|
||||
nsIContent *mContent; // WEAK, content owns us
|
||||
nsObjectFrame *mObjectFrame; // owns nsPluginInstanceOwner
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsCString mDocumentBase;
|
||||
char *mTagText;
|
||||
PRBool mWidgetCreationComplete;
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
nsRefPtr<nsPluginHost> mPluginHost;
|
||||
|
||||
@ -339,6 +348,9 @@ private:
|
||||
PRPackedBool mPluginWindowVisible;
|
||||
PRPackedBool mPluginDocumentActiveState;
|
||||
|
||||
// If true, destroy the widget on destruction. Used when plugin stop
|
||||
// is being delayed to a safer point in time.
|
||||
PRPackedBool mDestroyWidget;
|
||||
PRUint16 mNumCachedAttrs;
|
||||
PRUint16 mNumCachedParams;
|
||||
char **mCachedAttrParamNames;
|
||||
|
@ -102,11 +102,6 @@ _MOCHITEST_FILES = \
|
||||
test_zero_opacity.html \
|
||||
test_NPPVpluginWantsAllNetworkStreams.html \
|
||||
test_npruntime_npnsetexception.html \
|
||||
test_display_none.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
|
||||
@ -131,7 +126,6 @@ _MOCHICHROME_FILES = \
|
||||
|
||||
ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
|
||||
_MOCHITEST_FILES += \
|
||||
test_instance_re-parent-windowed.html \
|
||||
test_visibility.html \
|
||||
$(NULL)
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test npruntime and paint count for instance in a display:none div</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 style="display: none;">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function startTest() {
|
||||
var paintCount = -1;
|
||||
var exceptionThrown = false;
|
||||
|
||||
var p = document.getElementById('plugin1');
|
||||
try {
|
||||
paintCount = p.getPaintCount();
|
||||
} catch (e) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
|
||||
is(paintCount, 0, "Paint count test.");
|
||||
is(exceptionThrown, false, "Exception test.");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,59 +0,0 @@
|
||||
<!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>
|
@ -1,59 +0,0 @@
|
||||
<!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"></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>
|
@ -1,41 +0,0 @@
|
||||
<!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>
|
@ -1,50 +0,0 @@
|
||||
<!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>
|
@ -1,44 +0,0 @@
|
||||
<!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>
|
@ -7581,9 +7581,10 @@ PresShell::RemoveOverrideStyleSheet(nsIStyleSheet *aSheet)
|
||||
static void
|
||||
FreezeElement(nsIContent *aContent, void * /* unused */)
|
||||
{
|
||||
nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(aContent));
|
||||
if (olc) {
|
||||
olc->StopPluginInstance();
|
||||
nsIFrame *frame = aContent->GetPrimaryFrame();
|
||||
nsIObjectFrame *objectFrame = do_QueryFrame(frame);
|
||||
if (objectFrame) {
|
||||
objectFrame->StopPlugin();
|
||||
}
|
||||
}
|
||||
|
||||
@ -7661,9 +7662,10 @@ PresShell::FireOrClearDelayedEvents(PRBool aFireEvents)
|
||||
static void
|
||||
ThawElement(nsIContent *aContent, void *aShell)
|
||||
{
|
||||
nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(aContent));
|
||||
if (olc) {
|
||||
olc->StartPluginInstance();
|
||||
nsCOMPtr<nsIObjectLoadingContent> objlc(do_QueryInterface(aContent));
|
||||
if (objlc) {
|
||||
nsRefPtr<nsNPAPIPluginInstance> inst;
|
||||
objlc->EnsureInstantiation(getter_AddRefs(inst));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,42 @@ 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.
|
||||
*/
|
||||
|
@ -322,11 +322,17 @@ 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));
|
||||
|
||||
@ -338,17 +344,25 @@ nsObjectFrame::Init(nsIContent* aContent,
|
||||
void
|
||||
nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
||||
{
|
||||
// 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();
|
||||
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(PR_TRUE);
|
||||
|
||||
// StopPluginInternal might have disowned the widget; if it has,
|
||||
// mWidget will be null.
|
||||
if (mWidget) {
|
||||
mInnerView->DetachWidgetEventHandler(mWidget);
|
||||
mWidget->Destroy();
|
||||
}
|
||||
|
||||
if (mBackgroundSink) {
|
||||
mBackgroundSink->Destroy();
|
||||
}
|
||||
|
||||
SetInstanceOwner(nsnull);
|
||||
|
||||
nsObjectFrameSuper::DestroyFrom(aDestructRoot);
|
||||
}
|
||||
|
||||
@ -383,14 +397,20 @@ nsObjectFrame::GetFrameName(nsAString& aResult) const
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsObjectFrame::SetWidget(nsIWidget *aWidget)
|
||||
nsObjectFrame::CreateWidget(nscoord aWidth,
|
||||
nscoord aHeight,
|
||||
PRBool aViewOnly)
|
||||
{
|
||||
mWidget = aWidget;
|
||||
|
||||
nsIView* view = GetView();
|
||||
NS_ASSERTION(view, "Object frames must have views");
|
||||
if (!view) {
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK; //XXX why OK? MMP
|
||||
}
|
||||
|
||||
PRBool needsWidget = !aViewOnly;
|
||||
PRBool canCreateWidget = !nsIWidget::UsePuppetWidgets();
|
||||
if (needsWidget && !canCreateWidget) {
|
||||
NS_WARNING("Can't use native widgets, and can't hand a plugins a PuppetWidget");
|
||||
}
|
||||
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
@ -398,6 +418,9 @@ nsObjectFrame::SetWidget(nsIWidget *aWidget)
|
||||
// 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).
|
||||
@ -415,12 +438,12 @@ nsObjectFrame::SetWidget(nsIWidget *aWidget)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mWidget) {
|
||||
if (needsWidget && !mWidget && canCreateWidget) {
|
||||
// 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) {
|
||||
@ -429,27 +452,30 @@ nsObjectFrame::SetWidget(nsIWidget *aWidget)
|
||||
}
|
||||
viewMan->InsertChild(view, mInnerView, nsnull, PR_TRUE);
|
||||
|
||||
mWidget->SetParent(parentWidget);
|
||||
mWidget->Show(PR_TRUE);
|
||||
mWidget->Enable(PR_TRUE);
|
||||
nsresult rv;
|
||||
mWidget = do_CreateInstance(kWidgetCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// 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));
|
||||
nsWidgetInitData initData;
|
||||
initData.mWindowType = eWindowType_plugin;
|
||||
initData.mUnicode = PR_FALSE;
|
||||
initData.clipChildren = PR_TRUE;
|
||||
initData.clipSiblings = PR_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.
|
||||
EVENT_CALLBACK eventHandler = mInnerView->AttachWidgetEventHandler(mWidget);
|
||||
mWidget->SetEventCallback(eventHandler, dx);
|
||||
rv = mWidget->Create(parentWidget, nsnull, nsIntRect(0,0,0,0),
|
||||
eventHandler, dx, nsnull, nsnull, &initData);
|
||||
if (NS_FAILED(rv)) {
|
||||
mWidget->Destroy();
|
||||
mWidget = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
mWidget->EnableDragDrop(PR_TRUE);
|
||||
|
||||
// If this frame has an ancestor with a widget which is not
|
||||
// the root prescontext's widget, then this plugin should not be
|
||||
@ -465,7 +491,9 @@ nsObjectFrame::SetWidget(nsIWidget *aWidget)
|
||||
Invalidate(GetContentRectRelativeToSelf());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (mWidget) {
|
||||
rpc->RegisterPluginForGeometryUpdates(this);
|
||||
rpc->RequestUpdatePluginGeometry(this);
|
||||
|
||||
@ -486,9 +514,8 @@ nsObjectFrame::SetWidget(nsIWidget *aWidget)
|
||||
// Now that we have a widget we want to set the event model before
|
||||
// any events are processed.
|
||||
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
||||
if (!pluginWidget) {
|
||||
if (!pluginWidget)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
pluginWidget->SetPluginEventModel(mInstanceOwner->GetEventModel());
|
||||
pluginWidget->SetPluginDrawingModel(mInstanceOwner->GetDrawingModel());
|
||||
|
||||
@ -497,9 +524,6 @@ nsObjectFrame::SetWidget(nsIWidget *aWidget)
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// Changing to windowless mode changes the NPWindow geometry.
|
||||
FixupWindow(GetContentRectRelativeToSelf().Size());
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
rpc->RegisterPluginForGeometryUpdates(this);
|
||||
rpc->RequestUpdatePluginGeometry(this);
|
||||
@ -510,14 +534,7 @@ nsObjectFrame::SetWidget(nsIWidget *aWidget)
|
||||
viewMan->SetViewVisibility(view, nsViewVisibility_kShow);
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
nsAccessibilityService* accService = nsIPresShell::AccService();
|
||||
if (accService) {
|
||||
accService->RecreateAccessible(PresContext()->PresShell(), mContent);
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
return (needsWidget && !canCreateWidget) ? NS_ERROR_NOT_AVAILABLE : NS_OK;
|
||||
}
|
||||
|
||||
#define EMBED_DEF_WIDTH 240
|
||||
@ -676,6 +693,50 @@ nsObjectFrame::ReflowCallbackCanceled()
|
||||
mReflowCallbackPosted = PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsObjectFrame::InstantiatePlugin(nsPluginHost* aPluginHost,
|
||||
const char* aMimeType,
|
||||
nsIURI* aURI)
|
||||
{
|
||||
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->GetOwnerDoc();
|
||||
nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(doc));
|
||||
PRBool fullPageMode = PR_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)
|
||||
{
|
||||
@ -771,38 +832,6 @@ nsObjectFrame::CallSetWindow(PRBool 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->SetParent(nsnull);
|
||||
}
|
||||
} else {
|
||||
#ifndef XP_MACOSX
|
||||
rpc->UnregisterPluginForGeometryUpdates(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsObjectFrame::IsFocusable(PRInt32 *aTabIndex, PRBool aWithMouse)
|
||||
{
|
||||
@ -2048,11 +2077,400 @@ nsObjectFrame::GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance)
|
||||
{
|
||||
*aPluginInstance = nsnull;
|
||||
|
||||
if (!mInstanceOwner) {
|
||||
if (!mInstanceOwner)
|
||||
return NS_OK;
|
||||
|
||||
return mInstanceOwner->GetInstance(aPluginInstance);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsObjectFrame::PrepareInstanceOwner()
|
||||
{
|
||||
nsWeakFrame weakFrame(this);
|
||||
|
||||
// First, have to stop any possibly running plugins.
|
||||
StopPluginInternal(PR_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)
|
||||
{
|
||||
if (mPreventInstantiation) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mInstanceOwner->GetInstance(aPluginInstance);
|
||||
// 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 = PR_TRUE;
|
||||
rv = pluginHost->InstantiatePluginForChannel(aChannel, mInstanceOwner, aStreamListener);
|
||||
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mPreventInstantiation,
|
||||
"Instantiation should still be prevented!");
|
||||
mPreventInstantiation = PR_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)
|
||||
{
|
||||
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 = PR_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 = PR_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 PRBool
|
||||
DoDelayedStop(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop)
|
||||
{
|
||||
#if (MOZ_PLATFORM_MAEMO==5)
|
||||
// Don't delay stop on Maemo/Hildon (bug 530739).
|
||||
if (aDelayedStop && aInstanceOwner->MatchPluginName("Shockwave Flash"))
|
||||
return PR_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 PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop)
|
||||
{
|
||||
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()
|
||||
{
|
||||
// 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, PR_FALSE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectFrame::StopPlugin()
|
||||
{
|
||||
PRBool delayedStop = PR_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(PRBool aDelayedStop)
|
||||
{
|
||||
if (!mInstanceOwner) {
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
PRBool oldVal = mPreventInstantiation;
|
||||
mPreventInstantiation = PR_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);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -2086,6 +2504,43 @@ nsObjectFrame::SetIsDocumentActive(PRBool 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 = (JSContext *)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,6 +40,10 @@
|
||||
#ifndef nsObjectFrame_h___
|
||||
#define nsObjectFrame_h___
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
#include "nsIObjectFrame.h"
|
||||
#include "nsFrame.h"
|
||||
@ -120,9 +124,20 @@ 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(PRBool 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(PRBool aDelayedStop);
|
||||
|
||||
NS_IMETHOD GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor);
|
||||
|
||||
// Compute the desired position of the plugin's widget, on the assumption
|
||||
@ -148,7 +163,7 @@ public:
|
||||
#endif
|
||||
|
||||
//local methods
|
||||
nsresult SetWidget(nsIWidget *aWidget);
|
||||
nsresult CreateWidget(nscoord aWidth, nscoord aHeight, PRBool aViewOnly);
|
||||
|
||||
// for a given aRoot, this walks the frame tree looking for the next outFrame
|
||||
static nsIObjectFrame* GetNextObjectFrame(nsPresContext* aPresContext,
|
||||
@ -194,19 +209,6 @@ 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(PRBool aCheckIsHidden = PR_TRUE);
|
||||
|
||||
void SetInstanceOwner(nsPluginInstanceOwner* aOwner);
|
||||
|
||||
protected:
|
||||
nsObjectFrame(nsStyleContext* aContext);
|
||||
virtual ~nsObjectFrame();
|
||||
@ -217,6 +219,21 @@ 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(PRBool aCheckIsHidden = PR_TRUE);
|
||||
|
||||
PRBool IsFocusable(PRInt32 *aTabIndex = nsnull, PRBool aWithMouse = PR_FALSE);
|
||||
|
||||
// check attributes and optionally CSS to see if we should display anything
|
||||
@ -225,6 +242,8 @@ protected:
|
||||
PRBool IsOpaque() const;
|
||||
PRBool IsTransparentMode() const;
|
||||
|
||||
void NotifyContentObjectWrapper();
|
||||
|
||||
nsIntPoint GetWindowOriginInPixels(PRBool aWindowless);
|
||||
|
||||
static void PaintPrintPlugin(nsIFrame* aFrame,
|
||||
@ -236,6 +255,12 @@ 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),
|
||||
@ -267,7 +292,7 @@ private:
|
||||
nsString mEventType;
|
||||
};
|
||||
|
||||
nsPluginInstanceOwner* mInstanceOwner; // WEAK
|
||||
nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
|
||||
nsIView* mInnerView;
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
nsIntRect mWindowlessRect;
|
||||
@ -277,6 +302,11 @@ 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.
|
||||
PRBool mPreventInstantiation;
|
||||
|
||||
PRPackedBool mReflowCallbackPosted;
|
||||
|
||||
// A reference to the ImageContainer which contains the current frame
|
||||
|
@ -157,12 +157,7 @@ NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
|
||||
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace)
|
||||
{
|
||||
// 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 PR_FALSE;
|
||||
}
|
||||
NS_ASSERTION(inView, "Must have a native view to convert coordinates.");
|
||||
|
||||
// Caller has to want a result.
|
||||
if (!destX && !destY)
|
||||
|
Loading…
Reference in New Issue
Block a user