LCOV - code coverage report
Current view: top level - dom/html - HTMLAnchorElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 161 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 71 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/dom/HTMLAnchorElement.h"
       8             : 
       9             : #include "mozilla/dom/HTMLAnchorElementBinding.h"
      10             : #include "mozilla/EventDispatcher.h"
      11             : #include "mozilla/EventStates.h"
      12             : #include "mozilla/MemoryReporting.h"
      13             : #include "nsCOMPtr.h"
      14             : #include "nsContentUtils.h"
      15             : #include "nsGkAtoms.h"
      16             : #include "nsHTMLDNSPrefetch.h"
      17             : #include "nsAttrValueOrString.h"
      18             : #include "nsIDocument.h"
      19             : #include "nsIPresShell.h"
      20             : #include "nsPresContext.h"
      21             : #include "nsIURI.h"
      22             : 
      23           0 : NS_IMPL_NS_NEW_HTML_ELEMENT(Anchor)
      24             : 
      25             : namespace mozilla {
      26             : namespace dom {
      27             : 
      28             : #define ANCHOR_ELEMENT_FLAG_BIT(n_) NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
      29             : 
      30             : // Anchor element specific bits
      31             : enum {
      32             :   // Indicates that a DNS Prefetch has been requested from this Anchor elem
      33             :   HTML_ANCHOR_DNS_PREFETCH_REQUESTED =    ANCHOR_ELEMENT_FLAG_BIT(0),
      34             : 
      35             :   // Indicates that a DNS Prefetch was added to the deferral queue
      36             :   HTML_ANCHOR_DNS_PREFETCH_DEFERRED =     ANCHOR_ELEMENT_FLAG_BIT(1)
      37             : };
      38             : 
      39             : ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
      40             : 
      41             : #undef ANCHOR_ELEMENT_FLAG_BIT
      42             : 
      43             : // static
      44             : const DOMTokenListSupportedToken HTMLAnchorElement::sSupportedRelValues[] = {
      45             :   "noreferrer",
      46             :   "noopener",
      47             :   nullptr
      48             : };
      49             : 
      50           0 : HTMLAnchorElement::~HTMLAnchorElement()
      51             : {
      52           0 : }
      53             : 
      54             : bool
      55           0 : HTMLAnchorElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
      56             : {
      57           0 :   return HasAttr(kNameSpaceID_None, nsGkAtoms::href) ||
      58           0 :          nsGenericHTMLElement::IsInteractiveHTMLContent(aIgnoreTabindex);
      59             : }
      60             : 
      61           0 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLAnchorElement)
      62           0 :   NS_INTERFACE_TABLE_INHERITED(HTMLAnchorElement,
      63             :                                nsIDOMHTMLAnchorElement,
      64             :                                Link)
      65           0 : NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLElement)
      66             : 
      67           0 : NS_IMPL_ADDREF_INHERITED(HTMLAnchorElement, Element)
      68           0 : NS_IMPL_RELEASE_INHERITED(HTMLAnchorElement, Element)
      69             : 
      70             : NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLAnchorElement)
      71             : 
      72           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLAnchorElement,
      73             :                                                   nsGenericHTMLElement)
      74           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRelList)
      75           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      76             : 
      77           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLAnchorElement,
      78             :                                                 nsGenericHTMLElement)
      79           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRelList)
      80           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      81             : 
      82           0 : NS_IMPL_ELEMENT_CLONE(HTMLAnchorElement)
      83             : 
      84             : JSObject*
      85           0 : HTMLAnchorElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
      86             : {
      87           0 :   return HTMLAnchorElementBinding::Wrap(aCx, this, aGivenProto);
      88             : }
      89             : 
      90           0 : NS_IMPL_STRING_ATTR(HTMLAnchorElement, Charset, charset)
      91           0 : NS_IMPL_STRING_ATTR(HTMLAnchorElement, Coords, coords)
      92           0 : NS_IMPL_URI_ATTR(HTMLAnchorElement, Href, href)
      93           0 : NS_IMPL_STRING_ATTR(HTMLAnchorElement, Hreflang, hreflang)
      94           0 : NS_IMPL_STRING_ATTR(HTMLAnchorElement, Name, name)
      95           0 : NS_IMPL_STRING_ATTR(HTMLAnchorElement, Rel, rel)
      96           0 : NS_IMPL_STRING_ATTR(HTMLAnchorElement, Rev, rev)
      97           0 : NS_IMPL_STRING_ATTR(HTMLAnchorElement, Shape, shape)
      98           0 : NS_IMPL_STRING_ATTR(HTMLAnchorElement, Type, type)
      99           0 : NS_IMPL_STRING_ATTR(HTMLAnchorElement, Download, download)
     100             : 
     101             : int32_t
     102           0 : HTMLAnchorElement::TabIndexDefault()
     103             : {
     104           0 :   return 0;
     105             : }
     106             : 
     107             : bool
     108           0 : HTMLAnchorElement::Draggable() const
     109             : {
     110             :   // links can be dragged as long as there is an href and the
     111             :   // draggable attribute isn't false
     112           0 :   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
     113             :     // no href, so just use the same behavior as other elements
     114           0 :     return nsGenericHTMLElement::Draggable();
     115             :   }
     116             : 
     117           0 :   return !AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
     118           0 :                       nsGkAtoms::_false, eIgnoreCase);
     119             : }
     120             : 
     121             : void
     122           0 : HTMLAnchorElement::OnDNSPrefetchRequested()
     123             : {
     124           0 :   UnsetFlags(HTML_ANCHOR_DNS_PREFETCH_DEFERRED);
     125           0 :   SetFlags(HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
     126           0 : }
     127             : 
     128             : void
     129           0 : HTMLAnchorElement::OnDNSPrefetchDeferred()
     130             : {
     131           0 :   UnsetFlags(HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
     132           0 :   SetFlags(HTML_ANCHOR_DNS_PREFETCH_DEFERRED);
     133           0 : }
     134             : 
     135             : bool
     136           0 : HTMLAnchorElement::HasDeferredDNSPrefetchRequest()
     137             : {
     138           0 :   return HasFlag(HTML_ANCHOR_DNS_PREFETCH_DEFERRED);
     139             : }
     140             : 
     141             : nsresult
     142           0 : HTMLAnchorElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
     143             :                               nsIContent* aBindingParent,
     144             :                               bool aCompileEventHandlers)
     145             : {
     146           0 :   Link::ResetLinkState(false, Link::ElementHasHref());
     147             : 
     148           0 :   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
     149             :                                                  aBindingParent,
     150           0 :                                                  aCompileEventHandlers);
     151           0 :   NS_ENSURE_SUCCESS(rv, rv);
     152             : 
     153             :   // Prefetch links
     154           0 :   nsIDocument* doc = GetComposedDoc();
     155           0 :   if (doc) {
     156           0 :     doc->RegisterPendingLinkUpdate(this);
     157           0 :     TryDNSPrefetch();
     158             :   }
     159             : 
     160           0 :   return rv;
     161             : }
     162             : 
     163             : void
     164           0 : HTMLAnchorElement::UnbindFromTree(bool aDeep, bool aNullParent)
     165             : {
     166             :   // Cancel any DNS prefetches
     167             :   // Note: Must come before ResetLinkState.  If called after, it will recreate
     168             :   // mCachedURI based on data that is invalid - due to a call to GetHostname.
     169           0 :   CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
     170           0 :                     HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
     171             : 
     172             :   // If this link is ever reinserted into a document, it might
     173             :   // be under a different xml:base, so forget the cached state now.
     174           0 :   Link::ResetLinkState(false, Link::ElementHasHref());
     175             : 
     176           0 :   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
     177           0 : }
     178             : 
     179             : static bool
     180           0 : IsNodeInEditableRegion(nsINode* aNode)
     181             : {
     182           0 :   while (aNode) {
     183           0 :     if (aNode->IsEditable()) {
     184           0 :       return true;
     185             :     }
     186           0 :     aNode = aNode->GetParent();
     187             :   }
     188           0 :   return false;
     189             : }
     190             : 
     191             : bool
     192           0 : HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse,
     193             :                                    bool *aIsFocusable, int32_t *aTabIndex)
     194             : {
     195           0 :   if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
     196           0 :     return true;
     197             :   }
     198             : 
     199             :   // cannot focus links if there is no link handler
     200           0 :   nsIDocument* doc = GetComposedDoc();
     201           0 :   if (doc) {
     202           0 :     nsIPresShell* presShell = doc->GetShell();
     203           0 :     if (presShell) {
     204           0 :       nsPresContext* presContext = presShell->GetPresContext();
     205           0 :       if (presContext && !presContext->GetLinkHandler()) {
     206           0 :         *aIsFocusable = false;
     207           0 :         return false;
     208             :       }
     209             :     }
     210             :   }
     211             : 
     212             :   // Links that are in an editable region should never be focusable, even if
     213             :   // they are in a contenteditable="false" region.
     214           0 :   if (IsNodeInEditableRegion(this)) {
     215           0 :     if (aTabIndex) {
     216           0 :       *aTabIndex = -1;
     217             :     }
     218             : 
     219           0 :     *aIsFocusable = false;
     220             : 
     221           0 :     return true;
     222             :   }
     223             : 
     224           0 :   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
     225             :     // check whether we're actually a link
     226           0 :     if (!Link::HasURI()) {
     227             :       // Not tabbable or focusable without href (bug 17605), unless
     228             :       // forced to be via presence of nonnegative tabindex attribute
     229           0 :       if (aTabIndex) {
     230           0 :         *aTabIndex = -1;
     231             :       }
     232             : 
     233           0 :       *aIsFocusable = false;
     234             : 
     235           0 :       return false;
     236             :     }
     237             :   }
     238             : 
     239           0 :   if (aTabIndex && (sTabFocusModel & eTabFocus_linksMask) == 0) {
     240           0 :     *aTabIndex = -1;
     241             :   }
     242             : 
     243           0 :   *aIsFocusable = true;
     244             : 
     245           0 :   return false;
     246             : }
     247             : 
     248             : nsresult
     249           0 : HTMLAnchorElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
     250             : {
     251           0 :   return GetEventTargetParentForAnchors(aVisitor);
     252             : }
     253             : 
     254             : nsresult
     255           0 : HTMLAnchorElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
     256             : {
     257           0 :   return PostHandleEventForAnchors(aVisitor);
     258             : }
     259             : 
     260             : bool
     261           0 : HTMLAnchorElement::IsLink(nsIURI** aURI) const
     262             : {
     263           0 :   return IsHTMLLink(aURI);
     264             : }
     265             : 
     266             : void
     267           0 : HTMLAnchorElement::GetLinkTarget(nsAString& aTarget)
     268             : {
     269           0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::target, aTarget);
     270           0 :   if (aTarget.IsEmpty()) {
     271           0 :     GetBaseTarget(aTarget);
     272             :   }
     273           0 : }
     274             : 
     275             : NS_IMETHODIMP
     276           0 : HTMLAnchorElement::GetTarget(nsAString& aValue)
     277             : {
     278           0 :   if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue)) {
     279           0 :     GetBaseTarget(aValue);
     280             :   }
     281           0 :   return NS_OK;
     282             : }
     283             : 
     284             : NS_IMETHODIMP
     285           0 : HTMLAnchorElement::SetTarget(const nsAString& aValue)
     286             : {
     287           0 :   return SetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue, true);
     288             : }
     289             : 
     290             : nsDOMTokenList*
     291           0 : HTMLAnchorElement::RelList()
     292             : {
     293           0 :   if (!mRelList) {
     294           0 :     mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues);
     295             :   }
     296           0 :   return mRelList;
     297             : }
     298             : 
     299             : #define IMPL_URI_PART(_part)                                 \
     300             :   NS_IMETHODIMP                                              \
     301             :   HTMLAnchorElement::Get##_part(nsAString& a##_part)         \
     302             :   {                                                          \
     303             :     Link::Get##_part(a##_part);                              \
     304             :     return NS_OK;                                            \
     305             :   }                                                          \
     306             :   NS_IMETHODIMP                                              \
     307             :   HTMLAnchorElement::Set##_part(const nsAString& a##_part)   \
     308             :   {                                                          \
     309             :     Link::Set##_part(a##_part);                              \
     310             :     return NS_OK;                                            \
     311             :   }
     312             : 
     313           0 : IMPL_URI_PART(Protocol)
     314           0 : IMPL_URI_PART(Host)
     315           0 : IMPL_URI_PART(Hostname)
     316           0 : IMPL_URI_PART(Pathname)
     317           0 : IMPL_URI_PART(Search)
     318           0 : IMPL_URI_PART(Port)
     319           0 : IMPL_URI_PART(Hash)
     320             : 
     321             : #undef IMPL_URI_PART
     322             : 
     323             : NS_IMETHODIMP
     324           0 : HTMLAnchorElement::GetText(nsAString& aText)
     325             : {
     326           0 :   if(!nsContentUtils::GetNodeTextContent(this, true, aText, fallible)) {
     327           0 :     return NS_ERROR_OUT_OF_MEMORY;
     328             :   }
     329           0 :   return NS_OK;
     330             : }
     331             : 
     332             : NS_IMETHODIMP
     333           0 : HTMLAnchorElement::SetText(const nsAString& aText)
     334             : {
     335           0 :   return nsContentUtils::SetNodeTextContent(this, aText, false);
     336             : }
     337             : 
     338             : NS_IMETHODIMP
     339           0 : HTMLAnchorElement::ToString(nsAString& aSource)
     340             : {
     341           0 :   return GetHref(aSource);
     342             : }
     343             : 
     344             : NS_IMETHODIMP
     345           0 : HTMLAnchorElement::GetPing(nsAString& aValue)
     346             : {
     347           0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::ping, aValue);
     348           0 :   return NS_OK;
     349             : }
     350             : 
     351             : NS_IMETHODIMP
     352           0 : HTMLAnchorElement::SetPing(const nsAString& aValue)
     353             : {
     354           0 :   return SetAttr(kNameSpaceID_None, nsGkAtoms::ping, aValue, true);
     355             : }
     356             : 
     357             : already_AddRefed<nsIURI>
     358           0 : HTMLAnchorElement::GetHrefURI() const
     359             : {
     360           0 :   nsCOMPtr<nsIURI> uri = Link::GetCachedURI();
     361           0 :   if (uri) {
     362           0 :     return uri.forget();
     363             :   }
     364             : 
     365           0 :   return GetHrefURIForAnchors();
     366             : }
     367             : 
     368             : nsresult
     369           0 : HTMLAnchorElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
     370             :                                  const nsAttrValueOrString* aValue,
     371             :                                  bool aNotify)
     372             : {
     373           0 :   if (aNamespaceID == kNameSpaceID_None) {
     374           0 :     if (aName == nsGkAtoms::href) {
     375           0 :       CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
     376           0 :                         HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
     377             :     }
     378             :   }
     379             : 
     380           0 :   return nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, aValue,
     381           0 :                                              aNotify);
     382             : }
     383             : 
     384             : nsresult
     385           0 : HTMLAnchorElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
     386             :                                 const nsAttrValue* aValue,
     387             :                                 const nsAttrValue* aOldValue, bool aNotify)
     388             : {
     389           0 :   if (aNamespaceID == kNameSpaceID_None) {
     390           0 :     if (aName == nsGkAtoms::href) {
     391           0 :       Link::ResetLinkState(aNotify, !!aValue);
     392           0 :       if (aValue && IsInComposedDoc()) {
     393           0 :         TryDNSPrefetch();
     394             :       }
     395             :     }
     396             :   }
     397             : 
     398           0 :   return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName,
     399           0 :                                             aValue, aOldValue, aNotify);
     400             : }
     401             : 
     402             : EventStates
     403           0 : HTMLAnchorElement::IntrinsicState() const
     404             : {
     405           0 :   return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
     406             : }
     407             : 
     408             : size_t
     409           0 : HTMLAnchorElement::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
     410             : {
     411           0 :   return nsGenericHTMLElement::SizeOfExcludingThis(aMallocSizeOf) +
     412           0 :          Link::SizeOfExcludingThis(aMallocSizeOf);
     413             : }
     414             : 
     415             : } // namespace dom
     416             : } // namespace mozilla

Generated by: LCOV version 1.13