LCOV - code coverage report
Current view: top level - dom/html - HTMLSharedElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 31 148 20.9 %
Date: 2017-07-14 16:53:18 Functions: 8 25 32.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/HTMLSharedElement.h"
       8             : #include "mozilla/dom/HTMLBaseElementBinding.h"
       9             : #include "mozilla/dom/HTMLDirectoryElementBinding.h"
      10             : #include "mozilla/dom/HTMLHeadElementBinding.h"
      11             : #include "mozilla/dom/HTMLHtmlElementBinding.h"
      12             : #include "mozilla/dom/HTMLParamElementBinding.h"
      13             : #include "mozilla/dom/HTMLQuoteElementBinding.h"
      14             : 
      15             : #include "mozilla/GenericSpecifiedValuesInlines.h"
      16             : #include "nsAttrValueInlines.h"
      17             : #include "nsStyleConsts.h"
      18             : #include "nsMappedAttributes.h"
      19             : #include "nsContentUtils.h"
      20             : #include "nsIContentSecurityPolicy.h"
      21             : #include "nsIURI.h"
      22             : 
      23          28 : NS_IMPL_NS_NEW_HTML_ELEMENT(Shared)
      24             : 
      25             : namespace mozilla {
      26             : namespace dom {
      27             : 
      28             : extern nsAttrValue::EnumTable kListTypeTable[];
      29             : 
      30           0 : HTMLSharedElement::~HTMLSharedElement()
      31             : {
      32           0 : }
      33             : 
      34         173 : NS_IMPL_ADDREF_INHERITED(HTMLSharedElement, Element)
      35          98 : NS_IMPL_RELEASE_INHERITED(HTMLSharedElement, Element)
      36             : 
      37             : // QueryInterface implementation for HTMLSharedElement
      38          72 : NS_INTERFACE_MAP_BEGIN(HTMLSharedElement)
      39          72 :   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLBaseElement, base)
      40          72 :   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLDirectoryElement, dir)
      41          72 :   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLQuoteElement, q)
      42          72 :   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLQuoteElement, blockquote)
      43          72 :   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLHeadElement, head)
      44          72 :   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLHtmlElement, html)
      45          72 : NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
      46             : 
      47             : 
      48           0 : NS_IMPL_ELEMENT_CLONE(HTMLSharedElement)
      49             : 
      50             : // nsIDOMHTMLQuoteElement
      51           0 : NS_IMPL_URI_ATTR(HTMLSharedElement, Cite, cite)
      52             : 
      53             : // nsIDOMHTMLHeadElement
      54             : // Empty
      55             : 
      56             : // nsIDOMHTMLHtmlElement
      57           0 : NS_IMPL_STRING_ATTR(HTMLSharedElement, Version, version)
      58             : 
      59             : // nsIDOMHTMLBaseElement
      60           0 : NS_IMPL_STRING_ATTR(HTMLSharedElement, Target, target)
      61             : 
      62             : NS_IMETHODIMP
      63           0 : HTMLSharedElement::GetHref(nsAString& aValue)
      64             : {
      65           0 :   MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::base),
      66             :              "This should only get called for <base> elements");
      67           0 :   nsAutoString href;
      68           0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
      69             : 
      70           0 :   nsCOMPtr<nsIURI> uri;
      71           0 :   nsIDocument* doc = OwnerDoc();
      72           0 :   nsContentUtils::NewURIWithDocumentCharset(
      73           0 :     getter_AddRefs(uri), href, doc, doc->GetFallbackBaseURI());
      74             : 
      75           0 :   if (!uri) {
      76           0 :     aValue = href;
      77           0 :     return NS_OK;
      78             :   }
      79             : 
      80           0 :   nsAutoCString spec;
      81           0 :   uri->GetSpec(spec);
      82           0 :   CopyUTF8toUTF16(spec, aValue);
      83             : 
      84           0 :   return NS_OK;
      85             : }
      86             : 
      87             : NS_IMETHODIMP
      88           0 : HTMLSharedElement::SetHref(const nsAString& aValue)
      89             : {
      90           0 :   return SetAttrHelper(nsGkAtoms::href, aValue);
      91             : }
      92             : 
      93             : 
      94             : bool
      95           1 : HTMLSharedElement::ParseAttribute(int32_t aNamespaceID,
      96             :                                   nsIAtom* aAttribute,
      97             :                                   const nsAString& aValue,
      98             :                                   nsAttrValue& aResult)
      99             : {
     100           2 :   if (aNamespaceID == kNameSpaceID_None &&
     101           1 :       mNodeInfo->Equals(nsGkAtoms::dir)) {
     102           0 :     if (aAttribute == nsGkAtoms::type) {
     103           0 :       return aResult.ParseEnumValue(aValue, mozilla::dom::kListTypeTable, false);
     104             :     }
     105           0 :     if (aAttribute == nsGkAtoms::start) {
     106           0 :       return aResult.ParseIntWithBounds(aValue, 1);
     107             :     }
     108             :   }
     109             : 
     110           1 :   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
     111           1 :                                               aResult);
     112             : }
     113             : 
     114             : static void
     115           0 : DirectoryMapAttributesIntoRule(const nsMappedAttributes* aAttributes,
     116             :                                GenericSpecifiedValues* aData)
     117             : {
     118           0 :   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(List))) {
     119           0 :     if (!aData->PropertyIsSet(eCSSProperty_list_style_type)) {
     120             :       // type: enum
     121           0 :       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
     122           0 :       if (value) {
     123           0 :         if (value->Type() == nsAttrValue::eEnum) {
     124           0 :           aData->SetKeywordValue(eCSSProperty_list_style_type, value->GetEnumValue());
     125             :         } else {
     126           0 :           aData->SetKeywordValue(eCSSProperty_list_style_type, NS_STYLE_LIST_STYLE_DISC);
     127             :         }
     128             :       }
     129             :     }
     130             :   }
     131             : 
     132           0 :   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
     133           0 : }
     134             : 
     135             : NS_IMETHODIMP_(bool)
     136           2 : HTMLSharedElement::IsAttributeMapped(const nsIAtom* aAttribute) const
     137             : {
     138           2 :   if (mNodeInfo->Equals(nsGkAtoms::dir)) {
     139             :     static const MappedAttributeEntry attributes[] = {
     140             :       { &nsGkAtoms::type },
     141             :       // { &nsGkAtoms::compact }, // XXX
     142             :       { nullptr}
     143             :     };
     144             : 
     145             :     static const MappedAttributeEntry* const map[] = {
     146             :       attributes,
     147             :       sCommonAttributeMap,
     148             :     };
     149             : 
     150           0 :     return FindAttributeDependence(aAttribute, map);
     151             :   }
     152             : 
     153           2 :   return nsGenericHTMLElement::IsAttributeMapped(aAttribute);
     154             : }
     155             : 
     156             : static void
     157           0 : SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch)
     158             : {
     159           0 :   NS_PRECONDITION(aDocument, "Need a document!");
     160             : 
     161           0 :   for (nsIContent* child = aDocument->GetFirstChild(); child;
     162           0 :        child = child->GetNextNode()) {
     163           0 :     if (child->IsHTMLElement(nsGkAtoms::base) &&
     164           0 :         child->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
     165           0 :       if (aMustMatch && child != aMustMatch) {
     166           0 :         return;
     167             :       }
     168             : 
     169             :       // Resolve the <base> element's href relative to our document's
     170             :       // fallback base URI.
     171           0 :       nsAutoString href;
     172           0 :       child->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
     173             : 
     174           0 :       nsCOMPtr<nsIURI> newBaseURI;
     175           0 :       nsContentUtils::NewURIWithDocumentCharset(
     176           0 :         getter_AddRefs(newBaseURI), href, aDocument,
     177           0 :         aDocument->GetFallbackBaseURI());
     178             : 
     179             :       // Check if CSP allows this base-uri
     180           0 :       nsCOMPtr<nsIContentSecurityPolicy> csp;
     181           0 :       nsresult rv = aDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
     182           0 :       NS_ASSERTION(NS_SUCCEEDED(rv), "Getting CSP Failed");
     183             :       // For all the different error cases we assign a nullptr to
     184             :       // newBaseURI, so we basically call aDocument->SetBaseURI(nullptr);
     185           0 :       if (NS_FAILED(rv)) {
     186           0 :         newBaseURI = nullptr;
     187             :       }
     188           0 :       if (csp && newBaseURI) {
     189             :         // base-uri is only enforced if explicitly defined in the
     190             :         // policy - do *not* consult default-src, see:
     191             :         // http://www.w3.org/TR/CSP2/#directive-default-src
     192           0 :         bool cspPermitsBaseURI = true;
     193           0 :         rv = csp->Permits(newBaseURI, nsIContentSecurityPolicy::BASE_URI_DIRECTIVE,
     194           0 :                           true, &cspPermitsBaseURI);
     195           0 :         if (NS_FAILED(rv) || !cspPermitsBaseURI) {
     196           0 :           newBaseURI = nullptr;
     197             :         }
     198             :       }
     199           0 :       aDocument->SetBaseURI(newBaseURI);
     200           0 :       aDocument->SetChromeXHRDocBaseURI(nullptr);
     201           0 :       return;
     202             :     }
     203             :   }
     204             : 
     205           0 :   aDocument->SetBaseURI(nullptr);
     206             : }
     207             : 
     208             : static void
     209           0 : SetBaseTargetUsingFirstBaseWithTarget(nsIDocument* aDocument,
     210             :                                       nsIContent* aMustMatch)
     211             : {
     212           0 :   NS_PRECONDITION(aDocument, "Need a document!");
     213             : 
     214           0 :   for (nsIContent* child = aDocument->GetFirstChild(); child;
     215           0 :        child = child->GetNextNode()) {
     216           0 :     if (child->IsHTMLElement(nsGkAtoms::base) &&
     217           0 :         child->HasAttr(kNameSpaceID_None, nsGkAtoms::target)) {
     218           0 :       if (aMustMatch && child != aMustMatch) {
     219           0 :         return;
     220             :       }
     221             : 
     222           0 :       nsString target;
     223           0 :       child->GetAttr(kNameSpaceID_None, nsGkAtoms::target, target);
     224           0 :       aDocument->SetBaseTarget(target);
     225           0 :       return;
     226             :     }
     227             :   }
     228             : 
     229           0 :   aDocument->SetBaseTarget(EmptyString());
     230             : }
     231             : 
     232             : nsresult
     233           1 : HTMLSharedElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
     234             :                                 const nsAttrValue* aValue,
     235             :                                 const nsAttrValue* aOldValue, bool aNotify)
     236             : {
     237           1 :   if (aNamespaceID == kNameSpaceID_None) {
     238           1 :     if (aName == nsGkAtoms::href) {
     239             :       // If the href attribute of a <base> tag is changing, we may need to
     240             :       // update the document's base URI, which will cause all the links on the
     241             :       // page to be re-resolved given the new base.
     242             :       // If the href is being unset (aValue is null), we will need to find a new
     243             :       // <base>.
     244           0 :       if (mNodeInfo->Equals(nsGkAtoms::base) && IsInUncomposedDoc()) {
     245           0 :         SetBaseURIUsingFirstBaseWithHref(GetUncomposedDoc(),
     246           0 :                                          aValue ? this : nullptr);
     247             :       }
     248           1 :     } else if (aName == nsGkAtoms::target) {
     249             :       // The target attribute is in pretty much the same situation as the href
     250             :       // attribute, above.
     251           0 :       if (mNodeInfo->Equals(nsGkAtoms::base) && IsInUncomposedDoc()) {
     252           0 :         SetBaseTargetUsingFirstBaseWithTarget(GetUncomposedDoc(),
     253           0 :                                               aValue ? this : nullptr);
     254             :       }
     255             :     }
     256             :   }
     257             : 
     258           1 :   return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
     259           1 :                                             aOldValue, aNotify);
     260             : }
     261             : 
     262             : nsresult
     263          14 : HTMLSharedElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
     264             :                               nsIContent* aBindingParent,
     265             :                               bool aCompileEventHandlers)
     266             : {
     267          14 :   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
     268             :                                                  aBindingParent,
     269          14 :                                                  aCompileEventHandlers);
     270          14 :   NS_ENSURE_SUCCESS(rv, rv);
     271             : 
     272             :   // The document stores a pointer to its base URI and base target, which we may
     273             :   // need to update here.
     274          14 :   if (mNodeInfo->Equals(nsGkAtoms::base) &&
     275             :       aDocument) {
     276           0 :     if (HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
     277           0 :       SetBaseURIUsingFirstBaseWithHref(aDocument, this);
     278             :     }
     279           0 :     if (HasAttr(kNameSpaceID_None, nsGkAtoms::target)) {
     280           0 :       SetBaseTargetUsingFirstBaseWithTarget(aDocument, this);
     281             :     }
     282             :   }
     283             : 
     284          14 :   return NS_OK;
     285             : }
     286             : 
     287             : void
     288           0 : HTMLSharedElement::UnbindFromTree(bool aDeep, bool aNullParent)
     289             : {
     290           0 :   nsIDocument* doc = GetUncomposedDoc();
     291             : 
     292           0 :   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
     293             : 
     294             :   // If we're removing a <base> from a document, we may need to update the
     295             :   // document's base URI and base target
     296           0 :   if (doc && mNodeInfo->Equals(nsGkAtoms::base)) {
     297           0 :     if (HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
     298           0 :       SetBaseURIUsingFirstBaseWithHref(doc, nullptr);
     299             :     }
     300           0 :     if (HasAttr(kNameSpaceID_None, nsGkAtoms::target)) {
     301           0 :       SetBaseTargetUsingFirstBaseWithTarget(doc, nullptr);
     302             :     }
     303             :   }
     304           0 : }
     305             : 
     306             : nsMapRuleToAttributesFunc
     307           0 : HTMLSharedElement::GetAttributeMappingFunction() const
     308             : {
     309           0 :   if (mNodeInfo->Equals(nsGkAtoms::dir)) {
     310           0 :     return &DirectoryMapAttributesIntoRule;
     311             :   }
     312             : 
     313           0 :   return nsGenericHTMLElement::GetAttributeMappingFunction();
     314             : }
     315             : 
     316             : JSObject*
     317           0 : HTMLSharedElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
     318             : {
     319           0 :   if (mNodeInfo->Equals(nsGkAtoms::param)) {
     320           0 :     return HTMLParamElementBinding::Wrap(aCx, this, aGivenProto);
     321             :   }
     322           0 :   if (mNodeInfo->Equals(nsGkAtoms::base)) {
     323           0 :     return HTMLBaseElementBinding::Wrap(aCx, this, aGivenProto);
     324             :   }
     325           0 :   if (mNodeInfo->Equals(nsGkAtoms::dir)) {
     326           0 :     return HTMLDirectoryElementBinding::Wrap(aCx, this, aGivenProto);
     327             :   }
     328           0 :   if (mNodeInfo->Equals(nsGkAtoms::q) ||
     329           0 :       mNodeInfo->Equals(nsGkAtoms::blockquote)) {
     330           0 :     return HTMLQuoteElementBinding::Wrap(aCx, this, aGivenProto);
     331             :   }
     332           0 :   if (mNodeInfo->Equals(nsGkAtoms::head)) {
     333           0 :     return HTMLHeadElementBinding::Wrap(aCx, this, aGivenProto);
     334             :   }
     335           0 :   MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::html));
     336           0 :   return HTMLHtmlElementBinding::Wrap(aCx, this, aGivenProto);
     337             : }
     338             : 
     339             : } // namespace dom
     340             : } // namespace mozilla

Generated by: LCOV version 1.13