tor-browser

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

LinkStyle.h (9927B)


      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 #ifndef mozilla_dom_LinkStyle_h
      7 #define mozilla_dom_LinkStyle_h
      8 
      9 #include "mozilla/Attributes.h"
     10 #include "mozilla/Result.h"
     11 #include "mozilla/StyleSheet.h"
     12 #include "nsINode.h"
     13 #include "nsTArray.h"
     14 
     15 class nsIContent;
     16 class nsICSSLoaderObserver;
     17 class nsIPrincipal;
     18 class nsIURI;
     19 
     20 namespace mozilla::dom {
     21 
     22 class Document;
     23 enum class FetchPriority : uint8_t;
     24 class ShadowRoot;
     25 
     26 // https://drafts.csswg.org/cssom/#the-linkstyle-interface
     27 class LinkStyle {
     28 public:
     29  enum class ForceUpdate : uint8_t {
     30    No,
     31    Yes,
     32  };
     33 
     34  enum class Completed : uint8_t {
     35    No,
     36    Yes,
     37  };
     38 
     39  enum class HasAlternateRel : uint8_t {
     40    No,
     41    Yes,
     42  };
     43 
     44  enum class IsAlternate : uint8_t {
     45    No,
     46    Yes,
     47  };
     48 
     49  enum class IsInline : uint8_t {
     50    No,
     51    Yes,
     52  };
     53 
     54  enum class IsExplicitlyEnabled : uint8_t {
     55    No,
     56    Yes,
     57  };
     58 
     59  enum class MediaMatched : uint8_t {
     60    Yes,
     61    No,
     62  };
     63 
     64  struct Update {
     65   private:
     66    bool mWillNotify;
     67    bool mIsAlternate;
     68    bool mMediaMatched;
     69 
     70   public:
     71    Update() : mWillNotify(false), mIsAlternate(false), mMediaMatched(false) {}
     72 
     73    Update(Completed aCompleted, IsAlternate aIsAlternate,
     74           MediaMatched aMediaMatched)
     75        : mWillNotify(aCompleted == Completed::No),
     76          mIsAlternate(aIsAlternate == IsAlternate::Yes),
     77          mMediaMatched(aMediaMatched == MediaMatched::Yes) {}
     78 
     79    bool WillNotify() const { return mWillNotify; }
     80 
     81    bool ShouldBlock() const {
     82      if (!mWillNotify) {
     83        return false;
     84      }
     85 
     86      return !mIsAlternate && mMediaMatched;
     87    }
     88  };
     89 
     90  static LinkStyle* FromNode(nsINode& aNode) { return aNode.AsLinkStyle(); }
     91  static const LinkStyle* FromNode(const nsINode& aNode) {
     92    return aNode.AsLinkStyle();
     93  }
     94 
     95  static LinkStyle* FromNode(Element&);
     96  static const LinkStyle* FromNode(const Element& aElement) {
     97    return FromNode(const_cast<Element&>(aElement));
     98  }
     99 
    100  template <typename T>
    101  static LinkStyle* FromNodeOrNull(T* aNode) {
    102    return aNode ? FromNode(*aNode) : nullptr;
    103  }
    104 
    105  template <typename T>
    106  static const LinkStyle* FromNodeOrNull(const T* aNode) {
    107    return aNode ? FromNode(*aNode) : nullptr;
    108  }
    109 
    110  enum RelValue {
    111    ePREFETCH = 0x00000001,
    112    eDNS_PREFETCH = 0x00000002,
    113    eSTYLESHEET = 0x00000004,
    114    eNEXT = 0x00000008,
    115    eALTERNATE = 0x00000010,
    116    ePRECONNECT = 0x00000020,
    117    // NOTE: 0x40 is unused
    118    ePRELOAD = 0x00000080,
    119    eMODULE_PRELOAD = 0x00000100,
    120    eCOMPRESSION_DICTIONARY = 0x00000200
    121  };
    122 
    123  // The return value is a bitwise or of 0 or more RelValues.
    124  static uint32_t ParseLinkTypes(const nsAString& aTypes);
    125 
    126  void UpdateStyleSheetInternal() {
    127    (void)UpdateStyleSheetInternal(nullptr, nullptr);
    128  }
    129 
    130  struct MOZ_STACK_CLASS SheetInfo {
    131    nsIContent* mContent;
    132    // FIXME(emilio): do these really need to be strong refs?
    133    nsCOMPtr<nsIURI> mURI;
    134 
    135    // The principal of the scripted caller that initiated the load, if
    136    // available. Otherwise null.
    137    nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
    138    nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
    139    mozilla::CORSMode mCORSMode;
    140    nsString mTitle;
    141    nsString mMedia;
    142    nsString mIntegrity;
    143    nsString mNonce;
    144    const FetchPriority mFetchPriority;
    145 
    146    bool mHasAlternateRel;
    147    bool mIsInline;
    148    IsExplicitlyEnabled mIsExplicitlyEnabled;
    149 
    150    SheetInfo(const mozilla::dom::Document&, nsIContent*,
    151              already_AddRefed<nsIURI> aURI,
    152              already_AddRefed<nsIPrincipal> aTriggeringPrincipal,
    153              already_AddRefed<nsIReferrerInfo> aReferrerInfo,
    154              mozilla::CORSMode, const nsAString& aTitle,
    155              const nsAString& aMedia, const nsAString& aIntegrity,
    156              const nsAString& aNonce, HasAlternateRel, IsInline,
    157              IsExplicitlyEnabled, FetchPriority aFetchPriority);
    158 
    159    ~SheetInfo();
    160  };
    161 
    162  virtual nsIContent& AsContent() = 0;
    163  virtual Maybe<SheetInfo> GetStyleSheetInfo() = 0;
    164 
    165  /**
    166   * Used to make the association between a style sheet and
    167   * the element that linked it to the document.
    168   *
    169   * @param aStyleSheet the style sheet associated with this
    170   *                    element.
    171   */
    172  void SetStyleSheet(StyleSheet* aStyleSheet);
    173 
    174  /**
    175   * Tells this element whether to update the stylesheet when the element's
    176   * properties change. This is used by the parser until it has all content etc,
    177   * and to guarantee that the right observer is used.
    178   */
    179  void DisableUpdates() { mUpdatesEnabled = false; }
    180  Result<Update, nsresult> EnableUpdatesAndUpdateStyleSheet(
    181      nsICSSLoaderObserver* aObserver) {
    182    MOZ_ASSERT(!mUpdatesEnabled);
    183    mUpdatesEnabled = true;
    184    return DoUpdateStyleSheet(nullptr, nullptr, aObserver, ForceUpdate::No);
    185  }
    186 
    187  /**
    188   * Gets the charset that the element claims the style sheet is in.
    189   * Can return empty string to indicate that we have no charset
    190   * information.
    191   *
    192   * @param aCharset the charset
    193   */
    194  virtual void GetCharset(nsAString& aCharset);
    195 
    196  // This doesn't entirely belong here since they only make sense for
    197  // some types of linking elements, but it's a better place than
    198  // anywhere else.
    199  void SetLineNumber(uint32_t aLineNumber) { mLineNumber = aLineNumber; }
    200 
    201  /**
    202   * Get the line number, as previously set by SetLineNumber.
    203   *
    204   * @return the line number of this element; or 1 if no line number
    205   *         was set
    206   */
    207  uint32_t GetLineNumber() const { return mLineNumber; }
    208 
    209  // This doesn't entirely belong here since they only make sense for
    210  // some types of linking elements, but it's a better place than
    211  // anywhere else.
    212  void SetColumnNumber(uint32_t aColumnNumber) {
    213    mColumnNumber = aColumnNumber;
    214  }
    215 
    216  /**
    217   * Get the column number, as previously set by SetColumnNumber.
    218   *
    219   * @return the column number of this element; or 1 if no column number
    220   *         was set
    221   */
    222  uint32_t GetColumnNumber() const { return mColumnNumber; }
    223 
    224  StyleSheet* GetSheet() const { return mStyleSheet; }
    225 
    226  /** JS can only observe the sheet once fully loaded */
    227  StyleSheet* GetSheetForBindings() const;
    228 
    229 protected:
    230  LinkStyle();
    231  virtual ~LinkStyle();
    232 
    233  // Gets a suitable title and media for SheetInfo out of an element, which
    234  // needs to be `this`.
    235  //
    236  // NOTE(emilio): Needs nsString instead of nsAString because of
    237  // CompressWhitespace.
    238  static void GetTitleAndMediaForElement(const mozilla::dom::Element&,
    239                                         nsString& aTitle, nsString& aMedia);
    240 
    241  // Returns whether the type attribute specifies the text/css type for style
    242  // elements.
    243  static bool IsCSSMimeTypeAttributeForStyleElement(const Element&);
    244 
    245  // CC methods
    246  void Unlink();
    247  void Traverse(nsCycleCollectionTraversalCallback& cb);
    248 
    249  /**
    250   * @param aOldDocument   should be non-null only if we're updating because we
    251   *                       removed the node from the document.
    252   * @param aOldShadowRoot should be non-null only if we're updating because we
    253   *                       removed the node from a shadow tree.
    254   * @param aForceUpdate true will force the update even if the URI has not
    255   *                     changed.  This should be used in cases when something
    256   *                     about the content that affects the resulting sheet
    257   *                     changed but the URI may not have changed.
    258   *
    259   * TODO(emilio): Should probably pass a single DocumentOrShadowRoot.
    260   */
    261  Result<Update, nsresult> UpdateStyleSheetInternal(
    262      Document* aOldDocument, ShadowRoot* aOldShadowRoot,
    263      ForceUpdate = ForceUpdate::No);
    264 
    265  /**
    266   * @param aOldDocument should be non-null only if we're updating because we
    267   *                     removed the node from the document.
    268   * @param aOldShadowRoot The ShadowRoot that used to contain the style.
    269   *                     Passed as a parameter because on an update, the node
    270   *                     is removed from the tree before the sheet is removed
    271   *                     from the ShadowRoot.
    272   * @param aForceUpdate true will force the update even if the URI has not
    273   *                     changed.  This should be used in cases when something
    274   *                     about the content that affects the resulting sheet
    275   *                     changed but the URI may not have changed.
    276   */
    277  Result<Update, nsresult> DoUpdateStyleSheet(Document* aOldDocument,
    278                                              ShadowRoot* aOldShadowRoot,
    279                                              nsICSSLoaderObserver*,
    280                                              ForceUpdate);
    281 
    282  /**
    283   * If the node is being copied into a static document, we need to clone the
    284   * associated stylesheet over as well, preserving the relationship between
    285   * the node and the stylesheet (See bug 1930618 as to why this is required).
    286   * Nodes inheriting from this class should ensure that this is called on
    287   * clone, usually by implementing CopyInnerTo. Because we generally don't have
    288   * the knowledge of being in shadow root, the actual copying happens later.
    289   */
    290  void MaybeStartCopyStyleSheetTo(LinkStyle* aDest, Document* aDoc) const;
    291 
    292  /**
    293   * Continuation of MaybeStartCopyStyleSheetTo, called in
    294   * LinkStyle::DoUpdateStyleSheet. Unlike MaybeStartCopyStyleSheetTo, this is
    295   * called from LinkStyle being copied into.
    296   */
    297  void MaybeFinishCopyStyleSheet(Document* aDocument);
    298 
    299  void BindToTree();
    300 
    301  RefPtr<mozilla::StyleSheet> mStyleSheet;
    302  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
    303  bool mUpdatesEnabled = true;
    304  uint32_t mLineNumber = 1;
    305  uint32_t mColumnNumber = 1;
    306 };
    307 
    308 }  // namespace mozilla::dom
    309 
    310 #endif  // mozilla_dom_LinkStyle_h