diff --git a/mozilla/accessible/src/base/nsAccessibilityAtomList.h b/mozilla/accessible/src/base/nsAccessibilityAtomList.h index 5d13c8dec9e..d0c5fbd1b84 100755 --- a/mozilla/accessible/src/base/nsAccessibilityAtomList.h +++ b/mozilla/accessible/src/base/nsAccessibilityAtomList.h @@ -179,3 +179,8 @@ ACCESSIBILITY_ATOM(valuenow, "valuenow") // For DHTML widget values ACCESSIBILITY_ATOM(valuemin, "valuemin") ACCESSIBILITY_ATOM(valuemax, "valuemax") ACCESSIBILITY_ATOM(hidden, "hidden") + + // misc atoms +// a form property used to obtain the default label +// of an HTML button from the button frame +ACCESSIBILITY_ATOM(defaultLabel, "defaultLabel") diff --git a/mozilla/accessible/src/html/nsHTMLFormControlAccessible.cpp b/mozilla/accessible/src/html/nsHTMLFormControlAccessible.cpp index 1c5accde5e1..fb8fe4cb6bc 100644 --- a/mozilla/accessible/src/html/nsHTMLFormControlAccessible.cpp +++ b/mozilla/accessible/src/html/nsHTMLFormControlAccessible.cpp @@ -49,7 +49,6 @@ #include "nsIFrame.h" #include "nsINameSpaceManager.h" #include "nsISelectionController.h" -#include "nsISupportsArray.h" #include "nsITextControlFrame.h" // --- checkbox ----- @@ -201,15 +200,14 @@ NS_IMETHODIMP nsHTMLButtonAccessible::GetName(nsAString& aName) GetHTMLName(name, PR_FALSE); } if (name.IsEmpty()) { - // Use anonymous text child of button if nothing else works. - // This is necessary for submit, reset and browse buttons. - nsCOMPtr shell(GetPresShell()); - NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE); - nsCOMPtr anonymousElements; - shell->GetAnonymousContentFor(content, getter_AddRefs(anonymousElements)); - nsCOMPtr domNode(do_QueryElementAt(anonymousElements, 0)); - if (domNode) { - domNode->GetNodeValue(name); + // Use the button's (default) label if nothing else works + nsIFrame* frame = GetFrame(); + if (frame) { + nsIFormControlFrame* fcFrame; + frame->QueryInterface(NS_GET_IID(nsIFormControlFrame), + (void**) &fcFrame); + if (fcFrame) + fcFrame->GetFormProperty(nsAccessibilityAtoms::defaultLabel, name); } } if (name.IsEmpty() && diff --git a/mozilla/content/base/public/nsContentUtils.h b/mozilla/content/base/public/nsContentUtils.h index c91556bda0e..0f9a56dac5b 100644 --- a/mozilla/content/base/public/nsContentUtils.h +++ b/mozilla/content/base/public/nsContentUtils.h @@ -950,6 +950,11 @@ public: } } + /** + * Unbinds the content from the tree and nulls it out if it's not null. + */ + static void DestroyAnonymousContent(nsCOMPtr* aContent); + private: static nsresult doReparentContentWrapper(nsIContent *aChild, JSContext *cx, diff --git a/mozilla/content/base/src/nsContentUtils.cpp b/mozilla/content/base/src/nsContentUtils.cpp index 6969f71fb88..557c5c129e7 100644 --- a/mozilla/content/base/src/nsContentUtils.cpp +++ b/mozilla/content/base/src/nsContentUtils.cpp @@ -3389,3 +3389,13 @@ nsContentUtils::IsInSameAnonymousTree(nsINode* aNode, aContent->GetBindingParent(); } + +/* static */ +void +nsContentUtils::DestroyAnonymousContent(nsCOMPtr* aContent) +{ + if (*aContent) { + (*aContent)->UnbindFromTree(); + *aContent = nsnull; + } +} diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index d72a74f6724..2a23d725036 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -5405,19 +5405,6 @@ nsDocument::Destroy() // So we're just creating an inconsistent DOM for now and hoping. :( mChildren.ChildAt(indx)->UnbindFromTree(); } - - // Propagate the out-of-band notification to each PresShell's anonymous - // content as well. This ensures that there aren't any accidental references - // left in anonymous content keeping the document alive. (While not strictly - // necessary -- the PresShell owns us -- it's tidy.) - for (count = GetNumberOfShells() - 1; count >= 0; --count) { - nsCOMPtr shell = GetShellAt(count); - if (!shell) - continue; - - shell->ReleaseAnonymousContent(); - } - mLayoutHistoryState = nsnull; nsContentList::OnDocumentDestroy(this); diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index ac7a23970ae..85a5714adef 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -57,7 +57,6 @@ #include "nsIFocusController.h" #include "nsILinkHandler.h" #include "nsIScriptGlobalObject.h" -#include "nsISupportsArray.h" #include "nsIURL.h" #include "nsNetUtil.h" #include "nsIFrame.h" @@ -3666,29 +3665,7 @@ nsGenericElement::List(FILE* out, PRInt32 aIndent, // XXX sXBL/XBL2 issue! Owner or current document? nsIDocument *document = GetOwnerDoc(); if (document) { - nsIPresShell *shell = document->GetShellAt(0); - nsCOMPtr anonymousElements; - if (shell) { - shell->GetAnonymousContentFor(NS_CONST_CAST(nsGenericElement*, this), - getter_AddRefs(anonymousElements)); - } - - if (anonymousElements) { - anonymousElements->Count(&length); - if (length > 0) { - for (indent = aIndent; --indent >= 0; ) fputs(" ", out); - fputs("native-anonymous-children<\n", out); - - for (i = 0; i < length; ++i) { - nsCOMPtr node = do_QueryElementAt(anonymousElements, i); - nsCOMPtr child = do_QueryInterface(node); - child->List(out, aIndent + 1); - } - - for (indent = aIndent; --indent >= 0; ) fputs(" ", out); - fputs(">\n", out); - } - } + // Note: not listing nsIAnonymousContentCreator-created content... nsBindingManager* bindingManager = document->BindingManager(); nsCOMPtr anonymousChildren; diff --git a/mozilla/content/base/src/nsGenericElement.h b/mozilla/content/base/src/nsGenericElement.h index 3e87fd99178..ff7d3985047 100644 --- a/mozilla/content/base/src/nsGenericElement.h +++ b/mozilla/content/base/src/nsGenericElement.h @@ -67,7 +67,6 @@ class nsIDOMAttr; class nsIDOMEventListener; class nsIFrame; -class nsISupportsArray; class nsIDOMNamedNodeMap; class nsDOMCSSDeclaration; class nsIDOMCSSStyleDeclaration; diff --git a/mozilla/content/base/src/nsGkAtomList.h b/mozilla/content/base/src/nsGkAtomList.h index be54d747359..0a5a3fc9569 100755 --- a/mozilla/content/base/src/nsGkAtomList.h +++ b/mozilla/content/base/src/nsGkAtomList.h @@ -247,6 +247,7 @@ GK_ATOM(_default, "default") GK_ATOM(headerDefaultStyle, "default-style") GK_ATOM(defaultAction, "defaultAction") GK_ATOM(defaultchecked, "defaultchecked") +GK_ATOM(defaultLabel, "defaultLabel") GK_ATOM(defaultselected, "defaultselected") GK_ATOM(defaultvalue, "defaultvalue") GK_ATOM(defer, "defer") diff --git a/mozilla/content/svg/content/src/nsSVGUseElement.cpp b/mozilla/content/svg/content/src/nsSVGUseElement.cpp index c0fe33d8f85..3b8ff3ee3ed 100644 --- a/mozilla/content/svg/content/src/nsSVGUseElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGUseElement.cpp @@ -34,99 +34,18 @@ * * ***** END LICENSE BLOCK ***** */ +#include "nsSVGUseElement.h" #include "nsIDOMSVGGElement.h" #include "nsGkAtoms.h" #include "nsIDOMSVGAnimatedLength.h" #include "nsISVGSVGElement.h" #include "nsSVGCoordCtxProvider.h" -#include "nsIDOMSVGAnimatedString.h" #include "nsSVGAnimatedString.h" #include "nsIDOMDocument.h" #include "nsIDOMSVGSVGElement.h" #include "nsIDOMSVGSymbolElement.h" #include "nsIDocument.h" -#include "nsISupportsArray.h" #include "nsIPresShell.h" -#include "nsIAnonymousContentCreator.h" -#include "nsSVGGraphicElement.h" -#include "nsIDOMSVGURIReference.h" -#include "nsIDOMSVGUseElement.h" -#include "nsIMutationObserver.h" -#include "nsSVGLength2.h" - -#define NS_SVG_USE_ELEMENT_IMPL_CID \ -{ 0xa95c13d3, 0xc193, 0x465f, {0x81, 0xf0, 0x02, 0x6d, 0x67, 0x05, 0x54, 0x58 } } - -nsresult -NS_NewSVGSVGElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); - -typedef nsSVGGraphicElement nsSVGUseElementBase; - -class nsSVGUseElement : public nsSVGUseElementBase, - public nsIDOMSVGURIReference, - public nsIDOMSVGUseElement, - public nsIMutationObserver, - public nsIAnonymousContentCreator -{ -protected: - friend nsresult NS_NewSVGUseElement(nsIContent **aResult, - nsINodeInfo *aNodeInfo); - nsSVGUseElement(nsINodeInfo *aNodeInfo); - virtual ~nsSVGUseElement(); - virtual nsresult Init(); - -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVG_USE_ELEMENT_IMPL_CID) - - // interfaces: - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIDOMSVGUSEELEMENT - NS_DECL_NSIDOMSVGURIREFERENCE - NS_DECL_NSIMUTATIONOBSERVER - - // xxx I wish we could use virtual inheritance - NS_FORWARD_NSIDOMNODE(nsSVGUseElementBase::) - NS_FORWARD_NSIDOMELEMENT(nsSVGUseElementBase::) - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGUseElementBase::) - - // nsISVGValueObserver specialization: - NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable, - nsISVGValue::modificationType aModType); - - // nsIAnonymousContentCreator - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousItems); - NS_IMETHOD CreateFrameFor(nsPresContext *aPresContext, - nsIContent *aContent, - nsIFrame **aFrame); - - // nsSVGElement specializations: - virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr); - - // nsIContent interface - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; - -protected: - - virtual LengthAttributesInfo GetLengthInfo(); - - void SyncWidthHeight(PRUint8 aAttrEnum); - nsIContent *LookupHref(); - void TriggerReclone(); - void RemoveListener(); - - enum { X, Y, WIDTH, HEIGHT }; - nsSVGLength2 mLengthAttributes[4]; - static LengthInfo sLengthInfo[4]; - - nsCOMPtr mHref; - - nsCOMPtr mOriginal; // if we've been cloned, our "real" copy - nsCOMPtr mClone; // cloned tree - nsCOMPtr mSourceContent; // observed element -}; NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGUseElement, NS_SVG_USE_ELEMENT_IMPL_CID) @@ -156,7 +75,6 @@ NS_INTERFACE_MAP_BEGIN(nsSVGUseElement) NS_INTERFACE_MAP_ENTRY(nsIDOMSVGURIReference) NS_INTERFACE_MAP_ENTRY(nsIDOMSVGUseElement) NS_INTERFACE_MAP_ENTRY(nsIMutationObserver) - NS_INTERFACE_MAP_ENTRY(nsIAnonymousContentCreator) NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGUseElement) if (aIID.Equals(NS_GET_IID(nsSVGUseElement))) foundInterface = NS_REINTERPRET_CAST(nsISupports*, this); @@ -334,11 +252,9 @@ nsSVGUseElement::NodeWillBeDestroyed(const nsINode *aNode) } //---------------------------------------------------------------------- -// nsIAnonymousContentCreator methods -NS_IMETHODIMP -nsSVGUseElement::CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousItems) +nsIContent* +nsSVGUseElement::CreateAnonymousContent() { #ifdef DEBUG_tor nsAutoString href; @@ -351,7 +267,7 @@ nsSVGUseElement::CreateAnonymousContent(nsPresContext* aPresContext, nsCOMPtr targetContent = LookupHref(); if (!targetContent) - return NS_ERROR_FAILURE; + return nsnull; if (mSourceContent != targetContent) { RemoveListener(); @@ -375,13 +291,13 @@ nsSVGUseElement::CreateAnonymousContent(nsPresContext* aPresContext, tag != nsGkAtoms::polygon && tag != nsGkAtoms::image && tag != nsGkAtoms::use) - return NS_ERROR_FAILURE; + return nsnull; // circular loop detection // check 1 - check if we're a document descendent of the target if (nsContentUtils::ContentIsDescendantOf(this, targetContent)) - return NS_ERROR_FAILURE; + return nsnull; // check 2 - check if we're a clone, and if we already exist in the hierarchy if (this->GetParent() && mOriginal) { @@ -396,7 +312,7 @@ nsSVGUseElement::CreateAnonymousContent(nsPresContext* aPresContext, getter_AddRefs(useImpl)); if (useImpl && useImpl->mOriginal == mOriginal) - return NS_ERROR_FAILURE; + return nsnull; } } } @@ -409,7 +325,7 @@ nsSVGUseElement::CreateAnonymousContent(nsPresContext* aPresContext, nsCOMPtr newcontent = do_QueryInterface(newnode); if (!newcontent) - return NS_ERROR_FAILURE; + return nsnull; nsCOMPtr symbol = do_QueryInterface(newcontent); nsCOMPtr svg = do_QueryInterface(newcontent); @@ -417,23 +333,23 @@ nsSVGUseElement::CreateAnonymousContent(nsPresContext* aPresContext, if (symbol) { nsIDocument *document = GetCurrentDoc(); if (!document) - return NS_ERROR_FAILURE; + return nsnull; nsNodeInfoManager *nodeInfoManager = document->NodeInfoManager(); if (!nodeInfoManager) - return NS_ERROR_FAILURE; + return nsnull; nsCOMPtr nodeInfo; nodeInfoManager->GetNodeInfo(nsGkAtoms::svg, nsnull, kNameSpaceID_SVG, getter_AddRefs(nodeInfo)); if (!nodeInfo) - return NS_ERROR_FAILURE; + return nsnull; nsCOMPtr svgNode; NS_NewSVGSVGElement(getter_AddRefs(svgNode), nodeInfo); if (!svgNode) - return NS_ERROR_FAILURE; + return nsnull; if (newcontent->HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox)) { nsAutoString viewbox; @@ -478,22 +394,16 @@ nsSVGUseElement::CreateAnonymousContent(nsPresContext* aPresContext, } } - aAnonymousItems.AppendElement(newcontent); mClone = newcontent; - - return NS_OK; + return mClone; } -NS_IMETHODIMP -nsSVGUseElement::CreateFrameFor(nsPresContext *aPresContext, - nsIContent *aContent, - nsIFrame **aFrame) +void +nsSVGUseElement::DestroyAnonymousContent() { - *aFrame = nsnull; - return NS_ERROR_FAILURE; + nsContentUtils::DestroyAnonymousContent(&mClone); } - //---------------------------------------------------------------------- // implementation helpers diff --git a/mozilla/content/svg/content/src/nsSVGUseElement.h b/mozilla/content/svg/content/src/nsSVGUseElement.h new file mode 100644 index 00000000000..7e86c6e75d1 --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGUseElement.h @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla SVG project. + * + * The Initial Developer of the Original Code is IBM Corporation. + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __NS_SVGUSEELEMENT_H__ +#define __NS_SVGUSEELEMENT_H__ + +#include "nsIDOMSVGAnimatedString.h" +#include "nsIDOMSVGURIReference.h" +#include "nsIDOMSVGUseElement.h" +#include "nsIMutationObserver.h" +#include "nsISVGValue.h" +#include "nsSVGGraphicElement.h" +#include "nsSVGLength2.h" +#include "nsTArray.h" + +class nsIContent; +class nsINodeInfo; + +#define NS_SVG_USE_ELEMENT_IMPL_CID \ +{ 0xa95c13d3, 0xc193, 0x465f, {0x81, 0xf0, 0x02, 0x6d, 0x67, 0x05, 0x54, 0x58 } } + +nsresult +NS_NewSVGSVGElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); + +typedef nsSVGGraphicElement nsSVGUseElementBase; + +class nsSVGUseElement : public nsSVGUseElementBase, + public nsIDOMSVGURIReference, + public nsIDOMSVGUseElement, + public nsIMutationObserver +{ + friend class nsSVGUseFrame; +protected: + friend nsresult NS_NewSVGUseElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGUseElement(nsINodeInfo *aNodeInfo); + virtual ~nsSVGUseElement(); + virtual nsresult Init(); + +public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVG_USE_ELEMENT_IMPL_CID) + + // interfaces: + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIDOMSVGUSEELEMENT + NS_DECL_NSIDOMSVGURIREFERENCE + NS_DECL_NSIMUTATIONOBSERVER + + // xxx I wish we could use virtual inheritance + NS_FORWARD_NSIDOMNODE(nsSVGUseElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsSVGUseElementBase::) + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGUseElementBase::) + + // nsISVGValueObserver specialization: + NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable, + nsISVGValue::modificationType aModType); + + // for nsSVGUseFrame's nsIAnonymousContentCreator implementation. + nsIContent* CreateAnonymousContent(); + void DestroyAnonymousContent(); + + // nsSVGElement specializations: + virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr); + + // nsIContent interface + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; + +protected: + + virtual LengthAttributesInfo GetLengthInfo(); + + void SyncWidthHeight(PRUint8 aAttrEnum); + nsIContent *LookupHref(); + void TriggerReclone(); + void RemoveListener(); + + enum { X, Y, WIDTH, HEIGHT }; + nsSVGLength2 mLengthAttributes[4]; + static LengthInfo sLengthInfo[4]; + + nsCOMPtr mHref; + + nsCOMPtr mOriginal; // if we've been cloned, our "real" copy + nsCOMPtr mClone; // cloned tree + nsCOMPtr mSourceContent; // observed element +}; + +#endif diff --git a/mozilla/content/xbl/src/nsBindingManager.cpp b/mozilla/content/xbl/src/nsBindingManager.cpp index a493bb523f7..bf3d2208681 100644 --- a/mozilla/content/xbl/src/nsBindingManager.cpp +++ b/mozilla/content/xbl/src/nsBindingManager.cpp @@ -510,18 +510,6 @@ nsBindingManager::ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocum SetContentListFor(aContent, nsnull); SetAnonymousNodesFor(aContent, nsnull); - PRUint32 count = aOldDocument->GetNumberOfShells(); - - for (PRUint32 i = 0; i < count; ++i) { - nsIPresShell *shell = aOldDocument->GetShellAt(i); - NS_ASSERTION(shell != nsnull, "Zoiks! nsIDocument::GetShellAt() broke"); - - // now clear out the anonymous content for this node in the old presshell. - // XXXbz this really doesn't belong here, somehow... either that, or we - // need to better define what sort of bindings we're managing. - shell->SetAnonymousContentFor(aContent, nsnull); - } - return NS_OK; } diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index a844fb01f5b..5fc700a8441 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -1922,7 +1922,6 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIFrame* aParentFram if (!data.mContent.mImage) { // CSS had something specified that couldn't be converted to an // image object - *aFrame = nsnull; return NS_ERROR_FAILURE; } @@ -2153,16 +2152,6 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIFrame* aParentFram } } - if (content) { - nsCOMPtr anonymousItems; - nsresult rv = NS_NewISupportsArray(getter_AddRefs(anonymousItems)); - NS_ENSURE_SUCCESS(rv, rv); - - anonymousItems->AppendElement(content); - - mPresShell->SetAnonymousContentFor(aContent, anonymousItems); - } - return NS_OK; } @@ -4913,11 +4902,6 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState, // initialized as absolutely positioned. nsIFrame* scrolledFrame = NS_NewSelectsAreaFrame(mPresShell, aStyleContext, flags); - // make sure any existing anonymous content is cleared out. Gfx scroll frame construction - // should reset it to just be the anonymous scrollbars, but we don't want to depend - // on that. - mPresShell->SetAnonymousContentFor(aContent, nsnull); - InitializeSelectFrame(aState, listFrame, scrolledFrame, aContent, comboboxFrame, listStyle, PR_TRUE, aFrameItems); @@ -5594,96 +5578,67 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState, nsFrameItems& aChildItems) { nsCOMPtr creator(do_QueryInterface(aParentFrame)); - if (!creator) return NS_OK; - nsCOMPtr anonymousItems; - NS_NewISupportsArray(getter_AddRefs(anonymousItems)); + nsresult rv; - creator->CreateAnonymousContent(aState.mPresContext, *anonymousItems); - - PRUint32 count = 0; - anonymousItems->Count(&count); + nsAutoTArray newAnonymousItems; + rv = creator->CreateAnonymousContent(newAnonymousItems); + NS_ENSURE_SUCCESS(rv, rv); - if (count) { - // save the incoming pseudo frame state, so that we don't end up - // with those pseudoframes in aChildItems - nsPseudoFrames priorPseudoFrames; - aState.mPseudoFrames.Reset(&priorPseudoFrames); - - // A content element can have multiple sources of anonymous content. For example, - // SELECTs have a combobox dropdown button and also scrollbars in the list view. - // nsPresShell doesn't handle this very well. It's a problem because a reframe could - // cause anonymous content from one source to be destroyed and recreated while - // (in theory) leaving the rest intact, but the presshell doesn't have a way of tracking - // the anonymous content at that granularity. - - // So what we're doing right now is wiping out existing content whenever we get new - // anonymous content, except for the one case we care about where there are multiple - // sources (SELECTs). This case is handled by having SELECT initialization tell us - // explicitly not to wipe out the scrollbars when the combobox anonymous content is - // added. - // Note that we only wipe out existing content when there is actual new content. - // Otherwise we wipe out scrollbars and other anonymous content when we check sources - // that never provide anonymous content (e.g. the call to CreateAnonymousFrames - // from ConstructBlock). - - // What we SHOULD do is get rid of the presshell's need to track anonymous - // content. It's only used for cleanup as far as I can tell. - if (!aAppendToExisting) { - mPresShell->SetAnonymousContentFor(aParent, nsnull); - } - - // Inform the pres shell about the anonymous content - mPresShell->SetAnonymousContentFor(aParent, anonymousItems); - - for (PRUint32 i=0; i < count; i++) { - // get our child's content and set its parent to our content - nsCOMPtr content; - if (NS_FAILED(anonymousItems->QueryElementAt(i, NS_GET_IID(nsIContent), getter_AddRefs(content)))) - continue; - - content->SetNativeAnonymous(PR_TRUE); - - nsresult rv; - nsIContent* bindingParent = content; -#ifdef MOZ_SVG - // least-surprise CSS binding until we do the SVG specified - // cascading rules for - bug 265894 - if (aParent && - aParent->NodeInfo()->Equals(nsGkAtoms::use, kNameSpaceID_SVG)) - bindingParent = aParent; -#endif - - rv = content->BindToTree(aDocument, aParent, bindingParent, PR_TRUE); - if (NS_FAILED(rv)) { - content->UnbindFromTree(); - return rv; - } - - nsIFrame * newFrame = nsnull; - rv = creator->CreateFrameFor(aState.mPresContext, content, &newFrame); - if (NS_SUCCEEDED(rv) && newFrame != nsnull) { - aChildItems.AddChild(newFrame); - } - else { - // create the frame and attach it to our frame - ConstructFrame(aState, content, aParentFrame, aChildItems); - } - - creator->PostCreateFrames(); - } - - // process the current pseudo frame state - if (!aState.mPseudoFrames.IsEmpty()) { - ProcessPseudoFrames(aState, aChildItems); - } - - // restore the incoming pseudo frame state - aState.mPseudoFrames = priorPseudoFrames; + PRUint32 count = newAnonymousItems.Length(); + if (count == 0) { + return NS_OK; } + // save the incoming pseudo frame state, so that we don't end up + // with those pseudoframes in aChildItems + nsPseudoFrames priorPseudoFrames; + aState.mPseudoFrames.Reset(&priorPseudoFrames); + + for (PRUint32 i=0; i < count; i++) { + // get our child's content and set its parent to our content + nsIContent* content = newAnonymousItems[i]; + NS_ASSERTION(content, "null anonymous content?"); + + content->SetNativeAnonymous(PR_TRUE); + + nsIContent* bindingParent = content; +#ifdef MOZ_SVG + // least-surprise CSS binding until we do the SVG specified + // cascading rules for - bug 265894 + if (aParent && + aParent->NodeInfo()->Equals(nsGkAtoms::use, kNameSpaceID_SVG)) + bindingParent = aParent; +#endif + + rv = content->BindToTree(aDocument, aParent, bindingParent, PR_TRUE); + if (NS_FAILED(rv)) { + content->UnbindFromTree(); + return rv; + } + + nsIFrame* newFrame = creator->CreateFrameFor(content); + if (newFrame) { + aChildItems.AddChild(newFrame); + } + else { + // create the frame and attach it to our frame + ConstructFrame(aState, content, aParentFrame, aChildItems); + } + + creator->PostCreateFrames(); + } + + // process the current pseudo frame state + if (!aState.mPseudoFrames.IsEmpty()) { + ProcessPseudoFrames(aState, aChildItems); + } + + // restore the incoming pseudo frame state + aState.mPseudoFrames = priorPseudoFrames; + return NS_OK; } diff --git a/mozilla/layout/base/nsIPresShell.h b/mozilla/layout/base/nsIPresShell.h index 8f8e0b30e7e..1768d962038 100644 --- a/mozilla/layout/base/nsIPresShell.h +++ b/mozilla/layout/base/nsIPresShell.h @@ -98,10 +98,10 @@ class nsIScrollableFrame; typedef short SelectionType; -// 2b3dc6f2-1364-4535-9a23-2b728ebbd051 +// 6995eb7c-ffe8-4da2-ae32-c2117a740f0e #define NS_IPRESSHELL_IID \ -{ 0x2b3dc6f2, 0x1364, 0x4535, \ - { 0x9a, 0x23, 0x2b, 0x72, 0x8e, 0xbb, 0xd0, 0x51 } } +{ 0x6995eb7c, 0xffe8, 0x4da2, \ + { 0xae, 0x32, 0xc2, 0x11, 0x7a, 0x74, 0x0f, 0x0e } } // Constants uses for ScrollFrameIntoView() function #define NS_PRESSHELL_SCROLL_TOP 0 @@ -558,36 +558,6 @@ public: */ NS_IMETHOD IsReflowLocked(PRBool* aIsLocked) = 0; - /** - * Store the nsIAnonymousContentCreator-generated anonymous - * content that's associated with an element. The new anonymous content - * is added to whatever anonymous content might already be associated with - * the element. - * @param aContent the element with which the anonymous - * content is to be associated with - * @param aAnonymousElements an array of nsIContent - * objects, or null to indicate that any anonymous - * content should be dissociated from the aContent - */ - NS_IMETHOD SetAnonymousContentFor(nsIContent* aContent, nsISupportsArray* aAnonymousElements) = 0; - - /** - * Retrieve the nsIAnonymousContentCreator-generated anonymous - * content that's associated with an element. - * @param aContent the element for which to retrieve the - * associated anonymous content - * @param aAnonymousElements an array of nsIContent objects, - * or null to indicate that there are no anonymous elements - * associated with aContent - */ - NS_IMETHOD GetAnonymousContentFor(nsIContent* aContent, nsISupportsArray** aAnonymousElements) = 0; - - /** - * Release all nsIAnonymousContentCreator-generated - * anonymous content associated with the shell. - */ - NS_IMETHOD ReleaseAnonymousContent() = 0; - /** * Called to find out if painting is suppressed for this presshell. If it is suppressd, * we don't allow the painting of any layer but the background, and we don't diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 6ae05bc02d2..b57cbfaaeea 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -898,10 +898,6 @@ public: NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, PRBool aLeavingPage); - NS_IMETHOD SetAnonymousContentFor(nsIContent* aContent, nsISupportsArray* aAnonymousElements); - NS_IMETHOD GetAnonymousContentFor(nsIContent* aContent, nsISupportsArray** aAnonymousElements); - NS_IMETHOD ReleaseAnonymousContent(); - NS_IMETHOD IsPaintingSuppressed(PRBool* aResult); NS_IMETHOD UnsuppressPainting(); @@ -1127,7 +1123,6 @@ protected: PRPackedBool mDocumentLoading; PRPackedBool mDocumentOnloadBlocked; PRPackedBool mIsReflowing; - PRPackedBool mIsReleasingAnonymousContent; PRPackedBool mIgnoreFrameDestruction; PRPackedBool mHaveShutDown; @@ -1141,7 +1136,6 @@ protected: nsCOMPtr mCurrentEventContent; nsVoidArray mCurrentEventFrameStack; nsCOMArray mCurrentEventContentStack; - nsSupportsHashtable* mAnonymousContentTable; #ifdef NS_DEBUG nsRect mCurrentTargetRect; @@ -1403,7 +1397,6 @@ PresShell::PresShell() #endif mSelectionFlags = nsISelectionDisplay::DISPLAY_TEXT | nsISelectionDisplay::DISPLAY_IMAGES; mIsThemeSupportDisabled = PR_FALSE; - mIsReleasingAnonymousContent = PR_FALSE; new (this) nsFrameManager(); } @@ -1627,9 +1620,6 @@ PresShell::Destroy() // release our pref style sheet, if we have one still ClearPreferenceStyleRules(); - // free our table of anonymous content - ReleaseAnonymousContent(); - mIsDestroying = PR_TRUE; // We can't release all the event content in @@ -4340,107 +4330,6 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPa return NS_OK; } -NS_IMETHODIMP -PresShell::SetAnonymousContentFor(nsIContent* aContent, nsISupportsArray* aAnonymousElements) -{ - NS_PRECONDITION(aContent != nsnull, "null ptr"); - if (! aContent) - return NS_ERROR_NULL_POINTER; - - if (! mAnonymousContentTable) { - mAnonymousContentTable = new nsSupportsHashtable; - if (! mAnonymousContentTable) - return NS_ERROR_OUT_OF_MEMORY; - } - - nsISupportsKey key(aContent); - - nsCOMPtr oldAnonymousElements = - getter_AddRefs(NS_STATIC_CAST(nsISupportsArray*, mAnonymousContentTable->Get(&key))); - - if (!oldAnonymousElements) { - if (aAnonymousElements) { - mAnonymousContentTable->Put(&key, aAnonymousElements); - } - } else { - if (aAnonymousElements) { - oldAnonymousElements->AppendElements(aAnonymousElements); - } else { - // If we're trying to clear anonymous content for an element that - // already had anonymous content, then we need to be sure to clean - // up after the old content. (This can happen, for example, when a - // reframe occurs.) - PRUint32 count; - oldAnonymousElements->Count(&count); - - while (PRInt32(--count) >= 0) { - nsCOMPtr content = do_QueryElementAt(oldAnonymousElements, - count); - NS_ASSERTION(content != nsnull, "not an nsIContent"); - if (! content) - continue; - - content->UnbindFromTree(); - } - - if (!mIsReleasingAnonymousContent) - mAnonymousContentTable->Remove(&key); - } - } - - return NS_OK; -} - - -NS_IMETHODIMP -PresShell::GetAnonymousContentFor(nsIContent* aContent, nsISupportsArray** aAnonymousElements) -{ - if (! mAnonymousContentTable) { - *aAnonymousElements = nsnull; - return NS_OK; - } - - nsISupportsKey key(aContent); - *aAnonymousElements = - NS_REINTERPRET_CAST(nsISupportsArray*, mAnonymousContentTable->Get(&key)); // addrefs - - return NS_OK; -} - - -static PRBool PR_CALLBACK -ClearDocumentEnumerator(nsHashKey* aKey, void* aData, void* aClosure) -{ - nsISupportsArray* anonymousElements = - NS_STATIC_CAST(nsISupportsArray*, aData); - - PRUint32 count; - anonymousElements->Count(&count); - while (PRInt32(--count) >= 0) { - nsCOMPtr content = do_QueryElementAt(anonymousElements, count); - NS_ASSERTION(content != nsnull, "not an nsIContent"); - if (! content) - continue; - - content->UnbindFromTree(); - } - - return PR_TRUE; -} - - -NS_IMETHODIMP -PresShell::ReleaseAnonymousContent() -{ - if (mAnonymousContentTable) { - mIsReleasingAnonymousContent = PR_TRUE; - mAnonymousContentTable->Enumerate(ClearDocumentEnumerator); - delete mAnonymousContentTable; - mAnonymousContentTable = nsnull; - } - return NS_OK; -} - NS_IMETHODIMP PresShell::IsPaintingSuppressed(PRBool* aResult) { diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index be622c96791..fdee97d683e 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -64,7 +64,6 @@ #include "nsIEventListenerManager.h" #include "nsIDOMNode.h" #include "nsIPrivateDOMEvent.h" -#include "nsISupportsArray.h" #include "nsISelectControlFrame.h" #include "nsXPCOM.h" #include "nsISupportsPrimitives.h" @@ -969,9 +968,8 @@ nsComboboxControlFrame::GetContentInsertionFrame() { return mInRedisplayText ? mDisplayFrame : mDropdownFrame->GetContentInsertionFrame(); } -NS_IMETHODIMP -nsComboboxControlFrame::CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aChildList) +nsresult +nsComboboxControlFrame::CreateAnonymousContent(nsTArray& aElements) { // The frames used to display the combo box and the button used to popup the dropdown list // are created through anonymous content. The dropdown list is not created through anonymous @@ -993,44 +991,48 @@ nsComboboxControlFrame::CreateAnonymousContent(nsPresContext* aPresContext, nsNodeInfoManager *nimgr = mContent->NodeInfo()->NodeInfoManager(); - nsCOMPtr labelContent; - NS_NewTextNode(getter_AddRefs(labelContent), nimgr); + NS_NewTextNode(getter_AddRefs(mDisplayContent), nimgr); + if (!mDisplayContent) + return NS_ERROR_OUT_OF_MEMORY; - if (labelContent) { - // set the value of the text node - mDisplayContent.swap(labelContent); - mDisplayedIndex = mListControlFrame->GetSelectedIndex(); - if (mDisplayedIndex != -1) { - mListControlFrame->GetOptionText(mDisplayedIndex, mDisplayedOptionText); - } - ActuallyDisplayText(PR_FALSE); - - nsCOMPtr nodeInfo; - nimgr->GetNodeInfo(nsGkAtoms::input, nsnull, kNameSpaceID_None, - getter_AddRefs(nodeInfo)); - - aChildList.AppendElement(mDisplayContent); - - // create button which drops the list down - nsCOMPtr btnContent; - nsresult rv = NS_NewHTMLElement(getter_AddRefs(btnContent), nodeInfo); - NS_ENSURE_SUCCESS(rv, rv); - - // make someone to listen to the button. If its pressed by someone like Accessibility - // then open or close the combo box. - nsCOMPtr eventReceiver(do_QueryInterface(btnContent)); - if (eventReceiver) { - mButtonListener = new nsComboButtonListener(this); - eventReceiver->AddEventListenerByIID(mButtonListener, NS_GET_IID(nsIDOMMouseListener)); - } - - btnContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type, NS_LITERAL_STRING("button"), PR_FALSE); - // Set tabindex="-1" so that the button is not tabbable - btnContent->SetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, - NS_LITERAL_STRING("-1"), PR_FALSE); - - aChildList.AppendElement(btnContent); + // set the value of the text node + mDisplayedIndex = mListControlFrame->GetSelectedIndex(); + if (mDisplayedIndex != -1) { + mListControlFrame->GetOptionText(mDisplayedIndex, mDisplayedOptionText); } + ActuallyDisplayText(PR_FALSE); + + if (!aElements.AppendElement(mDisplayContent)) + return NS_ERROR_OUT_OF_MEMORY; + + nsCOMPtr nodeInfo; + nimgr->GetNodeInfo(nsGkAtoms::input, nsnull, kNameSpaceID_None, + getter_AddRefs(nodeInfo)); + + // create button which drops the list down + NS_NewHTMLElement(getter_AddRefs(mButtonContent), nodeInfo); + if (!mButtonContent) + return NS_ERROR_OUT_OF_MEMORY; + + // make someone to listen to the button. If its pressed by someone like Accessibility + // then open or close the combo box. + nsCOMPtr eventReceiver(do_QueryInterface(mButtonContent)); + if (eventReceiver) { + mButtonListener = new nsComboButtonListener(this); + if (!mButtonListener) + return NS_ERROR_OUT_OF_MEMORY; + eventReceiver->AddEventListenerByIID(mButtonListener, + NS_GET_IID(nsIDOMMouseListener)); + } + + mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type, + NS_LITERAL_STRING("button"), PR_FALSE); + // Set tabindex="-1" so that the button is not tabbable + mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, + NS_LITERAL_STRING("-1"), PR_FALSE); + + if (!aElements.AppendElement(mButtonContent)) + return NS_ERROR_OUT_OF_MEMORY; return NS_OK; } @@ -1109,25 +1111,20 @@ NS_NewComboboxDisplayFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, return it; } -NS_IMETHODIMP -nsComboboxControlFrame::CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame) +nsIFrame* +nsComboboxControlFrame::CreateFrameFor(nsIContent* aContent) { - NS_PRECONDITION(nsnull != aFrame, "null ptr"); NS_PRECONDITION(nsnull != aContent, "null ptr"); - NS_PRECONDITION(nsnull != aPresContext, "null ptr"); - *aFrame = nsnull; NS_ASSERTION(mDisplayContent, "mDisplayContent can't be null!"); if (mDisplayContent != aContent) { // We only handle the frames for mDisplayContent here - return NS_ERROR_FAILURE; + return nsnull; } // Get PresShell - nsIPresShell *shell = aPresContext->PresShell(); + nsIPresShell *shell = GetPresContext()->PresShell(); nsStyleSet *styleSet = shell->StyleSet(); // create the style contexts for the anonymous block frame and text frame @@ -1137,32 +1134,32 @@ nsComboboxControlFrame::CreateFrameFor(nsPresContext* aPresContext, nsCSSAnonBoxes::mozDisplayComboboxControlFrame, mStyleContext); if (NS_UNLIKELY(!styleContext)) { - return NS_ERROR_NULL_POINTER; + return nsnull; } nsRefPtr textStyleContext; textStyleContext = styleSet->ResolveStyleForNonElement(styleContext); if (NS_UNLIKELY(!textStyleContext)) { - return NS_ERROR_NULL_POINTER; + return nsnull; } // Start by by creating our anonymous block frame mDisplayFrame = NS_NewComboboxDisplayFrame(shell, styleContext, this); if (NS_UNLIKELY(!mDisplayFrame)) { - return NS_ERROR_OUT_OF_MEMORY; + return nsnull; } nsresult rv = mDisplayFrame->Init(mContent, this, nsnull); if (NS_FAILED(rv)) { mDisplayFrame->Destroy(); mDisplayFrame = nsnull; - return rv; + return nsnull; } // Create a text frame and put it inside the block frame mTextFrame = NS_NewTextFrame(shell, textStyleContext); if (NS_UNLIKELY(!mTextFrame)) { - return NS_ERROR_OUT_OF_MEMORY; + return nsnull; } // initialize the text frame @@ -1172,12 +1169,11 @@ nsComboboxControlFrame::CreateFrameFor(nsPresContext* aPresContext, mDisplayFrame = nsnull; mTextFrame->Destroy(); mTextFrame = nsnull; - return rv; + return nsnull; } mDisplayFrame->SetInitialChildList(nsnull, mTextFrame); - *aFrame = mDisplayFrame; - return NS_OK; + return mDisplayFrame; } void @@ -1195,7 +1191,7 @@ nsComboboxControlFrame::Destroy() nsIView* view = listFrame->GetView(); NS_ASSERTION(view, "nsComboboxControlFrame view is null"); if (view) { - nsIWidget* widget = view->GetWidget(); + nsIWidget* widget = view->GetWidget(); if (widget) widget->CaptureRollupEvents((nsIRollupListener *)this, PR_FALSE, PR_TRUE); } @@ -1204,7 +1200,8 @@ nsComboboxControlFrame::Destroy() // Cleanup frames in popup child list mPopupFrames.DestroyFrames(); - + nsContentUtils::DestroyAnonymousContent(&mDisplayContent); + nsContentUtils::DestroyAnonymousContent(&mButtonContent); nsAreaFrame::Destroy(); } diff --git a/mozilla/layout/forms/nsComboboxControlFrame.h b/mozilla/layout/forms/nsComboboxControlFrame.h index b72ba12736b..e03d496d6a2 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.h +++ b/mozilla/layout/forms/nsComboboxControlFrame.h @@ -96,15 +96,12 @@ public: nsComboboxControlFrame(nsStyleContext* aContext); ~nsComboboxControlFrame(); - // nsISupports + // nsISupports NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); - - // nsIAnonymousContentCreator - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aChildList); - NS_IMETHOD CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame); + + // nsIAnonymousContentCreator + virtual nsresult CreateAnonymousContent(nsTArray& aElements); + virtual nsIFrame* CreateFrameFor(nsIContent* aContent); #ifdef ACCESSIBILITY NS_IMETHOD GetAccessible(nsIAccessible** aAccessible); @@ -227,6 +224,7 @@ protected: nsFrameList mPopupFrames; // additional named child list nsCOMPtr mDisplayContent; // Anonymous content used to display the current selection + nsCOMPtr mButtonContent; // Anonymous content for the button nsIFrame* mDisplayFrame; // frame to display selection nsIFrame* mButtonFrame; // button frame nsIFrame* mDropdownFrame; // dropdown list frame diff --git a/mozilla/layout/forms/nsFileControlFrame.cpp b/mozilla/layout/forms/nsFileControlFrame.cpp index 625c39d8710..d9261482b84 100644 --- a/mozilla/layout/forms/nsFileControlFrame.cpp +++ b/mozilla/layout/forms/nsFileControlFrame.cpp @@ -49,7 +49,6 @@ #include "nsIFormControl.h" #include "nsINameSpaceManager.h" #include "nsCOMPtr.h" -#include "nsISupportsArray.h" #include "nsIDOMElement.h" #include "nsIDOMDocument.h" #include "nsIDocument.h" @@ -119,20 +118,21 @@ nsFileControlFrame::Destroy() nsCOMPtr receiver(do_QueryInterface(mBrowse)); receiver->RemoveEventListenerByIID(mMouseListener, NS_GET_IID(nsIDOMMouseListener)); + nsContentUtils::DestroyAnonymousContent(&mBrowse); } if (mTextContent) { nsCOMPtr receiver(do_QueryInterface(mTextContent)); receiver->RemoveEventListenerByIID(mMouseListener, NS_GET_IID(nsIDOMMouseListener)); + nsContentUtils::DestroyAnonymousContent(&mTextContent); } mMouseListener->ForgetFrame(); nsAreaFrame::Destroy(); } -NS_IMETHODIMP -nsFileControlFrame::CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aChildList) +nsresult +nsFileControlFrame::CreateAnonymousContent(nsTArray& aElements) { // Get the NodeInfoManager and tag necessary to create input elements nsCOMPtr doc = mContent->GetDocument(); @@ -143,66 +143,64 @@ nsFileControlFrame::CreateAnonymousContent(nsPresContext* aPresContext, getter_AddRefs(nodeInfo)); // Create the text content - nsCOMPtr content; - nsresult rv = NS_NewHTMLElement(getter_AddRefs(content), nodeInfo); - NS_ENSURE_SUCCESS(rv, rv); + NS_NewHTMLElement(getter_AddRefs(mTextContent), nodeInfo); + if (!mTextContent) + return NS_ERROR_OUT_OF_MEMORY; - content.swap(mTextContent); + mTextContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type, + NS_LITERAL_STRING("text"), PR_FALSE); - if (mTextContent) { - mTextContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type, NS_LITERAL_STRING("text"), PR_FALSE); - - nsCOMPtr textControl = do_QueryInterface(mTextContent); - if (textControl) { - nsCOMPtr fileControl = do_QueryInterface(mContent); - if (fileControl) { - // Initialize value when we create the content in case the value was set - // before we got here - nsAutoString value; - fileControl->GetFileName(value); - textControl->SetValue(value); - } - - textControl->SetTabIndex(-1); - textControl->SetDisabled(PR_TRUE); - textControl->SetReadOnly(PR_TRUE); + nsCOMPtr textControl = do_QueryInterface(mTextContent); + if (textControl) { + nsCOMPtr fileControl = do_QueryInterface(mContent); + if (fileControl) { + // Initialize value when we create the content in case the value was set + // before we got here + nsAutoString value; + fileControl->GetFileName(value); + textControl->SetValue(value); } - aChildList.AppendElement(mTextContent); - - // register as an event listener of the textbox to open file dialog on mouse click - nsCOMPtr receiver(do_QueryInterface(mTextContent)); - receiver->AddEventListenerByIID(mMouseListener, - NS_GET_IID(nsIDOMMouseListener)); + textControl->SetTabIndex(-1); + textControl->SetDisabled(PR_TRUE); + textControl->SetReadOnly(PR_TRUE); } + if (!aElements.AppendElement(mTextContent)) + return NS_ERROR_OUT_OF_MEMORY; + + // register as an event listener of the textbox to open file dialog on mouse click + nsCOMPtr receiver = do_QueryInterface(mTextContent); + receiver->AddEventListenerByIID(mMouseListener, + NS_GET_IID(nsIDOMMouseListener)); + // Create the browse button - rv = NS_NewHTMLElement(getter_AddRefs(content), nodeInfo); - NS_ENSURE_SUCCESS(rv, rv); + NS_NewHTMLElement(getter_AddRefs(mBrowse), nodeInfo); + if (!mBrowse) + return NS_ERROR_OUT_OF_MEMORY; - mBrowse = do_QueryInterface(content); - if (mBrowse) { - mBrowse->SetAttr(kNameSpaceID_None, nsGkAtoms::type, NS_LITERAL_STRING("button"), PR_FALSE); - nsCOMPtr fileContent = do_QueryInterface(mContent); - nsCOMPtr browseControl = do_QueryInterface(mBrowse); - if (fileContent && browseControl) { - PRInt32 tabIndex; - nsAutoString accessKey; - - fileContent->GetAccessKey(accessKey); - browseControl->SetAccessKey(accessKey); - fileContent->GetTabIndex(&tabIndex); - browseControl->SetTabIndex(tabIndex); - } + mBrowse->SetAttr(kNameSpaceID_None, nsGkAtoms::type, + NS_LITERAL_STRING("button"), PR_FALSE); + nsCOMPtr fileContent = do_QueryInterface(mContent); + nsCOMPtr browseControl = do_QueryInterface(mBrowse); + if (fileContent && browseControl) { + PRInt32 tabIndex; + nsAutoString accessKey; - aChildList.AppendElement(mBrowse); - - // register as an event listener of the button to open file dialog on mouse click - nsCOMPtr receiver(do_QueryInterface(mBrowse)); - receiver->AddEventListenerByIID(mMouseListener, - NS_GET_IID(nsIDOMMouseListener)); + fileContent->GetAccessKey(accessKey); + browseControl->SetAccessKey(accessKey); + fileContent->GetTabIndex(&tabIndex); + browseControl->SetTabIndex(tabIndex); } + if (!aElements.AppendElement(mBrowse)) + return NS_ERROR_OUT_OF_MEMORY; + + // register as an event listener of the button to open file dialog on mouse click + receiver = do_QueryInterface(mBrowse); + receiver->AddEventListenerByIID(mMouseListener, + NS_GET_IID(nsIDOMMouseListener)); + SyncAttr(kNameSpaceID_None, nsGkAtoms::size, SYNC_TEXT); SyncAttr(kNameSpaceID_None, nsGkAtoms::disabled, SYNC_BOTH); diff --git a/mozilla/layout/forms/nsFileControlFrame.h b/mozilla/layout/forms/nsFileControlFrame.h index 79e427fa276..b248ca3658c 100644 --- a/mozilla/layout/forms/nsFileControlFrame.h +++ b/mozilla/layout/forms/nsFileControlFrame.h @@ -47,8 +47,6 @@ #include "nsTextControlFrame.h" typedef nsTextControlFrame nsNewFrame; -class nsISupportsArray; - class nsFileControlFrame : public nsAreaFrame, public nsIFormControlFrame, public nsIAnonymousContentCreator @@ -92,12 +90,8 @@ public: - // from nsIAnonymousContentCreator - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aChildList); - NS_IMETHOD CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } + // nsIAnonymousContentCreator + virtual nsresult CreateAnonymousContent(nsTArray& aElements); protected: class MouseListener; diff --git a/mozilla/layout/forms/nsGfxButtonControlFrame.cpp b/mozilla/layout/forms/nsGfxButtonControlFrame.cpp index ca36a668d03..e34d5013dce 100644 --- a/mozilla/layout/forms/nsGfxButtonControlFrame.cpp +++ b/mozilla/layout/forms/nsGfxButtonControlFrame.cpp @@ -40,7 +40,6 @@ #include "nsIFontMetrics.h" #include "nsFormControlFrame.h" #include "nsIFormControl.h" -#include "nsISupportsArray.h" #include "nsINameSpaceManager.h" #ifdef ACCESSIBILITY #include "nsIAccessibilityService.h" @@ -70,7 +69,13 @@ NS_NewGfxButtonControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) { return new (aPresShell) nsGfxButtonControlFrame(aContext); } - + +void nsGfxButtonControlFrame::Destroy() +{ + nsContentUtils::DestroyAnonymousContent(&mTextContent); + nsHTMLButtonControlFrame::Destroy(); +} + nsIAtom* nsGfxButtonControlFrame::GetType() const { @@ -105,63 +110,66 @@ nsGfxButtonControlFrame::GetFrameName(nsAString& aResult) const // Create the text content used as label for the button. // The frame will be generated by the frame constructor. -NS_IMETHODIMP -nsGfxButtonControlFrame::CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aChildList) +nsresult +nsGfxButtonControlFrame::CreateAnonymousContent(nsTArray& aElements) { nsXPIDLString label; GetLabel(label); - + // Add a child text content node for the label - nsCOMPtr labelContent; - NS_NewTextNode(getter_AddRefs(labelContent), + NS_NewTextNode(getter_AddRefs(mTextContent), mContent->NodeInfo()->NodeInfoManager()); - if (labelContent) { - // set the value of the text node and add it to the child list - mTextContent.swap(labelContent); - mTextContent->SetText(label, PR_FALSE); - aChildList.AppendElement(mTextContent); - } + if (!mTextContent) + return NS_ERROR_OUT_OF_MEMORY; + + // set the value of the text node and add it to the child list + mTextContent->SetText(label, PR_FALSE); + if (!aElements.AppendElement(mTextContent)) + return NS_ERROR_OUT_OF_MEMORY; return NS_OK; } // Create the text content used as label for the button. // The frame will be generated by the frame constructor. -NS_IMETHODIMP -nsGfxButtonControlFrame::CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame) +nsIFrame* +nsGfxButtonControlFrame::CreateFrameFor(nsIContent* aContent) { nsIFrame * newFrame = nsnull; - nsresult rv = NS_ERROR_FAILURE; - - if (aFrame) - *aFrame = nsnull; if (aContent == mTextContent) { nsIFrame * parentFrame = mFrames.FirstChild(); nsStyleContext* styleContext = parentFrame->GetStyleContext(); + nsPresContext* presContext = GetPresContext(); nsRefPtr textStyleContext; - textStyleContext = aPresContext->StyleSet()-> + textStyleContext = presContext->StyleSet()-> ResolveStyleForNonElement(styleContext); - if (!textStyleContext) { return NS_ERROR_NULL_POINTER; } - if (styleContext) { - newFrame = NS_NewTextFrame(aPresContext->PresShell(), textStyleContext); - if (NS_UNLIKELY(!newFrame)) { - return NS_ERROR_OUT_OF_MEMORY; + if (textStyleContext && styleContext) { + newFrame = NS_NewTextFrame(presContext->PresShell(), textStyleContext); + if (newFrame) { + // initialize the text frame + newFrame->Init(mTextContent, parentFrame, nsnull); + newFrame->SetInitialChildList(nsnull, nsnull); } - - // initialize the text frame - newFrame->Init(mTextContent, parentFrame, nsnull); - newFrame->SetInitialChildList(nsnull, nsnull); - rv = NS_OK; } } - if (aFrame) { - *aFrame = newFrame; + return newFrame; +} + +nsresult +nsGfxButtonControlFrame::GetFormProperty(nsIAtom* aName, nsAString& aValue) const +{ + nsresult rv = NS_OK; + if (nsGkAtoms::defaultLabel == aName) { + // This property is used by accessibility to get + // the default label of the button. + nsXPIDLString temp; + rv = NS_CONST_CAST(nsGfxButtonControlFrame*, this)->GetDefaultLabel(temp); + aValue = temp; + } else { + aValue.Truncate(); } return rv; } @@ -202,7 +210,7 @@ else { // label from a string bundle as is done for all other UI strings. // See bug 16999 for further details. nsresult -nsGfxButtonControlFrame::GetDefaultLabel(nsXPIDLString& aString) +nsGfxButtonControlFrame::GetDefaultLabel(nsXPIDLString& aString) { nsCOMPtr form = do_QueryInterface(mContent); NS_ENSURE_TRUE(form, NS_ERROR_UNEXPECTED); diff --git a/mozilla/layout/forms/nsGfxButtonControlFrame.h b/mozilla/layout/forms/nsGfxButtonControlFrame.h index 9225be489bb..98fc5d6fa22 100644 --- a/mozilla/layout/forms/nsGfxButtonControlFrame.h +++ b/mozilla/layout/forms/nsGfxButtonControlFrame.h @@ -58,6 +58,8 @@ class nsGfxButtonControlFrame : public nsHTMLButtonControlFrame, public: nsGfxButtonControlFrame(nsStyleContext* aContext); + virtual void Destroy(); + NS_IMETHOD HandleEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus); @@ -74,13 +76,14 @@ public: #endif NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); - + // nsIAnonymousContentCreator - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aChildList); - NS_IMETHOD CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame); + virtual nsresult CreateAnonymousContent(nsTArray& aElements); + virtual nsIFrame* CreateFrameFor(nsIContent* aContent); + + // nsIFormControlFrame + virtual nsresult GetFormProperty(nsIAtom* aName, nsAString& aValue) const; + NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, diff --git a/mozilla/layout/forms/nsIsIndexFrame.cpp b/mozilla/layout/forms/nsIsIndexFrame.cpp index c70556635a7..c3254135d14 100644 --- a/mozilla/layout/forms/nsIsIndexFrame.cpp +++ b/mozilla/layout/forms/nsIsIndexFrame.cpp @@ -49,7 +49,6 @@ #include "nsIDOMHTMLInputElement.h" #include "nsINameSpaceManager.h" #include "nsCOMPtr.h" -#include "nsISupportsArray.h" #include "nsIDOMElement.h" #include "nsIDOMDocument.h" #include "nsIDocument.h" @@ -99,6 +98,16 @@ nsIsIndexFrame::~nsIsIndexFrame() } } +void +nsIsIndexFrame::Destroy() +{ + nsContentUtils::DestroyAnonymousContent(&mTextContent); + nsContentUtils::DestroyAnonymousContent(&mInputContent); + nsContentUtils::DestroyAnonymousContent(&mPreHr); + nsContentUtils::DestroyAnonymousContent(&mPostHr); + nsAreaFrame::Destroy(); +} + // REVIEW: We don't need to override BuildDisplayList, nsAreaFrame will honour // our visibility setting @@ -174,12 +183,9 @@ nsIsIndexFrame::SetFocus(PRBool aOn, PRBool aRepaint) } } -NS_IMETHODIMP -nsIsIndexFrame::CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aChildList) +nsresult +nsIsIndexFrame::CreateAnonymousContent(nsTArray& aElements) { - nsresult result; - // Get the node info manager (used to create hr's and input's) nsCOMPtr doc = mContent->GetDocument(); nsNodeInfoManager *nimgr = doc->NodeInfoManager(); @@ -189,48 +195,45 @@ nsIsIndexFrame::CreateAnonymousContent(nsPresContext* aPresContext, nimgr->GetNodeInfo(nsGkAtoms::hr, nsnull, kNameSpaceID_None, getter_AddRefs(hrInfo)); - nsCOMPtr prehr; - result = NS_NewHTMLElement(getter_AddRefs(prehr), hrInfo); - NS_ENSURE_SUCCESS(result, result); - - result = aChildList.AppendElement(prehr); + NS_NewHTMLElement(getter_AddRefs(mPreHr), hrInfo); + if (!mPreHr || !aElements.AppendElement(mPreHr)) + return NS_ERROR_OUT_OF_MEMORY; // Add a child text content node for the label - if (NS_SUCCEEDED(result)) { - nsCOMPtr labelContent; - NS_NewTextNode(getter_AddRefs(labelContent), nimgr); - if (labelContent) { - // set the value of the text node and add it to the child list - mTextContent.swap(labelContent); - UpdatePromptLabel(); - aChildList.AppendElement(mTextContent); - } - } + NS_NewTextNode(getter_AddRefs(mTextContent), nimgr); + if (!mTextContent) + return NS_ERROR_OUT_OF_MEMORY; + + // set the value of the text node and add it to the child list + UpdatePromptLabel(); + if (!aElements.AppendElement(mTextContent)) + return NS_ERROR_OUT_OF_MEMORY; // Create text input field nsCOMPtr inputInfo; nimgr->GetNodeInfo(nsGkAtoms::input, nsnull, kNameSpaceID_None, getter_AddRefs(inputInfo)); - result = NS_NewHTMLElement(getter_AddRefs(mInputContent), inputInfo); - NS_ENSURE_SUCCESS(result, result); + NS_NewHTMLElement(getter_AddRefs(mInputContent), inputInfo); + if (!mInputContent) + return NS_ERROR_OUT_OF_MEMORY; - mInputContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type, NS_LITERAL_STRING("text"), PR_FALSE); + mInputContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type, + NS_LITERAL_STRING("text"), PR_FALSE); - aChildList.AppendElement(mInputContent); + if (!aElements.AppendElement(mInputContent)) + return NS_ERROR_OUT_OF_MEMORY; // Register as an event listener to submit on Enter press nsCOMPtr receiver(do_QueryInterface(mInputContent)); receiver->AddEventListenerByIID(this, NS_GET_IID(nsIDOMKeyListener)); // Create an hr - nsCOMPtr posthr; - result = NS_NewHTMLElement(getter_AddRefs(posthr), hrInfo); - NS_ENSURE_SUCCESS(result, result); + NS_NewHTMLElement(getter_AddRefs(mPostHr), hrInfo); + if (!mPostHr || !aElements.AppendElement(mPostHr)) + return NS_ERROR_OUT_OF_MEMORY; - aChildList.AppendElement(posthr); - - return result; + return NS_OK; } // Frames are not refcounted, no need to AddRef diff --git a/mozilla/layout/forms/nsIsIndexFrame.h b/mozilla/layout/forms/nsIsIndexFrame.h index 1c2d8984b89..98d4a83fb0b 100644 --- a/mozilla/layout/forms/nsIsIndexFrame.h +++ b/mozilla/layout/forms/nsIsIndexFrame.h @@ -48,8 +48,6 @@ #include "nsTextControlFrame.h" typedef nsTextControlFrame nsNewFrame; -class nsISupportsArray; - class nsIsIndexFrame : public nsAreaFrame, public nsIAnonymousContentCreator, public nsIDOMKeyListener, @@ -59,6 +57,8 @@ public: nsIsIndexFrame(nsStyleContext* aContext); virtual ~nsIsIndexFrame(); + virtual void Destroy(); + /** * Processes a key pressed event * @param aKeyEvent @see nsIDOMEvent.h @@ -97,12 +97,8 @@ public: void SetFocus(PRBool aOn, PRBool aRepaint); - // from nsIAnonymousContentCreator - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aChildList); - NS_IMETHOD CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } + // nsIAnonymousContentCreator + virtual nsresult CreateAnonymousContent(nsTArray& aElements); NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; } @@ -113,8 +109,12 @@ public: NS_IMETHOD RestoreState(nsPresState* aState); protected: + // native anonymous content generated by this frame when + // asked via the nsIAnonymousContentCreator interface. nsCOMPtr mTextContent; nsCOMPtr mInputContent; + nsCOMPtr mPreHr; + nsCOMPtr mPostHr; private: NS_IMETHOD UpdatePromptLabel(); diff --git a/mozilla/layout/forms/nsTextControlFrame.cpp b/mozilla/layout/forms/nsTextControlFrame.cpp index f3ec1e45df3..4a3663ae4cb 100644 --- a/mozilla/layout/forms/nsTextControlFrame.cpp +++ b/mozilla/layout/forms/nsTextControlFrame.cpp @@ -76,7 +76,6 @@ #include "nsIView.h" #include "nsIViewManager.h" #include "nsIDOMHTMLInputElement.h" -#include "nsISupportsArray.h" #include "nsIDOMElement.h" #include "nsIDOMDocument.h" #include "nsIPresShell.h" @@ -1165,6 +1164,7 @@ nsTextControlFrame::Destroy() if (!mDidPreDestroy) { PreDestroy(); } + nsContentUtils::DestroyAnonymousContent(&mAnonymousDiv); nsBoxFrame::Destroy(); } @@ -1351,26 +1351,22 @@ void nsTextControlFrame::PostCreateFrames() { InitEditor(); } -NS_IMETHODIMP -nsTextControlFrame::CreateFrameFor(nsPresContext* aPresContext, - nsIContent* aContent, - nsIFrame** aFrame) +nsIFrame* +nsTextControlFrame::CreateFrameFor(nsIContent* aContent) { #ifdef DEBUG NS_ASSERTION(!mCreateFrameForCalled, "CreateFrameFor called more than once!"); mCreateFrameForCalled = PR_TRUE; #endif - // Note, we must set aFrame to nsnull. - *aFrame = nsnull; - - nsIPresShell *shell = aPresContext->GetPresShell(); + nsPresContext *presContext = GetPresContext(); + nsIPresShell *shell = presContext->GetPresShell(); if (!shell) - return NS_ERROR_FAILURE; + return nsnull; nsCOMPtr domdoc = do_QueryInterface(shell->GetDocument()); if (!domdoc) - return NS_ERROR_FAILURE; + return nsnull; // Don't create any frames here, but just setup the editor. // This way DOM Ranges (which editor uses) work properly since the anonymous @@ -1378,26 +1374,24 @@ nsTextControlFrame::CreateFrameFor(nsPresContext* aPresContext, // method. nsresult rv = NS_OK; mEditor = do_CreateInstance(kTextEditorCID, &rv); - if (NS_FAILED(rv)) - return rv; - if (!mEditor) - return NS_ERROR_OUT_OF_MEMORY; + if (NS_FAILED(rv) || !mEditor) + return nsnull; // Create selection mFrameSel = do_CreateInstance(kFrameSelectionCID, &rv); if (NS_FAILED(rv)) - return rv; + return nsnull; // Create a SelectionController mSelCon = NS_STATIC_CAST(nsISelectionController*, new nsTextInputSelectionImpl(mFrameSel, shell, aContent)); if (!mSelCon) - return NS_ERROR_OUT_OF_MEMORY; + return nsnull; mTextListener = new nsTextInputListener(); if (!mTextListener) - return NS_ERROR_OUT_OF_MEMORY; + return nsnull; NS_ADDREF(mTextListener); mTextListener->SetFrame(this); @@ -1432,11 +1426,11 @@ nsTextControlFrame::CreateFrameFor(nsPresContext* aPresContext, rv = mEditor->Init(domdoc, shell, aContent, mSelCon, editorFlags); if (NS_FAILED(rv)) - return rv; + return nsnull; // Initialize the controller for the editor - if (!SuppressEventHandlers(aPresContext)) { + if (!SuppressEventHandlers(presContext)) { nsCOMPtr controllers; nsCOMPtr inputElement = do_QueryInterface(mContent); @@ -1447,13 +1441,13 @@ nsTextControlFrame::CreateFrameFor(nsPresContext* aPresContext, do_QueryInterface(mContent); if (!textAreaElement) - return NS_ERROR_FAILURE; + return nsnull; rv = textAreaElement->GetControllers(getter_AddRefs(controllers)); } if (NS_FAILED(rv)) - return rv; + return nsnull; if (controllers) { PRUint32 numControllers; @@ -1528,7 +1522,7 @@ nsTextControlFrame::CreateFrameFor(nsPresContext* aPresContext, rv = mEditor->GetFlags(&editorFlags); if (NS_FAILED(rv)) - return rv; + return nsnull; // Check if the readonly attribute is set. @@ -1547,7 +1541,7 @@ nsTextControlFrame::CreateFrameFor(nsPresContext* aPresContext, mEditor->SetFlags(editorFlags); } - return NS_OK; + return nsnull; } nsresult @@ -1646,21 +1640,15 @@ nsTextControlFrame::InitEditor() return NS_OK; } -NS_IMETHODIMP -nsTextControlFrame::CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aChildList) +nsresult +nsTextControlFrame::CreateAnonymousContent(nsTArray& aElements) { - // Get the PresShell - mState |= NS_FRAME_INDEPENDENT_SELECTION; - nsIPresShell *shell = aPresContext->GetPresShell(); - + nsIPresShell* shell = GetPresContext()->GetPresShell(); if (!shell) return NS_ERROR_FAILURE; - // Get the DOM document - nsIDocument *doc = shell->GetDocument(); if (!doc) return NS_ERROR_FAILURE; @@ -1670,30 +1658,20 @@ nsTextControlFrame::CreateAnonymousContent(nsPresContext* aPresContext, nsresult rv = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::div, nsnull, kNameSpaceID_XHTML, getter_AddRefs(nodeInfo)); + NS_ENSURE_SUCCESS(rv, rv); - if (NS_FAILED(rv)) - return rv; - - if (!nodeInfo) - return NS_ERROR_FAILURE; - - nsCOMPtr divContent; - rv = NS_NewHTMLElement(getter_AddRefs(divContent), nodeInfo); - - if (NS_FAILED(rv)) - return rv; - - if (!divContent) - return NS_ERROR_FAILURE; + rv = NS_NewHTMLElement(getter_AddRefs(mAnonymousDiv), nodeInfo); + NS_ENSURE_SUCCESS(rv, rv); // Set the div native anonymous, so CSS will be its style language // no matter what. - divContent->SetNativeAnonymous(PR_TRUE); + mAnonymousDiv->SetNativeAnonymous(PR_TRUE); // Set the necessary style attributes on the text control. - rv = divContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, - NS_LITERAL_STRING("anonymous-div"), PR_FALSE); + rv = mAnonymousDiv->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, + NS_LITERAL_STRING("anonymous-div"), PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); if (!IsSingleLineTextControl()) { // We can't just inherit the overflow because setting visible overflow will @@ -1703,17 +1681,18 @@ nsTextControlFrame::CreateAnonymousContent(nsPresContext* aPresContext, const nsStyleDisplay* disp = GetStyleDisplay(); if (disp->mOverflowX != NS_STYLE_OVERFLOW_VISIBLE && disp->mOverflowX != NS_STYLE_OVERFLOW_CLIP) { - rv = divContent->SetAttr(kNameSpaceID_None, nsGkAtoms::style, - NS_LITERAL_STRING("overflow: inherit;"), - PR_FALSE); + rv = mAnonymousDiv->SetAttr(kNameSpaceID_None, nsGkAtoms::style, + NS_LITERAL_STRING("overflow: inherit;"), + PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); } } - if (NS_FAILED(rv)) - return rv; + if (!aElements.AppendElement(mAnonymousDiv)) + return NS_ERROR_OUT_OF_MEMORY; // rv = divContent->SetAttr(kNameSpaceID_None,nsGkAtoms::debug, NS_LITERAL_STRING("true"), PR_FALSE); - return aChildList.AppendElement(divContent); + return NS_OK; } nscoord diff --git a/mozilla/layout/forms/nsTextControlFrame.h b/mozilla/layout/forms/nsTextControlFrame.h index c2adf0cb7e4..71a59cce68a 100644 --- a/mozilla/layout/forms/nsTextControlFrame.h +++ b/mozilla/layout/forms/nsTextControlFrame.h @@ -52,7 +52,6 @@ #include "nsContentUtils.h" #include "nsDisplayList.h" -class nsISupportsArray; class nsIEditor; class nsISelectionController; class nsTextInputSelectionImpl; @@ -110,12 +109,9 @@ public: virtual PRBool IsFrameOfType(PRUint32 aFlags) const; - // from nsIAnonymousContentCreator - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aChildList); - NS_IMETHOD CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame); + // nsIAnonymousContentCreator + virtual nsresult CreateAnonymousContent(nsTArray& aElements); + virtual nsIFrame* CreateFrameFor(nsIContent* aContent); virtual void PostCreateFrames(); // Utility methods to set current widget state @@ -274,6 +270,8 @@ private: nsresult SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd); private: + nsCOMPtr mAnonymousDiv; + nsCOMPtr mEditor; // these packed bools could instead use the high order bits on mState, saving 4 bytes diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index 920b05c1f52..d890ef3294a 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -283,6 +283,20 @@ nsBlockFrame::~nsBlockFrame() void nsBlockFrame::Destroy() { + if (mState & NS_FRAME_GENERATED_CONTENT) { + // Make sure all the content nodes for the generated content inside + // this frame know it's going away. + // This is duplicated in nsInlineFrame::Destroy + // See also nsCSSFrameConstructor::CreateGeneratedContentFrame which + // created this frame. + + // XXXbz would this be better done via a global structure in + // nsCSSFrameConstructor that could key off of + // GeneratedContentFrameRemoved or something? The problem is that + // our kids are gone by the time that's called. + nsContainerFrame::CleanupGeneratedContentIn(mContent, this); + } + mAbsoluteContainer.DestroyFrames(this); // Outside bullets are not in our child-list so check for them here // and delete them when present. diff --git a/mozilla/layout/generic/nsContainerFrame.cpp b/mozilla/layout/generic/nsContainerFrame.cpp index 7a92dd416ba..516b804b251 100644 --- a/mozilla/layout/generic/nsContainerFrame.cpp +++ b/mozilla/layout/generic/nsContainerFrame.cpp @@ -239,8 +239,9 @@ nsContainerFrame::RemoveFrame(nsIAtom* aListName, return NS_OK; } -static void -CleanupGeneratedContentIn(nsIContent* aRealContent, nsIFrame* aRoot) { +void +nsContainerFrame::CleanupGeneratedContentIn(nsIContent* aRealContent, + nsIFrame* aRoot) { nsIAtom* frameList = nsnull; PRInt32 listIndex = 0; do { @@ -253,7 +254,7 @@ CleanupGeneratedContentIn(nsIContent* aRealContent, nsIFrame* aRoot) { aRoot->GetPresContext()->EventStateManager()->ContentRemoved(content); content->UnbindFromTree(); } - ::CleanupGeneratedContentIn(aRealContent, child); + CleanupGeneratedContentIn(aRealContent, child); child = child->GetNextSibling(); } frameList = aRoot->GetAdditionalChildListName(listIndex++); @@ -268,16 +269,6 @@ nsContainerFrame::Destroy() GetView()->SetClientData(nsnull); } - if (mState & NS_FRAME_GENERATED_CONTENT) { - // Make sure all the content nodes for the generated content inside - // this frame know it's going away. - // XXXbz would this be better done via a global structure in - // nsCSSFrameConstructor that could key off of - // GeneratedContentFrameRemoved or something? The problem is that - // our kids are gone by the time that's called. - ::CleanupGeneratedContentIn(mContent, this); - } - // Delete the primary child list mFrames.DestroyFrames(); diff --git a/mozilla/layout/generic/nsContainerFrame.h b/mozilla/layout/generic/nsContainerFrame.h index 64b89af7c1f..69597dd5a42 100644 --- a/mozilla/layout/generic/nsContainerFrame.h +++ b/mozilla/layout/generic/nsContainerFrame.h @@ -269,6 +269,14 @@ protected: nsIFrame* aFromChild, nsIFrame* aPrevSibling); + /** + * A helper for frames corresponding to generated content, which is used to + * remove the generated content from the tree when the :before or :after + * frame is destroyed. + */ + static void CleanupGeneratedContentIn(nsIContent* aRealContent, + nsIFrame* aRoot); + nsFrameList mFrames; }; diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp index df8260ac4eb..025d98a72e3 100644 --- a/mozilla/layout/generic/nsFrame.cpp +++ b/mozilla/layout/generic/nsFrame.cpp @@ -3845,32 +3845,15 @@ PRInt32 nsFrame::ContentIndexInContainer(const nsIFrame* aFrame) return result; } -#ifdef DEBUG_waterson - -/** - * List a single frame to stdout. Meant to be called from gdb. - */ -void -DebugListFrame(nsPresContext* aPresContext, nsIFrame* aFrame) -{ - ((nsFrame*) aFrame)->List(stdout, 0); - printf("\n"); -} - /** * List a frame tree to stdout. Meant to be called from gdb. */ void -DebugListFrameTree(nsPresContext* aPresContext, nsIFrame* aFrame) +DebugListFrameTree(nsIFrame* aFrame) { - nsIFrameDebug* fdbg; - aFrame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**) &fdbg); - if (fdbg) - fdbg->List(stdout, 0); + ((nsFrame*)aFrame)->List(stdout, 0); } -#endif - // Debugging NS_IMETHODIMP diff --git a/mozilla/layout/generic/nsGfxScrollFrame.cpp b/mozilla/layout/generic/nsGfxScrollFrame.cpp index 361a8ffc534..fbe0186af26 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.cpp +++ b/mozilla/layout/generic/nsGfxScrollFrame.cpp @@ -51,7 +51,6 @@ #include "nsGfxScrollFrame.h" #include "nsGkAtoms.h" #include "nsINameSpaceManager.h" -#include "nsISupportsArray.h" #include "nsIDocument.h" #include "nsIFontMetrics.h" #include "nsIDocumentObserver.h" @@ -73,6 +72,7 @@ #include "nsDocShellCID.h" #include "nsIDOMHTMLDocument.h" #include "nsEventDispatcher.h" +#include "nsContentUtils.h" #include "nsLayoutUtils.h" #ifdef ACCESSIBILITY #include "nsIAccessibilityService.h" @@ -144,12 +144,10 @@ nsIBox* nsHTMLScrollFrame::GetScrollbarBox(PRBool aVertical) return aVertical ? mInner.mVScrollbarBox : mInner.mHScrollbarBox; } -NS_IMETHODIMP -nsHTMLScrollFrame::CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousChildren) +nsresult +nsHTMLScrollFrame::CreateAnonymousContent(nsTArray& aElements) { - mInner.CreateAnonymousContent(aAnonymousChildren); - return NS_OK; + return mInner.CreateAnonymousContent(aElements); } void @@ -161,6 +159,7 @@ nsHTMLScrollFrame::Destroy() NS_ASSERTION(view, "unexpected null pointer"); if (view) view->RemoveScrollPositionListener(&mInner); + mInner.Destroy(); nsHTMLContainerFrame::Destroy(); } @@ -950,12 +949,10 @@ nsIBox* nsXULScrollFrame::GetScrollbarBox(PRBool aVertical) return aVertical ? mInner.mVScrollbarBox : mInner.mHScrollbarBox; } -NS_IMETHODIMP -nsXULScrollFrame::CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousChildren) +nsresult +nsXULScrollFrame::CreateAnonymousContent(nsTArray& aElements) { - mInner.CreateAnonymousContent(aAnonymousChildren); - return NS_OK; + return mInner.CreateAnonymousContent(aElements); } void @@ -967,6 +964,7 @@ nsXULScrollFrame::Destroy() NS_ASSERTION(view, "unexpected null pointer"); if (view) view->RemoveScrollPositionListener(&mInner); + mInner.Destroy(); nsBoxFrame::Destroy(); } @@ -1623,8 +1621,8 @@ nsGfxScrollFrameInner::ReloadChildFrames() } } -void -nsGfxScrollFrameInner::CreateAnonymousContent(nsISupportsArray& aAnonymousChildren) +nsresult +nsGfxScrollFrameInner::CreateAnonymousContent(nsTArray& aElements) { nsPresContext* presContext = mOuter->GetPresContext(); nsIFrame* parent = mOuter->GetParent(); @@ -1636,7 +1634,7 @@ nsGfxScrollFrameInner::CreateAnonymousContent(nsISupportsArray& aAnonymousChildr // we must be the scrollbars for the print preview window if (!(mIsRoot && presContext->HasPaginatedScrolling())) { mNeverHasVerticalScrollbar = mNeverHasHorizontalScrollbar = PR_TRUE; - return; + return NS_OK; } } @@ -1660,9 +1658,10 @@ nsGfxScrollFrameInner::CreateAnonymousContent(nsISupportsArray& aAnonymousChildr ScrollbarStyles styles = scrollable->GetScrollbarStyles(); PRBool canHaveHorizontal = styles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN; PRBool canHaveVertical = styles.mVertical != NS_STYLE_OVERFLOW_HIDDEN; - if (!canHaveHorizontal && !canHaveVertical) + if (!canHaveHorizontal && !canHaveVertical) { // Nothing to do. - return; + return NS_OK; + } // The anonymous
used by never gets scrollbars. nsCOMPtr textFrame(do_QueryInterface(parent)); @@ -1671,38 +1670,59 @@ nsGfxScrollFrameInner::CreateAnonymousContent(nsISupportsArray& aAnonymousChildr nsCOMPtr textAreaElement(do_QueryInterface(parent->GetContent())); if (!textAreaElement) { mNeverHasVerticalScrollbar = mNeverHasHorizontalScrollbar = PR_TRUE; - return; + return NS_OK; } } + nsresult rv; + nsNodeInfoManager *nodeInfoManager = presContext->Document()->NodeInfoManager(); nsCOMPtr nodeInfo; - nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbar, nsnull, - kNameSpaceID_XUL, getter_AddRefs(nodeInfo)); - - nsCOMPtr content; + rv = nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbar, nsnull, + kNameSpaceID_XUL, getter_AddRefs(nodeInfo)); + NS_ENSURE_SUCCESS(rv, rv); if (canHaveHorizontal) { - NS_NewElement(getter_AddRefs(content), kNameSpaceID_XUL, nodeInfo); - content->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, - NS_LITERAL_STRING("horizontal"), PR_FALSE); - aAnonymousChildren.AppendElement(content); + rv = NS_NewElement(getter_AddRefs(mHScrollbarContent), + kNameSpaceID_XUL, nodeInfo); + NS_ENSURE_SUCCESS(rv, rv); + mHScrollbarContent->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, + NS_LITERAL_STRING("horizontal"), PR_FALSE); + if (!aElements.AppendElement(mHScrollbarContent)) + return NS_ERROR_OUT_OF_MEMORY; } if (canHaveVertical) { - NS_NewElement(getter_AddRefs(content), kNameSpaceID_XUL, nodeInfo); - content->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, - NS_LITERAL_STRING("vertical"), PR_FALSE); - aAnonymousChildren.AppendElement(content); + rv = NS_NewElement(getter_AddRefs(mVScrollbarContent), + kNameSpaceID_XUL, nodeInfo); + NS_ENSURE_SUCCESS(rv, rv); + mVScrollbarContent->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, + NS_LITERAL_STRING("vertical"), PR_FALSE); + if (!aElements.AppendElement(mVScrollbarContent)) + return NS_ERROR_OUT_OF_MEMORY; } if (canHaveHorizontal && canHaveVertical) { nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollcorner, nsnull, kNameSpaceID_XUL, getter_AddRefs(nodeInfo)); - NS_NewElement(getter_AddRefs(content), kNameSpaceID_XUL, nodeInfo); - aAnonymousChildren.AppendElement(content); + rv = NS_NewElement(getter_AddRefs(mScrollCornerContent), + kNameSpaceID_XUL, nodeInfo); + NS_ENSURE_SUCCESS(rv, rv); + if (!aElements.AppendElement(mScrollCornerContent)) + return NS_ERROR_OUT_OF_MEMORY; } + + return NS_OK; +} + +void +nsGfxScrollFrameInner::Destroy() +{ + // Unbind any content created in CreateAnonymousContent from the tree + nsContentUtils::DestroyAnonymousContent(&mHScrollbarContent); + nsContentUtils::DestroyAnonymousContent(&mVScrollbarContent); + nsContentUtils::DestroyAnonymousContent(&mScrollCornerContent); } NS_IMETHODIMP diff --git a/mozilla/layout/generic/nsGfxScrollFrame.h b/mozilla/layout/generic/nsGfxScrollFrame.h index 6d837f07cbd..713aee4d4a1 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.h +++ b/mozilla/layout/generic/nsGfxScrollFrame.h @@ -51,7 +51,6 @@ #include "nsIScrollableView.h" #include "nsIView.h" -class nsISupportsArray; class nsPresContext; class nsIPresShell; class nsIContent; @@ -81,9 +80,10 @@ public: PRBool NeedsClipWidget() const; void CreateScrollableView(); - void CreateAnonymousContent(nsISupportsArray& aAnonymousChildren); + nsresult CreateAnonymousContent(nsTArray& aElements); nsresult FireScrollPortEvent(); void PostOverflowEvent(); + void Destroy(); nsresult BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, @@ -171,6 +171,11 @@ public: const nsRect& aOldScrollArea, const nsRect& aScrollArea); + // owning references to the nsIAnonymousContentCreator-built content + nsCOMPtr mHScrollbarContent; + nsCOMPtr mVScrollbarContent; + nsCOMPtr mScrollCornerContent; + nsRevocableEventPtr mScrollEvent; nsRevocableEventPtr mAsyncScrollPortEvent; nsIScrollableView* mScrollableView; @@ -309,11 +314,7 @@ public: } // nsIAnonymousContentCreator - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousItems); - NS_IMETHOD CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } + virtual nsresult CreateAnonymousContent(nsTArray& aElements); // nsIScrollableFrame virtual nsIFrame* GetScrolledFrame() const; @@ -465,11 +466,7 @@ public: } // nsIAnonymousContentCreator - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousItems); - NS_IMETHOD CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } + virtual nsresult CreateAnonymousContent(nsTArray& aElements); // nsIBox methods NS_DECL_ISUPPORTS diff --git a/mozilla/layout/generic/nsIAnonymousContentCreator.h b/mozilla/layout/generic/nsIAnonymousContentCreator.h index f1620145dee..d30ed259747 100644 --- a/mozilla/layout/generic/nsIAnonymousContentCreator.h +++ b/mozilla/layout/generic/nsIAnonymousContentCreator.h @@ -45,45 +45,56 @@ #include "nsISupports.h" #include "nsIContent.h" -#include "nsCOMPtr.h" class nsPresContext; -class nsISupportsArray; -class nsIAtom; class nsIFrame; -// {41a69e00-2d6d-11d3-b033-a1357139787c} -#define NS_IANONYMOUS_CONTENT_CREATOR_IID { 0x41a69e00, 0x2d6d, 0x11d3, { 0xb0, 0x33, 0xa1, 0x35, 0x71, 0x39, 0x78, 0x7c } } +// {7568a516-3831-4db4-88a7-a42578acc136} +#define NS_IANONYMOUS_CONTENT_CREATOR_IID \ +{ 0x7568a516, 0x3831, 0x4db4, \ + { 0x88, 0xa7, 0xa4, 0x25, 0x78, 0xac, 0xc1, 0x36 } } /** * Any source for anonymous content can implement this interface to provide it. * HTML frames like nsFileControlFrame currently use this as well as XUL frames - * like nsScrollbarFrame & nsSliderFrame. + * like nsScrollbarFrame and nsSliderFrame. + * + * @see nsCSSFrameConstructor */ class nsIAnonymousContentCreator : public nsISupports { public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_IANONYMOUS_CONTENT_CREATOR_IID) - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousItems)=0; + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IANONYMOUS_CONTENT_CREATOR_IID) - // If the creator doesn't want to create a special frame or frame hierarchy - // then it should null out aFrame and return NS_ERROR_FAILURE - NS_IMETHOD CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame)=0; + /** + * Creates "native" anonymous content and adds the created content to + * the aElements array. None of the returned elements can be nsnull. + * + * @note The returned elements are owned by this object. This object is + * responsible for calling UnbindFromTree on the elements it returned + * from CreateAnonymousContent when appropriate (i.e. before releasing + * them). + */ + virtual nsresult CreateAnonymousContent(nsTArray& aElements)=0; - // This gets called after the frames for the anonymous content have been - // created and added to the frame tree. By default it does nothing. - virtual void PostCreateFrames() {} + /** + * Implementations can override this method to create special frames for the + * anonymous content returned from CreateAnonymousContent. + * By default this method returns nsnull, which means the default frame + * is created. + */ + virtual nsIFrame* CreateFrameFor(nsIContent* aContent) { return nsnull; } + + /** + * This gets called after the frames for the anonymous content have been + * created and added to the frame tree. By default it does nothing. + */ + virtual void PostCreateFrames() {} }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIAnonymousContentCreator, NS_IANONYMOUS_CONTENT_CREATOR_IID) -nsresult NS_CreateAnonymousNode(nsIContent* aParent, nsIAtom* aTag, PRInt32 aNameSpaceId, nsCOMPtr& aNewNode); - - #endif diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp index 7af6ba559d1..f9eb1e590c7 100644 --- a/mozilla/layout/generic/nsInlineFrame.cpp +++ b/mozilla/layout/generic/nsInlineFrame.cpp @@ -89,6 +89,25 @@ nsInlineFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) return nsInlineFrameSuper::QueryInterface(aIID, aInstancePtr); } +void +nsInlineFrame::Destroy() +{ + if (mState & NS_FRAME_GENERATED_CONTENT) { + // Make sure all the content nodes for the generated content inside + // this frame know it's going away. + // This is duplicated in nsBlockFrame::Destroy. + // See also nsCSSFrameConstructor::CreateGeneratedContentFrame which + // created this frame. + + // XXXbz would this be better done via a global structure in + // nsCSSFrameConstructor that could key off of + // GeneratedContentFrameRemoved or something? The problem is that + // our kids are gone by the time that's called. + nsContainerFrame::CleanupGeneratedContentIn(mContent, this); + } + nsInlineFrameSuper::Destroy(); +} + #ifdef DEBUG NS_IMETHODIMP nsInlineFrame::GetFrameName(nsAString& aResult) const diff --git a/mozilla/layout/generic/nsInlineFrame.h b/mozilla/layout/generic/nsInlineFrame.h index 012d0ca980f..f870eeabbfb 100644 --- a/mozilla/layout/generic/nsInlineFrame.h +++ b/mozilla/layout/generic/nsInlineFrame.h @@ -89,6 +89,8 @@ public: const nsRect& aDirtyRect, const nsDisplayListSet& aLists); + virtual void Destroy(); + #ifdef ACCESSIBILITY NS_IMETHODIMP GetAccessible(nsIAccessible** aAccessible); #endif diff --git a/mozilla/layout/svg/base/src/nsSVGUseFrame.cpp b/mozilla/layout/svg/base/src/nsSVGUseFrame.cpp index 2818fbb317a..0f77bcd025e 100644 --- a/mozilla/layout/svg/base/src/nsSVGUseFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGUseFrame.cpp @@ -40,6 +40,7 @@ #include "nsIDOMSVGUseElement.h" #include "nsIDOMSVGTransformable.h" #include "nsSVGElement.h" +#include "nsSVGUseElement.h" typedef nsSVGGFrame nsSVGUseFrameBase; @@ -54,6 +55,7 @@ protected: // nsISupports interface: NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + private: NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } @@ -64,6 +66,8 @@ public: nsIAtom* aAttribute, PRInt32 aModType); + virtual void Destroy(); + // nsSVGContainerFrame methods: virtual already_AddRefed GetCanvasTM(); @@ -82,11 +86,7 @@ public: #endif // nsIAnonymousContentCreator - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousItems); - NS_IMETHOD CreateFrameFor(nsPresContext *aPresContext, - nsIContent *aContent, - nsIFrame **aFrame); + virtual nsresult CreateAnonymousContent(nsTArray& aElements); }; //---------------------------------------------------------------------- @@ -147,6 +147,14 @@ nsSVGUseFrame::AttributeChanged(PRInt32 aNameSpaceID, aAttribute, aModType); } +void +nsSVGUseFrame::Destroy() +{ + nsSVGUseElement *use = NS_STATIC_CAST(nsSVGUseElement*, mContent); + use->DestroyAnonymousContent(); + nsSVGUseFrameBase::Destroy(); +} + //---------------------------------------------------------------------- // nsSVGContainerFrame methods: @@ -184,23 +192,15 @@ nsSVGUseFrame::GetCanvasTM() //---------------------------------------------------------------------- // nsIAnonymousContentCreator methods: -NS_IMETHODIMP -nsSVGUseFrame::CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousItems) +nsresult +nsSVGUseFrame::CreateAnonymousContent(nsTArray& aElements) { - nsCOMPtr use = do_QueryInterface(mContent); + nsSVGUseElement *use = NS_STATIC_CAST(nsSVGUseElement*, mContent); - if (use) - return use->CreateAnonymousContent(aPresContext, aAnonymousItems); - else + nsIContent* clone = use->CreateAnonymousContent(); + if (!clone) return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -nsSVGUseFrame::CreateFrameFor(nsPresContext *aPresContext, - nsIContent *aContent, - nsIFrame **aFrame) -{ - *aFrame = nsnull; - return NS_ERROR_FAILURE; + if (!aElements.AppendElement(clone)) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; } diff --git a/mozilla/layout/xul/base/src/nsDocElementBoxFrame.cpp b/mozilla/layout/xul/base/src/nsDocElementBoxFrame.cpp index 9d4739c90fd..2400f0874c2 100644 --- a/mozilla/layout/xul/base/src/nsDocElementBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsDocElementBoxFrame.cpp @@ -54,16 +54,17 @@ #include "nsIAnonymousContentCreator.h" #include "nsINodeInfo.h" #include "nsIServiceManager.h" -#include "nsISupportsArray.h" #include "nsNodeInfoManager.h" #include "nsContentCreatorFunctions.h" - -// Interface IDs +#include "nsContentUtils.h" //#define DEBUG_REFLOW -class nsDocElementBoxFrame : public nsBoxFrame, public nsIAnonymousContentCreator { +class nsDocElementBoxFrame : public nsBoxFrame, + public nsIAnonymousContentCreator +{ public: + virtual void Destroy(); friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); @@ -74,16 +75,15 @@ public: NS_DECL_ISUPPORTS_INHERITED // nsIAnonymousContentCreator - NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousItems); - NS_IMETHOD CreateFrameFor(nsPresContext* aPresContext, - nsIContent * aContent, - nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } + virtual nsresult CreateAnonymousContent(nsTArray& aElements); virtual PRBool IsFrameOfType(PRUint32 aFlags) const; #ifdef DEBUG NS_IMETHOD GetFrameName(nsAString& aResult) const; #endif +private: + nsCOMPtr mPopupgroupContent; + nsCOMPtr mTooltipContent; }; //---------------------------------------------------------------------- @@ -94,14 +94,22 @@ NS_NewDocElementBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) return new (aPresShell) nsDocElementBoxFrame (aPresShell, aContext); } -NS_IMETHODIMP -nsDocElementBoxFrame::CreateAnonymousContent(nsPresContext* aPresContext, - nsISupportsArray& aAnonymousItems) +void +nsDocElementBoxFrame::Destroy() +{ + nsContentUtils::DestroyAnonymousContent(&mPopupgroupContent); + nsContentUtils::DestroyAnonymousContent(&mTooltipContent); + nsBoxFrame::Destroy(); +} + +nsresult +nsDocElementBoxFrame::CreateAnonymousContent(nsTArray& aElements) { nsIDocument* doc = mContent->GetDocument(); - if (!doc) + if (!doc) { // The page is currently being torn down. Why bother. return NS_ERROR_FAILURE; + } nsNodeInfoManager *nodeInfoManager = doc->NodeInfoManager(); // create the top-secret popupgroup node. shhhhh! @@ -111,23 +119,26 @@ nsDocElementBoxFrame::CreateAnonymousContent(nsPresContext* aPresContext, getter_AddRefs(nodeInfo)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr content; - rv = NS_NewXULElement(getter_AddRefs(content), nodeInfo); + rv = NS_NewXULElement(getter_AddRefs(mPopupgroupContent), nodeInfo); NS_ENSURE_SUCCESS(rv, rv); - aAnonymousItems.AppendElement(content); + if (!aElements.AppendElement(mPopupgroupContent)) + return NS_ERROR_OUT_OF_MEMORY; // create the top-secret default tooltip node. shhhhh! rv = nodeInfoManager->GetNodeInfo(nsGkAtoms::tooltip, nsnull, kNameSpaceID_XUL, getter_AddRefs(nodeInfo)); + NS_ENSURE_SUCCESS(rv, nsnull); + + rv = NS_NewXULElement(getter_AddRefs(mTooltipContent), nodeInfo); NS_ENSURE_SUCCESS(rv, rv); - rv = NS_NewXULElement(getter_AddRefs(content), nodeInfo); - NS_ENSURE_SUCCESS(rv, rv); + mTooltipContent->SetAttr(nsnull, nsGkAtoms::_default, + NS_LITERAL_STRING("true"), PR_FALSE); + + if (!aElements.AppendElement(mTooltipContent)) + return NS_ERROR_OUT_OF_MEMORY; - content->SetAttr(nsnull, nsGkAtoms::_default, NS_LITERAL_STRING("true"), PR_FALSE); - aAnonymousItems.AppendElement(content); - return NS_OK; }