|
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 #include "nsStyleUtil.h" |
|
7 #include "nsStyleConsts.h" |
|
8 |
|
9 #include "nsIContent.h" |
|
10 #include "nsCSSProps.h" |
|
11 #include "nsRuleNode.h" |
|
12 #include "nsROCSSPrimitiveValue.h" |
|
13 #include "nsIContentPolicy.h" |
|
14 #include "nsIContentSecurityPolicy.h" |
|
15 #include "nsIURI.h" |
|
16 |
|
17 using namespace mozilla; |
|
18 |
|
19 //------------------------------------------------------------------------------ |
|
20 // Font Algorithm Code |
|
21 //------------------------------------------------------------------------------ |
|
22 |
|
23 // Compare two language strings |
|
24 bool nsStyleUtil::DashMatchCompare(const nsAString& aAttributeValue, |
|
25 const nsAString& aSelectorValue, |
|
26 const nsStringComparator& aComparator) |
|
27 { |
|
28 bool result; |
|
29 uint32_t selectorLen = aSelectorValue.Length(); |
|
30 uint32_t attributeLen = aAttributeValue.Length(); |
|
31 if (selectorLen > attributeLen) { |
|
32 result = false; |
|
33 } |
|
34 else { |
|
35 nsAString::const_iterator iter; |
|
36 if (selectorLen != attributeLen && |
|
37 *aAttributeValue.BeginReading(iter).advance(selectorLen) != |
|
38 char16_t('-')) { |
|
39 // to match, the aAttributeValue must have a dash after the end of |
|
40 // the aSelectorValue's text (unless the aSelectorValue and the |
|
41 // aAttributeValue have the same text) |
|
42 result = false; |
|
43 } |
|
44 else { |
|
45 result = StringBeginsWith(aAttributeValue, aSelectorValue, aComparator); |
|
46 } |
|
47 } |
|
48 return result; |
|
49 } |
|
50 |
|
51 void nsStyleUtil::AppendEscapedCSSString(const nsAString& aString, |
|
52 nsAString& aReturn, |
|
53 char16_t quoteChar) |
|
54 { |
|
55 NS_PRECONDITION(quoteChar == '\'' || quoteChar == '"', |
|
56 "CSS strings must be quoted with ' or \""); |
|
57 aReturn.Append(quoteChar); |
|
58 |
|
59 const char16_t* in = aString.BeginReading(); |
|
60 const char16_t* const end = aString.EndReading(); |
|
61 for (; in != end; in++) { |
|
62 if (*in < 0x20 || (*in >= 0x7F && *in < 0xA0)) { |
|
63 // Escape U+0000 through U+001F and U+007F through U+009F numerically. |
|
64 aReturn.AppendPrintf("\\%hX ", *in); |
|
65 } else { |
|
66 if (*in == '"' || *in == '\'' || *in == '\\') { |
|
67 // Escape backslash and quote characters symbolically. |
|
68 // It's not technically necessary to escape the quote |
|
69 // character that isn't being used to delimit the string, |
|
70 // but we do it anyway because that makes testing simpler. |
|
71 aReturn.Append(char16_t('\\')); |
|
72 } |
|
73 aReturn.Append(*in); |
|
74 } |
|
75 } |
|
76 |
|
77 aReturn.Append(quoteChar); |
|
78 } |
|
79 |
|
80 /* static */ bool |
|
81 nsStyleUtil::AppendEscapedCSSIdent(const nsAString& aIdent, nsAString& aReturn) |
|
82 { |
|
83 // The relevant parts of the CSS grammar are: |
|
84 // ident [-]?{nmstart}{nmchar}* |
|
85 // nmstart [_a-z]|{nonascii}|{escape} |
|
86 // nmchar [_a-z0-9-]|{nonascii}|{escape} |
|
87 // nonascii [^\0-\177] |
|
88 // escape {unicode}|\\[^\n\r\f0-9a-f] |
|
89 // unicode \\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])? |
|
90 // from http://www.w3.org/TR/CSS21/syndata.html#tokenization |
|
91 |
|
92 const char16_t* in = aIdent.BeginReading(); |
|
93 const char16_t* const end = aIdent.EndReading(); |
|
94 |
|
95 if (in == end) |
|
96 return true; |
|
97 |
|
98 // A leading dash does not need to be escaped as long as it is not the |
|
99 // *only* character in the identifier. |
|
100 if (in + 1 != end && *in == '-') { |
|
101 aReturn.Append(char16_t('-')); |
|
102 ++in; |
|
103 } |
|
104 |
|
105 // Escape a digit at the start (including after a dash), |
|
106 // numerically. If we didn't escape it numerically, it would get |
|
107 // interpreted as a numeric escape for the wrong character. |
|
108 // A second dash immediately after a leading dash must also be |
|
109 // escaped, but this may be done symbolically. |
|
110 if (in != end && (*in == '-' || |
|
111 ('0' <= *in && *in <= '9'))) { |
|
112 if (*in == '-') { |
|
113 aReturn.Append(char16_t('\\')); |
|
114 aReturn.Append(char16_t('-')); |
|
115 } else { |
|
116 aReturn.AppendPrintf("\\%hX ", *in); |
|
117 } |
|
118 ++in; |
|
119 } |
|
120 |
|
121 for (; in != end; ++in) { |
|
122 char16_t ch = *in; |
|
123 if (ch == 0x00) { |
|
124 return false; |
|
125 } |
|
126 if (ch < 0x20 || (0x7F <= ch && ch < 0xA0)) { |
|
127 // Escape U+0000 through U+001F and U+007F through U+009F numerically. |
|
128 aReturn.AppendPrintf("\\%hX ", *in); |
|
129 } else { |
|
130 // Escape ASCII non-identifier printables as a backslash plus |
|
131 // the character. |
|
132 if (ch < 0x7F && |
|
133 ch != '_' && ch != '-' && |
|
134 (ch < '0' || '9' < ch) && |
|
135 (ch < 'A' || 'Z' < ch) && |
|
136 (ch < 'a' || 'z' < ch)) { |
|
137 aReturn.Append(char16_t('\\')); |
|
138 } |
|
139 aReturn.Append(ch); |
|
140 } |
|
141 } |
|
142 return true; |
|
143 } |
|
144 |
|
145 /* static */ void |
|
146 nsStyleUtil::AppendBitmaskCSSValue(nsCSSProperty aProperty, |
|
147 int32_t aMaskedValue, |
|
148 int32_t aFirstMask, |
|
149 int32_t aLastMask, |
|
150 nsAString& aResult) |
|
151 { |
|
152 for (int32_t mask = aFirstMask; mask <= aLastMask; mask <<= 1) { |
|
153 if (mask & aMaskedValue) { |
|
154 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, mask), |
|
155 aResult); |
|
156 aMaskedValue &= ~mask; |
|
157 if (aMaskedValue) { // more left |
|
158 aResult.Append(char16_t(' ')); |
|
159 } |
|
160 } |
|
161 } |
|
162 NS_ABORT_IF_FALSE(aMaskedValue == 0, "unexpected bit remaining in bitfield"); |
|
163 } |
|
164 |
|
165 /* static */ void |
|
166 nsStyleUtil::AppendAngleValue(const nsStyleCoord& aAngle, nsAString& aResult) |
|
167 { |
|
168 MOZ_ASSERT(aAngle.IsAngleValue(), "Should have angle value"); |
|
169 |
|
170 // Append number. |
|
171 AppendCSSNumber(aAngle.GetAngleValue(), aResult); |
|
172 |
|
173 // Append unit. |
|
174 switch (aAngle.GetUnit()) { |
|
175 case eStyleUnit_Degree: aResult.AppendLiteral("deg"); break; |
|
176 case eStyleUnit_Grad: aResult.AppendLiteral("grad"); break; |
|
177 case eStyleUnit_Radian: aResult.AppendLiteral("rad"); break; |
|
178 case eStyleUnit_Turn: aResult.AppendLiteral("turn"); break; |
|
179 default: NS_NOTREACHED("unrecognized angle unit"); |
|
180 } |
|
181 } |
|
182 |
|
183 /* static */ void |
|
184 nsStyleUtil::AppendPaintOrderValue(uint8_t aValue, |
|
185 nsAString& aResult) |
|
186 { |
|
187 static_assert |
|
188 (NS_STYLE_PAINT_ORDER_BITWIDTH * NS_STYLE_PAINT_ORDER_LAST_VALUE <= 8, |
|
189 "SVGStyleStruct::mPaintOrder and local variables not big enough"); |
|
190 |
|
191 if (aValue == NS_STYLE_PAINT_ORDER_NORMAL) { |
|
192 aResult.AppendLiteral("normal"); |
|
193 return; |
|
194 } |
|
195 |
|
196 // Append the minimal value necessary for the given paint order. |
|
197 static_assert(NS_STYLE_PAINT_ORDER_LAST_VALUE == 3, |
|
198 "paint-order values added; check serialization"); |
|
199 |
|
200 // The following relies on the default order being the order of the |
|
201 // constant values. |
|
202 |
|
203 const uint8_t MASK = (1 << NS_STYLE_PAINT_ORDER_BITWIDTH) - 1; |
|
204 |
|
205 uint32_t lastPositionToSerialize = 0; |
|
206 for (uint32_t position = NS_STYLE_PAINT_ORDER_LAST_VALUE - 1; |
|
207 position > 0; |
|
208 position--) { |
|
209 uint8_t component = |
|
210 (aValue >> (position * NS_STYLE_PAINT_ORDER_BITWIDTH)) & MASK; |
|
211 uint8_t earlierComponent = |
|
212 (aValue >> ((position - 1) * NS_STYLE_PAINT_ORDER_BITWIDTH)) & MASK; |
|
213 if (component < earlierComponent) { |
|
214 lastPositionToSerialize = position - 1; |
|
215 break; |
|
216 } |
|
217 } |
|
218 |
|
219 for (uint32_t position = 0; position <= lastPositionToSerialize; position++) { |
|
220 if (position > 0) { |
|
221 aResult.AppendLiteral(" "); |
|
222 } |
|
223 uint8_t component = aValue & MASK; |
|
224 switch (component) { |
|
225 case NS_STYLE_PAINT_ORDER_FILL: |
|
226 aResult.AppendLiteral("fill"); |
|
227 break; |
|
228 |
|
229 case NS_STYLE_PAINT_ORDER_STROKE: |
|
230 aResult.AppendLiteral("stroke"); |
|
231 break; |
|
232 |
|
233 case NS_STYLE_PAINT_ORDER_MARKERS: |
|
234 aResult.AppendLiteral("markers"); |
|
235 break; |
|
236 |
|
237 default: |
|
238 NS_NOTREACHED("unexpected paint-order component value"); |
|
239 } |
|
240 aValue >>= NS_STYLE_PAINT_ORDER_BITWIDTH; |
|
241 } |
|
242 } |
|
243 |
|
244 /* static */ void |
|
245 nsStyleUtil::AppendFontFeatureSettings(const nsTArray<gfxFontFeature>& aFeatures, |
|
246 nsAString& aResult) |
|
247 { |
|
248 for (uint32_t i = 0, numFeat = aFeatures.Length(); i < numFeat; i++) { |
|
249 const gfxFontFeature& feat = aFeatures[i]; |
|
250 |
|
251 if (i != 0) { |
|
252 aResult.AppendLiteral(", "); |
|
253 } |
|
254 |
|
255 // output tag |
|
256 char tag[7]; |
|
257 tag[0] = '"'; |
|
258 tag[1] = (feat.mTag >> 24) & 0xff; |
|
259 tag[2] = (feat.mTag >> 16) & 0xff; |
|
260 tag[3] = (feat.mTag >> 8) & 0xff; |
|
261 tag[4] = feat.mTag & 0xff; |
|
262 tag[5] = '"'; |
|
263 tag[6] = 0; |
|
264 aResult.AppendASCII(tag); |
|
265 |
|
266 // output value, if necessary |
|
267 if (feat.mValue == 0) { |
|
268 // 0 ==> off |
|
269 aResult.AppendLiteral(" off"); |
|
270 } else if (feat.mValue > 1) { |
|
271 aResult.AppendLiteral(" "); |
|
272 aResult.AppendInt(feat.mValue); |
|
273 } |
|
274 // else, omit value if 1, implied by default |
|
275 } |
|
276 } |
|
277 |
|
278 /* static */ void |
|
279 nsStyleUtil::AppendFontFeatureSettings(const nsCSSValue& aSrc, |
|
280 nsAString& aResult) |
|
281 { |
|
282 nsCSSUnit unit = aSrc.GetUnit(); |
|
283 |
|
284 if (unit == eCSSUnit_Normal) { |
|
285 aResult.AppendLiteral("normal"); |
|
286 return; |
|
287 } |
|
288 |
|
289 NS_PRECONDITION(unit == eCSSUnit_PairList || unit == eCSSUnit_PairListDep, |
|
290 "improper value unit for font-feature-settings:"); |
|
291 |
|
292 nsTArray<gfxFontFeature> featureSettings; |
|
293 nsRuleNode::ComputeFontFeatures(aSrc.GetPairListValue(), featureSettings); |
|
294 AppendFontFeatureSettings(featureSettings, aResult); |
|
295 } |
|
296 |
|
297 /* static */ void |
|
298 nsStyleUtil::GetFunctionalAlternatesName(int32_t aFeature, |
|
299 nsAString& aFeatureName) |
|
300 { |
|
301 aFeatureName.Truncate(); |
|
302 nsCSSKeyword key = |
|
303 nsCSSProps::ValueToKeywordEnum(aFeature, |
|
304 nsCSSProps::kFontVariantAlternatesFuncsKTable); |
|
305 |
|
306 NS_ASSERTION(key != eCSSKeyword_UNKNOWN, "bad alternate feature type"); |
|
307 AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(key), aFeatureName); |
|
308 } |
|
309 |
|
310 /* static */ void |
|
311 nsStyleUtil::SerializeFunctionalAlternates( |
|
312 const nsTArray<gfxAlternateValue>& aAlternates, |
|
313 nsAString& aResult) |
|
314 { |
|
315 nsAutoString funcName, funcParams; |
|
316 uint32_t numValues = aAlternates.Length(); |
|
317 |
|
318 uint32_t feature = 0; |
|
319 for (uint32_t i = 0; i < numValues; i++) { |
|
320 const gfxAlternateValue& v = aAlternates.ElementAt(i); |
|
321 if (feature != v.alternate) { |
|
322 feature = v.alternate; |
|
323 if (!funcName.IsEmpty() && !funcParams.IsEmpty()) { |
|
324 if (!aResult.IsEmpty()) { |
|
325 aResult.Append(char16_t(' ')); |
|
326 } |
|
327 |
|
328 // append the previous functional value |
|
329 aResult.Append(funcName); |
|
330 aResult.Append(char16_t('(')); |
|
331 aResult.Append(funcParams); |
|
332 aResult.Append(char16_t(')')); |
|
333 } |
|
334 |
|
335 // function name |
|
336 GetFunctionalAlternatesName(v.alternate, funcName); |
|
337 NS_ASSERTION(!funcName.IsEmpty(), "unknown property value name"); |
|
338 |
|
339 // function params |
|
340 funcParams.Truncate(); |
|
341 AppendEscapedCSSIdent(v.value, funcParams); |
|
342 } else { |
|
343 if (!funcParams.IsEmpty()) { |
|
344 funcParams.Append(NS_LITERAL_STRING(", ")); |
|
345 } |
|
346 AppendEscapedCSSIdent(v.value, funcParams); |
|
347 } |
|
348 } |
|
349 |
|
350 // append the previous functional value |
|
351 if (!funcName.IsEmpty() && !funcParams.IsEmpty()) { |
|
352 if (!aResult.IsEmpty()) { |
|
353 aResult.Append(char16_t(' ')); |
|
354 } |
|
355 |
|
356 aResult.Append(funcName); |
|
357 aResult.Append(char16_t('(')); |
|
358 aResult.Append(funcParams); |
|
359 aResult.Append(char16_t(')')); |
|
360 } |
|
361 } |
|
362 |
|
363 /* static */ void |
|
364 nsStyleUtil::ComputeFunctionalAlternates(const nsCSSValueList* aList, |
|
365 nsTArray<gfxAlternateValue>& aAlternateValues) |
|
366 { |
|
367 gfxAlternateValue v; |
|
368 |
|
369 aAlternateValues.Clear(); |
|
370 for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) { |
|
371 // list contains function units |
|
372 if (curr->mValue.GetUnit() != eCSSUnit_Function) { |
|
373 continue; |
|
374 } |
|
375 |
|
376 // element 0 is the propval in ident form |
|
377 const nsCSSValue::Array *func = curr->mValue.GetArrayValue(); |
|
378 |
|
379 // lookup propval |
|
380 nsCSSKeyword key = func->Item(0).GetKeywordValue(); |
|
381 NS_ASSERTION(key != eCSSKeyword_UNKNOWN, "unknown alternate property value"); |
|
382 |
|
383 int32_t alternate; |
|
384 if (key == eCSSKeyword_UNKNOWN || |
|
385 !nsCSSProps::FindKeyword(key, |
|
386 nsCSSProps::kFontVariantAlternatesFuncsKTable, |
|
387 alternate)) { |
|
388 NS_NOTREACHED("keyword not a font-variant-alternates value"); |
|
389 continue; |
|
390 } |
|
391 v.alternate = alternate; |
|
392 |
|
393 // other elements are the idents associated with the propval |
|
394 // append one alternate value for each one |
|
395 uint32_t numElems = func->Count(); |
|
396 for (uint32_t i = 1; i < numElems; i++) { |
|
397 const nsCSSValue& value = func->Item(i); |
|
398 NS_ASSERTION(value.GetUnit() == eCSSUnit_Ident, |
|
399 "weird unit found in variant alternate"); |
|
400 if (value.GetUnit() != eCSSUnit_Ident) { |
|
401 continue; |
|
402 } |
|
403 value.GetStringValue(v.value); |
|
404 aAlternateValues.AppendElement(v); |
|
405 } |
|
406 } |
|
407 } |
|
408 |
|
409 /* static */ float |
|
410 nsStyleUtil::ColorComponentToFloat(uint8_t aAlpha) |
|
411 { |
|
412 // Alpha values are expressed as decimals, so we should convert |
|
413 // back, using as few decimal places as possible for |
|
414 // round-tripping. |
|
415 // First try two decimal places: |
|
416 float rounded = NS_roundf(float(aAlpha) * 100.0f / 255.0f) / 100.0f; |
|
417 if (FloatToColorComponent(rounded) != aAlpha) { |
|
418 // Use three decimal places. |
|
419 rounded = NS_roundf(float(aAlpha) * 1000.0f / 255.0f) / 1000.0f; |
|
420 } |
|
421 return rounded; |
|
422 } |
|
423 |
|
424 /* static */ bool |
|
425 nsStyleUtil::IsSignificantChild(nsIContent* aChild, bool aTextIsSignificant, |
|
426 bool aWhitespaceIsSignificant) |
|
427 { |
|
428 NS_ASSERTION(!aWhitespaceIsSignificant || aTextIsSignificant, |
|
429 "Nonsensical arguments"); |
|
430 |
|
431 bool isText = aChild->IsNodeOfType(nsINode::eTEXT); |
|
432 |
|
433 if (!isText && !aChild->IsNodeOfType(nsINode::eCOMMENT) && |
|
434 !aChild->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) { |
|
435 return true; |
|
436 } |
|
437 |
|
438 return aTextIsSignificant && isText && aChild->TextLength() != 0 && |
|
439 (aWhitespaceIsSignificant || |
|
440 !aChild->TextIsOnlyWhitespace()); |
|
441 } |
|
442 |
|
443 /* static */ bool |
|
444 nsStyleUtil::CSPAllowsInlineStyle(nsIContent* aContent, |
|
445 nsIPrincipal* aPrincipal, |
|
446 nsIURI* aSourceURI, |
|
447 uint32_t aLineNumber, |
|
448 const nsSubstring& aStyleText, |
|
449 nsresult* aRv) |
|
450 { |
|
451 nsresult rv; |
|
452 |
|
453 if (aRv) { |
|
454 *aRv = NS_OK; |
|
455 } |
|
456 |
|
457 MOZ_ASSERT(!aContent || aContent->Tag() == nsGkAtoms::style, |
|
458 "aContent passed to CSPAllowsInlineStyle " |
|
459 "for an element that is not <style>"); |
|
460 |
|
461 nsCOMPtr<nsIContentSecurityPolicy> csp; |
|
462 rv = aPrincipal->GetCsp(getter_AddRefs(csp)); |
|
463 |
|
464 if (NS_FAILED(rv)) { |
|
465 if (aRv) |
|
466 *aRv = rv; |
|
467 return false; |
|
468 } |
|
469 |
|
470 if (!csp) { |
|
471 // No CSP --> the style is allowed |
|
472 return true; |
|
473 } |
|
474 |
|
475 // An inline style can be allowed because all inline styles are allowed, |
|
476 // or else because it is whitelisted by a nonce-source or hash-source. This |
|
477 // is a logical OR between whitelisting methods, so the allowInlineStyle |
|
478 // outparam can be reused for each check as long as we stop checking as soon |
|
479 // as it is set to true. This also optimizes performance by avoiding the |
|
480 // overhead of unnecessary checks. |
|
481 bool allowInlineStyle = true; |
|
482 nsAutoTArray<unsigned short, 3> violations; |
|
483 |
|
484 bool reportInlineViolation; |
|
485 rv = csp->GetAllowsInlineStyle(&reportInlineViolation, &allowInlineStyle); |
|
486 if (NS_FAILED(rv)) { |
|
487 if (aRv) |
|
488 *aRv = rv; |
|
489 return false; |
|
490 } |
|
491 if (reportInlineViolation) { |
|
492 violations.AppendElement(static_cast<unsigned short>( |
|
493 nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_STYLE)); |
|
494 } |
|
495 |
|
496 nsAutoString nonce; |
|
497 if (!allowInlineStyle) { |
|
498 // We can only find a nonce if aContent is provided |
|
499 bool foundNonce = !!aContent && |
|
500 aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::nonce, nonce); |
|
501 if (foundNonce) { |
|
502 bool reportNonceViolation; |
|
503 rv = csp->GetAllowsNonce(nonce, nsIContentPolicy::TYPE_STYLESHEET, |
|
504 &reportNonceViolation, &allowInlineStyle); |
|
505 if (NS_FAILED(rv)) { |
|
506 if (aRv) |
|
507 *aRv = rv; |
|
508 return false; |
|
509 } |
|
510 |
|
511 if (reportNonceViolation) { |
|
512 violations.AppendElement(static_cast<unsigned short>( |
|
513 nsIContentSecurityPolicy::VIOLATION_TYPE_NONCE_STYLE)); |
|
514 } |
|
515 } |
|
516 } |
|
517 |
|
518 if (!allowInlineStyle) { |
|
519 bool reportHashViolation; |
|
520 rv = csp->GetAllowsHash(aStyleText, nsIContentPolicy::TYPE_STYLESHEET, |
|
521 &reportHashViolation, &allowInlineStyle); |
|
522 if (NS_FAILED(rv)) { |
|
523 if (aRv) |
|
524 *aRv = rv; |
|
525 return false; |
|
526 } |
|
527 if (reportHashViolation) { |
|
528 violations.AppendElement(static_cast<unsigned short>( |
|
529 nsIContentSecurityPolicy::VIOLATION_TYPE_HASH_STYLE)); |
|
530 } |
|
531 } |
|
532 |
|
533 // What violation(s) should be reported? |
|
534 // |
|
535 // 1. If the style tag has a nonce attribute, and the nonce does not match |
|
536 // the policy, report VIOLATION_TYPE_NONCE_STYLE. |
|
537 // 2. If the policy has at least one hash-source, and the hashed contents of |
|
538 // the style tag did not match any of them, report VIOLATION_TYPE_HASH_STYLE |
|
539 // 3. Otherwise, report VIOLATION_TYPE_INLINE_STYLE if appropriate. |
|
540 // |
|
541 // 1 and 2 may occur together, 3 should only occur by itself. Naturally, |
|
542 // every VIOLATION_TYPE_NONCE_STYLE and VIOLATION_TYPE_HASH_STYLE are also |
|
543 // VIOLATION_TYPE_INLINE_STYLE, but reporting the |
|
544 // VIOLATION_TYPE_INLINE_STYLE is redundant and does not help the developer. |
|
545 if (!violations.IsEmpty()) { |
|
546 MOZ_ASSERT(violations[0] == nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_STYLE, |
|
547 "How did we get any violations without an initial inline style violation?"); |
|
548 // This inline style is not allowed by CSP, so report the violation |
|
549 nsAutoCString asciiSpec; |
|
550 aSourceURI->GetAsciiSpec(asciiSpec); |
|
551 nsAutoString styleSample(aStyleText); |
|
552 |
|
553 // cap the length of the style sample at 40 chars. |
|
554 if (styleSample.Length() > 40) { |
|
555 styleSample.Truncate(40); |
|
556 styleSample.AppendLiteral("..."); |
|
557 } |
|
558 |
|
559 for (uint32_t i = 0; i < violations.Length(); i++) { |
|
560 // Skip reporting the redundant inline style violation if there are |
|
561 // other (nonce and/or hash violations) as well. |
|
562 if (i > 0 || violations.Length() == 1) { |
|
563 csp->LogViolationDetails(violations[i], NS_ConvertUTF8toUTF16(asciiSpec), |
|
564 styleSample, aLineNumber, nonce, aStyleText); |
|
565 } |
|
566 } |
|
567 } |
|
568 |
|
569 if (!allowInlineStyle) { |
|
570 NS_ASSERTION(!violations.IsEmpty(), |
|
571 "CSP blocked inline style but is not reporting a violation"); |
|
572 // The inline style should be blocked. |
|
573 return false; |
|
574 } |
|
575 // CSP allows inline styles. |
|
576 return true; |
|
577 } |