diff --git a/mozilla/content/base/public/nsIContent.h b/mozilla/content/base/public/nsIContent.h index 45f06babb06..fd0409a0f80 100644 --- a/mozilla/content/base/public/nsIContent.h +++ b/mozilla/content/base/public/nsIContent.h @@ -449,7 +449,7 @@ public: * * @param aContent the binding parent [OUT] */ - NS_IMETHOD GetBindingParent(nsIContent** aContent) = 0; + NS_IMETHOD GetBindingParent(nsIContent** aContent) const = 0; /** * Bit-flags to pass (or'ed together) to IsContentOfType() diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.cpp b/mozilla/content/base/src/nsGenericDOMDataNode.cpp index 906d27ec739..bda64926f8e 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/content/base/src/nsGenericDOMDataNode.cpp @@ -1028,8 +1028,9 @@ nsGenericDOMDataNode::RemoveFocus(nsIPresContext* aPresContext) } NS_IMETHODIMP -nsGenericDOMDataNode::GetBindingParent(nsIContent** aContent) +nsGenericDOMDataNode::GetBindingParent(nsIContent** aContent) const { + *aContent = nsnull; return NS_OK; } diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.h b/mozilla/content/base/src/nsGenericDOMDataNode.h index 55c11a19fe4..b0b0949a624 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.h +++ b/mozilla/content/base/src/nsGenericDOMDataNode.h @@ -208,7 +208,7 @@ public: NS_IMETHOD SetFocus(nsIPresContext *aPresContext); NS_IMETHOD RemoveFocus(nsIPresContext *aPresContext); - NS_IMETHOD GetBindingParent(nsIContent** aContent); + NS_IMETHOD GetBindingParent(nsIContent** aContent) const; NS_IMETHOD SetBindingParent(nsIContent* aParent); NS_IMETHOD_(PRBool) IsContentOfType(PRUint32 aFlags); diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index e680513627b..a69619f9948 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -2252,14 +2252,46 @@ nsGenericElement::GetBaseURL(nsIURI** aBaseURL) const mNodeInfo->GetDocument(getter_AddRefs(doc)); } - // Our base URL depends on whether we have an xml:base attribute, as - // well as on whether any of our ancestors do. - nsCOMPtr parentBase; + // Our base URL depends on whether we have an xml:base attribute, as well as + // on whether any of our ancestors do. The basic idea is to ask our parent + // (mParent if we have one, our document otherwise) for its base URL. Then we + // resolve our xml:base attr, if any, relative to that. + + // The one complication is that we may be an anonymous node bound via XBL. + // If this is the case, we still want to use our parent's baseURL unless our + // parent is not part of our own binding (eg is the element the binding is + // attached to). If that is the case, we want to use the binding url as the + // "parent" url. + + nsCOMPtr bindingParent, parentsBindingParent; + GetBindingParent(getter_AddRefs(bindingParent)); + if (mParent) { + mParent->GetBindingParent(getter_AddRefs(parentsBindingParent)); + } + + nsCOMPtr parentBase; + // XXX Not all things with a bindingParent are actually XBL anonymous + // content, so we may not end up getting a binding in the case when we have a + // bindingParent... This seems very wrong. Perhaps it should be fixed? + if (bindingParent && bindingParent != parentsBindingParent) { + // Get hold of the binding and get its URI + nsCOMPtr bindingMgr; + doc->GetBindingManager(getter_AddRefs(bindingMgr)); + if (bindingMgr) { + nsCOMPtr binding; + bindingMgr->GetBinding(bindingParent, getter_AddRefs(binding)); + if (binding) { + nsCAutoString bindingURI; + binding->GetBindingURI(bindingURI); + NS_NewURI(getter_AddRefs(parentBase), bindingURI); + } + } + } else if (mParent) { mParent->GetBaseURL(getter_AddRefs(parentBase)); - } else if (doc) { - // No parent, so just use the document (we must be the root or not in the - // tree). + } + + if (!parentBase && doc) { doc->GetBaseURL(getter_AddRefs(parentBase)); } @@ -2452,7 +2484,7 @@ nsGenericElement::RemoveFocus(nsIPresContext* aPresContext) } nsresult -nsGenericElement::GetBindingParent(nsIContent** aContent) +nsGenericElement::GetBindingParent(nsIContent** aContent) const { nsDOMSlots *slots = GetExistingDOMSlots(); diff --git a/mozilla/content/base/src/nsGenericElement.h b/mozilla/content/base/src/nsGenericElement.h index d40a071e7f7..1207ec73165 100644 --- a/mozilla/content/base/src/nsGenericElement.h +++ b/mozilla/content/base/src/nsGenericElement.h @@ -415,7 +415,7 @@ public: NS_IMETHOD SetContentID(PRUint32 aID); NS_IMETHOD SetFocus(nsIPresContext* aContext); NS_IMETHOD RemoveFocus(nsIPresContext* aContext); - NS_IMETHOD GetBindingParent(nsIContent** aContent); + NS_IMETHOD GetBindingParent(nsIContent** aContent) const; NS_IMETHOD SetBindingParent(nsIContent* aParent); NS_IMETHOD_(PRBool) IsContentOfType(PRUint32 aFlags); NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult); diff --git a/mozilla/content/html/content/src/nsAttributeContent.cpp b/mozilla/content/html/content/src/nsAttributeContent.cpp index d2771d4be96..edd034f5a04 100644 --- a/mozilla/content/html/content/src/nsAttributeContent.cpp +++ b/mozilla/content/html/content/src/nsAttributeContent.cpp @@ -119,7 +119,8 @@ public: NS_IMETHOD SetFocus(nsIPresContext* aPresContext) { return NS_OK; } NS_IMETHOD RemoveFocus(nsIPresContext* aPresContext) { return NS_OK; } - NS_IMETHOD GetBindingParent(nsIContent** aContent) { + NS_IMETHOD GetBindingParent(nsIContent** aContent) const { + *aContent = nsnull; return NS_OK; } diff --git a/mozilla/content/xbl/src/nsXBLBinding.cpp b/mozilla/content/xbl/src/nsXBLBinding.cpp index 9e04a596239..fde39392773 100644 --- a/mozilla/content/xbl/src/nsXBLBinding.cpp +++ b/mozilla/content/xbl/src/nsXBLBinding.cpp @@ -324,8 +324,11 @@ nsXBLBinding::InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElem for (PRInt32 i = 0; i < childCount; i++) { nsCOMPtr child; aAnonParent->ChildAt(i, getter_AddRefs(child)); - child->SetParent(aElement); + // Set the binding parent first, since setting the parent may cause + // relative URIs to change (due to xml:base) and |child| may need to be + // able to tell that it's anonymous content as it recomputes its base URI. child->SetBindingParent(mBoundElement); + child->SetParent(aElement); #ifdef MOZ_XUL // To make XUL templates work (and other goodies that happen when diff --git a/mozilla/content/xul/content/src/nsXULElement.cpp b/mozilla/content/xul/content/src/nsXULElement.cpp index 75a07ec11f3..8100ba08211 100644 --- a/mozilla/content/xul/content/src/nsXULElement.cpp +++ b/mozilla/content/xul/content/src/nsXULElement.cpp @@ -4331,10 +4331,9 @@ nsXULElement::RemoveFocus(nsIPresContext* aPresContext) } NS_IMETHODIMP -nsXULElement::GetBindingParent(nsIContent** aContent) +nsXULElement::GetBindingParent(nsIContent** aContent) const { - *aContent = mBindingParent; - NS_IF_ADDREF(*aContent); + NS_IF_ADDREF(*aContent = mBindingParent); return NS_OK; } diff --git a/mozilla/editor/libeditor/html/nsHTMLAnonymousUtils.cpp b/mozilla/editor/libeditor/html/nsHTMLAnonymousUtils.cpp index 8e999684335..0175d0c2146 100644 --- a/mozilla/editor/libeditor/html/nsHTMLAnonymousUtils.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLAnonymousUtils.cpp @@ -152,9 +152,12 @@ nsHTMLEditor::CreateAnonymousElement(const nsAString & aTag, nsIDOMNode * aPare // establish parenthood of the element newContent->SetNativeAnonymous(PR_TRUE); - newContent->SetParent(parentContent); newContent->SetDocument(doc, PR_TRUE, PR_TRUE); + // Set the binding parent first, since setting the parent may cause relative + // URIs to change (due to xml:base) and |newContent| may need to be able to + // tell that it's anonymous content as it recomputes its base URI. newContent->SetBindingParent(newContent); + newContent->SetParent(parentContent); // display the element ps->RecreateFramesFor(newContent); diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 8778b104601..f70506531dc 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -5127,23 +5127,26 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell continue; content->SetNativeAnonymous(PR_TRUE); - content->SetParent(aParent); content->SetDocument(aDocument, PR_TRUE, PR_TRUE); - + // Set the binding parent first, since setting the parent may cause + // relative URIs to change (due to xml:base) and |child| may need to be + // able to tell that it's anonymous content as it recomputes its base + // URI. + nsIContent* bindingParent = content; #ifdef MOZ_XUL // Only cut XUL scrollbars off if they're not in a XUL document. This allows // scrollbars to be styled from XUL (although not from XML or HTML). nsCOMPtr tag; content->GetTag(getter_AddRefs(tag)); - if (tag.get() == nsXULAtoms::scrollbar) { + if (tag == nsXULAtoms::scrollbar) { nsCOMPtr xulDoc(do_QueryInterface(aDocument)); - if (xulDoc) - content->SetBindingParent(aParent); - else content->SetBindingParent(content); + if (xulDoc) { + bindingParent = aParent; + } } - else #endif - content->SetBindingParent(content); + content->SetBindingParent(bindingParent); + content->SetParent(aParent); nsIFrame * newFrame = nsnull; nsresult rv = creator->CreateFrameFor(aPresContext, content, &newFrame); diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 8778b104601..f70506531dc 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -5127,23 +5127,26 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell continue; content->SetNativeAnonymous(PR_TRUE); - content->SetParent(aParent); content->SetDocument(aDocument, PR_TRUE, PR_TRUE); - + // Set the binding parent first, since setting the parent may cause + // relative URIs to change (due to xml:base) and |child| may need to be + // able to tell that it's anonymous content as it recomputes its base + // URI. + nsIContent* bindingParent = content; #ifdef MOZ_XUL // Only cut XUL scrollbars off if they're not in a XUL document. This allows // scrollbars to be styled from XUL (although not from XML or HTML). nsCOMPtr tag; content->GetTag(getter_AddRefs(tag)); - if (tag.get() == nsXULAtoms::scrollbar) { + if (tag == nsXULAtoms::scrollbar) { nsCOMPtr xulDoc(do_QueryInterface(aDocument)); - if (xulDoc) - content->SetBindingParent(aParent); - else content->SetBindingParent(content); + if (xulDoc) { + bindingParent = aParent; + } } - else #endif - content->SetBindingParent(content); + content->SetBindingParent(bindingParent); + content->SetParent(aParent); nsIFrame * newFrame = nsnull; nsresult rv = creator->CreateFrameFor(aPresContext, content, &newFrame);