Regression-Fix (Re: security patches 1.5.0.9/2.0.0.1 issues for 1.7
branch)
Alexander Sack
asac at jwsdot.com
Tue Jan 16 01:29:40 CET 2007
Eric Dorland wrote:
> * Alexander Sack (asac at debian.org) wrote:
>> Hi,
>>
>> somehow late, but here they are :):
>>
>> I uploaded 1.7 branch backports for issues announced with
>> 1.5.0.9/2.0.0.1 release.
>>
>> Note: Everything, but mfsa2006-74, does apply to firefox.
>>
>> Current patches can be found at:
>> http://people.debian.org/~asac/backports-1.5.0.9.tar.gz
>>
>> Eric/Mike, can you prepare a firefox update and make it available
>> somewhere?
>
> Untested builds are up at http://people.debian.org/~eric/mozilla. I'll
> let you blog about it Alexander, I'm going to bed.
>
OK, as you know there has been a regression. Unfortunately, it was not mailnews
only, but a general xul regression due to code I uncommented for testing and
just forgot to revert that later. Anyway, though we haven't had explicit reports
for crashes of updated mozilla-firefox, it definitly needs an update too before
we can release.
To summarize: All packages need a new upload to security queue.
Attached you find the updated patch:
- 0015-MFSA-2006-68-CVE-2006-6497-Part-3-348304-with-regression.txt
which replaces the patch
- 0015-MFSA-2006-68-CVE-2006-6497-Part-3-348304.txt
previously released.
For mozilla-firefox, the -regression-interdiff patch should apply to svn sarge
branch. Eric, you have time to provide package updates?
- Alexander
--
GPG messages preferred. | .''`. ** Debian GNU/Linux **
Alexander Sack | : :' : The universal
asac at jwsdot.com | `. `' Operating System
http://www.asoftsite.org | `- http://www.debian.org/
-------------- next part --------------
diff -u b/layout/xul/base/src/nsMenuFrame.cpp b/layout/xul/base/src/nsMenuFrame.cpp
--- b/layout/xul/base/src/nsMenuFrame.cpp
+++ b/layout/xul/base/src/nsMenuFrame.cpp
@@ -2049,12 +2049,11 @@
nsASyncMenuGeneration(nsIFrame* aFrame)
: mWeakFrame(aFrame)
{
- // XXX: asac: implement this properly
- // nsIContent* content = aFrame ? aFrame->GetContent() : nsnull;
- // mDocument = content ? content->GetDocument() : nsnull;
+ nsIContent* content = aFrame ? aFrame->GetContent() : nsnull;
+ mDocument = content ? content->GetDocument() : nsnull;
if (mDocument) {
nsCOMPtr<nsIDocument_MOZILLA_1_7_BRANCH> doc17(do_QueryInterface(mDocument));
- //doc17->BlockOnload();
+ doc17->BlockOnload();
}
}
@@ -2076,7 +2075,7 @@
}
if (mDocument) {
nsCOMPtr<nsIDocument_MOZILLA_1_7_BRANCH> doc17(do_QueryInterface(mDocument));
-// doc17->UnblockOnload();
+ doc17->UnblockOnload();
}
}
-------------- next part --------------
From 75b9e9f0e7b569e2ccb2acb2eada552911231efb Mon Sep 17 00:00:00 2001
From: Alexander Sack <asac at hanson.localdomain>
Date: Mon, 8 Jan 2007 03:40:38 +0100
Subject: [PATCH] MFSA 2006-68; CVE-2006-6497; Part 3; 348304
---
content/base/public/nsIDocument.h | 22 +++
content/base/src/nsDocument.cpp | 92 +++++++++++++
content/base/src/nsDocument.h | 21 +++-
content/xul/content/src/nsXULElement.cpp | 172 ++++++++++++++----------
layout/xul/base/src/nsMenuBarFrame.cpp | 63 ++++++++--
layout/xul/base/src/nsMenuFrame.cpp | 212 ++++++++++++++++++++++++++----
layout/xul/base/src/nsMenuFrame.h | 1 +
layout/xul/base/src/nsMenuPopupFrame.cpp | 73 ++++++++++-
8 files changed, 544 insertions(+), 112 deletions(-)
diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h
index 529cfe2..5e523fa 100644
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -92,6 +92,10 @@ class nsIHTMLCSSStyleSheet;
{ 0x3000c2a4, 0xf7f1, 0x4636, \
{0x9c, 0x6e, 0xd5, 0x38, 0x1b, 0xf0, 0x18, 0x8a} }
+#define NS_IDOCUMENT_MOZILLA_1_7_BRANCH_IID \
+{ 0x8c0ccaeb, 0x0b83, 0x46ee, \
+ { 0xbe, 0x2c, 0xbe, 0xf6, 0x32, 0xb6, 0x5b, 0xa0 } }
+
// The base value for the content ID counter.
// This counter is used by the document to
// assign a monotonically increasing ID to each content
@@ -628,6 +632,24 @@ protected:
nsCOMPtr<nsISupports> mSecurityInfo;
};
+class nsIDocument_MOZILLA_1_7_BRANCH : public nsIDocument
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_MOZILLA_1_7_BRANCH_IID)
+
+ /**
+ * [asac: backported from 1.8 branch]
+ * Methods that can be used to prevent onload firing while an event that
+ * should block onload is posted. onload is guaranteed to not fire until
+ * either all calls to BlockOnload() have been matched by calls to
+ * UnblockOnload() or the load has been stopped altogether (by the user
+ * pressing the Stop button, say). onload may fire synchronously from inside
+ * the UnblockOnload() call.
+ */
+ virtual void BlockOnload() = 0;
+ virtual void UnblockOnload() = 0;
+};
+
/**
* Helper class to automatically handle batching of document updates. This
diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp
index 1495a1f..2133306 100644
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -272,6 +272,65 @@ nsDOMStyleSheetList::StyleSheetRemoved(nsIDocument *aDocument,
}
}
+NS_IMPL_ISUPPORTS1(nsOnloadBlocker, nsIRequest)
+
+NS_IMETHODIMP
+nsOnloadBlocker::GetName(nsACString &aResult)
+{
+ aResult = "about:document-onload-blocker";
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsOnloadBlocker::IsPending(PRBool *_retval)
+{
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsOnloadBlocker::GetStatus(nsresult *status)
+{
+ *status = NS_OK;
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsOnloadBlocker::Cancel(nsresult status)
+{
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsOnloadBlocker::Suspend(void)
+{
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsOnloadBlocker::Resume(void)
+{
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsOnloadBlocker::GetLoadGroup(nsILoadGroup * *aLoadGroup)
+{
+ *aLoadGroup = nsnull;
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsOnloadBlocker::SetLoadGroup(nsILoadGroup * aLoadGroup)
+{
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsOnloadBlocker::GetLoadFlags(nsLoadFlags *aLoadFlags)
+{
+ *aLoadFlags = nsIRequest::LOAD_NORMAL;
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsOnloadBlocker::SetLoadFlags(nsLoadFlags aLoadFlags)
+{
+ return NS_OK;
+}
+
+
class nsDOMImplementation : public nsIDOMDOMImplementation,
public nsIPrivateDOMImplementation
@@ -630,6 +689,7 @@ PRBool gHaveXPathDOM = PR_FALSE;
NS_INTERFACE_MAP_BEGIN(nsDocument)
NS_INTERFACE_MAP_ENTRY(nsIDocument)
+ NS_INTERFACE_MAP_ENTRY(nsIDocument_MOZILLA_1_7_BRANCH)
NS_INTERFACE_MAP_ENTRY(nsIDOMDocument)
NS_INTERFACE_MAP_ENTRY(nsIDOMNSDocument)
NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentEvent)
@@ -691,6 +751,9 @@ nsDocument::Init()
mNodeInfoManager = new nsNodeInfoManager();
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY);
+ mOnloadBlocker = new nsOnloadBlocker();
+ NS_ENSURE_TRUE(mOnloadBlocker, NS_ERROR_OUT_OF_MEMORY);
+
return mNodeInfoManager->Init(this);
}
@@ -3904,6 +3967,35 @@ nsDocument::RemoveEventListener(const nsAString& aType,
return RemoveGroupedEventListener(aType, aListener, aUseCapture, nsnull);
}
+void
+nsDocument::BlockOnload()
+{
+ if (mOnloadBlockCount == 0) {
+ nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
+ if (loadGroup) {
+ loadGroup->AddRequest(mOnloadBlocker, nsnull);
+ }
+ }
+ ++mOnloadBlockCount;
+}
+
+void
+nsDocument::UnblockOnload()
+{
+ if (mOnloadBlockCount == 0) {
+ return;
+ }
+
+ --mOnloadBlockCount;
+
+ if (mOnloadBlockCount == 0) {
+ nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
+ if (loadGroup) {
+ loadGroup->RemoveRequest(mOnloadBlocker, nsnull, NS_OK);
+ }
+ }
+}
+
NS_IMETHODIMP
nsDocument::DispatchEvent(nsIDOMEvent* aEvent, PRBool *_retval)
{
diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h
index 85b2a9e..f9db18e 100644
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -104,7 +104,7 @@ class nsIRadioVisitor;
class nsIFormControl;
class nsStyleSet;
struct nsRadioGroupStruct;
-
+class nsOnloadBlocker;
class nsDocHeaderData
{
@@ -168,6 +168,17 @@ protected:
void* mScriptObject;
};
+class nsOnloadBlocker : public nsIRequest
+{
+public:
+ nsOnloadBlocker() {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIREQUEST
+
+private:
+ ~nsOnloadBlocker() {}
+};
// Base class for our document implementations.
//
@@ -178,7 +189,7 @@ protected:
// nsIDOMXMLDocument's. nsDocument's QI should *not* claim to support
// nsIDOMXMLDocument unless someone writes a real implementation of
// the interface.
-class nsDocument : public nsIDocument,
+class nsDocument : public nsIDocument_MOZILLA_1_7_BRANCH,
public nsIDOMXMLDocument, // inherits nsIDOMDocument
public nsIDOMNSDocument,
public nsIDOMDocumentEvent,
@@ -199,6 +210,9 @@ class nsDocument : public nsIDocument,
public:
NS_DECL_ISUPPORTS
+ virtual void BlockOnload();
+ virtual void UnblockOnload();
+
virtual void Reset(nsIChannel *aChannel, nsILoadGroup *aLoadGroup);
virtual void ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup);
@@ -592,6 +606,9 @@ private:
nsDocument& operator=(const nsDocument& aOther);
nsXPathDocumentTearoff* mXPathDocument;
+
+ PRUint32 mOnloadBlockCount;
+ nsCOMPtr<nsIRequest> mOnloadBlocker;
};
diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp
index 8686ecd..ad077ac 100644
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -619,18 +619,19 @@ nsXULElement::GetNodeType(PRUint16* aNodeType)
NS_IMETHODIMP
nsXULElement::GetParentNode(nsIDOMNode** aParentNode)
{
+ nsCOMPtr<nsIDocument> doc = mDocument; // hard ref
if (GetParent()) {
return CallQueryInterface(GetParent(), aParentNode);
}
- if (mDocument) {
+ if (doc) {
nsIContent *thisIContent = this;
- if (mDocument->GetRootContent() == thisIContent) {
+ if (doc->GetRootContent() == thisIContent) {
// If we don't have a parent, and we're the root content
// of the document, DOM says that our parent is the
// document.
- return CallQueryInterface(mDocument, aParentNode);
+ return CallQueryInterface(doc, aParentNode);
}
}
@@ -885,6 +886,7 @@ nsXULElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
nsresult rv;
nsCOMPtr<nsIContent> result;
+ nsCOMPtr<nsIDocument> doc = mDocument;
// If we have a prototype, so will our clone.
if (mPrototype) {
@@ -900,7 +902,7 @@ nsXULElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
// XXX setting document on nodes not in a document so XBL will bind
// and chrome won't break. Make XBL bind to document-less nodes!
- result->SetDocument(mDocument, PR_TRUE, PR_TRUE);
+ result->SetDocument(doc, PR_TRUE, PR_TRUE);
}
// Copy attributes
@@ -1373,7 +1375,8 @@ nsXULElement::GetLazyState(LazyState aFlag, PRBool& aResult)
NS_IMETHODIMP
nsXULElement::AddScriptEventListener(nsIAtom* aName, const nsAString& aValue)
{
- if (! mDocument)
+ nsCOMPtr<nsIDocument> doc = mDocument;
+ if (! doc)
return NS_OK; // XXX
nsresult rv;
@@ -1383,10 +1386,10 @@ nsXULElement::AddScriptEventListener(nsIAtom* aName, const nsAString& aValue)
nsCOMPtr<nsIEventListenerManager> manager;
- nsIContent *root = mDocument->GetRootContent();
+ nsIContent *root = doc->GetRootContent();
nsCOMPtr<nsIContent> content(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)));
if ((!root || root == content) && !NodeInfo()->Equals(nsXULAtoms::overlay)) {
- nsIScriptGlobalObject *global = mDocument->GetScriptGlobalObject();
+ nsIScriptGlobalObject *global = doc->GetScriptGlobalObject();
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(global);
if (! receiver)
@@ -1404,7 +1407,7 @@ nsXULElement::AddScriptEventListener(nsIAtom* aName, const nsAString& aValue)
if (NS_FAILED(rv)) return rv;
return manager->AddScriptEventListener(target, aName, aValue, defer,
- !nsContentUtils::IsChromeDoc(mDocument));
+ !nsContentUtils::IsChromeDoc(doc));
}
nsresult
@@ -1456,6 +1459,8 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
nsresult rv;
JSObject* scopeObject;
+ nsCOMPtr<nsIDocument> doc = mDocument;
+
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheSets);
nsIScriptContext *context;
@@ -1472,7 +1477,7 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
// keeps the global object alive, so if we use this document's
// global object, we'll be putting something in the prototype
// that protects this document's global object from GC.
- nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mDocument);
+ nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
NS_ENSURE_TRUE(xuldoc, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIXULPrototypeDocument> protodoc;
@@ -1574,17 +1579,19 @@ void
nsXULElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
{
- if (aDocument != mDocument) {
- if (mDocument) {
+ nsCOMPtr<nsIDocument> doc = mDocument;
+
+ if (aDocument != doc) {
+ if (doc) {
// Notify XBL- & nsIAnonymousContentCreator-generated
// anonymous content that the document is changing.
- nsIBindingManager *bindingManager = mDocument->GetBindingManager();
+ nsIBindingManager *bindingManager = doc->GetBindingManager();
NS_ASSERTION(bindingManager, "no binding manager");
if (bindingManager) {
- bindingManager->ChangeDocumentFor(this, mDocument, aDocument);
+ bindingManager->ChangeDocumentFor(this, doc, aDocument);
}
- nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(mDocument));
+ nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(doc));
nsDoc->SetBoxObjectFor(this, nsnull);
}
@@ -1608,8 +1615,9 @@ nsXULElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
mListenerManager = nsnull;
nsIContent::SetDocument(aDocument, aDeep, aCompileEventHandlers);
+ doc = mDocument;
- if (mDocument) {
+ if (doc) {
// When we SetDocument(), we're either adding an element
// into the document that wasn't there before, or we're
// moving the element from one document to
@@ -1711,6 +1719,7 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
{
nsresult rv = EnsureContentsGenerated();
NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIDocument> doc = mDocument;
NS_PRECONDITION(nsnull != aKid, "null ptr");
@@ -1722,7 +1731,7 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
PRBool isAppend = aIndex == mAttrsAndChildren.ChildCount();
- mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify);
+ mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
if (aIndex > mAttrsAndChildren.ChildCount()) {
// XXX This *does* happen, probably a bug in the overlay code.
@@ -1736,14 +1745,14 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
aKid->SetParent(this);
//nsRange::OwnerChildInserted(this, aIndex);
- if (mDocument) {
- aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE);
+ if (doc) {
+ aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE);
if (aNotify) {
if (isAppend) {
- mDocument->ContentAppended(this, aIndex);
+ doc->ContentAppended(this, aIndex);
} else {
- mDocument->ContentInserted(this, aKid, aIndex);
+ doc->ContentInserted(this, aKid, aIndex);
}
}
@@ -1769,6 +1778,7 @@ nsXULElement::ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
{
nsresult rv = EnsureContentsGenerated();
NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIDocument> doc = mDocument;
NS_PRECONDITION(nsnull != aKid, "null ptr");
if (!aKid)
@@ -1783,18 +1793,18 @@ nsXULElement::ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
if (oldKid == aKid)
return NS_OK;
- mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify);
+ mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
mAttrsAndChildren.ReplaceChildAt(aKid, aIndex);
aKid->SetParent(this);
//nsRange::OwnerChildReplaced(this, aIndex, oldKid);
- if (mDocument) {
- aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE);
+ if (doc) {
+ aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE);
if (aNotify) {
- mDocument->ContentReplaced(this, oldKid, aKid, aIndex);
+ doc->ContentReplaced(this, oldKid, aKid, aIndex);
}
if (HasMutationListeners(this,
NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED)) {
@@ -1823,10 +1833,11 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify,
{
nsresult rv = EnsureContentsGenerated();
NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIDocument> doc = mDocument;
NS_PRECONDITION((nsnull != aKid) && (aKid != NS_STATIC_CAST(nsIStyledContent*, this)), "null ptr");
- mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify);
+ mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
rv = mAttrsAndChildren.AppendChild(aKid);
NS_ENSURE_SUCCESS(rv, rv);
@@ -1834,11 +1845,11 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify,
aKid->SetParent(this);
// ranges don't need adjustment since new child is at end of list
- if (mDocument) {
- aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE);
+ if (doc) {
+ aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE);
if (aNotify) {
- mDocument->ContentAppended(this,
+ doc->ContentAppended(this,
mAttrsAndChildren.ChildCount() - 1);
}
@@ -1861,6 +1872,7 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
nsresult rv = EnsureContentsGenerated();
NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIDocument> doc = mDocument;
nsCOMPtr<nsIContent> oldKid = mAttrsAndChildren.ChildAt(aIndex);
NS_ENSURE_TRUE(oldKid, NS_ERROR_FAILURE);
@@ -1869,7 +1881,7 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
nsMutationGuard guard;
- mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify);
+ mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEREMOVED, oldKid);
@@ -1949,8 +1961,8 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
mAttrsAndChildren.RemoveChildAt(aIndex);
//nsRange::OwnerChildRemoved(this, aIndex, oldKid);
- if (aNotify && mDocument) {
- mDocument->ContentRemoved(this, oldKid, aIndex);
+ if (aNotify && doc) {
+ doc->ContentRemoved(this, oldKid, aIndex);
}
if (newCurrentIndex == -2)
@@ -1972,7 +1984,7 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
}
if (fireSelectionHandler && GetDocument()) {
- nsCOMPtr<nsIDOMDocumentEvent> doc(do_QueryInterface(mDocument));
+ nsCOMPtr<nsIDOMDocumentEvent> doc(do_QueryInterface(doc));
nsCOMPtr<nsIDOMEvent> event;
doc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
@@ -2033,10 +2045,11 @@ nsXULElement::GetExistingAttrNameFromQName(const nsAString& aStr) const
void
nsXULElement::UnregisterAccessKey(const nsAString& aOldValue)
{
+ nsCOMPtr<nsIDocument> doc = mDocument;
// If someone changes the accesskey, unregister the old one
//
- if (mDocument && !aOldValue.IsEmpty()) {
- nsIPresShell *shell = mDocument->GetShellAt(0);
+ if (doc && !aOldValue.IsEmpty()) {
+ nsIPresShell *shell = doc->GetShellAt(0);
if (shell) {
PRBool validElement = PR_TRUE;
@@ -2072,11 +2085,13 @@ nsresult
nsXULElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, PRBool aNotify)
{
+ nsCOMPtr<nsIDocument> doc = mDocument;
+
nsAutoString oldValue;
PRBool hasListeners = PR_FALSE;
PRBool modification = PR_FALSE;
- if (mDocument) {
+ if (doc) {
PRBool isAccessKey = aName == nsXULAtoms::accesskey &&
aNamespaceID == kNameSpaceID_None;
hasListeners = nsGenericElement::HasMutationListeners(this,
@@ -2180,9 +2195,11 @@ nsXULElement::SetAttrAndNotify(PRInt32 aNamespaceID,
NS_STATIC_CAST(PRUint8, nsIDOMMutationEvent::MODIFICATION) :
NS_STATIC_CAST(PRUint8, nsIDOMMutationEvent::ADDITION);
- mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify);
- if (aNotify && mDocument) {
- mDocument->AttributeWillChange(this, aNamespaceID, aAttribute);
+ nsCOMPtr<nsIDocument> doc = mDocument;
+
+ mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
+ if (aNotify && doc) {
+ doc->AttributeWillChange(this, aNamespaceID, aAttribute);
}
if (aNamespaceID == kNameSpaceID_None) {
@@ -2200,9 +2217,9 @@ nsXULElement::SetAttrAndNotify(PRInt32 aNamespaceID,
NS_ENSURE_SUCCESS(rv, rv);
}
- if (mDocument) {
+ if (doc) {
nsCOMPtr<nsIXBLBinding> binding;
- mDocument->GetBindingManager()->GetBinding(this, getter_AddRefs(binding));
+ doc->GetBindingManager()->GetBinding(this, getter_AddRefs(binding));
if (binding) {
binding->AttributeChanged(aAttribute, aNamespaceID, PR_FALSE, aNotify);
}
@@ -2237,7 +2254,7 @@ nsXULElement::SetAttrAndNotify(PRInt32 aNamespaceID,
}
if (aNotify) {
- mDocument->AttributeChanged(this, aNamespaceID, aAttribute, modType);
+ doc->AttributeChanged(this, aNamespaceID, aAttribute, modType);
}
}
@@ -2307,6 +2324,7 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
{
NS_ASSERTION(nsnull != aName, "must have attribute name");
nsresult rv;
+ nsCOMPtr<nsIDocument> doc = mDocument;
// Because It's Hard to maintain a magic ``unset'' value in
// the local attributes, we'll fault all the attributes,
@@ -2343,9 +2361,9 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
nsAutoString oldValue;
GetAttr(aNameSpaceID, aName, oldValue);
- mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify);
- if (aNotify && mDocument) {
- mDocument->AttributeWillChange(this, aNameSpaceID, aName);
+ mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
+ if (aNotify && doc) {
+ doc->AttributeWillChange(this, aNameSpaceID, aName);
}
PRBool hasMutationListeners =
@@ -2379,13 +2397,13 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
// Check to see if the OBSERVES attribute is being unset. If so, we
// need to remove our broadcaster goop completely.
- if (mDocument && (aName == nsXULAtoms::observes ||
- aName == nsXULAtoms::command)) {
- nsCOMPtr<nsIDOMXULDocument> xuldoc = do_QueryInterface(mDocument);
+ if (doc && (aName == nsXULAtoms::observes ||
+ aName == nsXULAtoms::command)) {
+ nsCOMPtr<nsIDOMXULDocument> xuldoc = do_QueryInterface(doc);
if (xuldoc) {
// Do a getElementById to retrieve the broadcaster
nsCOMPtr<nsIDOMElement> broadcaster;
- nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
+ nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc);
domDoc->GetElementById(oldValue, getter_AddRefs(broadcaster));
if (broadcaster) {
xuldoc->RemoveBroadcastListenerFor(broadcaster, this,
@@ -2395,7 +2413,7 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
}
}
- if (mDocument) {
+ if (doc) {
if (hasMutationListeners) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this)));
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_ATTRMODIFIED, node);
@@ -2413,12 +2431,12 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
}
nsCOMPtr<nsIXBLBinding> binding;
- mDocument->GetBindingManager()->GetBinding(this, getter_AddRefs(binding));
+ doc->GetBindingManager()->GetBinding(this, getter_AddRefs(binding));
if (binding)
binding->AttributeChanged(aName, aNameSpaceID, PR_TRUE, aNotify);
if (aNotify) {
- mDocument->AttributeChanged(this, aNameSpaceID, aName,
+ doc->AttributeChanged(this, aNameSpaceID, aName,
nsIDOMMutationEvent::REMOVAL);
}
}
@@ -2550,6 +2568,7 @@ nsXULElement::List(FILE* out, PRInt32 aIndent) const
NS_PRECONDITION(mDocument != nsnull, "bad content");
PRUint32 i;
+ nsCOMPtr<nsIDocument> doc = mDocument;
rdf_Indent(out, aIndent);
fputs("<XUL", out);
@@ -2605,8 +2624,8 @@ nsXULElement::List(FILE* out, PRInt32 aIndent) const
}
fputs(">\n", out);
- if (mDocument) {
- nsIBindingManager *bindingManager = mDocument->GetBindingManager();
+ if (doc) {
+ nsIBindingManager *bindingManager = doc->GetBindingManager();
if (bindingManager) {
nsCOMPtr<nsIDOMNodeList> anonymousChildren;
bindingManager->GetAnonymousNodesFor(NS_STATIC_CAST(nsIContent*, NS_CONST_CAST(nsXULElement*, this)),
@@ -2677,6 +2696,7 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent,
PRBool retarget = PR_FALSE;
PRBool externalDOMEvent = PR_FALSE;
nsCOMPtr<nsIDOMEventTarget> oldTarget;
+ nsCOMPtr<nsIDocument> doc = mDocument;
nsIDOMEvent* domEvent = nsnull;
if (NS_EVENT_FLAG_INIT & aFlags) {
@@ -2686,7 +2706,7 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent,
nsAutoString command;
GetAttr(kNameSpaceID_None, nsXULAtoms::command, command);
if (!command.IsEmpty()) {
- nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(mDocument));
+ nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
nsCOMPtr<nsIDOMElement> commandElt;
domDoc->GetElementById(command, getter_AddRefs(commandElt));
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
@@ -2785,8 +2805,8 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent,
// determine the parent:
nsCOMPtr<nsIContent> parent;
- if (mDocument) {
- nsIBindingManager* bindingManager = mDocument->GetBindingManager();
+ if (doc) {
+ nsIBindingManager* bindingManager = doc->GetBindingManager();
if (bindingManager) {
// we have a binding manager -- do we have an anonymous parent?
bindingManager->GetInsertionParent(this, getter_AddRefs(parent));
@@ -2842,8 +2862,8 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent,
if (parent) {
parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags & NS_EVENT_CAPTURE_MASK, aEventStatus);
}
- else if (mDocument != nsnull) {
- ret = mDocument->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
+ else if (doc != nsnull) {
+ ret = doc->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_CAPTURE_MASK, aEventStatus);
}
}
@@ -2881,10 +2901,10 @@ nsXULElement::HandleDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent,
ret = parent->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_BUBBLE_MASK, aEventStatus);
}
- else if (mDocument != nsnull) {
+ else if (doc != nsnull) {
// We must be the document root. The event should bubble to the
// document.
- ret = mDocument->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
+ ret = doc->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags & NS_EVENT_BUBBLE_MASK, aEventStatus);
}
}
@@ -2943,9 +2963,10 @@ nsXULElement::GetBaseURI() const
{
// XXX TODO, should share the impl with nsGenericElement
nsIURI *base;
+ nsCOMPtr<nsIDocument> doc = mDocument;
- if (mDocument) {
- base = mDocument->GetBaseURI();
+ if (doc) {
+ base = doc->GetBaseURI();
NS_IF_ADDREF(base);
} else {
base = nsnull;
@@ -3281,9 +3302,11 @@ nsXULElement::GetClassAttributeName() const
NS_IMETHODIMP
nsXULElement::GetControllers(nsIControllers** aResult)
{
+ nsCOMPtr<nsIDocument> doc = mDocument;
+
if (! Controllers()) {
- NS_PRECONDITION(mDocument != nsnull, "no document");
- if (! mDocument)
+ NS_PRECONDITION(doc != nsnull, "no document");
+ if (! doc)
return NS_ERROR_NOT_INITIALIZED;
nsresult rv;
@@ -3295,7 +3318,7 @@ nsXULElement::GetControllers(nsIControllers** aResult)
if (NS_FAILED(rv)) return rv;
// Set the command dispatcher on the new controllers object
- nsCOMPtr<nsIDOMXULDocument> domxuldoc = do_QueryInterface(mDocument);
+ nsCOMPtr<nsIDOMXULDocument> domxuldoc = do_QueryInterface(doc);
NS_ASSERTION(domxuldoc != nsnull, "not an nsIDOMXULDocument");
if (! domxuldoc)
return NS_ERROR_UNEXPECTED;
@@ -3317,11 +3340,12 @@ NS_IMETHODIMP
nsXULElement::GetBoxObject(nsIBoxObject** aResult)
{
*aResult = nsnull;
+ nsCOMPtr<nsIDocument> doc = mDocument;
- if (!mDocument)
+ if (!doc)
return NS_ERROR_FAILURE;
- nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(mDocument));
+ nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(doc));
return nsDoc->GetBoxObjectFor(this, aResult);
}
@@ -3811,19 +3835,20 @@ nsXULElement::IsAncestor(nsIDOMNode* aParentNode, nsIDOMNode* aChildNode)
NS_IMETHODIMP
nsXULElement::Focus()
{
+ nsCOMPtr<nsIDocument> doc = mDocument;
if (!nsGenericElement::ShouldFocus(this)) {
return NS_OK;
}
// What kind of crazy tries to focus an element without a doc?
- if (!mDocument)
+ if (!doc)
return NS_OK;
// Obtain a presentation context and then call SetFocus.
- if (mDocument->GetNumberOfShells() == 0)
+ if (doc->GetNumberOfShells() == 0)
return NS_OK;
- nsIPresShell *shell = mDocument->GetShellAt(0);
+ nsIPresShell *shell = doc->GetShellAt(0);
// Retrieve the context
nsCOMPtr<nsIPresContext> presContext;
@@ -3838,15 +3863,16 @@ nsXULElement::Focus()
NS_IMETHODIMP
nsXULElement::Blur()
{
+ nsCOMPtr<nsIDocument> doc = mDocument;
// What kind of crazy tries to blur an element without a doc?
- if (!mDocument)
+ if (!doc)
return NS_OK;
// Obtain a presentation context and then call SetFocus.
- if (mDocument->GetNumberOfShells() == 0)
+ if (doc->GetNumberOfShells() == 0)
return NS_OK;
- nsIPresShell *shell = mDocument->GetShellAt(0);
+ nsIPresShell *shell = doc->GetShellAt(0);
// Retrieve the context
nsCOMPtr<nsIPresContext> presContext;
diff --git a/layout/xul/base/src/nsMenuBarFrame.cpp b/layout/xul/base/src/nsMenuBarFrame.cpp
index c23aeff..d408d76 100644
--- a/layout/xul/base/src/nsMenuBarFrame.cpp
+++ b/layout/xul/base/src/nsMenuBarFrame.cpp
@@ -373,11 +373,21 @@ nsMenuBarFrame::ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFl
nsIMenuFrame* result = FindMenuWithShortcut(aKeyEvent);
if (result) {
// We got one!
+ nsWeakFrame weakFrame(this);
+ nsIFrame* frame = nsnull;
+ CallQueryInterface(result, &frame);
+ nsWeakFrame weakResult(frame);
aHandledFlag = PR_TRUE;
SetActive(PR_TRUE);
- SetCurrentMenuItem(result);
- result->OpenMenu(PR_TRUE);
- result->SelectFirstItem();
+ if (weakFrame.IsAlive()) {
+ SetCurrentMenuItem(result);
+ }
+ if (weakResult.IsAlive()) {
+ result->OpenMenu(PR_TRUE);
+ if (weakResult.IsAlive()) {
+ result->SelectFirstItem();
+ }
+ }
}
return NS_OK;
@@ -391,6 +401,7 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
if (!mCurrentMenu)
return NS_OK;
+ nsWeakFrame weakFrame(this);
PRBool isContainer = PR_FALSE;
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsContainer(isContainer);
@@ -414,8 +425,13 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
GetNextMenuItem(mCurrentMenu, &nextItem);
else GetPreviousMenuItem(mCurrentMenu, &nextItem);
- SetCurrentMenuItem(nextItem);
+ nsIFrame* nextFrame = nsnull;
if (nextItem) {
+ CallQueryInterface(nextItem, &nextFrame);
+ }
+ nsWeakFrame weakNext(nextFrame);
+ SetCurrentMenuItem(nextItem);
+ if (weakNext.IsAlive()) {
PRBool nextIsOpen;
nextItem->MenuIsOpen(nextIsOpen);
if (nextIsOpen) {
@@ -428,6 +444,16 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
// Open the menu and select its first item.
mCurrentMenu->OpenMenu(PR_TRUE);
mCurrentMenu->SelectFirstItem();
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
+ nsIFrame* frame = nsnull;
+ CallQueryInterface(mCurrentMenu, &frame);
+ nsWeakFrame weakCurrentMenu(frame);
+ nsIMenuFrame* currentMenu = mCurrentMenu;
+ // Open the menu and select its first item.
+ currentMenu->OpenMenu(PR_TRUE);
+ if (weakCurrentMenu.IsAlive()) {
+ currentMenu->SelectFirstItem();
+ }
}
return NS_OK;
@@ -555,18 +581,31 @@ NS_IMETHODIMP nsMenuBarFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
if (nsMenuFrame::IsContextMenuActive())
return NS_OK;
+ nsWeakFrame weakFrame(this);
+
// Unset the current child.
if (mCurrentMenu) {
- mCurrentMenu->MenuIsOpen(wasOpen);
- mCurrentMenu->SelectMenu(PR_FALSE);
- if (wasOpen)
- mCurrentMenu->OpenMenu(PR_FALSE);
+ nsIFrame* frame = nsnull;
+ CallQueryInterface(mCurrentMenu, &frame);
+ nsWeakFrame weakCurrentMenu(frame);
+ nsIMenuFrame* currentMenu = mCurrentMenu;
+ currentMenu->MenuIsOpen(wasOpen);
+ currentMenu->SelectMenu(PR_FALSE);
+ if (wasOpen && weakCurrentMenu.IsAlive()) {
+ currentMenu->OpenMenu(PR_FALSE);
+ }
}
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
// Set the new child.
if (aMenuItem) {
+ nsIFrame* newMenu = nsnull;
+ CallQueryInterface(aMenuItem, &newMenu);
+ nsWeakFrame weakNewMenu(newMenu);
aMenuItem->SelectMenu(PR_TRUE);
+ NS_ENSURE_TRUE(weakNewMenu.IsAlive(), NS_OK);
aMenuItem->MarkAsGenerated(); // Have the menu building. Get it ready to be shown.
+ NS_ENSURE_TRUE(weakNewMenu.IsAlive(), NS_OK);
PRBool isDisabled = PR_FALSE;
aMenuItem->MenuIsDisabled(isDisabled);
@@ -575,6 +614,7 @@ NS_IMETHODIMP nsMenuBarFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
ClearRecentlyRolledUp();
}
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
mCurrentMenu = aMenuItem;
return NS_OK;
@@ -587,6 +627,7 @@ nsMenuBarFrame::Escape(PRBool& aHandledFlag)
if (!mCurrentMenu)
return NS_OK;
+ nsWeakFrame weakFrame(this);
// See if our menu is open.
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsOpen(isOpen);
@@ -594,10 +635,12 @@ nsMenuBarFrame::Escape(PRBool& aHandledFlag)
// Let the child menu handle this.
aHandledFlag = PR_FALSE;
mCurrentMenu->Escape(aHandledFlag);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
if (!aHandledFlag) {
// Close up this menu but keep our current menu item
// designation.
mCurrentMenu->OpenMenu(PR_FALSE);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
if (nsMenuFrame::sDismissalListener)
nsMenuFrame::sDismissalListener->Unregister();
@@ -606,6 +649,7 @@ nsMenuBarFrame::Escape(PRBool& aHandledFlag)
// Clear our current menu item if we've got one.
SetCurrentMenuItem(nsnull);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
SetActive(PR_FALSE);
@@ -670,8 +714,9 @@ nsMenuBarFrame::HideChain()
if (nsMenuFrame::sDismissalListener)
nsMenuFrame::sDismissalListener->Unregister();
+ nsWeakFrame weakFrame(this);
ClearRecentlyRolledUp();
- if (mCurrentMenu) {
+ if (mCurrentMenu && weakFrame.IsAlive()) {
mCurrentMenu->ActivateMenu(PR_FALSE);
mCurrentMenu->SelectMenu(PR_FALSE);
mRecentRollupMenu = mCurrentMenu;
diff --git a/layout/xul/base/src/nsMenuFrame.cpp b/layout/xul/base/src/nsMenuFrame.cpp
index bcaa6b9..c542a35 100644
--- a/layout/xul/base/src/nsMenuFrame.cpp
+++ b/layout/xul/base/src/nsMenuFrame.cpp
@@ -86,6 +86,8 @@
#include "nsIEventStateManager.h"
#include "nsITimerInternal.h"
#include "nsContentUtils.h"
+#include "nsIEventQueueService.h"
+#include "nsIServiceManager.h"
#define NS_MENU_POPUP_LIST_INDEX 0
@@ -93,6 +95,8 @@
#define NSCONTEXTMENUISMOUSEUP 1
#endif
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
static PRInt32 gEatMouseMove = PR_FALSE;
nsMenuDismissalListener* nsMenuFrame::sDismissalListener = nsnull;
@@ -180,6 +184,37 @@ nsMenuFrame::SetParent(const nsIFrame* aParent)
return NS_OK;
}
+struct nsASyncMenuInitialization : public PLEvent
+{
+ nsASyncMenuInitialization(nsIFrame* aFrame)
+ : mWeakFrame(aFrame)
+ {
+ }
+
+ void HandleEvent() {
+ if (mWeakFrame.IsAlive()) {
+ nsIMenuFrame* imenu = nsnull;
+ CallQueryInterface(mWeakFrame.GetFrame(), &imenu);
+ if (imenu) {
+ nsMenuFrame* menu = NS_STATIC_CAST(nsMenuFrame*, imenu);
+ menu->UpdateMenuType(menu->GetPresContext());
+ }
+ }
+ }
+
+ nsWeakFrame mWeakFrame;
+};
+
+static void* PR_CALLBACK HandleASyncMenuInitialization(PLEvent* aEvent)
+{
+ NS_STATIC_CAST(nsASyncMenuInitialization*, aEvent)->HandleEvent();
+ return nsnull;
+}
+static void PR_CALLBACK DestroyASyncMenuInitialization(PLEvent* aEvent)
+{
+ delete NS_STATIC_CAST(nsASyncMenuInitialization*, aEvent);
+}
+
NS_IMETHODIMP
nsMenuFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
@@ -199,9 +234,6 @@ nsMenuFrame::Init(nsIPresContext* aPresContext,
currFrame = currFrame->GetParent();
}
- // Do the type="checkbox" magic
- UpdateMenuType(aPresContext);
-
//load the display strings for the keyboard accelerators, but only once
if (gRefCnt++ == 0) {
@@ -238,6 +270,24 @@ nsMenuFrame::Init(nsIPresContext* aPresContext,
BuildAcceleratorText();
+ nsCOMPtr<nsIEventQueueService> eventService =
+ do_GetService(kEventQueueServiceCID);
+ NS_ENSURE_TRUE(eventService, PR_FALSE);
+ nsCOMPtr<nsIEventQueue> eventQueue;
+ eventService->GetThreadEventQueue(PR_GetCurrentThread(),
+ getter_AddRefs(eventQueue));
+ if (eventQueue) {
+ nsASyncMenuInitialization* initialization =
+ new nsASyncMenuInitialization(this);
+ if (initialization) {
+ PL_InitEvent(initialization, nsnull,
+ ::HandleASyncMenuInitialization,
+ ::DestroyASyncMenuInitialization);
+ if (NS_FAILED(eventQueue->PostEvent(initialization))) {
+ PL_DestroyEvent(initialization);
+ }
+ }
+ }
return rv;
}
@@ -338,15 +388,18 @@ NS_IMETHODIMP
nsMenuFrame::Destroy(nsIPresContext* aPresContext)
{
// are we our menu parent's current menu item?
+ nsWeakFrame weakFrame(this);
if (mMenuParent) {
nsIMenuFrame *curItem = nsnull;
mMenuParent->GetCurrentMenuItem(&curItem);
if (curItem == this) {
// yes; tell it that we're going away
mMenuParent->SetCurrentMenuItem(nsnull);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
}
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
DestroyPopupFrames(aPresContext);
return nsBoxFrame::Destroy(aPresContext);
}
@@ -383,6 +436,7 @@ nsMenuFrame::HandleEvent(nsIPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
+ nsWeakFrame weakFrame(this);
if (*aEventStatus == nsEventStatus_eIgnore)
*aEventStatus = nsEventStatus_eConsumeDoDefault;
@@ -409,6 +463,7 @@ nsMenuFrame::HandleEvent(nsIPresContext* aPresContext,
// We have children.
if ( isMenuBar || !mMenuParent ) {
ToggleMenuState();
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
if (!IsOpen() && mMenuParent) {
// We closed up. The menu bar should always be
@@ -496,6 +551,8 @@ nsMenuFrame::HandleEvent(nsIPresContext* aPresContext,
// Let the menu parent know we're the new item.
mMenuParent->SetCurrentMenuItem(this);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
+ NS_ENSURE_TRUE(mMenuParent, NS_OK);
// we need to check if we really became the current menu
// item or not
@@ -533,8 +590,10 @@ nsMenuFrame::HandleEvent(nsIPresContext* aPresContext,
NS_IMETHODIMP
nsMenuFrame::ToggleMenuState()
{
+ nsWeakFrame weakFrame(this);
if (mMenuOpen) {
OpenMenu(PR_FALSE);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
else {
PRBool justRolledUp = PR_FALSE;
@@ -546,21 +605,28 @@ nsMenuFrame::ToggleMenuState()
// from the same click. Otherwise, the user can't click on
// a menubar item to toggle its submenu closed.
OpenMenu(PR_FALSE);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
SelectMenu(PR_TRUE);
mMenuParent->SetActive(PR_FALSE);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
+ NS_ENSURE_TRUE(mMenuParent, NS_OK);
}
else {
if (mMenuParent) {
mMenuParent->SetActive(PR_TRUE);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
OpenMenu(PR_TRUE);
}
}
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
if (mMenuParent) {
// Make sure the current menu which is being toggled on
// the menubar is highlighted
mMenuParent->SetCurrentMenuItem(this);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
+ NS_ENSURE_TRUE(mMenuParent, NS_OK);
// We've successfully prevented the same click from both
// dismissing and reopening this menu.
// Clear the recent rollup state so we don't prevent
@@ -579,6 +645,7 @@ nsMenuFrame::SelectMenu(PRBool aActivateFlag)
}
nsAutoString domEventToFire;
+ nsWeakFrame weakFrame(this);
if (aActivateFlag) {
// Highlight the menu.
@@ -592,7 +659,9 @@ nsMenuFrame::SelectMenu(PRBool aActivateFlag)
domEventToFire.Assign(NS_LITERAL_STRING("DOMMenuItemInactive"));
}
- FireChromeDOMEvent(mPresContext, domEventToFire);
+ if (weakFrame.IsAlive()) {
+ FireChromeDOMEvent(mPresContext, domEventToFire);
+ }
return NS_OK;
}
@@ -734,15 +803,21 @@ nsMenuFrame::OpenMenu(PRBool aActivateFlag)
if (!mContent)
return NS_OK;
+ nsWeakFrame weakFrame(this);
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mContent));
if (aActivateFlag) {
// Now that the menu is opened, we should have a menupopup child built.
// Mark it as generated, which ensures a frame gets built.
MarkAsGenerated();
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
domElement->SetAttribute(NS_LITERAL_STRING("open"), NS_LITERAL_STRING("true"));
}
- else domElement->RemoveAttribute(NS_LITERAL_STRING("open"));
+ else {
+ domElement->RemoveAttribute(NS_LITERAL_STRING("open"));
+ }
+
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
return NS_OK;
}
@@ -755,9 +830,11 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
if (!mIsMenu)
return;
+ nsWeakFrame weakFrame(this);
+
if (aActivateFlag) {
// Execute the oncreate handler
- if (!OnCreate())
+ if (!OnCreate() || !weakFrame.IsAlive())
return;
mCreateHandlerSucceeded = PR_TRUE;
@@ -768,6 +845,7 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
// XXX Only have this here because of RDF-generated content.
MarkAsGenerated();
+ ENSURE_TRUE(weakFrame.IsAlive());
nsIFrame* frame = mPopupFrames.FirstChild();
nsMenuPopupFrame* menuPopup = (nsMenuPopupFrame*)frame;
@@ -775,11 +853,13 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
mMenuOpen = PR_TRUE;
if (menuPopup) {
+ nsWeakFrame weakMenuPopup(frame);
// inherit whether or not we're a context menu from the parent
if ( mMenuParent ) {
PRBool parentIsContextMenu = PR_FALSE;
mMenuParent->GetIsContextMenu(parentIsContextMenu);
menuPopup->SetIsContextMenu(parentIsContextMenu);
+ ENSURE_TRUE(weakFrame.IsAlive());
}
// Install a keyboard navigation listener if we're the root of the menu chain.
@@ -790,11 +870,16 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
if (mMenuParent && onMenuBar)
mMenuParent->InstallKeyboardNavigator();
else if (!mMenuParent)
+ {
+ ENSURE_TRUE(weakMenuPopup.IsAlive());
menuPopup->InstallKeyboardNavigator();
+ }
// Tell the menu bar we're active.
- if (mMenuParent)
+ if (mMenuParent) {
mMenuParent->SetActive(PR_TRUE);
+ ENSURE_TRUE(weakFrame.IsAlive());
+ }
nsIContent* menuPopupContent = menuPopup->GetContent();
@@ -849,12 +934,14 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
}
ActivateMenu(PR_TRUE);
+ ENSURE_TRUE(weakFrame.IsAlive());
nsIMenuParent *childPopup = nsnull;
CallQueryInterface(frame, &childPopup);
UpdateDismissalListener(childPopup);
OnCreated();
+ ENSURE_TRUE(weakFrame.IsAlive());
}
// Set the focus back to our view's widget.
@@ -866,7 +953,7 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
// Close the menu.
// Execute the ondestroy handler, but only if we're actually open
- if ( !mCreateHandlerSucceeded || !OnDestroy() )
+ if ( !mCreateHandlerSucceeded || !OnDestroy() || !weakFrame.IsAlive())
return;
mMenuOpen = PR_FALSE;
@@ -883,6 +970,7 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
// Make sure we clear out our own items.
if (menuPopup) {
menuPopup->SetCurrentMenuItem(nsnull);
+ ENSURE_TRUE(weakFrame.IsAlive());
menuPopup->KillCloseTimer();
PRBool onMenuBar = PR_TRUE;
@@ -909,8 +997,10 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag)
// activate false will also set the mMenuOpen to false.
ActivateMenu(PR_FALSE);
+ ENSURE_TRUE(weakFrame.IsAlive());
OnDestroyed();
+ ENSURE_TRUE(weakFrame.IsAlive());
if (nsMenuFrame::sDismissalListener)
nsMenuFrame::sDismissalListener->EnableListener(PR_TRUE);
@@ -1364,9 +1454,12 @@ nsMenuFrame::UpdateMenuType(nsIPresContext* aPresContext)
mGroupName = valueName;
}
else {
- if (mType != eMenuType_Normal)
+ if (mType != eMenuType_Normal) {
+ nsWeakFrame weakFrame(this);
mContent->UnsetAttr(kNameSpaceID_None, nsHTMLAtoms::checked,
PR_TRUE);
+ ENSURE_TRUE(weakFrame.IsAlive());
+ }
mType = eMenuType_Normal;
}
UpdateMenuSpecialState(aPresContext);
@@ -1481,7 +1574,9 @@ nsMenuFrame::BuildAcceleratorText()
AddStateBits(NS_STATE_ACCELTEXT_IS_DERIVED);
// If anything below fails, just leave the accelerator text blank.
+ nsWeakFrame weakFrame(this);
mContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::acceltext, PR_FALSE);
+ ENSURE_TRUE(weakFrame.IsAlive());
// See if we have a key node and use that instead.
nsAutoString keyValue;
@@ -1607,6 +1702,7 @@ nsMenuFrame::BuildAcceleratorText()
void
nsMenuFrame::Execute(nsGUIEvent *aEvent)
{
+ nsWeakFrame weakFrame(this);
// flip "checked" state if we're a checkbox menu, or an un-checked radio menu
if (mType == eMenuType_Checkbox || (mType == eMenuType_Radio && !mChecked)) {
nsAutoString value;
@@ -1615,10 +1711,12 @@ nsMenuFrame::Execute(nsGUIEvent *aEvent)
if (mChecked) {
mContent->UnsetAttr(kNameSpaceID_None, nsHTMLAtoms::checked,
PR_TRUE);
+ ENSURE_TRUE(weakFrame.IsAlive());
}
else {
mContent->SetAttr(kNameSpaceID_None, nsHTMLAtoms::checked, NS_LITERAL_STRING("true"),
PR_TRUE);
+ ENSURE_TRUE(weakFrame.IsAlive());
}
/* the AttributeChanged code will update all the internal state */
}
@@ -1636,6 +1734,7 @@ nsMenuFrame::Execute(nsGUIEvent *aEvent)
// Deselect ourselves.
SelectMenu(PR_FALSE);
+ ENSURE_TRUE(weakFrame.IsAlive());
// Now hide all of the open menus.
if (mMenuParent) {
@@ -1672,22 +1771,14 @@ nsMenuFrame::Execute(nsGUIEvent *aEvent)
nsCOMPtr<nsIViewManager> kungFuDeathGrip = mPresContext->GetViewManager();
// keep a reference so we can safely use this after dispatching the DOM event
nsCOMPtr<nsIPresShell> shell = mPresContext->GetPresShell();
- nsIFrame* me = this;
if (shell) {
shell->HandleDOMEventWithTarget(mContent, &event, &status);
- // shell may no longer be alive, don't use it here unless you keep a ref
+ ENSURE_TRUE(weakFrame.IsAlive());
}
- // XXX HACK. Just gracefully exit if the node has been removed, e.g., window.close()
- // was executed.
- nsIFrame* primary = nsnull;
- if (shell) shell->GetPrimaryFrameFor(content, &primary);
-
- // Now properly close them all up.
- if (content->GetDocument() && // <-- HACK IS HERE. ICK.
- (primary == me) && mMenuParent)
+ if (mMenuParent) {
mMenuParent->DismissChain();
- // END HACK
+ }
// Re-enable rollup events on this menu.
if ( nsMenuFrame::sDismissalListener ) {
@@ -1729,7 +1820,7 @@ nsMenuFrame::OnCreate()
PRUint32 count = child->GetChildCount();
for (PRUint32 i = 0; i < count; i++) {
- nsIContent *grandChild = child->GetChildAt(i);
+ nsCOMPtr<nsIContent> grandChild = child->GetChildAt(i);
if (grandChild->Tag() == nsXULAtoms::menuitem) {
// See if we have a command attribute.
@@ -1953,6 +2044,55 @@ nsMenuFrame::UpdateDismissalListener(nsIMenuParent* aMenuParent)
nsMenuFrame::sDismissalListener->SetCurrentMenuParent(aMenuParent);
}
+struct nsASyncMenuGeneration : public PLEvent
+{
+ nsASyncMenuGeneration(nsIFrame* aFrame)
+ : mWeakFrame(aFrame)
+ {
+ nsIContent* content = aFrame ? aFrame->GetContent() : nsnull;
+ mDocument = content ? content->GetDocument() : nsnull;
+ if (mDocument) {
+ nsCOMPtr<nsIDocument_MOZILLA_1_7_BRANCH> doc17(do_QueryInterface(mDocument));
+ doc17->BlockOnload();
+ }
+ }
+
+ void HandleEvent() {
+ nsIFrame* frame = mWeakFrame.GetFrame();
+ nsIBox *box = nsnull;
+ CallQueryInterface(frame, &box);
+ if (box) {
+ PRBool collapsed = PR_FALSE;
+ nsBoxLayoutState state(frame->GetPresContext());
+ box->IsCollapsed(state, collapsed);
+ if (!collapsed) {
+ nsIMenuFrame* imenu = nsnull;
+ CallQueryInterface(frame, &imenu);
+ if (imenu) {
+ imenu->MarkAsGenerated();
+ }
+ }
+ }
+ if (mDocument) {
+ nsCOMPtr<nsIDocument_MOZILLA_1_7_BRANCH> doc17(do_QueryInterface(mDocument));
+ doc17->UnblockOnload();
+ }
+ }
+
+ nsWeakFrame mWeakFrame;
+ nsCOMPtr<nsIDocument> mDocument;
+};
+
+static void* PR_CALLBACK HandleASyncMenuGeneration(PLEvent* aEvent)
+{
+ NS_STATIC_CAST(nsASyncMenuGeneration*, aEvent)->HandleEvent();
+ return nsnull;
+}
+static void PR_CALLBACK DestroyASyncMenuGeneration(PLEvent* aEvent)
+{
+ delete NS_STATIC_CAST(nsASyncMenuGeneration*, aEvent);
+}
+
NS_IMETHODIMP
nsMenuFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize)
{
@@ -1969,10 +2109,32 @@ nsMenuFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize)
if (tmpSize.width == -1 && flex==0) {
nsIFrame* frame = mPopupFrames.FirstChild();
if (!frame) {
- MarkAsGenerated();
- frame = mPopupFrames.FirstChild();
- // No child - just return
- if (!frame) return NS_OK;
+ nsCOMPtr<nsIContent> child;
+ GetMenuChildrenElement(getter_AddRefs(child));
+ if (child) {
+ nsAutoString genVal;
+ child->GetAttr(kNameSpaceID_None, nsXULAtoms::menugenerated, genVal);
+ if (genVal.IsEmpty()) {
+ nsCOMPtr<nsIEventQueueService> eventService =
+ do_GetService(kEventQueueServiceCID);
+ NS_ENSURE_TRUE(eventService, PR_FALSE);
+ nsCOMPtr<nsIEventQueue> eventQueue;
+ eventService->GetThreadEventQueue(PR_GetCurrentThread(),
+ getter_AddRefs(eventQueue));
+ if (eventQueue) {
+ nsASyncMenuGeneration* gen = new nsASyncMenuGeneration(this);
+ if (gen) {
+ PL_InitEvent(gen, nsnull,
+ ::HandleASyncMenuGeneration,
+ ::DestroyASyncMenuGeneration);
+ if (NS_FAILED(eventQueue->PostEvent(gen))) {
+ PL_DestroyEvent(gen);
+ }
+ }
+ }
+ }
+ }
+ return PR_FALSE;
}
nsIBox* ibox = nsnull;
diff --git a/layout/xul/base/src/nsMenuFrame.h b/layout/xul/base/src/nsMenuFrame.h
index f3ea8ec..71f4589 100644
--- a/layout/xul/base/src/nsMenuFrame.h
+++ b/layout/xul/base/src/nsMenuFrame.h
@@ -200,6 +200,7 @@ protected:
virtual void RePositionPopup(nsBoxLayoutState& aState);
static void UpdateDismissalListener(nsIMenuParent* aMenuParent);
+ friend class nsASyncMenuInitialization;
void UpdateMenuType(nsIPresContext* aPresContext);
void UpdateMenuSpecialState(nsIPresContext* aPresContext);
diff --git a/layout/xul/base/src/nsMenuPopupFrame.cpp b/layout/xul/base/src/nsMenuPopupFrame.cpp
index 046b599..2e2ff8e 100644
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -73,10 +73,14 @@
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
#include "nsCSSFrameConstructor.h"
+#include "nsIEventQueueService.h"
+#include "nsIServiceManager.h"
#ifdef XP_WIN
#include "nsISound.h"
#endif
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
const PRInt32 kMaxZ = 0x7fffffff; //XXX: Shouldn't there be a define somewhere for MaxInt for PRInt32
@@ -827,6 +831,37 @@ nsMenuPopupFrame::MovePopupToOtherSideOfParent ( PRBool inFlushAboveBelow, PRInt
} // MovePopupToOtherSideOfParent
+struct nsASyncMenuActivation : public PLEvent
+{
+ nsASyncMenuActivation(nsIContent* aContent)
+ : mContent(aContent)
+ {
+ }
+
+ void HandleEvent() {
+ nsAutoString shouldDisplay, menuActive;
+ mContent->GetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, menuActive);
+ if (!menuActive.Equals(NS_LITERAL_STRING("true"))) {
+ mContent->GetAttr(kNameSpaceID_None, nsXULAtoms::menutobedisplayed,
+ shouldDisplay);
+ if(shouldDisplay.Equals(NS_LITERAL_STRING("true"))) {
+ mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::menuactive,
+ NS_LITERAL_STRING("true"), PR_TRUE);
+ }
+ }
+ }
+
+ nsCOMPtr<nsIContent> mContent;
+};
+
+static void PR_CALLBACK HandleASyncMenuActivation(nsASyncMenuActivation* aEvent)
+{
+ aEvent->HandleEvent();
+}
+static void PR_CALLBACK DestroyASyncMenuActivation(nsASyncMenuActivation* aEvent)
+{
+ delete aEvent;
+}
nsresult
@@ -1213,8 +1248,25 @@ nsMenuPopupFrame::SyncViewWithFrame(nsIPresContext* aPresContext,
mContent->GetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, menuActive);
if (menuActive != NS_LITERAL_STRING("true")) {
mContent->GetAttr(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, shouldDisplay);
- if ( shouldDisplay == NS_LITERAL_STRING("true") )
- mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, NS_LITERAL_STRING("true"), PR_TRUE);
+ if ( shouldDisplay.Equals(NS_LITERAL_STRING("true")) ) {
+ nsCOMPtr<nsIEventQueueService> eventService =
+ do_GetService(kEventQueueServiceCID);
+ NS_ENSURE_TRUE(eventService, NS_ERROR_FAILURE);
+ nsCOMPtr<nsIEventQueue> eventQueue;
+ eventService->GetThreadEventQueue(PR_GetCurrentThread(),
+ getter_AddRefs(eventQueue));
+ if (eventQueue) {
+ nsASyncMenuActivation* activation = new nsASyncMenuActivation(mContent);
+ if (activation) {
+ PL_InitEvent(activation, nsnull,
+ (PLHandleEventProc) ::HandleASyncMenuActivation,
+ (PLDestroyEventProc) ::DestroyASyncMenuActivation);
+ if (NS_FAILED(eventQueue->PostEvent(activation))) {
+ PL_DestroyEvent(activation);
+ }
+ }
+ }
+ }
}
return NS_OK;
@@ -1751,10 +1803,14 @@ nsMenuPopupFrame::ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandled
nsIMenuFrame* result = FindMenuWithShortcut(aKeyEvent, action);
if (result) {
// We got one!
+ nsIFrame* frame = nsnull;
+ CallQueryInterface(result, &frame);
+ nsWeakFrame weakResult(frame);
aHandledFlag = PR_TRUE;
SetCurrentMenuItem(result);
- if (action)
+ if (action && weakResult.IsAlive()) {
result->Enter();
+ }
}
return NS_OK;
@@ -1792,6 +1848,7 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
PRBool isContainer = PR_FALSE;
PRBool isOpen = PR_FALSE;
PRBool isDisabled = PR_FALSE;
+ nsWeakFrame weakFrame(this);
if (mCurrentMenu) {
mCurrentMenu->MenuIsContainer(isContainer);
mCurrentMenu->MenuIsOpen(isOpen);
@@ -1800,13 +1857,19 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
if (isOpen) {
// Give our child a shot.
mCurrentMenu->KeyboardNavigation(aKeyCode, aHandledFlag);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
else if (theDirection == eNavigationDirection_End &&
isContainer && !isDisabled) {
// The menu is not yet open. Open it and select the first item.
aHandledFlag = PR_TRUE;
+ nsIFrame* frame = nsnull;
+ CallQueryInterface(mCurrentMenu, &frame);
+ nsWeakFrame weakCurrentFrame(frame);
mCurrentMenu->OpenMenu(PR_TRUE);
+ NS_ENSURE_TRUE(weakCurrentFrame.IsAlive(), NS_OK);
mCurrentMenu->SelectFirstItem();
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
}
}
@@ -1836,6 +1899,7 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
if (theDirection == eNavigationDirection_Start) {
// Close it up.
mCurrentMenu->OpenMenu(PR_FALSE);
+ NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
aHandledFlag = PR_TRUE;
}
}
@@ -1875,6 +1939,7 @@ nsMenuPopupFrame::HideChain()
nsIFrame* frame = GetParent();
if (frame) {
+ nsWeakFrame weakMenu(frame);
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(frame);
if (!menuFrame) {
nsIPopupSetFrame* popupSetFrame = GetPopupSetFrame(mPresContext);
@@ -1885,7 +1950,9 @@ nsMenuPopupFrame::HideChain()
}
menuFrame->ActivateMenu(PR_FALSE);
+ NS_ENSURE_TRUE(weakMenu.IsAlive(), NS_OK);
menuFrame->SelectMenu(PR_FALSE);
+ NS_ENSURE_TRUE(weakMenu.IsAlive(), NS_OK);
// Get the parent.
nsCOMPtr<nsIMenuParent> menuParent;
--
1.4.4.2
More information about the pkg-mozilla-maintainers
mailing list