Improve performance of testing for visited links CSS selector matching by reducing string conversion and by caching the state of the link on the link element. r=waterson b=25963

This commit is contained in:
dbaron%fas.harvard.edu 2000-07-27 23:17:53 +00:00
Родитель 8f5f2da417
Коммит a394eeee27
20 изменённых файлов: 1125 добавлений и 903 удалений

Просмотреть файл

@ -27,6 +27,7 @@
#include "nsIDOMEventReceiver.h"
#include "nsIHTMLContent.h"
#include "nsGenericHTMLElement.h"
#include "nsILink.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLIIDs.h"
#include "nsIStyleContext.h"
@ -56,6 +57,7 @@ static NS_DEFINE_IID(kIDOMHTMLAnchorElementIID, NS_IDOMHTMLANCHORELEMENT_IID);
class nsHTMLAnchorElement : public nsIDOMHTMLAnchorElement,
public nsIDOMNSHTMLAnchorElement,
public nsIJSScriptObject,
public nsILink,
public nsIHTMLContent
{
public:
@ -115,6 +117,11 @@ public:
// nsIJSScriptObject
NS_IMPL_IJSSCRIPTOBJECT_USING_GENERIC(mInner)
// nsILink
NS_IMETHOD GetLinkState(nsLinkState &aState);
NS_IMETHOD SetLinkState(nsLinkState aState);
NS_IMETHOD GetHrefCString(char* &aBuf);
// nsIContent
//NS_IMPL_ICONTENT_NO_FOCUS_USING_GENERIC(mInner)
NS_IMPL_ICONTENT_NO_SETPARENT_NO_SETDOCUMENT_NO_FOCUS_USING_GENERIC(mInner)
@ -126,10 +133,8 @@ protected:
nsresult RegUnRegAccessKey(PRBool aDoReg);
nsGenericHTMLContainerElement mInner;
// The "cached" canonical URL that the anchor really points to. This
// value is derived on-demand when someone asks for the ".href"
// property.
char* mCanonicalHref;
// The cached visited state
nsLinkState mLinkState;
};
nsresult
@ -147,19 +152,16 @@ NS_NewHTMLAnchorElement(nsIHTMLContent** aInstancePtrResult,
}
nsHTMLAnchorElement::nsHTMLAnchorElement(nsINodeInfo *aNodeInfo)
: mCanonicalHref(nsnull)
: mLinkState(eLinkState_Unknown)
{
NS_INIT_REFCNT();
mInner.Init(this, aNodeInfo);
nsHTMLUtils::AddRef();
nsHTMLUtils::AddRef(); // for GetHrefCString
}
nsHTMLAnchorElement::~nsHTMLAnchorElement()
{
if (mCanonicalHref)
nsCRT::free(mCanonicalHref);
nsHTMLUtils::Release();
nsHTMLUtils::Release(); // for GetHrefCString
}
NS_IMPL_ADDREF(nsHTMLAnchorElement)
@ -181,6 +183,11 @@ nsHTMLAnchorElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
else if (aIID.Equals(NS_GET_IID(nsILink))) {
*aInstancePtr = (void*)(nsILink*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
@ -415,46 +422,23 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext* aPresContext,
NS_IMETHODIMP
nsHTMLAnchorElement::GetHref(nsString& aValue)
{
// Return the canonical URI that this link refers to.
nsresult rv = NS_OK;
if (! mCanonicalHref) {
// We don't have a cached value: compute it from scratch.
// Get href= attribute (relative URL).
nsAutoString relURLSpec;
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, relURLSpec);
if (relURLSpec.Length()) {
// Get base URL.
nsCOMPtr<nsIURI> baseURL;
mInner.GetBaseURL(*getter_AddRefs(baseURL));
if (baseURL) {
// Get absolute URL.
NS_MakeAbsoluteURIWithCharset(&mCanonicalHref, relURLSpec, mInner.mDocument, baseURL,
nsHTMLUtils::IOService, nsHTMLUtils::CharsetMgr);
}
else {
// Absolute URL is same as relative URL.
mCanonicalHref = relURLSpec.ToNewUTF8String();
}
}
char *buf;
nsresult rv = GetHrefCString(buf);
if (NS_FAILED(rv)) return rv;
if (buf) {
aValue.AssignWithConversion(buf);
nsCRT::free(buf);
}
aValue.AssignWithConversion(mCanonicalHref);
return rv;
// NS_IMPL_STRING_ATTR does nothing where we have (buf == null)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAnchorElement::SetHref(const nsString& aValue)
{
if (mCanonicalHref) {
// Clobber our "cache", so we'll recompute it the next time
// somebody asks for it.
nsCRT::free(mCanonicalHref);
mCanonicalHref = nsnull;
}
// Clobber our "cache", so we'll recompute it the next time
// somebody asks for it.
mLinkState = eLinkState_Unknown;
return mInner.SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, aValue, PR_TRUE);
}
@ -679,3 +663,46 @@ nsHTMLAnchorElement::GetText(nsString& aText)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsHTMLAnchorElement::GetLinkState(nsLinkState &aState)
{
aState = mLinkState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAnchorElement::SetLinkState(nsLinkState aState)
{
mLinkState = aState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAnchorElement::GetHrefCString(char* &aBuf)
{
// Get href= attribute (relative URL).
nsAutoString relURLSpec;
if (NS_CONTENT_ATTR_HAS_VALUE ==
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, relURLSpec)) {
// Get base URL.
nsCOMPtr<nsIURI> baseURL;
mInner.GetBaseURL(*getter_AddRefs(baseURL));
if (baseURL) {
// Get absolute URL.
NS_MakeAbsoluteURIWithCharset(&aBuf, relURLSpec, mInner.mDocument, baseURL,
nsHTMLUtils::IOService, nsHTMLUtils::CharsetMgr);
}
else {
// Absolute URL is same as relative URL.
aBuf = relURLSpec.ToNewUTF8String();
}
}
else {
// Absolute URL is null to say we have no HREF.
aBuf = nsnull;
}
return NS_OK;
}

Просмотреть файл

@ -25,8 +25,8 @@
#include "nsIDOMEventReceiver.h"
#include "nsIHTMLContent.h"
#include "nsGenericHTMLElement.h"
#include "nsILink.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLUtils.h"
#include "nsHTMLIIDs.h"
#include "nsIStyleContext.h"
#include "nsIMutableStyleContext.h"
@ -35,12 +35,14 @@
#include "nsIEventStateManager.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
#include "nsHTMLUtils.h"
static NS_DEFINE_IID(kIDOMHTMLAreaElementIID, NS_IDOMHTMLAREAELEMENT_IID);
class nsHTMLAreaElement : public nsIDOMHTMLAreaElement,
public nsIDOMNSHTMLAreaElement,
public nsIJSScriptObject,
public nsILink,
public nsIHTMLContent
{
public:
@ -89,6 +91,11 @@ public:
// nsIJSScriptObject
NS_IMPL_IJSSCRIPTOBJECT_USING_GENERIC(mInner)
// nsILink
NS_IMETHOD GetLinkState(nsLinkState &aState);
NS_IMETHOD SetLinkState(nsLinkState aState);
NS_IMETHOD GetHrefCString(char* &aBuf);
// nsIContent
NS_IMPL_ICONTENT_NO_FOCUS_USING_GENERIC(mInner)
@ -97,6 +104,9 @@ public:
protected:
nsGenericHTMLLeafElement mInner;
// The cached visited state
nsLinkState mLinkState;
};
nsresult
@ -115,13 +125,16 @@ NS_NewHTMLAreaElement(nsIHTMLContent** aInstancePtrResult,
nsHTMLAreaElement::nsHTMLAreaElement(nsINodeInfo *aNodeInfo)
: mLinkState(eLinkState_Unknown)
{
NS_INIT_REFCNT();
mInner.Init(this, aNodeInfo);
nsHTMLUtils::AddRef(); // for GetHrefCString
}
nsHTMLAreaElement::~nsHTMLAreaElement()
{
nsHTMLUtils::Release(); // for GetHrefCString
}
NS_IMPL_ADDREF(nsHTMLAreaElement)
@ -144,6 +157,11 @@ nsHTMLAreaElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
else if (aIID.Equals(NS_GET_IID(nsILink))) {
*aInstancePtr = (void*)(nsILink*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
@ -257,42 +275,28 @@ nsHTMLAreaElement::RemoveFocus(nsIPresContext* aPresContext)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaElement::GetHref(nsString& aValue)
{
// Return the canonical URI that this link refers to.
nsresult rv = NS_OK;
// Get href= attribute (relative URL).
nsAutoString relURLSpec;
mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, relURLSpec);
if (relURLSpec.Length()) {
// Get base URL.
nsCOMPtr<nsIURI> baseURL;
mInner.GetBaseURL(*getter_AddRefs(baseURL));
if (baseURL) {
// Get absolute URL.
nsXPIDLCString absURI;
NS_MakeAbsoluteURIWithCharset(getter_Copies(absURI), relURLSpec, mInner.mDocument, baseURL,
nsHTMLUtils::IOService, nsHTMLUtils::CharsetMgr);
aValue.AssignWithConversion(absURI);
}
else {
// Absolute URL is same as relative URL.
aValue = relURLSpec;
}
char *buf;
nsresult rv = GetHrefCString(buf);
if (NS_FAILED(rv)) return rv;
if (buf) {
aValue.AssignWithConversion(buf);
nsCRT::free(buf);
}
return rv;
// NS_IMPL_STRING_ATTR does nothing where we have (buf == null)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaElement::SetHref(const nsString& aValue)
{
return mInner.SetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, aValue, PR_TRUE);
// Clobber our "cache", so we'll recompute it the next time
// somebody asks for it.
mLinkState = eLinkState_Unknown;
return mInner.SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, aValue, PR_TRUE);
}
NS_IMETHODIMP
@ -498,3 +502,47 @@ nsHTMLAreaElement::GetHash(nsString& aHash)
return result;
}
NS_IMETHODIMP
nsHTMLAreaElement::GetLinkState(nsLinkState &aState)
{
aState = mLinkState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaElement::SetLinkState(nsLinkState aState)
{
mLinkState = aState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaElement::GetHrefCString(char* &aBuf)
{
// Get href= attribute (relative URL).
nsAutoString relURLSpec;
if (NS_CONTENT_ATTR_HAS_VALUE ==
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, relURLSpec)) {
// Get base URL.
nsCOMPtr<nsIURI> baseURL;
mInner.GetBaseURL(*getter_AddRefs(baseURL));
if (baseURL) {
// Get absolute URL.
NS_MakeAbsoluteURIWithCharset(&aBuf, relURLSpec, mInner.mDocument, baseURL,
nsHTMLUtils::IOService, nsHTMLUtils::CharsetMgr);
}
else {
// Absolute URL is same as relative URL.
aBuf = relURLSpec.ToNewUTF8String();
}
}
else {
// Absolute URL is empty because we have no HREF.
aBuf = PL_strdup(""); // use a dummy empty string
}
return NS_OK;
}

Просмотреть файл

@ -24,6 +24,7 @@
#include "nsIDOMEventReceiver.h"
#include "nsIHTMLContent.h"
#include "nsGenericHTMLElement.h"
#include "nsILink.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLIIDs.h"
#include "nsIStyleContext.h"
@ -33,6 +34,8 @@
#include "nsIDOMStyleSheet.h"
#include "nsIStyleSheet.h"
#include "nsIStyleSheetLinkingElement.h"
#include "nsHTMLUtils.h"
#include "nsIURL.h"
static NS_DEFINE_IID(kIDOMHTMLLinkElementIID, NS_IDOMHTMLLINKELEMENT_IID);
static NS_DEFINE_IID(kIStyleSheetLinkingElementIID, NS_ISTYLESHEETLINKINGELEMENT_IID);
@ -40,6 +43,7 @@ static NS_DEFINE_IID(kIDOMStyleSheetIID, NS_IDOMSTYLESHEET_IID);
class nsHTMLLinkElement : public nsIDOMHTMLLinkElement,
public nsIJSScriptObject,
public nsILink,
public nsIHTMLContent,
public nsIStyleSheetLinkingElement
{
@ -82,6 +86,11 @@ public:
// nsIJSScriptObject
NS_IMPL_IJSSCRIPTOBJECT_USING_GENERIC(mInner)
// nsILink
NS_IMETHOD GetLinkState(nsLinkState &aState);
NS_IMETHOD SetLinkState(nsLinkState aState);
NS_IMETHOD GetHrefCString(char* &aBuf);
// nsIContent
NS_IMPL_ICONTENT_USING_GENERIC(mInner)
@ -95,6 +104,9 @@ public:
protected:
nsGenericHTMLLeafElement mInner;
nsIStyleSheet* mStyleSheet;
// The cached visited state
nsLinkState mLinkState;
};
nsresult
@ -113,15 +125,18 @@ NS_NewHTMLLinkElement(nsIHTMLContent** aInstancePtrResult,
nsHTMLLinkElement::nsHTMLLinkElement(nsINodeInfo *aNodeInfo)
: mLinkState(eLinkState_Unknown)
{
NS_INIT_REFCNT();
mInner.Init(this, aNodeInfo);
mStyleSheet = nsnull;
nsHTMLUtils::AddRef(); // for GetHrefCString
}
nsHTMLLinkElement::~nsHTMLLinkElement()
{
NS_IF_RELEASE(mStyleSheet);
nsHTMLUtils::Release(); // for GetHrefCString
}
NS_IMPL_ADDREF(nsHTMLLinkElement)
@ -144,6 +159,11 @@ nsHTMLLinkElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsILink))) {
*aInstancePtr = (void*)(nsILink*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
@ -198,7 +218,6 @@ nsHTMLLinkElement::SetDisabled(PRBool aDisabled)
}
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Charset, charset)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Href, href)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Hreflang, hreflang)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Media, media)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rel, rel)
@ -206,6 +225,30 @@ NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rev, rev)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Target, target)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Type, type)
NS_IMETHODIMP
nsHTMLLinkElement::GetHref(nsString& aValue)
{
char *buf;
nsresult rv = GetHrefCString(buf);
if (NS_FAILED(rv)) return rv;
if (buf) {
aValue.AssignWithConversion(buf);
nsCRT::free(buf);
}
// NS_IMPL_STRING_ATTR does nothing where we have (buf == null)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkElement::SetHref(const nsString& aValue)
{
// Clobber our "cache", so we'll recompute it the next time
// somebody asks for it.
mLinkState = eLinkState_Unknown;
return mInner.SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, aValue, PR_TRUE);
}
NS_IMETHODIMP
nsHTMLLinkElement::SetStyleSheet(nsIStyleSheet* aStyleSheet)
{
@ -289,3 +332,47 @@ nsHTMLLinkElement::SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const
{
return mInner.SizeOf(aSizer, aResult, sizeof(*this));
}
NS_IMETHODIMP
nsHTMLLinkElement::GetLinkState(nsLinkState &aState)
{
aState = mLinkState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkElement::SetLinkState(nsLinkState aState)
{
mLinkState = aState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkElement::GetHrefCString(char* &aBuf)
{
// Get href= attribute (relative URL).
nsAutoString relURLSpec;
if (NS_CONTENT_ATTR_HAS_VALUE ==
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, relURLSpec)) {
// Get base URL.
nsCOMPtr<nsIURI> baseURL;
mInner.GetBaseURL(*getter_AddRefs(baseURL));
if (baseURL) {
// Get absolute URL.
NS_MakeAbsoluteURIWithCharset(&aBuf, relURLSpec, mInner.mDocument, baseURL,
nsHTMLUtils::IOService, nsHTMLUtils::CharsetMgr);
}
else {
// Absolute URL is same as relative URL.
aBuf = relURLSpec.ToNewUTF8String();
}
}
else {
// Absolute URL is empty because we have no HREF.
aBuf = PL_strdup(""); // use a dummy empty string
}
return NS_OK;
}

Просмотреть файл

@ -27,11 +27,7 @@
#include "nsCRT.h"
#include "nsIAtom.h"
#include "nsIURL.h"
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsISupportsArray.h"
#include "nsHashtable.h"
#include "nsICSSStyleRuleProcessor.h"
@ -41,7 +37,6 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsIHTMLContent.h"
#include "nsIDocument.h"
#include "nsIPresContext.h"
#include "nsILinkHandler.h"
#include "nsIEventStateManager.h"
#include "nsHTMLAtoms.h"
#include "nsLayoutAtoms.h"
@ -67,10 +62,10 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsINameSpace.h"
#include "nsITextContent.h"
#include "prlog.h"
#include "nsIXMLContent.h"
#include "nsCOMPtr.h"
#include "nsIStyleSet.h"
#include "nsISizeOfHandler.h"
#include "nsStyleUtil.h"
//#define DEBUG_RULES
//#define EVENT_DEBUG
@ -83,9 +78,6 @@ static NS_DEFINE_IID(kIDOMCSSStyleSheetIID, NS_IDOMCSSSTYLESHEET_IID);
static NS_DEFINE_IID(kIDOMCSSStyleRuleIID, NS_IDOMCSSSTYLERULE_IID);
static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID);
static PRBool IsValidLink(nsIContent *aContent,nsString &aHREF);
static PRBool IsSimpleXlink(nsIContent *aContent, nsString &aHREF);
// ----------------------
// Rule hash key
//
@ -458,9 +450,6 @@ public:
nsINameSpace* mNameSpace;
PRInt32 mDefaultNameSpaceID;
nsHashtable mRelevantAttributes;
static nsIIOService* gIOService;
static nsrefcnt gRefcnt;
};
@ -1090,9 +1079,6 @@ static PRBool SetStyleSheetReference(nsISupports* aElement, void* aSheet)
return PR_TRUE;
}
nsIIOService* CSSStyleSheetInner::gIOService = nsnull;
nsrefcnt CSSStyleSheetInner::gRefcnt = 0;
CSSStyleSheetInner::CSSStyleSheetInner(nsICSSStyleSheet* aParentSheet)
: mSheets(),
mURL(nsnull),
@ -1102,13 +1088,6 @@ CSSStyleSheetInner::CSSStyleSheetInner(nsICSSStyleSheet* aParentSheet)
mRelevantAttributes()
{
MOZ_COUNT_CTOR(CSSStyleSheetInner);
if (gRefcnt++ == 0) {
nsresult rv;
rv = nsServiceManager::GetService(kIOServiceCID,
NS_GET_IID(nsIIOService),
(nsISupports**)&gIOService);
NS_ASSERTION(NS_SUCCEEDED(rv), "can't get nsIOService");
}
mSheets.AppendElement(aParentSheet);
}
@ -1146,13 +1125,6 @@ CSSStyleSheetInner::CSSStyleSheetInner(CSSStyleSheetInner& aCopy,
mRelevantAttributes()
{
MOZ_COUNT_CTOR(CSSStyleSheetInner);
if (gRefcnt++ == 0) {
nsresult rv;
rv = nsServiceManager::GetService(kIOServiceCID,
NS_GET_IID(nsIIOService),
(nsISupports**)&gIOService);
NS_ASSERTION(NS_SUCCEEDED(rv), "can't get nsIOService");
}
mSheets.AppendElement(aParentSheet);
NS_IF_ADDREF(mURL);
if (aCopy.mOrderedRules) {
@ -1179,12 +1151,6 @@ CSSStyleSheetInner::~CSSStyleSheetInner(void)
NS_RELEASE(mOrderedRules);
}
NS_IF_RELEASE(mNameSpace);
if (--gRefcnt == 0) {
nsresult rv;
rv = nsServiceManager::ReleaseService(kIOServiceCID, gIOService);
NS_ASSERTION(NS_SUCCEEDED(rv), "can't release nsIOService");
gIOService = nsnull;
}
}
CSSStyleSheetInner*
@ -2831,8 +2797,6 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
PRBool aTestState)
{
PRBool result = PR_FALSE;
PRBool tagset = PR_FALSE;
nsIAtom* contentTag = NULL; // Make sure this is NULL for NS_IF_RELEASE
// Bail out early if we can
if(kNameSpaceID_Unknown != aSelector->mNameSpace) {
@ -2843,10 +2807,11 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
}
}
nsCOMPtr<nsIAtom> contentTag;
if (((nsnull == aSelector->mTag) || (
aContent->GetTag(contentTag),
tagset=PR_TRUE,
aSelector->mTag == contentTag))) {
aContent->GetTag(*getter_AddRefs(contentTag)),
aSelector->mTag == contentTag.get()))) {
result = PR_TRUE;
// namespace/tag match
@ -2916,7 +2881,6 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
nsAtomList* pseudoClass = aSelector->mPseudoClassList;
PRInt32 eventState = NS_EVENT_STATE_UNSPECIFIED;
nsLinkState linkState = nsLinkState(-1); // not a link
nsILinkHandler* linkHandler = nsnull;
nsIEventStateManager* eventStateManager = nsnull;
while ((PR_TRUE == result) && (nsnull != pseudoClass)) {
@ -3008,9 +2972,7 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
else if (IsEventPseudo(pseudoClass->mAtom)) {
// check if the element is event-sensitive
if (!contentTag) {
if (aContent) {
aContent->GetTag(contentTag);
}
aContent->GetTag(*getter_AddRefs(contentTag));
}
#ifdef EVENT_DEBUG
@ -3041,7 +3003,7 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
nsAutoString strPseudo, strTag;
pseudoClass->mAtom->ToString(strPseudo);
if (!contentTag) {
if (aContent) aContent->GetTag(contentTag);
aContent->GetTag(*getter_AddRefs(contentTag));
}
if (contentTag) {
contentTag->ToString(strTag);
@ -3065,26 +3027,10 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
}
}
else if (IsLinkPseudo(pseudoClass->mAtom)) {
if(!tagset) {
tagset=PR_TRUE;
aContent->GetTag(contentTag);
}
nsAutoString href;
if (IsValidLink(aContent,href)) {
// Now 'href' will contain a canonical URI that we can
// look up in global history.
if (!contentTag) aContent->GetTag(*getter_AddRefs(contentTag));
if (nsStyleUtil::IsHTMLLink(aContent, contentTag, aPresContext, &linkState) ||
nsStyleUtil::IsSimpleXlink(aContent, aPresContext, &linkState)) {
if ((PR_FALSE != result) && (aTestState)) {
if (! linkHandler) {
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(href, linkState);
}
else {
// no link handler? then all links are unvisited
linkState = eLinkState_Unvisited;
}
}
if (nsCSSAtoms::linkPseudo == pseudoClass->mAtom) {
result = PRBool(eLinkState_Unvisited == linkState);
}
@ -3106,11 +3052,9 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
pseudoClass = pseudoClass->mNext;
}
NS_IF_RELEASE(linkHandler);
NS_IF_RELEASE(eventStateManager);
}
}
NS_IF_RELEASE(contentTag);
return result;
}
@ -3769,105 +3713,3 @@ CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium)
}
return cascade;
}
/*static*/
PRBool IsValidLink(nsIContent *aContent,nsString &aHREF)
{
NS_ASSERTION(aContent, "null arg in IsValidLink");
// check for:
// - HTML ANCHOR with valid HREF
// - HTML LINK with valid HREF
// - HTML AREA with valid HREF
// - Simple XLink
// if the content is a valid link, set the href to the canonicalized form and return TRUE
PRBool result = PR_FALSE;
PRBool bIsXLink = PR_FALSE;
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor;
nsCOMPtr<nsIDOMHTMLAreaElement> area;
nsCOMPtr<nsIDOMHTMLLinkElement> link;
if ((anchor = do_QueryInterface(aContent)) ||
(area = do_QueryInterface(aContent)) ||
(link = do_QueryInterface(aContent))) {
// if it is an anchor, area or link then check the href attribute
nsresult attrState = 0;
// make sure this anchor has a link even if we are not testing state
// if there is no link, then this anchor is not really a linkpseudo.
// bug=23209
attrState = aContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, aHREF);
if (NS_CONTENT_ATTR_HAS_VALUE != attrState) {
result = PR_FALSE;
}
else {
if (anchor) {
anchor->GetHref(aHREF);
result = PR_TRUE;
}
else if (area) {
area->GetHref(aHREF);
result = PR_TRUE;
}
else if (link) {
link->GetHref(aHREF);
result = PR_TRUE;
}
}
} // if anchor, area, link
else if ((bIsXLink = IsSimpleXlink(aContent,aHREF))) {
// It's an XLink. Resolve it relative to its document.
nsCOMPtr<nsIURI> baseURI = nsnull;
nsCOMPtr<nsIHTMLContent> htmlContent = do_QueryInterface(aContent);
if (htmlContent) {
// XXX why do this? will nsIHTMLContent's
// GetBaseURL() may return something different
// than the URL of the document it lives in?
htmlContent->GetBaseURL(*getter_AddRefs(baseURI));
}
else {
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (doc) {
doc->GetBaseURL(*getter_AddRefs(baseURI));
}
}
nsAutoString linkURI;
(void) NS_MakeAbsoluteURI(linkURI, aHREF, baseURI, CSSStyleSheetInner::gIOService);
aHREF = linkURI;
result = PR_TRUE;
} // if xlink
return result;
}
/*static*/
PRBool IsSimpleXlink(nsIContent *aContent, nsString &aHREF)
{
NS_ASSERTION(aContent, "invalid call to IsXlink with null content");
PRBool rv = PR_FALSE;
// set the out-param to default / empty
aHREF.Truncate(0);
if (aContent) {
// first see if we have an XML element
nsCOMPtr<nsIXMLContent> xml(do_QueryInterface(aContent));
if (xml) {
// see if it is type=simple (we don't deal with other types)
nsAutoString val;
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::type, val);
if (val == NS_LITERAL_STRING("simple")) {
// see if there is an xlink namespace'd href attribute:
// - get it if there is, if not no big deal, it is not required for xlinks
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::href, aHREF);
rv = PR_TRUE;
}
}
}
return rv;
}

Просмотреть файл

@ -33,15 +33,13 @@
#include "nsCRT.h"
#include "nsIAtom.h"
#include "nsIURL.h"
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsISupportsArray.h"
#include "nsHashtable.h"
#include "nsIHTMLContent.h"
#include "nsIHTMLAttributes.h"
#include "nsILink.h"
#include "nsStyleUtil.h"
#include "nsIStyleRuleProcessor.h"
#include "nsIStyleRule.h"
#include "nsIFrame.h"
@ -49,7 +47,6 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsIMutableStyleContext.h"
#include "nsHTMLAtoms.h"
#include "nsIPresContext.h"
#include "nsILinkHandler.h"
#include "nsIEventStateManager.h"
#include "nsIDocument.h"
#include "nsHTMLIIDs.h"
@ -850,69 +847,40 @@ HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
styledContent->GetTag(tag);
// if we have anchor colors, check if this is an anchor with an href
if (tag == nsHTMLAtoms::a) {
if ((nsnull != mLinkRule) || (nsnull != mVisitedRule)) {
// test link state
nsILinkHandler* linkHandler;
if (NS_OK == aPresContext->GetLinkHandler(&linkHandler)) {
nsAutoString base, href;
nsresult attrState = styledContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, href);
if (NS_CONTENT_ATTR_HAS_VALUE == attrState) {
if (! linkHandler) {
if (mLinkRule || mVisitedRule || mActiveRule) {
nsLinkState state;
if (nsStyleUtil::IsHTMLLink(aContent, tag, aPresContext, &state)) {
switch (state) {
case eLinkState_Unvisited:
if (nsnull != mLinkRule) {
aResults->AppendElement(mLinkRule);
}
}
else {
nsIHTMLContent* htmlContent;
if (NS_SUCCEEDED(styledContent->QueryInterface(kIHTMLContentIID, (void**)&htmlContent))) {
nsCOMPtr<nsIURI> baseURI;
htmlContent->GetBaseURL(*getter_AddRefs(baseURI));
nsAutoString linkURI;
(void) NS_MakeAbsoluteURI(linkURI, href, baseURI);
nsLinkState state;
if (NS_OK == linkHandler->GetLinkState(linkURI, state)) {
switch (state) {
case eLinkState_Unvisited:
if (nsnull != mLinkRule) {
aResults->AppendElement(mLinkRule);
}
break;
case eLinkState_Visited:
if (nsnull != mVisitedRule) {
aResults->AppendElement(mVisitedRule);
}
break;
default:
break;
}
}
NS_RELEASE(htmlContent);
break;
case eLinkState_Visited:
if (nsnull != mVisitedRule) {
aResults->AppendElement(mVisitedRule);
}
}
break;
default:
break;
}
}
NS_IF_RELEASE(linkHandler);
} // end link/visited rules
if (nsnull != mActiveRule) { // test active state of link
nsIEventStateManager* eventStateManager;
// No need to add to the active rule if it's not a link
if (mActiveRule) { // test active state of link
nsIEventStateManager* eventStateManager;
if ((NS_OK == aPresContext->GetEventStateManager(&eventStateManager)) &&
(nsnull != eventStateManager)) {
PRInt32 state;
if (NS_OK == eventStateManager->GetContentState(aContent, state)) {
if (0 != (state & NS_EVENT_STATE_ACTIVE)) {
aResults->AppendElement(mActiveRule);
if ((NS_OK == aPresContext->GetEventStateManager(&eventStateManager)) &&
(nsnull != eventStateManager)) {
PRInt32 state;
if (NS_OK == eventStateManager->GetContentState(aContent, state)) {
if (0 != (state & NS_EVENT_STATE_ACTIVE)) {
aResults->AppendElement(mActiveRule);
}
}
NS_RELEASE(eventStateManager);
}
}
NS_RELEASE(eventStateManager);
} // end active rule
}
} // end active rule
} // end link/visited/active rules
} // end A tag
// add the quirks background compatibility rule if in quirks mode
// and/or the Table TH rule for handling <TH> differently than <TD>

Просмотреть файл

@ -28,6 +28,16 @@
#include "nsStyleConsts.h"
#include "nsUnitConversion.h"
#include "nsHTMLAtoms.h"
#include "nsILinkHandler.h"
#include "nsILink.h"
#include "nsIXMLContent.h"
#include "nsIHTMLContent.h"
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsIServiceManager.h"
#include "nsIPref.h"
@ -476,6 +486,129 @@ const nsStyleColor* nsStyleUtil::FindNonTransparentBackground(nsIStyleContext* a
return result;
}
/*static*/
PRBool nsStyleUtil::IsHTMLLink(nsIContent *aContent, nsIAtom *aTag, nsIPresContext *aPresContext, nsLinkState *aState)
{
NS_ASSERTION(aContent && aState, "null arg in IsHTMLLink");
// check for:
// - HTML ANCHOR with valid HREF
// - HTML LINK with valid HREF
// - HTML AREA with valid HREF
PRBool result = PR_FALSE;
if ((aTag == nsHTMLAtoms::a) ||
(aTag == nsHTMLAtoms::link) ||
(aTag == nsHTMLAtoms::area)) {
nsCOMPtr<nsILink> link( do_QueryInterface(aContent) );
// In XML documents, this can be null.
if (link) {
nsLinkState linkState;
link->GetLinkState(linkState);
if (linkState == eLinkState_Unknown) {
// if it is an anchor, area or link then check the href attribute
// make sure this anchor has a link even if we are not testing state
// if there is no link, then this anchor is not really a linkpseudo.
// bug=23209
char* href;
link->GetHrefCString(href);
if (href) {
nsILinkHandler *linkHandler = nsnull;
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(href, linkState);
NS_RELEASE(linkHandler);
}
else {
// no link handler? then all links are unvisited
linkState = eLinkState_Unvisited;
}
nsCRT::free(href);
} else {
linkState = eLinkState_NotLink;
}
link->SetLinkState(linkState);
}
if (linkState != eLinkState_NotLink) {
*aState = linkState;
result = PR_TRUE;
}
}
}
return result;
}
/*static*/
PRBool nsStyleUtil::IsSimpleXlink(nsIContent *aContent, nsIPresContext *aPresContext, nsLinkState *aState)
{
// XXX PERF This function will cause serious performance problems on
// pages with lots of XLinks. We should be caching the visited
// state of the XLinks. Where???
NS_ASSERTION(aContent && aState, "invalid call to IsXlink with null content");
PRBool rv = PR_FALSE;
if (aContent && aState) {
// first see if we have an XML element
nsCOMPtr<nsIXMLContent> xml(do_QueryInterface(aContent));
if (xml) {
// see if it is type=simple (we don't deal with other types)
nsAutoString val;
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::type, val);
if (val == NS_LITERAL_STRING("simple")) {
// see if there is an xlink namespace'd href attribute:
// - get it if there is, if not no big deal, it is not required for xlinks
// is it bad to re-use val here?
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::href, val);
// It's an XLink. Resolve it relative to its document.
nsCOMPtr<nsIURI> baseURI;
nsCOMPtr<nsIHTMLContent> htmlContent = do_QueryInterface(aContent);
if (htmlContent) {
// XXX why do this? will nsIHTMLContent's
// GetBaseURL() may return something different
// than the URL of the document it lives in?
htmlContent->GetBaseURL(*getter_AddRefs(baseURI));
}
else {
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (doc) {
doc->GetBaseURL(*getter_AddRefs(baseURI));
}
}
// convert here, rather than twice in NS_MakeAbsoluteURI and
// back again
char * href = val.ToNewCString();
char * absHREF = nsnull;
(void) NS_MakeAbsoluteURI(&absHREF, href, baseURI);
nsCRT::free(href);
nsILinkHandler *linkHandler = nsnull;
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(absHREF, *aState);
NS_RELEASE(linkHandler);
}
else {
// no link handler? then all links are unvisited
*aState = eLinkState_Unvisited;
}
nsCRT::free(absHREF);
rv = PR_TRUE;
}
}
}
return rv;
}
//------------------------------------------------------------------------------
//

Просмотреть файл

@ -28,6 +28,16 @@
#include "nsStyleConsts.h"
#include "nsUnitConversion.h"
#include "nsHTMLAtoms.h"
#include "nsILinkHandler.h"
#include "nsILink.h"
#include "nsIXMLContent.h"
#include "nsIHTMLContent.h"
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsIServiceManager.h"
#include "nsIPref.h"
@ -476,6 +486,129 @@ const nsStyleColor* nsStyleUtil::FindNonTransparentBackground(nsIStyleContext* a
return result;
}
/*static*/
PRBool nsStyleUtil::IsHTMLLink(nsIContent *aContent, nsIAtom *aTag, nsIPresContext *aPresContext, nsLinkState *aState)
{
NS_ASSERTION(aContent && aState, "null arg in IsHTMLLink");
// check for:
// - HTML ANCHOR with valid HREF
// - HTML LINK with valid HREF
// - HTML AREA with valid HREF
PRBool result = PR_FALSE;
if ((aTag == nsHTMLAtoms::a) ||
(aTag == nsHTMLAtoms::link) ||
(aTag == nsHTMLAtoms::area)) {
nsCOMPtr<nsILink> link( do_QueryInterface(aContent) );
// In XML documents, this can be null.
if (link) {
nsLinkState linkState;
link->GetLinkState(linkState);
if (linkState == eLinkState_Unknown) {
// if it is an anchor, area or link then check the href attribute
// make sure this anchor has a link even if we are not testing state
// if there is no link, then this anchor is not really a linkpseudo.
// bug=23209
char* href;
link->GetHrefCString(href);
if (href) {
nsILinkHandler *linkHandler = nsnull;
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(href, linkState);
NS_RELEASE(linkHandler);
}
else {
// no link handler? then all links are unvisited
linkState = eLinkState_Unvisited;
}
nsCRT::free(href);
} else {
linkState = eLinkState_NotLink;
}
link->SetLinkState(linkState);
}
if (linkState != eLinkState_NotLink) {
*aState = linkState;
result = PR_TRUE;
}
}
}
return result;
}
/*static*/
PRBool nsStyleUtil::IsSimpleXlink(nsIContent *aContent, nsIPresContext *aPresContext, nsLinkState *aState)
{
// XXX PERF This function will cause serious performance problems on
// pages with lots of XLinks. We should be caching the visited
// state of the XLinks. Where???
NS_ASSERTION(aContent && aState, "invalid call to IsXlink with null content");
PRBool rv = PR_FALSE;
if (aContent && aState) {
// first see if we have an XML element
nsCOMPtr<nsIXMLContent> xml(do_QueryInterface(aContent));
if (xml) {
// see if it is type=simple (we don't deal with other types)
nsAutoString val;
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::type, val);
if (val == NS_LITERAL_STRING("simple")) {
// see if there is an xlink namespace'd href attribute:
// - get it if there is, if not no big deal, it is not required for xlinks
// is it bad to re-use val here?
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::href, val);
// It's an XLink. Resolve it relative to its document.
nsCOMPtr<nsIURI> baseURI;
nsCOMPtr<nsIHTMLContent> htmlContent = do_QueryInterface(aContent);
if (htmlContent) {
// XXX why do this? will nsIHTMLContent's
// GetBaseURL() may return something different
// than the URL of the document it lives in?
htmlContent->GetBaseURL(*getter_AddRefs(baseURI));
}
else {
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (doc) {
doc->GetBaseURL(*getter_AddRefs(baseURI));
}
}
// convert here, rather than twice in NS_MakeAbsoluteURI and
// back again
char * href = val.ToNewCString();
char * absHREF = nsnull;
(void) NS_MakeAbsoluteURI(&absHREF, href, baseURI);
nsCRT::free(href);
nsILinkHandler *linkHandler = nsnull;
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(absHREF, *aState);
NS_RELEASE(linkHandler);
}
else {
// no link handler? then all links are unvisited
*aState = eLinkState_Unvisited;
}
nsCRT::free(absHREF);
rv = PR_TRUE;
}
}
}
return rv;
}
//------------------------------------------------------------------------------
//

Просмотреть файл

@ -855,17 +855,14 @@ nsWebShell::OnOverLink(nsIContent* aContent,
}
NS_IMETHODIMP
nsWebShell::GetLinkState(const nsString& aLinkURI, nsLinkState& aState)
nsWebShell::GetLinkState(const char* aLinkURI, nsLinkState& aState)
{
aState = eLinkState_Unvisited;
if(mGlobalHistory)
{
nsCAutoString url;
url.AssignWithConversion(aLinkURI.GetUnicode());
PRInt64 lastVisitDate;
NS_ENSURE_SUCCESS(mGlobalHistory->GetLastVisitDate(url.GetBuffer(),
NS_ENSURE_SUCCESS(mGlobalHistory->GetLastVisitDate(aLinkURI,
&lastVisitDate), NS_ERROR_FAILURE);
// a last-visit-date of zero means we've never seen it before; so

Просмотреть файл

@ -92,7 +92,7 @@ public:
NS_IMETHOD OnOverLink(nsIContent* aContent,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec);
NS_IMETHOD GetLinkState(const nsString& aLinkURI, nsLinkState& aState);
NS_IMETHOD GetLinkState(const char* aLinkURI, nsLinkState& aState);
NS_IMETHOD FindNext(const PRUnichar * aSearchStr, PRBool aMatchCase, PRBool aSearchDown, PRBool &aIsFound);

Просмотреть файл

@ -27,6 +27,7 @@
#include "nsIDOMEventReceiver.h"
#include "nsIHTMLContent.h"
#include "nsGenericHTMLElement.h"
#include "nsILink.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLIIDs.h"
#include "nsIStyleContext.h"
@ -56,6 +57,7 @@ static NS_DEFINE_IID(kIDOMHTMLAnchorElementIID, NS_IDOMHTMLANCHORELEMENT_IID);
class nsHTMLAnchorElement : public nsIDOMHTMLAnchorElement,
public nsIDOMNSHTMLAnchorElement,
public nsIJSScriptObject,
public nsILink,
public nsIHTMLContent
{
public:
@ -115,6 +117,11 @@ public:
// nsIJSScriptObject
NS_IMPL_IJSSCRIPTOBJECT_USING_GENERIC(mInner)
// nsILink
NS_IMETHOD GetLinkState(nsLinkState &aState);
NS_IMETHOD SetLinkState(nsLinkState aState);
NS_IMETHOD GetHrefCString(char* &aBuf);
// nsIContent
//NS_IMPL_ICONTENT_NO_FOCUS_USING_GENERIC(mInner)
NS_IMPL_ICONTENT_NO_SETPARENT_NO_SETDOCUMENT_NO_FOCUS_USING_GENERIC(mInner)
@ -126,10 +133,8 @@ protected:
nsresult RegUnRegAccessKey(PRBool aDoReg);
nsGenericHTMLContainerElement mInner;
// The "cached" canonical URL that the anchor really points to. This
// value is derived on-demand when someone asks for the ".href"
// property.
char* mCanonicalHref;
// The cached visited state
nsLinkState mLinkState;
};
nsresult
@ -147,19 +152,16 @@ NS_NewHTMLAnchorElement(nsIHTMLContent** aInstancePtrResult,
}
nsHTMLAnchorElement::nsHTMLAnchorElement(nsINodeInfo *aNodeInfo)
: mCanonicalHref(nsnull)
: mLinkState(eLinkState_Unknown)
{
NS_INIT_REFCNT();
mInner.Init(this, aNodeInfo);
nsHTMLUtils::AddRef();
nsHTMLUtils::AddRef(); // for GetHrefCString
}
nsHTMLAnchorElement::~nsHTMLAnchorElement()
{
if (mCanonicalHref)
nsCRT::free(mCanonicalHref);
nsHTMLUtils::Release();
nsHTMLUtils::Release(); // for GetHrefCString
}
NS_IMPL_ADDREF(nsHTMLAnchorElement)
@ -181,6 +183,11 @@ nsHTMLAnchorElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
else if (aIID.Equals(NS_GET_IID(nsILink))) {
*aInstancePtr = (void*)(nsILink*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
@ -415,46 +422,23 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext* aPresContext,
NS_IMETHODIMP
nsHTMLAnchorElement::GetHref(nsString& aValue)
{
// Return the canonical URI that this link refers to.
nsresult rv = NS_OK;
if (! mCanonicalHref) {
// We don't have a cached value: compute it from scratch.
// Get href= attribute (relative URL).
nsAutoString relURLSpec;
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, relURLSpec);
if (relURLSpec.Length()) {
// Get base URL.
nsCOMPtr<nsIURI> baseURL;
mInner.GetBaseURL(*getter_AddRefs(baseURL));
if (baseURL) {
// Get absolute URL.
NS_MakeAbsoluteURIWithCharset(&mCanonicalHref, relURLSpec, mInner.mDocument, baseURL,
nsHTMLUtils::IOService, nsHTMLUtils::CharsetMgr);
}
else {
// Absolute URL is same as relative URL.
mCanonicalHref = relURLSpec.ToNewUTF8String();
}
}
char *buf;
nsresult rv = GetHrefCString(buf);
if (NS_FAILED(rv)) return rv;
if (buf) {
aValue.AssignWithConversion(buf);
nsCRT::free(buf);
}
aValue.AssignWithConversion(mCanonicalHref);
return rv;
// NS_IMPL_STRING_ATTR does nothing where we have (buf == null)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAnchorElement::SetHref(const nsString& aValue)
{
if (mCanonicalHref) {
// Clobber our "cache", so we'll recompute it the next time
// somebody asks for it.
nsCRT::free(mCanonicalHref);
mCanonicalHref = nsnull;
}
// Clobber our "cache", so we'll recompute it the next time
// somebody asks for it.
mLinkState = eLinkState_Unknown;
return mInner.SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, aValue, PR_TRUE);
}
@ -679,3 +663,46 @@ nsHTMLAnchorElement::GetText(nsString& aText)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsHTMLAnchorElement::GetLinkState(nsLinkState &aState)
{
aState = mLinkState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAnchorElement::SetLinkState(nsLinkState aState)
{
mLinkState = aState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAnchorElement::GetHrefCString(char* &aBuf)
{
// Get href= attribute (relative URL).
nsAutoString relURLSpec;
if (NS_CONTENT_ATTR_HAS_VALUE ==
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, relURLSpec)) {
// Get base URL.
nsCOMPtr<nsIURI> baseURL;
mInner.GetBaseURL(*getter_AddRefs(baseURL));
if (baseURL) {
// Get absolute URL.
NS_MakeAbsoluteURIWithCharset(&aBuf, relURLSpec, mInner.mDocument, baseURL,
nsHTMLUtils::IOService, nsHTMLUtils::CharsetMgr);
}
else {
// Absolute URL is same as relative URL.
aBuf = relURLSpec.ToNewUTF8String();
}
}
else {
// Absolute URL is null to say we have no HREF.
aBuf = nsnull;
}
return NS_OK;
}

Просмотреть файл

@ -25,8 +25,8 @@
#include "nsIDOMEventReceiver.h"
#include "nsIHTMLContent.h"
#include "nsGenericHTMLElement.h"
#include "nsILink.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLUtils.h"
#include "nsHTMLIIDs.h"
#include "nsIStyleContext.h"
#include "nsIMutableStyleContext.h"
@ -35,12 +35,14 @@
#include "nsIEventStateManager.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
#include "nsHTMLUtils.h"
static NS_DEFINE_IID(kIDOMHTMLAreaElementIID, NS_IDOMHTMLAREAELEMENT_IID);
class nsHTMLAreaElement : public nsIDOMHTMLAreaElement,
public nsIDOMNSHTMLAreaElement,
public nsIJSScriptObject,
public nsILink,
public nsIHTMLContent
{
public:
@ -89,6 +91,11 @@ public:
// nsIJSScriptObject
NS_IMPL_IJSSCRIPTOBJECT_USING_GENERIC(mInner)
// nsILink
NS_IMETHOD GetLinkState(nsLinkState &aState);
NS_IMETHOD SetLinkState(nsLinkState aState);
NS_IMETHOD GetHrefCString(char* &aBuf);
// nsIContent
NS_IMPL_ICONTENT_NO_FOCUS_USING_GENERIC(mInner)
@ -97,6 +104,9 @@ public:
protected:
nsGenericHTMLLeafElement mInner;
// The cached visited state
nsLinkState mLinkState;
};
nsresult
@ -115,13 +125,16 @@ NS_NewHTMLAreaElement(nsIHTMLContent** aInstancePtrResult,
nsHTMLAreaElement::nsHTMLAreaElement(nsINodeInfo *aNodeInfo)
: mLinkState(eLinkState_Unknown)
{
NS_INIT_REFCNT();
mInner.Init(this, aNodeInfo);
nsHTMLUtils::AddRef(); // for GetHrefCString
}
nsHTMLAreaElement::~nsHTMLAreaElement()
{
nsHTMLUtils::Release(); // for GetHrefCString
}
NS_IMPL_ADDREF(nsHTMLAreaElement)
@ -144,6 +157,11 @@ nsHTMLAreaElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
else if (aIID.Equals(NS_GET_IID(nsILink))) {
*aInstancePtr = (void*)(nsILink*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
@ -257,42 +275,28 @@ nsHTMLAreaElement::RemoveFocus(nsIPresContext* aPresContext)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaElement::GetHref(nsString& aValue)
{
// Return the canonical URI that this link refers to.
nsresult rv = NS_OK;
// Get href= attribute (relative URL).
nsAutoString relURLSpec;
mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, relURLSpec);
if (relURLSpec.Length()) {
// Get base URL.
nsCOMPtr<nsIURI> baseURL;
mInner.GetBaseURL(*getter_AddRefs(baseURL));
if (baseURL) {
// Get absolute URL.
nsXPIDLCString absURI;
NS_MakeAbsoluteURIWithCharset(getter_Copies(absURI), relURLSpec, mInner.mDocument, baseURL,
nsHTMLUtils::IOService, nsHTMLUtils::CharsetMgr);
aValue.AssignWithConversion(absURI);
}
else {
// Absolute URL is same as relative URL.
aValue = relURLSpec;
}
char *buf;
nsresult rv = GetHrefCString(buf);
if (NS_FAILED(rv)) return rv;
if (buf) {
aValue.AssignWithConversion(buf);
nsCRT::free(buf);
}
return rv;
// NS_IMPL_STRING_ATTR does nothing where we have (buf == null)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaElement::SetHref(const nsString& aValue)
{
return mInner.SetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, aValue, PR_TRUE);
// Clobber our "cache", so we'll recompute it the next time
// somebody asks for it.
mLinkState = eLinkState_Unknown;
return mInner.SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, aValue, PR_TRUE);
}
NS_IMETHODIMP
@ -498,3 +502,47 @@ nsHTMLAreaElement::GetHash(nsString& aHash)
return result;
}
NS_IMETHODIMP
nsHTMLAreaElement::GetLinkState(nsLinkState &aState)
{
aState = mLinkState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaElement::SetLinkState(nsLinkState aState)
{
mLinkState = aState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaElement::GetHrefCString(char* &aBuf)
{
// Get href= attribute (relative URL).
nsAutoString relURLSpec;
if (NS_CONTENT_ATTR_HAS_VALUE ==
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, relURLSpec)) {
// Get base URL.
nsCOMPtr<nsIURI> baseURL;
mInner.GetBaseURL(*getter_AddRefs(baseURL));
if (baseURL) {
// Get absolute URL.
NS_MakeAbsoluteURIWithCharset(&aBuf, relURLSpec, mInner.mDocument, baseURL,
nsHTMLUtils::IOService, nsHTMLUtils::CharsetMgr);
}
else {
// Absolute URL is same as relative URL.
aBuf = relURLSpec.ToNewUTF8String();
}
}
else {
// Absolute URL is empty because we have no HREF.
aBuf = PL_strdup(""); // use a dummy empty string
}
return NS_OK;
}

Просмотреть файл

@ -24,6 +24,7 @@
#include "nsIDOMEventReceiver.h"
#include "nsIHTMLContent.h"
#include "nsGenericHTMLElement.h"
#include "nsILink.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLIIDs.h"
#include "nsIStyleContext.h"
@ -33,6 +34,8 @@
#include "nsIDOMStyleSheet.h"
#include "nsIStyleSheet.h"
#include "nsIStyleSheetLinkingElement.h"
#include "nsHTMLUtils.h"
#include "nsIURL.h"
static NS_DEFINE_IID(kIDOMHTMLLinkElementIID, NS_IDOMHTMLLINKELEMENT_IID);
static NS_DEFINE_IID(kIStyleSheetLinkingElementIID, NS_ISTYLESHEETLINKINGELEMENT_IID);
@ -40,6 +43,7 @@ static NS_DEFINE_IID(kIDOMStyleSheetIID, NS_IDOMSTYLESHEET_IID);
class nsHTMLLinkElement : public nsIDOMHTMLLinkElement,
public nsIJSScriptObject,
public nsILink,
public nsIHTMLContent,
public nsIStyleSheetLinkingElement
{
@ -82,6 +86,11 @@ public:
// nsIJSScriptObject
NS_IMPL_IJSSCRIPTOBJECT_USING_GENERIC(mInner)
// nsILink
NS_IMETHOD GetLinkState(nsLinkState &aState);
NS_IMETHOD SetLinkState(nsLinkState aState);
NS_IMETHOD GetHrefCString(char* &aBuf);
// nsIContent
NS_IMPL_ICONTENT_USING_GENERIC(mInner)
@ -95,6 +104,9 @@ public:
protected:
nsGenericHTMLLeafElement mInner;
nsIStyleSheet* mStyleSheet;
// The cached visited state
nsLinkState mLinkState;
};
nsresult
@ -113,15 +125,18 @@ NS_NewHTMLLinkElement(nsIHTMLContent** aInstancePtrResult,
nsHTMLLinkElement::nsHTMLLinkElement(nsINodeInfo *aNodeInfo)
: mLinkState(eLinkState_Unknown)
{
NS_INIT_REFCNT();
mInner.Init(this, aNodeInfo);
mStyleSheet = nsnull;
nsHTMLUtils::AddRef(); // for GetHrefCString
}
nsHTMLLinkElement::~nsHTMLLinkElement()
{
NS_IF_RELEASE(mStyleSheet);
nsHTMLUtils::Release(); // for GetHrefCString
}
NS_IMPL_ADDREF(nsHTMLLinkElement)
@ -144,6 +159,11 @@ nsHTMLLinkElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsILink))) {
*aInstancePtr = (void*)(nsILink*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
@ -198,7 +218,6 @@ nsHTMLLinkElement::SetDisabled(PRBool aDisabled)
}
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Charset, charset)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Href, href)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Hreflang, hreflang)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Media, media)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rel, rel)
@ -206,6 +225,30 @@ NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rev, rev)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Target, target)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Type, type)
NS_IMETHODIMP
nsHTMLLinkElement::GetHref(nsString& aValue)
{
char *buf;
nsresult rv = GetHrefCString(buf);
if (NS_FAILED(rv)) return rv;
if (buf) {
aValue.AssignWithConversion(buf);
nsCRT::free(buf);
}
// NS_IMPL_STRING_ATTR does nothing where we have (buf == null)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkElement::SetHref(const nsString& aValue)
{
// Clobber our "cache", so we'll recompute it the next time
// somebody asks for it.
mLinkState = eLinkState_Unknown;
return mInner.SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, aValue, PR_TRUE);
}
NS_IMETHODIMP
nsHTMLLinkElement::SetStyleSheet(nsIStyleSheet* aStyleSheet)
{
@ -289,3 +332,47 @@ nsHTMLLinkElement::SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const
{
return mInner.SizeOf(aSizer, aResult, sizeof(*this));
}
NS_IMETHODIMP
nsHTMLLinkElement::GetLinkState(nsLinkState &aState)
{
aState = mLinkState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkElement::SetLinkState(nsLinkState aState)
{
mLinkState = aState;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkElement::GetHrefCString(char* &aBuf)
{
// Get href= attribute (relative URL).
nsAutoString relURLSpec;
if (NS_CONTENT_ATTR_HAS_VALUE ==
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, relURLSpec)) {
// Get base URL.
nsCOMPtr<nsIURI> baseURL;
mInner.GetBaseURL(*getter_AddRefs(baseURL));
if (baseURL) {
// Get absolute URL.
NS_MakeAbsoluteURIWithCharset(&aBuf, relURLSpec, mInner.mDocument, baseURL,
nsHTMLUtils::IOService, nsHTMLUtils::CharsetMgr);
}
else {
// Absolute URL is same as relative URL.
aBuf = relURLSpec.ToNewUTF8String();
}
}
else {
// Absolute URL is empty because we have no HREF.
aBuf = PL_strdup(""); // use a dummy empty string
}
return NS_OK;
}

Просмотреть файл

@ -1,63 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsStyleUtil_h___
#define nsStyleUtil_h___
#include "nslayout.h"
#include "nsCoord.h"
#include "nsIPresContext.h"
class nsIStyleContext;
struct nsStyleColor;
enum nsFontSizeType {
eFontSize_HTML = 1,
eFontSize_CSS = 2
};
// Style utility functions
class nsStyleUtil {
public:
static float GetScalingFactor(PRInt32 aScaler);
static nscoord CalcFontPointSize(PRInt32 aHTMLSize, PRInt32 aBasePointSize,
float aScalingFactor, nsIPresContext* aPresContext,
nsFontSizeType aFontSizeType = eFontSize_HTML);
static PRInt32 FindNextSmallerFontSize(nscoord aFontSize, PRInt32 aBasePointSize,
float aScalingFactor, nsIPresContext* aPresContext,
nsFontSizeType aFontSizeType = eFontSize_HTML);
static PRInt32 FindNextLargerFontSize(nscoord aFontSize, PRInt32 aBasePointSize,
float aScalingFactor, nsIPresContext* aPresContext,
nsFontSizeType aFontSizeType = eFontSize_HTML);
static PRInt32 ConstrainFontWeight(PRInt32 aWeight);
static const nsStyleColor* FindNonTransparentBackground(nsIStyleContext* aContext,
PRBool aStartAtParent = PR_FALSE);
};
#endif /* nsStyleUtil_h___ */

Просмотреть файл

@ -27,11 +27,7 @@
#include "nsCRT.h"
#include "nsIAtom.h"
#include "nsIURL.h"
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsISupportsArray.h"
#include "nsHashtable.h"
#include "nsICSSStyleRuleProcessor.h"
@ -41,7 +37,6 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsIHTMLContent.h"
#include "nsIDocument.h"
#include "nsIPresContext.h"
#include "nsILinkHandler.h"
#include "nsIEventStateManager.h"
#include "nsHTMLAtoms.h"
#include "nsLayoutAtoms.h"
@ -67,10 +62,10 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsINameSpace.h"
#include "nsITextContent.h"
#include "prlog.h"
#include "nsIXMLContent.h"
#include "nsCOMPtr.h"
#include "nsIStyleSet.h"
#include "nsISizeOfHandler.h"
#include "nsStyleUtil.h"
//#define DEBUG_RULES
//#define EVENT_DEBUG
@ -83,9 +78,6 @@ static NS_DEFINE_IID(kIDOMCSSStyleSheetIID, NS_IDOMCSSSTYLESHEET_IID);
static NS_DEFINE_IID(kIDOMCSSStyleRuleIID, NS_IDOMCSSSTYLERULE_IID);
static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID);
static PRBool IsValidLink(nsIContent *aContent,nsString &aHREF);
static PRBool IsSimpleXlink(nsIContent *aContent, nsString &aHREF);
// ----------------------
// Rule hash key
//
@ -458,9 +450,6 @@ public:
nsINameSpace* mNameSpace;
PRInt32 mDefaultNameSpaceID;
nsHashtable mRelevantAttributes;
static nsIIOService* gIOService;
static nsrefcnt gRefcnt;
};
@ -1090,9 +1079,6 @@ static PRBool SetStyleSheetReference(nsISupports* aElement, void* aSheet)
return PR_TRUE;
}
nsIIOService* CSSStyleSheetInner::gIOService = nsnull;
nsrefcnt CSSStyleSheetInner::gRefcnt = 0;
CSSStyleSheetInner::CSSStyleSheetInner(nsICSSStyleSheet* aParentSheet)
: mSheets(),
mURL(nsnull),
@ -1102,13 +1088,6 @@ CSSStyleSheetInner::CSSStyleSheetInner(nsICSSStyleSheet* aParentSheet)
mRelevantAttributes()
{
MOZ_COUNT_CTOR(CSSStyleSheetInner);
if (gRefcnt++ == 0) {
nsresult rv;
rv = nsServiceManager::GetService(kIOServiceCID,
NS_GET_IID(nsIIOService),
(nsISupports**)&gIOService);
NS_ASSERTION(NS_SUCCEEDED(rv), "can't get nsIOService");
}
mSheets.AppendElement(aParentSheet);
}
@ -1146,13 +1125,6 @@ CSSStyleSheetInner::CSSStyleSheetInner(CSSStyleSheetInner& aCopy,
mRelevantAttributes()
{
MOZ_COUNT_CTOR(CSSStyleSheetInner);
if (gRefcnt++ == 0) {
nsresult rv;
rv = nsServiceManager::GetService(kIOServiceCID,
NS_GET_IID(nsIIOService),
(nsISupports**)&gIOService);
NS_ASSERTION(NS_SUCCEEDED(rv), "can't get nsIOService");
}
mSheets.AppendElement(aParentSheet);
NS_IF_ADDREF(mURL);
if (aCopy.mOrderedRules) {
@ -1179,12 +1151,6 @@ CSSStyleSheetInner::~CSSStyleSheetInner(void)
NS_RELEASE(mOrderedRules);
}
NS_IF_RELEASE(mNameSpace);
if (--gRefcnt == 0) {
nsresult rv;
rv = nsServiceManager::ReleaseService(kIOServiceCID, gIOService);
NS_ASSERTION(NS_SUCCEEDED(rv), "can't release nsIOService");
gIOService = nsnull;
}
}
CSSStyleSheetInner*
@ -2831,8 +2797,6 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
PRBool aTestState)
{
PRBool result = PR_FALSE;
PRBool tagset = PR_FALSE;
nsIAtom* contentTag = NULL; // Make sure this is NULL for NS_IF_RELEASE
// Bail out early if we can
if(kNameSpaceID_Unknown != aSelector->mNameSpace) {
@ -2843,10 +2807,11 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
}
}
nsCOMPtr<nsIAtom> contentTag;
if (((nsnull == aSelector->mTag) || (
aContent->GetTag(contentTag),
tagset=PR_TRUE,
aSelector->mTag == contentTag))) {
aContent->GetTag(*getter_AddRefs(contentTag)),
aSelector->mTag == contentTag.get()))) {
result = PR_TRUE;
// namespace/tag match
@ -2916,7 +2881,6 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
nsAtomList* pseudoClass = aSelector->mPseudoClassList;
PRInt32 eventState = NS_EVENT_STATE_UNSPECIFIED;
nsLinkState linkState = nsLinkState(-1); // not a link
nsILinkHandler* linkHandler = nsnull;
nsIEventStateManager* eventStateManager = nsnull;
while ((PR_TRUE == result) && (nsnull != pseudoClass)) {
@ -3008,9 +2972,7 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
else if (IsEventPseudo(pseudoClass->mAtom)) {
// check if the element is event-sensitive
if (!contentTag) {
if (aContent) {
aContent->GetTag(contentTag);
}
aContent->GetTag(*getter_AddRefs(contentTag));
}
#ifdef EVENT_DEBUG
@ -3041,7 +3003,7 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
nsAutoString strPseudo, strTag;
pseudoClass->mAtom->ToString(strPseudo);
if (!contentTag) {
if (aContent) aContent->GetTag(contentTag);
aContent->GetTag(*getter_AddRefs(contentTag));
}
if (contentTag) {
contentTag->ToString(strTag);
@ -3065,26 +3027,10 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
}
}
else if (IsLinkPseudo(pseudoClass->mAtom)) {
if(!tagset) {
tagset=PR_TRUE;
aContent->GetTag(contentTag);
}
nsAutoString href;
if (IsValidLink(aContent,href)) {
// Now 'href' will contain a canonical URI that we can
// look up in global history.
if (!contentTag) aContent->GetTag(*getter_AddRefs(contentTag));
if (nsStyleUtil::IsHTMLLink(aContent, contentTag, aPresContext, &linkState) ||
nsStyleUtil::IsSimpleXlink(aContent, aPresContext, &linkState)) {
if ((PR_FALSE != result) && (aTestState)) {
if (! linkHandler) {
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(href, linkState);
}
else {
// no link handler? then all links are unvisited
linkState = eLinkState_Unvisited;
}
}
if (nsCSSAtoms::linkPseudo == pseudoClass->mAtom) {
result = PRBool(eLinkState_Unvisited == linkState);
}
@ -3106,11 +3052,9 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
pseudoClass = pseudoClass->mNext;
}
NS_IF_RELEASE(linkHandler);
NS_IF_RELEASE(eventStateManager);
}
}
NS_IF_RELEASE(contentTag);
return result;
}
@ -3769,105 +3713,3 @@ CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium)
}
return cascade;
}
/*static*/
PRBool IsValidLink(nsIContent *aContent,nsString &aHREF)
{
NS_ASSERTION(aContent, "null arg in IsValidLink");
// check for:
// - HTML ANCHOR with valid HREF
// - HTML LINK with valid HREF
// - HTML AREA with valid HREF
// - Simple XLink
// if the content is a valid link, set the href to the canonicalized form and return TRUE
PRBool result = PR_FALSE;
PRBool bIsXLink = PR_FALSE;
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor;
nsCOMPtr<nsIDOMHTMLAreaElement> area;
nsCOMPtr<nsIDOMHTMLLinkElement> link;
if ((anchor = do_QueryInterface(aContent)) ||
(area = do_QueryInterface(aContent)) ||
(link = do_QueryInterface(aContent))) {
// if it is an anchor, area or link then check the href attribute
nsresult attrState = 0;
// make sure this anchor has a link even if we are not testing state
// if there is no link, then this anchor is not really a linkpseudo.
// bug=23209
attrState = aContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, aHREF);
if (NS_CONTENT_ATTR_HAS_VALUE != attrState) {
result = PR_FALSE;
}
else {
if (anchor) {
anchor->GetHref(aHREF);
result = PR_TRUE;
}
else if (area) {
area->GetHref(aHREF);
result = PR_TRUE;
}
else if (link) {
link->GetHref(aHREF);
result = PR_TRUE;
}
}
} // if anchor, area, link
else if ((bIsXLink = IsSimpleXlink(aContent,aHREF))) {
// It's an XLink. Resolve it relative to its document.
nsCOMPtr<nsIURI> baseURI = nsnull;
nsCOMPtr<nsIHTMLContent> htmlContent = do_QueryInterface(aContent);
if (htmlContent) {
// XXX why do this? will nsIHTMLContent's
// GetBaseURL() may return something different
// than the URL of the document it lives in?
htmlContent->GetBaseURL(*getter_AddRefs(baseURI));
}
else {
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (doc) {
doc->GetBaseURL(*getter_AddRefs(baseURI));
}
}
nsAutoString linkURI;
(void) NS_MakeAbsoluteURI(linkURI, aHREF, baseURI, CSSStyleSheetInner::gIOService);
aHREF = linkURI;
result = PR_TRUE;
} // if xlink
return result;
}
/*static*/
PRBool IsSimpleXlink(nsIContent *aContent, nsString &aHREF)
{
NS_ASSERTION(aContent, "invalid call to IsXlink with null content");
PRBool rv = PR_FALSE;
// set the out-param to default / empty
aHREF.Truncate(0);
if (aContent) {
// first see if we have an XML element
nsCOMPtr<nsIXMLContent> xml(do_QueryInterface(aContent));
if (xml) {
// see if it is type=simple (we don't deal with other types)
nsAutoString val;
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::type, val);
if (val == NS_LITERAL_STRING("simple")) {
// see if there is an xlink namespace'd href attribute:
// - get it if there is, if not no big deal, it is not required for xlinks
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::href, aHREF);
rv = PR_TRUE;
}
}
}
return rv;
}

Просмотреть файл

@ -33,15 +33,13 @@
#include "nsCRT.h"
#include "nsIAtom.h"
#include "nsIURL.h"
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsISupportsArray.h"
#include "nsHashtable.h"
#include "nsIHTMLContent.h"
#include "nsIHTMLAttributes.h"
#include "nsILink.h"
#include "nsStyleUtil.h"
#include "nsIStyleRuleProcessor.h"
#include "nsIStyleRule.h"
#include "nsIFrame.h"
@ -49,7 +47,6 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsIMutableStyleContext.h"
#include "nsHTMLAtoms.h"
#include "nsIPresContext.h"
#include "nsILinkHandler.h"
#include "nsIEventStateManager.h"
#include "nsIDocument.h"
#include "nsHTMLIIDs.h"
@ -850,69 +847,40 @@ HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
styledContent->GetTag(tag);
// if we have anchor colors, check if this is an anchor with an href
if (tag == nsHTMLAtoms::a) {
if ((nsnull != mLinkRule) || (nsnull != mVisitedRule)) {
// test link state
nsILinkHandler* linkHandler;
if (NS_OK == aPresContext->GetLinkHandler(&linkHandler)) {
nsAutoString base, href;
nsresult attrState = styledContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, href);
if (NS_CONTENT_ATTR_HAS_VALUE == attrState) {
if (! linkHandler) {
if (mLinkRule || mVisitedRule || mActiveRule) {
nsLinkState state;
if (nsStyleUtil::IsHTMLLink(aContent, tag, aPresContext, &state)) {
switch (state) {
case eLinkState_Unvisited:
if (nsnull != mLinkRule) {
aResults->AppendElement(mLinkRule);
}
}
else {
nsIHTMLContent* htmlContent;
if (NS_SUCCEEDED(styledContent->QueryInterface(kIHTMLContentIID, (void**)&htmlContent))) {
nsCOMPtr<nsIURI> baseURI;
htmlContent->GetBaseURL(*getter_AddRefs(baseURI));
nsAutoString linkURI;
(void) NS_MakeAbsoluteURI(linkURI, href, baseURI);
nsLinkState state;
if (NS_OK == linkHandler->GetLinkState(linkURI, state)) {
switch (state) {
case eLinkState_Unvisited:
if (nsnull != mLinkRule) {
aResults->AppendElement(mLinkRule);
}
break;
case eLinkState_Visited:
if (nsnull != mVisitedRule) {
aResults->AppendElement(mVisitedRule);
}
break;
default:
break;
}
}
NS_RELEASE(htmlContent);
break;
case eLinkState_Visited:
if (nsnull != mVisitedRule) {
aResults->AppendElement(mVisitedRule);
}
}
break;
default:
break;
}
}
NS_IF_RELEASE(linkHandler);
} // end link/visited rules
if (nsnull != mActiveRule) { // test active state of link
nsIEventStateManager* eventStateManager;
// No need to add to the active rule if it's not a link
if (mActiveRule) { // test active state of link
nsIEventStateManager* eventStateManager;
if ((NS_OK == aPresContext->GetEventStateManager(&eventStateManager)) &&
(nsnull != eventStateManager)) {
PRInt32 state;
if (NS_OK == eventStateManager->GetContentState(aContent, state)) {
if (0 != (state & NS_EVENT_STATE_ACTIVE)) {
aResults->AppendElement(mActiveRule);
if ((NS_OK == aPresContext->GetEventStateManager(&eventStateManager)) &&
(nsnull != eventStateManager)) {
PRInt32 state;
if (NS_OK == eventStateManager->GetContentState(aContent, state)) {
if (0 != (state & NS_EVENT_STATE_ACTIVE)) {
aResults->AppendElement(mActiveRule);
}
}
NS_RELEASE(eventStateManager);
}
}
NS_RELEASE(eventStateManager);
} // end active rule
}
} // end active rule
} // end link/visited/active rules
} // end A tag
// add the quirks background compatibility rule if in quirks mode
// and/or the Table TH rule for handling <TH> differently than <TD>

Просмотреть файл

@ -28,6 +28,16 @@
#include "nsStyleConsts.h"
#include "nsUnitConversion.h"
#include "nsHTMLAtoms.h"
#include "nsILinkHandler.h"
#include "nsILink.h"
#include "nsIXMLContent.h"
#include "nsIHTMLContent.h"
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsIServiceManager.h"
#include "nsIPref.h"
@ -476,6 +486,129 @@ const nsStyleColor* nsStyleUtil::FindNonTransparentBackground(nsIStyleContext* a
return result;
}
/*static*/
PRBool nsStyleUtil::IsHTMLLink(nsIContent *aContent, nsIAtom *aTag, nsIPresContext *aPresContext, nsLinkState *aState)
{
NS_ASSERTION(aContent && aState, "null arg in IsHTMLLink");
// check for:
// - HTML ANCHOR with valid HREF
// - HTML LINK with valid HREF
// - HTML AREA with valid HREF
PRBool result = PR_FALSE;
if ((aTag == nsHTMLAtoms::a) ||
(aTag == nsHTMLAtoms::link) ||
(aTag == nsHTMLAtoms::area)) {
nsCOMPtr<nsILink> link( do_QueryInterface(aContent) );
// In XML documents, this can be null.
if (link) {
nsLinkState linkState;
link->GetLinkState(linkState);
if (linkState == eLinkState_Unknown) {
// if it is an anchor, area or link then check the href attribute
// make sure this anchor has a link even if we are not testing state
// if there is no link, then this anchor is not really a linkpseudo.
// bug=23209
char* href;
link->GetHrefCString(href);
if (href) {
nsILinkHandler *linkHandler = nsnull;
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(href, linkState);
NS_RELEASE(linkHandler);
}
else {
// no link handler? then all links are unvisited
linkState = eLinkState_Unvisited;
}
nsCRT::free(href);
} else {
linkState = eLinkState_NotLink;
}
link->SetLinkState(linkState);
}
if (linkState != eLinkState_NotLink) {
*aState = linkState;
result = PR_TRUE;
}
}
}
return result;
}
/*static*/
PRBool nsStyleUtil::IsSimpleXlink(nsIContent *aContent, nsIPresContext *aPresContext, nsLinkState *aState)
{
// XXX PERF This function will cause serious performance problems on
// pages with lots of XLinks. We should be caching the visited
// state of the XLinks. Where???
NS_ASSERTION(aContent && aState, "invalid call to IsXlink with null content");
PRBool rv = PR_FALSE;
if (aContent && aState) {
// first see if we have an XML element
nsCOMPtr<nsIXMLContent> xml(do_QueryInterface(aContent));
if (xml) {
// see if it is type=simple (we don't deal with other types)
nsAutoString val;
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::type, val);
if (val == NS_LITERAL_STRING("simple")) {
// see if there is an xlink namespace'd href attribute:
// - get it if there is, if not no big deal, it is not required for xlinks
// is it bad to re-use val here?
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::href, val);
// It's an XLink. Resolve it relative to its document.
nsCOMPtr<nsIURI> baseURI;
nsCOMPtr<nsIHTMLContent> htmlContent = do_QueryInterface(aContent);
if (htmlContent) {
// XXX why do this? will nsIHTMLContent's
// GetBaseURL() may return something different
// than the URL of the document it lives in?
htmlContent->GetBaseURL(*getter_AddRefs(baseURI));
}
else {
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (doc) {
doc->GetBaseURL(*getter_AddRefs(baseURI));
}
}
// convert here, rather than twice in NS_MakeAbsoluteURI and
// back again
char * href = val.ToNewCString();
char * absHREF = nsnull;
(void) NS_MakeAbsoluteURI(&absHREF, href, baseURI);
nsCRT::free(href);
nsILinkHandler *linkHandler = nsnull;
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(absHREF, *aState);
NS_RELEASE(linkHandler);
}
else {
// no link handler? then all links are unvisited
*aState = eLinkState_Unvisited;
}
nsCRT::free(absHREF);
rv = PR_TRUE;
}
}
}
return rv;
}
//------------------------------------------------------------------------------
//

Просмотреть файл

@ -27,11 +27,7 @@
#include "nsCRT.h"
#include "nsIAtom.h"
#include "nsIURL.h"
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsISupportsArray.h"
#include "nsHashtable.h"
#include "nsICSSStyleRuleProcessor.h"
@ -41,7 +37,6 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsIHTMLContent.h"
#include "nsIDocument.h"
#include "nsIPresContext.h"
#include "nsILinkHandler.h"
#include "nsIEventStateManager.h"
#include "nsHTMLAtoms.h"
#include "nsLayoutAtoms.h"
@ -67,10 +62,10 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsINameSpace.h"
#include "nsITextContent.h"
#include "prlog.h"
#include "nsIXMLContent.h"
#include "nsCOMPtr.h"
#include "nsIStyleSet.h"
#include "nsISizeOfHandler.h"
#include "nsStyleUtil.h"
//#define DEBUG_RULES
//#define EVENT_DEBUG
@ -83,9 +78,6 @@ static NS_DEFINE_IID(kIDOMCSSStyleSheetIID, NS_IDOMCSSSTYLESHEET_IID);
static NS_DEFINE_IID(kIDOMCSSStyleRuleIID, NS_IDOMCSSSTYLERULE_IID);
static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID);
static PRBool IsValidLink(nsIContent *aContent,nsString &aHREF);
static PRBool IsSimpleXlink(nsIContent *aContent, nsString &aHREF);
// ----------------------
// Rule hash key
//
@ -458,9 +450,6 @@ public:
nsINameSpace* mNameSpace;
PRInt32 mDefaultNameSpaceID;
nsHashtable mRelevantAttributes;
static nsIIOService* gIOService;
static nsrefcnt gRefcnt;
};
@ -1090,9 +1079,6 @@ static PRBool SetStyleSheetReference(nsISupports* aElement, void* aSheet)
return PR_TRUE;
}
nsIIOService* CSSStyleSheetInner::gIOService = nsnull;
nsrefcnt CSSStyleSheetInner::gRefcnt = 0;
CSSStyleSheetInner::CSSStyleSheetInner(nsICSSStyleSheet* aParentSheet)
: mSheets(),
mURL(nsnull),
@ -1102,13 +1088,6 @@ CSSStyleSheetInner::CSSStyleSheetInner(nsICSSStyleSheet* aParentSheet)
mRelevantAttributes()
{
MOZ_COUNT_CTOR(CSSStyleSheetInner);
if (gRefcnt++ == 0) {
nsresult rv;
rv = nsServiceManager::GetService(kIOServiceCID,
NS_GET_IID(nsIIOService),
(nsISupports**)&gIOService);
NS_ASSERTION(NS_SUCCEEDED(rv), "can't get nsIOService");
}
mSheets.AppendElement(aParentSheet);
}
@ -1146,13 +1125,6 @@ CSSStyleSheetInner::CSSStyleSheetInner(CSSStyleSheetInner& aCopy,
mRelevantAttributes()
{
MOZ_COUNT_CTOR(CSSStyleSheetInner);
if (gRefcnt++ == 0) {
nsresult rv;
rv = nsServiceManager::GetService(kIOServiceCID,
NS_GET_IID(nsIIOService),
(nsISupports**)&gIOService);
NS_ASSERTION(NS_SUCCEEDED(rv), "can't get nsIOService");
}
mSheets.AppendElement(aParentSheet);
NS_IF_ADDREF(mURL);
if (aCopy.mOrderedRules) {
@ -1179,12 +1151,6 @@ CSSStyleSheetInner::~CSSStyleSheetInner(void)
NS_RELEASE(mOrderedRules);
}
NS_IF_RELEASE(mNameSpace);
if (--gRefcnt == 0) {
nsresult rv;
rv = nsServiceManager::ReleaseService(kIOServiceCID, gIOService);
NS_ASSERTION(NS_SUCCEEDED(rv), "can't release nsIOService");
gIOService = nsnull;
}
}
CSSStyleSheetInner*
@ -2831,8 +2797,6 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
PRBool aTestState)
{
PRBool result = PR_FALSE;
PRBool tagset = PR_FALSE;
nsIAtom* contentTag = NULL; // Make sure this is NULL for NS_IF_RELEASE
// Bail out early if we can
if(kNameSpaceID_Unknown != aSelector->mNameSpace) {
@ -2843,10 +2807,11 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
}
}
nsCOMPtr<nsIAtom> contentTag;
if (((nsnull == aSelector->mTag) || (
aContent->GetTag(contentTag),
tagset=PR_TRUE,
aSelector->mTag == contentTag))) {
aContent->GetTag(*getter_AddRefs(contentTag)),
aSelector->mTag == contentTag.get()))) {
result = PR_TRUE;
// namespace/tag match
@ -2916,7 +2881,6 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
nsAtomList* pseudoClass = aSelector->mPseudoClassList;
PRInt32 eventState = NS_EVENT_STATE_UNSPECIFIED;
nsLinkState linkState = nsLinkState(-1); // not a link
nsILinkHandler* linkHandler = nsnull;
nsIEventStateManager* eventStateManager = nsnull;
while ((PR_TRUE == result) && (nsnull != pseudoClass)) {
@ -3008,9 +2972,7 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
else if (IsEventPseudo(pseudoClass->mAtom)) {
// check if the element is event-sensitive
if (!contentTag) {
if (aContent) {
aContent->GetTag(contentTag);
}
aContent->GetTag(*getter_AddRefs(contentTag));
}
#ifdef EVENT_DEBUG
@ -3041,7 +3003,7 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
nsAutoString strPseudo, strTag;
pseudoClass->mAtom->ToString(strPseudo);
if (!contentTag) {
if (aContent) aContent->GetTag(contentTag);
aContent->GetTag(*getter_AddRefs(contentTag));
}
if (contentTag) {
contentTag->ToString(strTag);
@ -3065,26 +3027,10 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
}
}
else if (IsLinkPseudo(pseudoClass->mAtom)) {
if(!tagset) {
tagset=PR_TRUE;
aContent->GetTag(contentTag);
}
nsAutoString href;
if (IsValidLink(aContent,href)) {
// Now 'href' will contain a canonical URI that we can
// look up in global history.
if (!contentTag) aContent->GetTag(*getter_AddRefs(contentTag));
if (nsStyleUtil::IsHTMLLink(aContent, contentTag, aPresContext, &linkState) ||
nsStyleUtil::IsSimpleXlink(aContent, aPresContext, &linkState)) {
if ((PR_FALSE != result) && (aTestState)) {
if (! linkHandler) {
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(href, linkState);
}
else {
// no link handler? then all links are unvisited
linkState = eLinkState_Unvisited;
}
}
if (nsCSSAtoms::linkPseudo == pseudoClass->mAtom) {
result = PRBool(eLinkState_Unvisited == linkState);
}
@ -3106,11 +3052,9 @@ static PRBool SelectorMatches(nsIPresContext* aPresContext,
pseudoClass = pseudoClass->mNext;
}
NS_IF_RELEASE(linkHandler);
NS_IF_RELEASE(eventStateManager);
}
}
NS_IF_RELEASE(contentTag);
return result;
}
@ -3769,105 +3713,3 @@ CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium)
}
return cascade;
}
/*static*/
PRBool IsValidLink(nsIContent *aContent,nsString &aHREF)
{
NS_ASSERTION(aContent, "null arg in IsValidLink");
// check for:
// - HTML ANCHOR with valid HREF
// - HTML LINK with valid HREF
// - HTML AREA with valid HREF
// - Simple XLink
// if the content is a valid link, set the href to the canonicalized form and return TRUE
PRBool result = PR_FALSE;
PRBool bIsXLink = PR_FALSE;
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor;
nsCOMPtr<nsIDOMHTMLAreaElement> area;
nsCOMPtr<nsIDOMHTMLLinkElement> link;
if ((anchor = do_QueryInterface(aContent)) ||
(area = do_QueryInterface(aContent)) ||
(link = do_QueryInterface(aContent))) {
// if it is an anchor, area or link then check the href attribute
nsresult attrState = 0;
// make sure this anchor has a link even if we are not testing state
// if there is no link, then this anchor is not really a linkpseudo.
// bug=23209
attrState = aContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, aHREF);
if (NS_CONTENT_ATTR_HAS_VALUE != attrState) {
result = PR_FALSE;
}
else {
if (anchor) {
anchor->GetHref(aHREF);
result = PR_TRUE;
}
else if (area) {
area->GetHref(aHREF);
result = PR_TRUE;
}
else if (link) {
link->GetHref(aHREF);
result = PR_TRUE;
}
}
} // if anchor, area, link
else if ((bIsXLink = IsSimpleXlink(aContent,aHREF))) {
// It's an XLink. Resolve it relative to its document.
nsCOMPtr<nsIURI> baseURI = nsnull;
nsCOMPtr<nsIHTMLContent> htmlContent = do_QueryInterface(aContent);
if (htmlContent) {
// XXX why do this? will nsIHTMLContent's
// GetBaseURL() may return something different
// than the URL of the document it lives in?
htmlContent->GetBaseURL(*getter_AddRefs(baseURI));
}
else {
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (doc) {
doc->GetBaseURL(*getter_AddRefs(baseURI));
}
}
nsAutoString linkURI;
(void) NS_MakeAbsoluteURI(linkURI, aHREF, baseURI, CSSStyleSheetInner::gIOService);
aHREF = linkURI;
result = PR_TRUE;
} // if xlink
return result;
}
/*static*/
PRBool IsSimpleXlink(nsIContent *aContent, nsString &aHREF)
{
NS_ASSERTION(aContent, "invalid call to IsXlink with null content");
PRBool rv = PR_FALSE;
// set the out-param to default / empty
aHREF.Truncate(0);
if (aContent) {
// first see if we have an XML element
nsCOMPtr<nsIXMLContent> xml(do_QueryInterface(aContent));
if (xml) {
// see if it is type=simple (we don't deal with other types)
nsAutoString val;
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::type, val);
if (val == NS_LITERAL_STRING("simple")) {
// see if there is an xlink namespace'd href attribute:
// - get it if there is, if not no big deal, it is not required for xlinks
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::href, aHREF);
rv = PR_TRUE;
}
}
}
return rv;
}

Просмотреть файл

@ -33,15 +33,13 @@
#include "nsCRT.h"
#include "nsIAtom.h"
#include "nsIURL.h"
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsISupportsArray.h"
#include "nsHashtable.h"
#include "nsIHTMLContent.h"
#include "nsIHTMLAttributes.h"
#include "nsILink.h"
#include "nsStyleUtil.h"
#include "nsIStyleRuleProcessor.h"
#include "nsIStyleRule.h"
#include "nsIFrame.h"
@ -49,7 +47,6 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nsIMutableStyleContext.h"
#include "nsHTMLAtoms.h"
#include "nsIPresContext.h"
#include "nsILinkHandler.h"
#include "nsIEventStateManager.h"
#include "nsIDocument.h"
#include "nsHTMLIIDs.h"
@ -850,69 +847,40 @@ HTMLStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
styledContent->GetTag(tag);
// if we have anchor colors, check if this is an anchor with an href
if (tag == nsHTMLAtoms::a) {
if ((nsnull != mLinkRule) || (nsnull != mVisitedRule)) {
// test link state
nsILinkHandler* linkHandler;
if (NS_OK == aPresContext->GetLinkHandler(&linkHandler)) {
nsAutoString base, href;
nsresult attrState = styledContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, href);
if (NS_CONTENT_ATTR_HAS_VALUE == attrState) {
if (! linkHandler) {
if (mLinkRule || mVisitedRule || mActiveRule) {
nsLinkState state;
if (nsStyleUtil::IsHTMLLink(aContent, tag, aPresContext, &state)) {
switch (state) {
case eLinkState_Unvisited:
if (nsnull != mLinkRule) {
aResults->AppendElement(mLinkRule);
}
}
else {
nsIHTMLContent* htmlContent;
if (NS_SUCCEEDED(styledContent->QueryInterface(kIHTMLContentIID, (void**)&htmlContent))) {
nsCOMPtr<nsIURI> baseURI;
htmlContent->GetBaseURL(*getter_AddRefs(baseURI));
nsAutoString linkURI;
(void) NS_MakeAbsoluteURI(linkURI, href, baseURI);
nsLinkState state;
if (NS_OK == linkHandler->GetLinkState(linkURI, state)) {
switch (state) {
case eLinkState_Unvisited:
if (nsnull != mLinkRule) {
aResults->AppendElement(mLinkRule);
}
break;
case eLinkState_Visited:
if (nsnull != mVisitedRule) {
aResults->AppendElement(mVisitedRule);
}
break;
default:
break;
}
}
NS_RELEASE(htmlContent);
break;
case eLinkState_Visited:
if (nsnull != mVisitedRule) {
aResults->AppendElement(mVisitedRule);
}
}
break;
default:
break;
}
}
NS_IF_RELEASE(linkHandler);
} // end link/visited rules
if (nsnull != mActiveRule) { // test active state of link
nsIEventStateManager* eventStateManager;
// No need to add to the active rule if it's not a link
if (mActiveRule) { // test active state of link
nsIEventStateManager* eventStateManager;
if ((NS_OK == aPresContext->GetEventStateManager(&eventStateManager)) &&
(nsnull != eventStateManager)) {
PRInt32 state;
if (NS_OK == eventStateManager->GetContentState(aContent, state)) {
if (0 != (state & NS_EVENT_STATE_ACTIVE)) {
aResults->AppendElement(mActiveRule);
if ((NS_OK == aPresContext->GetEventStateManager(&eventStateManager)) &&
(nsnull != eventStateManager)) {
PRInt32 state;
if (NS_OK == eventStateManager->GetContentState(aContent, state)) {
if (0 != (state & NS_EVENT_STATE_ACTIVE)) {
aResults->AppendElement(mActiveRule);
}
}
NS_RELEASE(eventStateManager);
}
}
NS_RELEASE(eventStateManager);
} // end active rule
}
} // end active rule
} // end link/visited/active rules
} // end A tag
// add the quirks background compatibility rule if in quirks mode
// and/or the Table TH rule for handling <TH> differently than <TD>

Просмотреть файл

@ -28,6 +28,16 @@
#include "nsStyleConsts.h"
#include "nsUnitConversion.h"
#include "nsHTMLAtoms.h"
#include "nsILinkHandler.h"
#include "nsILink.h"
#include "nsIXMLContent.h"
#include "nsIHTMLContent.h"
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsIServiceManager.h"
#include "nsIPref.h"
@ -476,6 +486,129 @@ const nsStyleColor* nsStyleUtil::FindNonTransparentBackground(nsIStyleContext* a
return result;
}
/*static*/
PRBool nsStyleUtil::IsHTMLLink(nsIContent *aContent, nsIAtom *aTag, nsIPresContext *aPresContext, nsLinkState *aState)
{
NS_ASSERTION(aContent && aState, "null arg in IsHTMLLink");
// check for:
// - HTML ANCHOR with valid HREF
// - HTML LINK with valid HREF
// - HTML AREA with valid HREF
PRBool result = PR_FALSE;
if ((aTag == nsHTMLAtoms::a) ||
(aTag == nsHTMLAtoms::link) ||
(aTag == nsHTMLAtoms::area)) {
nsCOMPtr<nsILink> link( do_QueryInterface(aContent) );
// In XML documents, this can be null.
if (link) {
nsLinkState linkState;
link->GetLinkState(linkState);
if (linkState == eLinkState_Unknown) {
// if it is an anchor, area or link then check the href attribute
// make sure this anchor has a link even if we are not testing state
// if there is no link, then this anchor is not really a linkpseudo.
// bug=23209
char* href;
link->GetHrefCString(href);
if (href) {
nsILinkHandler *linkHandler = nsnull;
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(href, linkState);
NS_RELEASE(linkHandler);
}
else {
// no link handler? then all links are unvisited
linkState = eLinkState_Unvisited;
}
nsCRT::free(href);
} else {
linkState = eLinkState_NotLink;
}
link->SetLinkState(linkState);
}
if (linkState != eLinkState_NotLink) {
*aState = linkState;
result = PR_TRUE;
}
}
}
return result;
}
/*static*/
PRBool nsStyleUtil::IsSimpleXlink(nsIContent *aContent, nsIPresContext *aPresContext, nsLinkState *aState)
{
// XXX PERF This function will cause serious performance problems on
// pages with lots of XLinks. We should be caching the visited
// state of the XLinks. Where???
NS_ASSERTION(aContent && aState, "invalid call to IsXlink with null content");
PRBool rv = PR_FALSE;
if (aContent && aState) {
// first see if we have an XML element
nsCOMPtr<nsIXMLContent> xml(do_QueryInterface(aContent));
if (xml) {
// see if it is type=simple (we don't deal with other types)
nsAutoString val;
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::type, val);
if (val == NS_LITERAL_STRING("simple")) {
// see if there is an xlink namespace'd href attribute:
// - get it if there is, if not no big deal, it is not required for xlinks
// is it bad to re-use val here?
aContent->GetAttribute(kNameSpaceID_XLink, nsHTMLAtoms::href, val);
// It's an XLink. Resolve it relative to its document.
nsCOMPtr<nsIURI> baseURI;
nsCOMPtr<nsIHTMLContent> htmlContent = do_QueryInterface(aContent);
if (htmlContent) {
// XXX why do this? will nsIHTMLContent's
// GetBaseURL() may return something different
// than the URL of the document it lives in?
htmlContent->GetBaseURL(*getter_AddRefs(baseURI));
}
else {
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (doc) {
doc->GetBaseURL(*getter_AddRefs(baseURI));
}
}
// convert here, rather than twice in NS_MakeAbsoluteURI and
// back again
char * href = val.ToNewCString();
char * absHREF = nsnull;
(void) NS_MakeAbsoluteURI(&absHREF, href, baseURI);
nsCRT::free(href);
nsILinkHandler *linkHandler = nsnull;
aPresContext->GetLinkHandler(&linkHandler);
if (linkHandler) {
linkHandler->GetLinkState(absHREF, *aState);
NS_RELEASE(linkHandler);
}
else {
// no link handler? then all links are unvisited
*aState = eLinkState_Unvisited;
}
nsCRT::free(absHREF);
rv = PR_TRUE;
}
}
}
return rv;
}
//------------------------------------------------------------------------------
//

Просмотреть файл

@ -34,9 +34,11 @@ struct nsGUIEvent;
{ 0xa6cf905b, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
enum nsLinkState {
eLinkState_Unvisited = 0,
eLinkState_Visited = 1,
eLinkState_OutOfDate = 2 // visited, but the cache is stale
eLinkState_Unknown = 0,
eLinkState_Unvisited = 1,
eLinkState_Visited = 2,
eLinkState_OutOfDate = 3, // visited, but the cache is stale
eLinkState_NotLink = 4
};
// XXX Verb to use for link actuation. These are the verbs specified
@ -82,7 +84,7 @@ public:
/**
* Get the state of a link to a given absolute URL
*/
NS_IMETHOD GetLinkState(const nsString& aLinkURI, nsLinkState& aState) = 0;
NS_IMETHOD GetLinkState(const char* aLinkURI, nsLinkState& aState) = 0;
};
#endif /* nsILinkHandler_h___ */