summaryrefslogtreecommitdiffstats
path: root/layout/style/StyleSheet.h
blob: 7a1a71466a8aeb474931b82bae4c837677cb49c7 (plain)
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
/* -*- 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"
#include "mozilla/dom/CSSStyleSheetBinding.h"
#include "mozilla/net/ReferrerPolicy.h"
#include "mozilla/StyleBackendType.h"
#include "mozilla/CORSMode.h"
#include "mozilla/ServoUtils.h"

#include "nsIDOMCSSStyleSheet.h"
#include "nsWrapperCache.h"

class nsIDocument;
class nsINode;
class nsIPrincipal;
class nsMediaList;

namespace mozilla {

class CSSStyleSheet;
class ServoStyleSheet;
struct StyleSheetInfo;

namespace dom {
class CSSRuleList;
class SRIMetadata;
} // namespace dom

/**
 * Superclass for data common to CSSStyleSheet and ServoStyleSheet.
 */
class StyleSheet : public nsIDOMCSSStyleSheet
                 , public nsWrapperCache
{
protected:
  StyleSheet(StyleBackendType aType, css::SheetParsingMode aParsingMode);
  StyleSheet(const StyleSheet& aCopy,
             nsIDocument* aDocumentToUse,
             nsINode* aOwningNodeToUse);
  virtual ~StyleSheet() {}

public:
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(StyleSheet)

  void SetOwningNode(nsINode* aOwningNode)
  {
    mOwningNode = aOwningNode;
  }

  css::SheetParsingMode ParsingMode() { return mParsingMode; }
  mozilla::dom::CSSStyleSheetParsingMode ParsingModeDOM();

  // The document this style sheet is associated with.  May be null
  nsIDocument* GetDocument() const { return mDocument; }

  /**
   * Whether the sheet is complete.
   */
  bool IsComplete() const;
  void SetComplete();

  MOZ_DECL_STYLO_METHODS(CSSStyleSheet, ServoStyleSheet)

  // Whether the sheet is for an inline <style> element.
  inline bool IsInline() const;

  inline nsIURI* GetSheetURI() const;
  /* Get the URI this sheet was originally loaded from, if any.  Can
     return null */
  inline nsIURI* GetOriginalURI() const;
  inline nsIURI* GetBaseURI() const;
  /**
   * SetURIs must be called on all sheets before parsing into them.
   * SetURIs may only be called while the sheet is 1) incomplete and 2)
   * has no rules in it
   */
  inline void SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI,
                      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.
   */
  inline bool IsApplicable() const;
  inline bool HasRules() const;

  // style sheet owner info
  enum DocumentAssociationMode {
    // OwnedByDocument means mDocument owns us (possibly via a chain of other
    // stylesheets).
    OwnedByDocument,
    // NotOwnedByDocument means we're owned by something that might have a
    // different lifetime than mDocument.
    NotOwnedByDocument
  };
  nsIDocument* GetAssociatedDocument() const { return mDocument; }
  bool IsOwnedByDocument() const {
    return mDocumentAssociationMode == OwnedByDocument;
  }
  // aDocument must not be null.
  inline void SetAssociatedDocument(nsIDocument* aDocument,
                                    DocumentAssociationMode aMode);
  inline void ClearAssociatedDocument();
  nsINode* GetOwnerNode() const { return mOwningNode; }
  inline StyleSheet* GetParentSheet() const;

  inline void AppendStyleSheet(StyleSheet* aSheet);

  // Principal() never returns a null pointer.
  inline nsIPrincipal* Principal() const;
  /**
   * SetPrincipal should be called on all sheets before parsing into them.
   * 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.
   */
  inline void SetPrincipal(nsIPrincipal* aPrincipal);

  // Get this style sheet's CORS mode
  inline CORSMode GetCORSMode() const;
  // Get this style sheet's Referrer Policy
  inline net::ReferrerPolicy GetReferrerPolicy() const;
  // Get this style sheet's integrity metadata
  inline void GetIntegrity(dom::SRIMetadata& aResult) const;

  inline size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
#ifdef DEBUG
  inline void List(FILE* aOut = stdout, int32_t aIndex = 0) const;
#endif

  // WebIDL StyleSheet API
  // The XPCOM GetType is fine for WebIDL.
  // The XPCOM GetHref is fine for WebIDL
  // GetOwnerNode is defined above.
  inline StyleSheet* GetParentStyleSheet() const;
  // The XPCOM GetTitle is fine for WebIDL.
  virtual nsMediaList* Media() = 0;
  bool Disabled() const { return mDisabled; }
  // The XPCOM SetDisabled is fine for WebIDL.

  // WebIDL CSSStyleSheet API
  virtual nsIDOMCSSRule* GetDOMOwnerRule() const = 0;
  dom::CSSRuleList* GetCssRules(nsIPrincipal& aSubjectPrincipal,
                                ErrorResult& aRv);
  uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
                      nsIPrincipal& aSubjectPrincipal,
                      ErrorResult& aRv);
  void DeleteRule(uint32_t aIndex,
                  nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aRv);
  int32_t AddRule(const nsAString& aSelector, const nsAString& aBlock,
                  const dom::Optional<uint32_t>& aIndex,
                  nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);

  // WebIDL miscellaneous bits
  inline dom::ParentObject GetParentObject() const;
  JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;

  // nsIDOMStyleSheet interface
  NS_IMETHOD GetType(nsAString& aType) final;
  NS_IMETHOD GetDisabled(bool* aDisabled) final;
  NS_IMETHOD SetDisabled(bool aDisabled) final;
  NS_IMETHOD GetOwnerNode(nsIDOMNode** aOwnerNode) final;
  NS_IMETHOD GetParentStyleSheet(nsIDOMStyleSheet** aParentStyleSheet) final;
  NS_IMETHOD GetHref(nsAString& aHref) final;
  NS_IMETHOD GetTitle(nsAString& aTitle) final;
  NS_IMETHOD GetMedia(nsIDOMMediaList** aMedia) final;

  // nsIDOMCSSStyleSheet
  NS_IMETHOD GetOwnerRule(nsIDOMCSSRule** aOwnerRule) final;
  NS_IMETHOD GetCssRules(nsIDOMCSSRuleList** aCssRules) final;
  NS_IMETHOD InsertRule(const nsAString& aRule, uint32_t aIndex,
                      uint32_t* aReturn) final;
  NS_IMETHOD DeleteRule(uint32_t aIndex) final;

  // Changes to sheets should be inside of a WillDirty-DidDirty pair.
  // However, the calls do not need to be matched; it's ok to call
  // WillDirty and then make no change and skip the DidDirty call.
  inline void WillDirty();
  inline void DidDirty();

private:
  // Get a handle to the various stylesheet bits which live on the 'inner' for
  // gecko stylesheets and live on the StyleSheet for Servo stylesheets.
  inline StyleSheetInfo& SheetInfo();
  inline const StyleSheetInfo& SheetInfo() const;

  // 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.
  bool AreRulesAvailable(nsIPrincipal& aSubjectPrincipal,
                         ErrorResult& aRv);

protected:
  // 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);

  nsString              mTitle;
  nsIDocument*          mDocument; // weak ref; parents maintain this for their children
  nsINode*              mOwningNode; // weak ref

  // 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.
  css::SheetParsingMode mParsingMode;

  const StyleBackendType mType;
  bool                  mDisabled;

  // mDocumentAssociationMode determines whether mDocument directly owns us (in
  // the sense that if it's known-live then we're known-live).  Always
  // NotOwnedByDocument when mDocument is null.
  DocumentAssociationMode mDocumentAssociationMode;
};

} // namespace mozilla

#endif // mozilla_StyleSheet_h