From 9f4b50c028c971baaf789ff88b4e97e1d6524646 Mon Sep 17 00:00:00 2001 From: "cvshook%sicking.cc" Date: Thu, 9 Mar 2006 07:29:41 +0000 Subject: [PATCH] Bug 326645: Remove mRootContent from nsDocument to avoid all the pains of keeping it in sync with the childlist. Also remove mBodyContent from nsHTMLDocument for the same reason. r=bz sr=jst --- content/base/public/nsIDocument.h | 9 +- content/base/src/nsDocument.cpp | 225 +++++------------- content/base/src/nsDocument.h | 3 +- content/html/document/src/nsHTMLDocument.cpp | 194 ++++++--------- content/html/document/src/nsHTMLDocument.h | 5 +- content/html/document/src/nsImageDocument.cpp | 9 +- content/html/document/src/nsMediaDocument.cpp | 1 - .../html/document/src/nsPluginDocument.cpp | 2 +- content/svg/content/src/nsSVGSVGElement.cpp | 24 +- content/svg/document/src/nsSVGDocument.cpp | 5 +- content/xml/document/src/nsXMLDocument.cpp | 7 +- content/xul/document/src/nsXULDocument.cpp | 8 +- 12 files changed, 169 insertions(+), 323 deletions(-) diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index a49bce428d41..ba0b1bc99fa7 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -363,10 +363,7 @@ public: /** * Return the root content object for this document. */ - nsIContent *GetRootContent() const - { - return mRootContent; - } + virtual nsIContent *GetRootContent() const = 0; /** * Accessors to the collection of stylesheets owned by this document. @@ -914,10 +911,6 @@ protected: // This is just a weak pointer; the parent document owns its children. nsIDocument* mParentDocument; - // A weak reference to the only child element, or null if no - // such element exists. - nsIContent* mRootContent; - nsCOMPtr mBindingManager; nsNodeInfoManager* mNodeInfoManager; // [STRONG] diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 75ac4f1577d2..3f549f7e20bd 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -746,27 +746,16 @@ nsDocument::~nsDocument() mSubDocuments = nsnull; } - if (mRootContent) { - if (mRootContent->GetCurrentDoc()) { - NS_ASSERTION(mRootContent->GetCurrentDoc() == this, - "Unexpected current doc in root content"); - // The root content still has a pointer back to the document, - // clear the document pointer in all children. - - // Destroy link map now so we don't waste time removing - // links one by one - DestroyLinkMap(); + // Destroy link map now so we don't waste time removing + // links one by one + DestroyLinkMap(); - PRUint32 count = mChildren.ChildCount(); - for (indx = PRInt32(count) - 1; indx >= 0; --indx) { - mChildren.ChildAt(indx)->UnbindFromTree(); - mChildren.RemoveChildAt(indx); - } - } + PRUint32 count = mChildren.ChildCount(); + for (indx = PRInt32(count) - 1; indx >= 0; --indx) { + mChildren.ChildAt(indx)->UnbindFromTree(); + mChildren.RemoveChildAt(indx); } - mRootContent = nsnull; - // Let the stylesheets know we're going away indx = mStyleSheets.Count(); while (--indx >= 0) { @@ -981,7 +970,6 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup) // links one by one DestroyLinkMap(); - mRootContent = nsnull; PRUint32 count = mChildren.ChildCount(); for (PRInt32 i = PRInt32(count) - 1; i >= 0; i--) { nsCOMPtr content = mChildren.ChildAt(i); @@ -1689,6 +1677,22 @@ nsDocument::FindContentForSubDocument(nsIDocument *aDocument) const return data.mResult; } +nsIContent* +nsDocument::GetRootContent() const +{ + // Loop backwards because any non-elements, such as doctypes and PIs + // are likely to appear before the root element. + PRUint32 i; + for (i = mChildren.ChildCount(); i > 0; --i) { + nsIContent* child = mChildren.ChildAt(i - 1); + if (child->IsContentOfType(nsIContent::eELEMENT)) { + return child; + } + } + + return nsnull; +} + nsIContent * nsDocument::GetChildAt(PRUint32 aIndex) const { @@ -1711,37 +1715,13 @@ nsresult nsDocument::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify) { - if (aKid->IsContentOfType(nsIContent::eELEMENT)) { - if (mRootContent) { - NS_ERROR("Inserting element child when we already have one"); - return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; - } - - mRootContent = aKid; + if (aKid->IsContentOfType(nsIContent::eELEMENT) && GetRootContent()) { + NS_ERROR("Inserting element child when we already have one"); + return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; } - nsresult rv = nsGenericElement::doInsertChildAt(aKid, aIndex, aNotify, - nsnull, this, mChildren); - - if (NS_FAILED(rv) && mRootContent == aKid) { - PRInt32 kidIndex = mChildren.IndexOfChild(aKid); - NS_ASSERTION(kidIndex == -1, - "Error result and still have same root content but it's in " - "our child list?"); - // Check to make sure that we're keeping mRootContent in sync with our - // child list... but really, if kidIndex != -1 we have major problems - // coming up; hence the assert above. This check is just a feeble attempt - // to not die due to mRootContent being bogus. - if (kidIndex == -1) { - mRootContent = nsnull; - } - } - -#ifdef DEBUG - VerifyRootContentState(); -#endif - - return rv; + return nsGenericElement::doInsertChildAt(aKid, aIndex, aNotify, + nsnull, this, mChildren); } nsresult @@ -1759,58 +1739,19 @@ nsresult nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) { nsCOMPtr oldKid = GetChildAt(aIndex); - nsresult rv = NS_OK; - if (oldKid) { - if (oldKid == mRootContent) { - NS_ASSERTION(oldKid->IsContentOfType(nsIContent::eELEMENT), - "Non-element root content?"); - // Destroy the link map up front and null out mRootContent before we mess - // with the child list. Hopefully no one in doRemoveChildAt will compare - // the content being removed to GetRootContent().... Need to do this - // before calling doRemoveChildAt because DOM events might fire while - // we're inside the doInsertChildAt call and want to set a new - // mRootContent; if they do that, setting mRootContent after the - // doRemoveChildAt call would clobber state. If we ever fix the issue of - // DOM events firing at inconvenient times, consider changing the order - // here. Just make sure we DestroyLinkMap() before unbinding the - // content. - DestroyLinkMap(); - mRootContent = nsnull; - } - - rv = nsGenericElement::doRemoveChildAt(aIndex, aNotify, oldKid, + if (!oldKid) { + return NS_OK; + } + + if (oldKid->IsContentOfType(nsIContent::eELEMENT)) { + // Destroy the link map up front before we mess with the child list. + DestroyLinkMap(); + } + + return nsGenericElement::doRemoveChildAt(aIndex, aNotify, oldKid, nsnull, this, mChildren); - if (NS_FAILED(rv) && mChildren.IndexOfChild(oldKid) != -1) { - mRootContent = oldKid; - } - } - -#ifdef DEBUG - VerifyRootContentState(); -#endif - - return rv; } -#ifdef DEBUG -void -nsDocument::VerifyRootContentState() -{ - nsIContent* elementChild = nsnull; - for (PRUint32 i = 0; i < GetChildCount(); ++i) { - nsIContent* kid = GetChildAt(i); - NS_ASSERTION(kid, "Must have kid here"); - - if (kid->IsContentOfType(nsIContent::eELEMENT)) { - NS_ASSERTION(!elementChild, "Multiple element kids?"); - elementChild = kid; - } - } - - NS_ASSERTION(mRootContent == elementChild, "Incorrect mRootContent"); -} -#endif // DEBUG - PRInt32 nsDocument::GetNumberOfStyleSheets() const { @@ -2546,28 +2487,11 @@ nsDocument::GetDoctype(nsIDOMDocumentType** aDoctype) *aDoctype = nsnull; PRInt32 i, count; count = mChildren.ChildCount(); - nsCOMPtr rootContentNode(do_QueryInterface(mRootContent) ); - nsCOMPtr node; - for (i = 0; i < count; i++) { - node = do_QueryInterface(mChildren.ChildAt(i)); + CallQueryInterface(mChildren.ChildAt(i), aDoctype); - NS_ASSERTION(node, "null element of mChildren"); - - // doctype can't be after the root - // XXX Do we really want to enforce this when we don't enforce - // anything else? - if (node == rootContentNode) + if (*aDoctype) { return NS_OK; - - if (node) { - PRUint16 nodeType; - - node->GetNodeType(&nodeType); - - if (nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) { - return CallQueryInterface(node, aDoctype); - } } } @@ -2598,16 +2522,14 @@ nsDocument::GetDocumentElement(nsIDOMElement** aDocumentElement) { NS_ENSURE_ARG_POINTER(aDocumentElement); - nsresult rv = NS_OK; - - if (mRootContent) { - rv = CallQueryInterface(mRootContent, aDocumentElement); - NS_ASSERTION(NS_OK == rv, "Must be a DOM Element"); - } else { - *aDocumentElement = nsnull; + nsIContent* root = GetRootContent(); + if (root) { + return CallQueryInterface(root, aDocumentElement); } - return rv; + *aDocumentElement = nsnull; + + return NS_OK; } NS_IMETHODIMP @@ -3619,38 +3541,6 @@ nsDocument::GetLocalName(nsAString& aLocalName) return NS_OK; } -nsresult -nsDocument::IsAllowedAsChild(PRUint16 aNodeType, nsIContent* aRefContent) -{ - if (aNodeType != nsIDOMNode::COMMENT_NODE && - aNodeType != nsIDOMNode::ELEMENT_NODE && - aNodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE && - aNodeType != nsIDOMNode::DOCUMENT_TYPE_NODE) { - return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; - } - - if (aNodeType == nsIDOMNode::ELEMENT_NODE && mRootContent && - mRootContent != aRefContent) { - // We already have a child Element, and we're not trying to - // replace it, so throw an error. - return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; - } - - if (aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) { - nsCOMPtr docType; - GetDoctype(getter_AddRefs(docType)); - - nsCOMPtr docTypeContent = do_QueryInterface(docType); - if (docTypeContent && docTypeContent != aRefContent) { - // We already have a doctype, and we're not trying to - // replace it, so throw an error. - return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; - } - } - - return NS_OK; -} - NS_IMETHODIMP nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aReturn) @@ -4051,7 +3941,7 @@ NS_IMETHODIMP nsDocument::LookupPrefix(const nsAString& aNamespaceURI, nsAString& aPrefix) { - nsCOMPtr root(do_QueryInterface(mRootContent)); + nsCOMPtr root(do_QueryInterface(GetRootContent())); if (root) { return root->LookupPrefix(aNamespaceURI, aPrefix); } @@ -4064,7 +3954,7 @@ NS_IMETHODIMP nsDocument::LookupNamespaceURI(const nsAString& aNamespacePrefix, nsAString& aNamespaceURI) { - if (NS_FAILED(nsContentUtils::LookupNamespaceURI(mRootContent, + if (NS_FAILED(nsContentUtils::LookupNamespaceURI(GetRootContent(), aNamespacePrefix, aNamespaceURI))) { SetDOMStringToNull(aNamespaceURI); @@ -5139,12 +5029,13 @@ nsDocument::Destroy() if (mIsGoingAway) return; - PRInt32 count = mChildren.ChildCount(); - mIsGoingAway = PR_TRUE; DestroyLinkMap(); - for (PRInt32 indx = 0; indx < count; ++indx) { - mChildren.ChildAt(indx)->UnbindFromTree(); + + PRInt32 count = mChildren.ChildCount(); + for (PRInt32 indx = count; indx > 0; --indx) { + mChildren.ChildAt(indx - 1)->UnbindFromTree(); + mChildren.RemoveChildAt(indx - 1); } // Propagate the out-of-band notification to each PresShell's anonymous @@ -5306,12 +5197,13 @@ nsDocument::OnPageShow(PRBool aPersisted) mVisible = PR_TRUE; UpdateLinkMap(); - if (aPersisted) { + nsIContent* root = GetRootContent(); + if (aPersisted && root) { // Send out notifications that our elements are attached. nsRefPtr links = NS_GetContentList(this, nsHTMLAtoms::link, kNameSpaceID_Unknown, - mRootContent); + root); if (links) { PRUint32 linkCount = links->Length(PR_TRUE); @@ -5333,11 +5225,12 @@ nsDocument::OnPageHide(PRBool aPersisted) { // Send out notifications that our elements are detached, // but only if this is not a full unload. - if (aPersisted) { + nsIContent* root = GetRootContent(); + if (aPersisted && root) { nsRefPtr links = NS_GetContentList(this, nsHTMLAtoms::link, kNameSpaceID_Unknown, - mRootContent); + root); if (links) { PRUint32 linkCount = links->Length(PR_TRUE); diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index a173e70919ad..7b72307c5628 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -385,6 +385,7 @@ public: nsIDocument* aSubDoc); virtual nsIDocument* GetSubDocumentFor(nsIContent *aContent) const; virtual nsIContent* FindContentForSubDocument(nsIDocument *aDocument) const; + virtual nsIContent* GetRootContent() const; /** * Get the style sheets owned by this document. @@ -772,8 +773,6 @@ protected: nsString mBaseTarget; private: - nsresult IsAllowedAsChild(PRUint16 aNodeType, nsIContent* aRefContent); - void PostUnblockOnloadEvent(); static EventHandlerFunc HandleOnloadBlockerEvent; static EventDestructorFunc DestroyOnloadBlockerEvent; diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 1b2e1ea013e9..4c286f61a014 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -417,8 +417,6 @@ nsHTMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup) mLinks = nsnull; mAnchors = nsnull; - mBodyContent = nsnull; - mImageMaps.Clear(); mForms = nsnull; @@ -1173,12 +1171,6 @@ nsHTMLDocument::ContentRemoved(nsIContent* aContainer, nsIContent* aContent, { NS_ABORT_IF_FALSE(aContent, "Null content!"); - if (aContainer == mRootContent) { - // Reset mBodyContent in case we got a new body. - - mBodyContent = nsnull; - } - nsresult rv = UnregisterNamedItems(aContent); if (NS_FAILED(rv)) { @@ -1631,66 +1623,62 @@ nsHTMLDocument::GetURL(nsAString& aURL) NS_IMETHODIMP nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody) { - NS_ENSURE_ARG_POINTER(aBody); *aBody = nsnull; - nsISupports* element = nsnull; - nsCOMPtr node; + nsIContent* body = GetBodyContent(); - if (mBodyContent || GetBodyContent()) { + if (body) { // There is a body element, return that as the body. - element = mBodyContent; - } else { - // The document is most likely a frameset document so look for the - // outer most frameset element - - nsCOMPtr nodeList; - - nsresult rv; - if (IsXHTML()) { - rv = GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"), - NS_LITERAL_STRING("frameset"), - getter_AddRefs(nodeList)); - } else { - rv = GetElementsByTagName(NS_LITERAL_STRING("frameset"), - getter_AddRefs(nodeList)); - } - - if (nodeList) { - rv |= nodeList->Item(0, getter_AddRefs(node)); - - element = node; - } - - NS_ENSURE_SUCCESS(rv, rv); + return CallQueryInterface(body, aBody); } - return element ? CallQueryInterface(element, aBody) : NS_OK; + // The document is most likely a frameset document so look for the + // outer most frameset element + nsCOMPtr nodeList; + + nsresult rv; + if (IsXHTML()) { + rv = GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"), + NS_LITERAL_STRING("frameset"), + getter_AddRefs(nodeList)); + } else { + rv = GetElementsByTagName(NS_LITERAL_STRING("frameset"), + getter_AddRefs(nodeList)); + } + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr node; + nodeList->Item(0, getter_AddRefs(node)); + + return node ? CallQueryInterface(node, aBody) : NS_OK; } NS_IMETHODIMP nsHTMLDocument::SetBody(nsIDOMHTMLElement* aBody) { - nsCOMPtr body(do_QueryInterface(aBody)); - nsCOMPtr root(do_QueryInterface(mRootContent)); + nsCOMPtr newBody = do_QueryInterface(aBody); + nsIContent* root = GetRootContent(); - // The body element must be either a body tag or a frameset tag. - if (!body || !root || !(body->Tag() == nsHTMLAtoms::body || - body->Tag() == nsHTMLAtoms::frameset)) { + // The body element must be either a body tag or a frameset tag. And we must + // have a html root tag, otherwise GetBody will not return the newly set + // body. + if (!newBody || !(newBody->Tag() == nsHTMLAtoms::body || + newBody->Tag() == nsHTMLAtoms::frameset) || + !root || !root->IsContentOfType(nsIContent::eHTML) || + root->Tag() != nsHTMLAtoms::html) { return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; } + nsCOMPtr rootElem = do_QueryInterface(root); nsCOMPtr tmp; - if (mBodyContent || GetBodyContent()) { - root->ReplaceChild(aBody, mBodyContent, getter_AddRefs(tmp)); - } else { - root->AppendChild(aBody, getter_AddRefs(tmp)); + // Use DOM methods so that we pass through the appropriate security checks. + nsCOMPtr currentBody = do_QueryInterface(GetBodyContent()); + if (currentBody) { + return rootElem->ReplaceChild(aBody, currentBody, getter_AddRefs(tmp)); } - mBodyContent = aBody; - - return PR_FALSE; + return rootElem->AppendChild(aBody, getter_AddRefs(tmp)); } NS_IMETHODIMP @@ -1984,10 +1972,10 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace) // (http://bugzilla.mozilla.org/show_bug.cgi?id=55334). // Hold on to our root element - nsCOMPtr root(mRootContent); + nsCOMPtr root = GetRootContent(); if (root) { - PRInt32 rootIndex = mChildren.IndexOfChild(mRootContent); + PRInt32 rootIndex = mChildren.IndexOfChild(root); NS_ASSERTION(rootIndex >= 0, "Root must be in list!"); PRUint32 count = root->GetChildCount(); @@ -1997,7 +1985,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace) root->RemoveChildAt(count, PR_TRUE); } - count = mRootContent->GetAttrCount(); + count = root->GetAttrCount(); // Remove all attributes from the root element while (count-- > 0) { @@ -2007,8 +1995,6 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace) // Remove the root from the childlist mChildren.RemoveChildAt(rootIndex); - - mRootContent = nsnull; } // Call Reset(), this will now do the full reset, except removing @@ -2030,7 +2016,6 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace) // element was never set to null) mChildren.AppendChild(root); - mRootContent = root; } if (mEditingIsOn) { @@ -2440,11 +2425,12 @@ nsHTMLDocument::GetElementById(const nsAString& aElementId, // If IdTableIsLive(), no need to look for the element in the document, // since we're fully maintaining our table's state as the DOM mutates. if (!IdTableIsLive()) { + nsIContent* root = GetRootContent(); if (IdTableShouldBecomeLive()) { // Just make sure our table is up to date and call this method again // to look up in the hashtable. - if (mRootContent) { - RegisterNamedItems(mRootContent); + if (root) { + RegisterNamedItems(root); } return GetElementById(aElementId, aReturn); } @@ -2452,8 +2438,8 @@ nsHTMLDocument::GetElementById(const nsAString& aElementId, NS_WARN_IF_FALSE(!aElementId.IsEmpty(), "getElementById(\"\") called, fix caller?"); - if (mRootContent && !aElementId.IsEmpty()) { - e = nsContentUtils::MatchElementId(mRootContent, idAtom); + if (root && !aElementId.IsEmpty()) { + e = nsContentUtils::MatchElementId(root, idAtom); } } @@ -2461,9 +2447,9 @@ nsHTMLDocument::GetElementById(const nsAString& aElementId, #ifdef DEBUG // No reason to call MatchElementId if !IdTableIsLive, since // we'd have done just that already - if (IdTableIsLive() && mRootContent && !aElementId.IsEmpty()) { + if (IdTableIsLive() && GetRootContent() && !aElementId.IsEmpty()) { nsIContent* eDebug = - nsContentUtils::MatchElementId(mRootContent, idAtom); + nsContentUtils::MatchElementId(GetRootContent(), idAtom); NS_ASSERTION(!eDebug, "We got null for |e| but MatchElementId found something?"); } @@ -2592,11 +2578,7 @@ nsHTMLDocument::GetPixelDimensions(nsIPresShell* aShell, // Find the element: this is what we'll want to use for the // document's width and height values. - if (!mBodyContent && !GetBodyContent()) { - return NS_OK; - } - - nsCOMPtr body = do_QueryInterface(mBodyContent); + nsIContent* body = GetBodyContent(); // Now grab its frame nsIFrame* frame = aShell->GetPrimaryFrameFor(body); @@ -2685,8 +2667,7 @@ nsHTMLDocument::GetAlinkColor(nsAString& aAlinkColor) { aAlinkColor.Truncate(); - nsCOMPtr body; - GetBodyElement(getter_AddRefs(body)); + nsCOMPtr body = do_QueryInterface(GetBodyContent()); if (body) { body->GetALink(aAlinkColor); @@ -2704,8 +2685,7 @@ nsHTMLDocument::GetAlinkColor(nsAString& aAlinkColor) NS_IMETHODIMP nsHTMLDocument::SetAlinkColor(const nsAString& aAlinkColor) { - nsCOMPtr body; - GetBodyElement(getter_AddRefs(body)); + nsCOMPtr body = do_QueryInterface(GetBodyContent()); if (body) { body->SetALink(aAlinkColor); @@ -2726,8 +2706,7 @@ nsHTMLDocument::GetLinkColor(nsAString& aLinkColor) { aLinkColor.Truncate(); - nsCOMPtr body; - GetBodyElement(getter_AddRefs(body)); + nsCOMPtr body = do_QueryInterface(GetBodyContent()); if (body) { body->GetLink(aLinkColor); @@ -2745,8 +2724,7 @@ nsHTMLDocument::GetLinkColor(nsAString& aLinkColor) NS_IMETHODIMP nsHTMLDocument::SetLinkColor(const nsAString& aLinkColor) { - nsCOMPtr body; - GetBodyElement(getter_AddRefs(body)); + nsCOMPtr body = do_QueryInterface(GetBodyContent()); if (body) { body->SetLink(aLinkColor); @@ -2767,8 +2745,7 @@ nsHTMLDocument::GetVlinkColor(nsAString& aVlinkColor) { aVlinkColor.Truncate(); - nsCOMPtr body; - GetBodyElement(getter_AddRefs(body)); + nsCOMPtr body = do_QueryInterface(GetBodyContent()); if (body) { body->GetVLink(aVlinkColor); @@ -2786,8 +2763,7 @@ nsHTMLDocument::GetVlinkColor(nsAString& aVlinkColor) NS_IMETHODIMP nsHTMLDocument::SetVlinkColor(const nsAString& aVlinkColor) { - nsCOMPtr body; - GetBodyElement(getter_AddRefs(body)); + nsCOMPtr body = do_QueryInterface(GetBodyContent()); if (body) { body->SetVLink(aVlinkColor); @@ -2808,8 +2784,7 @@ nsHTMLDocument::GetBgColor(nsAString& aBgColor) { aBgColor.Truncate(); - nsCOMPtr body; - GetBodyElement(getter_AddRefs(body)); + nsCOMPtr body = do_QueryInterface(GetBodyContent()); if (body) { body->GetBgColor(aBgColor); @@ -2821,8 +2796,7 @@ nsHTMLDocument::GetBgColor(nsAString& aBgColor) NS_IMETHODIMP nsHTMLDocument::SetBgColor(const nsAString& aBgColor) { - nsCOMPtr body; - GetBodyElement(getter_AddRefs(body)); + nsCOMPtr body = do_QueryInterface(GetBodyContent()); if (body) { body->SetBgColor(aBgColor); @@ -2837,8 +2811,7 @@ nsHTMLDocument::GetFgColor(nsAString& aFgColor) { aFgColor.Truncate(); - nsCOMPtr body; - GetBodyElement(getter_AddRefs(body)); + nsCOMPtr body = do_QueryInterface(GetBodyContent()); if (body) { body->GetText(aFgColor); @@ -2850,8 +2823,7 @@ nsHTMLDocument::GetFgColor(nsAString& aFgColor) NS_IMETHODIMP nsHTMLDocument::SetFgColor(const nsAString& aFgColor) { - nsCOMPtr body; - GetBodyElement(getter_AddRefs(body)); + nsCOMPtr body = do_QueryInterface(GetBodyContent()); if (body) { body->SetText(aFgColor); @@ -3335,10 +3307,11 @@ nsHTMLDocument::ResolveName(const nsAString& aName, entry->mNameContentList = list; NS_ADDREF(entry->mNameContentList); - if (mRootContent && !aName.IsEmpty()) { + nsIContent* root = GetRootContent(); + if (root && !aName.IsEmpty()) { // We'll never get here if !IsXHTML(), so we can just pass // PR_FALSE to FindNamedItems(). - FindNamedItems(name, mRootContent, *entry, PR_FALSE); + FindNamedItems(name, root, *entry, PR_FALSE); } } @@ -3427,42 +3400,27 @@ nsHTMLDocument::ResolveName(const nsAString& aName, //---------------------------- -PRBool +nsIContent* nsHTMLDocument::GetBodyContent() { - if (!mRootContent) { - return PR_FALSE; - } + // Loop backwards because any non-elements, such as doctypes and PIs + // are likly to appear before the root element. + nsIContent* html = GetRootContent(); + if (html->Tag() == nsHTMLAtoms::html && + html->IsContentOfType(nsIContent::eHTML)) { - PRUint32 i, child_count = mRootContent->GetChildCount(); - - for (i = 0; i < child_count; ++i) { - nsIContent *child = mRootContent->GetChildAt(i); - NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED); - - if (child->NodeInfo()->Equals(nsHTMLAtoms::body, mDefaultNamespaceID) && - child->IsContentOfType(nsIContent::eHTML)) { - mBodyContent = do_QueryInterface(child); - - return PR_TRUE; + // Look for body inside html + PRUint32 i, count = html->GetChildCount(); + for (i = 0; i < count; ++i) { + nsIContent* body = html->GetChildAt(i); + if (body->Tag() == nsHTMLAtoms::body && + body->IsContentOfType(nsIContent::eHTML)) { + return body; + } } } - return PR_FALSE; -} - -void -nsHTMLDocument::GetBodyElement(nsIDOMHTMLBodyElement** aBody) -{ - *aBody = nsnull; - - if (!mBodyContent && !GetBodyContent()) { - // No body in this document. - - return; - } - - CallQueryInterface(mBodyContent, aBody); + return nsnull; } // forms related stuff diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 213f9b28b208..4fffd32fc71b 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -234,8 +234,7 @@ protected: static void DocumentWriteTerminationFunc(nsISupports *aRef); - PRBool GetBodyContent(); - void GetBodyElement(nsIDOMHTMLBodyElement** aBody); + nsIContent* GetBodyContent(); void GetDomainURI(nsIURI **uri); @@ -321,8 +320,6 @@ protected: // Load flags of the document's channel PRUint32 mLoadFlags; - nsCOMPtr mBodyContent; - /* * Bug 13871: Frameset spoofing - find out if document.domain was set */ diff --git a/content/html/document/src/nsImageDocument.cpp b/content/html/document/src/nsImageDocument.cpp index 63b64cc40864..14e0c087bee4 100644 --- a/content/html/document/src/nsImageDocument.cpp +++ b/content/html/document/src/nsImageDocument.cpp @@ -346,7 +346,7 @@ nsImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObjec nsHTMLDocument::SetScriptGlobalObject(aScriptGlobalObject); if (aScriptGlobalObject) { - if (!mRootContent) { + if (!GetRootContent()) { // Create synthetic document nsresult rv = CreateSyntheticDocument(); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic document"); @@ -605,7 +605,7 @@ nsImageDocument::CreateSyntheticDocument() nsresult rv = nsMediaDocument::CreateSyntheticDocument(); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr body = do_QueryInterface(mBodyContent); + nsIContent* body = GetBodyContent(); if (!body) { NS_WARNING("no body on image document!"); return NS_ERROR_FAILURE; @@ -650,7 +650,10 @@ nsImageDocument::CheckOverflowing(PRBool changeState) nsPresContext *context = shell->GetPresContext(); nsRect visibleArea = context->GetVisibleArea(); - nsCOMPtr content = do_QueryInterface(mBodyContent); + nsIContent* content = GetBodyContent(); + if (!content) { + return NS_OK; + } nsRefPtr styleContext = context->StyleSet()->ResolveStyleFor(content, nsnull); diff --git a/content/html/document/src/nsMediaDocument.cpp b/content/html/document/src/nsMediaDocument.cpp index 5668a6156fd6..1f280ff6eec5 100644 --- a/content/html/document/src/nsMediaDocument.cpp +++ b/content/html/document/src/nsMediaDocument.cpp @@ -256,7 +256,6 @@ nsMediaDocument::CreateSyntheticDocument() if (!body) { return NS_ERROR_OUT_OF_MEMORY; } - mBodyContent = do_QueryInterface(body); root->AppendChildTo(body, PR_FALSE); diff --git a/content/html/document/src/nsPluginDocument.cpp b/content/html/document/src/nsPluginDocument.cpp index 1b6e61290408..5c23b27d0e5b 100644 --- a/content/html/document/src/nsPluginDocument.cpp +++ b/content/html/document/src/nsPluginDocument.cpp @@ -222,7 +222,7 @@ nsPluginDocument::CreateSyntheticPluginDocument() NS_ENSURE_SUCCESS(rv, rv); // then attach our plugin - nsCOMPtr body = do_QueryInterface(mBodyContent); + nsIContent* body = GetBodyContent(); if (!body) { NS_WARNING("no body on plugin document!"); return NS_ERROR_FAILURE; diff --git a/content/svg/content/src/nsSVGSVGElement.cpp b/content/svg/content/src/nsSVGSVGElement.cpp index 990d659e4b00..53e9a6a34707 100644 --- a/content/svg/content/src/nsSVGSVGElement.cpp +++ b/content/svg/content/src/nsSVGSVGElement.cpp @@ -129,6 +129,12 @@ protected: // implementation helpers: void GetOffsetToAncestor(nsIContent* ancestor, float &x, float &y); + PRBool IsRoot() { + NS_ASSERTION((IsInDoc() && !GetParent()) == + (GetOwnerDoc() && (GetOwnerDoc()->GetRootContent() == this)), + "Can't determine if we're root"); + return IsInDoc() && !GetParent(); + } nsCOMPtr mWidth; nsCOMPtr mHeight; @@ -984,8 +990,7 @@ nsSVGSVGElement::GetCTM(nsIDOMSVGMatrix **_retval) if (!ancestorCTM) { // we didn't find an SVG ancestor float s=1, x=0, y=0; - if (ownerDoc && - ownerDoc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) { + if (IsRoot()) { // we're the root element. get our currentScale and currentTranslate vals mCurrentScale->GetValue(&s); mCurrentTranslate->GetX(&x); @@ -1093,8 +1098,7 @@ nsSVGSVGElement::GetScreenCTM(nsIDOMSVGMatrix **_retval) if (!ancestorScreenCTM) { // we didn't find an SVG ancestor float s=1, x=0, y=0; - if (ownerDoc && - ownerDoc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) { + if (IsRoot()) { // we're the root element. get our currentScale and currentTranslate vals mCurrentScale->GetValue(&s); mCurrentTranslate->GetX(&x); @@ -1272,8 +1276,7 @@ nsSVGSVGElement::SetCurrentScaleTranslate(float s, float x, float y) if (doc) { nsIPresShell* presShell = doc->GetShellAt(0); NS_ASSERTION(presShell, "no presShell"); - if (presShell && - doc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) { + if (presShell && IsRoot()) { nsEventStatus status = nsEventStatus_eIgnore; nsGUIEvent event(PR_TRUE, NS_SVG_ZOOM, 0); event.eventStructType = NS_SVGZOOM_EVENT; @@ -1297,8 +1300,7 @@ nsSVGSVGElement::SetCurrentTranslate(float x, float y) if (doc) { nsIPresShell* presShell = doc->GetShellAt(0); NS_ASSERTION(presShell, "no presShell"); - if (presShell && - doc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) { + if (presShell && IsRoot()) { nsEventStatus status = nsEventStatus_eIgnore; nsEvent event(PR_TRUE, NS_SVG_SCROLL); event.eventStructType = NS_SVG_EVENT; @@ -1400,8 +1402,7 @@ nsSVGSVGElement::DidModifySVGObservable (nsISVGValue* observable, // dispatch an SVGZoom or SVGScroll DOM event before repainting nsCOMPtr n = do_QueryInterface(observable); if (n && n==mCurrentScale) { - if (mDispatchEvent && - doc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) { + if (mDispatchEvent && IsRoot()) { nsEventStatus status = nsEventStatus_eIgnore; nsGUIEvent event(PR_TRUE, NS_SVG_ZOOM, 0); event.eventStructType = NS_SVGZOOM_EVENT; @@ -1414,8 +1415,7 @@ nsSVGSVGElement::DidModifySVGObservable (nsISVGValue* observable, else { nsCOMPtr p = do_QueryInterface(observable); if (p && p==mCurrentTranslate) { - if (mDispatchEvent && - doc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) { + if (mDispatchEvent && IsRoot()) { nsEventStatus status = nsEventStatus_eIgnore; nsEvent event(PR_TRUE, NS_SVG_SCROLL); event.eventStructType = NS_SVG_EVENT; diff --git a/content/svg/document/src/nsSVGDocument.cpp b/content/svg/document/src/nsSVGDocument.cpp index f8b730509b61..25f63896296d 100644 --- a/content/svg/document/src/nsSVGDocument.cpp +++ b/content/svg/document/src/nsSVGDocument.cpp @@ -121,7 +121,10 @@ nsSVGDocument::GetURL(nsAString& aURL) NS_IMETHODIMP nsSVGDocument::GetRootElement(nsIDOMSVGSVGElement** aRootElement) { - return CallQueryInterface(mRootContent, aRootElement); + *aRootElement = nsnull; + nsIContent* root = GetRootContent(); + + return root ? CallQueryInterface(root, aRootElement) : NS_OK; } //////////////////////////////////////////////////////////////////////// diff --git a/content/xml/document/src/nsXMLDocument.cpp b/content/xml/document/src/nsXMLDocument.cpp index f002e1121981..fffad7848dee 100644 --- a/content/xml/document/src/nsXMLDocument.cpp +++ b/content/xml/document/src/nsXMLDocument.cpp @@ -546,7 +546,7 @@ nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn) mEventQService->PopThreadEventQueue(modalEventQueue); // We set return to true unless there was a parsing error - nsCOMPtr node = do_QueryInterface(mRootContent); + nsCOMPtr node = do_QueryInterface(GetRootContent()); if (node) { nsAutoString name, ns; if (NS_SUCCEEDED(node->GetLocalName(name)) && @@ -771,14 +771,15 @@ nsXMLDocument::GetElementById(const nsAString& aElementId, // If we tried to load a document and something went wrong, we might not have // root content. This can happen when you do document.load() and the document // to load is not XML, for example. - if (!mRootContent) + nsIContent* root = GetRootContent(); + if (!root) return NS_OK; // XXX For now, we do a brute force search of the content tree. // We should come up with a more efficient solution. // Note that content is *not* refcounted here, so do *not* release it! nsIContent *content = - nsContentUtils::MatchElementId(mRootContent, aElementId); + nsContentUtils::MatchElementId(root, aElementId); if (!content) { return NS_OK; diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index be181b25266c..1ea473579c8f 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -1428,7 +1428,7 @@ nsXULDocument::GetPixelDimensions(nsIPresShell* aShell, PRInt32* aWidth, FlushPendingNotifications(Flush_Layout); - nsIFrame* frame = aShell->GetPrimaryFrameFor(mRootContent); + nsIFrame* frame = aShell->GetPrimaryFrameFor(GetRootContent()); if (frame) { nsIView* view = frame->GetView(); // If we have a view check if it's scrollable. If not, @@ -1962,7 +1962,7 @@ nsXULDocument::Init() nsresult nsXULDocument::StartLayout(void) { - if (!mRootContent) { + if (!GetRootContent()) { #ifdef PR_LOGGING if (PR_LOG_TEST(gXULLog, PR_LOG_WARNING)) { nsCAutoString urlspec; @@ -2949,7 +2949,7 @@ nsXULDocument::ResumeWalk() mDocumentLoaded = PR_TRUE; nsAutoString title; - mRootContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::title, title); + GetRootContent()->GetAttr(kNameSpaceID_None, nsHTMLAtoms::title, title); SetTitle(title); StartLayout(); @@ -3601,7 +3601,7 @@ nsXULDocument::OverlayForwardReference::Resolve() mOverlay->GetAttr(kNameSpaceID_None, nsXULAtoms::id, id); if (id.IsEmpty()) { // overlay had no id, use the root element - mDocument->InsertElement(mDocument->mRootContent, mOverlay, notify); + mDocument->InsertElement(mDocument->GetRootContent(), mOverlay, notify); mResolved = PR_TRUE; return eResolve_Succeeded; }