Fixing bug 334587. Unify event handling for links and fix various XLink bugs. r=olli.pettay@gmail.com, r=dbaron@mozilla.com, sr=bugmail@sicking.cc

This commit is contained in:
jwatt%jwatt.org 2007-01-04 10:53:59 +00:00
Родитель 2c7ea76e3c
Коммит 688f763168
30 изменённых файлов: 487 добавлений и 622 удалений

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

@ -571,23 +571,6 @@ public:
*/
static PRBool IsDraggableLink(nsIContent* aContent);
/**
* Method that gets the URI of the link content. If the content
* isn't a link, return null.
*
* @param aContent The link content
* @return the URI the link points to
*/
static already_AddRefed<nsIURI> GetLinkURI(nsIContent* aContent);
/**
* Method that gets the XLink uri for a content node, if it's an XLink
*
* @param aContent The content node, possibly an XLink
* @return Null if aContent is not an XLink, the URI it points to otherwise
*/
static already_AddRefed<nsIURI> GetXLinkURI(nsIContent* aContent);
/**
* Convenience method to create a new nodeinfo that differs only by name
* from aNodeInfo.

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

@ -62,8 +62,9 @@ class nsTextFragment;
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
{ 0x38cb1dfd, 0xeeac, 0x4f35, \
{ 0x93, 0x83, 0xc0, 0xb5, 0xe5, 0xf1, 0xcd, 0xa4 } }
{ 0x43511041, 0xae82, 0x45aa, \
{ 0xb9, 0x48, 0xd6, 0x1d, 0x81, 0xc9, 0xc3, 0x25 } }
// hack to make egcs / gcc 2.95.2 happy
class nsIContent_base : public nsINode {
@ -545,6 +546,21 @@ public:
*/
virtual already_AddRefed<nsIURI> GetBaseURI() const = 0;
/**
* API to check if this is a link that's traversed in response to user input
* (e.g. a click event). Specializations for HTML/SVG/generic XML allow for
* different types of link in different types of content.
*
* @param aURI Required out param. If this content is a link, a new nsIURI
* set to this link's URI will be passed out.
*
* @note The out param, aURI, is guaranteed to be set to a non-null pointer
* when the return value is PR_TRUE.
*
* XXXjwatt: IMO IsInteractiveLink would be a better name.
*/
virtual PRBool IsLink(nsIURI** aURI) const = 0;
/**
* This method is called when the parser finishes creating the element. This
* particularly means that it has done everything you would expect it to have

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

@ -979,21 +979,14 @@ nsTransferableFactory::FindParentLinkNode(nsIDOMNode* inNode)
//
// GetAnchorURL
//
// Get the url for this anchor. First try the href, and if that's
// empty, go for the name.
//
void
nsTransferableFactory::GetAnchorURL(nsIDOMNode* inNode, nsAString& outURL)
{
outURL.Truncate();
nsCOMPtr<nsIContent> content(do_QueryInterface(inNode));
if (!content) {
nsCOMPtr<nsIURI> linkURI;
nsCOMPtr<nsIContent> content = do_QueryInterface(inNode);
if (!content || !content->IsLink(getter_AddRefs(linkURI))) {
// Not a link
return;
}
nsCOMPtr<nsIURI> linkURI = nsContentUtils::GetLinkURI(content);
if (!linkURI) {
outURL.Truncate();
return;
}

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

@ -66,7 +66,6 @@
#include "nsIDOMNode.h"
#include "nsIDOM3Node.h"
#include "nsIIOService.h"
#include "nsIURI.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsIScriptSecurityManager.h"
@ -101,10 +100,8 @@
#include "nsIImageLoadingContent.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsILink.h"
#include "nsILoadGroup.h"
#include "nsContentPolicyUtils.h"
#include "nsDOMString.h"
#include "nsNodeInfoManager.h"
#include "nsIXBLService.h"
#include "nsCRT.h"
@ -2107,54 +2104,8 @@ nsContentUtils::IsDraggableImage(nsIContent* aContent)
// static
PRBool
nsContentUtils::IsDraggableLink(nsIContent* aContent) {
nsCOMPtr<nsIURI> linkURI = GetLinkURI(aContent);
// Does it have a URI? If not, it's not draggable
return linkURI != nsnull;
}
// static
already_AddRefed<nsIURI>
nsContentUtils::GetLinkURI(nsIContent* aContent)
{
NS_PRECONDITION(aContent, "Must have content node to work with");
nsCOMPtr<nsILink> link(do_QueryInterface(aContent));
if (link) {
nsIURI* uri = nsnull;
link->GetHrefURI(&uri);
if (uri) {
return uri;
}
}
// It could still be an XLink
return GetXLinkURI(aContent);
}
// static
already_AddRefed<nsIURI>
nsContentUtils::GetXLinkURI(nsIContent* aContent)
{
NS_PRECONDITION(aContent, "Must have content node to work with");
if (aContent->AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
nsGkAtoms::simple, eCaseMatters)) {
nsAutoString value;
// Check that we have a URI
if (aContent->GetAttr(kNameSpaceID_XLink, nsGkAtoms::href, value)) {
// Resolve it relative to aContent's base URI.
nsCOMPtr<nsIURI> baseURI = aContent->GetBaseURI();
nsIURI* uri = nsnull;
nsContentUtils::NewURIWithDocumentCharset(&uri, value,
aContent->GetDocument(),
baseURI);
return uri;
}
}
return nsnull;
nsCOMPtr<nsIURI> absURI;
return aContent->IsLink(getter_AddRefs(absURI));
}
// static

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

@ -5239,9 +5239,9 @@ nsDocument::ForgetLink(nsIContent* aContent)
// now before we waste time constructing a URI object.
if (mLinkMap.Count() == 0)
return;
nsCOMPtr<nsIURI> uri = nsContentUtils::GetLinkURI(aContent);
if (!uri)
nsCOMPtr<nsIURI> uri;
if (!aContent->IsLink(getter_AddRefs(uri)))
return;
PRUint32 hash = GetURIHash(uri);
nsUint32ToContentHashEntry* entry = mLinkMap.GetEntry(hash);
@ -5264,8 +5264,8 @@ public:
virtual void Visit(nsIContent* aContent) {
// Ensure that the URIs really match before we try to do anything
nsCOMPtr<nsIURI> uri = nsContentUtils::GetLinkURI(aContent);
if (!uri) {
nsCOMPtr<nsIURI> uri;
if (!aContent->IsLink(getter_AddRefs(uri))) {
NS_ERROR("Should have found a URI for content in the link map");
return;
}

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

@ -811,6 +811,13 @@ nsGenericDOMDataNode::GetBaseURI() const
return uri;
}
PRBool
nsGenericDOMDataNode::IsLink(nsIURI** aURI) const
{
*aURI = nsnull;
return PR_FALSE;
}
nsINode::nsSlots*
nsGenericDOMDataNode::CreateSlots()
{

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

@ -231,6 +231,7 @@ public:
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
virtual already_AddRefed<nsIURI> GetBaseURI() const;
virtual PRBool IsLink(nsIURI** aURI) const;
virtual PRBool MayHaveFrame() const;

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

@ -113,6 +113,7 @@
#include "nsIDOMUserDataHandler.h"
#include "nsEventDispatcher.h"
#include "nsContentCreatorFunctions.h"
#include "nsIFocusController.h"
#ifdef MOZ_SVG
PRBool NS_SVG_TestFeature(const nsAString &fstr);
@ -2135,6 +2136,13 @@ nsGenericElement::GetBaseURI() const
return base;
}
PRBool
nsGenericElement::IsLink(nsIURI** aURI) const
{
*aURI = nsnull;
return PR_FALSE;
}
void
nsGenericElement::SetFocus(nsPresContext* aPresContext)
{
@ -3049,7 +3057,6 @@ nsGenericElement::LeaveLink(nsPresContext* aPresContext)
nsresult
nsGenericElement::TriggerLink(nsPresContext* aPresContext,
nsLinkVerb aVerb,
nsIURI* aLinkURI,
const nsAFlatString& aTargetSpec,
PRBool aClick,
@ -3079,7 +3086,7 @@ nsGenericElement::TriggerLink(nsPresContext* aPresContext,
// Only pass off the click event if the script security manager
// says it's ok.
if (NS_SUCCEEDED(proceed))
handler->OnLinkClick(this, aVerb, aLinkURI, aTargetSpec.get());
handler->OnLinkClick(this, aLinkURI, aTargetSpec.get());
} else {
handler->OnOverLink(this, aLinkURI, aTargetSpec.get());
}
@ -3155,7 +3162,7 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
if (kNameSpaceID_XLink == aNamespaceID && nsGkAtoms::href == aName) {
// XLink URI(s) might be changing. Drop the link from the map. If it
// is still style relevant it will be re-added by
// nsStyleUtil::IsSimpleXlink. Make sure to keep the style system
// nsStyleUtil::IsLink. Make sure to keep the style system
// consistent so this remains true! In particular if the style system
// were to get smarter and not restyling an XLink element if the href
// doesn't change in a "significant" way, we'd need to do the same
@ -3769,3 +3776,154 @@ nsGenericElement::CreateSlots()
{
return new nsDOMSlots(mFlagsOrSlots);
}
nsresult
nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor)
{
// Optimisation: return early if this event doesn't interest us.
// IMPORTANT: this switch and the switch below it must be kept in sync!
switch (aVisitor.mEvent->message) {
case NS_MOUSE_BUTTON_DOWN:
case NS_MOUSE_CLICK:
case NS_UI_ACTIVATE:
case NS_KEY_PRESS:
case NS_MOUSE_ENTER_SYNTH:
case NS_FOCUS_CONTENT:
case NS_MOUSE_EXIT_SYNTH:
case NS_BLUR_CONTENT:
break;
default:
return NS_OK;
}
if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault ||
!NS_IS_TRUSTED_EVENT(aVisitor.mEvent) ||
!aVisitor.mPresContext) {
return NS_OK;
}
// Make sure we actually are a link before continuing
nsCOMPtr<nsIURI> absURI;
if (!IsLink(getter_AddRefs(absURI))) {
return NS_OK;
}
nsresult rv = NS_OK;
switch (aVisitor.mEvent->message) {
case NS_MOUSE_BUTTON_DOWN:
{
if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
NS_STATIC_CAST(nsMouseEvent*, aVisitor.mEvent)->button ==
nsMouseEvent::eLeftButton) {
// don't make the link grab the focus if there is no link handler
nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler();
nsIDocument *document = GetCurrentDoc();
if (handler && document && ShouldFocus(this)) {
// If the window is not active, do not allow the focus to bring the
// window to the front. We update the focus controller, but do nothing
// else.
nsPIDOMWindow *win = document->GetWindow();
if (win) {
nsIFocusController *focusController =
win->GetRootFocusController();
if (focusController) {
PRBool isActive = PR_FALSE;
focusController->GetActive(&isActive);
if (!isActive) {
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
if(domElement)
focusController->SetFocusedElement(domElement);
break;
}
}
}
aVisitor.mPresContext->EventStateManager()->
SetContentState(this, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS);
}
}
}
break;
case NS_MOUSE_CLICK:
if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
nsInputEvent* inputEvent = NS_STATIC_CAST(nsInputEvent*, aVisitor.mEvent);
if (inputEvent->isControl || inputEvent->isMeta ||
inputEvent->isAlt ||inputEvent->isShift) {
break;
}
// The default action is simply to dispatch DOMActivate
nsIPresShell *shell = aVisitor.mPresContext->GetPresShell();
if (shell) {
// single-click
nsEventStatus status = nsEventStatus_eIgnore;
nsUIEvent actEvent(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
NS_UI_ACTIVATE, 1);
rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
}
}
break;
case NS_UI_ACTIVATE:
{
nsAutoString target;
GetLinkTarget(target);
rv = TriggerLink(aVisitor.mPresContext, absURI, target, PR_TRUE, PR_TRUE);
}
break;
case NS_KEY_PRESS:
{
if (aVisitor.mEvent->eventStructType == NS_KEY_EVENT) {
nsKeyEvent* keyEvent = NS_STATIC_CAST(nsKeyEvent*, aVisitor.mEvent);
if (keyEvent->keyCode == NS_VK_RETURN) {
nsEventStatus status = nsEventStatus_eIgnore;
rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this,
PR_FALSE, &status);
if (NS_SUCCEEDED(rv)) {
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
}
}
break;
// Set the status bar the same for focus and mouseover
case NS_MOUSE_ENTER_SYNTH:
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
// FALL THROUGH
case NS_FOCUS_CONTENT:
{
nsAutoString target;
GetLinkTarget(target);
rv = TriggerLink(aVisitor.mPresContext, absURI, target, PR_FALSE, PR_TRUE);
}
break;
case NS_MOUSE_EXIT_SYNTH:
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
rv = LeaveLink(aVisitor.mPresContext);
break;
case NS_BLUR_CONTENT:
rv = LeaveLink(aVisitor.mPresContext);
break;
default:
// switch not in sync with the optimization switch earlier in this function
NS_NOTREACHED("switch statements not in sync");
return NS_ERROR_UNEXPECTED;
}
return rv;
}
void
nsGenericElement::GetLinkTarget(nsAString& aTarget)
{
aTarget.Truncate();
}

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

@ -427,6 +427,7 @@ public:
virtual nsIContent *GetBindingParent() const;
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
virtual already_AddRefed<nsIURI> GetBaseURI() const;
virtual PRBool IsLink(nsIURI** aURI) const;
virtual void SetMayHaveFrame(PRBool aMayHaveFrame);
virtual PRBool MayHaveFrame() const;
@ -562,7 +563,6 @@ public:
* check.
*
* @param aPresContext the pres context.
* @param aVerb how the link will be loaded (replace page, new window, etc.)
* @param aLinkURI the URI of the link
* @param aTargetSpec the target (like target=, may be empty)
* @param aClick whether this was a click or not (if false, it assumes you
@ -572,7 +572,6 @@ public:
* click() method if we ever implement it.
*/
nsresult TriggerLink(nsPresContext* aPresContext,
nsLinkVerb aVerb,
nsIURI* aLinkURI,
const nsAFlatString& aTargetSpec,
PRBool aClick,
@ -981,6 +980,24 @@ protected:
*/
void GetContentsAsText(nsAString& aText);
/**
* Unified function to carry out event default actions for links of all types
* (HTML links, XLinks, SVG "XLinks", etc.)
*/
nsresult PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor);
/**
* Get the target of this link element. Consumers should established that
* this element is a link (probably using IsLink) before calling this
* function (or else why call it?)
*
* Note: for HTML this gets the value of the 'target' attribute; for XLink
* this gets the value of the xlink:_moz_target attribute, or failing that,
* the value of xlink:show, converted to a suitably equivalent named target
* (e.g. _blank).
*/
virtual void GetLinkTarget(nsAString& aTarget);
/**
* Array containing all attributes and children for this element
*/

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

@ -584,6 +584,7 @@ GK_ATOM(onpopuphidden, "onpopuphidden")
GK_ATOM(onpopuphiding, "onpopuphiding")
GK_ATOM(onpopupshowing, "onpopupshowing")
GK_ATOM(onpopupshown, "onpopupshown")
GK_ATOM(onRequest, "onRequest")
GK_ATOM(onreset, "onreset")
GK_ATOM(onresize, "onresize")
GK_ATOM(onscroll, "onscroll")

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

@ -1221,8 +1221,7 @@ nsFormSubmission::SubmitTo(nsIURI* aActionURI, const nsAString& aTarget,
//
NS_ENSURE_ARG_POINTER(aLinkHandler);
return aLinkHandler->OnLinkClickSync(aSource, eLinkVerb_Replace,
aActionURI,
return aLinkHandler->OnLinkClickSync(aSource, aActionURI,
PromiseFlatString(aTarget).get(),
postDataStream, nsnull,
aDocShell, aRequest);

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

@ -40,21 +40,17 @@
#include "nsGenericHTMLElement.h"
#include "nsCOMPtr.h"
#include "nsIAtom.h"
#include "nsINodeInfo.h"
#include "nsIContentViewer.h"
#include "nsICSSParser.h"
#include "nsICSSLoader.h"
#include "nsICSSStyleRule.h"
#include "nsCSSStruct.h"
#include "nsCSSDeclaration.h"
#include "nsIDocument.h"
#include "nsIDocumentEncoder.h"
#include "nsIDOMHTMLBodyElement.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMAttr.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMNamedNodeMap.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMDocumentFragment.h"
#include "nsIDOMNSHTMLDocument.h"
#include "nsIDOMNSHTMLElement.h"
@ -62,19 +58,15 @@
#include "nsIDOMWindow.h"
#include "nsIDOMDocument.h"
#include "nsIEventListenerManager.h"
#include "nsIFocusController.h"
#include "nsMappedAttributes.h"
#include "nsHTMLStyleSheet.h"
#include "nsIHTMLDocument.h"
#include "nsILink.h"
#include "nsILinkHandler.h"
#include "nsPIDOMWindow.h"
#include "nsIStyleRule.h"
#include "nsISupportsArray.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
#include "nsEscape.h"
#include "nsStyleConsts.h"
#include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "nsIScrollableView.h"
@ -83,8 +75,6 @@
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIDocShell.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsINameSpaceManager.h"
#include "nsDOMError.h"
#include "nsScriptLoader.h"
@ -96,47 +86,23 @@
#include "nsHTMLParts.h"
#include "nsContentUtils.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
#include "nsLayoutAtoms.h"
#include "nsIEventStateManager.h"
#include "nsIDOMEvent.h"
#include "nsIDOMNSEvent.h"
#include "nsIPrivateDOMEvent.h"
#include "nsDOMCID.h"
#include "nsIServiceManager.h"
#include "nsDOMCSSDeclaration.h"
#include "nsICSSOMFactory.h"
#include "prprf.h"
#include "prmem.h"
#include "nsITextControlFrame.h"
#include "nsIForm.h"
#include "nsIFormControl.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsILanguageAtomService.h"
#include "nsIDOMMutationEvent.h"
#include "nsMutationEvent.h"
#include "nsIBindingManager.h"
#include "nsXBLBinding.h"
#include "nsRuleWalker.h"
#include "nsIObjectFrame.h"
#include "xptinfo.h"
#include "nsIInterfaceInfoManager.h"
#include "nsIServiceManager.h"
#include "nsIParser.h"
#include "nsParserCIID.h"
#include "nsIHTMLContentSink.h"
#include "nsLayoutCID.h"
#include "nsContentCID.h"
#include "nsIDOMText.h"
#include "nsCOMArray.h"
#include "nsNodeInfoManager.h"
#include "nsIEditor.h"
#include "nsIEditorIMESupport.h"
@ -144,6 +110,10 @@
#include "nsLayoutUtils.h"
#include "nsContentCreatorFunctions.h"
class nsINodeInfo;
class nsIDOMNodeList;
class nsRuleWalker;
// XXX todo: add in missing out-of-memory checks
//----------------------------------------------------------------------
@ -1427,163 +1397,39 @@ nsGenericHTMLElement::PostHandleEventForAnchors(nsEventChainPostVisitor& aVisito
NS_PRECONDITION(nsCOMPtr<nsILink>(do_QueryInterface(this)),
"should be called only when |this| implements |nsILink|");
nsresult rv = NS_OK;
if (!aVisitor.mPresContext) {
// We need a pres context to do link stuff. Some events (e.g. mutation
// events) don't have one.
// XXX: ideally, shouldn't we be able to do what we need without one?
return rv;
}
if (!NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) {
return rv;
return NS_OK;
}
//Need to check if we hit an imagemap area and if so see if we're handling
//the event on that map or on a link farther up the tree. If we're on a
//link farther up, do nothing.
nsCOMPtr<nsIContent> target;
aVisitor.mPresContext->EventStateManager()->
GetEventTargetContent(aVisitor.mEvent, getter_AddRefs(target));
if (target && IsArea(target) && !IsArea(this)) {
return rv;
return NS_OK;
}
if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault) {
return PostHandleEventForLinks(aVisitor);
}
// We'll use the equivalent of |GetHrefUTF8| on the
// nsILink interface to get a canonified URL that has been
// correctly escaped and URL-encoded for the document's charset.
PRBool
nsGenericHTMLElement::IsHTMLLink(nsIURI** aURI) const
{
NS_PRECONDITION(aURI, "Must provide aURI out param");
nsCOMPtr<nsIURI> hrefURI;
GetHrefURIForAnchors(getter_AddRefs(hrefURI));
// Only bother to handle the mouse event if there was an href
// specified.
if (hrefURI) {
switch (aVisitor.mEvent->message) {
case NS_MOUSE_BUTTON_DOWN:
{
if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
NS_STATIC_CAST(nsMouseEvent*, aVisitor.mEvent)->button ==
nsMouseEvent::eLeftButton) {
// don't make the link grab the focus if there is no link handler
nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler();
nsIDocument *document = GetCurrentDoc();
if (handler && document && ShouldFocus(this)) {
// If the window is not active, do not allow the focus to bring the
// window to the front. We update the focus controller, but do
// nothing else.
nsPIDOMWindow *win = document->GetWindow();
if (win) {
nsIFocusController *focusController =
win->GetRootFocusController();
if (focusController) {
PRBool isActive = PR_FALSE;
focusController->GetActive(&isActive);
if (!isActive) {
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
if(domElement)
focusController->SetFocusedElement(domElement);
break;
}
}
}
aVisitor.mPresContext->EventStateManager()->
SetContentState(this,
NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS);
}
}
}
break;
case NS_MOUSE_CLICK:
if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
nsInputEvent* inputEvent =
NS_STATIC_CAST(nsInputEvent*, aVisitor.mEvent);
if (inputEvent->isControl || inputEvent->isMeta ||
inputEvent->isAlt ||inputEvent->isShift) {
break;
}
// The default action is simply to dispatch DOMActivate
nsIPresShell *shell = aVisitor.mPresContext->GetPresShell();
if (shell) {
// single-click
nsUIEvent actEvent(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
NS_UI_ACTIVATE, 1);
nsEventStatus status = nsEventStatus_eIgnore;
rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
}
}
break;
case NS_UI_ACTIVATE:
{
nsAutoString target;
GetAttr(kNameSpaceID_None, nsGkAtoms::target, target);
if (target.IsEmpty()) {
GetBaseTarget(target);
}
rv = TriggerLink(aVisitor.mPresContext, eLinkVerb_Replace, hrefURI,
target, PR_TRUE, PR_TRUE);
}
break;
case NS_KEY_PRESS:
if (aVisitor.mEvent->eventStructType == NS_KEY_EVENT) {
nsKeyEvent* keyEvent = NS_STATIC_CAST(nsKeyEvent*, aVisitor.mEvent);
if (keyEvent->keyCode == NS_VK_RETURN) {
nsEventStatus status = nsEventStatus_eIgnore;
rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this,
PR_FALSE, &status);
if (NS_SUCCEEDED(rv)) {
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
}
break;
// Set the status bar the same for focus and mouseover
case NS_MOUSE_ENTER_SYNTH:
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
// FALL THROUGH
case NS_FOCUS_CONTENT:
{
nsAutoString target;
GetAttr(kNameSpaceID_None, nsGkAtoms::target, target);
if (target.IsEmpty()) {
GetBaseTarget(target);
}
rv = TriggerLink(aVisitor.mPresContext, eLinkVerb_Replace,
hrefURI, target, PR_FALSE, PR_TRUE);
}
break;
case NS_MOUSE_EXIT_SYNTH:
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
rv = LeaveLink(aVisitor.mPresContext);
break;
case NS_BLUR_CONTENT:
rv = LeaveLink(aVisitor.mPresContext);
break;
default:
break;
}
}
}
return rv;
GetHrefURIForAnchors(aURI);
// We promise out param is non-null if we return true, so base rv on it
return *aURI != nsnull;
}
nsresult
nsGenericHTMLElement::GetHrefURIForAnchors(nsIURI** aURI)
nsGenericHTMLElement::GetHrefURIForAnchors(nsIURI** aURI) const
{
// This is used by the three nsILink implementations and
// nsHTMLStyleElement.

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

@ -194,10 +194,11 @@ public:
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
nsresult PostHandleEventForAnchors(nsEventChainPostVisitor& aVisitor);
PRBool IsHTMLLink(nsIURI** aURI) const;
// Used by A, AREA, LINK, and STYLE.
// Callers must hold a reference to nsHTMLUtils's global reference count.
nsresult GetHrefURIForAnchors(nsIURI** aURI);
nsresult GetHrefURIForAnchors(nsIURI** aURI) const;
// HTML element methods
void Compact() { mAttrsAndChildren.Compact(); }

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

@ -112,6 +112,8 @@ public:
virtual PRBool IsFocusable(PRBool *aTabIndex = nsnull);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual PRBool IsLink(nsIURI** aURI) const;
virtual void GetLinkTarget(nsAString& aTarget);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
@ -265,8 +267,8 @@ nsHTMLAnchorElement::IsFocusable(PRInt32 *aTabIndex)
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
// check whether we're actually a link
nsCOMPtr<nsIURI> linkURI = nsContentUtils::GetLinkURI(this);
if (!linkURI) {
nsCOMPtr<nsIURI> absURI;
if (!IsLink(getter_AddRefs(absURI))) {
// Not tabbable or focusable without href (bug 17605), unless
// forced to be via presence of nonnegative tabindex attribute
if (aTabIndex) {
@ -289,6 +291,18 @@ nsHTMLAnchorElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
return PostHandleEventForAnchors(aVisitor);
}
PRBool
nsHTMLAnchorElement::IsLink(nsIURI** aURI) const
{
return IsHTMLLink(aURI);
}
void
nsHTMLAnchorElement::GetLinkTarget(nsAString& aTarget)
{
GetTarget(aTarget);
}
NS_IMETHODIMP
nsHTMLAnchorElement::GetTarget(nsAString& aValue)
{

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

@ -88,6 +88,8 @@ public:
NS_IMETHOD LinkRemoved() { return NS_OK; }
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual PRBool IsLink(nsIURI** aURI) const;
virtual void GetLinkTarget(nsAString& aTarget);
virtual void SetFocus(nsPresContext* aPresContext);
@ -174,6 +176,18 @@ nsHTMLAreaElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
return PostHandleEventForAnchors(aVisitor);
}
PRBool
nsHTMLAreaElement::IsLink(nsIURI** aURI) const
{
return IsHTMLLink(aURI);
}
void
nsHTMLAreaElement::GetLinkTarget(nsAString& aTarget)
{
GetTarget(aTarget);
}
void
nsHTMLAreaElement::SetFocus(nsPresContext* aPresContext)
{

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

@ -108,6 +108,8 @@ public:
PRBool aNotify);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual PRBool IsLink(nsIURI** aURI) const;
virtual void GetLinkTarget(nsAString& aTarget);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
@ -329,6 +331,20 @@ nsHTMLLinkElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
return PostHandleEventForAnchors(aVisitor);
}
PRBool
nsHTMLLinkElement::IsLink(nsIURI** aURI) const
{
return IsHTMLLink(aURI);
}
void
nsHTMLLinkElement::GetLinkTarget(nsAString& aTarget)
{
if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, aTarget)) {
GetBaseTarget(aTarget);
}
}
NS_IMETHODIMP
nsHTMLLinkElement::GetLinkState(nsLinkState &aState)
{

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

@ -37,38 +37,12 @@
* ***** END LICENSE BLOCK ***** */
#include "nsXMLElement.h"
#include "nsLayoutAtoms.h"
#include "nsIDocument.h"
#include "nsIAtom.h"
#include "nsNetUtil.h"
#include "nsIEventListenerManager.h"
#include "nsIDocShell.h"
#include "nsIEventStateManager.h"
#include "nsIDOMEvent.h"
#include "nsINameSpaceManager.h"
#include "nsINodeInfo.h"
#include "nsIURL.h"
#include "nsIIOService.h"
#include "nsNetCID.h"
#include "nsIServiceManager.h"
#include "nsXPIDLString.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIScriptSecurityManager.h"
#include "nsIRefreshURI.h"
#include "nsStyleConsts.h"
#include "nsIPresShell.h"
#include "nsGUIEvent.h"
#include "nsPresContext.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsIDOMViewCSS.h"
#include "nsIXBLService.h"
#include "nsIBindingManager.h"
#include "nsEventDispatcher.h"
#include "nsContentErrors.h"
static nsIContent::AttrValuesArray strings[] =
{&nsGkAtoms::_new, &nsGkAtoms::replace, &nsGkAtoms::embed, nsnull};
#include "nsIDocument.h"
nsresult
NS_NewXMLElement(nsIContent** aInstancePtrResult, nsINodeInfo *aNodeInfo)
@ -84,12 +58,7 @@ NS_NewXMLElement(nsIContent** aInstancePtrResult, nsINodeInfo *aNodeInfo)
}
nsXMLElement::nsXMLElement(nsINodeInfo *aNodeInfo)
: nsGenericElement(aNodeInfo),
mIsLink(PR_FALSE)
{
}
nsXMLElement::~nsXMLElement()
: nsGenericElement(aNodeInfo)
{
}
@ -132,24 +101,6 @@ nsXMLElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_IMPL_ADDREF_INHERITED(nsXMLElement, nsGenericElement)
NS_IMPL_RELEASE_INHERITED(nsXMLElement, nsGenericElement)
nsresult
nsXMLElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, PRBool aNotify)
{
if (aNameSpaceID == kNameSpaceID_XLink && aName == nsGkAtoms::type) {
// NOTE: This really is a link according to the XLink spec,
// we do not need to check other attributes. If there
// is no href attribute, then this link is simply
// untraversible [XLink 3.2].
mIsLink = aValue.EqualsLiteral("simple");
// We will check for actuate="onLoad" in MaybeTriggerAutoLink
}
return nsGenericElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
aNotify);
}
static nsresult
DocShellToPresContext(nsIDocShell *aShell, nsPresContext **aPresContext)
@ -164,26 +115,10 @@ DocShellToPresContext(nsIDocShell *aShell, nsPresContext **aPresContext)
return ds->GetPresContext(aPresContext);
}
static inline
nsresult SpecialAutoLoadReturn(nsresult aRv, nsLinkVerb aVerb)
nsresult
nsXMLElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
if (NS_SUCCEEDED(aRv)) {
switch(aVerb) {
case eLinkVerb_Embed:
aRv = NS_XML_AUTOLINK_EMBED;
break;
case eLinkVerb_New:
aRv = NS_XML_AUTOLINK_NEW;
break;
case eLinkVerb_Replace:
aRv = NS_XML_AUTOLINK_REPLACE;
break;
default:
aRv = NS_XML_AUTOLINK_UNDEFINED;
break;
}
}
return aRv;
return PostHandleEventForLinks(aVisitor);
}
NS_IMETHODIMP
@ -191,184 +126,73 @@ nsXMLElement::MaybeTriggerAutoLink(nsIDocShell *aShell)
{
NS_ENSURE_ARG_POINTER(aShell);
nsresult rv = NS_OK;
if (mIsLink) {
do {
// actuate="onLoad" ?
if (AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::actuate,
nsGkAtoms::onLoad, eCaseMatters)) {
// Disable in Mail/News for now. We may want a pref to control
// this at some point.
nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(aShell));
if (docShellItem) {
nsCOMPtr<nsIDocShellTreeItem> rootItem;
docShellItem->GetRootTreeItem(getter_AddRefs(rootItem));
nsCOMPtr<nsIDocShell> docshell(do_QueryInterface(rootItem));
if (docshell) {
PRUint32 appType;
if (NS_SUCCEEDED(docshell->GetAppType(&appType)) &&
appType == nsIDocShell::APP_TYPE_MAIL) {
return NS_OK;
}
}
}
// show= ?
nsLinkVerb verb = eLinkVerb_Undefined; // basically means same as replace
PRBool stop = PR_FALSE;
// XXX Should probably do this using atoms
switch (FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show,
strings, eCaseMatters)) {
// We should just act like an HTML link with target="_blank" and if
// someone diverts or blocks those, that's fine with us. We don't
// care.
case 0: verb = eLinkVerb_New; break;
// We want to actually stop processing the current document now.
// We do this by returning the correct value so that the one
// that called us knows to stop processing.
case 1: verb = eLinkVerb_Replace; break;
// XXX TODO
case 2: stop = PR_TRUE; break;
}
if (stop)
break;
// Get our URI
nsCOMPtr<nsIURI> uri = nsContentUtils::GetXLinkURI(this);
if (!uri)
break;
nsCOMPtr<nsPresContext> pc;
rv = DocShellToPresContext(aShell, getter_AddRefs(pc));
if (NS_SUCCEEDED(rv)) {
rv = TriggerLink(pc, verb, uri, EmptyString(), PR_TRUE, PR_FALSE);
return SpecialAutoLoadReturn(rv,verb);
}
}
} while (0);
// We require an xlink:href, xlink:type="simple" and xlink:actuate="onLoad"
// XXX: as of XLink 1.1, elements will be links even without xlink:type set
if (!HasAttr(kNameSpaceID_XLink, nsGkAtoms::href) ||
!AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
nsGkAtoms::simple, eCaseMatters) ||
!AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::actuate,
nsGkAtoms::onLoad, eCaseMatters)) {
return NS_OK;
}
return rv;
}
nsresult
nsXMLElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
nsresult rv = NS_OK;
if (mIsLink && nsEventStatus_eIgnore == aVisitor.mEventStatus) {
switch (aVisitor.mEvent->message) {
case NS_MOUSE_BUTTON_DOWN:
{
if (aVisitor.mPresContext &&
aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT) {
if (NS_STATIC_CAST(nsMouseEvent*, aVisitor.mEvent)->button ==
nsMouseEvent::eLeftButton) {
aVisitor.mPresContext->EventStateManager()->
SetContentState(this, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS);
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
} else if (NS_STATIC_CAST(nsMouseEvent*, aVisitor.mEvent)->button ==
nsMouseEvent::eRightButton) {
// XXX Bring up a contextual menu provided by the application
}
}
// Disable in Mail/News for now. We may want a pref to control
// this at some point.
nsCOMPtr<nsIDocShellTreeItem> docShellItem = do_QueryInterface(aShell);
if (docShellItem) {
nsCOMPtr<nsIDocShellTreeItem> rootItem;
docShellItem->GetRootTreeItem(getter_AddRefs(rootItem));
nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(rootItem);
if (docshell) {
PRUint32 appType;
if (NS_SUCCEEDED(docshell->GetAppType(&appType)) &&
appType == nsIDocShell::APP_TYPE_MAIL) {
return NS_OK;
}
break;
case NS_MOUSE_CLICK:
{
if (nsEventStatus_eConsumeNoDefault != aVisitor.mEventStatus &&
aVisitor.mPresContext && NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
nsInputEvent* inputEvent =
NS_STATIC_CAST(nsInputEvent*, aVisitor.mEvent);
if (inputEvent->isControl || inputEvent->isMeta ||
inputEvent->isAlt || inputEvent->isShift) {
break; // let the click go through so we can handle it in JS/XUL
}
nsAutoString href;
nsLinkVerb verb = eLinkVerb_Undefined; // basically means same as replace
nsCOMPtr<nsIURI> uri = nsContentUtils::GetXLinkURI(this);
if (!uri) {
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
break;
}
// XXX Should probably do this using atoms
switch (FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show,
strings, eCaseMatters)) {
case 0: verb = eLinkVerb_New; break;
case 1: verb = eLinkVerb_Replace; break;
case 2: verb = eLinkVerb_Embed; break;
}
nsAutoString target;
GetAttr(kNameSpaceID_XLink, nsGkAtoms::_moz_target, target);
rv = TriggerLink(aVisitor.mPresContext, verb, uri,
target, PR_TRUE, PR_TRUE);
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
}
}
break;
case NS_KEY_PRESS:
if (aVisitor.mEvent->eventStructType == NS_KEY_EVENT) {
nsKeyEvent* keyEvent = NS_STATIC_CAST(nsKeyEvent*, aVisitor.mEvent);
if (keyEvent->keyCode == NS_VK_RETURN) {
nsEventStatus status = nsEventStatus_eIgnore;
rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this,
PR_FALSE, &status);
if (NS_SUCCEEDED(rv)) {
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
}
break;
case NS_MOUSE_ENTER_SYNTH:
{
if (aVisitor.mPresContext) {
nsCOMPtr<nsIURI> uri = nsContentUtils::GetXLinkURI(this);
if (!uri) {
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
break;
}
rv = TriggerLink(aVisitor.mPresContext, eLinkVerb_Replace, uri,
EmptyString(), PR_FALSE, PR_TRUE);
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
}
}
break;
// XXX this doesn't seem to do anything yet
case NS_MOUSE_EXIT_SYNTH:
{
if (aVisitor.mPresContext) {
rv = LeaveLink(aVisitor.mPresContext);
aVisitor.mEventStatus = nsEventStatus_eConsumeDoDefault;
}
}
break;
default:
break;
}
}
return rv;
// Get absolute URI
nsCOMPtr<nsIURI> absURI;
nsAutoString href;
GetAttr(kNameSpaceID_XLink, nsGkAtoms::href, href);
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(absURI), href,
GetOwnerDoc(), baseURI);
if (!absURI) {
return NS_OK;
}
// Check that the link's URI isn't the same as its document's URI, or else
// we'll recursively load the document forever (possibly in new windows!)
PRBool isDocURI;
absURI->Equals(GetOwnerDoc()->GetDocumentURI(), &isDocURI);
if (isDocURI) {
return NS_OK;
}
// Get target
nsAutoString target;
nsresult special_rv = GetLinkTargetAndAutoType(target);
// Ignore this link if xlink:show has a value we don't implement
if (NS_FAILED(special_rv)) return NS_OK;
// Attempt to load the URI
nsCOMPtr<nsPresContext> pc;
nsresult rv = DocShellToPresContext(aShell, getter_AddRefs(pc));
NS_ENSURE_SUCCESS(rv, rv);
rv = TriggerLink(pc, absURI, target, PR_TRUE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
return special_rv; // return GetLinkTargetAndAutoType's special rv!
}
PRBool
nsXMLElement::IsFocusable(PRInt32 *aTabIndex)
{
nsCOMPtr<nsIURI> linkURI = nsContentUtils::GetLinkURI(this);
if (linkURI) {
nsCOMPtr<nsIURI> absURI;
if (IsLink(getter_AddRefs(absURI))) {
if (aTabIndex) {
*aTabIndex = ((sTabFocusModel & eTabFocus_linksMask) == 0 ? -1 : 0);
}
@ -382,5 +206,84 @@ nsXMLElement::IsFocusable(PRInt32 *aTabIndex)
return PR_FALSE;
}
PRBool
nsXMLElement::IsLink(nsIURI** aURI) const
{
NS_PRECONDITION(aURI, "Must provide aURI out param");
// To be an XLink for styling and interaction purposes, we require:
//
// xlink:href - must be set
// xlink:type - must be set to "simple"
// xlink:_moz_target - must be set, OR
// xlink:show - must be unset or set to "", "new" or "replace"
// xlink:actuate - must be unset or set to "" or "onRequest"
//
// For any other values, we're either not a *clickable* XLink, or the end
// result is poorly specified. Either way, we return PR_FALSE.
static nsIContent::AttrValuesArray sShowVals[] =
{ &nsGkAtoms::_empty, &nsGkAtoms::_new, &nsGkAtoms::replace, nsnull };
static nsIContent::AttrValuesArray sActuateVals[] =
{ &nsGkAtoms::_empty, &nsGkAtoms::onRequest, nsnull };
// Optimization: check for href first for early return
const nsAttrValue* href = mAttrsAndChildren.GetAttr(nsGkAtoms::href,
kNameSpaceID_XLink);
if (href &&
AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
nsGkAtoms::simple, eCaseMatters) &&
(HasAttr(kNameSpaceID_XLink, nsGkAtoms::_moz_target) ||
FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show,
sShowVals, eCaseMatters) !=
nsIContent::ATTR_VALUE_NO_MATCH) &&
FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::actuate,
sActuateVals, eCaseMatters) !=
nsIContent::ATTR_VALUE_NO_MATCH) {
// Get absolute URI
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsContentUtils::NewURIWithDocumentCharset(aURI, href->GetStringValue(),
GetOwnerDoc(), baseURI);
return !!*aURI; // must promise out param is non-null if we return true
}
*aURI = nsnull;
return PR_FALSE;
}
void
nsXMLElement::GetLinkTarget(nsAString& aTarget)
{
GetLinkTargetAndAutoType(aTarget);
}
nsresult
nsXMLElement::GetLinkTargetAndAutoType(nsAString& aTarget)
{
// Mozilla extension xlink:_moz_target overrides xlink:show
if (GetAttr(kNameSpaceID_XLink, nsGkAtoms::_moz_target, aTarget)) {
return aTarget.IsEmpty() ? NS_XML_AUTOLINK_REPLACE : NS_OK;
}
// Try xlink:show if no xlink:_moz_target
GetAttr(kNameSpaceID_XLink, nsGkAtoms::show, aTarget);
if (aTarget.IsEmpty()) {
return NS_XML_AUTOLINK_UNDEFINED;
}
if (aTarget.EqualsLiteral("new")) {
aTarget.AssignLiteral("_blank");
return NS_XML_AUTOLINK_NEW;
}
if (aTarget.EqualsLiteral("replace")) {
aTarget.Truncate();
return NS_XML_AUTOLINK_REPLACE;
}
// xlink:show="embed" isn't handled by this code path
aTarget.Truncate();
return NS_ERROR_FAILURE;
}
NS_IMPL_ELEMENT_CLONE(nsXMLElement)

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

@ -39,14 +39,10 @@
#ifndef nsXMLElement_h___
#define nsXMLElement_h___
#include "nsCOMPtr.h"
#include "nsIDOMElement.h"
#include "nsIDOMEventReceiver.h"
#include "nsIXMLContent.h"
#include "nsGenericElement.h"
class nsIEventListenerManager;
class nsIURI;
class nsIDocShell;
class nsXMLElement : public nsGenericElement,
@ -54,7 +50,6 @@ class nsXMLElement : public nsGenericElement,
{
public:
nsXMLElement(nsINodeInfo *aNodeInfo);
virtual ~nsXMLElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
@ -65,25 +60,22 @@ public:
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT(nsGenericElement::)
// nsINode interface methods
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
// nsIXMLContent
NS_IMETHOD MaybeTriggerAutoLink(nsIDocShell *aShell);
// nsIContent
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual PRBool IsLink(nsIURI** aURI) const;
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
// nsGenericElement specializations
virtual void GetLinkTarget(nsAString& aTarget);
protected:
PRBool mIsLink;
// Get target plus a special rv for MaybeTriggerAutoLink's caller
nsresult GetLinkTargetAndAutoType(nsAString& aTarget);
};
#endif // nsXMLElement_h___

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

@ -714,7 +714,7 @@ nsWebShell::SetRendering(PRBool aRender)
class OnLinkClickEvent : public nsRunnable {
public:
OnLinkClickEvent(nsWebShell* aHandler, nsIContent* aContent,
nsLinkVerb aVerb, nsIURI* aURI,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream = 0,
nsIInputStream* aHeadersDataStream = 0);
@ -723,7 +723,7 @@ public:
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mHandler->mScriptGlobal));
nsAutoPopupStatePusher popupStatePusher(window, mPopupState);
mHandler->OnLinkClickSync(mContent, mVerb, mURI,
mHandler->OnLinkClickSync(mContent, mURI,
mTargetSpec.get(), mPostDataStream,
mHeadersDataStream,
nsnull, nsnull);
@ -737,13 +737,11 @@ private:
nsCOMPtr<nsIInputStream> mPostDataStream;
nsCOMPtr<nsIInputStream> mHeadersDataStream;
nsCOMPtr<nsIContent> mContent;
nsLinkVerb mVerb;
PopupControlState mPopupState;
};
OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
nsIContent *aContent,
nsLinkVerb aVerb,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream,
@ -754,7 +752,6 @@ OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
, mPostDataStream(aPostDataStream)
, mHeadersDataStream(aHeadersDataStream)
, mContent(aContent)
, mVerb(aVerb)
{
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mHandler->mScriptGlobal));
@ -765,7 +762,6 @@ OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
NS_IMETHODIMP
nsWebShell::OnLinkClick(nsIContent* aContent,
nsLinkVerb aVerb,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream,
@ -773,14 +769,13 @@ nsWebShell::OnLinkClick(nsIContent* aContent,
{
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
nsCOMPtr<nsIRunnable> ev =
new OnLinkClickEvent(this, aContent, aVerb, aURI, aTargetSpec,
new OnLinkClickEvent(this, aContent, aURI, aTargetSpec,
aPostDataStream, aHeadersDataStream);
return NS_DispatchToCurrentThread(ev);
}
NS_IMETHODIMP
nsWebShell::OnLinkClickSync(nsIContent *aContent,
nsLinkVerb aVerb,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream,
@ -867,39 +862,21 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent,
anchor->GetType(typeHint);
}
switch(aVerb) {
case eLinkVerb_New:
NS_ASSERTION(target.IsEmpty(), "Losing window name information");
target.AssignLiteral("_blank");
// Fall into replace case
case eLinkVerb_Undefined:
// Fall through, this seems like the most reasonable action
case eLinkVerb_Replace:
{
rv = InternalLoad(aURI, // New URI
referer, // Referer URI
nsnull, // No onwer
INTERNAL_LOAD_FLAGS_INHERIT_OWNER, // Inherit owner from document
target.get(), // Window target
NS_LossyConvertUTF16toASCII(typeHint).get(),
aPostDataStream, // Post data stream
aHeadersDataStream, // Headers stream
LOAD_LINK, // Load type
nsnull, // No SHEntry
PR_TRUE, // first party site
aDocShell, // DocShell out-param
aRequest); // Request out-param
if (NS_SUCCEEDED(rv)) {
DispatchPings(aContent, referer);
}
}
break;
case eLinkVerb_Embed:
// XXX TODO Should be similar to the HTML IMG ALT attribute handling
// in NS 4.x
default:
NS_ABORT_IF_FALSE(0,"unexpected link verb");
rv = NS_ERROR_UNEXPECTED;
rv = InternalLoad(aURI, // New URI
referer, // Referer URI
nsnull, // No onwer
INTERNAL_LOAD_FLAGS_INHERIT_OWNER, // Inherit owner from document
target.get(), // Window target
NS_LossyConvertUTF16toASCII(typeHint).get(),
aPostDataStream, // Post data stream
aHeadersDataStream, // Headers stream
LOAD_LINK, // Load type
nsnull, // No SHEntry
PR_TRUE, // first party site
aDocShell, // DocShell out-param
aRequest); // Request out-param
if (NS_SUCCEEDED(rv)) {
DispatchPings(aContent, referer);
}
return rv;
}

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

@ -81,13 +81,11 @@ public:
// nsILinkHandler
NS_IMETHOD OnLinkClick(nsIContent* aContent,
nsLinkVerb aVerb,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream = 0,
nsIInputStream* aHeadersDataStream = 0);
NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
nsLinkVerb aVerb,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream = 0,

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

@ -1842,8 +1842,8 @@ END_COM_MAP()
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMElement));
lh->OnLinkClick(content, eLinkVerb_Replace,
uri, szTargetFrame ? szTargetFrame : mUseTarget);
lh->OnLinkClick(content, uri,
szTargetFrame ? szTargetFrame : mUseTarget);
}
}
hr = S_OK;

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

@ -432,9 +432,7 @@ nsIsIndexFrame::OnSubmit(nsPresContext* aPresContext)
// Now pass on absolute url to the click handler
if (handler) {
handler->OnLinkClick(mContent, eLinkVerb_Replace,
uri,
nsnull, nsnull);
handler->OnLinkClick(mContent, uri, nsnull);
}
return result;
}

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

@ -1461,8 +1461,7 @@ nsImageFrame::TriggerLink(nsPresContext* aPresContext,
// Only pass off the click event if the script security manager
// says it's ok.
if (NS_SUCCEEDED(rv))
handler->OnLinkClick(mContent, eLinkVerb_Replace, aURI,
aTargetSpec.get());
handler->OnLinkClick(mContent, aURI, aTargetSpec.get());
}
else {
handler->OnOverLink(mContent, aURI, aTargetSpec.get());

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

@ -1792,8 +1792,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarge
nsContentUtils::GetIntPref("privacy.popups.disable_from_plugins");
nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups);
rv = lh->OnLinkClick(mContent, eLinkVerb_Replace,
uri, unitarget.get(),
rv = lh->OnLinkClick(mContent, uri, unitarget.get(),
postDataStream, headersDataStream);
return rv;

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

@ -740,8 +740,7 @@ RuleProcessorData::RuleProcessorData(nsPresContext* aPresContext,
mContentID = nsnull;
mHasAttributes = PR_FALSE;
mIsHTMLContent = PR_FALSE;
mIsHTMLLink = PR_FALSE;
mIsSimpleXLink = PR_FALSE;
mIsLink = PR_FALSE;
mLinkState = eLinkState_Unknown;
mEventState = 0;
mNameSpaceID = kNameSpaceID_Unknown;
@ -791,17 +790,17 @@ RuleProcessorData::RuleProcessorData(nsPresContext* aPresContext,
if (mIsHTMLContent && mHasAttributes) {
// check if it is an HTML Link
if(nsStyleUtil::IsHTMLLink(aContent, mContentTag, mPresContext, &mLinkState)) {
mIsHTMLLink = PR_TRUE;
mIsLink = PR_TRUE;
}
}
// if not an HTML link, check for a simple xlink (cannot be both HTML link and xlink)
// NOTE: optimization: cannot be an XLink if no attributes (since it needs an
if(!mIsHTMLLink &&
if(!mIsLink &&
mHasAttributes &&
!(mIsHTMLContent || aContent->IsNodeOfType(nsINode::eXUL)) &&
nsStyleUtil::IsSimpleXlink(aContent, mPresContext, &mLinkState)) {
mIsSimpleXLink = PR_TRUE;
nsStyleUtil::IsLink(aContent, mPresContext, &mLinkState)) {
mIsLink = PR_TRUE;
}
}
}
@ -906,7 +905,7 @@ inline PRBool IsLinkPseudo(nsIAtom* aAtom)
// Return whether we should apply a "global" (i.e., universal-tag)
// selector for event states in quirks mode. Note that
// |data.mIsHTMLLink| is checked separately by the caller, so we return
// |data.mIsLink| is checked separately by the caller, so we return
// false for |nsGkAtoms::a|, which here means a named anchor.
inline PRBool IsQuirkEventSensitive(nsIAtom *aContentTag)
{
@ -1175,7 +1174,7 @@ static PRBool SelectorMatches(RuleProcessorData &data,
stateToCheck = NS_EVENT_STATE_URLTARGET;
}
else if (IsLinkPseudo(pseudoClass->mAtom)) {
if (data.mIsHTMLLink || data.mIsSimpleXLink) {
if (data.mIsLink) {
if (nsCSSPseudoClasses::mozAnyLink == pseudoClass->mAtom) {
result = PR_TRUE;
}
@ -1185,8 +1184,7 @@ static PRBool SelectorMatches(RuleProcessorData &data,
"somebody changed IsLinkPseudo");
NS_ASSERTION(data.mLinkState == eLinkState_Unvisited ||
data.mLinkState == eLinkState_Visited,
"unexpected link state for "
"mIsHTMLLink || mIsSimpleXLink");
"unexpected link state for mIsLink");
if (aStateMask & NS_EVENT_STATE_VISITED) {
result = PR_TRUE;
if (aDependence)
@ -1276,7 +1274,7 @@ static PRBool SelectorMatches(RuleProcessorData &data,
// (unnegated)). This at least makes it closer to the spec.
!isNegated &&
// important for |IsQuirkEventSensitive|:
data.mIsHTMLContent && !data.mIsHTMLLink &&
data.mIsHTMLContent && !data.mIsLink &&
!IsQuirkEventSensitive(data.mContentTag)) {
// In quirks mode, only make certain elements sensitive to
// selectors ":hover" and ":active".

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

@ -442,7 +442,7 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
// if we have anchor colors, check if this is an anchor with an href
if (tag == nsGkAtoms::a) {
if (mLinkRule || mVisitedRule || mActiveRule) {
if (aData->mIsHTMLLink) {
if (aData->mIsLink) {
switch (aData->mLinkState) {
case eLinkState_Unvisited:
if (mLinkRule)
@ -519,7 +519,7 @@ nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData,
{
if (aData->mContent &&
aData->mIsHTMLContent &&
aData->mIsHTMLLink &&
aData->mIsLink &&
aData->mContentTag == nsGkAtoms::a &&
((mActiveRule && (aData->mStateMask & NS_EVENT_STATE_ACTIVE)) ||
(mLinkRule && (aData->mStateMask & NS_EVENT_STATE_VISITED)) ||

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

@ -91,10 +91,9 @@ struct RuleProcessorData {
nsIAtom* mContentTag; // if content, then content->GetTag()
nsIAtom* mContentID; // if styled content, then weak reference to styledcontent->GetID()
PRPackedBool mIsHTMLContent; // if content, then does QI on HTMLContent, true or false
PRPackedBool mIsHTMLLink; // if content, calls nsStyleUtil::IsHTMLLink
PRPackedBool mIsSimpleXLink; // if content, calls nsStyleUtil::IsSimpleXLink
nsCompatibility mCompatMode; // Possibly remove use of this in SelectorMatches?
PRPackedBool mIsLink; // if content, calls nsStyleUtil::IsHTMLLink or nsStyleUtil::IsLink
PRPackedBool mHasAttributes; // if content, content->GetAttrCount() > 0
nsCompatibility mCompatMode; // Possibly remove use of this in SelectorMatches?
nsLinkState mLinkState; // if a link, this is the state, otherwise unknown
PRInt32 mEventState; // if content, eventStateMgr->GetContentState()
PRInt32 mNameSpaceID; // if content, content->GetNameSapce()

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

@ -473,34 +473,33 @@ PRBool nsStyleUtil::IsHTMLLink(nsIContent *aContent, nsIAtom *aTag, nsPresContex
return result;
}
/*static*/
PRBool nsStyleUtil::IsSimpleXlink(nsIContent *aContent, nsPresContext *aPresContext, nsLinkState *aState)
/*static*/
PRBool nsStyleUtil::IsLink(nsIContent *aContent,
nsPresContext *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");
NS_ASSERTION(aContent && aState, "invalid call to IsLink 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) {
nsCOMPtr<nsIURI> absURI = nsContentUtils::GetXLinkURI(aContent);
if (absURI) {
nsILinkHandler *linkHandler = aPresContext->GetLinkHandler();
if (linkHandler) {
linkHandler->GetLinkState(absURI, *aState);
}
else {
// no link handler? then all links are unvisited
*aState = eLinkState_Unvisited;
}
aPresContext->Document()->AddStyleRelevantLink(aContent, absURI);
rv = PR_TRUE;
nsCOMPtr<nsIURI> absURI;
if (aContent->IsLink(getter_AddRefs(absURI))) {
nsILinkHandler *linkHandler = aPresContext->GetLinkHandler();
if (linkHandler) {
linkHandler->GetLinkState(absURI, *aState);
}
else {
// no link handler? then all links are unvisited
*aState = eLinkState_Unvisited;
}
aPresContext->Document()->AddStyleRelevantLink(aContent, absURI);
rv = PR_TRUE;
}
}
return rv;

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

@ -70,7 +70,7 @@ public:
static PRInt32 ConstrainFontWeight(PRInt32 aWeight);
static PRBool IsHTMLLink(nsIContent *aContent, nsIAtom *aTag, nsPresContext *aPresContext, nsLinkState *aState);
static PRBool IsSimpleXlink(nsIContent *aContent, nsPresContext *aPresContext, nsLinkState *aState);
static PRBool IsLink(nsIContent *aContent, nsPresContext *aPresContext, nsLinkState *aState);
static PRBool DashMatchCompare(const nsAString& aAttributeValue,
const nsAString& aSelectorValue,

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

@ -48,7 +48,7 @@ class nsGUIEvent;
// Interface ID for nsILinkHandler
#define NS_ILINKHANDLER_IID \
{ 0xa6cf905b, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
{ 0x514bc565, 0x8d38, 0x4dde,{0xb4, 0xeb, 0xe7, 0xb5, 0x01, 0x2b, 0xf4, 0x64}}
enum nsLinkState {
eLinkState_Unknown = 0,
@ -57,16 +57,6 @@ enum nsLinkState {
eLinkState_NotLink = 3
};
// XXX Verb to use for link actuation. These are the verbs specified
// in the current XLink draft. We may actually want to support more
// (especially for extended links).
enum nsLinkVerb {
eLinkVerb_Replace = 0,
eLinkVerb_New = 1,
eLinkVerb_Embed = 2,
eLinkVerb_Undefined = 3
};
/**
* Interface used for handling clicks on links
*/
@ -78,7 +68,6 @@ public:
* Process a click on a link.
*
* @param aContent the content for the frame that generated the trigger
* @param aVerb the verb to use when the link is triggered
* @param aURI a URI object that defines the destination for the link
* @param aTargetSpec indicates where the link is targeted (may be an empty
* string)
@ -86,7 +75,6 @@ public:
* @param aHeadersDataStream ???
*/
NS_IMETHOD OnLinkClick(nsIContent* aContent,
nsLinkVerb aVerb,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream = 0,
@ -99,7 +87,6 @@ public:
* through an event.
*
* @param aContent the content for the frame that generated the trigger
* @param aVerb the verb to use when the link is triggered
* @param aURI a URI obect that defines the destination for the link
* @param aTargetSpec indicates where the link is targeted (may be an empty
* string)
@ -109,7 +96,6 @@ public:
* @param aRequest the request that was opened
*/
NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
nsLinkVerb aVerb,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream = 0,