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/net/ReferrerPolicy.h"
|
|
|
|
#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-03-01 23:39:29 +03:00
|
|
|
class nsIDocument;
|
2016-02-26 04:51:01 +03:00
|
|
|
class nsINode;
|
2016-10-14 14:25:38 +03:00
|
|
|
class nsIPrincipal;
|
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-10-14 03:05:59 +03:00
|
|
|
enum class OriginFlags : uint8_t;
|
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;
|
|
|
|
} // 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.
|
|
|
|
//
|
|
|
|
// FIXME(emilio): I think as of right now we also set this flag for normal
|
|
|
|
// @import rules, which looks very fishy.
|
|
|
|
ModifiedRules = 1 << 3,
|
|
|
|
};
|
|
|
|
|
|
|
|
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,
|
|
|
|
net::ReferrerPolicy aReferrerPolicy,
|
|
|
|
const dom::SRIMetadata& aIntegrity);
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
// Parses a stylesheet. The aLoadData argument corresponds to the
|
|
|
|
// SheetLoadData for this stylesheet. It may be null in some cases.
|
|
|
|
RefPtr<StyleSheetParsePromise> ParseSheet(css::Loader* aLoader,
|
|
|
|
const nsACString& aBytes,
|
|
|
|
css::SheetLoadData* aLoadData);
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
// Similar to the above, but guarantees that parsing will be performed
|
|
|
|
// synchronously.
|
|
|
|
void ParseSheetSync(
|
|
|
|
css::Loader* aLoader, const nsACString& aBytes,
|
|
|
|
css::SheetLoadData* aLoadData, uint32_t aLineNumber,
|
|
|
|
css::LoaderReusableStyleSheets* aReusableSheets = nullptr);
|
|
|
|
|
|
|
|
nsresult ReparseSheet(const nsAString& aInput);
|
|
|
|
|
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
|
|
|
|
NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasAlternate,
|
|
|
|
nsresult aStatus) final;
|
|
|
|
|
|
|
|
// Internal GetCssRules methods which do not have security check and
|
|
|
|
// completeness check.
|
|
|
|
ServoCSSRuleList* GetCssRulesInternal();
|
|
|
|
|
|
|
|
// Returns the stylesheet's Servo origin as an OriginFlags value.
|
2018-10-14 03:05:59 +03:00
|
|
|
mozilla::OriginFlags GetOrigin();
|
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; }
|
2016-08-02 23:17:06 +03:00
|
|
|
mozilla::dom::CSSStyleSheetParsingMode ParsingModeDOM();
|
|
|
|
|
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
|
|
|
|
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 ClearModifiedRules() { mState &= ~State::ModifiedRules; }
|
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
|
|
|
|
2017-05-16 03:11:08 +03:00
|
|
|
// Append all of this sheet's child sheets to aArray.
|
|
|
|
void AppendAllChildSheets(nsTArray<StyleSheet*>& aArray);
|
|
|
|
|
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.
|
|
|
|
nsIDocument* GetComposedDoc() const;
|
|
|
|
|
|
|
|
// Returns the document we're associated to, via mDocumentOrShadowRoot.
|
|
|
|
//
|
|
|
|
// Non-null iff GetAssociatedDocumentOrShadowRoot is non-null.
|
|
|
|
nsIDocument* GetAssociatedDocument() const;
|
|
|
|
|
|
|
|
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; }
|
|
|
|
|
2017-05-30 04:10:25 +03:00
|
|
|
void PrependStyleSheet(StyleSheet* aSheet);
|
2016-09-26 15:03:25 +03:00
|
|
|
|
2018-04-30 19:11:41 +03:00
|
|
|
// Prepend a stylesheet to the child list without calling WillDirty.
|
2017-06-29 20:09:56 +03:00
|
|
|
void PrependStyleSheetSilently(StyleSheet* aSheet);
|
|
|
|
|
2017-01-24 02:52:56 +03:00
|
|
|
StyleSheet* GetFirstChild() const;
|
2017-05-30 04:10:25 +03:00
|
|
|
StyleSheet* GetMostRecentlyAddedChildSheet() const {
|
|
|
|
// New child sheet can only be prepended into the linked list of
|
|
|
|
// child sheets, so the most recently added one is always the first.
|
|
|
|
return GetFirstChild();
|
|
|
|
}
|
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; }
|
2016-11-09 09:28:24 +03:00
|
|
|
void SetMedia(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; }
|
|
|
|
|
2018-09-17 08:35:26 +03:00
|
|
|
// Set style sheet's Referrer Policy
|
|
|
|
void SetReferrerPolicy(net::ReferrerPolicy aReferrerPolicy);
|
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
// Get this style sheet's Referrer Policy
|
2018-04-30 20:47:12 +03:00
|
|
|
net::ReferrerPolicy GetReferrerPolicy() const {
|
|
|
|
return Inner().mReferrerPolicy;
|
|
|
|
}
|
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);
|
|
|
|
|
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;
|
|
|
|
|
2017-05-30 04:10:25 +03:00
|
|
|
template <typename Func>
|
|
|
|
void EnumerateChildSheets(Func aCallback) {
|
|
|
|
for (StyleSheet* child = GetFirstChild(); child; child = child->mNext) {
|
|
|
|
aCallback(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-26 15:03:25 +03:00
|
|
|
private:
|
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
|
|
|
|
2018-09-17 08:36:45 +03:00
|
|
|
already_AddRefed<URLExtraData> CreateURLExtraData() const;
|
|
|
|
|
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&);
|
|
|
|
|
2018-03-17 00:56:05 +03:00
|
|
|
void ApplicableStateChanged(bool aApplicable);
|
|
|
|
|
2017-03-07 03:27:32 +03:00
|
|
|
struct ChildSheetListBuilder {
|
|
|
|
RefPtr<StyleSheet>* sheetSlot;
|
|
|
|
StyleSheet* parent;
|
|
|
|
|
|
|
|
void SetParentLinks(StyleSheet* aSheet);
|
|
|
|
|
|
|
|
static void ReparentChildList(StyleSheet* aPrimarySheet,
|
|
|
|
StyleSheet* aFirstChild);
|
|
|
|
};
|
|
|
|
|
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
|
|
|
|
// inner, error otherwise. This will also succeed if the subject has
|
|
|
|
// UniversalXPConnect or if access is allowed by CORS. In the latter case,
|
|
|
|
// it will set the principal of the inner to the subject principal.
|
|
|
|
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
|
|
|
|
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
|
|
|
|
2017-01-24 02:36:09 +03:00
|
|
|
RefPtr<StyleSheet> mNext;
|
|
|
|
|
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.
|
|
|
|
friend struct mozilla::StyleSheetInfo;
|
2016-02-26 04:51:01 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // mozilla_StyleSheet_h
|