Bug 312592: Reduce amount of duplicated code in html contentsink.

r=mrbkap sr=peterv
This commit is contained in:
cvshook@sicking.cc
2005-11-10 15:51:10 +00:00
parent e7247d7356
commit 3a1f3e0e4b
4 changed files with 99 additions and 240 deletions

View File

@@ -71,6 +71,8 @@ class nsContentSink : public nsICSSLoaderObserver,
NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet* aSheet, PRBool aWasAlternate,
nsresult aStatus);
nsresult ProcessMETATag(nsIContent* aContent);
protected:
nsContentSink();
virtual ~nsContentSink();
@@ -94,8 +96,6 @@ protected:
const nsSubstring& aType,
const nsSubstring& aMedia);
nsresult ProcessMETATag(nsIContent* aContent);
void PrefetchHref(const nsAString &aHref, PRBool aExplicit);
PRBool ScrollToRef(PRBool aReallyScroll);

View File

@@ -335,7 +335,6 @@ protected:
nsString mTitleString;
PRInt32 mInNotification;
nsRefPtr<nsGenericHTMLElement> mCurrentForm;
nsCOMPtr<nsIContent> mCurrentMap;
nsAutoVoidArray mContextStack;
SinkContext* mCurrentContext;
@@ -386,9 +385,6 @@ protected:
*/
void AddBaseTagInfo(nsIContent* aContent);
void ProcessBaseHref(const nsAString& aBaseHref);
void ProcessBaseTarget(const nsAString& aBaseTarget);
// Routines for tags that require special handling
nsresult CloseHTML();
nsresult OpenFrameset(const nsIParserNode& aNode);
@@ -397,10 +393,8 @@ protected:
nsresult CloseBody();
nsresult OpenForm(const nsIParserNode& aNode);
nsresult CloseForm();
nsresult ProcessAREATag(const nsIParserNode& aNode);
nsresult ProcessBASETag(const nsIParserNode& aNode);
void ProcessBASEElement(nsGenericHTMLElement* aElement);
nsresult ProcessLINKTag(const nsIParserNode& aNode);
nsresult ProcessMETATag(const nsIParserNode& aNode);
// Routines for tags that require special handling when we reach their end
// tag.
@@ -1246,13 +1240,6 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
mSink->mInsideNoXXXTag++;
break;
case eHTMLTag_map:
// We used to strip whitespace from the NAME attribute, to match
// a 4.x quirk, but it proved too quirky for us, and IE never
// did that. See bug 79738 for details.
mSink->mCurrentMap = content;
break;
case eHTMLTag_iframe:
mSink->mNumOpenIFRAMES++;
break;
@@ -1381,11 +1368,6 @@ SinkContext::CloseContainer(const nsHTMLTag aTag)
break;
case eHTMLTag_map:
mSink->mCurrentMap = nsnull;
break;
case eHTMLTag_select:
case eHTMLTag_textarea:
case eHTMLTag_object:
@@ -1451,7 +1433,8 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
// this for elements that have useful URI attributes.
// See bug 18478 and bug 30617 for why we need to do this.
switch (nodeType) {
// leaves with 'SRC='
case eHTMLTag_area:
case eHTMLTag_meta:
case eHTMLTag_img:
case eHTMLTag_frame:
case eHTMLTag_input:
@@ -1476,8 +1459,23 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
// Add new leaf to its parent
AddLeaf(content);
// Notify input and button that they are now fully created
// 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.
// Bug 40072: Don't evaluate METAs after FRAMESET.
if (!mSink->mInsideNoXXXTag && !mSink->mFrameset) {
rv = mSink->ProcessMETATag(content);
}
break;
case eHTMLTag_input:
case eHTMLTag_button:
content->DoneCreatingElement();
@@ -2941,24 +2939,10 @@ HTMLContentSink::AddLeaf(const nsIParserNode& aNode)
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
switch (nodeType) {
case eHTMLTag_area:
rv = ProcessAREATag(aNode);
break;
case eHTMLTag_base:
mCurrentContext->FlushTextAndRelease();
rv = ProcessBASETag(aNode);
break;
case eHTMLTag_link:
mCurrentContext->FlushTextAndRelease();
rv = ProcessLINKTag(aNode);
break;
case eHTMLTag_meta:
mCurrentContext->FlushTextAndRelease();
rv = ProcessMETATag(aNode);
break;
default:
rv = mCurrentContext->AddLeaf(aNode);
@@ -3496,71 +3480,6 @@ HTMLContentSink::AddBaseTagInfo(nsIContent* aContent)
}
}
nsresult
HTMLContentSink::ProcessAREATag(const nsIParserNode& aNode)
{
if (!mCurrentMap) {
return NS_OK;
}
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
nsRefPtr<nsGenericHTMLElement> area =
CreateContentObject(aNode, nodeType, nsnull, nsnull);
if (!area) {
return 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.
AddBaseTagInfo(area);
// Set the content's attributes
nsresult rv = AddAttributes(aNode, area);
NS_ENSURE_SUCCESS(rv, rv);
// Add AREA object to the current map
mCurrentMap->AppendChildTo(area, PR_FALSE);
return NS_OK;
}
void
HTMLContentSink::ProcessBaseHref(const nsAString& aBaseHref)
{
//-- Make sure this page is allowed to load this URI
nsresult rv;
nsCOMPtr<nsIURI> baseHrefURI;
rv = NS_NewURI(getter_AddRefs(baseHrefURI), aBaseHref, 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
rv = mDocument->SetBaseURI(baseHrefURI);
if (NS_SUCCEEDED(rv)) {
mDocumentBaseURI = mDocument->GetBaseURI();
}
} else {
// NAV compatibility quirk
nsIScriptSecurityManager *securityManager =
nsContentUtils::GetSecurityManager();
rv = securityManager->
CheckLoadURIWithPrincipal(mDocument->GetPrincipal(), baseHrefURI,
nsIScriptSecurityManager::STANDARD);
if (NS_FAILED(rv)) {
return;
}
mBaseHREF = aBaseHref;
}
}
nsresult
HTMLContentSink::OpenHeadContext()
{
@@ -3605,59 +3524,51 @@ HTMLContentSink::CloseHeadContext()
}
void
HTMLContentSink::ProcessBaseTarget(const nsAString& aBaseTarget)
HTMLContentSink::ProcessBASEElement(nsGenericHTMLElement* aElement)
{
if (!mBody) {
// still in real HEAD
mDocument->SetBaseTarget(aBaseTarget);
} else {
// NAV compatibility quirk
mBaseTarget = aBaseTarget;
}
}
// href attribute
nsAutoString attrValue;
if (aElement->GetAttr(kNameSpaceID_None, nsHTMLAtoms::href, attrValue)) {
//-- Make sure this page is allowed to load this URI
nsresult rv;
nsCOMPtr<nsIURI> baseHrefURI;
rv = NS_NewURI(getter_AddRefs(baseHrefURI), attrValue, nsnull);
if (NS_FAILED(rv))
return;
nsresult
HTMLContentSink::ProcessBASETag(const nsIParserNode& aNode)
{
nsresult result = NS_OK;
nsGenericHTMLElement* parent = nsnull;
if (mCurrentContext) {
parent = mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mContent;
}
if (parent) {
// Create content object
nsCOMPtr<nsIContent> element;
nsCOMPtr<nsINodeInfo> nodeInfo;
mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::base, nsnull,
kNameSpaceID_None,
getter_AddRefs(nodeInfo));
result = NS_NewHTMLElement(getter_AddRefs(element), nodeInfo);
NS_ENSURE_SUCCESS(result, result);
element->SetContentID(mDocument->GetAndIncrementContentID());
// Add in the attributes and add the base content object to the
// head container.
result = AddAttributes(aNode, element);
NS_ENSURE_SUCCESS(result, result);
parent->AppendChildTo(element, PR_FALSE);
if (!mInsideNoXXXTag) {
nsAutoString value;
if (element->GetAttr(kNameSpaceID_None, nsHTMLAtoms::href, value)) {
ProcessBaseHref(value);
// 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
if (element->GetAttr(kNameSpaceID_None, nsHTMLAtoms::target, value)) {
ProcessBaseTarget(value);
nsIScriptSecurityManager *securityManager =
nsContentUtils::GetSecurityManager();
rv = securityManager->
CheckLoadURIWithPrincipal(mDocument->GetPrincipal(), baseHrefURI,
nsIScriptSecurityManager::STANDARD);
if (NS_SUCCEEDED(rv)) {
mBaseHREF = attrValue;
}
}
}
return result;
// target attribute
if (aElement->GetAttr(kNameSpaceID_None, nsHTMLAtoms::target, attrValue)) {
if (!mBody) {
// still in real HEAD
mDocument->SetBaseTarget(attrValue);
} else {
// NAV compatibility quirk
mBaseTarget = attrValue;
}
}
}
nsresult
@@ -3729,55 +3640,6 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode)
return result;
}
nsresult
HTMLContentSink::ProcessMETATag(const nsIParserNode& aNode)
{
nsGenericHTMLElement* parent = nsnull;
if (mCurrentContext) {
parent = mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mContent;
}
if (!parent) {
return NS_OK;
}
nsresult rv = NS_OK;
// Create content object
nsCOMPtr<nsINodeInfo> nodeInfo;
rv = mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::meta, nsnull,
kNameSpaceID_None,
getter_AddRefs(nodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsGenericHTMLElement> it = NS_NewHTMLMetaElement(nodeInfo);
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
it->SetContentID(mDocument->GetAndIncrementContentID());
// Add in the attributes and add the meta content object to the head
// container.
AddBaseTagInfo(it);
rv = AddAttributes(aNode, it);
if (NS_FAILED(rv)) {
return rv;
}
parent->AppendChildTo(it, PR_FALSE);
// XXX It's just not sufficient to check if the parent is head. Also
// check for the preference.
// Bug 40072: Don't evaluate METAs after FRAMESET.
if (!mInsideNoXXXTag && !mFrameset) {
rv = nsContentSink::ProcessMETATag(it);
}
return rv;
}
#ifdef DEBUG
void
HTMLContentSink::ForceReflow()

View File

@@ -67,6 +67,7 @@
#include "nsIStringBundle.h"
#include "nsIDocument.h"
#include "nsContentUtils.h"
#include "nsHTMLAtoms.h"
static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
@@ -802,25 +803,47 @@ nsImageMap::Init(nsIPresShell* aPresShell, nsIFrame* aImageFrame, nsIDOMHTMLMapE
nsresult
nsImageMap::UpdateAreasForBlock(nsIContent* aParent, PRBool* aFoundAnchor)
nsImageMap::SearchForAreas(nsIContent* aParent, PRBool& aFoundArea,
PRBool& aFoundAnchor)
{
nsresult rv = NS_OK;
PRUint32 i, n = aParent->GetChildCount();
for (i = 0; (i < n) && NS_SUCCEEDED(rv); i++) {
// Look for <area> or <a> elements. We'll use whichever type we find first.
for (i = 0; i < n; i++) {
nsIContent *child = aParent->GetChildAt(i);
nsCOMPtr<nsIDOMHTMLAnchorElement> area = do_QueryInterface(child);
if (area) {
*aFoundAnchor = PR_TRUE;
rv = AddArea(child);
if (child->IsContentOfType(nsIContent::eHTML)) {
// If we haven't determined that the map element contains an
// <a> element yet, then look for <area>.
if (!aFoundAnchor && child->Tag() == nsHTMLAtoms::area) {
aFoundArea = PR_TRUE;
rv = AddArea(child);
NS_ENSURE_SUCCESS(rv, rv);
// Continue to next child. This stops mContainsBlockContents from
// getting set. It also makes us ignore children of <area>s which
// is consistent with how we react to dynamic insertion of such
// children.
continue;
}
// If we haven't determined that the map element contains an
// <area> element yet, then look for <a>.
if (!aFoundArea && child->Tag() == nsHTMLAtoms::a) {
aFoundAnchor = PR_TRUE;
rv = AddArea(child);
NS_ENSURE_SUCCESS(rv, rv);
}
}
else {
rv = UpdateAreasForBlock(child, aFoundAnchor);
if (child->IsContentOfType(nsIContent::eELEMENT)) {
mContainsBlockContents = PR_TRUE;
rv = SearchForAreas(child, aFoundArea, aFoundAnchor);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return rv;
return NS_OK;
}
nsresult
@@ -829,38 +852,11 @@ nsImageMap::UpdateAreas()
// Get rid of old area data
FreeAreas();
PRUint32 i, n = mMap->GetChildCount();
PRBool containsBlock = PR_FALSE, containsArea = PR_FALSE;
PRBool foundArea = PR_FALSE;
PRBool foundAnchor = PR_FALSE;
mContainsBlockContents = PR_FALSE;
for (i = 0; i < n; i++) {
nsIContent *child = mMap->GetChildAt(i);
// Only look at elements and not text, comments, etc.
if (!child->IsContentOfType(nsIContent::eHTML))
continue;
// First check if this map element contains an AREA element.
// If so, we only look for AREA elements
if (!containsBlock) {
nsCOMPtr<nsIDOMHTMLAreaElement> area = do_QueryInterface(child);
if (area) {
containsArea = PR_TRUE;
AddArea(child);
}
}
// If we haven't determined that the map element contains an
// AREA element yet, the look for a block element with children
// that are anchors.
if (!containsArea) {
UpdateAreasForBlock(child, &containsBlock);
if (containsBlock)
mContainsBlockContents = PR_TRUE;
}
}
return NS_OK;
return SearchForAreas(mMap, foundArea, foundAnchor);
}
nsresult
@@ -979,9 +975,9 @@ nsImageMap::AttributeChanged(nsIDocument* aDocument,
// the map. But only do this if the node is an HTML <area> or <a>
// and the attribute that's changing is "shape" or "coords" -- those
// are the only cases we care about.
if (aContent->IsContentOfType(nsIContent::eHTML) &&
(aContent->NodeInfo()->Equals(nsHTMLAtoms::area) ||
if ((aContent->NodeInfo()->Equals(nsHTMLAtoms::area) ||
aContent->NodeInfo()->Equals(nsHTMLAtoms::a)) &&
aContent->IsContentOfType(nsIContent::eHTML) &&
aNameSpaceID == kNameSpaceID_None &&
(aAttribute == nsHTMLAtoms::shape ||
aAttribute == nsHTMLAtoms::coords)) {

View File

@@ -114,7 +114,8 @@ protected:
void FreeAreas();
nsresult UpdateAreas();
nsresult UpdateAreasForBlock(nsIContent* aParent, PRBool* aFoundAnchor);
nsresult SearchForAreas(nsIContent* aParent, PRBool& aFoundArea,
PRBool& aFoundAnchor);
nsresult AddArea(nsIContent* aArea);