Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /* rules in a CSS stylesheet other than style rules (e.g., @import rules) */
7 :
8 : #include "nsCSSRules.h"
9 : #include "nsCSSCounterStyleRule.h"
10 : #include "nsCSSFontFaceRule.h"
11 :
12 : #include "mozilla/Attributes.h"
13 :
14 : #include "nsCSSValue.h"
15 : #include "mozilla/StyleSheetInlines.h"
16 : #include "mozilla/MemoryReporting.h"
17 : #include "mozilla/css/ImportRule.h"
18 : #include "mozilla/css/NameSpaceRule.h"
19 :
20 : #include "nsString.h"
21 : #include "nsIAtom.h"
22 :
23 : #include "nsCSSProps.h"
24 :
25 : #include "nsCOMPtr.h"
26 : #include "nsIDOMCSSStyleSheet.h"
27 : #include "nsMediaList.h"
28 : #include "mozilla/dom/CSSRuleList.h"
29 : #include "nsIDocument.h"
30 : #include "nsPresContext.h"
31 :
32 : #include "nsContentUtils.h"
33 : #include "nsError.h"
34 : #include "nsStyleUtil.h"
35 : #include "mozilla/DeclarationBlockInlines.h"
36 : #include "nsCSSParser.h"
37 : #include "nsDOMClassInfoID.h"
38 : #include "mozilla/dom/CSSStyleDeclarationBinding.h"
39 : #include "mozilla/dom/CSSFontFaceRuleBinding.h"
40 : #include "mozilla/dom/CSSFontFeatureValuesRuleBinding.h"
41 : #include "mozilla/dom/CSSCounterStyleRuleBinding.h"
42 : #include "StyleRule.h"
43 : #include "nsFont.h"
44 : #include "nsIURI.h"
45 : #include "mozAutoDocUpdate.h"
46 : #include "nsCCUncollectableMarker.h"
47 : #include "nsWrapperCacheInlines.h"
48 :
49 : using namespace mozilla;
50 : using namespace mozilla::dom;
51 :
52 : // base class for all rule types in a CSS style sheet
53 :
54 : namespace mozilla {
55 : namespace css {
56 :
57 6692 : NS_IMPL_CYCLE_COLLECTING_ADDREF(Rule)
58 3427 : NS_IMPL_CYCLE_COLLECTING_RELEASE(Rule)
59 :
60 266 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Rule)
61 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
62 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
63 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
64 0 : NS_INTERFACE_MAP_END
65 :
66 16 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(Rule)
67 :
68 : bool
69 0 : Rule::IsCCLeaf() const
70 : {
71 0 : return !PreservingWrapper();
72 : }
73 :
74 : bool
75 0 : Rule::IsKnownLive() const
76 : {
77 0 : if (HasKnownLiveWrapper()) {
78 0 : return true;
79 : }
80 :
81 0 : StyleSheet* sheet = GetStyleSheet();
82 0 : if (!sheet) {
83 0 : return false;
84 : }
85 :
86 0 : if (!sheet->IsOwnedByDocument()) {
87 0 : return false;
88 : }
89 :
90 0 : return nsCCUncollectableMarker::InGeneration(
91 0 : sheet->GetAssociatedDocument()->GetMarkedCCGeneration());
92 : }
93 :
94 0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Rule)
95 0 : return tmp->IsCCLeaf() || tmp->IsKnownLive();
96 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
97 :
98 0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Rule)
99 : // Please see documentation for nsCycleCollectionParticipant::CanSkip* for why
100 : // we need to check HasNothingToTrace here but not in the other two CanSkip
101 : // methods.
102 0 : return tmp->IsCCLeaf() ||
103 0 : (tmp->IsKnownLive() && tmp->HasNothingToTrace(tmp));
104 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
105 :
106 0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Rule)
107 0 : return tmp->IsCCLeaf() || tmp->IsKnownLive();
108 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
109 :
110 : /* virtual */ void
111 3488 : Rule::SetStyleSheet(StyleSheet* aSheet)
112 : {
113 : // We don't reference count this up reference. The style sheet
114 : // will tell us when it's going away or when we're detached from
115 : // it.
116 3488 : mSheet = aSheet;
117 3488 : }
118 :
119 : NS_IMETHODIMP
120 0 : Rule::GetParentRule(nsIDOMCSSRule** aParentRule)
121 : {
122 0 : NS_IF_ADDREF(*aParentRule = mParentRule);
123 0 : return NS_OK;
124 : }
125 :
126 : NS_IMETHODIMP
127 0 : Rule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
128 : {
129 0 : NS_ENSURE_ARG_POINTER(aSheet);
130 :
131 0 : NS_IF_ADDREF(*aSheet = GetStyleSheet());
132 0 : return NS_OK;
133 : }
134 :
135 : /* virtual */ css::Rule*
136 0 : Rule::GetCSSRule()
137 : {
138 0 : return this;
139 : }
140 :
141 : NS_IMETHODIMP
142 0 : Rule::GetType(uint16_t* aType)
143 : {
144 0 : *aType = Type();
145 0 : return NS_OK;
146 : }
147 :
148 : NS_IMETHODIMP
149 0 : Rule::SetCssText(const nsAString& aCssText)
150 : {
151 : // We used to throw for some rule types, but not all. Specifically, we did
152 : // not throw for StyleRule. Let's just always not throw.
153 0 : return NS_OK;
154 : }
155 :
156 : NS_IMETHODIMP
157 0 : Rule::GetCssText(nsAString& aCssText)
158 : {
159 0 : GetCssTextImpl(aCssText);
160 0 : return NS_OK;
161 : }
162 :
163 : Rule*
164 0 : Rule::GetParentRule() const
165 : {
166 0 : return mParentRule;
167 : }
168 :
169 : // -------------------------------------------
170 : // ImportRule
171 : //
172 :
173 3 : ImportRule::ImportRule(nsMediaList* aMedia, const nsString& aURLSpec,
174 3 : uint32_t aLineNumber, uint32_t aColumnNumber)
175 : : CSSImportRule(aLineNumber, aColumnNumber)
176 : , mURLSpec(aURLSpec)
177 3 : , mMedia(aMedia)
178 : {
179 3 : MOZ_ASSERT(aMedia);
180 : // XXXbz This is really silly.... the mMedia here will be replaced
181 : // with itself if we manage to load a sheet. Which should really
182 : // never fail nowadays, in sane cases.
183 3 : }
184 :
185 0 : ImportRule::ImportRule(const ImportRule& aCopy)
186 : : CSSImportRule(aCopy),
187 0 : mURLSpec(aCopy.mURLSpec)
188 : {
189 : // Whether or not an @import rule has a null sheet is a permanent
190 : // property of that @import rule, since it is null only if the target
191 : // sheet failed security checks.
192 0 : if (aCopy.mChildSheet) {
193 : RefPtr<StyleSheet> sheet =
194 0 : aCopy.mChildSheet->Clone(nullptr, this, nullptr, nullptr);
195 0 : SetSheet(static_cast<CSSStyleSheet*>(sheet.get()));
196 : // SetSheet sets mMedia appropriately
197 : } else {
198 : // We better just copy mMedia from aCopy, since we have nowhere else to get
199 : // one.
200 0 : mMedia = aCopy.mMedia;
201 : }
202 0 : }
203 :
204 0 : ImportRule::~ImportRule()
205 : {
206 0 : if (mChildSheet) {
207 0 : mChildSheet->SetOwnerRule(nullptr);
208 : }
209 0 : }
210 :
211 6 : NS_IMPL_ADDREF_INHERITED(ImportRule, CSSImportRule)
212 3 : NS_IMPL_RELEASE_INHERITED(ImportRule, CSSImportRule)
213 :
214 0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(ImportRule, CSSImportRule, mMedia, mChildSheet)
215 :
216 : // QueryInterface implementation for ImportRule
217 3 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ImportRule)
218 0 : NS_INTERFACE_MAP_END_INHERITING(CSSImportRule)
219 :
220 : #ifdef DEBUG
221 : /* virtual */ void
222 0 : ImportRule::List(FILE* out, int32_t aIndent) const
223 : {
224 0 : nsAutoCString str;
225 : // Indent
226 0 : for (int32_t indent = aIndent; --indent >= 0; ) {
227 0 : str.AppendLiteral(" ");
228 : }
229 :
230 0 : str.AppendLiteral("@import \"");
231 0 : AppendUTF16toUTF8(mURLSpec, str);
232 0 : str.AppendLiteral("\" ");
233 :
234 0 : nsAutoString mediaText;
235 0 : mMedia->GetText(mediaText);
236 0 : AppendUTF16toUTF8(mediaText, str);
237 0 : str.AppendLiteral("\n");
238 0 : fprintf_stderr(out, "%s", str.get());
239 0 : }
240 : #endif
241 :
242 : /* virtual */ already_AddRefed<Rule>
243 0 : ImportRule::Clone() const
244 : {
245 0 : RefPtr<Rule> clone = new ImportRule(*this);
246 0 : return clone.forget();
247 : }
248 :
249 : void
250 3 : ImportRule::SetSheet(CSSStyleSheet* aSheet)
251 : {
252 3 : NS_PRECONDITION(aSheet, "null arg");
253 :
254 : // set the new sheet
255 3 : mChildSheet = aSheet;
256 3 : aSheet->SetOwnerRule(this);
257 :
258 : // set our medialist to be the same as the sheet's medialist
259 3 : mMedia = static_cast<nsMediaList*>(mChildSheet->Media());
260 3 : }
261 :
262 : void
263 0 : ImportRule::GetCssTextImpl(nsAString& aCssText) const
264 : {
265 0 : aCssText.AssignLiteral("@import url(");
266 0 : nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
267 0 : aCssText.Append(')');
268 0 : if (mMedia) {
269 0 : nsAutoString mediaText;
270 0 : mMedia->GetText(mediaText);
271 0 : if (!mediaText.IsEmpty()) {
272 0 : aCssText.Append(' ');
273 0 : aCssText.Append(mediaText);
274 : }
275 : }
276 0 : aCssText.Append(';');
277 0 : }
278 :
279 : MediaList*
280 0 : ImportRule::GetMedia() const
281 : {
282 0 : return mMedia;
283 : }
284 :
285 : StyleSheet*
286 8 : ImportRule::GetStyleSheet() const
287 : {
288 8 : return mChildSheet;
289 : }
290 :
291 : NS_IMETHODIMP
292 0 : ImportRule::GetHref(nsAString & aHref)
293 : {
294 0 : aHref = mURLSpec;
295 0 : return NS_OK;
296 : }
297 :
298 : /* virtual */ size_t
299 0 : ImportRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
300 : {
301 0 : return aMallocSizeOf(this);
302 :
303 : // Measurement of the following members may be added later if DMD finds it is
304 : // worthwhile:
305 : // - mURLSpec
306 : //
307 : // The following members are not measured:
308 : // - mMedia, because it is measured via CSSStyleSheet::mMedia
309 : // - mChildSheet, because it is measured via CSSStyleSheetInner::mSheets
310 : }
311 :
312 : // -------------------------------------------
313 : // nsICSSMediaRule
314 : //
315 48 : MediaRule::MediaRule(uint32_t aLineNumber, uint32_t aColumnNumber)
316 48 : : CSSMediaRule(aLineNumber, aColumnNumber)
317 : {
318 48 : }
319 :
320 0 : MediaRule::MediaRule(const MediaRule& aCopy)
321 0 : : CSSMediaRule(aCopy)
322 : {
323 0 : if (aCopy.mMedia) {
324 0 : mMedia = aCopy.mMedia->Clone().downcast<nsMediaList>();
325 : // XXXldb This doesn't really make sense.
326 0 : mMedia->SetStyleSheet(aCopy.GetStyleSheet());
327 : }
328 0 : }
329 :
330 0 : MediaRule::~MediaRule()
331 : {
332 0 : if (mMedia) {
333 0 : mMedia->SetStyleSheet(nullptr);
334 : }
335 0 : }
336 :
337 144 : NS_IMPL_ADDREF_INHERITED(MediaRule, CSSMediaRule)
338 96 : NS_IMPL_RELEASE_INHERITED(MediaRule, CSSMediaRule)
339 :
340 : // QueryInterface implementation for MediaRule
341 48 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaRule)
342 0 : NS_INTERFACE_MAP_END_INHERITING(CSSMediaRule)
343 :
344 0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaRule, CSSMediaRule,
345 : mMedia)
346 :
347 : /* virtual */ void
348 48 : MediaRule::SetStyleSheet(StyleSheet* aSheet)
349 : {
350 48 : if (mMedia) {
351 : // Set to null so it knows it's leaving one sheet and joining another.
352 0 : mMedia->SetStyleSheet(nullptr);
353 0 : if (aSheet) {
354 0 : mMedia->SetStyleSheet(aSheet->AsGecko());
355 : }
356 : }
357 :
358 48 : GroupRule::SetStyleSheet(aSheet);
359 48 : }
360 :
361 : #ifdef DEBUG
362 : /* virtual */ void
363 0 : MediaRule::List(FILE* out, int32_t aIndent) const
364 : {
365 0 : nsAutoCString indentStr;
366 0 : for (int32_t indent = aIndent; --indent >= 0; ) {
367 0 : indentStr.AppendLiteral(" ");
368 : }
369 :
370 0 : nsAutoCString str(indentStr);
371 0 : str.AppendLiteral("@media ");
372 :
373 0 : if (mMedia) {
374 0 : nsAutoString mediaText;
375 0 : mMedia->GetText(mediaText);
376 0 : AppendUTF16toUTF8(mediaText, str);
377 : }
378 :
379 0 : str.AppendLiteral(" {\n");
380 0 : fprintf_stderr(out, "%s", str.get());
381 :
382 0 : GroupRule::List(out, aIndent);
383 :
384 0 : fprintf_stderr(out, "%s}\n", indentStr.get());
385 0 : }
386 : #endif
387 :
388 : /* virtual */ already_AddRefed<Rule>
389 0 : MediaRule::Clone() const
390 : {
391 0 : RefPtr<Rule> clone = new MediaRule(*this);
392 0 : return clone.forget();
393 : }
394 :
395 : nsresult
396 48 : MediaRule::SetMedia(nsMediaList* aMedia)
397 : {
398 48 : mMedia = aMedia;
399 48 : if (aMedia)
400 48 : mMedia->SetStyleSheet(GetStyleSheet());
401 48 : return NS_OK;
402 : }
403 :
404 : MediaList*
405 0 : MediaRule::Media()
406 : {
407 : // In practice, if we end up being parsed at all, we have non-null mMedia. So
408 : // it's OK to claim we don't return null here.
409 0 : return mMedia;
410 : }
411 :
412 : void
413 0 : MediaRule::GetCssTextImpl(nsAString& aCssText) const
414 : {
415 0 : aCssText.AssignLiteral("@media ");
416 0 : AppendConditionText(aCssText);
417 0 : GroupRule::AppendRulesToCssText(aCssText);
418 0 : }
419 :
420 : // nsIDOMCSSConditionRule methods
421 : NS_IMETHODIMP
422 0 : MediaRule::GetConditionText(nsAString& aConditionText)
423 : {
424 0 : aConditionText.Truncate(0);
425 0 : AppendConditionText(aConditionText);
426 0 : return NS_OK;
427 : }
428 :
429 : NS_IMETHODIMP
430 0 : MediaRule::SetConditionText(const nsAString& aConditionText)
431 : {
432 0 : if (!mMedia) {
433 0 : RefPtr<nsMediaList> media = new nsMediaList();
434 0 : media->SetStyleSheet(GetStyleSheet());
435 0 : nsresult rv = media->SetMediaText(aConditionText);
436 0 : if (NS_SUCCEEDED(rv)) {
437 0 : mMedia = media;
438 : }
439 0 : return rv;
440 : }
441 :
442 0 : return mMedia->SetMediaText(aConditionText);
443 : }
444 :
445 : // GroupRule interface
446 : /* virtual */ bool
447 149 : MediaRule::UseForPresentation(nsPresContext* aPresContext,
448 : nsMediaQueryResultCacheKey& aKey)
449 : {
450 149 : if (mMedia) {
451 149 : MOZ_ASSERT(aPresContext);
452 149 : return mMedia->Matches(aPresContext, &aKey);
453 : }
454 0 : return true;
455 : }
456 :
457 : /* virtual */ size_t
458 0 : MediaRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
459 : {
460 0 : size_t n = aMallocSizeOf(this);
461 0 : n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
462 :
463 : // Measurement of the following members may be added later if DMD finds it is
464 : // worthwhile:
465 : // - mMedia
466 :
467 0 : return n;
468 : }
469 :
470 : void
471 0 : MediaRule::AppendConditionText(nsAString& aOutput) const
472 : {
473 0 : if (mMedia) {
474 0 : nsAutoString mediaText;
475 0 : mMedia->GetText(mediaText);
476 0 : aOutput.Append(mediaText);
477 : }
478 0 : }
479 :
480 2 : DocumentRule::DocumentRule(uint32_t aLineNumber, uint32_t aColumnNumber)
481 2 : : dom::CSSMozDocumentRule(aLineNumber, aColumnNumber)
482 : {
483 2 : }
484 :
485 0 : DocumentRule::DocumentRule(const DocumentRule& aCopy)
486 : : dom::CSSMozDocumentRule(aCopy)
487 0 : , mURLs(new URL(*aCopy.mURLs))
488 : {
489 0 : }
490 :
491 0 : DocumentRule::~DocumentRule()
492 : {
493 0 : }
494 :
495 6 : NS_IMPL_ADDREF_INHERITED(DocumentRule, ConditionRule)
496 4 : NS_IMPL_RELEASE_INHERITED(DocumentRule, ConditionRule)
497 :
498 : // QueryInterface implementation for DocumentRule
499 2 : NS_INTERFACE_MAP_BEGIN(DocumentRule)
500 2 : NS_INTERFACE_MAP_END_INHERITING(dom::CSSMozDocumentRule)
501 :
502 : #ifdef DEBUG
503 : /* virtual */ void
504 0 : DocumentRule::List(FILE* out, int32_t aIndent) const
505 : {
506 0 : nsAutoCString indentStr;
507 0 : for (int32_t indent = aIndent; --indent >= 0; ) {
508 0 : indentStr.AppendLiteral(" ");
509 : }
510 :
511 0 : nsAutoCString str;
512 0 : str.AppendLiteral("@-moz-document ");
513 0 : for (URL *url = mURLs; url; url = url->next) {
514 0 : switch (url->func) {
515 : case URLMatchingFunction::eURL:
516 0 : str.AppendLiteral("url(\"");
517 0 : break;
518 : case URLMatchingFunction::eURLPrefix:
519 0 : str.AppendLiteral("url-prefix(\"");
520 0 : break;
521 : case URLMatchingFunction::eDomain:
522 0 : str.AppendLiteral("domain(\"");
523 0 : break;
524 : case URLMatchingFunction::eRegExp:
525 0 : str.AppendLiteral("regexp(\"");
526 0 : break;
527 : }
528 0 : nsAutoCString escapedURL(url->url);
529 0 : escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes
530 0 : str.Append(escapedURL);
531 0 : str.AppendLiteral("\"), ");
532 : }
533 0 : str.Cut(str.Length() - 2, 1); // remove last ,
534 0 : fprintf_stderr(out, "%s%s {\n", indentStr.get(), str.get());
535 :
536 0 : GroupRule::List(out, aIndent);
537 :
538 0 : fprintf_stderr(out, "%s}\n", indentStr.get());
539 0 : }
540 : #endif
541 :
542 : /* virtual */ already_AddRefed<Rule>
543 0 : DocumentRule::Clone() const
544 : {
545 0 : RefPtr<Rule> clone = new DocumentRule(*this);
546 0 : return clone.forget();
547 : }
548 :
549 : void
550 0 : DocumentRule::GetCssTextImpl(nsAString& aCssText) const
551 : {
552 0 : aCssText.AssignLiteral("@-moz-document ");
553 0 : AppendConditionText(aCssText);
554 0 : GroupRule::AppendRulesToCssText(aCssText);
555 0 : }
556 :
557 : // nsIDOMCSSConditionRule methods
558 : NS_IMETHODIMP
559 0 : DocumentRule::GetConditionText(nsAString& aConditionText)
560 : {
561 0 : aConditionText.Truncate(0);
562 0 : AppendConditionText(aConditionText);
563 0 : return NS_OK;
564 : }
565 :
566 : NS_IMETHODIMP
567 0 : DocumentRule::SetConditionText(const nsAString& aConditionText)
568 : {
569 0 : return NS_ERROR_NOT_IMPLEMENTED;
570 : }
571 :
572 : // GroupRule interface
573 : /* virtual */ bool
574 0 : DocumentRule::UseForPresentation(nsPresContext* aPresContext,
575 : nsMediaQueryResultCacheKey& aKey)
576 : {
577 0 : return UseForPresentation(aPresContext);
578 : }
579 :
580 : bool
581 11 : DocumentRule::UseForPresentation(nsPresContext* aPresContext)
582 : {
583 11 : nsIDocument *doc = aPresContext->Document();
584 11 : nsIURI *docURI = doc->GetDocumentURI();
585 22 : nsAutoCString docURISpec;
586 11 : if (docURI) {
587 : // If GetSpec fails (due to OOM) just skip these URI-specific CSS rules.
588 11 : nsresult rv = docURI->GetSpec(docURISpec);
589 11 : NS_ENSURE_SUCCESS(rv, false);
590 : }
591 :
592 18 : for (URL *url = mURLs; url; url = url->next) {
593 11 : if (UseForPresentation(doc, docURI, docURISpec, url->url, url->func)) {
594 4 : return true;
595 : }
596 : }
597 :
598 7 : return false;
599 : }
600 :
601 : bool
602 11 : DocumentRule::UseForPresentation(nsIDocument* aDoc,
603 : nsIURI* aDocURI,
604 : const nsACString& aDocURISpec,
605 : const nsACString& aPattern,
606 : URLMatchingFunction aUrlMatchingFunction)
607 : {
608 11 : switch (aUrlMatchingFunction) {
609 : case URLMatchingFunction::eURL: {
610 0 : if (aDocURISpec == aPattern) {
611 0 : return true;
612 : }
613 0 : } break;
614 : case URLMatchingFunction::eURLPrefix: {
615 11 : if (StringBeginsWith(aDocURISpec, aPattern)) {
616 4 : return true;
617 : }
618 7 : } break;
619 : case URLMatchingFunction::eDomain: {
620 0 : nsAutoCString host;
621 0 : if (aDocURI) {
622 0 : aDocURI->GetHost(host);
623 : }
624 0 : int32_t lenDiff = host.Length() - aPattern.Length();
625 0 : if (lenDiff == 0) {
626 0 : if (host == aPattern) {
627 0 : return true;
628 : }
629 : } else {
630 0 : if (StringEndsWith(host, aPattern) &&
631 0 : host.CharAt(lenDiff - 1) == '.') {
632 0 : return true;
633 : }
634 : }
635 0 : } break;
636 : case URLMatchingFunction::eRegExp: {
637 0 : NS_ConvertUTF8toUTF16 spec(aDocURISpec);
638 0 : NS_ConvertUTF8toUTF16 regex(aPattern);
639 0 : if (nsContentUtils::IsPatternMatching(spec, regex, aDoc)) {
640 0 : return true;
641 : }
642 0 : } break;
643 : }
644 :
645 7 : return false;
646 : }
647 :
648 0 : DocumentRule::URL::~URL()
649 : {
650 0 : NS_CSS_DELETE_LIST_MEMBER(DocumentRule::URL, this, next);
651 0 : }
652 :
653 : /* virtual */ size_t
654 0 : DocumentRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
655 : {
656 0 : size_t n = aMallocSizeOf(this);
657 0 : n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
658 :
659 : // Measurement of the following members may be added later if DMD finds it is
660 : // worthwhile:
661 : // - mURLs
662 :
663 0 : return n;
664 : }
665 :
666 : void
667 0 : DocumentRule::AppendConditionText(nsAString& aCssText) const
668 : {
669 0 : for (URL *url = mURLs; url; url = url->next) {
670 0 : switch (url->func) {
671 : case URLMatchingFunction::eURL:
672 0 : aCssText.AppendLiteral("url(");
673 0 : break;
674 : case URLMatchingFunction::eURLPrefix:
675 0 : aCssText.AppendLiteral("url-prefix(");
676 0 : break;
677 : case URLMatchingFunction::eDomain:
678 0 : aCssText.AppendLiteral("domain(");
679 0 : break;
680 : case URLMatchingFunction::eRegExp:
681 0 : aCssText.AppendLiteral("regexp(");
682 0 : break;
683 : }
684 0 : nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(url->url),
685 0 : aCssText);
686 0 : aCssText.AppendLiteral("), ");
687 : }
688 0 : aCssText.Truncate(aCssText.Length() - 2); // remove last ", "
689 0 : }
690 :
691 : // -------------------------------------------
692 : // NameSpaceRule
693 : //
694 :
695 64 : NameSpaceRule::NameSpaceRule(nsIAtom* aPrefix, const nsString& aURLSpec,
696 64 : uint32_t aLineNumber, uint32_t aColumnNumber)
697 : : CSSNamespaceRule(aLineNumber, aColumnNumber),
698 : mPrefix(aPrefix),
699 64 : mURLSpec(aURLSpec)
700 : {
701 64 : }
702 :
703 0 : NameSpaceRule::NameSpaceRule(const NameSpaceRule& aCopy)
704 : : CSSNamespaceRule(aCopy),
705 : mPrefix(aCopy.mPrefix),
706 0 : mURLSpec(aCopy.mURLSpec)
707 : {
708 0 : }
709 :
710 0 : NameSpaceRule::~NameSpaceRule()
711 : {
712 0 : }
713 :
714 192 : NS_IMPL_ADDREF_INHERITED(NameSpaceRule, CSSNamespaceRule)
715 128 : NS_IMPL_RELEASE_INHERITED(NameSpaceRule, CSSNamespaceRule)
716 :
717 : // QueryInterface implementation for NameSpaceRule
718 : // If this ever gets its own cycle-collection bits, reevaluate our IsCCLeaf
719 : // implementation.
720 128 : NS_INTERFACE_MAP_BEGIN(NameSpaceRule)
721 128 : if (aIID.Equals(NS_GET_IID(css::NameSpaceRule))) {
722 64 : *aInstancePtr = this;
723 64 : NS_ADDREF_THIS();
724 64 : return NS_OK;
725 : }
726 : else
727 64 : NS_INTERFACE_MAP_END_INHERITING(CSSNamespaceRule)
728 :
729 : #ifdef DEBUG
730 : /* virtual */ void
731 0 : NameSpaceRule::List(FILE* out, int32_t aIndent) const
732 : {
733 0 : nsAutoCString str;
734 0 : for (int32_t indent = aIndent; --indent >= 0; ) {
735 0 : str.AppendLiteral(" ");
736 : }
737 :
738 0 : nsAutoString buffer;
739 :
740 0 : str.AppendLiteral("@namespace ");
741 :
742 0 : if (mPrefix) {
743 0 : mPrefix->ToString(buffer);
744 0 : AppendUTF16toUTF8(buffer, str);
745 0 : str.Append(' ');
746 : }
747 :
748 0 : str.AppendLiteral("url(\"");
749 0 : AppendUTF16toUTF8(mURLSpec, str);
750 0 : str.AppendLiteral("\")\n");
751 0 : fprintf_stderr(out, "%s", str.get());
752 0 : }
753 : #endif
754 :
755 : /* virtual */ already_AddRefed<Rule>
756 0 : NameSpaceRule::Clone() const
757 : {
758 0 : RefPtr<Rule> clone = new NameSpaceRule(*this);
759 0 : return clone.forget();
760 : }
761 :
762 : void
763 0 : NameSpaceRule::GetCssTextImpl(nsAString& aCssText) const
764 : {
765 0 : aCssText.AssignLiteral("@namespace ");
766 0 : if (mPrefix) {
767 0 : aCssText.Append(nsDependentAtomString(mPrefix) + NS_LITERAL_STRING(" "));
768 : }
769 0 : aCssText.AppendLiteral("url(");
770 0 : nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
771 0 : aCssText.AppendLiteral(");");
772 0 : }
773 :
774 : /* virtual */ size_t
775 0 : NameSpaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
776 : {
777 0 : return aMallocSizeOf(this);
778 :
779 : // Measurement of the following members may be added later if DMD finds it is
780 : // worthwhile:
781 : // - mPrefix
782 : // - mURLSpec
783 : }
784 :
785 : } // namespace css
786 : } // namespace mozilla
787 :
788 : // -------------------------------------------
789 : // nsCSSFontFaceStyleDecl and related routines
790 : //
791 :
792 : // Mapping from nsCSSFontDesc codes to CSSFontFaceDescriptors fields.
793 : nsCSSValue CSSFontFaceDescriptors::* const
794 : CSSFontFaceDescriptors::Fields[] = {
795 : #define CSS_FONT_DESC(name_, method_) &CSSFontFaceDescriptors::m##method_,
796 : #include "nsCSSFontDescList.h"
797 : #undef CSS_FONT_DESC
798 : };
799 :
800 : const nsCSSValue&
801 0 : CSSFontFaceDescriptors::Get(nsCSSFontDesc aFontDescID) const
802 : {
803 0 : MOZ_ASSERT(aFontDescID > eCSSFontDesc_UNKNOWN &&
804 : aFontDescID < eCSSFontDesc_COUNT);
805 0 : return this->*CSSFontFaceDescriptors::Fields[aFontDescID];
806 : }
807 :
808 : nsCSSValue&
809 0 : CSSFontFaceDescriptors::Get(nsCSSFontDesc aFontDescID)
810 : {
811 0 : MOZ_ASSERT(aFontDescID > eCSSFontDesc_UNKNOWN &&
812 : aFontDescID < eCSSFontDesc_COUNT);
813 0 : return this->*CSSFontFaceDescriptors::Fields[aFontDescID];
814 : }
815 :
816 : // QueryInterface implementation for nsCSSFontFaceStyleDecl
817 0 : NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceStyleDecl)
818 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
819 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleDeclaration)
820 0 : NS_INTERFACE_MAP_ENTRY(nsICSSDeclaration)
821 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
822 : // We forward the cycle collection interfaces to ContainingRule(), which is
823 : // never null (in fact, we're part of that object!)
824 0 : if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ||
825 0 : aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
826 0 : return ContainingRule()->QueryInterface(aIID, aInstancePtr);
827 : }
828 : else
829 0 : NS_INTERFACE_MAP_END
830 :
831 0 : NS_IMPL_ADDREF_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
832 0 : NS_IMPL_RELEASE_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
833 :
834 : // helper for string GetPropertyValue and RemovePropertyValue
835 : nsresult
836 0 : nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
837 : nsAString & aResult) const
838 : {
839 0 : NS_ENSURE_ARG_RANGE(aFontDescID, eCSSFontDesc_UNKNOWN,
840 : eCSSFontDesc_COUNT - 1);
841 :
842 0 : aResult.Truncate();
843 0 : if (aFontDescID == eCSSFontDesc_UNKNOWN)
844 0 : return NS_OK;
845 :
846 0 : const nsCSSValue& val = mDescriptors.Get(aFontDescID);
847 :
848 0 : if (val.GetUnit() == eCSSUnit_Null) {
849 : // Avoid having to check no-value in the Family and Src cases below.
850 0 : return NS_OK;
851 : }
852 :
853 0 : switch (aFontDescID) {
854 : case eCSSFontDesc_Family: {
855 : // we don't use nsCSSValue::AppendToString here because it doesn't
856 : // canonicalize the way we want, and anyway it's overkill when
857 : // we know we have eCSSUnit_String
858 0 : NS_ASSERTION(val.GetUnit() == eCSSUnit_String, "unexpected unit");
859 0 : nsDependentString family(val.GetStringBufferValue());
860 0 : nsStyleUtil::AppendEscapedCSSString(family, aResult);
861 0 : return NS_OK;
862 : }
863 :
864 : case eCSSFontDesc_Style:
865 : val.AppendToString(eCSSProperty_font_style, aResult,
866 0 : nsCSSValue::eNormalized);
867 0 : return NS_OK;
868 :
869 : case eCSSFontDesc_Weight:
870 : val.AppendToString(eCSSProperty_font_weight, aResult,
871 0 : nsCSSValue::eNormalized);
872 0 : return NS_OK;
873 :
874 : case eCSSFontDesc_Stretch:
875 : val.AppendToString(eCSSProperty_font_stretch, aResult,
876 0 : nsCSSValue::eNormalized);
877 0 : return NS_OK;
878 :
879 : case eCSSFontDesc_FontFeatureSettings:
880 0 : nsStyleUtil::AppendFontFeatureSettings(val, aResult);
881 0 : return NS_OK;
882 :
883 : case eCSSFontDesc_FontLanguageOverride:
884 : val.AppendToString(eCSSProperty_font_language_override, aResult,
885 0 : nsCSSValue::eNormalized);
886 0 : return NS_OK;
887 :
888 : case eCSSFontDesc_Display:
889 0 : NS_ASSERTION(val.GetUnit() == eCSSUnit_Enumerated,
890 : "unknown unit for font-display descriptor");
891 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(val.GetIntValue(),
892 0 : nsCSSProps::kFontDisplayKTable), aResult);
893 0 : return NS_OK;
894 :
895 : case eCSSFontDesc_Src:
896 0 : nsStyleUtil::AppendSerializedFontSrc(val, aResult);
897 0 : return NS_OK;
898 :
899 : case eCSSFontDesc_UnicodeRange:
900 0 : nsStyleUtil::AppendUnicodeRange(val, aResult);
901 0 : return NS_OK;
902 :
903 : case eCSSFontDesc_UNKNOWN:
904 : case eCSSFontDesc_COUNT:
905 : ;
906 : }
907 0 : NS_NOTREACHED("nsCSSFontFaceStyleDecl::GetPropertyValue: "
908 : "out-of-range value got to the switch");
909 0 : return NS_ERROR_INVALID_ARG;
910 : }
911 :
912 :
913 : NS_IMETHODIMP
914 0 : nsCSSFontFaceStyleDecl::GetCssText(nsAString & aCssText)
915 : {
916 0 : GetCssTextImpl(aCssText);
917 0 : return NS_OK;
918 : }
919 :
920 : void
921 0 : nsCSSFontFaceStyleDecl::GetCssTextImpl(nsAString& aCssText) const
922 : {
923 0 : nsAutoString descStr;
924 :
925 0 : aCssText.Truncate();
926 0 : for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
927 0 : id < eCSSFontDesc_COUNT;
928 0 : id = nsCSSFontDesc(id + 1)) {
929 0 : if (mDescriptors.Get(id).GetUnit() != eCSSUnit_Null &&
930 0 : NS_SUCCEEDED(GetPropertyValue(id, descStr))) {
931 0 : NS_ASSERTION(descStr.Length() > 0,
932 : "GetCssText: non-null unit, empty property value");
933 0 : aCssText.AppendLiteral(" ");
934 0 : aCssText.AppendASCII(nsCSSProps::GetStringValue(id).get());
935 0 : aCssText.AppendLiteral(": ");
936 0 : aCssText.Append(descStr);
937 0 : aCssText.AppendLiteral(";\n");
938 : }
939 : }
940 0 : }
941 :
942 : NS_IMETHODIMP
943 0 : nsCSSFontFaceStyleDecl::SetCssText(const nsAString & aCssText)
944 : {
945 0 : return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
946 : }
947 :
948 : NS_IMETHODIMP
949 0 : nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName,
950 : nsAString & aResult)
951 : {
952 0 : return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
953 : }
954 :
955 : NS_IMETHODIMP
956 0 : nsCSSFontFaceStyleDecl::GetAuthoredPropertyValue(const nsAString& propertyName,
957 : nsAString& aResult)
958 : {
959 : // We don't return any authored property values different from
960 : // GetPropertyValue, currently.
961 0 : return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
962 : }
963 :
964 : already_AddRefed<dom::CSSValue>
965 0 : nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName,
966 : ErrorResult& aRv)
967 : {
968 : // ??? nsDOMCSSDeclaration returns null/NS_OK, but that seems wrong.
969 0 : aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
970 0 : return nullptr;
971 : }
972 :
973 : NS_IMETHODIMP
974 0 : nsCSSFontFaceStyleDecl::RemoveProperty(const nsAString & propertyName,
975 : nsAString & aResult)
976 : {
977 0 : nsCSSFontDesc descID = nsCSSProps::LookupFontDesc(propertyName);
978 0 : NS_ASSERTION(descID >= eCSSFontDesc_UNKNOWN &&
979 : descID < eCSSFontDesc_COUNT,
980 : "LookupFontDesc returned value out of range");
981 :
982 0 : if (descID == eCSSFontDesc_UNKNOWN) {
983 0 : aResult.Truncate();
984 : } else {
985 0 : nsresult rv = GetPropertyValue(descID, aResult);
986 0 : NS_ENSURE_SUCCESS(rv, rv);
987 0 : mDescriptors.Get(descID).Reset();
988 : }
989 0 : return NS_OK;
990 : }
991 :
992 : NS_IMETHODIMP
993 0 : nsCSSFontFaceStyleDecl::GetPropertyPriority(const nsAString & propertyName,
994 : nsAString & aResult)
995 : {
996 : // font descriptors do not have priorities at present
997 0 : aResult.Truncate();
998 0 : return NS_OK;
999 : }
1000 :
1001 : NS_IMETHODIMP
1002 0 : nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName,
1003 : const nsAString & value,
1004 : const nsAString & priority)
1005 : {
1006 : // FIXME(heycam): If we are changing unicode-range, then a FontFace object
1007 : // representing this rule must have its mUnicodeRange value invalidated.
1008 :
1009 0 : return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1010 : }
1011 :
1012 : NS_IMETHODIMP
1013 0 : nsCSSFontFaceStyleDecl::GetLength(uint32_t *aLength)
1014 : {
1015 0 : uint32_t len = 0;
1016 0 : for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1017 0 : id < eCSSFontDesc_COUNT;
1018 0 : id = nsCSSFontDesc(id + 1))
1019 0 : if (mDescriptors.Get(id).GetUnit() != eCSSUnit_Null)
1020 0 : len++;
1021 :
1022 0 : *aLength = len;
1023 0 : return NS_OK;
1024 : }
1025 :
1026 : NS_IMETHODIMP
1027 0 : nsCSSFontFaceStyleDecl::Item(uint32_t aIndex, nsAString& aReturn)
1028 : {
1029 : bool found;
1030 0 : IndexedGetter(aIndex, found, aReturn);
1031 0 : if (!found) {
1032 0 : aReturn.Truncate();
1033 : }
1034 0 : return NS_OK;
1035 : }
1036 :
1037 : void
1038 0 : nsCSSFontFaceStyleDecl::IndexedGetter(uint32_t index, bool& aFound, nsAString & aResult)
1039 : {
1040 0 : int32_t nset = -1;
1041 0 : for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1042 0 : id < eCSSFontDesc_COUNT;
1043 0 : id = nsCSSFontDesc(id + 1)) {
1044 0 : if (mDescriptors.Get(id).GetUnit() != eCSSUnit_Null) {
1045 0 : nset++;
1046 0 : if (nset == int32_t(index)) {
1047 0 : aFound = true;
1048 0 : aResult.AssignASCII(nsCSSProps::GetStringValue(id).get());
1049 0 : return;
1050 : }
1051 : }
1052 : }
1053 0 : aFound = false;
1054 : }
1055 :
1056 : NS_IMETHODIMP
1057 0 : nsCSSFontFaceStyleDecl::GetParentRule(nsIDOMCSSRule** aParentRule)
1058 : {
1059 0 : NS_IF_ADDREF(*aParentRule = ContainingRule());
1060 0 : return NS_OK;
1061 : }
1062 :
1063 : NS_IMETHODIMP
1064 0 : nsCSSFontFaceStyleDecl::GetPropertyValue(const nsCSSPropertyID aPropID,
1065 : nsAString& aValue)
1066 : {
1067 : return
1068 0 : GetPropertyValue(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
1069 0 : aValue);
1070 : }
1071 :
1072 : NS_IMETHODIMP
1073 0 : nsCSSFontFaceStyleDecl::SetPropertyValue(const nsCSSPropertyID aPropID,
1074 : const nsAString& aValue)
1075 : {
1076 0 : return SetProperty(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
1077 0 : aValue, EmptyString());
1078 : }
1079 :
1080 : nsINode*
1081 0 : nsCSSFontFaceStyleDecl::GetParentObject()
1082 : {
1083 0 : return ContainingRule()->GetDocument();
1084 : }
1085 :
1086 : JSObject*
1087 0 : nsCSSFontFaceStyleDecl::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
1088 : {
1089 0 : return mozilla::dom::CSSStyleDeclarationBinding::Wrap(cx, this, aGivenProto);
1090 : }
1091 :
1092 : // -------------------------------------------
1093 : // nsCSSFontFaceRule
1094 : //
1095 :
1096 : /* virtual */ already_AddRefed<css::Rule>
1097 0 : nsCSSFontFaceRule::Clone() const
1098 : {
1099 0 : RefPtr<css::Rule> clone = new nsCSSFontFaceRule(*this);
1100 0 : return clone.forget();
1101 : }
1102 :
1103 0 : NS_IMPL_ADDREF_INHERITED(nsCSSFontFaceRule, mozilla::css::Rule)
1104 0 : NS_IMPL_RELEASE_INHERITED(nsCSSFontFaceRule, mozilla::css::Rule)
1105 :
1106 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSFontFaceRule)
1107 :
1108 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsCSSFontFaceRule,
1109 : mozilla::css::Rule)
1110 : // Keep this in sync with IsCCLeaf.
1111 :
1112 : // Trace the wrapper for our declaration. This just expands out
1113 : // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use
1114 : // directly because the wrapper is on the declaration, not on us.
1115 0 : tmp->mDecl.TraceWrapper(aCallbacks, aClosure);
1116 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
1117 :
1118 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsCSSFontFaceRule,
1119 : mozilla::css::Rule)
1120 : // Keep this in sync with IsCCLeaf.
1121 :
1122 : // Unlink the wrapper for our declaraton. This just expands out
1123 : // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use
1124 : // directly because the wrapper is on the declaration, not on us.
1125 0 : tmp->mDecl.ReleaseWrapper(static_cast<nsISupports*>(p));
1126 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
1127 :
1128 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsCSSFontFaceRule,
1129 : mozilla::css::Rule)
1130 : // Keep this in sync with IsCCLeaf.
1131 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1132 :
1133 : bool
1134 0 : nsCSSFontFaceRule::IsCCLeaf() const
1135 : {
1136 0 : if (!Rule::IsCCLeaf()) {
1137 0 : return false;
1138 : }
1139 :
1140 0 : return !mDecl.PreservingWrapper();
1141 : }
1142 :
1143 : // QueryInterface implementation for nsCSSFontFaceRule
1144 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsCSSFontFaceRule)
1145 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFaceRule)
1146 0 : NS_INTERFACE_MAP_END_INHERITING(Rule)
1147 :
1148 : #ifdef DEBUG
1149 : void
1150 0 : nsCSSFontFaceRule::List(FILE* out, int32_t aIndent) const
1151 : {
1152 0 : nsCString baseInd, descInd;
1153 0 : for (int32_t indent = aIndent; --indent >= 0; ) {
1154 0 : baseInd.AppendLiteral(" ");
1155 0 : descInd.AppendLiteral(" ");
1156 : }
1157 0 : descInd.AppendLiteral(" ");
1158 :
1159 0 : nsString descStr;
1160 :
1161 0 : fprintf_stderr(out, "%s@font-face {\n", baseInd.get());
1162 0 : for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1163 0 : id < eCSSFontDesc_COUNT;
1164 0 : id = nsCSSFontDesc(id + 1))
1165 0 : if (mDecl.mDescriptors.Get(id).GetUnit() != eCSSUnit_Null) {
1166 0 : if (NS_FAILED(mDecl.GetPropertyValue(id, descStr)))
1167 0 : descStr.AssignLiteral("#<serialization error>");
1168 0 : else if (descStr.Length() == 0)
1169 0 : descStr.AssignLiteral("#<serialization missing>");
1170 0 : fprintf_stderr(out, "%s%s: %s\n",
1171 0 : descInd.get(), nsCSSProps::GetStringValue(id).get(),
1172 0 : NS_ConvertUTF16toUTF8(descStr).get());
1173 : }
1174 0 : fprintf_stderr(out, "%s}\n", baseInd.get());
1175 0 : }
1176 : #endif
1177 :
1178 : /* virtual */ int32_t
1179 0 : nsCSSFontFaceRule::GetType() const
1180 : {
1181 0 : return Rule::FONT_FACE_RULE;
1182 : }
1183 :
1184 : uint16_t
1185 0 : nsCSSFontFaceRule::Type() const
1186 : {
1187 0 : return nsIDOMCSSRule::FONT_FACE_RULE;
1188 : }
1189 :
1190 : void
1191 0 : nsCSSFontFaceRule::GetCssTextImpl(nsAString& aCssText) const
1192 : {
1193 0 : nsAutoString propText;
1194 0 : mDecl.GetCssTextImpl(propText);
1195 :
1196 0 : aCssText.AssignLiteral("@font-face {\n");
1197 0 : aCssText.Append(propText);
1198 0 : aCssText.Append('}');
1199 0 : }
1200 :
1201 : nsICSSDeclaration*
1202 0 : nsCSSFontFaceRule::Style()
1203 : {
1204 0 : return &mDecl;
1205 : }
1206 :
1207 : NS_IMETHODIMP
1208 0 : nsCSSFontFaceRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
1209 : {
1210 0 : NS_IF_ADDREF(*aStyle = &mDecl);
1211 0 : return NS_OK;
1212 : }
1213 :
1214 : // Arguably these should forward to nsCSSFontFaceStyleDecl methods.
1215 : void
1216 0 : nsCSSFontFaceRule::SetDesc(nsCSSFontDesc aDescID, nsCSSValue const & aValue)
1217 : {
1218 0 : NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
1219 : aDescID < eCSSFontDesc_COUNT,
1220 : "aDescID out of range in nsCSSFontFaceRule::SetDesc");
1221 :
1222 : // FIXME: handle dynamic changes
1223 :
1224 : // FIXME(heycam): If we are changing unicode-range, then a FontFace object
1225 : // representing this rule must have its mUnicodeRange value invalidated.
1226 :
1227 0 : mDecl.mDescriptors.Get(aDescID) = aValue;
1228 0 : }
1229 :
1230 : void
1231 0 : nsCSSFontFaceRule::GetDesc(nsCSSFontDesc aDescID, nsCSSValue & aValue)
1232 : {
1233 0 : NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
1234 : aDescID < eCSSFontDesc_COUNT,
1235 : "aDescID out of range in nsCSSFontFaceRule::GetDesc");
1236 :
1237 0 : aValue = mDecl.mDescriptors.Get(aDescID);
1238 0 : }
1239 :
1240 : /* virtual */ size_t
1241 0 : nsCSSFontFaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
1242 : {
1243 0 : return aMallocSizeOf(this);
1244 :
1245 : // Measurement of the following members may be added later if DMD finds it is
1246 : // worthwhile:
1247 : // - mDecl
1248 : }
1249 :
1250 : /* virtual */ JSObject*
1251 0 : nsCSSFontFaceRule::WrapObject(JSContext* aCx,
1252 : JS::Handle<JSObject*> aGivenProto)
1253 : {
1254 0 : return CSSFontFaceRuleBinding::Wrap(aCx, this, aGivenProto);
1255 : }
1256 :
1257 : // -----------------------------------
1258 : // nsCSSFontFeatureValuesRule
1259 : //
1260 :
1261 : /* virtual */ already_AddRefed<css::Rule>
1262 0 : nsCSSFontFeatureValuesRule::Clone() const
1263 : {
1264 0 : RefPtr<css::Rule> clone = new nsCSSFontFeatureValuesRule(*this);
1265 0 : return clone.forget();
1266 : }
1267 :
1268 0 : NS_IMPL_ADDREF_INHERITED(nsCSSFontFeatureValuesRule, mozilla::css::Rule)
1269 0 : NS_IMPL_RELEASE_INHERITED(nsCSSFontFeatureValuesRule, mozilla::css::Rule)
1270 :
1271 : // QueryInterface implementation for nsCSSFontFeatureValuesRule
1272 : // If this ever gets its own cycle-collection bits, reevaluate our IsCCLeaf
1273 : // implementation.
1274 0 : NS_INTERFACE_MAP_BEGIN(nsCSSFontFeatureValuesRule)
1275 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFeatureValuesRule)
1276 0 : NS_INTERFACE_MAP_END_INHERITING(mozilla::css::Rule)
1277 :
1278 : bool
1279 0 : nsCSSFontFeatureValuesRule::IsCCLeaf() const
1280 : {
1281 0 : return Rule::IsCCLeaf();
1282 : }
1283 :
1284 : static void
1285 0 : FeatureValuesToString(
1286 : const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
1287 : nsAString& aOutStr)
1288 : {
1289 : uint32_t i, n;
1290 :
1291 : // append values
1292 0 : n = aFeatureValues.Length();
1293 0 : for (i = 0; i < n; i++) {
1294 0 : const gfxFontFeatureValueSet::FeatureValues& fv = aFeatureValues[i];
1295 :
1296 : // @alternate
1297 0 : aOutStr.AppendLiteral(" @");
1298 0 : nsAutoString functAlt;
1299 0 : nsStyleUtil::GetFunctionalAlternatesName(fv.alternate, functAlt);
1300 0 : aOutStr.Append(functAlt);
1301 0 : aOutStr.AppendLiteral(" {");
1302 :
1303 : // for each ident-values tuple
1304 0 : uint32_t j, numValues = fv.valuelist.Length();
1305 0 : for (j = 0; j < numValues; j++) {
1306 0 : aOutStr.Append(' ');
1307 0 : const gfxFontFeatureValueSet::ValueList& vlist = fv.valuelist[j];
1308 0 : nsStyleUtil::AppendEscapedCSSIdent(vlist.name, aOutStr);
1309 0 : aOutStr.Append(':');
1310 :
1311 0 : uint32_t k, numSelectors = vlist.featureSelectors.Length();
1312 0 : for (k = 0; k < numSelectors; k++) {
1313 0 : aOutStr.Append(' ');
1314 0 : aOutStr.AppendInt(vlist.featureSelectors[k]);
1315 : }
1316 :
1317 0 : aOutStr.Append(';');
1318 : }
1319 0 : aOutStr.AppendLiteral(" }\n");
1320 : }
1321 0 : }
1322 :
1323 : static void
1324 0 : FontFeatureValuesRuleToString(
1325 : const mozilla::FontFamilyList& aFamilyList,
1326 : const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
1327 : nsAString& aOutStr)
1328 : {
1329 0 : aOutStr.AssignLiteral("@font-feature-values ");
1330 0 : nsAutoString familyListStr, valueTextStr;
1331 0 : nsStyleUtil::AppendEscapedCSSFontFamilyList(aFamilyList, familyListStr);
1332 0 : aOutStr.Append(familyListStr);
1333 0 : aOutStr.AppendLiteral(" {\n");
1334 0 : FeatureValuesToString(aFeatureValues, valueTextStr);
1335 0 : aOutStr.Append(valueTextStr);
1336 0 : aOutStr.Append('}');
1337 0 : }
1338 :
1339 : #ifdef DEBUG
1340 : void
1341 0 : nsCSSFontFeatureValuesRule::List(FILE* out, int32_t aIndent) const
1342 : {
1343 0 : nsAutoString text;
1344 0 : FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, text);
1345 0 : NS_ConvertUTF16toUTF8 utf8(text);
1346 :
1347 : // replace newlines with newlines plus indent spaces
1348 0 : char* indent = new char[(aIndent + 1) * 2];
1349 : int32_t i;
1350 0 : for (i = 1; i < (aIndent + 1) * 2 - 1; i++) {
1351 0 : indent[i] = 0x20;
1352 : }
1353 0 : indent[0] = 0xa;
1354 0 : indent[aIndent * 2 + 1] = 0;
1355 0 : utf8.ReplaceSubstring("\n", indent);
1356 0 : delete [] indent;
1357 :
1358 0 : nsAutoCString indentStr;
1359 0 : for (i = aIndent; --i >= 0; ) {
1360 0 : indentStr.AppendLiteral(" ");
1361 : }
1362 0 : fprintf_stderr(out, "%s%s\n", indentStr.get(), utf8.get());
1363 0 : }
1364 : #endif
1365 :
1366 : /* virtual */ int32_t
1367 0 : nsCSSFontFeatureValuesRule::GetType() const
1368 : {
1369 0 : return Rule::FONT_FEATURE_VALUES_RULE;
1370 : }
1371 :
1372 : uint16_t
1373 0 : nsCSSFontFeatureValuesRule::Type() const
1374 : {
1375 0 : return nsIDOMCSSRule::FONT_FEATURE_VALUES_RULE;
1376 : }
1377 :
1378 : void
1379 0 : nsCSSFontFeatureValuesRule::GetCssTextImpl(nsAString& aCssText) const
1380 : {
1381 0 : FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, aCssText);
1382 0 : }
1383 :
1384 : void
1385 0 : nsCSSFontFeatureValuesRule::SetFontFamily(const nsAString& aFamily,
1386 : ErrorResult& aRv)
1387 : {
1388 0 : aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
1389 0 : }
1390 :
1391 : void
1392 0 : nsCSSFontFeatureValuesRule::SetValueText(const nsAString& aFamily,
1393 : ErrorResult& aRv)
1394 : {
1395 0 : aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
1396 0 : }
1397 :
1398 : NS_IMETHODIMP
1399 0 : nsCSSFontFeatureValuesRule::GetFontFamily(nsAString& aFamilyListStr)
1400 : {
1401 0 : nsStyleUtil::AppendEscapedCSSFontFamilyList(mFamilyList, aFamilyListStr);
1402 0 : return NS_OK;
1403 : }
1404 :
1405 : NS_IMETHODIMP
1406 0 : nsCSSFontFeatureValuesRule::SetFontFamily(const nsAString& aFontFamily)
1407 : {
1408 0 : return NS_ERROR_NOT_IMPLEMENTED;
1409 : }
1410 :
1411 : NS_IMETHODIMP
1412 0 : nsCSSFontFeatureValuesRule::GetValueText(nsAString& aValueText)
1413 : {
1414 0 : FeatureValuesToString(mFeatureValues, aValueText);
1415 0 : return NS_OK;
1416 : }
1417 :
1418 : NS_IMETHODIMP
1419 0 : nsCSSFontFeatureValuesRule::SetValueText(const nsAString& aValueText)
1420 : {
1421 0 : return NS_ERROR_NOT_IMPLEMENTED;
1422 : }
1423 :
1424 : struct MakeFamilyArray {
1425 : explicit MakeFamilyArray(nsTArray<nsString>& aFamilyArray)
1426 : : familyArray(aFamilyArray), hasGeneric(false)
1427 : {}
1428 :
1429 : static bool
1430 : AddFamily(const nsString& aFamily, bool aGeneric, void* aData)
1431 : {
1432 : MakeFamilyArray *familyArr = reinterpret_cast<MakeFamilyArray*> (aData);
1433 : if (!aGeneric && !aFamily.IsEmpty()) {
1434 : familyArr->familyArray.AppendElement(aFamily);
1435 : }
1436 : if (aGeneric) {
1437 : familyArr->hasGeneric = true;
1438 : }
1439 : return true;
1440 : }
1441 :
1442 : nsTArray<nsString>& familyArray;
1443 : bool hasGeneric;
1444 : };
1445 :
1446 : void
1447 0 : nsCSSFontFeatureValuesRule::SetFamilyList(
1448 : const mozilla::FontFamilyList& aFamilyList)
1449 : {
1450 0 : mFamilyList = aFamilyList;
1451 0 : }
1452 :
1453 : void
1454 0 : nsCSSFontFeatureValuesRule::AddValueList(int32_t aVariantAlternate,
1455 : nsTArray<gfxFontFeatureValueSet::ValueList>& aValueList)
1456 : {
1457 0 : uint32_t i, len = mFeatureValues.Length();
1458 0 : bool foundAlternate = false;
1459 :
1460 : // add to an existing list for a given property value
1461 0 : for (i = 0; i < len; i++) {
1462 0 : gfxFontFeatureValueSet::FeatureValues& f = mFeatureValues.ElementAt(i);
1463 :
1464 0 : if (f.alternate == uint32_t(aVariantAlternate)) {
1465 0 : f.valuelist.AppendElements(aValueList);
1466 0 : foundAlternate = true;
1467 0 : break;
1468 : }
1469 : }
1470 :
1471 : // create a new list for a given property value
1472 0 : if (!foundAlternate) {
1473 0 : gfxFontFeatureValueSet::FeatureValues &f = *mFeatureValues.AppendElement();
1474 0 : f.alternate = aVariantAlternate;
1475 0 : f.valuelist.AppendElements(aValueList);
1476 : }
1477 0 : }
1478 :
1479 : size_t
1480 0 : nsCSSFontFeatureValuesRule::SizeOfIncludingThis(
1481 : MallocSizeOf aMallocSizeOf) const
1482 : {
1483 0 : return aMallocSizeOf(this);
1484 : }
1485 :
1486 : /* virtual */ JSObject*
1487 0 : nsCSSFontFeatureValuesRule::WrapObject(JSContext* aCx,
1488 : JS::Handle<JSObject*> aGivenProto)
1489 : {
1490 0 : return CSSFontFeatureValuesRuleBinding::Wrap(aCx, this, aGivenProto);
1491 : }
1492 :
1493 : // -------------------------------------------
1494 : // nsCSSKeyframeStyleDeclaration
1495 : //
1496 :
1497 0 : nsCSSKeyframeStyleDeclaration::nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule)
1498 0 : : mRule(aRule)
1499 : {
1500 0 : }
1501 :
1502 0 : nsCSSKeyframeStyleDeclaration::~nsCSSKeyframeStyleDeclaration()
1503 : {
1504 0 : NS_ASSERTION(!mRule, "DropReference not called.");
1505 0 : }
1506 :
1507 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeStyleDeclaration)
1508 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeStyleDeclaration)
1509 :
1510 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSKeyframeStyleDeclaration)
1511 :
1512 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeStyleDeclaration)
1513 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
1514 0 : NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
1515 :
1516 : DeclarationBlock*
1517 0 : nsCSSKeyframeStyleDeclaration::GetCSSDeclaration(Operation aOperation)
1518 : {
1519 0 : if (mRule) {
1520 0 : return mRule->Declaration();
1521 : } else {
1522 0 : return nullptr;
1523 : }
1524 : }
1525 :
1526 : void
1527 0 : nsCSSKeyframeStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
1528 : {
1529 0 : GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
1530 0 : }
1531 :
1532 : nsDOMCSSDeclaration::ServoCSSParsingEnvironment
1533 0 : nsCSSKeyframeStyleDeclaration::GetServoCSSParsingEnvironment() const
1534 : {
1535 0 : MOZ_CRASH("GetURLData shouldn't be calling on a Gecko rule");
1536 : }
1537 :
1538 : NS_IMETHODIMP
1539 0 : nsCSSKeyframeStyleDeclaration::GetParentRule(nsIDOMCSSRule **aParent)
1540 : {
1541 0 : NS_ENSURE_ARG_POINTER(aParent);
1542 :
1543 0 : NS_IF_ADDREF(*aParent = mRule);
1544 0 : return NS_OK;
1545 : }
1546 :
1547 : nsresult
1548 0 : nsCSSKeyframeStyleDeclaration::SetCSSDeclaration(DeclarationBlock* aDecl)
1549 : {
1550 0 : MOZ_ASSERT(aDecl, "must be non-null");
1551 0 : mRule->ChangeDeclaration(aDecl->AsGecko());
1552 0 : return NS_OK;
1553 : }
1554 :
1555 : nsIDocument*
1556 0 : nsCSSKeyframeStyleDeclaration::DocToUpdate()
1557 : {
1558 0 : return nullptr;
1559 : }
1560 :
1561 : nsINode*
1562 0 : nsCSSKeyframeStyleDeclaration::GetParentObject()
1563 : {
1564 0 : return mRule ? mRule->GetDocument() : nullptr;
1565 : }
1566 :
1567 : // -------------------------------------------
1568 : // nsCSSKeyframeRule
1569 : //
1570 :
1571 0 : nsCSSKeyframeRule::nsCSSKeyframeRule(const nsCSSKeyframeRule& aCopy)
1572 : // copy everything except our reference count and mDOMDeclaration
1573 : : dom::CSSKeyframeRule(aCopy)
1574 : , mKeys(aCopy.mKeys)
1575 0 : , mDeclaration(new css::Declaration(*aCopy.mDeclaration))
1576 : {
1577 0 : mDeclaration->SetOwningRule(this);
1578 0 : }
1579 :
1580 0 : nsCSSKeyframeRule::~nsCSSKeyframeRule()
1581 : {
1582 0 : mDeclaration->SetOwningRule(nullptr);
1583 0 : if (mDOMDeclaration) {
1584 0 : mDOMDeclaration->DropReference();
1585 : }
1586 0 : }
1587 :
1588 : /* virtual */ already_AddRefed<css::Rule>
1589 0 : nsCSSKeyframeRule::Clone() const
1590 : {
1591 0 : RefPtr<css::Rule> clone = new nsCSSKeyframeRule(*this);
1592 0 : return clone.forget();
1593 : }
1594 :
1595 156 : NS_IMPL_ADDREF_INHERITED(nsCSSKeyframeRule, dom::CSSKeyframeRule)
1596 78 : NS_IMPL_RELEASE_INHERITED(nsCSSKeyframeRule, dom::CSSKeyframeRule)
1597 :
1598 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSKeyframeRule)
1599 :
1600 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsCSSKeyframeRule,
1601 : dom::CSSKeyframeRule)
1602 0 : if (tmp->mDOMDeclaration) {
1603 0 : tmp->mDOMDeclaration->DropReference();
1604 0 : tmp->mDOMDeclaration = nullptr;
1605 : }
1606 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
1607 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsCSSKeyframeRule,
1608 : dom::CSSKeyframeRule)
1609 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration)
1610 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1611 :
1612 : bool
1613 0 : nsCSSKeyframeRule::IsCCLeaf() const
1614 : {
1615 : // Let's not worry about figuring out whether we're a leaf or not.
1616 0 : return false;
1617 : }
1618 :
1619 : // QueryInterface implementation for nsCSSKeyframeRule
1620 78 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsCSSKeyframeRule)
1621 0 : NS_INTERFACE_MAP_END_INHERITING(dom::CSSKeyframeRule)
1622 :
1623 : #ifdef DEBUG
1624 : void
1625 0 : nsCSSKeyframeRule::List(FILE* out, int32_t aIndent) const
1626 : {
1627 0 : nsAutoCString str;
1628 0 : for (int32_t index = aIndent; --index >= 0; ) {
1629 0 : str.AppendLiteral(" ");
1630 : }
1631 :
1632 0 : nsAutoString tmp;
1633 0 : DoGetKeyText(tmp);
1634 0 : AppendUTF16toUTF8(tmp, str);
1635 0 : str.AppendLiteral(" { ");
1636 0 : mDeclaration->ToString(tmp);
1637 0 : AppendUTF16toUTF8(tmp, str);
1638 0 : str.AppendLiteral("}\n");
1639 0 : fprintf_stderr(out, "%s", str.get());
1640 0 : }
1641 : #endif
1642 :
1643 : void
1644 0 : nsCSSKeyframeRule::GetCssTextImpl(nsAString& aCssText) const
1645 : {
1646 0 : DoGetKeyText(aCssText);
1647 0 : aCssText.AppendLiteral(" { ");
1648 0 : nsAutoString tmp;
1649 0 : mDeclaration->ToString(tmp);
1650 0 : aCssText.Append(tmp);
1651 0 : aCssText.AppendLiteral(" }");
1652 0 : }
1653 :
1654 : NS_IMETHODIMP
1655 0 : nsCSSKeyframeRule::GetKeyText(nsAString& aKeyText)
1656 : {
1657 0 : DoGetKeyText(aKeyText);
1658 0 : return NS_OK;
1659 : }
1660 :
1661 : void
1662 0 : nsCSSKeyframeRule::DoGetKeyText(nsAString& aKeyText) const
1663 : {
1664 0 : aKeyText.Truncate();
1665 0 : uint32_t i = 0, i_end = mKeys.Length();
1666 0 : MOZ_ASSERT(i_end != 0, "must have some keys");
1667 : for (;;) {
1668 0 : aKeyText.AppendFloat(mKeys[i] * 100.0f);
1669 0 : aKeyText.Append(char16_t('%'));
1670 0 : if (++i == i_end) {
1671 0 : break;
1672 : }
1673 0 : aKeyText.AppendLiteral(", ");
1674 : }
1675 0 : }
1676 :
1677 : NS_IMETHODIMP
1678 0 : nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText)
1679 : {
1680 0 : nsCSSParser parser;
1681 :
1682 0 : InfallibleTArray<float> newSelectors;
1683 : // FIXME: pass filename and line number
1684 0 : if (!parser.ParseKeyframeSelectorString(aKeyText, nullptr, 0, newSelectors)) {
1685 : // for now, we don't do anything if the parse fails
1686 0 : return NS_OK;
1687 : }
1688 :
1689 0 : nsIDocument* doc = GetDocument();
1690 0 : MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
1691 :
1692 0 : newSelectors.SwapElements(mKeys);
1693 :
1694 0 : if (StyleSheet* sheet = GetStyleSheet()) {
1695 0 : sheet->AsGecko()->SetModifiedByChildRule();
1696 0 : if (doc) {
1697 0 : doc->StyleRuleChanged(sheet, this);
1698 : }
1699 : }
1700 :
1701 0 : return NS_OK;
1702 : }
1703 :
1704 : nsICSSDeclaration*
1705 0 : nsCSSKeyframeRule::Style()
1706 : {
1707 0 : if (!mDOMDeclaration) {
1708 0 : mDOMDeclaration = new nsCSSKeyframeStyleDeclaration(this);
1709 : }
1710 0 : return mDOMDeclaration;
1711 : }
1712 :
1713 : void
1714 0 : nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration)
1715 : {
1716 : // Our caller already did a BeginUpdate/EndUpdate, but with
1717 : // UPDATE_CONTENT, and we need UPDATE_STYLE to trigger work in
1718 : // PresShell::EndUpdate.
1719 0 : nsIDocument* doc = GetDocument();
1720 0 : MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
1721 :
1722 0 : if (aDeclaration != mDeclaration) {
1723 0 : mDeclaration->SetOwningRule(nullptr);
1724 0 : mDeclaration = aDeclaration;
1725 0 : mDeclaration->SetOwningRule(this);
1726 : }
1727 :
1728 0 : if (StyleSheet* sheet = GetStyleSheet()) {
1729 0 : sheet->AsGecko()->SetModifiedByChildRule();
1730 0 : if (doc) {
1731 0 : doc->StyleRuleChanged(sheet, this);
1732 : }
1733 : }
1734 0 : }
1735 :
1736 : /* virtual */ size_t
1737 0 : nsCSSKeyframeRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
1738 : {
1739 0 : return aMallocSizeOf(this);
1740 :
1741 : // Measurement of the following members may be added later if DMD finds it is
1742 : // worthwhile:
1743 : // - mKeys
1744 : // - mDeclaration
1745 : // - mDOMDeclaration
1746 : }
1747 :
1748 : // -------------------------------------------
1749 : // nsCSSKeyframesRule
1750 : //
1751 :
1752 0 : nsCSSKeyframesRule::nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy)
1753 : // copy everything except our reference count. GroupRule's copy
1754 : // constructor also doesn't copy the lazily-constructed
1755 : // mRuleCollection.
1756 : : dom::CSSKeyframesRule(aCopy),
1757 0 : mName(aCopy.mName)
1758 : {
1759 0 : }
1760 :
1761 0 : nsCSSKeyframesRule::~nsCSSKeyframesRule()
1762 : {
1763 0 : }
1764 :
1765 : /* virtual */ already_AddRefed<css::Rule>
1766 0 : nsCSSKeyframesRule::Clone() const
1767 : {
1768 0 : RefPtr<css::Rule> clone = new nsCSSKeyframesRule(*this);
1769 0 : return clone.forget();
1770 : }
1771 :
1772 62 : NS_IMPL_ADDREF_INHERITED(nsCSSKeyframesRule, dom::CSSKeyframesRule)
1773 31 : NS_IMPL_RELEASE_INHERITED(nsCSSKeyframesRule, dom::CSSKeyframesRule)
1774 :
1775 : // QueryInterface implementation for nsCSSKeyframesRule
1776 31 : NS_INTERFACE_MAP_BEGIN(nsCSSKeyframesRule)
1777 31 : NS_INTERFACE_MAP_END_INHERITING(dom::CSSKeyframesRule)
1778 :
1779 : #ifdef DEBUG
1780 : void
1781 0 : nsCSSKeyframesRule::List(FILE* out, int32_t aIndent) const
1782 : {
1783 0 : nsAutoCString indentStr;
1784 0 : for (int32_t indent = aIndent; --indent >= 0; ) {
1785 0 : indentStr.AppendLiteral(" ");
1786 : }
1787 :
1788 0 : fprintf_stderr(out, "%s@keyframes %s {\n",
1789 0 : indentStr.get(), NS_ConvertUTF16toUTF8(mName).get());
1790 :
1791 0 : GroupRule::List(out, aIndent);
1792 :
1793 0 : fprintf_stderr(out, "%s}\n", indentStr.get());
1794 0 : }
1795 : #endif
1796 :
1797 : void
1798 0 : nsCSSKeyframesRule::GetCssTextImpl(nsAString& aCssText) const
1799 : {
1800 0 : aCssText.AssignLiteral("@keyframes ");
1801 0 : aCssText.Append(mName);
1802 0 : aCssText.AppendLiteral(" {\n");
1803 0 : nsAutoString tmp;
1804 0 : for (const Rule* rule : GeckoRules()) {
1805 0 : static_cast<const nsCSSKeyframeRule*>(rule)->GetCssText(tmp);
1806 0 : aCssText.Append(tmp);
1807 0 : aCssText.Append('\n');
1808 : }
1809 0 : aCssText.Append('}');
1810 0 : }
1811 :
1812 : NS_IMETHODIMP
1813 0 : nsCSSKeyframesRule::GetName(nsAString& aName)
1814 : {
1815 0 : aName = mName;
1816 0 : return NS_OK;
1817 : }
1818 :
1819 : NS_IMETHODIMP
1820 0 : nsCSSKeyframesRule::SetName(const nsAString& aName)
1821 : {
1822 0 : if (mName == aName) {
1823 0 : return NS_OK;
1824 : }
1825 :
1826 0 : nsIDocument* doc = GetDocument();
1827 0 : MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
1828 :
1829 0 : mName = aName;
1830 :
1831 0 : if (StyleSheet* sheet = GetStyleSheet()) {
1832 0 : sheet->AsGecko()->SetModifiedByChildRule();
1833 0 : if (doc) {
1834 0 : doc->StyleRuleChanged(sheet, this);
1835 : }
1836 : }
1837 :
1838 0 : return NS_OK;
1839 : }
1840 :
1841 : NS_IMETHODIMP
1842 0 : nsCSSKeyframesRule::AppendRule(const nsAString& aRule)
1843 : {
1844 : // The spec is confusing, and I think we should just append the rule,
1845 : // which also turns out to match WebKit:
1846 : // http://lists.w3.org/Archives/Public/www-style/2011Apr/0034.html
1847 0 : nsCSSParser parser;
1848 :
1849 : // FIXME: pass filename and line number
1850 : RefPtr<nsCSSKeyframeRule> rule =
1851 0 : parser.ParseKeyframeRule(aRule, nullptr, 0);
1852 0 : if (rule) {
1853 0 : nsIDocument* doc = GetDocument();
1854 0 : MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
1855 :
1856 0 : AppendStyleRule(rule);
1857 :
1858 0 : if (StyleSheet* sheet = GetStyleSheet()) {
1859 0 : sheet->AsGecko()->SetModifiedByChildRule();
1860 0 : if (doc) {
1861 0 : doc->StyleRuleChanged(sheet, this);
1862 : }
1863 : }
1864 : }
1865 :
1866 0 : return NS_OK;
1867 : }
1868 :
1869 : static const uint32_t RULE_NOT_FOUND = uint32_t(-1);
1870 :
1871 : uint32_t
1872 0 : nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey)
1873 : {
1874 0 : nsCSSParser parser;
1875 :
1876 0 : InfallibleTArray<float> keys;
1877 : // FIXME: pass filename and line number
1878 0 : if (parser.ParseKeyframeSelectorString(aKey, nullptr, 0, keys)) {
1879 0 : IncrementalClearCOMRuleArray& rules = GeckoRules();
1880 : // The spec isn't clear, but we'll match on the key list, which
1881 : // mostly matches what WebKit does, except we'll do last-match
1882 : // instead of first-match, and handling parsing differences better.
1883 : // http://lists.w3.org/Archives/Public/www-style/2011Apr/0036.html
1884 : // http://lists.w3.org/Archives/Public/www-style/2011Apr/0037.html
1885 0 : for (uint32_t i = rules.Count(); i-- != 0; ) {
1886 0 : if (static_cast<nsCSSKeyframeRule*>(rules[i])->GetKeys() == keys) {
1887 0 : return i;
1888 : }
1889 : }
1890 : }
1891 :
1892 0 : return RULE_NOT_FOUND;
1893 : }
1894 :
1895 : NS_IMETHODIMP
1896 0 : nsCSSKeyframesRule::DeleteRule(const nsAString& aKey)
1897 : {
1898 0 : uint32_t index = FindRuleIndexForKey(aKey);
1899 0 : if (index != RULE_NOT_FOUND) {
1900 0 : nsIDocument* doc = GetDocument();
1901 0 : MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
1902 :
1903 0 : DeleteStyleRuleAt(index);
1904 :
1905 0 : if (StyleSheet* sheet = GetStyleSheet()) {
1906 0 : sheet->AsGecko()->SetModifiedByChildRule();
1907 :
1908 0 : if (doc) {
1909 0 : doc->StyleRuleChanged(sheet, this);
1910 : }
1911 : }
1912 : }
1913 0 : return NS_OK;
1914 : }
1915 :
1916 : nsCSSKeyframeRule*
1917 0 : nsCSSKeyframesRule::FindRule(const nsAString& aKey)
1918 : {
1919 0 : uint32_t index = FindRuleIndexForKey(aKey);
1920 0 : if (index == RULE_NOT_FOUND) {
1921 0 : return nullptr;
1922 : }
1923 0 : return static_cast<nsCSSKeyframeRule*>(GeckoRules()[index]);
1924 : }
1925 :
1926 : /* virtual */ size_t
1927 0 : nsCSSKeyframesRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
1928 : {
1929 0 : size_t n = aMallocSizeOf(this);
1930 0 : n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
1931 :
1932 : // Measurement of the following members may be added later if DMD finds it is
1933 : // worthwhile:
1934 : // - mName
1935 :
1936 0 : return n;
1937 : }
1938 :
1939 : // -------------------------------------------
1940 : // nsCSSPageStyleDeclaration
1941 : //
1942 :
1943 0 : nsCSSPageStyleDeclaration::nsCSSPageStyleDeclaration(nsCSSPageRule* aRule)
1944 0 : : mRule(aRule)
1945 : {
1946 0 : }
1947 :
1948 0 : nsCSSPageStyleDeclaration::~nsCSSPageStyleDeclaration()
1949 : {
1950 0 : NS_ASSERTION(!mRule, "DropReference not called.");
1951 0 : }
1952 :
1953 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageStyleDeclaration)
1954 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageStyleDeclaration)
1955 :
1956 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSPageStyleDeclaration)
1957 :
1958 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageStyleDeclaration)
1959 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
1960 0 : NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
1961 :
1962 : DeclarationBlock*
1963 0 : nsCSSPageStyleDeclaration::GetCSSDeclaration(Operation aOperation)
1964 : {
1965 0 : if (mRule) {
1966 0 : return mRule->Declaration();
1967 : } else {
1968 0 : return nullptr;
1969 : }
1970 : }
1971 :
1972 : void
1973 0 : nsCSSPageStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
1974 : {
1975 0 : GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
1976 0 : }
1977 :
1978 : nsDOMCSSDeclaration::ServoCSSParsingEnvironment
1979 0 : nsCSSPageStyleDeclaration::GetServoCSSParsingEnvironment() const
1980 : {
1981 0 : MOZ_CRASH("GetURLData shouldn't be calling on a Gecko rule");
1982 : }
1983 :
1984 : NS_IMETHODIMP
1985 0 : nsCSSPageStyleDeclaration::GetParentRule(nsIDOMCSSRule** aParent)
1986 : {
1987 0 : NS_ENSURE_ARG_POINTER(aParent);
1988 :
1989 0 : NS_IF_ADDREF(*aParent = mRule);
1990 0 : return NS_OK;
1991 : }
1992 :
1993 : nsresult
1994 0 : nsCSSPageStyleDeclaration::SetCSSDeclaration(DeclarationBlock* aDecl)
1995 : {
1996 0 : MOZ_ASSERT(aDecl, "must be non-null");
1997 0 : mRule->ChangeDeclaration(aDecl->AsGecko());
1998 0 : return NS_OK;
1999 : }
2000 :
2001 : nsIDocument*
2002 0 : nsCSSPageStyleDeclaration::DocToUpdate()
2003 : {
2004 0 : return nullptr;
2005 : }
2006 :
2007 : nsINode*
2008 0 : nsCSSPageStyleDeclaration::GetParentObject()
2009 : {
2010 0 : return mRule ? mRule->GetDocument() : nullptr;
2011 : }
2012 :
2013 : // -------------------------------------------
2014 : // nsCSSPageRule
2015 : //
2016 :
2017 0 : nsCSSPageRule::nsCSSPageRule(const nsCSSPageRule& aCopy)
2018 : // copy everything except our reference count and mDOMDeclaration
2019 : : dom::CSSPageRule(aCopy)
2020 0 : , mDeclaration(new css::Declaration(*aCopy.mDeclaration))
2021 : {
2022 0 : mDeclaration->SetOwningRule(this);
2023 0 : }
2024 :
2025 0 : nsCSSPageRule::~nsCSSPageRule()
2026 : {
2027 0 : mDeclaration->SetOwningRule(nullptr);
2028 0 : if (mDOMDeclaration) {
2029 0 : mDOMDeclaration->DropReference();
2030 : }
2031 0 : }
2032 :
2033 : /* virtual */ already_AddRefed<css::Rule>
2034 0 : nsCSSPageRule::Clone() const
2035 : {
2036 0 : RefPtr<css::Rule> clone = new nsCSSPageRule(*this);
2037 0 : return clone.forget();
2038 : }
2039 :
2040 0 : NS_IMPL_ADDREF_INHERITED(nsCSSPageRule, dom::CSSPageRule)
2041 0 : NS_IMPL_RELEASE_INHERITED(nsCSSPageRule, dom::CSSPageRule)
2042 :
2043 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSPageRule)
2044 :
2045 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsCSSPageRule,
2046 : dom::CSSPageRule)
2047 0 : if (tmp->mDOMDeclaration) {
2048 0 : tmp->mDOMDeclaration->DropReference();
2049 0 : tmp->mDOMDeclaration = nullptr;
2050 : }
2051 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
2052 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsCSSPageRule,
2053 : dom::CSSPageRule)
2054 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration)
2055 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
2056 :
2057 : bool
2058 0 : nsCSSPageRule::IsCCLeaf() const
2059 : {
2060 : // Let's not worry about figuring out whether we're a leaf or not.
2061 0 : return false;
2062 : }
2063 :
2064 : // QueryInterface implementation for nsCSSPageRule
2065 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsCSSPageRule)
2066 0 : NS_INTERFACE_MAP_END_INHERITING(dom::CSSPageRule)
2067 :
2068 : #ifdef DEBUG
2069 : void
2070 0 : nsCSSPageRule::List(FILE* out, int32_t aIndent) const
2071 : {
2072 0 : nsAutoCString str;
2073 0 : for (int32_t indent = aIndent; --indent >= 0; ) {
2074 0 : str.AppendLiteral(" ");
2075 : }
2076 :
2077 0 : str.AppendLiteral("@page { ");
2078 0 : nsAutoString tmp;
2079 0 : mDeclaration->ToString(tmp);
2080 0 : AppendUTF16toUTF8(tmp, str);
2081 0 : str.AppendLiteral("}\n");
2082 0 : fprintf_stderr(out, "%s", str.get());
2083 0 : }
2084 : #endif
2085 :
2086 : void
2087 0 : nsCSSPageRule::GetCssTextImpl(nsAString& aCssText) const
2088 : {
2089 0 : aCssText.AppendLiteral("@page { ");
2090 0 : nsAutoString tmp;
2091 0 : mDeclaration->ToString(tmp);
2092 0 : aCssText.Append(tmp);
2093 0 : aCssText.AppendLiteral(" }");
2094 0 : }
2095 :
2096 : nsICSSDeclaration*
2097 0 : nsCSSPageRule::Style()
2098 : {
2099 0 : if (!mDOMDeclaration) {
2100 0 : mDOMDeclaration = new nsCSSPageStyleDeclaration(this);
2101 : }
2102 0 : return mDOMDeclaration;
2103 : }
2104 :
2105 : void
2106 0 : nsCSSPageRule::ChangeDeclaration(css::Declaration* aDeclaration)
2107 : {
2108 0 : if (aDeclaration != mDeclaration) {
2109 0 : mDeclaration->SetOwningRule(nullptr);
2110 0 : mDeclaration = aDeclaration;
2111 0 : mDeclaration->SetOwningRule(this);
2112 : }
2113 :
2114 0 : if (StyleSheet* sheet = GetStyleSheet()) {
2115 0 : sheet->AsGecko()->SetModifiedByChildRule();
2116 : }
2117 0 : }
2118 :
2119 : /* virtual */ size_t
2120 0 : nsCSSPageRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
2121 : {
2122 0 : return aMallocSizeOf(this);
2123 : }
2124 :
2125 : namespace mozilla {
2126 :
2127 0 : CSSSupportsRule::CSSSupportsRule(bool aConditionMet,
2128 : const nsString& aCondition,
2129 0 : uint32_t aLineNumber, uint32_t aColumnNumber)
2130 : : dom::CSSSupportsRule(aLineNumber, aColumnNumber)
2131 : , mUseGroup(aConditionMet)
2132 0 : , mCondition(aCondition)
2133 : {
2134 0 : }
2135 :
2136 0 : CSSSupportsRule::~CSSSupportsRule()
2137 : {
2138 0 : }
2139 :
2140 0 : CSSSupportsRule::CSSSupportsRule(const CSSSupportsRule& aCopy)
2141 : : dom::CSSSupportsRule(aCopy),
2142 0 : mUseGroup(aCopy.mUseGroup),
2143 0 : mCondition(aCopy.mCondition)
2144 : {
2145 0 : }
2146 :
2147 : #ifdef DEBUG
2148 : /* virtual */ void
2149 0 : CSSSupportsRule::List(FILE* out, int32_t aIndent) const
2150 : {
2151 0 : nsAutoCString indentStr;
2152 0 : for (int32_t indent = aIndent; --indent >= 0; ) {
2153 0 : indentStr.AppendLiteral(" ");
2154 : }
2155 :
2156 0 : fprintf_stderr(out, "%s@supports %s {\n",
2157 0 : indentStr.get(), NS_ConvertUTF16toUTF8(mCondition).get());
2158 :
2159 0 : css::GroupRule::List(out, aIndent);
2160 :
2161 0 : fprintf_stderr(out, "%s}\n", indentStr.get());
2162 0 : }
2163 : #endif
2164 :
2165 : /* virtual */ already_AddRefed<mozilla::css::Rule>
2166 0 : CSSSupportsRule::Clone() const
2167 : {
2168 0 : RefPtr<css::Rule> clone = new CSSSupportsRule(*this);
2169 0 : return clone.forget();
2170 : }
2171 :
2172 : /* virtual */ bool
2173 0 : CSSSupportsRule::UseForPresentation(nsPresContext* aPresContext,
2174 : nsMediaQueryResultCacheKey& aKey)
2175 : {
2176 0 : return mUseGroup;
2177 : }
2178 :
2179 0 : NS_IMPL_ADDREF_INHERITED(mozilla::CSSSupportsRule, dom::CSSSupportsRule)
2180 0 : NS_IMPL_RELEASE_INHERITED(mozilla::CSSSupportsRule, dom::CSSSupportsRule)
2181 :
2182 : // QueryInterface implementation for CSSSupportsRule
2183 0 : NS_INTERFACE_MAP_BEGIN(CSSSupportsRule)
2184 0 : NS_INTERFACE_MAP_END_INHERITING(dom::CSSSupportsRule)
2185 :
2186 : void
2187 0 : CSSSupportsRule::GetCssTextImpl(nsAString& aCssText) const
2188 : {
2189 0 : aCssText.AssignLiteral("@supports ");
2190 0 : aCssText.Append(mCondition);
2191 0 : css::GroupRule::AppendRulesToCssText(aCssText);
2192 0 : }
2193 :
2194 : // nsIDOMCSSConditionRule methods
2195 : NS_IMETHODIMP
2196 0 : CSSSupportsRule::GetConditionText(nsAString& aConditionText)
2197 : {
2198 0 : aConditionText.Assign(mCondition);
2199 0 : return NS_OK;
2200 : }
2201 :
2202 : NS_IMETHODIMP
2203 0 : CSSSupportsRule::SetConditionText(const nsAString& aConditionText)
2204 : {
2205 0 : return NS_ERROR_NOT_IMPLEMENTED;
2206 : }
2207 :
2208 : /* virtual */ size_t
2209 0 : CSSSupportsRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
2210 : {
2211 0 : size_t n = aMallocSizeOf(this);
2212 0 : n += css::GroupRule::SizeOfExcludingThis(aMallocSizeOf);
2213 0 : n += mCondition.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
2214 0 : return n;
2215 : }
2216 :
2217 : } // namespace mozilla
2218 :
2219 : // -------------------------------------------
2220 : // nsCSSCounterStyleRule
2221 : //
2222 :
2223 0 : nsCSSCounterStyleRule::nsCSSCounterStyleRule(const nsCSSCounterStyleRule& aCopy)
2224 : : Rule(aCopy)
2225 : , mName(aCopy.mName)
2226 0 : , mGeneration(aCopy.mGeneration)
2227 : {
2228 0 : for (size_t i = 0; i < ArrayLength(mValues); ++i) {
2229 0 : mValues[i] = aCopy.mValues[i];
2230 : }
2231 0 : }
2232 :
2233 0 : nsCSSCounterStyleRule::~nsCSSCounterStyleRule()
2234 : {
2235 0 : }
2236 :
2237 : /* virtual */ already_AddRefed<css::Rule>
2238 0 : nsCSSCounterStyleRule::Clone() const
2239 : {
2240 0 : RefPtr<css::Rule> clone = new nsCSSCounterStyleRule(*this);
2241 0 : return clone.forget();
2242 : }
2243 :
2244 : nsCSSCounterStyleRule::Getter const
2245 : nsCSSCounterStyleRule::kGetters[] = {
2246 : #define CSS_COUNTER_DESC(name_, method_) &nsCSSCounterStyleRule::Get##method_,
2247 : #include "nsCSSCounterDescList.h"
2248 : #undef CSS_COUNTER_DESC
2249 : };
2250 :
2251 276 : NS_IMPL_ADDREF_INHERITED(nsCSSCounterStyleRule, mozilla::css::Rule)
2252 138 : NS_IMPL_RELEASE_INHERITED(nsCSSCounterStyleRule, mozilla::css::Rule)
2253 :
2254 : // QueryInterface implementation for nsCSSCounterStyleRule
2255 : // If this ever gets its own cycle-collection bits, reevaluate our IsCCLeaf
2256 : // implementation.
2257 138 : NS_INTERFACE_MAP_BEGIN(nsCSSCounterStyleRule)
2258 138 : NS_INTERFACE_MAP_ENTRY(nsIDOMCSSCounterStyleRule)
2259 138 : NS_INTERFACE_MAP_END_INHERITING(mozilla::css::Rule)
2260 :
2261 : bool
2262 0 : nsCSSCounterStyleRule::IsCCLeaf() const
2263 : {
2264 0 : return Rule::IsCCLeaf();
2265 : }
2266 :
2267 : #ifdef DEBUG
2268 : void
2269 0 : nsCSSCounterStyleRule::List(FILE* out, int32_t aIndent) const
2270 : {
2271 0 : nsCString baseInd, descInd;
2272 0 : for (int32_t indent = aIndent; --indent >= 0; ) {
2273 0 : baseInd.AppendLiteral(" ");
2274 : }
2275 0 : descInd = baseInd;
2276 0 : descInd.AppendLiteral(" ");
2277 :
2278 0 : nsDependentAtomString name(mName);
2279 0 : fprintf_stderr(out, "%s@counter-style %s (rev.%u) {\n",
2280 0 : baseInd.get(), NS_ConvertUTF16toUTF8(name).get(),
2281 0 : mGeneration);
2282 : // TODO
2283 0 : fprintf_stderr(out, "%s}\n", baseInd.get());
2284 0 : }
2285 : #endif
2286 :
2287 : /* virtual */ int32_t
2288 698 : nsCSSCounterStyleRule::GetType() const
2289 : {
2290 698 : return Rule::COUNTER_STYLE_RULE;
2291 : }
2292 :
2293 : uint16_t
2294 0 : nsCSSCounterStyleRule::Type() const
2295 : {
2296 0 : return nsIDOMCSSRule::COUNTER_STYLE_RULE;
2297 : }
2298 :
2299 : void
2300 0 : nsCSSCounterStyleRule::GetCssTextImpl(nsAString& aCssText) const
2301 : {
2302 0 : aCssText.AssignLiteral(u"@counter-style ");
2303 0 : nsDependentAtomString name(mName);
2304 0 : nsStyleUtil::AppendEscapedCSSIdent(name, aCssText);
2305 0 : aCssText.AppendLiteral(u" {\n");
2306 0 : for (nsCSSCounterDesc id = nsCSSCounterDesc(0);
2307 0 : id < eCSSCounterDesc_COUNT;
2308 0 : id = nsCSSCounterDesc(id + 1)) {
2309 0 : if (mValues[id].GetUnit() != eCSSUnit_Null) {
2310 0 : nsAutoString tmp;
2311 : // This is annoying. We want to be a const method, but kGetters stores
2312 : // XPCOM method pointers, which aren't const methods. The thing is,
2313 : // none of those mutate "this". So it's OK to cast away const here.
2314 0 : (const_cast<nsCSSCounterStyleRule*>(this)->*kGetters[id])(tmp);
2315 0 : aCssText.AppendLiteral(u" ");
2316 0 : AppendASCIItoUTF16(nsCSSProps::GetStringValue(id), aCssText);
2317 0 : aCssText.AppendLiteral(u": ");
2318 0 : aCssText.Append(tmp);
2319 0 : aCssText.AppendLiteral(u";\n");
2320 : }
2321 : }
2322 0 : aCssText.AppendLiteral(u"}");
2323 0 : }
2324 :
2325 : // nsIDOMCSSCounterStyleRule methods
2326 : NS_IMETHODIMP
2327 0 : nsCSSCounterStyleRule::GetName(nsAString& aName)
2328 : {
2329 0 : aName.Truncate();
2330 0 : nsDependentAtomString name(mName);
2331 0 : nsStyleUtil::AppendEscapedCSSIdent(name, aName);
2332 0 : return NS_OK;
2333 : }
2334 :
2335 : NS_IMETHODIMP
2336 0 : nsCSSCounterStyleRule::SetName(const nsAString& aName)
2337 : {
2338 0 : nsCSSParser parser;
2339 0 : if (nsCOMPtr<nsIAtom> name = parser.ParseCounterStyleName(aName, nullptr)) {
2340 0 : nsIDocument* doc = GetDocument();
2341 0 : MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
2342 :
2343 0 : mName = name;
2344 :
2345 0 : if (StyleSheet* sheet = GetStyleSheet()) {
2346 0 : if (sheet->IsGecko()) {
2347 0 : sheet->AsGecko()->SetModifiedByChildRule();
2348 : }
2349 0 : if (doc) {
2350 0 : doc->StyleRuleChanged(sheet, this);
2351 : }
2352 : }
2353 : }
2354 0 : return NS_OK;
2355 : }
2356 :
2357 : int32_t
2358 138 : nsCSSCounterStyleRule::GetSystem() const
2359 : {
2360 138 : const nsCSSValue& system = GetDesc(eCSSCounterDesc_System);
2361 138 : switch (system.GetUnit()) {
2362 : case eCSSUnit_Enumerated:
2363 78 : return system.GetIntValue();
2364 : case eCSSUnit_Pair:
2365 60 : return system.GetPairValue().mXValue.GetIntValue();
2366 : default:
2367 0 : return NS_STYLE_COUNTER_SYSTEM_SYMBOLIC;
2368 : }
2369 : }
2370 :
2371 : const nsCSSValue&
2372 0 : nsCSSCounterStyleRule::GetSystemArgument() const
2373 : {
2374 0 : const nsCSSValue& system = GetDesc(eCSSCounterDesc_System);
2375 0 : MOZ_ASSERT(system.GetUnit() == eCSSUnit_Pair,
2376 : "Invalid system value");
2377 0 : return system.GetPairValue().mYValue;
2378 : }
2379 :
2380 : void
2381 254 : nsCSSCounterStyleRule::SetDesc(nsCSSCounterDesc aDescID, const nsCSSValue& aValue)
2382 : {
2383 254 : MOZ_ASSERT(aDescID >= 0 && aDescID < eCSSCounterDesc_COUNT,
2384 : "descriptor ID out of range");
2385 :
2386 254 : nsIDocument* doc = GetDocument();
2387 508 : MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
2388 :
2389 254 : mValues[aDescID] = aValue;
2390 254 : mGeneration++;
2391 :
2392 254 : if (StyleSheet* sheet = GetStyleSheet()) {
2393 0 : if (sheet->IsGecko()) {
2394 0 : sheet->AsGecko()->SetModifiedByChildRule();
2395 : }
2396 0 : if (doc) {
2397 0 : doc->StyleRuleChanged(sheet, this);
2398 : }
2399 : }
2400 254 : }
2401 :
2402 : NS_IMETHODIMP
2403 0 : nsCSSCounterStyleRule::GetSystem(nsAString& aSystem)
2404 : {
2405 0 : const nsCSSValue& value = GetDesc(eCSSCounterDesc_System);
2406 0 : if (value.GetUnit() == eCSSUnit_Null) {
2407 0 : aSystem.Truncate();
2408 0 : return NS_OK;
2409 : }
2410 :
2411 0 : aSystem = NS_ConvertASCIItoUTF16(nsCSSProps::ValueToKeyword(
2412 0 : GetSystem(), nsCSSProps::kCounterSystemKTable));
2413 0 : if (value.GetUnit() == eCSSUnit_Pair) {
2414 0 : aSystem.Append(' ');
2415 0 : GetSystemArgument().AppendToString(
2416 0 : eCSSProperty_UNKNOWN, aSystem, nsCSSValue::eNormalized);
2417 : }
2418 0 : return NS_OK;
2419 : }
2420 :
2421 : NS_IMETHODIMP
2422 0 : nsCSSCounterStyleRule::GetSymbols(nsAString& aSymbols)
2423 : {
2424 0 : const nsCSSValue& value = GetDesc(eCSSCounterDesc_Symbols);
2425 :
2426 0 : aSymbols.Truncate();
2427 0 : if (value.GetUnit() == eCSSUnit_List) {
2428 0 : for (const nsCSSValueList* item = value.GetListValue();
2429 0 : item; item = item->mNext) {
2430 0 : item->mValue.AppendToString(eCSSProperty_UNKNOWN,
2431 : aSymbols,
2432 0 : nsCSSValue::eNormalized);
2433 0 : if (item->mNext) {
2434 0 : aSymbols.Append(' ');
2435 : }
2436 : }
2437 : }
2438 0 : return NS_OK;
2439 : }
2440 :
2441 : NS_IMETHODIMP
2442 0 : nsCSSCounterStyleRule::GetAdditiveSymbols(nsAString& aSymbols)
2443 : {
2444 0 : const nsCSSValue& value = GetDesc(eCSSCounterDesc_AdditiveSymbols);
2445 :
2446 0 : aSymbols.Truncate();
2447 0 : if (value.GetUnit() == eCSSUnit_PairList) {
2448 0 : for (const nsCSSValuePairList* item = value.GetPairListValue();
2449 0 : item; item = item->mNext) {
2450 0 : item->mXValue.AppendToString(eCSSProperty_UNKNOWN,
2451 0 : aSymbols, nsCSSValue::eNormalized);
2452 0 : aSymbols.Append(' ');
2453 0 : item->mYValue.AppendToString(eCSSProperty_UNKNOWN,
2454 0 : aSymbols, nsCSSValue::eNormalized);
2455 0 : if (item->mNext) {
2456 0 : aSymbols.AppendLiteral(", ");
2457 : }
2458 : }
2459 : }
2460 0 : return NS_OK;
2461 : }
2462 :
2463 : NS_IMETHODIMP
2464 0 : nsCSSCounterStyleRule::GetRange(nsAString& aRange)
2465 : {
2466 0 : const nsCSSValue& value = GetDesc(eCSSCounterDesc_Range);
2467 :
2468 0 : switch (value.GetUnit()) {
2469 : case eCSSUnit_Auto:
2470 0 : aRange.AssignLiteral(u"auto");
2471 0 : break;
2472 :
2473 : case eCSSUnit_PairList:
2474 0 : aRange.Truncate();
2475 0 : for (const nsCSSValuePairList* item = value.GetPairListValue();
2476 0 : item; item = item->mNext) {
2477 0 : const nsCSSValue& lower = item->mXValue;
2478 0 : const nsCSSValue& upper = item->mYValue;
2479 0 : if (lower.GetUnit() == eCSSUnit_Enumerated) {
2480 0 : NS_ASSERTION(lower.GetIntValue() ==
2481 : NS_STYLE_COUNTER_RANGE_INFINITE,
2482 : "Unrecognized keyword");
2483 0 : aRange.AppendLiteral("infinite");
2484 : } else {
2485 0 : aRange.AppendInt(lower.GetIntValue());
2486 : }
2487 0 : aRange.Append(' ');
2488 0 : if (upper.GetUnit() == eCSSUnit_Enumerated) {
2489 0 : NS_ASSERTION(upper.GetIntValue() ==
2490 : NS_STYLE_COUNTER_RANGE_INFINITE,
2491 : "Unrecognized keyword");
2492 0 : aRange.AppendLiteral("infinite");
2493 : } else {
2494 0 : aRange.AppendInt(upper.GetIntValue());
2495 : }
2496 0 : if (item->mNext) {
2497 0 : aRange.AppendLiteral(", ");
2498 : }
2499 : }
2500 0 : break;
2501 :
2502 : default:
2503 0 : aRange.Truncate();
2504 : }
2505 0 : return NS_OK;
2506 : }
2507 :
2508 : NS_IMETHODIMP
2509 0 : nsCSSCounterStyleRule::GetSpeakAs(nsAString& aSpeakAs)
2510 : {
2511 0 : const nsCSSValue& value = GetDesc(eCSSCounterDesc_SpeakAs);
2512 :
2513 0 : switch (value.GetUnit()) {
2514 : case eCSSUnit_Enumerated:
2515 0 : switch (value.GetIntValue()) {
2516 : case NS_STYLE_COUNTER_SPEAKAS_BULLETS:
2517 0 : aSpeakAs.AssignLiteral(u"bullets");
2518 0 : break;
2519 : case NS_STYLE_COUNTER_SPEAKAS_NUMBERS:
2520 0 : aSpeakAs.AssignLiteral(u"numbers");
2521 0 : break;
2522 : case NS_STYLE_COUNTER_SPEAKAS_WORDS:
2523 0 : aSpeakAs.AssignLiteral(u"words");
2524 0 : break;
2525 : case NS_STYLE_COUNTER_SPEAKAS_SPELL_OUT:
2526 0 : aSpeakAs.AssignLiteral(u"spell-out");
2527 0 : break;
2528 : default:
2529 0 : NS_NOTREACHED("Unknown speech synthesis");
2530 : }
2531 0 : break;
2532 :
2533 : case eCSSUnit_Auto:
2534 : case eCSSUnit_AtomIdent:
2535 0 : aSpeakAs.Truncate();
2536 : value.AppendToString(eCSSProperty_UNKNOWN,
2537 0 : aSpeakAs, nsCSSValue::eNormalized);
2538 0 : break;
2539 :
2540 : case eCSSUnit_Null:
2541 0 : aSpeakAs.Truncate();
2542 0 : break;
2543 :
2544 : default:
2545 0 : NS_NOTREACHED("Unknown speech synthesis");
2546 0 : aSpeakAs.Truncate();
2547 : }
2548 0 : return NS_OK;
2549 : }
2550 :
2551 : nsresult
2552 0 : nsCSSCounterStyleRule::GetDescriptor(nsCSSCounterDesc aDescID,
2553 : nsAString& aValue)
2554 : {
2555 0 : NS_ASSERTION(aDescID == eCSSCounterDesc_Negative ||
2556 : aDescID == eCSSCounterDesc_Prefix ||
2557 : aDescID == eCSSCounterDesc_Suffix ||
2558 : aDescID == eCSSCounterDesc_Pad ||
2559 : aDescID == eCSSCounterDesc_Fallback,
2560 : "Unexpected descriptor");
2561 0 : const nsCSSValue& value = GetDesc(aDescID);
2562 0 : aValue.Truncate();
2563 0 : if (value.GetUnit() != eCSSUnit_Null) {
2564 : value.AppendToString(
2565 0 : eCSSProperty_UNKNOWN, aValue, nsCSSValue::eNormalized);
2566 : }
2567 0 : return NS_OK;
2568 : }
2569 :
2570 : #define CSS_COUNTER_DESC_GETTER(name_) \
2571 : NS_IMETHODIMP \
2572 : nsCSSCounterStyleRule::Get##name_(nsAString& a##name_) \
2573 : { \
2574 : return GetDescriptor(eCSSCounterDesc_##name_, a##name_);\
2575 : }
2576 0 : CSS_COUNTER_DESC_GETTER(Negative)
2577 0 : CSS_COUNTER_DESC_GETTER(Prefix)
2578 0 : CSS_COUNTER_DESC_GETTER(Suffix)
2579 0 : CSS_COUNTER_DESC_GETTER(Pad)
2580 0 : CSS_COUNTER_DESC_GETTER(Fallback)
2581 : #undef CSS_COUNTER_DESC_GETTER
2582 :
2583 : /* static */ bool
2584 66 : nsCSSCounterStyleRule::CheckDescValue(int32_t aSystem,
2585 : nsCSSCounterDesc aDescID,
2586 : const nsCSSValue& aValue)
2587 : {
2588 66 : switch (aDescID) {
2589 : case eCSSCounterDesc_System:
2590 0 : if (aValue.GetUnit() != eCSSUnit_Pair) {
2591 0 : return aValue.GetIntValue() == aSystem;
2592 : } else {
2593 0 : return aValue.GetPairValue().mXValue.GetIntValue() == aSystem;
2594 : }
2595 :
2596 : case eCSSCounterDesc_Symbols:
2597 66 : switch (aSystem) {
2598 : case NS_STYLE_COUNTER_SYSTEM_NUMERIC:
2599 : case NS_STYLE_COUNTER_SYSTEM_ALPHABETIC:
2600 : // for these two system, the list must contain at least 2 elements
2601 66 : return aValue.GetListValue()->mNext;
2602 : case NS_STYLE_COUNTER_SYSTEM_EXTENDS:
2603 : // for extends system, no symbols should be set
2604 0 : return false;
2605 : default:
2606 0 : return true;
2607 : }
2608 :
2609 : case eCSSCounterDesc_AdditiveSymbols:
2610 0 : switch (aSystem) {
2611 : case NS_STYLE_COUNTER_SYSTEM_EXTENDS:
2612 0 : return false;
2613 : default:
2614 0 : return true;
2615 : }
2616 :
2617 : default:
2618 0 : return true;
2619 : }
2620 : }
2621 :
2622 : nsresult
2623 0 : nsCSSCounterStyleRule::SetDescriptor(nsCSSCounterDesc aDescID,
2624 : const nsAString& aValue)
2625 : {
2626 0 : nsCSSParser parser;
2627 0 : nsCSSValue value;
2628 0 : nsIURI* baseURL = nullptr;
2629 0 : nsIPrincipal* principal = nullptr;
2630 0 : if (StyleSheet* sheet = GetStyleSheet()) {
2631 0 : baseURL = sheet->GetBaseURI();
2632 0 : principal = sheet->Principal();
2633 : }
2634 0 : if (parser.ParseCounterDescriptor(aDescID, aValue, nullptr,
2635 : baseURL, principal, value)) {
2636 0 : if (CheckDescValue(GetSystem(), aDescID, value)) {
2637 0 : SetDesc(aDescID, value);
2638 : }
2639 : }
2640 0 : return NS_OK;
2641 : }
2642 :
2643 : #define CSS_COUNTER_DESC_SETTER(name_) \
2644 : NS_IMETHODIMP \
2645 : nsCSSCounterStyleRule::Set##name_(const nsAString& a##name_) \
2646 : { \
2647 : return SetDescriptor(eCSSCounterDesc_##name_, a##name_); \
2648 : }
2649 0 : CSS_COUNTER_DESC_SETTER(System)
2650 0 : CSS_COUNTER_DESC_SETTER(Symbols)
2651 0 : CSS_COUNTER_DESC_SETTER(AdditiveSymbols)
2652 0 : CSS_COUNTER_DESC_SETTER(Negative)
2653 0 : CSS_COUNTER_DESC_SETTER(Prefix)
2654 0 : CSS_COUNTER_DESC_SETTER(Suffix)
2655 0 : CSS_COUNTER_DESC_SETTER(Range)
2656 0 : CSS_COUNTER_DESC_SETTER(Pad)
2657 0 : CSS_COUNTER_DESC_SETTER(Fallback)
2658 0 : CSS_COUNTER_DESC_SETTER(SpeakAs)
2659 : #undef CSS_COUNTER_DESC_SETTER
2660 :
2661 : /* virtual */ size_t
2662 0 : nsCSSCounterStyleRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
2663 : {
2664 0 : return aMallocSizeOf(this);
2665 : }
2666 :
2667 : /* virtual */ JSObject*
2668 0 : nsCSSCounterStyleRule::WrapObject(JSContext* aCx,
2669 : JS::Handle<JSObject*> aGivenProto)
2670 : {
2671 0 : return CSSCounterStyleRuleBinding::Wrap(aCx, this, aGivenProto);
2672 : }
|