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
// a plugin)
// 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->mContentType.Equals(mContentType)) {
if (LOG_ENABLED()) {
@ -140,7 +141,7 @@ nsAsyncInstantiateEvent::Run()
mContent, mContentType.get(), mURI.get(), spec.get()));
}
nsresult rv = mContent->Instantiate(mContentType, mURI);
nsresult rv = mContent->Instantiate(frame, mContentType, mURI);
if (NS_FAILED(rv)) {
mContent->Fallback(PR_TRUE);
}
@ -643,7 +644,7 @@ nsObjectLoadingContent::EnsureInstantiation(nsIPluginInstance** aInstance)
// We may have a plugin instance already; if so, do nothing
nsresult rv = frame->GetPluginInstance(*aInstance);
if (!*aInstance) {
rv = Instantiate(mContentType, mURI);
rv = Instantiate(frame, mContentType, mURI);
if (NS_SUCCEEDED(rv)) {
rv = frame->GetPluginInstance(*aInstance);
} else {
@ -931,6 +932,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
if (overrideType.IsEmpty()) {
newType = GetTypeOfContent(aTypeHint);
} else {
mContentType = overrideType;
newType = eType_Plugin;
}
@ -957,6 +959,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
// Must notify here for plugins
// If aNotify is false, we'll just wait until we get a frame and use the
// async instantiate path.
// XXX is this still needed? (for documents?)
mType = newType;
if (aNotify)
notifier.Notify();
@ -967,7 +970,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
rv = LoadImage(aURI, aForceLoad, PR_FALSE);
break;
case eType_Plugin:
rv = Instantiate(aTypeHint, aURI);
rv = TryInstantiate(mContentType, mURI);
break;
case eType_Document:
rv = mFrameLoader->LoadURI(aURI);
@ -1019,8 +1022,6 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
// Or: supported class id, plugin will handle the load.
LOG(("OBJLC [%p]: (classid) Changing type from %u to eType_Plugin\n", this, mType));
mType = eType_Plugin;
if (aNotify)
notifier.Notify();
// At this point, the stored content type
// 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;
}
@ -1062,10 +1063,8 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
}
// E.g. mms://
mType = eType_Plugin;
if (aNotify)
notifier.Notify();
rv = Instantiate(aTypeHint, aURI);
rv = TryInstantiate(aTypeHint, aURI);
return NS_OK;
}
@ -1436,13 +1435,29 @@ nsObjectLoadingContent::GetFrame(PRBool aFlushLayout)
}
nsresult
nsObjectLoadingContent::Instantiate(const nsACString& aMIMEType, nsIURI* aURI)
nsObjectLoadingContent::TryInstantiate(const nsACString& aMIMEType,
nsIURI* aURI)
{
nsIObjectFrame* frame = GetFrame(PR_FALSE);
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
}
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);
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
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));
return frame->Instantiate(typeToUse.get(), aURI);
return aFrame->Instantiate(typeToUse.get(), aURI);
}
/* static */ PRBool

View File

@ -284,12 +284,18 @@ class nsObjectLoadingContent : public nsImageLoadingContent
*/
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
* that it ensures that the URI will be non-null, and that a MIME type
* 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

View File

@ -506,11 +506,7 @@ nsObjectFrame::Init(nsIContent* aContent,
mInstantiating = PR_FALSE;
#endif
nsresult rv = 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;
return nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow);
}
void
@ -724,7 +720,6 @@ nsObjectFrame::Reflow(nsPresContext* aPresContext,
return NS_OK;
}
FixupWindow(nsSize(aMetrics.width, aMetrics.height));
aStatus = NS_FRAME_COMPLETE;
@ -776,10 +771,6 @@ nsObjectFrame::InstantiatePlugin(nsIPluginHost* aPluginHost,
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;
}
@ -796,11 +787,17 @@ nsObjectFrame::FixupWindow(const nsSize& aSize)
NS_ENSURE_TRUE(window, /**/);
nsPoint origin;
nsIView *parentWithView;
GetOffsetFromView(origin, &parentWithView);
window->x = presContext->AppUnitsToDevPixels(origin.x);
window->y = presContext->AppUnitsToDevPixels(origin.y);
#ifdef XP_MACOSX
mInstanceOwner->FixUpPluginWindow(ePluginPaintDisable);
#endif
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->height = presContext->AppUnitsToDevPixels(aSize.height);
@ -896,6 +893,15 @@ nsObjectFrame::DidReflow(nsPresContext* aPresContext,
const nsHTMLReflowState* aReflowState,
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);
// 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);
// 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;
}