Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/frame/csp/SourceListDirective.h" | 5 #include "core/frame/csp/SourceListDirective.h" |
| 6 | 6 |
| 7 #include "core/frame/csp/CSPSourceList.h" | 7 #include "core/frame/csp/CSPSource.h" |
| 8 #include "core/frame/csp/ContentSecurityPolicy.h" | 8 #include "core/frame/csp/ContentSecurityPolicy.h" |
| 9 #include "platform/network/ContentSecurityPolicyParsers.h" | 9 #include "platform/network/ContentSecurityPolicyParsers.h" |
| 10 #include "platform/weborigin/KURL.h" | 10 #include "platform/weborigin/KURL.h" |
| 11 #include "platform/weborigin/SecurityOrigin.h" | |
| 12 #include "wtf/HashSet.h" | |
| 13 #include "wtf/text/Base64.h" | |
| 14 #include "wtf/text/ParsingUtilities.h" | |
| 15 #include "wtf/text/StringToNumber.h" | |
| 11 #include "wtf/text/WTFString.h" | 16 #include "wtf/text/WTFString.h" |
| 12 | 17 |
| 13 namespace blink { | 18 namespace blink { |
| 14 | 19 |
| 15 SourceListDirective::SourceListDirective(const String& name, | 20 SourceListDirective::SourceListDirective(const String& name, |
| 16 const String& value, | 21 const String& value, |
| 17 ContentSecurityPolicy* policy) | 22 ContentSecurityPolicy* policy) |
| 18 : CSPDirective(name, value, policy), m_sourceList(policy, name) { | 23 : CSPDirective(name, value, policy), |
| 24 m_policy(policy), | |
| 25 m_directiveName(name), | |
| 26 m_allowSelf(false), | |
| 27 m_allowStar(false), | |
| 28 m_allowInline(false), | |
| 29 m_allowEval(false), | |
| 30 m_allowDynamic(false), | |
| 31 m_allowHashedAttributes(false), | |
| 32 m_hashAlgorithmsUsed(0) { | |
| 19 Vector<UChar> characters; | 33 Vector<UChar> characters; |
| 20 value.appendTo(characters); | 34 value.appendTo(characters); |
| 21 | 35 parse(characters.data(), characters.data() + characters.size()); |
| 22 m_sourceList.parse(characters.data(), characters.data() + characters.size()); | 36 } |
| 37 | |
| 38 static bool isSourceListNone(const UChar* begin, const UChar* end) { | |
| 39 skipWhile<UChar, isASCIISpace>(begin, end); | |
| 40 | |
| 41 const UChar* position = begin; | |
| 42 skipWhile<UChar, isSourceCharacter>(position, end); | |
| 43 if (!equalIgnoringCase("'none'", StringView(begin, position - begin))) | |
| 44 return false; | |
| 45 | |
| 46 skipWhile<UChar, isASCIISpace>(position, end); | |
| 47 if (position != end) | |
| 48 return false; | |
| 49 | |
| 50 return true; | |
| 23 } | 51 } |
| 24 | 52 |
| 25 bool SourceListDirective::allows( | 53 bool SourceListDirective::allows( |
| 26 const KURL& url, | 54 const KURL& url, |
| 27 ResourceRequest::RedirectStatus redirectStatus) const { | 55 ResourceRequest::RedirectStatus redirectStatus) const { |
| 28 return m_sourceList.matches(url, redirectStatus); | 56 // Wildcards match network schemes ('http', 'https', 'ftp', 'ws', 'wss'), and |
| 57 // the scheme of the protected resource: | |
| 58 // https://w3c.github.io/webappsec-csp/#match-url-to-source-expression. Other | |
| 59 // schemes, including custom schemes, must be explicitly listed in a source | |
| 60 // list. | |
| 61 if (m_allowStar) { | |
| 62 if (url.protocolIsInHTTPFamily() || url.protocolIs("ftp") || | |
| 63 url.protocolIs("ws") || url.protocolIs("wss") || | |
| 64 m_policy->protocolMatchesSelf(url)) | |
| 65 return true; | |
| 66 | |
| 67 return hasSourceMatchInList(url, redirectStatus); | |
| 68 } | |
| 69 | |
| 70 KURL effectiveURL = | |
| 71 m_policy->selfMatchesInnerURL() && SecurityOrigin::shouldUseInnerURL(url) | |
| 72 ? SecurityOrigin::extractInnerURL(url) | |
| 73 : url; | |
| 74 | |
| 75 if (m_allowSelf && m_policy->urlMatchesSelf(effectiveURL)) | |
| 76 return true; | |
| 77 | |
| 78 return hasSourceMatchInList(effectiveURL, redirectStatus); | |
| 29 } | 79 } |
| 30 | 80 |
| 31 bool SourceListDirective::allowInline() const { | 81 bool SourceListDirective::allowInline() const { |
| 32 return m_sourceList.allowInline(); | 82 return m_allowInline; |
| 33 } | 83 } |
| 34 | 84 |
| 35 bool SourceListDirective::allowEval() const { | 85 bool SourceListDirective::allowEval() const { |
| 36 return m_sourceList.allowEval(); | 86 return m_allowEval; |
| 37 } | 87 } |
| 38 | 88 |
| 39 bool SourceListDirective::allowDynamic() const { | 89 bool SourceListDirective::allowDynamic() const { |
| 40 return m_sourceList.allowDynamic(); | 90 return m_allowDynamic; |
| 41 } | 91 } |
| 42 | 92 |
| 43 bool SourceListDirective::allowNonce(const String& nonce) const { | 93 bool SourceListDirective::allowNonce(const String& nonce) const { |
| 44 return m_sourceList.allowNonce(nonce.stripWhiteSpace()); | 94 String nonceStripped = nonce.stripWhiteSpace(); |
|
amalika
2016/10/27 12:34:19
Changed this to strip white space inside!
| |
| 95 return !nonceStripped.isNull() && m_nonces.contains(nonceStripped); | |
| 45 } | 96 } |
| 46 | 97 |
| 47 bool SourceListDirective::allowHash(const CSPHashValue& hashValue) const { | 98 bool SourceListDirective::allowHash(const CSPHashValue& hashValue) const { |
| 48 return m_sourceList.allowHash(hashValue); | 99 return m_hashes.contains(hashValue); |
| 49 } | 100 } |
| 50 | 101 |
| 51 bool SourceListDirective::allowHashedAttributes() const { | 102 bool SourceListDirective::allowHashedAttributes() const { |
| 52 return m_sourceList.allowHashedAttributes(); | 103 return m_allowHashedAttributes; |
| 104 } | |
| 105 | |
| 106 uint8_t SourceListDirective::hashAlgorithmsUsed() const { | |
| 107 return m_hashAlgorithmsUsed; | |
| 53 } | 108 } |
| 54 | 109 |
| 55 bool SourceListDirective::isHashOrNoncePresent() const { | 110 bool SourceListDirective::isHashOrNoncePresent() const { |
| 56 return m_sourceList.isHashOrNoncePresent(); | 111 return !m_nonces.isEmpty() || |
| 57 } | 112 m_hashAlgorithmsUsed != ContentSecurityPolicyHashAlgorithmNone; |
| 58 | 113 } |
| 59 uint8_t SourceListDirective::hashAlgorithmsUsed() const { | 114 |
| 60 return m_sourceList.hashAlgorithmsUsed(); | 115 // source-list = *WSP [ source *( 1*WSP source ) *WSP ] |
| 116 // / *WSP "'none'" *WSP | |
| 117 // | |
| 118 void SourceListDirective::parse(const UChar* begin, const UChar* end) { | |
| 119 // We represent 'none' as an empty m_list. | |
| 120 if (isSourceListNone(begin, end)) | |
| 121 return; | |
| 122 | |
| 123 const UChar* position = begin; | |
| 124 while (position < end) { | |
| 125 skipWhile<UChar, isASCIISpace>(position, end); | |
| 126 if (position == end) | |
| 127 return; | |
| 128 | |
| 129 const UChar* beginSource = position; | |
| 130 skipWhile<UChar, isSourceCharacter>(position, end); | |
| 131 | |
| 132 String scheme, host, path; | |
| 133 int port = 0; | |
| 134 CSPSource::WildcardDisposition hostWildcard = CSPSource::NoWildcard; | |
| 135 CSPSource::WildcardDisposition portWildcard = CSPSource::NoWildcard; | |
| 136 | |
| 137 if (parseSource(beginSource, position, scheme, host, port, path, | |
| 138 hostWildcard, portWildcard)) { | |
| 139 // Wildcard hosts and keyword sources ('self', 'unsafe-inline', | |
| 140 // etc.) aren't stored in m_list, but as attributes on the source | |
| 141 // list itself. | |
| 142 if (scheme.isEmpty() && host.isEmpty()) | |
| 143 continue; | |
| 144 if (m_policy->isDirectiveName(host)) | |
| 145 m_policy->reportDirectiveAsSourceExpression(m_directiveName, host); | |
| 146 m_list.append(new CSPSource(m_policy, scheme, host, port, path, | |
| 147 hostWildcard, portWildcard)); | |
| 148 } else { | |
| 149 m_policy->reportInvalidSourceExpression( | |
| 150 m_directiveName, String(beginSource, position - beginSource)); | |
| 151 } | |
| 152 | |
| 153 DCHECK(position == end || isASCIISpace(*position)); | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 // source = scheme ":" | |
| 158 // / ( [ scheme "://" ] host [ port ] [ path ] ) | |
| 159 // / "'self'" | |
| 160 bool SourceListDirective::parseSource( | |
| 161 const UChar* begin, | |
| 162 const UChar* end, | |
| 163 String& scheme, | |
| 164 String& host, | |
| 165 int& port, | |
| 166 String& path, | |
| 167 CSPSource::WildcardDisposition& hostWildcard, | |
| 168 CSPSource::WildcardDisposition& portWildcard) { | |
| 169 if (begin == end) | |
| 170 return false; | |
| 171 | |
| 172 StringView token(begin, end - begin); | |
| 173 | |
| 174 if (equalIgnoringCase("'none'", token)) | |
| 175 return false; | |
| 176 | |
| 177 if (end - begin == 1 && *begin == '*') { | |
| 178 addSourceStar(); | |
| 179 return true; | |
| 180 } | |
| 181 | |
| 182 if (equalIgnoringCase("'self'", token)) { | |
| 183 addSourceSelf(); | |
| 184 return true; | |
| 185 } | |
| 186 | |
| 187 if (equalIgnoringCase("'unsafe-inline'", token)) { | |
| 188 addSourceUnsafeInline(); | |
| 189 return true; | |
| 190 } | |
| 191 | |
| 192 if (equalIgnoringCase("'unsafe-eval'", token)) { | |
| 193 addSourceUnsafeEval(); | |
| 194 return true; | |
| 195 } | |
| 196 | |
| 197 if (equalIgnoringCase("'strict-dynamic'", token)) { | |
| 198 addSourceStrictDynamic(); | |
| 199 return true; | |
| 200 } | |
| 201 | |
| 202 if (equalIgnoringCase("'unsafe-hashed-attributes'", token)) { | |
| 203 addSourceUnsafeHashedAttributes(); | |
| 204 return true; | |
| 205 } | |
| 206 | |
| 207 String nonce; | |
| 208 if (!parseNonce(begin, end, nonce)) | |
| 209 return false; | |
| 210 | |
| 211 if (!nonce.isNull()) { | |
| 212 addSourceNonce(nonce); | |
| 213 return true; | |
| 214 } | |
| 215 | |
| 216 DigestValue hash; | |
| 217 ContentSecurityPolicyHashAlgorithm algorithm = | |
| 218 ContentSecurityPolicyHashAlgorithmNone; | |
| 219 if (!parseHash(begin, end, hash, algorithm)) | |
| 220 return false; | |
| 221 | |
| 222 if (hash.size() > 0) { | |
| 223 addSourceHash(algorithm, hash); | |
| 224 return true; | |
| 225 } | |
| 226 | |
| 227 const UChar* position = begin; | |
| 228 const UChar* beginHost = begin; | |
| 229 const UChar* beginPath = end; | |
| 230 const UChar* beginPort = 0; | |
| 231 | |
| 232 skipWhile<UChar, isNotColonOrSlash>(position, end); | |
| 233 | |
| 234 if (position == end) { | |
| 235 // host | |
| 236 // ^ | |
| 237 return parseHost(beginHost, position, host, hostWildcard); | |
| 238 } | |
| 239 | |
| 240 if (position < end && *position == '/') { | |
| 241 // host/path || host/ || / | |
| 242 // ^ ^ ^ | |
| 243 return parseHost(beginHost, position, host, hostWildcard) && | |
| 244 parsePath(position, end, path); | |
| 245 } | |
| 246 | |
| 247 if (position < end && *position == ':') { | |
| 248 if (end - position == 1) { | |
| 249 // scheme: | |
| 250 // ^ | |
| 251 return parseScheme(begin, position, scheme); | |
| 252 } | |
| 253 | |
| 254 if (position[1] == '/') { | |
| 255 // scheme://host || scheme:// | |
| 256 // ^ ^ | |
| 257 if (!parseScheme(begin, position, scheme) || | |
| 258 !skipExactly<UChar>(position, end, ':') || | |
| 259 !skipExactly<UChar>(position, end, '/') || | |
| 260 !skipExactly<UChar>(position, end, '/')) | |
| 261 return false; | |
| 262 if (position == end) | |
| 263 return false; | |
| 264 beginHost = position; | |
| 265 skipWhile<UChar, isNotColonOrSlash>(position, end); | |
| 266 } | |
| 267 | |
| 268 if (position < end && *position == ':') { | |
| 269 // host:port || scheme://host:port | |
| 270 // ^ ^ | |
| 271 beginPort = position; | |
| 272 skipUntil<UChar>(position, end, '/'); | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 if (position < end && *position == '/') { | |
| 277 // scheme://host/path || scheme://host:port/path | |
| 278 // ^ ^ | |
| 279 if (position == beginHost) | |
| 280 return false; | |
| 281 beginPath = position; | |
| 282 } | |
| 283 | |
| 284 if (!parseHost(beginHost, beginPort ? beginPort : beginPath, host, | |
| 285 hostWildcard)) | |
| 286 return false; | |
| 287 | |
| 288 if (beginPort) { | |
| 289 if (!parsePort(beginPort, beginPath, port, portWildcard)) | |
| 290 return false; | |
| 291 } else { | |
| 292 port = 0; | |
| 293 } | |
| 294 | |
| 295 if (beginPath != end) { | |
| 296 if (!parsePath(beginPath, end, path)) | |
| 297 return false; | |
| 298 } | |
| 299 | |
| 300 return true; | |
| 301 } | |
| 302 | |
| 303 // nonce-source = "'nonce-" nonce-value "'" | |
| 304 // nonce-value = 1*( ALPHA / DIGIT / "+" / "/" / "=" ) | |
| 305 // | |
| 306 bool SourceListDirective::parseNonce(const UChar* begin, | |
| 307 const UChar* end, | |
| 308 String& nonce) { | |
| 309 size_t nonceLength = end - begin; | |
| 310 StringView prefix("'nonce-"); | |
| 311 | |
| 312 // TODO(esprehn): Should be StringView(begin, nonceLength).startsWith(prefix). | |
| 313 if (nonceLength <= prefix.length() || | |
| 314 !equalIgnoringCase(prefix, StringView(begin, prefix.length()))) | |
| 315 return true; | |
| 316 | |
| 317 const UChar* position = begin + prefix.length(); | |
| 318 const UChar* nonceBegin = position; | |
| 319 | |
| 320 DCHECK(position < end); | |
| 321 skipWhile<UChar, isNonceCharacter>(position, end); | |
| 322 DCHECK(nonceBegin <= position); | |
| 323 | |
| 324 if (position + 1 != end || *position != '\'' || position == nonceBegin) | |
| 325 return false; | |
| 326 | |
| 327 nonce = String(nonceBegin, position - nonceBegin); | |
| 328 return true; | |
| 329 } | |
| 330 | |
| 331 // hash-source = "'" hash-algorithm "-" hash-value "'" | |
| 332 // hash-algorithm = "sha1" / "sha256" / "sha384" / "sha512" | |
| 333 // hash-value = 1*( ALPHA / DIGIT / "+" / "/" / "=" ) | |
| 334 // | |
| 335 bool SourceListDirective::parseHash( | |
| 336 const UChar* begin, | |
| 337 const UChar* end, | |
| 338 DigestValue& hash, | |
| 339 ContentSecurityPolicyHashAlgorithm& hashAlgorithm) { | |
| 340 // Any additions or subtractions from this struct should also modify the | |
| 341 // respective entries in the kAlgorithmMap array in checkDigest(). | |
| 342 static const struct { | |
| 343 const char* prefix; | |
| 344 ContentSecurityPolicyHashAlgorithm type; | |
| 345 } kSupportedPrefixes[] = { | |
| 346 // FIXME: Drop support for SHA-1. It's not in the spec. | |
| 347 {"'sha1-", ContentSecurityPolicyHashAlgorithmSha1}, | |
| 348 {"'sha256-", ContentSecurityPolicyHashAlgorithmSha256}, | |
| 349 {"'sha384-", ContentSecurityPolicyHashAlgorithmSha384}, | |
| 350 {"'sha512-", ContentSecurityPolicyHashAlgorithmSha512}, | |
| 351 {"'sha-256-", ContentSecurityPolicyHashAlgorithmSha256}, | |
| 352 {"'sha-384-", ContentSecurityPolicyHashAlgorithmSha384}, | |
| 353 {"'sha-512-", ContentSecurityPolicyHashAlgorithmSha512}}; | |
| 354 | |
| 355 StringView prefix; | |
| 356 hashAlgorithm = ContentSecurityPolicyHashAlgorithmNone; | |
| 357 size_t hashLength = end - begin; | |
| 358 | |
| 359 for (const auto& algorithm : kSupportedPrefixes) { | |
| 360 prefix = algorithm.prefix; | |
| 361 // TODO(esprehn): Should be StringView(begin, end - | |
| 362 // begin).startsWith(prefix). | |
| 363 if (hashLength > prefix.length() && | |
| 364 equalIgnoringCase(prefix, StringView(begin, prefix.length()))) { | |
| 365 hashAlgorithm = algorithm.type; | |
| 366 break; | |
| 367 } | |
| 368 } | |
| 369 | |
| 370 if (hashAlgorithm == ContentSecurityPolicyHashAlgorithmNone) | |
| 371 return true; | |
| 372 | |
| 373 const UChar* position = begin + prefix.length(); | |
| 374 const UChar* hashBegin = position; | |
| 375 | |
| 376 DCHECK(position < end); | |
| 377 skipWhile<UChar, isBase64EncodedCharacter>(position, end); | |
| 378 DCHECK(hashBegin <= position); | |
| 379 | |
| 380 // Base64 encodings may end with exactly one or two '=' characters | |
| 381 if (position < end) | |
| 382 skipExactly<UChar>(position, position + 1, '='); | |
| 383 if (position < end) | |
| 384 skipExactly<UChar>(position, position + 1, '='); | |
| 385 | |
| 386 if (position + 1 != end || *position != '\'' || position == hashBegin) | |
| 387 return false; | |
| 388 | |
| 389 Vector<char> hashVector; | |
| 390 // We accept base64url-encoded data here by normalizing it to base64. | |
| 391 base64Decode(normalizeToBase64(String(hashBegin, position - hashBegin)), | |
| 392 hashVector); | |
| 393 if (hashVector.size() > kMaxDigestSize) | |
| 394 return false; | |
| 395 hash.append(reinterpret_cast<uint8_t*>(hashVector.data()), hashVector.size()); | |
| 396 return true; | |
| 397 } | |
| 398 | |
| 399 // ; <scheme> production from RFC 3986 | |
| 400 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) | |
| 401 // | |
| 402 bool SourceListDirective::parseScheme(const UChar* begin, | |
| 403 const UChar* end, | |
| 404 String& scheme) { | |
| 405 DCHECK(begin <= end); | |
| 406 DCHECK(scheme.isEmpty()); | |
| 407 | |
| 408 if (begin == end) | |
| 409 return false; | |
| 410 | |
| 411 const UChar* position = begin; | |
| 412 | |
| 413 if (!skipExactly<UChar, isASCIIAlpha>(position, end)) | |
| 414 return false; | |
| 415 | |
| 416 skipWhile<UChar, isSchemeContinuationCharacter>(position, end); | |
| 417 | |
| 418 if (position != end) | |
| 419 return false; | |
| 420 | |
| 421 scheme = String(begin, end - begin); | |
| 422 return true; | |
| 423 } | |
| 424 | |
| 425 // host = [ "*." ] 1*host-char *( "." 1*host-char ) | |
| 426 // / "*" | |
| 427 // host-char = ALPHA / DIGIT / "-" | |
| 428 // | |
| 429 bool SourceListDirective::parseHost( | |
| 430 const UChar* begin, | |
| 431 const UChar* end, | |
| 432 String& host, | |
| 433 CSPSource::WildcardDisposition& hostWildcard) { | |
| 434 DCHECK(begin <= end); | |
| 435 DCHECK(host.isEmpty()); | |
| 436 DCHECK(hostWildcard == CSPSource::NoWildcard); | |
| 437 | |
| 438 if (begin == end) | |
| 439 return false; | |
| 440 | |
| 441 const UChar* position = begin; | |
| 442 | |
| 443 if (skipExactly<UChar>(position, end, '*')) { | |
| 444 hostWildcard = CSPSource::HasWildcard; | |
| 445 | |
| 446 if (position == end) | |
| 447 return true; | |
| 448 | |
| 449 if (!skipExactly<UChar>(position, end, '.')) | |
| 450 return false; | |
| 451 } | |
| 452 | |
| 453 const UChar* hostBegin = position; | |
| 454 | |
| 455 while (position < end) { | |
| 456 if (!skipExactly<UChar, isHostCharacter>(position, end)) | |
| 457 return false; | |
| 458 | |
| 459 skipWhile<UChar, isHostCharacter>(position, end); | |
| 460 | |
| 461 if (position < end && !skipExactly<UChar>(position, end, '.')) | |
| 462 return false; | |
| 463 } | |
| 464 | |
| 465 DCHECK(position == end); | |
| 466 host = String(hostBegin, end - hostBegin); | |
| 467 return true; | |
| 468 } | |
| 469 | |
| 470 bool SourceListDirective::parsePath(const UChar* begin, | |
| 471 const UChar* end, | |
| 472 String& path) { | |
| 473 DCHECK(begin <= end); | |
| 474 DCHECK(path.isEmpty()); | |
| 475 | |
| 476 const UChar* position = begin; | |
| 477 skipWhile<UChar, isPathComponentCharacter>(position, end); | |
| 478 // path/to/file.js?query=string || path/to/file.js#anchor | |
| 479 // ^ ^ | |
| 480 if (position < end) { | |
| 481 m_policy->reportInvalidPathCharacter(m_directiveName, | |
| 482 String(begin, end - begin), *position); | |
| 483 } | |
| 484 | |
| 485 path = decodeURLEscapeSequences(String(begin, position - begin)); | |
| 486 | |
| 487 DCHECK(position <= end); | |
| 488 DCHECK(position == end || (*position == '#' || *position == '?')); | |
| 489 return true; | |
| 490 } | |
| 491 | |
| 492 // port = ":" ( 1*DIGIT / "*" ) | |
| 493 // | |
| 494 bool SourceListDirective::parsePort( | |
| 495 const UChar* begin, | |
| 496 const UChar* end, | |
| 497 int& port, | |
| 498 CSPSource::WildcardDisposition& portWildcard) { | |
| 499 DCHECK(begin <= end); | |
| 500 DCHECK(!port); | |
| 501 DCHECK(portWildcard == CSPSource::NoWildcard); | |
| 502 | |
| 503 if (!skipExactly<UChar>(begin, end, ':')) | |
| 504 NOTREACHED(); | |
| 505 | |
| 506 if (begin == end) | |
| 507 return false; | |
| 508 | |
| 509 if (end - begin == 1 && *begin == '*') { | |
| 510 port = 0; | |
| 511 portWildcard = CSPSource::HasWildcard; | |
| 512 return true; | |
| 513 } | |
| 514 | |
| 515 const UChar* position = begin; | |
| 516 skipWhile<UChar, isASCIIDigit>(position, end); | |
| 517 | |
| 518 if (position != end) | |
| 519 return false; | |
| 520 | |
| 521 bool ok; | |
| 522 port = charactersToIntStrict(begin, end - begin, &ok); | |
| 523 return ok; | |
| 524 } | |
| 525 | |
| 526 void SourceListDirective::addSourceSelf() { | |
| 527 m_allowSelf = true; | |
| 528 } | |
| 529 | |
| 530 void SourceListDirective::addSourceStar() { | |
| 531 m_allowStar = true; | |
| 532 } | |
| 533 | |
| 534 void SourceListDirective::addSourceUnsafeInline() { | |
| 535 m_allowInline = true; | |
| 536 } | |
| 537 | |
| 538 void SourceListDirective::addSourceUnsafeEval() { | |
| 539 m_allowEval = true; | |
| 540 } | |
| 541 | |
| 542 void SourceListDirective::addSourceStrictDynamic() { | |
| 543 m_allowDynamic = true; | |
| 544 } | |
| 545 | |
| 546 void SourceListDirective::addSourceUnsafeHashedAttributes() { | |
| 547 m_allowHashedAttributes = true; | |
| 548 } | |
| 549 | |
| 550 void SourceListDirective::addSourceNonce(const String& nonce) { | |
| 551 m_nonces.add(nonce); | |
| 552 } | |
| 553 | |
| 554 void SourceListDirective::addSourceHash( | |
| 555 const ContentSecurityPolicyHashAlgorithm& algorithm, | |
| 556 const DigestValue& hash) { | |
| 557 m_hashes.add(CSPHashValue(algorithm, hash)); | |
| 558 m_hashAlgorithmsUsed |= algorithm; | |
| 559 } | |
| 560 | |
| 561 bool SourceListDirective::hasSourceMatchInList( | |
| 562 const KURL& url, | |
| 563 ResourceRequest::RedirectStatus redirectStatus) const { | |
| 564 for (size_t i = 0; i < m_list.size(); ++i) { | |
| 565 if (m_list[i]->matches(url, redirectStatus)) | |
| 566 return true; | |
| 567 } | |
| 568 | |
| 569 return false; | |
| 61 } | 570 } |
| 62 | 571 |
| 63 DEFINE_TRACE(SourceListDirective) { | 572 DEFINE_TRACE(SourceListDirective) { |
| 64 visitor->trace(m_sourceList); | 573 visitor->trace(m_policy); |
| 574 visitor->trace(m_list); | |
| 65 CSPDirective::trace(visitor); | 575 CSPDirective::trace(visitor); |
| 66 } | 576 } |
| 67 | 577 |
| 68 } // namespace blink | 578 } // namespace blink |
| OLD | NEW |