mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-28 21:28:55 +00:00
Make PopupSet registration on the root box frame done by the popupset and add unregistration when the popupset goes away to fix crashes from dangling pointers. b=156719 (and 136513) r=bryner sr=kin
This commit is contained in:
parent
78007eba43
commit
d765859c85
@ -5463,16 +5463,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
|
||||
isReplaced = PR_TRUE;
|
||||
rv = NS_NewPopupSetFrame(aPresShell, &newFrame);
|
||||
((nsPopupSetFrame*) newFrame)->SetFrameConstructor(this);
|
||||
|
||||
// Locate the root frame and tell it about the popupgroup.
|
||||
nsIFrame* rootFrame;
|
||||
aState.mFrameManager->GetRootFrame(&rootFrame);
|
||||
if (rootFrame)
|
||||
rootFrame->FirstChild(aPresContext, nsnull, &rootFrame);
|
||||
nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
|
||||
if (rootBox)
|
||||
rootBox->SetPopupSetFrame(newFrame);
|
||||
|
||||
}
|
||||
else if (aTag == nsXULAtoms::scrollbox) {
|
||||
rv = NS_NewScrollBoxFrame(aPresShell, &newFrame);
|
||||
|
@ -5463,16 +5463,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
|
||||
isReplaced = PR_TRUE;
|
||||
rv = NS_NewPopupSetFrame(aPresShell, &newFrame);
|
||||
((nsPopupSetFrame*) newFrame)->SetFrameConstructor(this);
|
||||
|
||||
// Locate the root frame and tell it about the popupgroup.
|
||||
nsIFrame* rootFrame;
|
||||
aState.mFrameManager->GetRootFrame(&rootFrame);
|
||||
if (rootFrame)
|
||||
rootFrame->FirstChild(aPresContext, nsnull, &rootFrame);
|
||||
nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
|
||||
if (rootBox)
|
||||
rootBox->SetPopupSetFrame(newFrame);
|
||||
|
||||
}
|
||||
else if (aTag == nsXULAtoms::scrollbox) {
|
||||
rv = NS_NewScrollBoxFrame(aPresShell, &newFrame);
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsIRootBox.h"
|
||||
|
||||
#define NS_MENU_POPUP_LIST_INDEX 0
|
||||
|
||||
@ -158,6 +159,16 @@ nsPopupSetFrame::Init(nsIPresContext* aPresContext,
|
||||
{
|
||||
mPresContext = aPresContext; // Don't addref it. Our lifetime is shorter.
|
||||
nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
|
||||
|
||||
nsIFrame *grandParent;
|
||||
aParent->GetParent(&grandParent);
|
||||
nsIRootBox *rootBox;
|
||||
nsresult res = CallQueryInterface(grandParent, &rootBox);
|
||||
NS_ASSERTION(NS_SUCCEEDED(res), "grandparent should be root box");
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
rootBox->SetPopupSetFrame(this);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -177,6 +188,15 @@ nsPopupSetFrame::Destroy(nsIPresContext* aPresContext)
|
||||
}
|
||||
}
|
||||
|
||||
nsIFrame *grandParent;
|
||||
mParent->GetParent(&grandParent);
|
||||
nsIRootBox *rootBox;
|
||||
nsresult res = CallQueryInterface(grandParent, &rootBox);
|
||||
NS_ASSERTION(NS_SUCCEEDED(res), "grandparent should be root box");
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
rootBox->SetPopupSetFrame(nsnull);
|
||||
}
|
||||
|
||||
return nsBoxFrame::Destroy(aPresContext);
|
||||
}
|
||||
|
||||
|
@ -289,9 +289,19 @@ nsRootBoxFrame::GetPopupSetFrame(nsIFrame** aResult)
|
||||
NS_IMETHODIMP
|
||||
nsRootBoxFrame::SetPopupSetFrame(nsIFrame* aPopupSet)
|
||||
{
|
||||
NS_ASSERTION(!mPopupSetFrame, "Popup set is already defined! Only 1 allowed.");
|
||||
if (!mPopupSetFrame)
|
||||
// Under normal conditions this should only be called once. However,
|
||||
// if something triggers ReconstructDocElementHierarchy, we will
|
||||
// destroy this frame's child (the nsDocElementBoxFrame), but not this
|
||||
// frame. This will cause the popupset to remove itself by calling
|
||||
// |SetPopupSetFrame(nsnull)|, and then we'll be able to accept a new
|
||||
// popupset. Since the anonymous content is associated with the
|
||||
// nsDocElementBoxFrame, we'll get a new popupset when the new doc
|
||||
// element box frame is created.
|
||||
if (!mPopupSetFrame || !aPopupSet) {
|
||||
mPopupSetFrame = aPopupSet;
|
||||
} else {
|
||||
NS_NOTREACHED("Popup set is already defined! Only 1 allowed.");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user