Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: Source/core/fetch/CrossOriginAccessControl.cpp

Issue 379113002: Move fetch-related predicates to core/fetch. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: rebase Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 22 matching lines...) Expand all
33 #include "platform/network/ResourceRequest.h" 33 #include "platform/network/ResourceRequest.h"
34 #include "platform/network/ResourceResponse.h" 34 #include "platform/network/ResourceResponse.h"
35 #include "platform/weborigin/SchemeRegistry.h" 35 #include "platform/weborigin/SchemeRegistry.h"
36 #include "platform/weborigin/SecurityOrigin.h" 36 #include "platform/weborigin/SecurityOrigin.h"
37 #include "wtf/Threading.h" 37 #include "wtf/Threading.h"
38 #include "wtf/text/AtomicString.h" 38 #include "wtf/text/AtomicString.h"
39 #include "wtf/text/StringBuilder.h" 39 #include "wtf/text/StringBuilder.h"
40 40
41 namespace WebCore { 41 namespace WebCore {
42 42
43 bool isOnAccessControlSimpleRequestMethodWhitelist(const String& method) 43 namespace {
44
45 struct ForbiddenHeaderNames {
46 WTF_MAKE_NONCOPYABLE(ForbiddenHeaderNames); WTF_MAKE_FAST_ALLOCATED;
47 public:
48 ForbiddenHeaderNames();
49 bool has(const String& name) const
50 {
51 return m_fixedNames.contains(name)
52 || name.startsWith(m_proxyHeaderPrefix, false)
53 || name.startsWith(m_secHeaderPrefix, false);
54 }
55
56 private:
57 String m_proxyHeaderPrefix;
58 String m_secHeaderPrefix;
59 HashSet<String, CaseFoldingHash> m_fixedNames;
60 };
61
62 ForbiddenHeaderNames::ForbiddenHeaderNames()
63 : m_proxyHeaderPrefix("proxy-")
64 , m_secHeaderPrefix("sec-")
44 { 65 {
45 return method == "GET" || method == "HEAD" || method == "POST"; 66 m_fixedNames.add("accept-charset");
67 m_fixedNames.add("accept-encoding");
68 m_fixedNames.add("access-control-request-headers");
69 m_fixedNames.add("access-control-request-method");
70 m_fixedNames.add("connection");
71 m_fixedNames.add("content-length");
72 m_fixedNames.add("cookie");
73 m_fixedNames.add("cookie2");
74 m_fixedNames.add("date");
75 m_fixedNames.add("dnt");
76 m_fixedNames.add("expect");
77 m_fixedNames.add("host");
78 m_fixedNames.add("keep-alive");
79 m_fixedNames.add("origin");
80 m_fixedNames.add("referer");
81 m_fixedNames.add("te");
82 m_fixedNames.add("trailer");
83 m_fixedNames.add("transfer-encoding");
84 m_fixedNames.add("upgrade");
85 m_fixedNames.add("user-agent");
86 m_fixedNames.add("via");
46 } 87 }
47 88
48 bool isOnAccessControlSimpleRequestHeaderWhitelist(const AtomicString& name, con st AtomicString& value) 89 static const ForbiddenHeaderNames* forbiddenHeaderNames = nullptr;
90
91 static const ForbiddenHeaderNames* createForbiddenHeaderNames()
49 { 92 {
50 if (equalIgnoringCase(name, "accept") 93 forbiddenHeaderNames = new ForbiddenHeaderNames;
51 || equalIgnoringCase(name, "accept-language") 94 return forbiddenHeaderNames;
52 || equalIgnoringCase(name, "content-language")
53 || equalIgnoringCase(name, "origin")
54 || equalIgnoringCase(name, "referer"))
55 return true;
56
57 // Preflight is required for MIME types that can not be sent via form submis sion.
58 if (equalIgnoringCase(name, "content-type")) {
59 AtomicString mimeType = extractMIMETypeFromMediaType(value);
60 return equalIgnoringCase(mimeType, "application/x-www-form-urlencoded")
61 || equalIgnoringCase(mimeType, "multipart/form-data")
62 || equalIgnoringCase(mimeType, "text/plain");
63 }
64
65 return false;
66 } 95 }
67 96
68 bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap& headerMap) 97 static const ForbiddenHeaderNames* initializeForbiddenHeaderNames()
sof 2014/07/17 08:18:09 Unless there are reasons not to, should we move th
yhirano 2014/08/06 08:48:03 Done.
69 { 98 {
70 if (!isOnAccessControlSimpleRequestMethodWhitelist(method)) 99 // Uses dummy to avoid warnings about an unused variable.
sof 2014/07/17 08:18:09 I know this is code that you moved into here, but
yhirano 2014/08/06 08:48:03 Done.
71 return false; 100 AtomicallyInitializedStatic(const ForbiddenHeaderNames*, dummy = createForbi ddenHeaderNames());
101 return dummy;
102 }
72 103
73 HTTPHeaderMap::const_iterator end = headerMap.end(); 104 } // namespace
74 for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) {
75 if (!isOnAccessControlSimpleRequestHeaderWhitelist(it->key, it->value))
76 return false;
77 }
78
79 return true;
80 }
81 105
82 static PassOwnPtr<HTTPHeaderSet> createAllowedCrossOriginResponseHeadersSet() 106 static PassOwnPtr<HTTPHeaderSet> createAllowedCrossOriginResponseHeadersSet()
83 { 107 {
84 OwnPtr<HTTPHeaderSet> headerSet = adoptPtr(new HashSet<String, CaseFoldingHa sh>); 108 OwnPtr<HTTPHeaderSet> headerSet = adoptPtr(new HashSet<String, CaseFoldingHa sh>);
85 109
86 headerSet->add("cache-control"); 110 headerSet->add("cache-control");
87 headerSet->add("content-language"); 111 headerSet->add("content-language");
88 headerSet->add("content-type"); 112 headerSet->add("content-type");
89 headerSet->add("expires"); 113 headerSet->add("expires");
90 headerSet->add("last-modified"); 114 headerSet->add("last-modified");
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 request.clearHTTPOrigin(); 301 request.clearHTTPOrigin();
278 request.setHTTPOrigin(securityOrigin->toAtomicString()); 302 request.setHTTPOrigin(securityOrigin->toAtomicString());
279 // If the user didn't request credentials in the first place, update our 303 // If the user didn't request credentials in the first place, update our
280 // state so we neither request them nor expect they must be allowed. 304 // state so we neither request them nor expect they must be allowed.
281 if (options.credentialsRequested == ClientDidNotRequestCredentials) 305 if (options.credentialsRequested == ClientDidNotRequestCredentials)
282 options.allowCredentials = DoNotAllowStoredCredentials; 306 options.allowCredentials = DoNotAllowStoredCredentials;
283 } 307 }
284 return true; 308 return true;
285 } 309 }
286 310
311 bool CrossOriginAccessControl::isSimpleMethod(const String& method)
312 {
313 // "A simple method is a method that is `GET`, `HEAD`, or `POST`."
sof 2014/07/17 08:18:09 Anchor this with a spec href?
yhirano 2014/08/06 08:48:02 Done.
314 return method == "GET" || method == "HEAD" || method == "POST";
315 }
316
317 bool CrossOriginAccessControl::isSimpleHeader(const AtomicString& name, const At omicString& value)
318 {
319 // "A simple header is a header whose name is either one of `Accept`,
sof 2014/07/17 08:18:09 This is also something with a settled spec referen
yhirano 2014/08/06 08:48:03 Done.
320 // `Accept-Language`, and `Content-Language`, or whose name is
321 // `Content-Type` and value, once parsed, is one of
322 // `application/x-www-form-urlencoded`, `multipart/form-data`, and
323 // `text/plain`."
324
325 if (equalIgnoringCase(name, "accept")
326 || equalIgnoringCase(name, "accept-language")
327 || equalIgnoringCase(name, "content-language"))
328 return true;
329
330 // Preflight is required for MIME types that can not be sent via form submis sion.
331 if (equalIgnoringCase(name, "content-type")) {
332 AtomicString mimeType = extractMIMETypeFromMediaType(value);
333 return equalIgnoringCase(mimeType, "application/x-www-form-urlencoded")
334 || equalIgnoringCase(mimeType, "multipart/form-data")
335 || equalIgnoringCase(mimeType, "text/plain");
336 }
337
338 return false;
339 }
340
341 bool CrossOriginAccessControl::isSimpleRequest(const String& method, const HTTPH eaderMap& headerMap)
342 {
343 if (!isSimpleMethod(method))
344 return false;
345
346 HTTPHeaderMap::const_iterator end = headerMap.end();
347 for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) {
348 if (!isSimpleHeader(it->key, it->value))
349 return false;
350 }
351
352 return true;
353 }
354
355 bool CrossOriginAccessControl::isForbiddenMethod(const String& method)
356 {
357 // "A forbidden method is a method that is a byte case-insensitive match"
sof 2014/07/17 08:18:09 I think it is a good idea to share definitions lik
yhirano 2014/08/06 08:48:02 I didn't come up with a great name, but moved thes
sof 2014/08/06 19:48:15 Yes, "Utils" classes can grow to become a disparat
358 // for one of `CONNECT`, `TRACE`, and `TRACK`."
359 return equalIgnoringCase(method, "TRACE")
360 || equalIgnoringCase(method, "TRACK")
361 || equalIgnoringCase(method, "CONNECT");
362 }
363
364 bool CrossOriginAccessControl::isForbiddenHeaderName(const String& name)
365 {
366 // "A forbidden header name is a header names that is one of:
367 // `Accept-Charset`, `Accept-Encoding`, `Access-Control-Request-Headers`,
368 // `Access-Control-Request-Method`, `Connection`,
369 // `Content-Length, Cookie`, `Cookie2`, `Date`, `DNT`, `Expect`, `Host`,
370 // `Keep-Alive`, `Origin`, `Referer`, `TE`, `Trailer`,
371 // `Transfer-Encoding`, `Upgrade`, `User-Agent`, `Via`
372 // or starts with `Proxy-` or `Sec-` (including when it is just `Proxy-` or
373 // `Sec-`)."
374
375 initializeForbiddenHeaderNames();
376 return forbiddenHeaderNames->has(name);
377 }
378
379 bool CrossOriginAccessControl::isForbiddenResponseHeaderName(const String& name)
380 {
381 // "A forbidden response header name is a header name that is one of:
382 // `Set-Cookie`, `Set-Cookie2`"
383
384 return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set -cookie2");
385 }
386
387 bool CrossOriginAccessControl::isSimpleOrForbiddenRequest(const String& method, const HTTPHeaderMap& headerMap)
388 {
389 if (!isSimpleMethod(method))
390 return false;
391
392 HTTPHeaderMap::const_iterator end = headerMap.end();
393 for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) {
394 if (!isSimpleHeader(it->key, it->value) && !isForbiddenHeaderName(it->ke y))
395 return false;
396 }
397
398 return true;
399 }
400
287 } // namespace WebCore 401 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698