1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
|
/* -*- 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 "mozilla/Attributes.h"
#include "mozilla/Result.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/Unused.h"
#include "nsINode.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);
/**
* If the node is being copied into a static document, we need to clone the
* associated stylesheet over as well, preserving the relationship between
* the node and the stylesheet (See bug 1930618 as to why this is required).
* Nodes inheriting from this class should ensure that this is called on
* clone, usually by implementing CopyInnerTo. Because we generally don't have
* the knowledge of being in shadow root, the actual copying happens later.
*/
void MaybeStartCopyStyleSheetTo(LinkStyle* aDest, Document* aDoc) const;
/**
* Continuation of MaybeStartCopyStyleSheetTo, called in
* LinkStyle::DoUpdateStyleSheet. Unlike MaybeStartCopyStyleSheetTo, this is
* called from LinkStyle being copied into.
*/
void MaybeFinishCopyStyleSheet(Document* aDocument);
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
|