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

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

Issue 2389643002: Reflow comments in core/fetch (Closed)
Patch Set: yoavs comments Created 4 years, 2 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 preflightRequest.setRequestContext(request.requestContext()); 76 preflightRequest.setRequestContext(request.requestContext());
77 preflightRequest.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All); 77 preflightRequest.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All);
78 78
79 if (request.isExternalRequest()) 79 if (request.isExternalRequest())
80 preflightRequest.setHTTPHeaderField( 80 preflightRequest.setHTTPHeaderField(
81 HTTPNames::Access_Control_Request_External, "true"); 81 HTTPNames::Access_Control_Request_External, "true");
82 82
83 const HTTPHeaderMap& requestHeaderFields = request.httpHeaderFields(); 83 const HTTPHeaderMap& requestHeaderFields = request.httpHeaderFields();
84 84
85 if (requestHeaderFields.size() > 0) { 85 if (requestHeaderFields.size() > 0) {
86 // Fetch API Spec: 86 // Fetch API Spec: https://fetch.spec.whatwg.org/#cors-preflight-fetch-0
87 // https://fetch.spec.whatwg.org/#cors-preflight-fetch-0
88 Vector<String> headers; 87 Vector<String> headers;
89 for (const auto& header : requestHeaderFields) { 88 for (const auto& header : requestHeaderFields) {
90 if (FetchUtils::isSimpleHeader(header.key, header.value)) { 89 if (FetchUtils::isSimpleHeader(header.key, header.value)) {
91 // Exclude simple headers. 90 // Exclude simple headers.
92 continue; 91 continue;
93 } 92 }
94 if (equalIgnoringCase(header.key, "referer")) { 93 if (equalIgnoringCase(header.key, "referer")) {
95 // When the request is from a Worker, referrer header was added 94 // When the request is from a Worker, referrer header was added by
96 // by WorkerThreadableLoader. But it should not be added to 95 // WorkerThreadableLoader. But it should not be added to
97 // Access-Control-Request-Headers header. 96 // Access-Control-Request-Headers header.
98 continue; 97 continue;
99 } 98 }
100 headers.append(header.key.lower()); 99 headers.append(header.key.lower());
101 } 100 }
102 // Sort header names lexicographically. 101 // Sort header names lexicographically.
103 std::sort(headers.begin(), headers.end(), WTF::codePointCompareLessThan); 102 std::sort(headers.begin(), headers.end(), WTF::codePointCompareLessThan);
104 StringBuilder headerBuffer; 103 StringBuilder headerBuffer;
105 for (const String& header : headers) { 104 for (const String& header : headers) {
106 if (!headerBuffer.isEmpty()) 105 if (!headerBuffer.isEmpty())
107 headerBuffer.append(", "); 106 headerBuffer.append(", ");
108 headerBuffer.append(header); 107 headerBuffer.append(header);
109 } 108 }
110 preflightRequest.setHTTPHeaderField( 109 preflightRequest.setHTTPHeaderField(
111 HTTPNames::Access_Control_Request_Headers, 110 HTTPNames::Access_Control_Request_Headers,
112 AtomicString(headerBuffer.toString())); 111 AtomicString(headerBuffer.toString()));
113 } 112 }
114 113
115 return preflightRequest; 114 return preflightRequest;
116 } 115 }
117 116
118 static bool isOriginSeparator(UChar ch) { 117 static bool isOriginSeparator(UChar ch) {
119 return isASCIISpace(ch) || ch == ','; 118 return isASCIISpace(ch) || ch == ',';
120 } 119 }
121 120
122 static bool isInterestingStatusCode(int statusCode) { 121 static bool isInterestingStatusCode(int statusCode) {
123 // Predicate that gates what status codes should be included in 122 // Predicate that gates what status codes should be included in console error
124 // console error messages for responses containing no access 123 // messages for responses containing no access control headers.
125 // control headers.
126 return statusCode >= 400; 124 return statusCode >= 400;
127 } 125 }
128 126
129 static String buildAccessControlFailureMessage( 127 static String buildAccessControlFailureMessage(
130 const String& detail, 128 const String& detail,
131 const SecurityOrigin* securityOrigin) { 129 const SecurityOrigin* securityOrigin) {
132 return detail + " Origin '" + securityOrigin->toString() + 130 return detail + " Origin '" + securityOrigin->toString() +
133 "' is therefore not allowed access."; 131 "' is therefore not allowed access.";
134 } 132 }
135 133
(...skipping 19 matching lines...) Expand all
155 153
156 if (!statusCode) { 154 if (!statusCode) {
157 errorDescription = 155 errorDescription =
158 buildAccessControlFailureMessage("Invalid response.", securityOrigin); 156 buildAccessControlFailureMessage("Invalid response.", securityOrigin);
159 return false; 157 return false;
160 } 158 }
161 159
162 const AtomicString& allowOriginHeaderValue = 160 const AtomicString& allowOriginHeaderValue =
163 response.httpHeaderField(allowOriginHeaderName); 161 response.httpHeaderField(allowOriginHeaderName);
164 162
165 // Check Suborigins, unless the Access-Control-Allow-Origin is '*', 163 // Check Suborigins, unless the Access-Control-Allow-Origin is '*', which
166 // which implies that all Suborigins are okay as well. 164 // implies that all Suborigins are okay as well.
167 if (securityOrigin->hasSuborigin() && allowOriginHeaderValue != starAtom) { 165 if (securityOrigin->hasSuborigin() && allowOriginHeaderValue != starAtom) {
168 const AtomicString& allowSuboriginHeaderValue = 166 const AtomicString& allowSuboriginHeaderValue =
169 response.httpHeaderField(allowSuboriginHeaderName); 167 response.httpHeaderField(allowSuboriginHeaderName);
170 AtomicString atomicSuboriginName(securityOrigin->suborigin()->name()); 168 AtomicString atomicSuboriginName(securityOrigin->suborigin()->name());
171 if (allowSuboriginHeaderValue != starAtom && 169 if (allowSuboriginHeaderValue != starAtom &&
172 allowSuboriginHeaderValue != atomicSuboriginName) { 170 allowSuboriginHeaderValue != atomicSuboriginName) {
173 errorDescription = buildAccessControlFailureMessage( 171 errorDescription = buildAccessControlFailureMessage(
174 "The 'Access-Control-Allow-Suborigin' header has a value '" + 172 "The 'Access-Control-Allow-Suborigin' header has a value '" +
175 allowSuboriginHeaderValue + 173 allowSuboriginHeaderValue +
176 "' that is not equal to the supplied suborigin.", 174 "' that is not equal to the supplied suborigin.",
177 securityOrigin); 175 securityOrigin);
178 return false; 176 return false;
179 } 177 }
180 } 178 }
181 179
182 if (allowOriginHeaderValue == starAtom) { 180 if (allowOriginHeaderValue == starAtom) {
183 // A wildcard Access-Control-Allow-Origin can not be used if credentials are to be sent, 181 // A wildcard Access-Control-Allow-Origin can not be used if credentials are
184 // even with Access-Control-Allow-Credentials set to true. 182 // to be sent, even with Access-Control-Allow-Credentials set to true.
185 if (includeCredentials == DoNotAllowStoredCredentials) 183 if (includeCredentials == DoNotAllowStoredCredentials)
186 return true; 184 return true;
187 if (response.isHTTP()) { 185 if (response.isHTTP()) {
188 errorDescription = buildAccessControlFailureMessage( 186 errorDescription = buildAccessControlFailureMessage(
189 "A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' " 187 "A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' "
190 "header when the credentials flag is true.", 188 "header when the credentials flag is true.",
191 securityOrigin); 189 securityOrigin);
192 190
193 if (context == WebURLRequest::RequestContextXMLHttpRequest) 191 if (context == WebURLRequest::RequestContextXMLHttpRequest)
194 errorDescription.append( 192 errorDescription.append(
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 return false; 257 return false;
260 } 258 }
261 } 259 }
262 260
263 return true; 261 return true;
264 } 262 }
265 263
266 bool passesPreflightStatusCheck(const ResourceResponse& response, 264 bool passesPreflightStatusCheck(const ResourceResponse& response,
267 String& errorDescription) { 265 String& errorDescription) {
268 // CORS preflight with 3XX is considered network error in 266 // CORS preflight with 3XX is considered network error in
269 // Fetch API Spec: 267 // Fetch API Spec: https://fetch.spec.whatwg.org/#cors-preflight-fetch
270 // https://fetch.spec.whatwg.org/#cors-preflight-fetch 268 // CORS Spec: http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0
271 // CORS Spec:
272 // http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0
273 // https://crbug.com/452394 269 // https://crbug.com/452394
274 if (response.httpStatusCode() < 200 || response.httpStatusCode() >= 300) { 270 if (response.httpStatusCode() < 200 || response.httpStatusCode() >= 300) {
275 errorDescription = "Response for preflight has invalid HTTP status code " + 271 errorDescription = "Response for preflight has invalid HTTP status code " +
276 String::number(response.httpStatusCode()); 272 String::number(response.httpStatusCode());
277 return false; 273 return false;
278 } 274 }
279 275
280 return true; 276 return true;
281 } 277 }
282 278
(...skipping 29 matching lines...) Expand all
312 String strippedHeader = headers[headerCount].stripWhiteSpace(); 308 String strippedHeader = headers[headerCount].stripWhiteSpace();
313 if (!strippedHeader.isEmpty()) 309 if (!strippedHeader.isEmpty())
314 headerSet.add(strippedHeader); 310 headerSet.add(strippedHeader);
315 } 311 }
316 } 312 }
317 313
318 void extractCorsExposedHeaderNamesList(const ResourceResponse& response, 314 void extractCorsExposedHeaderNamesList(const ResourceResponse& response,
319 HTTPHeaderSet& headerSet) { 315 HTTPHeaderSet& headerSet) {
320 // If a response was fetched via a service worker, it will always have 316 // If a response was fetched via a service worker, it will always have
321 // corsExposedHeaderNames set, either from the Access-Control-Expose-Headers 317 // corsExposedHeaderNames set, either from the Access-Control-Expose-Headers
322 // header, or explicitly via foreign fetch. For requests that didn't come 318 // header, or explicitly via foreign fetch. For requests that didn't come from
323 // from a service worker, foreign fetch doesn't apply so just parse the CORS 319 // a service worker, foreign fetch doesn't apply so just parse the CORS
324 // header. 320 // header.
325 if (response.wasFetchedViaServiceWorker()) { 321 if (response.wasFetchedViaServiceWorker()) {
326 for (const auto& header : response.corsExposedHeaderNames()) 322 for (const auto& header : response.corsExposedHeaderNames())
327 headerSet.add(header); 323 headerSet.add(header);
328 return; 324 return;
329 } 325 }
330 parseAccessControlExposeHeadersAllowList( 326 parseAccessControlExposeHeadersAllowList(
331 response.httpHeaderField(HTTPNames::Access_Control_Expose_Headers), 327 response.httpHeaderField(HTTPNames::Access_Control_Expose_Headers),
332 headerSet); 328 headerSet);
333 } 329 }
334 330
335 bool CrossOriginAccessControl::isLegalRedirectLocation( 331 bool CrossOriginAccessControl::isLegalRedirectLocation(
336 const KURL& requestURL, 332 const KURL& requestURL,
337 String& errorDescription) { 333 String& errorDescription) {
338 // Block non HTTP(S) schemes as specified in the step 4 in 334 // Block non HTTP(S) schemes as specified in the step 4 in
339 // https://fetch.spec.whatwg.org/#http-redirect-fetch. Chromium also allows 335 // https://fetch.spec.whatwg.org/#http-redirect-fetch. Chromium also allows
340 // the data scheme. 336 // the data scheme.
341 // 337 //
342 // TODO(tyoshino): This check should be performed regardless of the CORS 338 // TODO(tyoshino): This check should be performed regardless of the CORS flag
343 // flag and request's mode. 339 // and request's mode.
344 if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled( 340 if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(
345 requestURL.protocol())) { 341 requestURL.protocol())) {
346 errorDescription = "Redirect location '" + requestURL.getString() + 342 errorDescription = "Redirect location '" + requestURL.getString() +
347 "' has a disallowed scheme for cross-origin requests."; 343 "' has a disallowed scheme for cross-origin requests.";
348 return false; 344 return false;
349 } 345 }
350 346
351 // Block URLs including credentials as specified in the step 9 in 347 // Block URLs including credentials as specified in the step 9 in
352 // https://fetch.spec.whatwg.org/#http-redirect-fetch. 348 // https://fetch.spec.whatwg.org/#http-redirect-fetch.
353 // 349 //
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 if (!lastOrigin->canRequest(newURL)) { 401 if (!lastOrigin->canRequest(newURL)) {
406 options.securityOrigin = SecurityOrigin::createUnique(); 402 options.securityOrigin = SecurityOrigin::createUnique();
407 newSecurityOrigin = options.securityOrigin; 403 newSecurityOrigin = options.securityOrigin;
408 } 404 }
409 } 405 }
410 406
411 if (!currentSecurityOrigin->canRequest(newURL)) { 407 if (!currentSecurityOrigin->canRequest(newURL)) {
412 newRequest.clearHTTPOrigin(); 408 newRequest.clearHTTPOrigin();
413 newRequest.setHTTPOrigin(newSecurityOrigin.get()); 409 newRequest.setHTTPOrigin(newSecurityOrigin.get());
414 410
415 // Unset credentials flag if request's credentials mode is 411 // Unset credentials flag if request's credentials mode is "same-origin" as
416 // "same-origin" as request's response tainting becomes "cors". 412 // request's response tainting becomes "cors".
417 // 413 //
418 // This is equivalent to the step 2 in 414 // This is equivalent to the step 2 in
419 // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch 415 // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
420 if (options.credentialsRequested == ClientDidNotRequestCredentials) 416 if (options.credentialsRequested == ClientDidNotRequestCredentials)
421 options.allowCredentials = DoNotAllowStoredCredentials; 417 options.allowCredentials = DoNotAllowStoredCredentials;
422 } 418 }
423 return true; 419 return true;
424 } 420 }
425 421
426 } // namespace blink 422 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698