Bug 390385 make sure that plugins don't get instantiated before the first Reflow of the objectframe, so that the first NPP_SetWindow call contains the right dimensions r+sr=bz

This commit is contained in:
cbiesinger@gmx.at 2007-08-06 17:32:14 -07:00
parent 640a4e236d
commit 952d1075d3
3 changed files with 57 additions and 35 deletions

View File

@ -128,7 +128,8 @@ nsAsyncInstantiateEvent::Run()
// the type here - GetFrame() only returns object frames, and that means we're // the type here - GetFrame() only returns object frames, and that means we're
// a plugin) // a plugin)
// Also make sure that we still refer to the same data. // Also make sure that we still refer to the same data.
if (mContent->GetFrame(PR_FALSE) == mFrame && nsIObjectFrame* frame = mContent->GetFrame(PR_FALSE);
if (frame == mFrame &&
mContent->mURI == mURI && mContent->mURI == mURI &&
mContent->mContentType.Equals(mContentType)) { mContent->mContentType.Equals(mContentType)) {
if (LOG_ENABLED()) { if (LOG_ENABLED()) {
@ -140,7 +141,7 @@ nsAsyncInstantiateEvent::Run()
mContent, mContentType.get(), mURI.get(), spec.get())); mContent, mContentType.get(), mURI.get(), spec.get()));
} }
nsresult rv = mContent->Instantiate(mContentType, mURI); nsresult rv = mContent->Instantiate(frame, mContentType, mURI);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mContent->Fallback(PR_TRUE); mContent->Fallback(PR_TRUE);
} }
@ -643,7 +644,7 @@ nsObjectLoadingContent::EnsureInstantiation(nsIPluginInstance** aInstance)
// We may have a plugin instance already; if so, do nothing // We may have a plugin instance already; if so, do nothing
nsresult rv = frame->GetPluginInstance(*aInstance); nsresult rv = frame->GetPluginInstance(*aInstance);
if (!*aInstance) { if (!*aInstance) {
rv = Instantiate(mContentType, mURI); rv = Instantiate(frame, mContentType, mURI);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
rv = frame->GetPluginInstance(*aInstance); rv = frame->GetPluginInstance(*aInstance);
} else { } else {
@ -931,6 +932,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
if (overrideType.IsEmpty()) { if (overrideType.IsEmpty()) {
newType = GetTypeOfContent(aTypeHint); newType = GetTypeOfContent(aTypeHint);
} else { } else {
mContentType = overrideType;
newType = eType_Plugin; newType = eType_Plugin;
} }
@ -957,6 +959,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
// Must notify here for plugins // Must notify here for plugins
// If aNotify is false, we'll just wait until we get a frame and use the // If aNotify is false, we'll just wait until we get a frame and use the
// async instantiate path. // async instantiate path.
// XXX is this still needed? (for documents?)
mType = newType; mType = newType;
if (aNotify) if (aNotify)
notifier.Notify(); notifier.Notify();
@ -967,7 +970,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
rv = LoadImage(aURI, aForceLoad, PR_FALSE); rv = LoadImage(aURI, aForceLoad, PR_FALSE);
break; break;
case eType_Plugin: case eType_Plugin:
rv = Instantiate(aTypeHint, aURI); rv = TryInstantiate(mContentType, mURI);
break; break;
case eType_Document: case eType_Document:
rv = mFrameLoader->LoadURI(aURI); rv = mFrameLoader->LoadURI(aURI);
@ -1019,8 +1022,6 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
// Or: supported class id, plugin will handle the load. // Or: supported class id, plugin will handle the load.
LOG(("OBJLC [%p]: (classid) Changing type from %u to eType_Plugin\n", this, mType)); LOG(("OBJLC [%p]: (classid) Changing type from %u to eType_Plugin\n", this, mType));
mType = eType_Plugin; mType = eType_Plugin;
if (aNotify)
notifier.Notify();
// At this point, the stored content type // At this point, the stored content type
// must be equal to our type hint. Similar, // must be equal to our type hint. Similar,
@ -1043,7 +1044,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
} }
} }
rv = Instantiate(mContentType, mURI); rv = TryInstantiate(mContentType, mURI);
return NS_OK; return NS_OK;
} }
@ -1062,10 +1063,8 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
} }
// E.g. mms:// // E.g. mms://
mType = eType_Plugin; mType = eType_Plugin;
if (aNotify)
notifier.Notify();
rv = Instantiate(aTypeHint, aURI); rv = TryInstantiate(aTypeHint, aURI);
return NS_OK; return NS_OK;
} }
@ -1436,13 +1435,29 @@ nsObjectLoadingContent::GetFrame(PRBool aFlushLayout)
} }
nsresult nsresult
nsObjectLoadingContent::Instantiate(const nsACString& aMIMEType, nsIURI* aURI) nsObjectLoadingContent::TryInstantiate(const nsACString& aMIMEType,
nsIURI* aURI)
{ {
nsIObjectFrame* frame = GetFrame(PR_FALSE); nsIObjectFrame* frame = GetFrame(PR_FALSE);
if (!frame) { if (!frame) {
LOG(("OBJLC [%p]: Attempted to instantiate, but have no frame\n", this)); LOG(("OBJLC [%p]: No frame yet\n", this));
return NS_OK; // Not a failure to have no frame return NS_OK; // Not a failure to have no frame
} }
nsIFrame* iframe;
CallQueryInterface(frame, &iframe);
if (iframe->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
LOG(("OBJLC [%p]: Frame hasn't been reflown yet\n", this));
return NS_OK; // Not a failure to have no frame
}
return Instantiate(frame, aMIMEType, aURI);
}
nsresult
nsObjectLoadingContent::Instantiate(nsIObjectFrame* aFrame,
const nsACString& aMIMEType,
nsIURI* aURI)
{
NS_ASSERTION(aFrame, "Must have a frame here");
nsCString typeToUse(aMIMEType); nsCString typeToUse(aMIMEType);
if (typeToUse.IsEmpty() && aURI) { if (typeToUse.IsEmpty() && aURI) {
@ -1463,9 +1478,9 @@ nsObjectLoadingContent::Instantiate(const nsACString& aMIMEType, nsIURI* aURI)
// We'll always have a type or a URI by the time we get here // We'll always have a type or a URI by the time we get here
NS_ASSERTION(aURI || !typeToUse.IsEmpty(), "Need a URI or a type"); NS_ASSERTION(aURI || !typeToUse.IsEmpty(), "Need a URI or a type");
LOG(("OBJLC [%p]: Calling [%p]->Instantiate(<%s>, %p)\n", this, frame, LOG(("OBJLC [%p]: Calling [%p]->Instantiate(<%s>, %p)\n", this, aFrame,
typeToUse.get(), aURI)); typeToUse.get(), aURI));
return frame->Instantiate(typeToUse.get(), aURI); return aFrame->Instantiate(typeToUse.get(), aURI);
} }
/* static */ PRBool /* static */ PRBool

View File

@ -284,12 +284,18 @@ class nsObjectLoadingContent : public nsImageLoadingContent
*/ */
nsIObjectFrame* GetFrame(PRBool aFlushLayout); nsIObjectFrame* GetFrame(PRBool aFlushLayout);
/**
* Checks if we have a frame that's ready for instantiation, and if so,
* calls Instantiate().
*/
nsresult TryInstantiate(const nsACString& aMIMEType, nsIURI* aURI);
/** /**
* Instantiates the plugin. This differs from GetFrame()->Instantiate() in * Instantiates the plugin. This differs from GetFrame()->Instantiate() in
* that it ensures that the URI will be non-null, and that a MIME type * that it ensures that the URI will be non-null, and that a MIME type
* will be passed. * will be passed.
*/ */
nsresult Instantiate(const nsACString& aMIMEType, nsIURI* aURI); nsresult Instantiate(nsIObjectFrame* aFrame, const nsACString& aMIMEType, nsIURI* aURI);
/** /**
* Whether to treat this content as a plugin, even though we can't handle * Whether to treat this content as a plugin, even though we can't handle

View File

@ -506,11 +506,7 @@ nsObjectFrame::Init(nsIContent* aContent,
mInstantiating = PR_FALSE; mInstantiating = PR_FALSE;
#endif #endif
nsresult rv = nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow); return nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow);
nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
NS_ASSERTION(objContent, "Why not an object loading content?");
objContent->HasNewFrame(this);
return rv;
} }
void void
@ -724,7 +720,6 @@ nsObjectFrame::Reflow(nsPresContext* aPresContext,
return NS_OK; return NS_OK;
} }
FixupWindow(nsSize(aMetrics.width, aMetrics.height)); FixupWindow(nsSize(aMetrics.width, aMetrics.height));
aStatus = NS_FRAME_COMPLETE; aStatus = NS_FRAME_COMPLETE;
@ -776,10 +771,6 @@ nsObjectFrame::InstantiatePlugin(nsIPluginHost* aPluginHost,
appShell->ResumeNative(); appShell->ResumeNative();
} }
// XXX having to do this sucks. it'd be better to move the code from DidReflow
// to FixupWindow or something.
PresContext()->GetPresShell()->
FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
return rv; return rv;
} }
@ -796,11 +787,17 @@ nsObjectFrame::FixupWindow(const nsSize& aSize)
NS_ENSURE_TRUE(window, /**/); NS_ENSURE_TRUE(window, /**/);
nsPoint origin; #ifdef XP_MACOSX
nsIView *parentWithView; mInstanceOwner->FixUpPluginWindow(ePluginPaintDisable);
GetOffsetFromView(origin, &parentWithView); #endif
window->x = presContext->AppUnitsToDevPixels(origin.x);
window->y = presContext->AppUnitsToDevPixels(origin.y); PRBool windowless = (window->type == nsPluginWindowType_Drawable);
nsPoint origin = GetWindowOriginInPixels(windowless);
window->x = origin.x;
window->y = origin.y;
window->width = presContext->AppUnitsToDevPixels(aSize.width); window->width = presContext->AppUnitsToDevPixels(aSize.width);
window->height = presContext->AppUnitsToDevPixels(aSize.height); window->height = presContext->AppUnitsToDevPixels(aSize.height);
@ -896,6 +893,15 @@ nsObjectFrame::DidReflow(nsPresContext* aPresContext,
const nsHTMLReflowState* aReflowState, const nsHTMLReflowState* aReflowState,
nsDidReflowStatus aStatus) nsDidReflowStatus aStatus)
{ {
// Do this check before calling the superclass, as that clears
// NS_FRAME_FIRST_REFLOW
if (aStatus == NS_FRAME_REFLOW_FINISHED &&
(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
NS_ASSERTION(objContent, "Why not an object loading content?");
objContent->HasNewFrame(this);
}
nsresult rv = nsObjectFrameSuper::DidReflow(aPresContext, aReflowState, aStatus); nsresult rv = nsObjectFrameSuper::DidReflow(aPresContext, aReflowState, aStatus);
// The view is created hidden; once we have reflowed it and it has been // The view is created hidden; once we have reflowed it and it has been
@ -1391,11 +1397,6 @@ nsObjectFrame::Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamList
rv = pluginHost->InstantiatePluginForChannel(aChannel, mInstanceOwner, aStreamListener); rv = pluginHost->InstantiatePluginForChannel(aChannel, mInstanceOwner, aStreamListener);
// XXX having to do this sucks. it'd be better to move the code from DidReflow
// to FixupWindow.
PresContext()->GetPresShell()->
FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
return rv; return rv;
} }