tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

HTMLStyleElement.cpp (8495B)


      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 #include "mozilla/dom/HTMLStyleElement.h"
      7 
      8 #include "mozilla/dom/Document.h"
      9 #include "mozilla/dom/FetchPriority.h"
     10 #include "mozilla/dom/HTMLStyleElementBinding.h"
     11 #include "mozilla/dom/ReferrerInfo.h"
     12 #include "nsContentUtils.h"
     13 #include "nsDOMTokenList.h"
     14 #include "nsGkAtoms.h"
     15 #include "nsStubMutationObserver.h"
     16 #include "nsStyleConsts.h"
     17 #include "nsThreadUtils.h"
     18 #include "nsUnicharUtils.h"
     19 
     20 NS_IMPL_NS_NEW_HTML_ELEMENT(Style)
     21 
     22 namespace mozilla::dom {
     23 
     24 HTMLStyleElement::HTMLStyleElement(
     25    already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     26    : nsGenericHTMLElement(std::move(aNodeInfo)) {
     27  AddMutationObserver(this);
     28 }
     29 
     30 HTMLStyleElement::~HTMLStyleElement() = default;
     31 
     32 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLStyleElement)
     33 
     34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLStyleElement,
     35                                                  nsGenericHTMLElement)
     36  tmp->LinkStyle::Traverse(cb);
     37  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBlocking)
     38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     39 
     40 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLStyleElement,
     41                                                nsGenericHTMLElement)
     42  tmp->LinkStyle::Unlink();
     43  NS_IMPL_CYCLE_COLLECTION_UNLINK(mBlocking)
     44 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     45 
     46 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLStyleElement,
     47                                             nsGenericHTMLElement,
     48                                             nsIMutationObserver)
     49 
     50 NS_IMPL_ELEMENT_CLONE(HTMLStyleElement)
     51 
     52 bool HTMLStyleElement::Disabled() const {
     53  StyleSheet* ss = GetSheet();
     54  return ss && ss->Disabled();
     55 }
     56 
     57 void HTMLStyleElement::SetDisabled(bool aDisabled) {
     58  if (StyleSheet* ss = GetSheet()) {
     59    ss->SetDisabled(aDisabled);
     60  }
     61 }
     62 
     63 void HTMLStyleElement::CharacterDataChanged(nsIContent* aContent,
     64                                            const CharacterDataChangeInfo&) {
     65  ContentChanged(aContent);
     66 }
     67 
     68 void HTMLStyleElement::ContentAppended(nsIContent* aFirstNewContent,
     69                                       const ContentAppendInfo&) {
     70  ContentChanged(aFirstNewContent->GetParent());
     71 }
     72 
     73 void HTMLStyleElement::ContentInserted(nsIContent* aChild,
     74                                       const ContentInsertInfo&) {
     75  ContentChanged(aChild);
     76 }
     77 
     78 void HTMLStyleElement::ContentWillBeRemoved(nsIContent* aChild,
     79                                            const ContentRemoveInfo& aInfo) {
     80  mTriggeringPrincipal = nullptr;
     81  if (!nsContentUtils::IsInSameAnonymousTree(this, aChild)) {
     82    return;
     83  }
     84  if (aInfo.mBatchRemovalState && !aInfo.mBatchRemovalState->mIsFirst) {
     85    return;
     86  }
     87  // Make sure to run this once the removal has taken place.
     88  nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
     89      "HTMLStyleElement::ContentWillBeRemoved",
     90      [self = RefPtr{this}] { self->UpdateStyleSheetInternal(); }));
     91 }
     92 
     93 void HTMLStyleElement::ContentChanged(nsIContent* aContent) {
     94  mTriggeringPrincipal = nullptr;
     95  if (nsContentUtils::IsInSameAnonymousTree(this, aContent)) {
     96    (void)UpdateStyleSheetInternal(nullptr, nullptr);
     97  }
     98 }
     99 
    100 nsresult HTMLStyleElement::BindToTree(BindContext& aContext, nsINode& aParent) {
    101  nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
    102  NS_ENSURE_SUCCESS(rv, rv);
    103  LinkStyle::BindToTree();
    104  return rv;
    105 }
    106 
    107 void HTMLStyleElement::UnbindFromTree(UnbindContext& aContext) {
    108  RefPtr<Document> oldDoc = GetUncomposedDoc();
    109  ShadowRoot* oldShadow = GetContainingShadow();
    110 
    111  nsGenericHTMLElement::UnbindFromTree(aContext);
    112 
    113  (void)UpdateStyleSheetInternal(oldDoc, oldShadow);
    114 }
    115 
    116 bool HTMLStyleElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
    117                                      const nsAString& aValue,
    118                                      nsIPrincipal* aMaybeScriptedPrincipal,
    119                                      nsAttrValue& aResult) {
    120  if (aNamespaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::blocking &&
    121      StaticPrefs::dom_element_blocking_enabled()) {
    122    aResult.ParseAtomArray(aValue);
    123    return true;
    124  }
    125 
    126  return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
    127                                              aMaybeScriptedPrincipal, aResult);
    128 }
    129 
    130 void HTMLStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
    131                                    const nsAttrValue* aValue,
    132                                    const nsAttrValue* aOldValue,
    133                                    nsIPrincipal* aSubjectPrincipal,
    134                                    bool aNotify) {
    135  if (aNameSpaceID == kNameSpaceID_None) {
    136    if (aName == nsGkAtoms::title || aName == nsGkAtoms::media ||
    137        aName == nsGkAtoms::type) {
    138      (void)UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes);
    139    }
    140  }
    141 
    142  return nsGenericHTMLElement::AfterSetAttr(
    143      aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify);
    144 }
    145 
    146 void HTMLStyleElement::GetInnerHTML(nsAString& aInnerHTML,
    147                                    OOMReporter& aError) {
    148  if (!nsContentUtils::GetNodeTextContent(this, false, aInnerHTML, fallible)) {
    149    aError.ReportOOM();
    150  }
    151 }
    152 
    153 void HTMLStyleElement::SetInnerHTMLTrusted(const nsAString& aInnerHTML,
    154                                           nsIPrincipal* aSubjectPrincipal,
    155                                           ErrorResult& aError) {
    156  SetTextContentInternal(aInnerHTML, aSubjectPrincipal, aError);
    157 }
    158 
    159 void HTMLStyleElement::SetTextContentInternal(const nsAString& aTextContent,
    160                                              nsIPrincipal* aScriptedPrincipal,
    161                                              ErrorResult& aError,
    162                                              MutationEffectOnScript) {
    163  // Per spec, if we're setting text content to an empty string and don't
    164  // already have any children, we should not trigger any mutation observers, or
    165  // re-parse the stylesheet.
    166  if (aTextContent.IsEmpty() && !GetFirstChild()) {
    167    nsIPrincipal* principal =
    168        mTriggeringPrincipal ? mTriggeringPrincipal.get() : NodePrincipal();
    169    if (principal == aScriptedPrincipal) {
    170      return;
    171    }
    172  }
    173 
    174  const bool updatesWereEnabled = mUpdatesEnabled;
    175  DisableUpdates();
    176 
    177  aError = nsContentUtils::SetNodeTextContent(this, aTextContent, true);
    178  if (updatesWereEnabled) {
    179    mTriggeringPrincipal = aScriptedPrincipal;
    180    (void)EnableUpdatesAndUpdateStyleSheet(nullptr);
    181  }
    182 }
    183 
    184 void HTMLStyleElement::SetDevtoolsAsTriggeringPrincipal() {
    185  mTriggeringPrincipal = CreateDevtoolsPrincipal();
    186 }
    187 
    188 Maybe<LinkStyle::SheetInfo> HTMLStyleElement::GetStyleSheetInfo() {
    189  if (!IsCSSMimeTypeAttributeForStyleElement(*this)) {
    190    return Nothing();
    191  }
    192 
    193  nsAutoString title;
    194  nsAutoString media;
    195  GetTitleAndMediaForElement(*this, title, media);
    196 
    197  return Some(SheetInfo{
    198      *OwnerDoc(),
    199      this,
    200      nullptr,
    201      do_AddRef(mTriggeringPrincipal),
    202      MakeAndAddRef<ReferrerInfo>(*this),
    203      CORS_NONE,
    204      title,
    205      media,
    206      /* integrity = */ u""_ns,
    207      /* nsStyleUtil::CSPAllowsInlineStyle takes care of nonce checking for
    208         inline styles. Bug 1607011 */
    209      /* nonce = */ u""_ns,
    210      HasAlternateRel::No,
    211      IsInline::Yes,
    212      IsExplicitlyEnabled::No,
    213      FetchPriority::Auto,
    214  });
    215 }
    216 
    217 JSObject* HTMLStyleElement::WrapNode(JSContext* aCx,
    218                                     JS::Handle<JSObject*> aGivenProto) {
    219  return HTMLStyleElement_Binding::Wrap(aCx, this, aGivenProto);
    220 }
    221 
    222 nsDOMTokenList* HTMLStyleElement::Blocking() {
    223  if (!mBlocking) {
    224    mBlocking =
    225        new nsDOMTokenList(this, nsGkAtoms::blocking, sSupportedBlockingValues);
    226  }
    227  return mBlocking;
    228 }
    229 
    230 bool HTMLStyleElement::IsPotentiallyRenderBlocking() {
    231  return BlockingContainsRender();
    232 
    233  // TODO: handle implicitly potentially render blocking
    234  // https://html.spec.whatwg.org/#implicitly-potentially-render-blocking
    235  // A style element is implicitly potentially render-blocking if the element
    236  // was created by its node document's parser.
    237 }
    238 
    239 nsresult HTMLStyleElement::CopyInnerTo(HTMLStyleElement* aDest) {
    240  nsresult rv = Element::CopyInnerTo(aDest);
    241  NS_ENSURE_SUCCESS(rv, rv);
    242  MaybeStartCopyStyleSheetTo(aDest, aDest->OwnerDoc());
    243  return NS_OK;
    244 }
    245 
    246 }  // namespace mozilla::dom