LCOV - code coverage report
Current view: directory - content/html/content/src - nsHTMLLinkElement.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 142 0 0.0 %
Date: 2012-06-02 Functions: 141 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : #include "nsIDOMHTMLLinkElement.h"
      38                 : #include "nsIDOMLinkStyle.h"
      39                 : #include "nsGenericHTMLElement.h"
      40                 : #include "nsILink.h"
      41                 : #include "nsGkAtoms.h"
      42                 : #include "nsStyleConsts.h"
      43                 : #include "nsIDOMStyleSheet.h"
      44                 : #include "nsIStyleSheet.h"
      45                 : #include "nsIStyleSheetLinkingElement.h"
      46                 : #include "nsStyleLinkElement.h"
      47                 : #include "nsReadableUtils.h"
      48                 : #include "nsUnicharUtils.h"
      49                 : #include "nsIURL.h"
      50                 : #include "nsNetUtil.h"
      51                 : #include "nsIDocument.h"
      52                 : #include "nsIDOMEvent.h"
      53                 : #include "nsIPrivateDOMEvent.h"
      54                 : #include "nsIDOMEventTarget.h"
      55                 : #include "nsContentUtils.h"
      56                 : #include "nsPIDOMWindow.h"
      57                 : #include "nsAsyncDOMEvent.h"
      58                 : 
      59                 : #include "Link.h"
      60                 : using namespace mozilla::dom;
      61                 : 
      62                 : class nsHTMLLinkElement : public nsGenericHTMLElement,
      63                 :                           public nsIDOMHTMLLinkElement,
      64                 :                           public nsILink,
      65                 :                           public nsStyleLinkElement,
      66                 :                           public Link
      67                 : {
      68                 : public:
      69                 :   nsHTMLLinkElement(already_AddRefed<nsINodeInfo> aNodeInfo);
      70                 :   virtual ~nsHTMLLinkElement();
      71                 : 
      72                 :   // nsISupports
      73                 :   NS_DECL_ISUPPORTS_INHERITED
      74                 : 
      75                 :   // nsIDOMNode
      76               0 :   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
      77                 : 
      78                 :   // nsIDOMElement
      79               0 :   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
      80                 : 
      81                 :   // nsIDOMHTMLElement
      82               0 :   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
      83                 : 
      84                 :   // nsIDOMHTMLLinkElement
      85                 :   NS_DECL_NSIDOMHTMLLINKELEMENT
      86                 : 
      87                 :   // DOM memory reporter participant
      88                 :   NS_DECL_SIZEOF_EXCLUDING_THIS
      89                 : 
      90                 :   // nsILink
      91                 :   NS_IMETHOD    LinkAdded();
      92                 :   NS_IMETHOD    LinkRemoved();
      93                 : 
      94                 :   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
      95                 :                               nsIContent* aBindingParent,
      96                 :                               bool aCompileEventHandlers);
      97                 :   virtual void UnbindFromTree(bool aDeep = true,
      98                 :                               bool aNullParent = true);
      99                 :   void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
     100                 :   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
     101                 :                    const nsAString& aValue, bool aNotify)
     102                 :   {
     103                 :     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
     104                 :   }
     105                 :   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
     106                 :                            nsIAtom* aPrefix, const nsAString& aValue,
     107                 :                            bool aNotify);
     108                 :   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
     109                 :                              bool aNotify);
     110                 : 
     111                 :   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
     112                 :   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
     113                 :   virtual bool IsLink(nsIURI** aURI) const;
     114                 :   virtual void GetLinkTarget(nsAString& aTarget);
     115                 :   virtual nsLinkState GetLinkState() const;
     116                 :   virtual already_AddRefed<nsIURI> GetHrefURI() const;
     117                 : 
     118                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
     119                 : 
     120                 :   virtual nsEventStates IntrinsicState() const;
     121                 : 
     122                 :   virtual nsXPCClassInfo* GetClassInfo();
     123                 : protected:
     124                 :   virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline);
     125                 :   virtual void GetStyleSheetInfo(nsAString& aTitle,
     126                 :                                  nsAString& aType,
     127                 :                                  nsAString& aMedia,
     128                 :                                  bool* aIsAlternate);
     129                 : };
     130                 : 
     131                 : 
     132               0 : NS_IMPL_NS_NEW_HTML_ELEMENT(Link)
     133                 : 
     134                 : 
     135               0 : nsHTMLLinkElement::nsHTMLLinkElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     136                 :   : nsGenericHTMLElement(aNodeInfo),
     137               0 :     Link(this)
     138                 : {
     139               0 : }
     140                 : 
     141               0 : nsHTMLLinkElement::~nsHTMLLinkElement()
     142                 : {
     143               0 : }
     144                 : 
     145                 : 
     146               0 : NS_IMPL_ADDREF_INHERITED(nsHTMLLinkElement, nsGenericElement) 
     147               0 : NS_IMPL_RELEASE_INHERITED(nsHTMLLinkElement, nsGenericElement) 
     148                 : 
     149                 : 
     150               0 : DOMCI_NODE_DATA(HTMLLinkElement, nsHTMLLinkElement)
     151                 : 
     152                 : // QueryInterface implementation for nsHTMLLinkElement
     153               0 : NS_INTERFACE_TABLE_HEAD(nsHTMLLinkElement)
     154               0 :   NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLLinkElement,
     155                 :                                    nsIDOMHTMLLinkElement,
     156                 :                                    nsIDOMLinkStyle,
     157                 :                                    nsILink,
     158                 :                                    nsIStyleSheetLinkingElement,
     159                 :                                    Link)
     160               0 :   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLLinkElement,
     161                 :                                                nsGenericHTMLElement)
     162               0 : NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLLinkElement)
     163                 : 
     164                 : 
     165               0 : NS_IMPL_ELEMENT_CLONE(nsHTMLLinkElement)
     166                 : 
     167                 : 
     168                 : NS_IMETHODIMP
     169               0 : nsHTMLLinkElement::GetDisabled(bool* aDisabled)
     170                 : {
     171               0 :   nsCOMPtr<nsIDOMStyleSheet> ss = do_QueryInterface(GetStyleSheet());
     172               0 :   nsresult result = NS_OK;
     173                 : 
     174               0 :   if (ss) {
     175               0 :     result = ss->GetDisabled(aDisabled);
     176                 :   } else {
     177               0 :     *aDisabled = false;
     178                 :   }
     179                 : 
     180               0 :   return result;
     181                 : }
     182                 : 
     183                 : NS_IMETHODIMP 
     184               0 : nsHTMLLinkElement::SetDisabled(bool aDisabled)
     185                 : {
     186               0 :   nsCOMPtr<nsIDOMStyleSheet> ss = do_QueryInterface(GetStyleSheet());
     187               0 :   nsresult result = NS_OK;
     188                 : 
     189               0 :   if (ss) {
     190               0 :     result = ss->SetDisabled(aDisabled);
     191                 :   }
     192                 : 
     193               0 :   return result;
     194                 : }
     195                 : 
     196                 : 
     197               0 : NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Charset, charset)
     198               0 : NS_IMPL_URI_ATTR(nsHTMLLinkElement, Href, href)
     199               0 : NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Hreflang, hreflang)
     200               0 : NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Media, media)
     201               0 : NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rel, rel)
     202               0 : NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rev, rev)
     203               0 : NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Target, target)
     204               0 : NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Type, type)
     205                 : 
     206                 : nsresult
     207               0 : nsHTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
     208                 :                               nsIContent* aBindingParent,
     209                 :                               bool aCompileEventHandlers)
     210                 : {
     211               0 :   Link::ResetLinkState(false);
     212                 : 
     213                 :   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
     214                 :                                                  aBindingParent,
     215               0 :                                                  aCompileEventHandlers);
     216               0 :   NS_ENSURE_SUCCESS(rv, rv);
     217                 :   
     218               0 :   if (aDocument) {
     219               0 :     aDocument->RegisterPendingLinkUpdate(this);
     220                 :   }
     221                 : 
     222               0 :   void (nsHTMLLinkElement::*update)() = &nsHTMLLinkElement::UpdateStyleSheetInternal;
     223               0 :   nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this, update));
     224                 : 
     225               0 :   CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMLinkAdded"));
     226                 : 
     227               0 :   return rv;
     228                 : }
     229                 : 
     230                 : NS_IMETHODIMP
     231               0 : nsHTMLLinkElement::LinkAdded()
     232                 : {
     233               0 :   CreateAndDispatchEvent(OwnerDoc(), NS_LITERAL_STRING("DOMLinkAdded"));
     234               0 :   return NS_OK;
     235                 : }
     236                 : 
     237                 : NS_IMETHODIMP
     238               0 : nsHTMLLinkElement::LinkRemoved()
     239                 : {
     240               0 :   CreateAndDispatchEvent(OwnerDoc(), NS_LITERAL_STRING("DOMLinkRemoved"));
     241               0 :   return NS_OK;
     242                 : }
     243                 : 
     244                 : void
     245               0 : nsHTMLLinkElement::UnbindFromTree(bool aDeep, bool aNullParent)
     246                 : {
     247                 :   // If this link is ever reinserted into a document, it might
     248                 :   // be under a different xml:base, so forget the cached state now.
     249               0 :   Link::ResetLinkState(false);
     250                 : 
     251                 :   // Once we have XPCOMGC we shouldn't need to call UnbindFromTree during Unlink
     252                 :   // and so this messy event dispatch can go away.
     253               0 :   nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
     254               0 :   if (oldDoc) {
     255               0 :     oldDoc->UnregisterPendingLinkUpdate(this);
     256                 :   }
     257               0 :   CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMLinkRemoved"));
     258               0 :   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
     259               0 :   UpdateStyleSheetInternal(oldDoc);
     260               0 : }
     261                 : 
     262                 : void
     263               0 : nsHTMLLinkElement::CreateAndDispatchEvent(nsIDocument* aDoc,
     264                 :                                           const nsAString& aEventName)
     265                 : {
     266               0 :   if (!aDoc)
     267               0 :     return;
     268                 : 
     269                 :   // In the unlikely case that both rev is specified *and* rel=stylesheet,
     270                 :   // this code will cause the event to fire, on the principle that maybe the
     271                 :   // page really does want to specify that its author is a stylesheet. Since
     272                 :   // this should never actually happen and the performance hit is minimal,
     273                 :   // doing the "right" thing costs virtually nothing here, even if it doesn't
     274                 :   // make much sense.
     275                 :   static nsIContent::AttrValuesArray strings[] =
     276                 :     {&nsGkAtoms::_empty, &nsGkAtoms::stylesheet, nsnull};
     277                 : 
     278               0 :   if (!nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None,
     279               0 :                                        nsGkAtoms::rev) &&
     280                 :       FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::rel,
     281               0 :                       strings, eIgnoreCase) != ATTR_VALUE_NO_MATCH)
     282               0 :     return;
     283                 : 
     284                 :   nsRefPtr<nsAsyncDOMEvent> event = new nsAsyncDOMEvent(this, aEventName, true,
     285               0 :                                                         true);
     286                 :   // Always run async in order to avoid running script when the content
     287                 :   // sink isn't expecting it.
     288               0 :   event->PostDOMEvent();
     289                 : }
     290                 : 
     291                 : nsresult
     292               0 : nsHTMLLinkElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
     293                 :                            nsIAtom* aPrefix, const nsAString& aValue,
     294                 :                            bool aNotify)
     295                 : {
     296                 :   nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
     297               0 :                                               aValue, aNotify);
     298                 : 
     299                 :   // The ordering of the parent class's SetAttr call and Link::ResetLinkState
     300                 :   // is important here!  The attribute is not set until SetAttr returns, and
     301                 :   // we will need the updated attribute value because notifying the document
     302                 :   // that content states have changed will call IntrinsicState, which will try
     303                 :   // to get updated information about the visitedness from Link.
     304               0 :   if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
     305               0 :     Link::ResetLinkState(!!aNotify);
     306                 :   }
     307                 : 
     308               0 :   if (NS_SUCCEEDED(rv)) {
     309               0 :     bool dropSheet = false;
     310               0 :     if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::rel &&
     311               0 :         GetStyleSheet()) {
     312               0 :       PRUint32 linkTypes = nsStyleLinkElement::ParseLinkTypes(aValue);
     313               0 :       dropSheet = !(linkTypes & STYLESHEET);          
     314                 :     }
     315                 :     
     316                 :     UpdateStyleSheetInternal(nsnull,
     317                 :                              dropSheet ||
     318                 :                              (aNameSpaceID == kNameSpaceID_None &&
     319                 :                               (aName == nsGkAtoms::title ||
     320                 :                                aName == nsGkAtoms::media ||
     321               0 :                                aName == nsGkAtoms::type)));
     322                 :   }
     323                 : 
     324               0 :   return rv;
     325                 : }
     326                 : 
     327                 : nsresult
     328               0 : nsHTMLLinkElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
     329                 :                              bool aNotify)
     330                 : {
     331                 :   nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute,
     332               0 :                                                 aNotify);
     333               0 :   if (NS_SUCCEEDED(rv)) {
     334                 :     UpdateStyleSheetInternal(nsnull,
     335                 :                              aNameSpaceID == kNameSpaceID_None &&
     336                 :                              (aAttribute == nsGkAtoms::rel ||
     337                 :                               aAttribute == nsGkAtoms::title ||
     338                 :                               aAttribute == nsGkAtoms::media ||
     339               0 :                               aAttribute == nsGkAtoms::type));
     340                 :   }
     341                 : 
     342                 :   // The ordering of the parent class's UnsetAttr call and Link::ResetLinkState
     343                 :   // is important here!  The attribute is not unset until UnsetAttr returns, and
     344                 :   // we will need the updated attribute value because notifying the document
     345                 :   // that content states have changed will call IntrinsicState, which will try
     346                 :   // to get updated information about the visitedness from Link.
     347               0 :   if (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
     348               0 :     Link::ResetLinkState(!!aNotify);
     349                 :   }
     350                 : 
     351               0 :   return rv;
     352                 : }
     353                 : 
     354                 : nsresult
     355               0 : nsHTMLLinkElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
     356                 : {
     357               0 :   return PreHandleEventForAnchors(aVisitor);
     358                 : }
     359                 : 
     360                 : nsresult
     361               0 : nsHTMLLinkElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
     362                 : {
     363               0 :   return PostHandleEventForAnchors(aVisitor);
     364                 : }
     365                 : 
     366                 : bool
     367               0 : nsHTMLLinkElement::IsLink(nsIURI** aURI) const
     368                 : {
     369               0 :   return IsHTMLLink(aURI);
     370                 : }
     371                 : 
     372                 : void
     373               0 : nsHTMLLinkElement::GetLinkTarget(nsAString& aTarget)
     374                 : {
     375               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::target, aTarget);
     376               0 :   if (aTarget.IsEmpty()) {
     377               0 :     GetBaseTarget(aTarget);
     378                 :   }
     379               0 : }
     380                 : 
     381                 : nsLinkState
     382               0 : nsHTMLLinkElement::GetLinkState() const
     383                 : {
     384               0 :   return Link::GetLinkState();
     385                 : }
     386                 : 
     387                 : already_AddRefed<nsIURI>
     388               0 : nsHTMLLinkElement::GetHrefURI() const
     389                 : {
     390               0 :   return GetHrefURIForAnchors();
     391                 : }
     392                 : 
     393                 : already_AddRefed<nsIURI>
     394               0 : nsHTMLLinkElement::GetStyleSheetURL(bool* aIsInline)
     395                 : {
     396               0 :   *aIsInline = false;
     397               0 :   nsAutoString href;
     398               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
     399               0 :   if (href.IsEmpty()) {
     400               0 :     return nsnull;
     401                 :   }
     402               0 :   return Link::GetURI();
     403                 : }
     404                 : 
     405                 : void
     406               0 : nsHTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
     407                 :                                      nsAString& aType,
     408                 :                                      nsAString& aMedia,
     409                 :                                      bool* aIsAlternate)
     410                 : {
     411               0 :   aTitle.Truncate();
     412               0 :   aType.Truncate();
     413               0 :   aMedia.Truncate();
     414               0 :   *aIsAlternate = false;
     415                 : 
     416               0 :   nsAutoString rel;
     417               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel);
     418               0 :   PRUint32 linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
     419                 :   // Is it a stylesheet link?
     420               0 :   if (!(linkTypes & STYLESHEET)) {
     421                 :     return;
     422                 :   }
     423                 : 
     424               0 :   nsAutoString title;
     425               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
     426               0 :   title.CompressWhitespace();
     427               0 :   aTitle.Assign(title);
     428                 : 
     429                 :   // If alternate, does it have title?
     430               0 :   if (linkTypes & ALTERNATE) {
     431               0 :     if (aTitle.IsEmpty()) { // alternates must have title
     432                 :       return;
     433                 :     } else {
     434               0 :       *aIsAlternate = true;
     435                 :     }
     436                 :   }
     437                 : 
     438               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia);
     439                 :   // The HTML5 spec is formulated in terms of the CSSOM spec, which specifies
     440                 :   // that media queries should be ASCII lowercased during serialization.
     441               0 :   nsContentUtils::ASCIIToLower(aMedia);
     442                 : 
     443               0 :   nsAutoString mimeType;
     444               0 :   nsAutoString notUsed;
     445               0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType);
     446               0 :   nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
     447               0 :   if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
     448                 :     return;
     449                 :   }
     450                 : 
     451                 :   // If we get here we assume that we're loading a css file, so set the
     452                 :   // type to 'text/css'
     453               0 :   aType.AssignLiteral("text/css");
     454                 : 
     455                 :   return;
     456                 : }
     457                 : 
     458                 : nsEventStates
     459               0 : nsHTMLLinkElement::IntrinsicState() const
     460                 : {
     461               0 :   return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
     462                 : }
     463                 : 
     464                 : size_t
     465               0 : nsHTMLLinkElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
     466                 : {
     467               0 :   return nsGenericHTMLElement::SizeOfExcludingThis(aMallocSizeOf) +
     468               0 :          Link::SizeOfExcludingThis(aMallocSizeOf);
     469                 : }
     470                 : 

Generated by: LCOV version 1.7