зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
2c7ea76e3c
Коммит
688f763168
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче