Commit 84612910 authored by morrita@chromium.org's avatar morrita@chromium.org

HTML Imports: Send credentials for same origin requests

This captures following spec chagne: https://www.w3.org/Bugs/Public/show_bug.cgi?id=24905
The essential part of the change is in HTMLImportsController.cpp.
Anything else is to make it work with redirect.

The problem here is that allowCredentials flag is held both
by ResourceLoaderOptions and ResourceRequest and these two
can go out-of-sync. This change tries to make them in sync.

Such a state duplication should be resolved eventually, but
that is another story.

BUG=348671
TEST=import-cors-credentials.html
R=dglazkov@chromium.org, japhet@chromium.org, abarth

Committed: https://src.chromium.org/viewvc/blink?view=rev&revision=169496

Review URL: https://codereview.chromium.org/196043002

git-svn-id: svn://svn.chromium.org/blink/trunk@169578 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 02f76492
PASS sameOrigin.import.body.innerHTML is "PASS"
PASS crossOrigin.import.body.innerHTML is "PASS"
PASS fromSameToCrossOrigin.import.getElementById('crossOrigin').import.body.innerHTML is "PASS"
PASS fromCrossToSameOrigin.import.getElementById('sameOrigin').import.body.innerHTML is "PASS"
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<script src="/js-test-resources/js-test.js"></script>
<script>
document.cookie = "key=HelloCredentials";
</script>
<link id="sameOrigin" rel="import" href="resources/cookie-match.cgi?key=HelloCredentials">
<link id="crossOrigin" rel="import" href="http://localhost:8080/htmlimports/resources/cookie-match.cgi">
<link id="fromSameToCrossOrigin" rel="import" href="resources/having-cookie-match-8080.html">
<link id="fromCrossToSameOrigin" rel="import" href="http://localhost:8080/htmlimports/resources/having-cookie-match-same.cgi">
<script>
if (window.testRunner)
testRunner.dumpAsText();
shouldBeEqualToString("sameOrigin.import.body.innerHTML", "PASS");
shouldBeEqualToString("crossOrigin.import.body.innerHTML", "PASS");
shouldBeEqualToString("fromSameToCrossOrigin.import.getElementById('crossOrigin').import.body.innerHTML", "PASS");
shouldBeEqualToString("fromCrossToSameOrigin.import.getElementById('sameOrigin').import.body.innerHTML", "PASS");
</script>
#!/usr/bin/perl -wT
use strict;
my $query = $ENV{"QUERY_STRING"};
my $cookie = $ENV{"HTTP_COOKIE"};
$query =~ s/\?//g; # Squash "?" that is added to prevent dedup.
print "Content-Type: text/html\n";
print "Access-Control-Allow-Credentials: true\n";
print "Access-Control-Allow-Origin: *\n";
print "\n";
if ($query eq $cookie) {
print "<body>PASS</body>"
} else {
print "<body>FAIL: Cookie:" . $cookie .", Query:" . $query . "</body>";
}
<!DOCTYPE html>
<!-- Put ? at the end of the URL to prevent de-deup -->
<link id="crossOrigin" rel="import" href="http://localhost:8080/htmlimports/resources/cookie-match.cgi?">
#!/usr/bin/perl -wT
use strict;
print "Content-Type: text/html\n";
print "Access-Control-Allow-Credentials: true\n";
print "Access-Control-Allow-Origin: *\n";
print "\n";
print <<EOF
<!DOCTYPE html>
<!-- Put an extra "?" in the URL to prevent de-deup -->
<link id="sameOrigin" rel="import" href="http://127.0.0.1:8000/htmlimports/resources/cookie-match.cgi?key=HelloCredentials?">
EOF
...@@ -106,7 +106,7 @@ StyleFetchedImageSet* CSSImageSetValue::cachedImageSet(ResourceFetcher* loader, ...@@ -106,7 +106,7 @@ StyleFetchedImageSet* CSSImageSetValue::cachedImageSet(ResourceFetcher* loader,
FetchRequest request(ResourceRequest(document->completeURL(image.imageURL)), FetchInitiatorTypeNames::css, options); FetchRequest request(ResourceRequest(document->completeURL(image.imageURL)), FetchInitiatorTypeNames::css, options);
if (options.corsEnabled == IsCORSEnabled) if (options.corsEnabled == IsCORSEnabled)
request.setCrossOriginAccessControl(loader->document()->securityOrigin(), options.allowCredentials); request.setCrossOriginAccessControl(loader->document()->securityOrigin(), options.allowCredentials, options.credentialsRequested);
if (ResourcePtr<ImageResource> cachedImage = loader->fetchImage(request)) { if (ResourcePtr<ImageResource> cachedImage = loader->fetchImage(request)) {
m_imageSet = StyleFetchedImageSet::create(cachedImage.get(), image.scaleFactor, this); m_imageSet = StyleFetchedImageSet::create(cachedImage.get(), image.scaleFactor, this);
......
...@@ -242,7 +242,7 @@ bool CrossOriginAccessControl::handleRedirect(Resource* resource, SecurityOrigin ...@@ -242,7 +242,7 @@ bool CrossOriginAccessControl::handleRedirect(Resource* resource, SecurityOrigin
bool allowRedirect = isLegalRedirectLocation(requestURL, errorDescription); bool allowRedirect = isLegalRedirectLocation(requestURL, errorDescription);
if (allowRedirect) { if (allowRedirect) {
// Step 5: perform resource sharing access check. // Step 5: perform resource sharing access check.
StoredCredentials withCredentials = resource->resourceRequest().allowStoredCredentials() ? AllowStoredCredentials : DoNotAllowStoredCredentials; StoredCredentials withCredentials = resource->lastResourceRequest().allowStoredCredentials() ? AllowStoredCredentials : DoNotAllowStoredCredentials;
allowRedirect = passesAccessControlCheck(redirectResponse, withCredentials, securityOrigin, errorDescription); allowRedirect = passesAccessControlCheck(redirectResponse, withCredentials, securityOrigin, errorDescription);
if (allowRedirect) { if (allowRedirect) {
RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(originalURL); RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(originalURL);
......
...@@ -69,11 +69,18 @@ FetchRequest::~FetchRequest() ...@@ -69,11 +69,18 @@ FetchRequest::~FetchRequest()
{ {
} }
void FetchRequest::setCrossOriginAccessControl(SecurityOrigin* origin, StoredCredentials allowCredentials) void FetchRequest::setCrossOriginAccessControl(SecurityOrigin* origin, StoredCredentials allowCredentials, CredentialRequest requested)
{ {
ASSERT(requested == ClientDidNotRequestCredentials || allowCredentials == AllowStoredCredentials);
updateRequestForAccessControl(m_resourceRequest, origin, allowCredentials); updateRequestForAccessControl(m_resourceRequest, origin, allowCredentials);
m_options.corsEnabled = IsCORSEnabled; m_options.corsEnabled = IsCORSEnabled;
m_options.securityOrigin = origin; m_options.securityOrigin = origin;
m_options.credentialsRequested = requested;
}
void FetchRequest::setCrossOriginAccessControl(SecurityOrigin* origin, StoredCredentials allowCredentials)
{
setCrossOriginAccessControl(origin, allowCredentials, allowCredentials == AllowStoredCredentials ? ClientRequestedCredentials : ClientDidNotRequestCredentials);
} }
void FetchRequest::setCrossOriginAccessControl(SecurityOrigin* origin, const AtomicString& crossOriginMode) void FetchRequest::setCrossOriginAccessControl(SecurityOrigin* origin, const AtomicString& crossOriginMode)
......
...@@ -59,6 +59,7 @@ public: ...@@ -59,6 +59,7 @@ public:
DeferOption defer() const { return m_defer; } DeferOption defer() const { return m_defer; }
void setDefer(DeferOption defer) { m_defer = defer; } void setDefer(DeferOption defer) { m_defer = defer; }
void setContentSecurityCheck(ContentSecurityPolicyCheck contentSecurityPolicyOption) { m_options.contentSecurityPolicyOption = contentSecurityPolicyOption; } void setContentSecurityCheck(ContentSecurityPolicyCheck contentSecurityPolicyOption) { m_options.contentSecurityPolicyOption = contentSecurityPolicyOption; }
void setCrossOriginAccessControl(SecurityOrigin*, StoredCredentials, CredentialRequest);
void setCrossOriginAccessControl(SecurityOrigin*, StoredCredentials); void setCrossOriginAccessControl(SecurityOrigin*, StoredCredentials);
void setCrossOriginAccessControl(SecurityOrigin*, const AtomicString& crossOriginMode); void setCrossOriginAccessControl(SecurityOrigin*, const AtomicString& crossOriginMode);
OriginRestriction originRestriction() const { return m_originRestriction; } OriginRestriction originRestriction() const { return m_originRestriction; }
......
...@@ -336,6 +336,13 @@ static bool canUseResponse(const ResourceResponse& response, double responseTime ...@@ -336,6 +336,13 @@ static bool canUseResponse(const ResourceResponse& response, double responseTime
return currentAge(response, responseTimestamp) <= freshnessLifetime(response, responseTimestamp); return currentAge(response, responseTimestamp) <= freshnessLifetime(response, responseTimestamp);
} }
const ResourceRequest& Resource::lastResourceRequest()
{
if (!m_redirectChain.size())
return m_resourceRequest;
return m_redirectChain.last().m_request;
}
void Resource::willSendRequest(ResourceRequest& request, const ResourceResponse& response) void Resource::willSendRequest(ResourceRequest& request, const ResourceResponse& response)
{ {
m_redirectChain.append(RedirectPair(request, response)); m_redirectChain.append(RedirectPair(request, response));
......
...@@ -108,6 +108,7 @@ public: ...@@ -108,6 +108,7 @@ public:
virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return false; } virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return false; }
ResourceRequest& resourceRequest() { return m_resourceRequest; } ResourceRequest& resourceRequest() { return m_resourceRequest; }
const ResourceRequest& lastResourceRequest();
const KURL& url() const { return m_resourceRequest.url();} const KURL& url() const { return m_resourceRequest.url();}
Type type() const { return static_cast<Type>(m_type); } Type type() const { return static_cast<Type>(m_type); }
const ResourceLoaderOptions& options() const { return m_options; } const ResourceLoaderOptions& options() const { return m_options; }
......
...@@ -121,7 +121,7 @@ void ResourceLoader::init(const ResourceRequest& passedRequest) ...@@ -121,7 +121,7 @@ void ResourceLoader::init(const ResourceRequest& passedRequest)
request.setReportLoadTiming(true); request.setReportLoadTiming(true);
ASSERT(m_state != Terminated); ASSERT(m_state != Terminated);
ASSERT(!request.isNull()); ASSERT(!request.isNull());
m_originalRequest = m_request = request; m_originalRequest = m_request = applyOptions(request);
m_resource->updateRequest(request); m_resource->updateRequest(request);
m_host->didInitializeResourceLoader(this); m_host->didInitializeResourceLoader(this);
} }
...@@ -153,7 +153,6 @@ void ResourceLoader::start() ...@@ -153,7 +153,6 @@ void ResourceLoader::start()
m_loader = adoptPtr(blink::Platform::current()->createURLLoader()); m_loader = adoptPtr(blink::Platform::current()->createURLLoader());
ASSERT(m_loader); ASSERT(m_loader);
blink::WrappedResourceRequest wrappedRequest(m_request); blink::WrappedResourceRequest wrappedRequest(m_request);
wrappedRequest.setAllowStoredCredentials(m_options.allowCredentials == AllowStoredCredentials);
m_loader->loadAsynchronously(wrappedRequest, this); m_loader->loadAsynchronously(wrappedRequest, this);
} }
...@@ -174,7 +173,7 @@ void ResourceLoader::setDefersLoading(bool defers) ...@@ -174,7 +173,7 @@ void ResourceLoader::setDefersLoading(bool defers)
if (m_loader) if (m_loader)
m_loader->setDefersLoading(defers); m_loader->setDefersLoading(defers);
if (!defers && !m_deferredRequest.isNull()) { if (!defers && !m_deferredRequest.isNull()) {
m_request = m_deferredRequest; m_request = applyOptions(m_deferredRequest);
m_deferredRequest = ResourceRequest(); m_deferredRequest = ResourceRequest();
start(); start();
} }
...@@ -263,7 +262,7 @@ void ResourceLoader::willSendRequest(blink::WebURLLoader*, blink::WebURLRequest& ...@@ -263,7 +262,7 @@ void ResourceLoader::willSendRequest(blink::WebURLLoader*, blink::WebURLRequest&
{ {
RefPtr<ResourceLoader> protect(this); RefPtr<ResourceLoader> protect(this);
ResourceRequest& request(passedRequest.toMutableResourceRequest()); ResourceRequest& request(applyOptions(passedRequest.toMutableResourceRequest()));
ASSERT(!request.isNull()); ASSERT(!request.isNull());
const ResourceResponse& redirectResponse(passedRedirectResponse.toResourceResponse()); const ResourceResponse& redirectResponse(passedRedirectResponse.toResourceResponse());
ASSERT(!redirectResponse.isNull()); ASSERT(!redirectResponse.isNull());
...@@ -272,6 +271,7 @@ void ResourceLoader::willSendRequest(blink::WebURLLoader*, blink::WebURLRequest& ...@@ -272,6 +271,7 @@ void ResourceLoader::willSendRequest(blink::WebURLLoader*, blink::WebURLRequest&
return; return;
} }
applyOptions(request); // canAccessRedirect() can modify m_options so we should re-apply it.
m_host->redirectReceived(m_resource, redirectResponse); m_host->redirectReceived(m_resource, redirectResponse);
m_resource->willSendRequest(request, redirectResponse); m_resource->willSendRequest(request, redirectResponse);
if (request.isNull() || m_state == Terminated) if (request.isNull() || m_state == Terminated)
...@@ -456,7 +456,6 @@ void ResourceLoader::requestSynchronously() ...@@ -456,7 +456,6 @@ void ResourceLoader::requestSynchronously()
m_connectionState = ConnectionStateStarted; m_connectionState = ConnectionStateStarted;
blink::WrappedResourceRequest requestIn(m_request); blink::WrappedResourceRequest requestIn(m_request);
requestIn.setAllowStoredCredentials(m_options.allowCredentials == AllowStoredCredentials);
blink::WebURLResponse responseOut; blink::WebURLResponse responseOut;
responseOut.initialize(); responseOut.initialize();
blink::WebURLError errorOut; blink::WebURLError errorOut;
...@@ -476,4 +475,10 @@ void ResourceLoader::requestSynchronously() ...@@ -476,4 +475,10 @@ void ResourceLoader::requestSynchronously()
didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength); didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength);
} }
ResourceRequest& ResourceLoader::applyOptions(ResourceRequest& request) const
{
request.setAllowStoredCredentials(m_options.allowCredentials == AllowStoredCredentials);
return request;
}
} }
...@@ -93,6 +93,8 @@ private: ...@@ -93,6 +93,8 @@ private:
bool responseNeedsAccessControlCheck() const; bool responseNeedsAccessControlCheck() const;
ResourceRequest& applyOptions(ResourceRequest&) const;
OwnPtr<blink::WebURLLoader> m_loader; OwnPtr<blink::WebURLLoader> m_loader;
RefPtr<ResourceLoaderHost> m_host; RefPtr<ResourceLoaderHost> m_host;
......
...@@ -692,10 +692,8 @@ void LinkStyle::process() ...@@ -692,10 +692,8 @@ void LinkStyle::process()
// Load stylesheets that are not needed for the rendering immediately with low priority. // Load stylesheets that are not needed for the rendering immediately with low priority.
FetchRequest request = builder.build(blocking); FetchRequest request = builder.build(blocking);
AtomicString crossOriginMode = m_owner->fastGetAttribute(HTMLNames::crossoriginAttr); AtomicString crossOriginMode = m_owner->fastGetAttribute(HTMLNames::crossoriginAttr);
if (!crossOriginMode.isNull()) { if (!crossOriginMode.isNull())
StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; request.setCrossOriginAccessControl(document().securityOrigin(), crossOriginMode);
request.setCrossOriginAccessControl(document().securityOrigin(), allowCredentials);
}
setResource(document().fetcher()->fetchCSSStyleSheet(request)); setResource(document().fetcher()->fetchCSSStyleSheet(request));
if (!resource()) { if (!resource()) {
......
...@@ -87,7 +87,10 @@ HTMLImportChild* HTMLImportsController::load(HTMLImport* parent, HTMLImportChild ...@@ -87,7 +87,10 @@ HTMLImportChild* HTMLImportsController::load(HTMLImport* parent, HTMLImportChild
return child; return child;
} }
request.setCrossOriginAccessControl(securityOrigin(), DoNotAllowStoredCredentials); bool sameOriginRequest = securityOrigin()->canRequest(request.url());
request.setCrossOriginAccessControl(
securityOrigin(), sameOriginRequest ? AllowStoredCredentials : DoNotAllowStoredCredentials,
ClientDidNotRequestCredentials);
ResourcePtr<RawResource> resource = parent->document()->fetcher()->fetchImport(request); ResourcePtr<RawResource> resource = parent->document()->fetcher()->fetchImport(request);
if (!resource) if (!resource)
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment