2016-02-26 04:51:01 +03:00
|
|
|
/* -*- 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_StyleSheet_h
|
|
|
|
#define mozilla_StyleSheet_h
|
|
|
|
|
|
|
|
#include "mozilla/css/SheetParsingMode.h"
|
2016-08-02 23:17:06 +03:00
|
|
|
#include "mozilla/dom/CSSStyleSheetBinding.h"
|
2018-04-30 18:50:03 +03:00
|
|
|
#include "mozilla/dom/SRIMetadata.h"
|
2016-09-26 15:03:25 +03:00
|
|
|
#include "mozilla/CORSMode.h"
|
2018-04-30 18:50:03 +03:00
|
|
|
#include "mozilla/MozPromise.h"
|
|
|
|
#include "mozilla/RefPtr.h"
|
|
|
|
#include "mozilla/ServoBindingTypes.h"
|
2016-10-13 15:45:03 +03:00
|
|
|
#include "mozilla/ServoUtils.h"
|
2018-04-30 18:50:03 +03:00
|
|
|
#include "mozilla/StyleSheetInfo.h"
|
|
|
|
#include "mozilla/URLExtraData.h"
|
2017-04-03 12:55:06 +03:00
|
|
|
#include "nsICSSLoaderObserver.h"
|
2016-10-14 14:25:38 +03:00
|
|
|
#include "nsWrapperCache.h"
|
2018-04-30 18:50:03 +03:00
|
|
|
#include "nsCompatibility.h"
|
|
|
|
#include "nsStringFwd.h"
|
2016-10-14 14:25:38 +03:00
|
|
|
|
2016-02-26 04:51:01 +03:00
|
|
|
class nsINode;
|
2016-10-14 14:25:38 +03:00
|
|
|
class nsIPrincipal;
|
2019-03-30 03:23:49 +03:00
|
|
|
struct RawServoSharedMemoryBuilder;
|
2019-07-16 14:43:39 +03:00
|
|
|
class nsIReferrerInfo;
|
2016-02-26 04:51:01 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
2018-04-30 18:50:03 +03:00
|
|
|
class ServoCSSRuleList;
|
2018-03-29 14:15:46 +03:00
|
|
|
class ServoStyleSet;
|
2018-04-30 18:50:03 +03:00
|
|
|
|
|
|
|
typedef MozPromise</* Dummy */ bool,
|
|
|
|
/* Dummy */ bool,
|
|
|
|
/* IsExclusive = */ true>
|
|
|
|
StyleSheetParsePromise;
|
|
|
|
|
|
|
|
namespace css {
|
|
|
|
class GroupRule;
|
|
|
|
class Loader;
|
|
|
|
class LoaderReusableStyleSheets;
|
|
|
|
class Rule;
|
|
|
|
class SheetLoadData;
|
|
|
|
} // namespace css
|
2016-09-26 15:03:25 +03:00
|
|
|
|
|
|
|
namespace dom {
|
2017-05-30 04:10:25 +03:00
|
|
|
class CSSImportRule;
|
2016-10-14 14:25:38 +03:00
|
|
|
class CSSRuleList;
|
2018-05-11 13:57:38 +03:00
|
|
|
class DocumentOrShadowRoot;
|
2016-11-09 09:28:24 +03:00
|
|
|
class MediaList;
|
2018-03-17 00:56:05 +03:00
|
|
|
class ShadowRoot;
|
2016-09-26 15:03:25 +03:00
|
|
|
class SRIMetadata;
|
2020-01-01 00:58:40 +03:00
|
|
|
struct CSSStyleSheetInit;
|
2016-09-26 15:03:25 +03:00
|
|
|
} // namespace dom
|
2016-03-02 01:38:13 +03:00
|
|
|
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
enum class StyleSheetState : uint8_t {
|
|
|
|
// Whether the sheet is disabled. Sheets can be made disabled via CSSOM, or
|
|
|
|
// via alternate links and such.
|
|
|
|
Disabled = 1 << 0,
|
|
|
|
// Whether the sheet is complete. The sheet is complete if it's finished
|
|
|
|
// loading. See StyleSheet::SetComplete.
|
|
|
|
Complete = 1 << 1,
|
|
|
|
// Whether we've forced a unique inner. StyleSheet objects share an 'inner'
|
|
|
|
// StyleSheetInfo object if they share URL, CORS mode, etc.
|
|
|
|
//
|
|
|
|
// See the Loader's `mCompleteSheets` and `mLoadingSheets`.
|
|
|
|
ForcedUniqueInner = 1 << 2,
|
|
|
|
// Whether this stylesheet has suffered any modification to the rules via
|
|
|
|
// CSSOM.
|
|
|
|
ModifiedRules = 1 << 3,
|
2019-12-03 14:04:03 +03:00
|
|
|
// Same flag, but devtools clears it in some specific situations.
|
|
|
|
//
|
|
|
|
// Used to control whether devtools shows the rule in its authored form or
|
|
|
|
// not.
|
|
|
|
ModifiedRulesForDevtools = 1 << 4,
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(StyleSheetState)
|
|
|
|
|
2018-04-30 18:50:03 +03:00
|
|
|
class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
|
2016-02-26 04:51:01 +03:00
|
|
|
StyleSheet(const StyleSheet& aCopy, StyleSheet* aParentToUse,
|
2017-05-30 04:10:25 +03:00
|
|
|
dom::CSSImportRule* aOwnerRuleToUse,
|
2018-05-11 13:57:38 +03:00
|
|
|
dom::DocumentOrShadowRoot* aDocOrShadowRootToUse,
|
2016-02-26 04:51:01 +03:00
|
|
|
nsINode* aOwningNodeToUse);
|
2018-04-30 18:50:03 +03:00
|
|
|
|
2017-01-06 10:05:24 +03:00
|
|
|
virtual ~StyleSheet();
|
2016-02-26 04:51:01 +03:00
|
|
|
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
using State = StyleSheetState;
|
|
|
|
|
2016-03-02 01:38:13 +03:00
|
|
|
public:
|
2018-04-30 18:50:03 +03:00
|
|
|
StyleSheet(css::SheetParsingMode aParsingMode, CORSMode aCORSMode,
|
|
|
|
const dom::SRIMetadata& aIntegrity);
|
|
|
|
|
2020-01-01 00:58:40 +03:00
|
|
|
static already_AddRefed<StyleSheet> Constructor(const dom::GlobalObject&,
|
|
|
|
const dom::CSSStyleSheetInit&,
|
|
|
|
ErrorResult&);
|
|
|
|
|
2016-10-14 14:25:38 +03:00
|
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
2018-01-11 11:17:57 +03:00
|
|
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(StyleSheet)
|
2016-10-14 14:25:38 +03:00
|
|
|
|
2018-04-30 18:50:03 +03:00
|
|
|
already_AddRefed<StyleSheet> CreateEmptyChildSheet(
|
|
|
|
already_AddRefed<dom::MediaList> aMediaList) const;
|
|
|
|
|
|
|
|
bool HasRules() const;
|
|
|
|
|
2019-08-16 13:56:09 +03:00
|
|
|
// Parses a stylesheet. The load data argument corresponds to the
|
|
|
|
// SheetLoadData for this stylesheet.
|
2020-01-09 03:52:44 +03:00
|
|
|
// NOTE: ParseSheet can run synchronously or asynchronously
|
|
|
|
// based on the result of `AllowParallelParse`
|
2019-08-16 13:56:09 +03:00
|
|
|
RefPtr<StyleSheetParsePromise> ParseSheet(css::Loader&,
|
2018-04-30 18:50:03 +03:00
|
|
|
const nsACString& aBytes,
|
2019-08-16 13:56:09 +03:00
|
|
|
css::SheetLoadData&);
|
2018-04-30 18:50:03 +03:00
|
|
|
|
|
|
|
// Common code that needs to be called after servo finishes parsing. This is
|
|
|
|
// shared between the parallel and sequential paths.
|
|
|
|
void FinishAsyncParse(
|
|
|
|
already_AddRefed<RawServoStyleSheetContents> aSheetContents);
|
|
|
|
|
2020-01-09 03:52:44 +03:00
|
|
|
// Similar to `ParseSheet`, but guarantees that
|
|
|
|
// parsing will be performed synchronously.
|
|
|
|
// NOTE: ParseSheet can still run synchronously.
|
|
|
|
// This is not a strict alternative.
|
2019-08-16 13:56:09 +03:00
|
|
|
//
|
|
|
|
// The load data may be null sometimes.
|
2018-04-30 18:50:03 +03:00
|
|
|
void ParseSheetSync(
|
|
|
|
css::Loader* aLoader, const nsACString& aBytes,
|
|
|
|
css::SheetLoadData* aLoadData, uint32_t aLineNumber,
|
|
|
|
css::LoaderReusableStyleSheets* aReusableSheets = nullptr);
|
|
|
|
|
2020-01-08 04:21:30 +03:00
|
|
|
nsresult ReparseSheet(const nsACString& aInput);
|
2018-04-30 18:50:03 +03:00
|
|
|
|
2018-04-30 20:47:12 +03:00
|
|
|
const RawServoStyleSheetContents* RawContents() const {
|
|
|
|
return Inner().mContents;
|
2018-04-30 18:50:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetContentsForImport(const RawServoStyleSheetContents* aContents) {
|
2018-04-30 20:47:12 +03:00
|
|
|
MOZ_ASSERT(!Inner().mContents);
|
|
|
|
Inner().mContents = aContents;
|
2018-04-30 18:50:03 +03:00
|
|
|
}
|
|
|
|
|
2018-04-30 20:47:12 +03:00
|
|
|
URLExtraData* URLData() const { return Inner().mURLData; }
|
2018-04-30 18:50:03 +03:00
|
|
|
|
|
|
|
// nsICSSLoaderObserver interface
|
2019-08-16 13:56:16 +03:00
|
|
|
NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred,
|
2018-04-30 18:50:03 +03:00
|
|
|
nsresult aStatus) final;
|
|
|
|
|
|
|
|
// Internal GetCssRules methods which do not have security check and
|
|
|
|
// completeness check.
|
|
|
|
ServoCSSRuleList* GetCssRulesInternal();
|
|
|
|
|
2019-04-29 08:34:06 +03:00
|
|
|
// Returns the stylesheet's Servo origin as a StyleOrigin value.
|
2019-11-30 14:57:10 +03:00
|
|
|
StyleOrigin GetOrigin() const;
|
2018-04-30 18:50:03 +03:00
|
|
|
|
2017-05-24 05:28:58 +03:00
|
|
|
/**
|
|
|
|
* The different changes that a stylesheet may go through.
|
|
|
|
*
|
|
|
|
* Used by the StyleSets in order to handle more efficiently some kinds of
|
|
|
|
* changes.
|
|
|
|
*/
|
|
|
|
enum class ChangeType {
|
|
|
|
Added,
|
|
|
|
Removed,
|
|
|
|
ApplicableStateChanged,
|
|
|
|
RuleAdded,
|
|
|
|
RuleRemoved,
|
|
|
|
RuleChanged,
|
|
|
|
};
|
|
|
|
|
2016-02-26 04:51:01 +03:00
|
|
|
void SetOwningNode(nsINode* aOwningNode) { mOwningNode = aOwningNode; }
|
|
|
|
|
2017-06-29 20:09:56 +03:00
|
|
|
css::SheetParsingMode ParsingMode() const { return mParsingMode; }
|
2019-11-30 14:57:10 +03:00
|
|
|
dom::CSSStyleSheetParsingMode ParsingModeDOM();
|
2016-08-02 23:17:06 +03:00
|
|
|
|
2016-03-02 02:10:45 +03:00
|
|
|
/**
|
|
|
|
* Whether the sheet is complete.
|
|
|
|
*/
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
bool IsComplete() const { return bool(mState & State::Complete); }
|
|
|
|
|
2016-03-02 02:10:45 +03:00
|
|
|
void SetComplete();
|
|
|
|
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
void SetEnabled(bool aEnabled) { SetDisabled(!aEnabled); }
|
2017-01-06 10:05:24 +03:00
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
// Whether the sheet is for an inline <style> element.
|
2018-04-30 20:47:12 +03:00
|
|
|
bool IsInline() const { return !GetOriginalURI(); }
|
|
|
|
|
|
|
|
nsIURI* GetSheetURI() const { return Inner().mSheetURI; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the URI this sheet was originally loaded from, if any. Can return null.
|
|
|
|
*/
|
|
|
|
nsIURI* GetOriginalURI() const { return Inner().mOriginalSheetURI; }
|
|
|
|
|
|
|
|
nsIURI* GetBaseURI() const { return Inner().mBaseURI; }
|
2016-09-26 15:03:25 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* SetURIs must be called on all sheets before parsing into them.
|
|
|
|
* SetURIs may only be called while the sheet is 1) incomplete and 2)
|
2018-04-30 20:47:12 +03:00
|
|
|
* has no rules in it.
|
|
|
|
*
|
|
|
|
* FIXME(emilio): Can we pass this down when constructing the sheet instead?
|
2016-09-26 15:03:25 +03:00
|
|
|
*/
|
2018-04-30 20:47:12 +03:00
|
|
|
inline void SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI,
|
2016-09-26 15:03:25 +03:00
|
|
|
nsIURI* aBaseURI);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether the sheet is applicable. A sheet that is not applicable
|
|
|
|
* should never be inserted into a style set. A sheet may not be
|
|
|
|
* applicable for a variety of reasons including being disabled and
|
|
|
|
* being incomplete.
|
|
|
|
*/
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
bool IsApplicable() const { return !Disabled() && IsComplete(); }
|
2016-09-26 15:03:25 +03:00
|
|
|
|
2018-04-30 18:50:03 +03:00
|
|
|
already_AddRefed<StyleSheet> Clone(
|
|
|
|
StyleSheet* aCloneParent, dom::CSSImportRule* aCloneOwnerRule,
|
2018-05-11 13:57:38 +03:00
|
|
|
dom::DocumentOrShadowRoot* aCloneDocumentOrShadowRoot,
|
2018-04-30 18:50:03 +03:00
|
|
|
nsINode* aCloneOwningNode) const;
|
2017-02-16 00:33:17 +03:00
|
|
|
|
2018-02-16 13:34:12 +03:00
|
|
|
bool HasForcedUniqueInner() const {
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
return bool(mState & State::ForcedUniqueInner);
|
2018-02-16 13:34:12 +03:00
|
|
|
}
|
|
|
|
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
bool HasModifiedRules() const { return bool(mState & State::ModifiedRules); }
|
2018-02-16 13:34:12 +03:00
|
|
|
|
2019-12-03 14:04:03 +03:00
|
|
|
bool HasModifiedRulesForDevtools() const {
|
|
|
|
return bool(mState & State::ModifiedRulesForDevtools);
|
|
|
|
}
|
2017-02-13 21:27:46 +03:00
|
|
|
|
2018-04-30 20:47:12 +03:00
|
|
|
bool HasUniqueInner() const { return Inner().mSheets.Length() == 1; }
|
|
|
|
|
|
|
|
void AssertHasUniqueInner() const { MOZ_ASSERT(HasUniqueInner()); }
|
|
|
|
|
2017-05-16 02:30:10 +03:00
|
|
|
void EnsureUniqueInner();
|
2017-05-16 02:19:17 +03:00
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
// style sheet owner info
|
2018-05-11 13:57:38 +03:00
|
|
|
enum AssociationMode : uint8_t {
|
|
|
|
// OwnedByDocumentOrShadowRoot means mDocumentOrShadowRoot owns us (possibly
|
|
|
|
// via a chain of other stylesheets).
|
|
|
|
OwnedByDocumentOrShadowRoot,
|
2017-01-20 07:49:44 +03:00
|
|
|
// NotOwnedByDocument means we're owned by something that might have a
|
|
|
|
// different lifetime than mDocument.
|
2018-05-11 13:57:38 +03:00
|
|
|
NotOwnedByDocumentOrShadowRoot
|
2017-01-20 07:49:44 +03:00
|
|
|
};
|
2018-05-11 13:57:38 +03:00
|
|
|
dom::DocumentOrShadowRoot* GetAssociatedDocumentOrShadowRoot() const {
|
|
|
|
return mDocumentOrShadowRoot;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Whether this stylesheet is kept alive by the associated document or
|
|
|
|
// associated shadow root's document somehow, and thus at least has the same
|
|
|
|
// lifetime as GetAssociatedDocument().
|
|
|
|
bool IsKeptAliveByDocument() const;
|
|
|
|
|
|
|
|
// Returns the document whose styles this sheet is affecting.
|
2019-01-02 16:05:23 +03:00
|
|
|
dom::Document* GetComposedDoc() const;
|
2018-05-11 13:57:38 +03:00
|
|
|
|
|
|
|
// Returns the document we're associated to, via mDocumentOrShadowRoot.
|
|
|
|
//
|
|
|
|
// Non-null iff GetAssociatedDocumentOrShadowRoot is non-null.
|
2019-01-02 16:05:23 +03:00
|
|
|
dom::Document* GetAssociatedDocument() const;
|
2018-05-11 13:57:38 +03:00
|
|
|
|
|
|
|
void SetAssociatedDocumentOrShadowRoot(dom::DocumentOrShadowRoot*,
|
|
|
|
AssociationMode);
|
|
|
|
void ClearAssociatedDocumentOrShadowRoot() {
|
|
|
|
SetAssociatedDocumentOrShadowRoot(nullptr, NotOwnedByDocumentOrShadowRoot);
|
2017-01-20 07:49:44 +03:00
|
|
|
}
|
2018-04-30 20:47:12 +03:00
|
|
|
|
|
|
|
nsINode* GetOwnerNode() const { return mOwningNode; }
|
|
|
|
|
|
|
|
StyleSheet* GetParentSheet() const { return mParent; }
|
2016-09-26 15:03:25 +03:00
|
|
|
|
2017-05-30 04:10:25 +03:00
|
|
|
void SetOwnerRule(dom::CSSImportRule* aOwnerRule) {
|
|
|
|
mOwnerRule = aOwnerRule; /* Not ref counted */
|
|
|
|
}
|
|
|
|
dom::CSSImportRule* GetOwnerRule() const { return mOwnerRule; }
|
|
|
|
|
2019-12-03 13:49:23 +03:00
|
|
|
void AppendStyleSheet(StyleSheet&);
|
2016-09-26 15:03:25 +03:00
|
|
|
|
2019-12-03 13:49:23 +03:00
|
|
|
// Append a stylesheet to the child list without calling WillDirty.
|
|
|
|
void AppendStyleSheetSilently(StyleSheet&);
|
2017-06-29 20:09:56 +03:00
|
|
|
|
2019-12-03 13:49:23 +03:00
|
|
|
const nsTArray<RefPtr<StyleSheet>>& ChildSheets() const {
|
|
|
|
#ifdef DEBUG
|
|
|
|
for (StyleSheet* child : Inner().mChildren) {
|
|
|
|
MOZ_ASSERT(child->GetParentSheet());
|
|
|
|
MOZ_ASSERT(child->GetParentSheet()->mInner == mInner);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return Inner().mChildren;
|
2017-05-30 04:10:25 +03:00
|
|
|
}
|
2017-01-24 02:52:56 +03:00
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
// Principal() never returns a null pointer.
|
2018-04-30 20:47:12 +03:00
|
|
|
nsIPrincipal* Principal() const { return Inner().mPrincipal; }
|
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
/**
|
|
|
|
* SetPrincipal should be called on all sheets before parsing into them.
|
2018-04-30 20:47:12 +03:00
|
|
|
* This can only be called once with a non-null principal.
|
|
|
|
*
|
|
|
|
* Calling this with a null pointer is allowed and is treated as a no-op.
|
|
|
|
*
|
|
|
|
* FIXME(emilio): Can we get this at construction time instead?
|
2016-09-26 15:03:25 +03:00
|
|
|
*/
|
2018-04-30 20:47:12 +03:00
|
|
|
void SetPrincipal(nsIPrincipal* aPrincipal) {
|
|
|
|
StyleSheetInfo& info = Inner();
|
|
|
|
MOZ_ASSERT(!info.mPrincipalSet, "Should only set principal once");
|
|
|
|
if (aPrincipal) {
|
|
|
|
info.mPrincipal = aPrincipal;
|
|
|
|
#ifdef DEBUG
|
|
|
|
info.mPrincipalSet = true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2016-09-26 15:03:25 +03:00
|
|
|
|
2017-01-06 10:05:24 +03:00
|
|
|
void SetTitle(const nsAString& aTitle) { mTitle = aTitle; }
|
2020-01-07 03:19:53 +03:00
|
|
|
void SetMedia(already_AddRefed<dom::MediaList> aMedia);
|
2017-01-06 10:05:24 +03:00
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
// Get this style sheet's CORS mode
|
2018-04-30 20:47:12 +03:00
|
|
|
CORSMode GetCORSMode() const { return Inner().mCORSMode; }
|
|
|
|
|
2019-07-16 14:43:39 +03:00
|
|
|
// Get this style sheet's ReferrerInfo
|
|
|
|
nsIReferrerInfo* GetReferrerInfo() const { return Inner().mReferrerInfo; }
|
2018-09-17 08:35:26 +03:00
|
|
|
|
2019-07-16 14:43:39 +03:00
|
|
|
// Set this style sheet's ReferrerInfo
|
|
|
|
void SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
|
|
|
|
Inner().mReferrerInfo = aReferrerInfo;
|
2018-04-30 20:47:12 +03:00
|
|
|
}
|
2019-07-16 14:43:39 +03:00
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
// Get this style sheet's integrity metadata
|
2018-04-30 20:47:12 +03:00
|
|
|
void GetIntegrity(dom::SRIMetadata& aResult) const {
|
|
|
|
aResult = Inner().mIntegrity;
|
|
|
|
}
|
2016-09-26 15:03:25 +03:00
|
|
|
|
2018-04-30 18:50:03 +03:00
|
|
|
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
|
2016-09-26 15:03:25 +03:00
|
|
|
#ifdef DEBUG
|
2018-04-30 18:50:03 +03:00
|
|
|
void List(FILE* aOut = stdout, int32_t aIndex = 0) const;
|
2016-09-26 15:03:25 +03:00
|
|
|
#endif
|
|
|
|
|
2016-10-14 14:25:38 +03:00
|
|
|
// WebIDL StyleSheet API
|
2018-01-11 11:17:57 +03:00
|
|
|
void GetType(nsAString& aType);
|
|
|
|
void GetHref(nsAString& aHref, ErrorResult& aRv);
|
2016-10-14 14:25:38 +03:00
|
|
|
// GetOwnerNode is defined above.
|
2018-04-30 20:47:12 +03:00
|
|
|
StyleSheet* GetParentStyleSheet() const { return GetParentSheet(); }
|
2018-01-11 11:17:57 +03:00
|
|
|
void GetTitle(nsAString& aTitle);
|
2016-11-09 09:28:24 +03:00
|
|
|
dom::MediaList* Media();
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
bool Disabled() const { return bool(mState & State::Disabled); }
|
2018-01-11 11:17:57 +03:00
|
|
|
void SetDisabled(bool aDisabled);
|
2017-06-29 02:51:46 +03:00
|
|
|
void GetSourceMapURL(nsAString& aTitle);
|
|
|
|
void SetSourceMapURL(const nsAString& aSourceMapURL);
|
2017-08-09 22:33:24 +03:00
|
|
|
void SetSourceMapURLFromComment(const nsAString& aSourceMapURLFromComment);
|
2017-09-14 23:59:32 +03:00
|
|
|
void GetSourceURL(nsAString& aSourceURL);
|
|
|
|
void SetSourceURL(const nsAString& aSourceURL);
|
2016-10-14 14:25:38 +03:00
|
|
|
|
2016-10-14 14:25:38 +03:00
|
|
|
// WebIDL CSSStyleSheet API
|
2017-05-30 04:10:25 +03:00
|
|
|
// Can't be inline because we can't include ImportRule here. And can't be
|
|
|
|
// called GetOwnerRule because that would be ambiguous with the ImportRule
|
|
|
|
// version.
|
|
|
|
css::Rule* GetDOMOwnerRule() const;
|
2018-04-30 18:50:03 +03:00
|
|
|
dom::CSSRuleList* GetCssRules(nsIPrincipal& aSubjectPrincipal, ErrorResult&);
|
2016-10-14 14:25:38 +03:00
|
|
|
uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
|
|
|
|
nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
|
|
|
|
void DeleteRule(uint32_t aIndex, nsIPrincipal& aSubjectPrincipal,
|
|
|
|
ErrorResult& aRv);
|
2019-05-09 15:32:52 +03:00
|
|
|
int32_t AddRule(const nsAString& aSelector, const nsAString& aBlock,
|
|
|
|
const dom::Optional<uint32_t>& aIndex,
|
|
|
|
nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
|
2020-01-01 00:58:40 +03:00
|
|
|
already_AddRefed<dom::Promise> Replace(const nsAString& aText, ErrorResult&);
|
|
|
|
void ReplaceSync(const nsAString& aText, ErrorResult&);
|
2016-10-14 14:25:38 +03:00
|
|
|
|
2016-10-14 14:25:38 +03:00
|
|
|
// WebIDL miscellaneous bits
|
|
|
|
inline dom::ParentObject GetParentObject() const;
|
2018-04-30 18:50:03 +03:00
|
|
|
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
|
2016-10-14 14:25:38 +03:00
|
|
|
|
2018-04-30 19:11:41 +03:00
|
|
|
// Changes to sheets should be after a WillDirty call.
|
2017-05-16 02:19:17 +03:00
|
|
|
void WillDirty();
|
2016-10-14 14:25:38 +03:00
|
|
|
|
2017-11-28 03:50:45 +03:00
|
|
|
// Called when a rule changes from CSSOM.
|
|
|
|
//
|
|
|
|
// FIXME(emilio): This shouldn't allow null, but MediaList doesn't know about
|
|
|
|
// it's owning media rule, plus it's used for the stylesheet media itself.
|
|
|
|
void RuleChanged(css::Rule*);
|
|
|
|
|
2018-03-29 14:15:46 +03:00
|
|
|
void AddStyleSet(ServoStyleSet* aStyleSet);
|
|
|
|
void DropStyleSet(ServoStyleSet* aStyleSet);
|
2017-05-16 02:27:15 +03:00
|
|
|
|
2017-03-08 10:04:15 +03:00
|
|
|
nsresult DeleteRuleFromGroup(css::GroupRule* aGroup, uint32_t aIndex);
|
|
|
|
nsresult InsertRuleIntoGroup(const nsAString& aRule, css::GroupRule* aGroup,
|
|
|
|
uint32_t aIndex);
|
|
|
|
|
2017-07-11 00:52:00 +03:00
|
|
|
// Find the ID of the owner inner window.
|
|
|
|
uint64_t FindOwningWindowInnerID() const;
|
|
|
|
|
2019-03-30 03:23:49 +03:00
|
|
|
// Copy the contents of this style sheet into the shared memory buffer managed
|
|
|
|
// by aBuilder. Returns the pointer into the buffer that the sheet contents
|
|
|
|
// were stored at. (The returned pointer is to an Arc<Locked<Rules>> value.)
|
|
|
|
const ServoCssRules* ToShared(RawServoSharedMemoryBuilder* aBuilder);
|
|
|
|
|
|
|
|
// Sets the contents of this style sheet to the specified aSharedRules
|
|
|
|
// pointer, which must be a pointer somewhere in the aSharedMemory buffer
|
|
|
|
// as previously returned by a ToShared() call.
|
2019-11-07 14:19:23 +03:00
|
|
|
void SetSharedContents(const ServoCssRules* aSharedRules);
|
2019-03-30 03:23:49 +03:00
|
|
|
|
2019-04-29 08:34:06 +03:00
|
|
|
// Whether this style sheet should not allow any modifications.
|
|
|
|
//
|
|
|
|
// This is true for any User Agent sheets once they are complete.
|
|
|
|
bool IsReadOnly() const;
|
|
|
|
|
2019-12-03 13:43:57 +03:00
|
|
|
// Removes a stylesheet from its parent sheet child list, if any.
|
|
|
|
void RemoveFromParent();
|
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
private:
|
2019-12-03 14:04:03 +03:00
|
|
|
void SetModifiedRules() {
|
|
|
|
mState |= State::ModifiedRules | State::ModifiedRulesForDevtools;
|
|
|
|
}
|
|
|
|
|
2019-11-30 15:24:24 +03:00
|
|
|
// Returns the ShadowRoot that contains this stylesheet or our ancestor
|
|
|
|
// stylesheet, if any.
|
|
|
|
//
|
|
|
|
// TODO(emilio): This may need to have multiple shadow roots with
|
|
|
|
// constructable stylesheets.
|
2018-03-17 00:56:05 +03:00
|
|
|
dom::ShadowRoot* GetContainingShadow() const;
|
|
|
|
|
2018-04-30 20:47:12 +03:00
|
|
|
StyleSheetInfo& Inner() {
|
|
|
|
MOZ_ASSERT(mInner);
|
|
|
|
return *mInner;
|
|
|
|
}
|
2018-04-30 18:50:03 +03:00
|
|
|
|
2018-04-30 20:47:12 +03:00
|
|
|
const StyleSheetInfo& Inner() const {
|
|
|
|
MOZ_ASSERT(mInner);
|
|
|
|
return *mInner;
|
|
|
|
}
|
2016-09-26 15:03:25 +03:00
|
|
|
|
2016-10-14 14:25:38 +03:00
|
|
|
// Check if the rules are available for read and write.
|
|
|
|
// It does the security check as well as whether the rules have been
|
|
|
|
// completely loaded. aRv will have an exception set if this function
|
|
|
|
// returns false.
|
2018-04-30 18:50:03 +03:00
|
|
|
bool AreRulesAvailable(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
|
2016-10-14 14:25:38 +03:00
|
|
|
|
2019-03-30 03:15:43 +03:00
|
|
|
void SetURLExtraData();
|
2018-09-17 08:36:45 +03:00
|
|
|
|
2016-02-26 04:51:01 +03:00
|
|
|
protected:
|
2018-04-30 18:50:03 +03:00
|
|
|
// Internal methods which do not have security check and completeness check.
|
|
|
|
uint32_t InsertRuleInternal(const nsAString& aRule, uint32_t aIndex,
|
|
|
|
ErrorResult&);
|
|
|
|
void DeleteRuleInternal(uint32_t aIndex, ErrorResult&);
|
|
|
|
nsresult InsertRuleIntoGroupInternal(const nsAString& aRule,
|
|
|
|
css::GroupRule* aGroup, uint32_t aIndex);
|
|
|
|
|
|
|
|
// Common tail routine for the synchronous and asynchronous parsing paths.
|
|
|
|
void FinishParse();
|
|
|
|
|
|
|
|
// Take the recently cloned sheets from the `@import` rules, and reparent them
|
|
|
|
// correctly to `aPrimarySheet`.
|
|
|
|
void BuildChildListAfterInnerClone();
|
|
|
|
|
|
|
|
void DropRuleList();
|
|
|
|
|
2017-11-28 03:50:45 +03:00
|
|
|
// Called when a rule is removed from the sheet from CSSOM.
|
|
|
|
void RuleAdded(css::Rule&);
|
|
|
|
|
|
|
|
// Called when a rule is added to the sheet from CSSOM.
|
|
|
|
void RuleRemoved(css::Rule&);
|
|
|
|
|
2019-05-22 09:01:51 +03:00
|
|
|
// Called when a stylesheet is cloned.
|
|
|
|
void StyleSheetCloned(StyleSheet&);
|
|
|
|
|
2018-03-17 00:56:05 +03:00
|
|
|
void ApplicableStateChanged(bool aApplicable);
|
|
|
|
|
2017-01-24 03:37:59 +03:00
|
|
|
void UnparentChildren();
|
|
|
|
|
2017-06-19 03:15:49 +03:00
|
|
|
void LastRelease();
|
|
|
|
|
2016-10-14 14:25:38 +03:00
|
|
|
// Return success if the subject principal subsumes the principal of our
|
2020-01-09 02:14:48 +03:00
|
|
|
// inner, error otherwise. This will also succeed if access is allowed by
|
|
|
|
// CORS. In that case, it will set the principal of the inner to the
|
|
|
|
// subject principal.
|
2016-10-14 14:25:38 +03:00
|
|
|
void SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal,
|
|
|
|
ErrorResult& aRv);
|
|
|
|
|
2017-01-06 10:05:24 +03:00
|
|
|
// Drop our reference to mMedia
|
|
|
|
void DropMedia();
|
|
|
|
|
2018-04-30 18:50:03 +03:00
|
|
|
// Unlink our inner, if needed, for cycle collection.
|
|
|
|
void UnlinkInner();
|
2017-02-16 03:19:33 +03:00
|
|
|
// Traverse our inner, if needed, for cycle collection
|
2018-04-30 18:50:03 +03:00
|
|
|
void TraverseInner(nsCycleCollectionTraversalCallback&);
|
2017-02-16 03:19:33 +03:00
|
|
|
|
2017-05-30 04:10:25 +03:00
|
|
|
// Return whether the given @import rule has pending child sheet.
|
|
|
|
static bool RuleHasPendingChildSheet(css::Rule* aRule);
|
|
|
|
|
2018-04-30 18:50:03 +03:00
|
|
|
StyleSheet* mParent; // weak ref
|
2017-01-25 00:09:33 +03:00
|
|
|
|
2020-01-01 00:58:40 +03:00
|
|
|
RefPtr<dom::Document> mConstructorDocument;
|
|
|
|
|
2018-04-30 18:50:03 +03:00
|
|
|
nsString mTitle;
|
2018-12-05 21:44:03 +03:00
|
|
|
|
|
|
|
// weak ref; parents maintain this for their children
|
|
|
|
dom::DocumentOrShadowRoot* mDocumentOrShadowRoot;
|
2018-04-30 18:50:03 +03:00
|
|
|
nsINode* mOwningNode; // weak ref
|
|
|
|
dom::CSSImportRule* mOwnerRule; // weak ref
|
2016-08-02 23:12:27 +03:00
|
|
|
|
2016-11-09 09:28:24 +03:00
|
|
|
RefPtr<dom::MediaList> mMedia;
|
2017-01-06 10:05:24 +03:00
|
|
|
|
2016-08-02 23:12:27 +03:00
|
|
|
// mParsingMode controls access to nonstandard style constructs that
|
|
|
|
// are not safe for use on the public Web but necessary in UA sheets
|
|
|
|
// and/or useful in user sheets.
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
//
|
|
|
|
// FIXME(emilio): Given we store the parsed contents in the Inner, this should
|
|
|
|
// probably also move there.
|
2016-02-26 04:51:01 +03:00
|
|
|
css::SheetParsingMode mParsingMode;
|
2016-08-02 23:12:27 +03:00
|
|
|
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
State mState;
|
2017-06-14 07:26:48 +03:00
|
|
|
|
2018-05-11 13:57:38 +03:00
|
|
|
// mAssociationMode determines whether mDocumentOrShadowRoot directly owns us
|
|
|
|
// (in the sense that if it's known-live then we're known-live).
|
|
|
|
//
|
|
|
|
// Always NotOwnedByDocumentOrShadowRoot when mDocumentOrShadowRoot is null.
|
|
|
|
AssociationMode mAssociationMode;
|
2017-01-24 02:36:09 +03:00
|
|
|
|
2017-02-14 20:41:33 +03:00
|
|
|
// Core information we get from parsed sheets, which are shared amongst
|
|
|
|
// StyleSheet clones.
|
2018-04-30 18:50:03 +03:00
|
|
|
//
|
Bug 1484690 - Move the enabled state to the sheet instead of sharing it. r=heycam
We share the inner object across sheets from the same URL, so what happens here
is that, once the sheet parses and loads, we call SetEnabled() on the first
sheet, which sets the inner bit, then calls ApplicableStateChanged.
That set actually turned the second sheet complete, so when inserting the sheet,
we think that the second sheet is already enabled, and thus in the author data,
and try to insert before it. Of course there's nothing there, so we panic.
We rely on calling SetEnabled() on all the sheets already to insert them in the
styleset / author data, so this makes it clearer and fixes the bug by moving the
state to each individual sheet.
Differential Revision: https://phabricator.services.mozilla.com/D3798
--HG--
extra : moz-landing-system : lando
2018-08-21 11:55:10 +03:00
|
|
|
// Always nonnull until LastRelease().
|
2017-02-14 20:41:33 +03:00
|
|
|
StyleSheetInfo* mInner;
|
|
|
|
|
2018-03-29 14:15:46 +03:00
|
|
|
nsTArray<ServoStyleSet*> mStyleSets;
|
2017-05-16 02:27:15 +03:00
|
|
|
|
2018-04-30 18:50:03 +03:00
|
|
|
RefPtr<ServoCSSRuleList> mRuleList;
|
2017-01-24 02:36:09 +03:00
|
|
|
|
2018-04-30 18:50:03 +03:00
|
|
|
MozPromiseHolder<StyleSheetParsePromise> mParsePromise;
|
2017-03-07 03:27:32 +03:00
|
|
|
|
|
|
|
// Make StyleSheetInfo and subclasses into friends so they can use
|
|
|
|
// ChildSheetListBuilder.
|
2019-11-30 14:57:10 +03:00
|
|
|
friend struct StyleSheetInfo;
|
2016-02-26 04:51:01 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // mozilla_StyleSheet_h
|