#include "wtf/text/AtomicString.h"
#include "wtf/text/StringBuilder.h"
-namespace WebCore {
-
-bool isOnAccessControlSimpleRequestMethodWhitelist(const String& method)
-{
- return method == "GET" || method == "HEAD" || method == "POST";
-}
-
-bool isOnAccessControlSimpleRequestHeaderWhitelist(const AtomicString& name, const AtomicString& value)
-{
- if (equalIgnoringCase(name, "accept")
- || equalIgnoringCase(name, "accept-language")
- || equalIgnoringCase(name, "content-language")
- || equalIgnoringCase(name, "origin")
- || equalIgnoringCase(name, "referer"))
- return true;
-
- // Preflight is required for MIME types that can not be sent via form submission.
- if (equalIgnoringCase(name, "content-type")) {
- AtomicString mimeType = extractMIMETypeFromMediaType(value);
- return equalIgnoringCase(mimeType, "application/x-www-form-urlencoded")
- || equalIgnoringCase(mimeType, "multipart/form-data")
- || equalIgnoringCase(mimeType, "text/plain");
- }
-
- return false;
-}
-
-bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap& headerMap)
-{
- if (!isOnAccessControlSimpleRequestMethodWhitelist(method))
- return false;
-
- HTTPHeaderMap::const_iterator end = headerMap.end();
- for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) {
- if (!isOnAccessControlSimpleRequestHeaderWhitelist(it->key, it->value))
- return false;
- }
-
- return true;
-}
+namespace blink {
static PassOwnPtr<HTTPHeaderSet> createAllowedCrossOriginResponseHeadersSet()
{
void updateRequestForAccessControl(ResourceRequest& request, SecurityOrigin* securityOrigin, StoredCredentials allowCredentials)
{
request.removeCredentials();
- request.setAllowCookies(allowCredentials == AllowStoredCredentials);
+ request.setAllowStoredCredentials(allowCredentials == AllowStoredCredentials);
+ request.setFetchCredentialsMode(allowCredentials == AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRequest::FetchCredentialsModeOmit);
if (securityOrigin)
request.setHTTPOrigin(securityOrigin->toAtomicString());
preflightRequest.setHTTPMethod("OPTIONS");
preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", request.httpMethod());
preflightRequest.setPriority(request.priority());
+ preflightRequest.setRequestContext(request.requestContext());
const HTTPHeaderMap& requestHeaderFields = request.httpHeaderFields();
return isASCIISpace(ch) || ch == ',';
}
+static bool isInterestingStatusCode(int statusCode)
+{
+ // Predicate that gates what status codes should be included in
+ // console error messages for responses containing no access
+ // control headers.
+ return statusCode >= 400;
+}
+
bool passesAccessControlCheck(const ResourceResponse& response, StoredCredentials includeCredentials, SecurityOrigin* securityOrigin, String& errorDescription)
{
AtomicallyInitializedStatic(AtomicString&, accessControlAllowOrigin = *new AtomicString("access-control-allow-origin", AtomicString::ConstructFromLiteral));
return false;
}
- // A wildcard Access-Control-Allow-Origin can not be used if credentials are to be sent,
- // even with Access-Control-Allow-Credentials set to true.
const AtomicString& accessControlOriginString = response.httpHeaderField(accessControlAllowOrigin);
- if (accessControlOriginString == starAtom && includeCredentials == DoNotAllowStoredCredentials)
- return true;
-
- if (accessControlOriginString != securityOrigin->toAtomicString()) {
- if (accessControlOriginString == starAtom) {
+ if (accessControlOriginString == starAtom) {
+ // A wildcard Access-Control-Allow-Origin can not be used if credentials are to be sent,
+ // even with Access-Control-Allow-Credentials set to true.
+ if (includeCredentials == DoNotAllowStoredCredentials)
+ return true;
+ if (response.isHTTP()) {
errorDescription = "A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin '" + securityOrigin->toString() + "' is therefore not allowed access.";
- } else if (accessControlOriginString.isEmpty()) {
+ return false;
+ }
+ } else if (accessControlOriginString != securityOrigin->toAtomicString()) {
+ if (accessControlOriginString.isNull()) {
errorDescription = "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '" + securityOrigin->toString() + "' is therefore not allowed access.";
+
+ if (isInterestingStatusCode(response.httpStatusCode()))
+ errorDescription.append(" The response had HTTP status code " + String::number(response.httpStatusCode()) + ".");
} else if (accessControlOriginString.string().find(isOriginSeparator, 0) != kNotFound) {
errorDescription = "The 'Access-Control-Allow-Origin' header contains multiple values '" + accessControlOriginString + "', but only one is allowed. Origin '" + securityOrigin->toString() + "' is therefore not allowed access.";
} else {
bool allowRedirect = isLegalRedirectLocation(requestURL, errorDescription);
if (allowRedirect) {
// Step 5: perform resource sharing access check.
- StoredCredentials withCredentials = resource->resourceRequest().allowCookies() ? AllowStoredCredentials : DoNotAllowStoredCredentials;
+ StoredCredentials withCredentials = resource->lastResourceRequest().allowStoredCredentials() ? AllowStoredCredentials : DoNotAllowStoredCredentials;
allowRedirect = passesAccessControlCheck(redirectResponse, withCredentials, securityOrigin, errorDescription);
if (allowRedirect) {
RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(originalURL);
return true;
}
-} // namespace WebCore
+} // namespace blink