summaryrefslogtreecommitdiffstats
path: root/dom/base/LinkStyle.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/LinkStyle.h')
-rw-r--r--dom/base/LinkStyle.h293
1 files changed, 293 insertions, 0 deletions
diff --git a/dom/base/LinkStyle.h b/dom/base/LinkStyle.h
new file mode 100644
index 0000000000..d62ab8f4e1
--- /dev/null
+++ b/dom/base/LinkStyle.h
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef mozilla_dom_LinkStyle_h
+#define mozilla_dom_LinkStyle_h
+
+#include "nsINode.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/StyleSheet.h"
+#include "mozilla/Result.h"
+#include "mozilla/Unused.h"
+#include "nsTArray.h"
+
+class nsIContent;
+class nsICSSLoaderObserver;
+class nsIPrincipal;
+class nsIURI;
+
+namespace mozilla::dom {
+
+class Document;
+enum class FetchPriority : uint8_t;
+class ShadowRoot;
+
+// https://drafts.csswg.org/cssom/#the-linkstyle-interface
+class LinkStyle {
+ public:
+ enum class ForceUpdate : uint8_t {
+ No,
+ Yes,
+ };
+
+ enum class Completed : uint8_t {
+ No,
+ Yes,
+ };
+
+ enum class HasAlternateRel : uint8_t {
+ No,
+ Yes,
+ };
+
+ enum class IsAlternate : uint8_t {
+ No,
+ Yes,
+ };
+
+ enum class IsInline : uint8_t {
+ No,
+ Yes,
+ };
+
+ enum class IsExplicitlyEnabled : uint8_t {
+ No,
+ Yes,
+ };
+
+ enum class MediaMatched : uint8_t {
+ Yes,
+ No,
+ };
+
+ struct Update {
+ private:
+ bool mWillNotify;
+ bool mIsAlternate;
+ bool mMediaMatched;
+
+ public:
+ Update() : mWillNotify(false), mIsAlternate(false), mMediaMatched(false) {}
+
+ Update(Completed aCompleted, IsAlternate aIsAlternate,
+ MediaMatched aMediaMatched)
+ : mWillNotify(aCompleted == Completed::No),
+ mIsAlternate(aIsAlternate == IsAlternate::Yes),
+ mMediaMatched(aMediaMatched == MediaMatched::Yes) {}
+
+ bool WillNotify() const { return mWillNotify; }
+
+ bool ShouldBlock() const {
+ if (!mWillNotify) {
+ return false;
+ }
+
+ return !mIsAlternate && mMediaMatched;
+ }
+ };
+
+ static LinkStyle* FromNode(nsINode& aNode) { return aNode.AsLinkStyle(); }
+ static const LinkStyle* FromNode(const nsINode& aNode) {
+ return aNode.AsLinkStyle();
+ }
+
+ static LinkStyle* FromNode(Element&);
+ static const LinkStyle* FromNode(const Element& aElement) {
+ return FromNode(const_cast<Element&>(aElement));
+ }
+
+ template <typename T>
+ static LinkStyle* FromNodeOrNull(T* aNode) {
+ return aNode ? FromNode(*aNode) : nullptr;
+ }
+
+ template <typename T>
+ static const LinkStyle* FromNodeOrNull(const T* aNode) {
+ return aNode ? FromNode(*aNode) : nullptr;
+ }
+
+ enum RelValue {
+ ePREFETCH = 0x00000001,
+ eDNS_PREFETCH = 0x00000002,
+ eSTYLESHEET = 0x00000004,
+ eNEXT = 0x00000008,
+ eALTERNATE = 0x00000010,
+ ePRECONNECT = 0x00000020,
+ // NOTE: 0x40 is unused
+ ePRELOAD = 0x00000080,
+ eMODULE_PRELOAD = 0x00000100
+ };
+
+ // The return value is a bitwise or of 0 or more RelValues.
+ static uint32_t ParseLinkTypes(const nsAString& aTypes);
+
+ void UpdateStyleSheetInternal() {
+ Unused << UpdateStyleSheetInternal(nullptr, nullptr);
+ }
+
+ struct MOZ_STACK_CLASS SheetInfo {
+ nsIContent* mContent;
+ // FIXME(emilio): do these really need to be strong refs?
+ nsCOMPtr<nsIURI> mURI;
+
+ // The principal of the scripted caller that initiated the load, if
+ // available. Otherwise null.
+ nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
+ nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
+ mozilla::CORSMode mCORSMode;
+ nsString mTitle;
+ nsString mMedia;
+ nsString mIntegrity;
+ nsString mNonce;
+ const FetchPriority mFetchPriority;
+
+ bool mHasAlternateRel;
+ bool mIsInline;
+ IsExplicitlyEnabled mIsExplicitlyEnabled;
+
+ SheetInfo(const mozilla::dom::Document&, nsIContent*,
+ already_AddRefed<nsIURI> aURI,
+ already_AddRefed<nsIPrincipal> aTriggeringPrincipal,
+ already_AddRefed<nsIReferrerInfo> aReferrerInfo,
+ mozilla::CORSMode, const nsAString& aTitle,
+ const nsAString& aMedia, const nsAString& aIntegrity,
+ const nsAString& aNonce, HasAlternateRel, IsInline,
+ IsExplicitlyEnabled, FetchPriority aFetchPriority);
+
+ ~SheetInfo();
+ };
+
+ virtual nsIContent& AsContent() = 0;
+ virtual Maybe<SheetInfo> GetStyleSheetInfo() = 0;
+
+ /**
+ * Used to make the association between a style sheet and
+ * the element that linked it to the document.
+ *
+ * @param aStyleSheet the style sheet associated with this
+ * element.
+ */
+ void SetStyleSheet(StyleSheet* aStyleSheet);
+
+ /**
+ * Tells this element whether to update the stylesheet when the element's
+ * properties change. This is used by the parser until it has all content etc,
+ * and to guarantee that the right observer is used.
+ */
+ void DisableUpdates() { mUpdatesEnabled = false; }
+ Result<Update, nsresult> EnableUpdatesAndUpdateStyleSheet(
+ nsICSSLoaderObserver* aObserver) {
+ MOZ_ASSERT(!mUpdatesEnabled);
+ mUpdatesEnabled = true;
+ return DoUpdateStyleSheet(nullptr, nullptr, aObserver, ForceUpdate::No);
+ }
+
+ /**
+ * Gets the charset that the element claims the style sheet is in.
+ * Can return empty string to indicate that we have no charset
+ * information.
+ *
+ * @param aCharset the charset
+ */
+ virtual void GetCharset(nsAString& aCharset);
+
+ // This doesn't entirely belong here since they only make sense for
+ // some types of linking elements, but it's a better place than
+ // anywhere else.
+ void SetLineNumber(uint32_t aLineNumber) { mLineNumber = aLineNumber; }
+
+ /**
+ * Get the line number, as previously set by SetLineNumber.
+ *
+ * @return the line number of this element; or 1 if no line number
+ * was set
+ */
+ uint32_t GetLineNumber() const { return mLineNumber; }
+
+ // This doesn't entirely belong here since they only make sense for
+ // some types of linking elements, but it's a better place than
+ // anywhere else.
+ void SetColumnNumber(uint32_t aColumnNumber) {
+ mColumnNumber = aColumnNumber;
+ }
+
+ /**
+ * Get the column number, as previously set by SetColumnNumber.
+ *
+ * @return the column number of this element; or 1 if no column number
+ * was set
+ */
+ uint32_t GetColumnNumber() const { return mColumnNumber; }
+
+ StyleSheet* GetSheet() const { return mStyleSheet; }
+
+ /** JS can only observe the sheet once fully loaded */
+ StyleSheet* GetSheetForBindings() const;
+
+ protected:
+ LinkStyle();
+ virtual ~LinkStyle();
+
+ // Gets a suitable title and media for SheetInfo out of an element, which
+ // needs to be `this`.
+ //
+ // NOTE(emilio): Needs nsString instead of nsAString because of
+ // CompressWhitespace.
+ static void GetTitleAndMediaForElement(const mozilla::dom::Element&,
+ nsString& aTitle, nsString& aMedia);
+
+ // Returns whether the type attribute specifies the text/css type for style
+ // elements.
+ static bool IsCSSMimeTypeAttributeForStyleElement(const Element&);
+
+ // CC methods
+ void Unlink();
+ void Traverse(nsCycleCollectionTraversalCallback& cb);
+
+ /**
+ * @param aOldDocument should be non-null only if we're updating because we
+ * removed the node from the document.
+ * @param aOldShadowRoot should be non-null only if we're updating because we
+ * removed the node from a shadow tree.
+ * @param aForceUpdate true will force the update even if the URI has not
+ * changed. This should be used in cases when something
+ * about the content that affects the resulting sheet
+ * changed but the URI may not have changed.
+ *
+ * TODO(emilio): Should probably pass a single DocumentOrShadowRoot.
+ */
+ Result<Update, nsresult> UpdateStyleSheetInternal(
+ Document* aOldDocument, ShadowRoot* aOldShadowRoot,
+ ForceUpdate = ForceUpdate::No);
+
+ /**
+ * @param aOldDocument should be non-null only if we're updating because we
+ * removed the node from the document.
+ * @param aOldShadowRoot The ShadowRoot that used to contain the style.
+ * Passed as a parameter because on an update, the node
+ * is removed from the tree before the sheet is removed
+ * from the ShadowRoot.
+ * @param aForceUpdate true will force the update even if the URI has not
+ * changed. This should be used in cases when something
+ * about the content that affects the resulting sheet
+ * changed but the URI may not have changed.
+ */
+ Result<Update, nsresult> DoUpdateStyleSheet(Document* aOldDocument,
+ ShadowRoot* aOldShadowRoot,
+ nsICSSLoaderObserver*,
+ ForceUpdate);
+
+ void BindToTree();
+
+ RefPtr<mozilla::StyleSheet> mStyleSheet;
+ nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
+ bool mUpdatesEnabled = true;
+ uint32_t mLineNumber = 1;
+ uint32_t mColumnNumber = 1;
+};
+
+} // namespace mozilla::dom
+
+#endif // mozilla_dom_LinkStyle_h