Bug 515401: Make implementation of <base> HTML5 compliant, and clean it up. r=benjamn a=dholbert

This commit is contained in:
Jonas Sicking 2010-04-23 09:10:07 -07:00
parent 70a324e5f9
commit 24b255ef47
23 changed files with 253 additions and 591 deletions

View File

@ -115,8 +115,8 @@ class Link;
} // namespace mozilla
#define NS_IDOCUMENT_IID \
{ 0x17e1c0ce, 0x3883, 0x4efc, \
{ 0xbf, 0xdf, 0x40, 0xa6, 0x26, 0x9f, 0xbd, 0x2c } }
{ 0x4a0c9bfa, 0xef60, 0x4bb2, \
{ 0x87, 0x5e, 0xac, 0xdb, 0xe8, 0xfe, 0xa1, 0xb5 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -249,8 +249,7 @@ public:
/**
* Get/Set the base target of a link in a document.
*/
virtual void GetBaseTarget(nsAString &aBaseTarget) const = 0;
virtual void SetBaseTarget(const nsAString &aBaseTarget) = 0;
virtual void GetBaseTarget(nsAString &aBaseTarget) = 0;
/**
* Return a standard name for the document's character set.
@ -1328,24 +1327,6 @@ public:
*/
virtual PRInt32 GetDocumentState() = 0;
/**
* Gets the document's cached pointer to the first <base> element in this
* document which has an href attribute. If the document doesn't contain any
* <base> elements with an href, returns null.
*/
virtual nsIContent* GetFirstBaseNodeWithHref() = 0;
/**
* Sets the document's cached pointer to the first <base> element with an
* href attribute in this document and updates the document's base URI
* according to the element's href.
*
* If the given node is the same as the current first base node, this
* function still updates the document's base URI according to the node's
* href, if it changed.
*/
virtual nsresult SetFirstBaseNodeWithHref(nsIContent *node) = 0;
virtual nsISupports* GetCurrentContentSink() = 0;
/**

View File

@ -232,7 +232,6 @@ nsContentSink::Init(nsIDocument* aDoc,
mDocument = aDoc;
mDocumentURI = aURI;
mDocumentBaseURI = aURI;
mDocShell = do_QueryInterface(aContainer);
if (mDocShell) {
PRUint32 loadType = 0;
@ -781,7 +780,8 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement,
}
nsCOMPtr<nsIURI> url;
nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nsnull, mDocumentBaseURI);
nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nsnull,
mDocument->GetBaseURI());
if (NS_FAILED(rv)) {
// The URI is bad, move along, don't propagate the error (for now)
@ -890,7 +890,7 @@ nsContentSink::PrefetchHref(const nsAString &aHref,
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), aHref,
charset.IsEmpty() ? nsnull : PromiseFlatCString(charset).get(),
mDocumentBaseURI);
mDocument->GetBaseURI());
if (uri) {
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aSource);
prefetchService->PrefetchURI(uri, mDocumentURI, domNode, aExplicit);

View File

@ -306,7 +306,6 @@ protected:
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsIParser> mParser;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIURI> mDocumentBaseURI;
nsCOMPtr<nsIDocShell> mDocShell;
nsRefPtr<mozilla::css::Loader> mCSSLoader;
nsRefPtr<nsNodeInfoManager> mNodeInfoManager;

View File

@ -2913,48 +2913,45 @@ nsDocument::ReleaseCapture()
nsresult
nsDocument::SetBaseURI(nsIURI* aURI)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> oldBase = nsIDocument::GetBaseURI();
if (aURI) {
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(NodePrincipal(), aURI,
nsIScriptSecurityManager::STANDARD);
if (NS_SUCCEEDED(rv)) {
mDocumentBaseURI = NS_TryToMakeImmutable(aURI);
if (!aURI && !mDocumentBaseURI) {
return NS_OK;
}
// Don't do anything if the URI wasn't actually changed.
if (aURI && mDocumentBaseURI) {
PRBool equalBases = PR_FALSE;
mDocumentBaseURI->Equals(aURI, &equalBases);
if (equalBases) {
return NS_OK;
}
}
if (aURI) {
mDocumentBaseURI = NS_TryToMakeImmutable(aURI);
} else {
mDocumentBaseURI = nsnull;
}
RefreshLinkHrefs();
nsIURI* newBase = nsIDocument::GetBaseURI();
PRBool equalBases = PR_FALSE;
if (oldBase && newBase) {
oldBase->Equals(newBase, &equalBases);
}
else {
equalBases = !oldBase && !newBase;
}
// If the document's base URI has changed, we need to re-resolve all the
// cached link hrefs relative to the new base.
if (!equalBases) {
RefreshLinkHrefs();
}
return rv;
return NS_OK;
}
void
nsDocument::GetBaseTarget(nsAString &aBaseTarget) const
nsDocument::GetBaseTarget(nsAString &aBaseTarget)
{
aBaseTarget.Assign(mBaseTarget);
}
void
nsDocument::SetBaseTarget(const nsAString &aBaseTarget)
{
mBaseTarget.Assign(aBaseTarget);
aBaseTarget.Truncate();
nsIContent* head = GetHeadContent();
if (!head) {
return;
}
for (ChildIterator iter(head); !iter.IsDone(); iter.Next()) {
nsIContent* child = iter;
if (child->NodeInfo()->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
child->GetAttr(kNameSpaceID_None, nsGkAtoms::target, aBaseTarget)) {
return;
}
}
}
void
@ -7572,48 +7569,6 @@ nsDocument::RefreshLinkHrefs()
}
}
nsIContent*
nsDocument::GetFirstBaseNodeWithHref()
{
return mFirstBaseNodeWithHref;
}
nsresult
nsDocument::SetFirstBaseNodeWithHref(nsIContent *elem)
{
mFirstBaseNodeWithHref = elem;
if (!elem) {
SetBaseURI(nsnull);
return NS_OK;
}
NS_ASSERTION(elem->Tag() == nsGkAtoms::base,
"Setting base node to a non <base> element?");
NS_ASSERTION(elem->GetNameSpaceID() == kNameSpaceID_XHTML,
"Setting base node to a non XHTML element?");
nsIDocument* doc = elem->GetOwnerDoc();
nsIURI* currentURI = nsIDocument::GetDocumentURI();
// Resolve the <base> element's href relative to our current URI
nsAutoString href;
PRBool hasHref = elem->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
NS_ASSERTION(hasHref,
"Setting first base node to a node with no href attr?");
nsCOMPtr<nsIURI> newBaseURI;
nsContentUtils::NewURIWithDocumentCharset(
getter_AddRefs(newBaseURI), href, doc, currentURI);
// Try to set our base URI. If that fails, try to set our base URI to null.
nsresult rv = SetBaseURI(newBaseURI);
if (NS_FAILED(rv)) {
return SetBaseURI(nsnull);
}
return rv;
}
NS_IMETHODIMP
nsDocument::GetScriptTypeID(PRUint32 *aScriptType)
{

View File

@ -544,8 +544,7 @@ public:
/**
* Get/Set the base target of a link in a document.
*/
virtual void GetBaseTarget(nsAString &aBaseTarget) const;
virtual void SetBaseTarget(const nsAString &aBaseTarget);
virtual void GetBaseTarget(nsAString &aBaseTarget);
/**
* Return a standard name for the document's character set. This will

View File

@ -423,8 +423,6 @@ GK_ATOM(href, "href")
GK_ATOM(hreflang, "hreflang")
GK_ATOM(hspace, "hspace")
GK_ATOM(html, "html")
GK_ATOM(htmlBaseHref, "html-base-href")
GK_ATOM(htmlBaseTarget, "html-base-target")
GK_ATOM(httpEquiv, "http-equiv")
GK_ATOM(i, "i")
GK_ATOM(id, "id")

View File

@ -366,6 +366,7 @@ _TEST_FILES = test_bug5141.html \
test_bug545644.html \
test_bug545644.xhtml \
test_bug553896.xhtml \
test_bug515401.html \
test_bug541937.html \
file_bug541937.html \
file_bug541937.xhtml \

View File

@ -0,0 +1,134 @@
<<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=515401
-->
<head>
<title>Test for Bug 515401</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<base id=basehref href="base/">
<base id=basehref2>
<base id=basetarget target="def_target">
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=515401">Mozilla Bug 515401</a>
<a id=a href="dest.html">Simple link</a>
<a id=awtarget target="a_target">Link with target</a>
<p id="display"></p>
<pre id="test">
<script class="testbody" type="text/javascript">
var a = $('a');
var awtarget = $('awtarget');
var head = document.documentElement.firstElementChild;
// Test targets
is(a.target, "def_target", "using default target");
is(awtarget.target, "a_target", "specified target");
$('basetarget').setAttribute("target", "new_def_target");
is(a.target, "new_def_target", "using new default target");
is(awtarget.target, "a_target", "still specified target");
$('basetarget').removeAttribute("target");
is(a.target, "", "no target");
is(awtarget.target, "a_target", "yet still specified target");
newbasetarget = document.createElement('base');
newbasetarget.target = "new_target_elem";
head.appendChild(newbasetarget);
is(a.target, "new_target_elem", "new target element");
is(awtarget.target, "a_target", "yet still specified target");
newbasetarget.target = "new_target_elem_value";
is(a.target, "new_target_elem_value", "new target element attribute");
is(awtarget.target, "a_target", "yet still specified target");
newbasetarget.target = "";
is(a.target, "", "new target element no attribute");
is(awtarget.target, "a_target", "yet still specified target");
// link hrefs
var basehref = $('basehref');
var basehref2 = $('basehref2');
var pre = "http://mochi.test:8888/tests/content/base/test/";
function verifyBase(base, test) {
if (base == "") {
is(document.baseURI, document.URL, "document base when " + test);
is(a.href, pre + "dest.html", "link href when " + test);
}
else {
is(document.baseURI, pre + base, "document base when " + test);
is(a.href, pre + base + "dest.html", "link href when " + test);
}
}
// In document base
verifyBase("base/", "from markup");
// Modify existing <base>
basehref.href = "base2/";
verifyBase("base2/", "modify existing");
// Remove href on existing element
basehref.removeAttribute("href");
verifyBase("", "remove href on existing element");
// Create href on existing element
basehref.href = "base3/";
verifyBase("base3/", "create href on existing element");
// Fall back to second after remove attr
basehref2.href = "base4/";
verifyBase("base3/", "add href on second base");
basehref.removeAttribute("href");
verifyBase("base4/", "fall back to second after remove attr");
// Set href on existing again
basehref.href = "base5/";
verifyBase("base5/", "set href on existing again");
// Unset href on second
basehref2.removeAttribute("href");
verifyBase("base5/", "unset href on second");
// Insert base with href before existing
var basehref0 = document.createElement("base");
basehref0.href = "base6/";
verifyBase("base5/", "nothing modified");
head.insertBefore(basehref0, head.firstChild.nextElementSibling);
verifyBase("base6/", "insert base with href before existing");
// Insert base as grandchild of head
var baseerr = document.createElement("base");
baseerr.href = "baseerr/";
var tmp = document.createElement("head");
tmp.appendChild(baseerr);
head.insertBefore(tmp, head.firstChild);
verifyBase("base6/", "inserted base as grandchild of head");
is(baseerr.parentNode.parentNode, head, "base got inserted correctly");
// Remove secondary bases
var tmp, tmp2;
for (tmp = head.firstChild; tmp = tmp.nextSibling; tmp) {
if (tmp.localName == "base" && tmp != basehref0) {
tmp2 = tmp.previousSibling;
head.removeChild(tmp);
tmp = tmp2;
}
verifyBase("base6/", "remove unneeded base");
}
// Remove head
document.documentElement.removeChild(head);
verifyBase("", "removed head");
// Insert base in body
document.body.insertBefore(baseerr, document.body.firstChild);
verifyBase("", "inserted base in body");
</script>
</pre>
</body>
</html>

View File

@ -266,23 +266,6 @@ nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst) const
NS_ENSURE_SUCCESS(rv, rv);
}
// Copy the baseuri and basetarget
void* prop;
if ((prop = GetProperty(nsGkAtoms::htmlBaseHref))) {
rv = aDst->SetProperty(nsGkAtoms::htmlBaseHref, prop,
nsPropertyTable::SupportsDtorFunc, PR_TRUE);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(static_cast<nsIURI*>(prop));
}
}
if ((prop = GetProperty(nsGkAtoms::htmlBaseTarget))) {
rv = aDst->SetProperty(nsGkAtoms::htmlBaseTarget, prop,
nsPropertyTable::SupportsDtorFunc, PR_TRUE);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(static_cast<nsIAtom*>(prop));
}
}
return NS_OK;
}
@ -1153,30 +1136,9 @@ nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
return NS_OK;
}
already_AddRefed<nsIURI>
nsGenericHTMLElement::GetBaseURI() const
{
void* prop;
if (HasFlag(NODE_HAS_PROPERTIES) && (prop = GetProperty(nsGkAtoms::htmlBaseHref))) {
nsIURI* uri = static_cast<nsIURI*>(prop);
NS_ADDREF(uri);
return uri;
}
return nsGenericHTMLElementBase::GetBaseURI();
}
void
nsGenericHTMLElement::GetBaseTarget(nsAString& aBaseTarget) const
{
void* prop;
if (HasFlag(NODE_HAS_PROPERTIES) && (prop = GetProperty(nsGkAtoms::htmlBaseTarget))) {
static_cast<nsIAtom*>(prop)->ToString(aBaseTarget);
return;
}
nsIDocument* ownerDoc = GetOwnerDoc();
if (ownerDoc) {
ownerDoc->GetBaseTarget(aBaseTarget);

View File

@ -209,8 +209,6 @@ public:
virtual void UpdateEditableState();
already_AddRefed<nsIURI> GetBaseURI() const;
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,

View File

@ -428,6 +428,43 @@ nsHTMLSharedElement::IsAttributeMapped(const nsIAtom* aAttribute) const
return nsGenericHTMLElement::IsAttributeMapped(aAttribute);
}
void
SetBaseURIUsingFirstBaseWithHref(nsIContent* aHead, nsIContent* aMustMatch)
{
NS_PRECONDITION(aHead && aHead->GetOwnerDoc() &&
aHead->GetOwnerDoc()->GetHeadContent() == aHead,
"Bad head");
nsIDocument* doc = aHead->GetOwnerDoc();
for (nsINode::ChildIterator iter(aHead); !iter.IsDone(); iter.Next()) {
nsIContent* child = iter;
if (child->NodeInfo()->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
child->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
if (aMustMatch && child != aMustMatch) {
return;
}
// Resolve the <base> element's href relative to our document URI
nsAutoString href;
child->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
nsCOMPtr<nsIURI> newBaseURI;
nsContentUtils::NewURIWithDocumentCharset(
getter_AddRefs(newBaseURI), href, doc, doc->GetDocumentURI());
// Try to set our base URI. If that fails, try to set base URI to null
nsresult rv = doc->SetBaseURI(newBaseURI);
if (NS_FAILED(rv)) {
doc->SetBaseURI(nsnull);
}
return;
}
}
doc->SetBaseURI(nsnull);
}
nsresult
nsHTMLSharedElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
@ -435,64 +472,22 @@ nsHTMLSharedElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
{
nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
aValue, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
// If the href attribute of a <base> tag is changing, we may need to update
// the document's base URI, which will cause all the links on the page to be
// re-resolved given the new base.
if (NS_SUCCEEDED(rv) &&
mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
nsIContent* head;
if (mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
aName == nsGkAtoms::href &&
aNameSpaceID == kNameSpaceID_None &&
GetOwnerDoc() == GetCurrentDoc()) {
nsIDocument* doc = GetCurrentDoc();
NS_ENSURE_TRUE(doc, NS_OK);
// We become the first base node with an href if
// * there's no other base node with an href, or
// * we come before the first base node with an href (this would happen
// if we didn't have an href before this call to SetAttr).
// Additionally, we call doc->SetFirstBaseNodeWithHref if we're the first
// base node with an href so the document updates its base URI with our new
// href.
nsIContent* firstBase = doc->GetFirstBaseNodeWithHref();
if (!firstBase || this == firstBase ||
nsContentUtils::PositionIsBefore(this, firstBase)) {
return doc->SetFirstBaseNodeWithHref(this);
}
IsInDoc() &&
(head = GetParent()) &&
head == GetOwnerDoc()->GetHeadContent()) {
SetBaseURIUsingFirstBaseWithHref(head, this);
}
return rv;
}
// Helper function for nsHTMLSharedElement::UnbindFromTree. Finds and returns
// the first <base> tag with an href attribute which is a child of elem, if one
// exists.
static nsIContent*
FindBaseRecursive(nsINode * const elem)
{
// We can't use NS_GetContentList to get the list of <base> elements, because
// that flushes content notifications, and we need this function to work in
// UnbindFromTree. Once we land the HTML5 parser and get rid of content
// notifications, we should fix this up. (bug 515819)
PRUint32 childCount;
nsIContent * const * child = elem->GetChildArray(&childCount);
nsIContent * const * end = child + childCount;
for ( ; child != end; child++) {
nsIContent *childElem = *child;
if (childElem->NodeInfo()->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
childElem->HasAttr(kNameSpaceID_None, nsGkAtoms::href))
return childElem;
nsIContent* base = FindBaseRecursive(childElem);
if (base)
return base;
}
return nsnull;
return NS_OK;
}
nsresult
@ -500,31 +495,22 @@ nsHTMLSharedElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
PRBool aNotify)
{
nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aName, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
// If we're the first <base> with an href and our href attribute is being
// unset, then we're no longer the first <base> with an href, and we need to
// find the new one.
if (NS_SUCCEEDED(rv) &&
mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
nsIContent* head;
if (mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
aName == nsGkAtoms::href &&
aNameSpaceID == kNameSpaceID_None &&
GetOwnerDoc() == GetCurrentDoc()) {
nsIDocument* doc = GetCurrentDoc();
NS_ENSURE_TRUE(doc, NS_OK);
// If we're not the first <base> in the document, then unsetting our href
// doesn't affect the document's base URI.
if (this != doc->GetFirstBaseNodeWithHref())
return NS_OK;
// We're the first base, but we don't have an href; find the first base
// which does have an href, and set the document's first base to that.
nsIContent* newBaseNode = FindBaseRecursive(doc);
return doc->SetFirstBaseNodeWithHref(newBaseNode);
IsInDoc() &&
(head = GetParent()) &&
head == GetOwnerDoc()->GetHeadContent()) {
SetBaseURIUsingFirstBaseWithHref(head, nsnull);
}
return rv;
return NS_OK;
}
nsresult
@ -535,46 +521,46 @@ nsHTMLSharedElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
// The document stores a pointer to its first <base> element, which we may
// need to update here.
if (NS_SUCCEEDED(rv) &&
mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
if (mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
HasAttr(kNameSpaceID_None, nsGkAtoms::href) &&
aDocument) {
aDocument && aParent &&
aDocument->GetHeadContent() == aParent) {
// If there's no <base> in the document, or if this comes before the one
// that's currently there, set the document's first <base> to this.
nsINode* curBaseNode = aDocument->GetFirstBaseNodeWithHref();
if (!curBaseNode ||
nsContentUtils::PositionIsBefore(this, curBaseNode)) {
aDocument->SetFirstBaseNodeWithHref(this);
}
SetBaseURIUsingFirstBaseWithHref(aParent, this);
}
return rv;
return NS_OK;
}
void
nsHTMLSharedElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsCOMPtr<nsIDocument> doc = GetCurrentDoc();
nsIDocument* doc;
nsIContent* parent;
PRBool inHeadBase = mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
(doc = GetCurrentDoc()) &&
(parent = GetParent()) &&
parent->NodeInfo()->Equals(nsGkAtoms::head,
kNameSpaceID_XHTML);
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
// If we're removing a <base> from a document, we may need to update the
// document's record of the first base node.
if (doc && mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML)) {
// If we're not the first base node, then we don't need to do anything.
if (this != doc->GetFirstBaseNodeWithHref())
return;
// If we were the first base node, we need to find the new first base.
nsIContent* newBaseNode = FindBaseRecursive(doc);
doc->SetFirstBaseNodeWithHref(newBaseNode);
if (inHeadBase) {
// We might have gotten here as a result of the <head> being removed
// from the document. In that case we need to call SetBaseURI(nsnull)
nsIContent* head = doc->GetHeadContent();
if (head) {
SetBaseURIUsingFirstBaseWithHref(head, nsnull);
}
else {
doc->SetBaseURI(nsnull);
}
}
}

View File

@ -250,9 +250,6 @@ protected:
SinkContext* mHeadContext;
PRInt32 mNumOpenIFRAMES;
nsCOMPtr<nsIURI> mBaseHref;
nsCOMPtr<nsIAtom> mBaseTarget;
// depth of containment within <noembed>, <noframes> etc
PRInt32 mInsideNoXXXTag;
@ -277,14 +274,6 @@ protected:
void StartLayout(PRBool aIgnorePendingSheets);
/**
* AddBaseTagInfo adds the "current" base URI and target to the content node
* in the form of bogo-attributes. This MUST be called before attributes are
* added to the content node, since the way URI attributes are treated may
* depend on the value of the base URI
*/
void AddBaseTagInfo(nsIContent* aContent);
// Routines for tags that require special handling
nsresult CloseHTML();
nsresult OpenFrameset(const nsIParserNode& aNode);
@ -293,7 +282,6 @@ protected:
nsresult CloseBody();
nsresult OpenForm(const nsIParserNode& aNode);
nsresult CloseForm();
void ProcessBASEElement(nsGenericHTMLElement* aElement);
nsresult ProcessLINKTag(const nsIParserNode& aNode);
// Routines for tags that require special handling when we reach their end
@ -788,39 +776,6 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
ssle->SetEnableUpdates(PR_FALSE);
}
// Make sure to add base tag info, if needed, before setting any other
// attributes -- what URI attrs do will depend on the base URI. Only do this
// for elements that have useful URI attributes.
// See bug 18478 and bug 30617 for why we need to do this.
switch (nodeType) {
// Containers with "href="
case eHTMLTag_a:
case eHTMLTag_map:
// Containers with "src="
case eHTMLTag_script:
// Containers with "action="
case eHTMLTag_form:
// Containers with "data="
case eHTMLTag_object:
// Containers with "background="
case eHTMLTag_table:
case eHTMLTag_thead:
case eHTMLTag_tbody:
case eHTMLTag_tfoot:
case eHTMLTag_tr:
case eHTMLTag_td:
case eHTMLTag_th:
mSink->AddBaseTagInfo(content);
break;
default:
break;
}
rv = mSink->AddAttributes(aNode, content);
MaybeSetForm(content, nodeType, mSink);
@ -1047,28 +1002,8 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
mSink->CreateContentObject(aNode, nodeType);
NS_ENSURE_TRUE(content, NS_ERROR_OUT_OF_MEMORY);
// Make sure to add base tag info, if needed, before setting any other
// attributes -- what URI attrs do will depend on the base URI. Only do
// this for elements that have useful URI attributes.
// See bug 18478 and bug 30617 for why we need to do this.
switch (nodeType) {
case eHTMLTag_area:
case eHTMLTag_meta:
case eHTMLTag_img:
case eHTMLTag_frame:
case eHTMLTag_input:
case eHTMLTag_embed:
mSink->AddBaseTagInfo(content);
break;
// <form> can end up as a leaf if it's misnested with table elements
case eHTMLTag_form:
mSink->AddBaseTagInfo(content);
if (nodeType == eHTMLTag_form) {
mSink->mCurrentForm = content;
break;
default:
break;
}
rv = mSink->AddAttributes(aNode, content);
@ -1082,12 +1017,6 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
// Additional processing needed once the element is in the tree
switch (nodeType) {
case eHTMLTag_base:
if (!mSink->mInsideNoXXXTag) {
mSink->ProcessBASEElement(content);
}
break;
case eHTMLTag_meta:
// XXX It's just not sufficient to check if the parent is head. Also
// check for the preference.
@ -2630,28 +2559,6 @@ HTMLContentSink::StartLayout(PRBool aIgnorePendingSheets)
nsContentSink::StartLayout(aIgnorePendingSheets);
}
void
HTMLContentSink::AddBaseTagInfo(nsIContent* aContent)
{
nsresult rv;
if (mBaseHref) {
rv = aContent->SetProperty(nsGkAtoms::htmlBaseHref, mBaseHref,
nsPropertyTable::SupportsDtorFunc, PR_TRUE);
if (NS_SUCCEEDED(rv)) {
// circumvent nsDerivedSafe
NS_ADDREF(static_cast<nsIURI*>(mBaseHref));
}
}
if (mBaseTarget) {
rv = aContent->SetProperty(nsGkAtoms::htmlBaseTarget, mBaseTarget,
nsPropertyTable::SupportsDtorFunc, PR_TRUE);
if (NS_SUCCEEDED(rv)) {
// circumvent nsDerivedSafe
NS_ADDREF(static_cast<nsIAtom*>(mBaseTarget));
}
}
}
nsresult
HTMLContentSink::OpenHeadContext()
{
@ -2703,56 +2610,6 @@ HTMLContentSink::CloseHeadContext()
}
}
void
HTMLContentSink::ProcessBASEElement(nsGenericHTMLElement* aElement)
{
// href attribute
nsAutoString attrValue;
if (aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, attrValue)) {
//-- Make sure this page is allowed to load this URI
nsresult rv;
nsCOMPtr<nsIURI> baseHrefURI;
rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(baseHrefURI),
attrValue, mDocument,
nsnull);
if (NS_FAILED(rv))
return;
// Setting "BASE URI" from the last BASE tag appearing in HEAD.
if (!mBody) {
// The document checks if it is legal to set this base. Failing here is
// ok, we just won't set a new base.
rv = mDocument->SetBaseURI(baseHrefURI);
if (NS_SUCCEEDED(rv)) {
mDocumentBaseURI = mDocument->GetBaseURI();
}
} else {
// NAV compatibility quirk
nsIScriptSecurityManager *securityManager =
nsContentUtils::GetSecurityManager();
rv = securityManager->
CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), baseHrefURI,
nsIScriptSecurityManager::STANDARD);
if (NS_SUCCEEDED(rv)) {
mBaseHref = baseHrefURI;
}
}
}
// target attribute
if (aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::target, attrValue)) {
if (!mBody) {
// still in real HEAD
mDocument->SetBaseTarget(attrValue);
} else {
// NAV compatibility quirk
mBaseTarget = do_GetAtom(attrValue);
}
}
}
nsresult
HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode)
{
@ -2781,7 +2638,6 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode)
// Add in the attributes and add the style content object to the
// head container.
AddBaseTagInfo(element);
result = AddAttributes(aNode, element);
if (NS_FAILED(result)) {
return result;

View File

@ -136,9 +136,6 @@ public:
nsresult AddText(const nsAString& aString);
nsresult FlushText();
void ProcessBaseTag(nsIContent* aContent);
void AddBaseTagInfo(nsIContent* aContent);
nsresult Init();
PRPackedBool mAllContent;
@ -156,9 +153,6 @@ public:
PRInt32 mTextLength;
PRInt32 mTextSize;
nsCOMPtr<nsIURI> mBaseHref;
nsCOMPtr<nsIAtom> mBaseTarget;
nsCOMPtr<nsIDocument> mTargetDocument;
nsRefPtr<nsNodeInfoManager> mNodeInfoManager;
@ -328,63 +322,6 @@ nsHTMLFragmentContentSink::OpenHead()
return NS_OK;
}
void
nsHTMLFragmentContentSink::ProcessBaseTag(nsIContent* aContent)
{
nsAutoString value;
if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, value)) {
nsCOMPtr<nsIURI> baseHrefURI;
nsresult rv =
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(baseHrefURI),
value, mTargetDocument,
nsnull);
if (NS_FAILED(rv))
return;
nsIScriptSecurityManager *securityManager =
nsContentUtils::GetSecurityManager();
NS_ASSERTION(aContent->NodePrincipal() == mTargetDocument->NodePrincipal(),
"How'd that happpen?");
rv = securityManager->
CheckLoadURIWithPrincipal(mTargetDocument->NodePrincipal(), baseHrefURI,
nsIScriptSecurityManager::STANDARD);
if (NS_SUCCEEDED(rv)) {
mBaseHref = baseHrefURI;
}
}
if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::target, value)) {
mBaseTarget = do_GetAtom(value);
}
}
void
nsHTMLFragmentContentSink::AddBaseTagInfo(nsIContent* aContent)
{
if (!aContent) {
return;
}
nsresult rv;
if (mBaseHref) {
rv = aContent->SetProperty(nsGkAtoms::htmlBaseHref, mBaseHref,
nsPropertyTable::SupportsDtorFunc, PR_TRUE);
if (NS_SUCCEEDED(rv)) {
// circumvent nsDerivedSafe
NS_ADDREF(static_cast<nsIURI*>(mBaseHref));
}
}
if (mBaseTarget) {
rv = aContent->SetProperty(nsGkAtoms::htmlBaseTarget, mBaseTarget,
nsPropertyTable::SupportsDtorFunc, PR_TRUE);
if (NS_SUCCEEDED(rv)) {
// circumvent nsDerivedSafe
NS_ADDREF(static_cast<nsIAtom*>(mBaseTarget));
}
}
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
{
@ -459,16 +396,6 @@ nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
parent->AppendChildTo(content, PR_FALSE);
PushContent(content);
if (nodeType == eHTMLTag_table
|| nodeType == eHTMLTag_thead
|| nodeType == eHTMLTag_tbody
|| nodeType == eHTMLTag_tfoot
|| nodeType == eHTMLTag_tr
|| nodeType == eHTMLTag_td
|| nodeType == eHTMLTag_th)
// XXX if navigator_quirks_mode (only body in html supports background)
AddBaseTagInfo(content);
}
else if (mProcessing && mIgnoreContainer) {
mIgnoreContainer = PR_FALSE;
@ -553,12 +480,6 @@ nsHTMLFragmentContentSink::AddLeaf(const nsIParserNode& aNode)
}
parent->AppendChildTo(content, PR_FALSE);
if (nodeType == eHTMLTag_img || nodeType == eHTMLTag_frame
|| nodeType == eHTMLTag_input) // elements with 'SRC='
AddBaseTagInfo(content);
else if (nodeType == eHTMLTag_base)
ProcessBaseTag(content);
}
break;
case eToken_text:
@ -1073,16 +994,6 @@ nsHTMLParanoidFragmentSink::AddAttributes(const nsIParserNode& aNode,
// Add attribute to content
aContent->SetAttr(kNameSpaceID_None, keyAtom, v, PR_FALSE);
}
if (nodeType == eHTMLTag_a ||
nodeType == eHTMLTag_form ||
nodeType == eHTMLTag_img ||
nodeType == eHTMLTag_map ||
nodeType == eHTMLTag_q ||
nodeType == eHTMLTag_blockquote ||
nodeType == eHTMLTag_input) {
AddBaseTagInfo(aContent);
}
}
return NS_OK;
@ -1150,21 +1061,8 @@ nsHTMLParanoidFragmentSink::AddLeaf(const nsIParserNode& aNode)
rv = NameFromNode(aNode, getter_AddRefs(name));
NS_ENSURE_SUCCESS(rv, rv);
// We will process base tags, but we won't include them
// in the output
// Don't include base tags in output.
if (name == nsGkAtoms::base) {
nsCOMPtr<nsIContent> content;
nsCOMPtr<nsINodeInfo> nodeInfo;
nsIParserService* parserService = nsContentUtils::GetParserService();
if (!parserService)
return NS_ERROR_OUT_OF_MEMORY;
nodeInfo = mNodeInfoManager->GetNodeInfo(name, nsnull,
kNameSpaceID_XHTML);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
rv = NS_NewHTMLElement(getter_AddRefs(content), nodeInfo, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
AddAttributes(aNode, content);
ProcessBaseTag(content);
return NS_OK;
}

View File

@ -632,13 +632,7 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
return rv;
}
if (nodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) &&
!mHasProcessedBase) {
// The first base wins
ProcessBASETag(aContent);
mHasProcessedBase = PR_TRUE;
}
else if (nodeInfo->Equals(nsGkAtoms::meta, kNameSpaceID_XHTML) &&
if (nodeInfo->Equals(nsGkAtoms::meta, kNameSpaceID_XHTML) &&
// Need to check here to make sure this meta tag does not set
// mPrettyPrintXML to false when we have a special root!
(!mPrettyPrintXML || !mPrettyPrintHasSpecialRoot)) {
@ -756,7 +750,8 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement,
return NS_OK;
nsCOMPtr<nsIURI> url;
rv = NS_NewURI(getter_AddRefs(url), aHref, nsnull, mDocumentBaseURI);
rv = NS_NewURI(getter_AddRefs(url), aHref, nsnull,
mDocument->GetBaseURI());
NS_ENSURE_SUCCESS(rv, rv);
// Do security check
@ -797,32 +792,6 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement,
return rv;
}
void
nsXMLContentSink::ProcessBASETag(nsIContent* aContent)
{
NS_ASSERTION(aContent, "missing base-element");
if (mDocument) {
nsAutoString value;
if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::target, value)) {
mDocument->SetBaseTarget(value);
}
if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, value)) {
nsCOMPtr<nsIURI> baseURI;
nsresult rv = NS_NewURI(getter_AddRefs(baseURI), value);
if (NS_SUCCEEDED(rv)) {
rv = mDocument->SetBaseURI(baseURI); // The document checks if it is legal to set this base
if (NS_SUCCEEDED(rv)) {
mDocumentBaseURI = mDocument->GetBaseURI();
}
}
}
}
}
NS_IMETHODIMP
nsXMLContentSink::SetDocumentCharset(nsACString& aCharset)
{

View File

@ -152,8 +152,6 @@ protected:
void PopContent();
PRBool HaveNotifiedForCurrentContent() const;
void ProcessBASETag(nsIContent* aContent);
nsresult FlushTags();
void UpdateChildCounts();
@ -206,7 +204,6 @@ protected:
PRUint8 mPrettyPrintXML : 1;
PRUint8 mPrettyPrintHasSpecialRoot : 1;
PRUint8 mPrettyPrintHasFactoredElements : 1;
PRUint8 mHasProcessedBase : 1;
PRUint8 mPrettyPrinting : 1; // True if we called PrettyPrint() and it
// decided we should in fact prettyprint.

View File

@ -86,7 +86,6 @@ txMozillaXMLOutput::txMozillaXMLOutput(const nsSubstring& aRootName,
: mTreeDepth(0),
mBadChildLevel(0),
mTableState(NORMAL),
mHaveBaseElement(PR_FALSE),
mCreatingNewDocument(PR_TRUE),
mOpenedElementIsHTML(PR_FALSE),
mRootContentCreated(PR_FALSE),
@ -111,7 +110,6 @@ txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
: mTreeDepth(0),
mBadChildLevel(0),
mTableState(NORMAL),
mHaveBaseElement(PR_FALSE),
mCreatingNewDocument(PR_FALSE),
mOpenedElementIsHTML(PR_FALSE),
mRootContentCreated(PR_FALSE),
@ -763,23 +761,6 @@ txMozillaXMLOutput::endHTMLElement(nsIContent* aElement)
return NS_OK;
}
else if (mCreatingNewDocument && atom == txHTMLAtoms::base &&
!mHaveBaseElement) {
// The first base wins
mHaveBaseElement = PR_TRUE;
nsAutoString value;
aElement->GetAttr(kNameSpaceID_None, txHTMLAtoms::target, value);
mDocument->SetBaseTarget(value);
aElement->GetAttr(kNameSpaceID_None, txHTMLAtoms::href, value);
nsCOMPtr<nsIURI> baseURI;
NS_NewURI(getter_AddRefs(baseURI), value, nsnull);
if (baseURI) {
mDocument->SetBaseURI(baseURI); // The document checks if it is legal to set this base
}
}
else if (mCreatingNewDocument && atom == txHTMLAtoms::meta) {
// handle HTTP-EQUIV data
nsAutoString httpEquiv;

View File

@ -153,8 +153,6 @@ private:
txOutputFormat mOutputFormat;
PRPackedBool mHaveBaseElement;
PRPackedBool mCreatingNewDocument;
PRPackedBool mOpenedElementIsHTML;

View File

@ -449,8 +449,6 @@ nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer,
Initialize(doc, uri, nsnull, nsnull);
// Initialize() doesn't deal with base URI
mExecutor->SetBaseUriFromDocument();
mExecutor->SetParser(this);
mExecutor->SetNodeInfoManager(doc->NodeInfoManager());

View File

@ -501,12 +501,6 @@ nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent
treeOp->Init(eTreeOpDoneCreatingElement, aElement);
return;
}
if (aName == nsHtml5Atoms::base) {
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
NS_ASSERTION(treeOp, "Tree op allocation failed.");
treeOp->Init(eTreeOpProcessBase, aElement);
return;
}
if (aName == nsHtml5Atoms::meta) {
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
NS_ASSERTION(treeOp, "Tree op allocation failed.");

View File

@ -603,34 +603,6 @@ nsHtml5TreeOpExecutor::FlushDocumentWrite()
}
}
nsresult
nsHtml5TreeOpExecutor::ProcessBASETag(nsIContent* aContent)
{
NS_ASSERTION(aContent, "missing base-element");
if (mHasProcessedBase) {
return NS_OK;
}
mHasProcessedBase = PR_TRUE;
nsresult rv = NS_OK;
if (mDocument) {
nsAutoString value;
if (aContent->GetAttr(kNameSpaceID_None, nsHtml5Atoms::target, value)) {
mDocument->SetBaseTarget(value);
}
if (aContent->GetAttr(kNameSpaceID_None, nsHtml5Atoms::href, value)) {
nsCOMPtr<nsIURI> baseURI;
rv = NS_NewURI(getter_AddRefs(baseURI), value);
if (NS_SUCCEEDED(rv)) {
rv = mDocument->SetBaseURI(baseURI); // The document checks if it is legal to set this base
if (NS_SUCCEEDED(rv)) {
mDocumentBaseURI = mDocument->GetBaseURI();
}
}
}
}
return rv;
}
// copied from HTML content sink
PRBool
nsHtml5TreeOpExecutor::IsScriptEnabled()
@ -827,7 +799,6 @@ nsHtml5TreeOpExecutor::GetTokenizer()
void
nsHtml5TreeOpExecutor::Reset() {
DropHeldElements();
mHasProcessedBase = PR_FALSE;
mReadingFromStage = PR_FALSE;
mOpQueue.Clear();
mStarted = PR_FALSE;

View File

@ -97,7 +97,6 @@ class nsHtml5TreeOpExecutor : public nsContentSink,
*/
PRBool mSuppressEOF;
PRBool mHasProcessedBase;
PRBool mReadingFromStage;
nsTArray<nsHtml5TreeOperation> mOpQueue;
nsTArray<nsIContentPtr> mElementsSeenInThisAppendBatch;
@ -188,7 +187,6 @@ class nsHtml5TreeOpExecutor : public nsContentSink,
virtual nsISupports *GetTarget();
// nsContentSink methods
virtual nsresult ProcessBASETag(nsIContent* aContent);
virtual void UpdateChildCounts();
virtual nsresult FlushTags();
virtual void PostEvaluateScript(nsIScriptElement *aElement);
@ -214,11 +212,6 @@ class nsHtml5TreeOpExecutor : public nsContentSink,
return IsScriptExecutingImpl();
}
void SetBaseUriFromDocument() {
mDocumentBaseURI = mDocument->GetBaseURI();
mHasProcessedBase = PR_TRUE;
}
void SetNodeInfoManager(nsNodeInfoManager* aManager) {
mNodeInfoManager = aManager;
}

View File

@ -603,11 +603,6 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
aBuilder->UpdateStyleSheet(node);
return rv;
}
case eTreeOpProcessBase: {
nsIContent* node = *(mOne.node);
rv = aBuilder->ProcessBASETag(node);
return rv;
}
case eTreeOpProcessMeta: {
nsIContent* node = *(mOne.node);
rv = aBuilder->ProcessMETATag(node);

View File

@ -74,7 +74,6 @@ enum eHtml5TreeOperation {
eTreeOpSetDocumentCharset,
eTreeOpNeedsCharsetSwitchTo,
eTreeOpUpdateStyleSheet,
eTreeOpProcessBase,
eTreeOpProcessMeta,
eTreeOpProcessOfflineManifest,
eTreeOpMarkMalformedIfScript,