Backout bcac58cbf328 & 9c75f0428f8a (bug 775965) for causing bug 782981

This commit is contained in:
Ed Morley 2012-08-15 18:10:55 +01:00
parent 4ca9719626
commit 83e4908d83
9 changed files with 49 additions and 217 deletions

@ -288,7 +288,6 @@ NS_INTERFACE_MAP_END
nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
: mOwnerContent(aOwner)
, mDetachedSubdocViews(nullptr)
, mDepthTooGreat(false)
, mIsTopLevelContent(false)
, mDestroyCalled(false)
@ -2378,18 +2377,3 @@ nsFrameLoader::SetRemoteBrowser(nsITabParent* aTabParent)
ShowRemoteFrame(nsIntSize(0, 0));
}
void
nsFrameLoader::SetDetachedSubdocView(nsIView* aDetachedViews,
nsIDocument* aContainerDoc)
{
mDetachedSubdocViews = aDetachedViews;
mContainerDocWhileDetached = aContainerDoc;
}
nsIView*
nsFrameLoader::GetDetachedSubdocView(nsIDocument** aContainerDoc) const
{
NS_IF_ADDREF(*aContainerDoc = mContainerDocWhileDetached);
return mDetachedSubdocViews;
}

@ -268,25 +268,6 @@ public:
*/
void SetRemoteBrowser(nsITabParent* aTabParent);
/**
* Stashes a detached view on the frame loader. We do this when we're
* destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is
* being reframed we'll restore the detached view when it's recreated,
* otherwise we'll discard the old presentation and set the detached
* subdoc view to null. aContainerDoc is the document containing the
* the subdoc frame. This enables us to detect when the containing
* document has changed during reframe, so we can discard the presentation
* in that case.
*/
void SetDetachedSubdocView(nsIView* aDetachedView,
nsIDocument* aContainerDoc);
/**
* Retrieves the detached view and the document containing the view,
* as set by SetDetachedSubdocView().
*/
nsIView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const;
private:
void SetOwnerContent(mozilla::dom::Element* aContent);
@ -345,16 +326,6 @@ public:
nsRefPtr<nsFrameMessageManager> mMessageManager;
nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
private:
// Stores the root view of the subdocument while the subdocument is being
// reframed. Used to restore the presentation after reframing.
nsIView* mDetachedSubdocViews;
// Stores the containing document of the frame corresponding to this
// frame loader. This is reference is kept valid while the subframe's
// presentation is detached and stored in mDetachedSubdocViews. This
// enables us to detect whether the frame has moved documents during
// a reframe, so that we know not to restore the presentation.
nsCOMPtr<nsIDocument> mContainerDocWhileDetached;
bool mDepthTooGreat : 1;
bool mIsTopLevelContent : 1;
bool mDestroyCalled : 1;

@ -2361,13 +2361,13 @@ nsRootPresContext::~nsRootPresContext()
}
void
nsRootPresContext::RegisterPluginForGeometryUpdates(nsIContent* aPlugin)
nsRootPresContext::RegisterPluginForGeometryUpdates(nsObjectFrame* aPlugin)
{
mRegisteredPlugins.PutEntry(aPlugin);
}
void
nsRootPresContext::UnregisterPluginForGeometryUpdates(nsIContent* aPlugin)
nsRootPresContext::UnregisterPluginForGeometryUpdates(nsObjectFrame* aPlugin)
{
mRegisteredPlugins.RemoveEntry(aPlugin);
}
@ -2382,14 +2382,10 @@ struct PluginGeometryClosure {
nsTArray<nsIWidget::Configuration>* mOutputConfigurations;
};
static PLDHashOperator
PluginBoundsEnumerator(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
PluginBoundsEnumerator(nsPtrHashKey<nsObjectFrame>* aEntry, void* userArg)
{
PluginGeometryClosure* closure = static_cast<PluginGeometryClosure*>(userArg);
nsObjectFrame* f = static_cast<nsObjectFrame*>(aEntry->GetKey()->GetPrimaryFrame());
if (!f) {
NS_WARNING("Null frame in PluginBoundsEnumerator");
return PL_DHASH_NEXT;
}
nsObjectFrame* f = aEntry->GetKey();
nsRect fBounds = f->GetContentRect() +
f->GetParent()->GetOffsetToCrossDoc(closure->mRootFrame);
PRInt32 APD = f->PresContext()->AppUnitsPerDevPixel();
@ -2670,13 +2666,9 @@ nsRootPresContext::RequestUpdatePluginGeometry(nsIFrame* aFrame)
}
static PLDHashOperator
PluginDidSetGeometryEnumerator(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
PluginDidSetGeometryEnumerator(nsPtrHashKey<nsObjectFrame>* aEntry, void* userArg)
{
nsObjectFrame* f = static_cast<nsObjectFrame*>(aEntry->GetKey()->GetPrimaryFrame());
if (!f) {
NS_WARNING("Null frame in PluginDidSetGeometryEnumerator");
return PL_DHASH_NEXT;
}
nsObjectFrame* f = aEntry->GetKey();
f->DidSetWidgetGeometry();
return PL_DHASH_NEXT;
}

@ -1227,13 +1227,13 @@ public:
* Callers must call UnregisterPluginForGeometryUpdates before
* the aPlugin frame is destroyed.
*/
void RegisterPluginForGeometryUpdates(nsIContent* aPlugin);
void RegisterPluginForGeometryUpdates(nsObjectFrame* aPlugin);
/**
* Stops a plugin receiving geometry updates (position and clip
* region). If the plugin was not already registered, this does
* nothing.
*/
void UnregisterPluginForGeometryUpdates(nsIContent* aPlugin);
void UnregisterPluginForGeometryUpdates(nsObjectFrame* aPlugin);
/**
* Iterate through all plugins that are registered for geometry updates
@ -1337,7 +1337,7 @@ protected:
nsCOMPtr<nsITimer> mNotifyDidPaintTimer;
nsCOMPtr<nsITimer> mUpdatePluginGeometryTimer;
nsTHashtable<nsRefPtrHashKey<nsIContent> > mRegisteredPlugins;
nsTHashtable<nsPtrHashKey<nsObjectFrame> > mRegisteredPlugins;
// if mNeedsToUpdatePluginGeometry is set, then this is the frame to
// use as the root of the subtree to search for plugin updates, or
// null to use the root frame of this prescontext

@ -431,7 +431,7 @@ nsObjectFrame::PrepForDrawing(nsIWidget *aWidget)
}
#endif
rpc->RegisterPluginForGeometryUpdates(mContent);
rpc->RegisterPluginForGeometryUpdates(this);
rpc->RequestUpdatePluginGeometry(this);
// Here we set the background color for this widget because some plugins will use
@ -451,7 +451,7 @@ nsObjectFrame::PrepForDrawing(nsIWidget *aWidget)
FixupWindow(GetContentRectRelativeToSelf().Size());
#ifndef XP_MACOSX
rpc->RegisterPluginForGeometryUpdates(mContent);
rpc->RegisterPluginForGeometryUpdates(this);
rpc->RequestUpdatePluginGeometry(this);
#endif
}
@ -739,26 +739,32 @@ void
nsObjectFrame::SetInstanceOwner(nsPluginInstanceOwner* aOwner)
{
mInstanceOwner = aOwner;
if (mInstanceOwner) {
return;
}
nsRootPresContext* rpc = PresContext()->GetRootPresContext();
if (rpc) {
rpc->UnregisterPluginForGeometryUpdates(mContent);
}
if (mWidget && mInnerView) {
mInnerView->DetachWidgetEventHandler(mWidget);
// 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);
if (!mInstanceOwner) {
nsRootPresContext* rpc = PresContext()->GetRootPresContext();
if (rpc) {
if (mWidget) {
if (mInnerView) {
mInnerView->DetachWidgetEventHandler(mWidget);
mWidget->Show(false);
mWidget->Enable(false);
mWidget->SetParent(nullptr);
rpc->UnregisterPluginForGeometryUpdates(this);
// Make sure the plugin is hidden in case an update of plugin geometry
// hasn't happened since this plugin became hidden.
nsIWidget* parent = mWidget->GetParent();
if (parent) {
nsTArray<nsIWidget::Configuration> configurations;
this->GetEmptyClipConfiguration(&configurations);
parent->ConfigureChildren(configurations);
mWidget->Show(false);
mWidget->Enable(false);
mWidget->SetParent(nullptr);
}
}
} else {
#ifndef XP_MACOSX
rpc->UnregisterPluginForGeometryUpdates(this);
#endif
}
}
}
}
@ -2213,7 +2219,7 @@ nsObjectFrame::BeginSwapDocShells(nsIContent* aContent, void*)
"Plugin windows must not be toplevel");
nsRootPresContext* rootPC = objectFrame->PresContext()->GetRootPresContext();
NS_ASSERTION(rootPC, "unable to unregister the plugin frame");
rootPC->UnregisterPluginForGeometryUpdates(aContent);
rootPC->UnregisterPluginForGeometryUpdates(objectFrame);
}
/*static*/ void
@ -2239,7 +2245,7 @@ nsObjectFrame::EndSwapDocShells(nsIContent* aContent, void*)
objectFrame->CallSetWindow();
// Register for geometry updates and make a request.
rootPC->RegisterPluginForGeometryUpdates(aContent);
rootPC->RegisterPluginForGeometryUpdates(objectFrame);
rootPC->RequestUpdatePluginGeometry(objectFrame);
}
}

@ -117,12 +117,6 @@ private:
nsWeakFrame mFrame;
};
static void
InsertViewsInReverseOrder(nsIView* aSibling, nsIView* aParent);
static void
EndSwapDocShellsForViews(nsIView* aView);
NS_IMETHODIMP
nsSubDocumentFrame::Init(nsIContent* aContent,
nsIFrame* aParent,
@ -152,28 +146,6 @@ nsSubDocumentFrame::Init(nsIContent* aContent,
}
EnsureInnerView();
// If we have a detached subdoc's root view on our frame loader, re-insert
// it into the view tree. This happens when we've been reframed, and
// ensures the presentation persists across reframes. If the frame element
// has changed documents however, we blow away the presentation.
nsRefPtr<nsFrameLoader> frameloader = FrameLoader();
if (frameloader) {
nsCOMPtr<nsIDocument> oldContainerDoc;
nsIView* detachedViews =
frameloader->GetDetachedSubdocView(getter_AddRefs(oldContainerDoc));
if (detachedViews) {
if (oldContainerDoc == aContent->OwnerDoc()) {
// Restore stashed presentation.
::InsertViewsInReverseOrder(detachedViews, mInnerView);
::EndSwapDocShellsForViews(mInnerView->GetFirstChild());
} else {
// Presentation is for a different document, don't restore it.
frameloader->Hide();
}
}
frameloader->SetDetachedSubdocView(nullptr, nullptr);
}
// Set the primary frame now so that
// DocumentViewerImpl::FindContainerView called by ShowViewer below
// can find it if necessary.
@ -786,49 +758,6 @@ NS_NewSubDocumentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
NS_IMPL_FRAMEARENA_HELPERS(nsSubDocumentFrame)
class nsHideViewer : public nsRunnable {
public:
nsHideViewer(nsIContent* aFrameElement,
nsFrameLoader* aFrameLoader,
nsIPresShell* aPresShell,
bool aHideViewerIfFrameless)
: mFrameElement(aFrameElement),
mFrameLoader(aFrameLoader),
mPresShell(aPresShell),
mHideViewerIfFrameless(aHideViewerIfFrameless)
{
NS_ASSERTION(mFrameElement, "Must have a frame element");
NS_ASSERTION(mFrameLoader, "Must have a frame loader");
NS_ASSERTION(mPresShell, "Must have a presshell");
}
NS_IMETHOD Run()
{
// Flush frames, to ensure any pending display:none changes are made.
// Note it can be unsafe to flush if we've destroyed the presentation
// for some other reason, like if we're shutting down.
if (!mPresShell->IsDestroying()) {
mPresShell->FlushPendingNotifications(Flush_Frames);
}
nsIFrame* frame = mFrameElement->GetPrimaryFrame();
if (!frame && mHideViewerIfFrameless) {
// The frame element has no nsIFrame. Hide the nsFrameLoader,
// which destroys the presentation.
mFrameLoader->SetDetachedSubdocView(nullptr, nullptr);
mFrameLoader->Hide();
}
return NS_OK;
}
private:
nsCOMPtr<nsIContent> mFrameElement;
nsRefPtr<nsFrameLoader> mFrameLoader;
nsCOMPtr<nsIPresShell> mPresShell;
bool mHideViewerIfFrameless;
};
static nsIView*
BeginSwapDocShellsForViews(nsIView* aSibling);
void
nsSubDocumentFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
@ -836,27 +765,19 @@ nsSubDocumentFrame::DestroyFrom(nsIFrame* aDestructRoot)
PresContext()->PresShell()->CancelReflowCallback(this);
mPostedReflowCallback = false;
}
// Detach the subdocument's views and stash them in the frame loader.
// We can then reattach them if we're being reframed (for example if
// the frame has been made position:fixed).
nsFrameLoader* frameloader = FrameLoader();
if (frameloader) {
nsIView* detachedViews = ::BeginSwapDocShellsForViews(mInnerView->GetFirstChild());
frameloader->SetDetachedSubdocView(detachedViews, mContent->OwnerDoc());
// We call nsFrameLoader::HideViewer() in a script runner so that we can
// safely determine whether the frame is being reframed or destroyed.
nsContentUtils::AddScriptRunner(
new nsHideViewer(mContent,
mFrameLoader,
PresContext()->PresShell(),
(mDidCreateDoc || mCallingShow)));
}
HideViewer();
nsLeafFrame::DestroyFrom(aDestructRoot);
}
void
nsSubDocumentFrame::HideViewer()
{
if (mFrameLoader && (mDidCreateDoc || mCallingShow))
mFrameLoader->Hide();
}
nsIntSize
nsSubDocumentFrame::GetMarginAttributes()
{

@ -119,9 +119,8 @@ protected:
virtual int GetSkipSides() const;
// Show our document viewer. The document viewer is hidden via a script
// runner, so that we can save and restore the presentation if we're
// being reframed.
// Hide or show our document viewer
void HideViewer();
void ShowViewer();
/* Obtains the frame we should use for intrinsic size information if we are

@ -14,7 +14,6 @@ include $(DEPTH)/config/autoconf.mk
# in the list below, we make sure that the tests that require focus
# run before test_plugin_clipping, which can steal focus for its window.
MOCHITEST_FILES = \
test_contained_plugin_transplant.html \
bug344830_testembed.svg \
plugin_clipping_helper.xhtml \
plugin_clipping_helper2.xhtml \

@ -1,40 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=775965
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 775965</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body onload="run();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=775965">Mozilla Bug 775965</a>
<p id="display"></p>
<div id="content">
<iframe id="iframe1" src="data:text/html,<embed type='application/x-test' width='200' height='200'></embed>"></iframe>
<iframe id="iframe2"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 775965 **/
SimpleTest.waitForExplicitFinish();
function run() {
var iframe1 = document.getElementById("iframe1");
var iframe2 = document.getElementById("iframe2");
iframe1.parentNode.removeChild(iframe1);
iframe1.style.position = "fixed";
iframe2.contentDocument.body.appendChild(iframe1);
setTimeout(function() { ok(true, "We didn't crash!"); SimpleTest.finish(); }, 0);
}
</script>
</pre>
</body>
</html>