Commit 1ba4e442 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=abarth, dglazkov@chromium.org

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

git-svn-id: svn://svn.chromium.org/blink/trunk@169496 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 9916131e
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,
FetchRequest request(ResourceRequest(document->completeURL(image.imageURL)), FetchInitiatorTypeNames::css, options);
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)) {
m_imageSet = StyleFetchedImageSet::create(cachedImage.get(), image.scaleFactor, this);
......
......@@ -242,7 +242,7 @@ bool CrossOriginAccessControl::handleRedirect(Resource* resource, SecurityOrigin
bool allowRedirect = isLegalRedirectLocation(requestURL, errorDescription);
if (allowRedirect) {
// 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);
if (allowRedirect) {
RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(originalURL);
......
......@@ -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);
m_options.corsEnabled = IsCORSEnabled;
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)
......
......@@ -59,6 +59,7 @@ public:
DeferOption defer() const { return m_defer; }
void setDefer(DeferOption defer) { m_defer = defer; }
void setContentSecurityCheck(ContentSecurityPolicyCheck contentSecurityPolicyOption) { m_options.contentSecurityPolicyOption = contentSecurityPolicyOption; }
void setCrossOriginAccessControl(SecurityOrigin*, StoredCredentials, CredentialRequest);
void setCrossOriginAccessControl(SecurityOrigin*, StoredCredentials);
void setCrossOriginAccessControl(SecurityOrigin*, const AtomicString& crossOriginMode);
OriginRestriction originRestriction() const { return m_originRestriction; }
......
......@@ -336,6 +336,13 @@ static bool canUseResponse(const ResourceResponse& response, double responseTime
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)
{
m_redirectChain.append(RedirectPair(request, response));
......
......@@ -108,6 +108,7 @@ public:
virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return false; }
ResourceRequest& resourceRequest() { return m_resourceRequest; }
const ResourceRequest& lastResourceRequest();
const KURL& url() const { return m_resourceRequest.url();}
Type type() const { return static_cast<Type>(m_type); }
const ResourceLoaderOptions& options() const { return m_options; }
......
......@@ -121,7 +121,7 @@ void ResourceLoader::init(const ResourceRequest& passedRequest)
request.setReportLoadTiming(true);
ASSERT(m_state != Terminated);
ASSERT(!request.isNull());
m_originalRequest = m_request = request;
m_originalRequest = m_request = applyOptions(request);
m_resource->updateRequest(request);
m_host->didInitializeResourceLoader(this);
}
......@@ -153,7 +153,6 @@ void ResourceLoader::start()
m_loader = adoptPtr(blink::Platform::current()->createURLLoader());
ASSERT(m_loader);
blink::WrappedResourceRequest wrappedRequest(m_request);
wrappedRequest.setAllowStoredCredentials(m_options.allowCredentials == AllowStoredCredentials);
m_loader->loadAsynchronously(wrappedRequest, this);
}
......@@ -174,7 +173,7 @@ void ResourceLoader::setDefersLoading(bool defers)
if (m_loader)
m_loader->setDefersLoading(defers);
if (!defers && !m_deferredRequest.isNull()) {
m_request = m_deferredRequest;
m_request = applyOptions(m_deferredRequest);
m_deferredRequest = ResourceRequest();
start();
}
......@@ -263,7 +262,7 @@ void ResourceLoader::willSendRequest(blink::WebURLLoader*, blink::WebURLRequest&
{
RefPtr<ResourceLoader> protect(this);
ResourceRequest& request(passedRequest.toMutableResourceRequest());
ResourceRequest& request(applyOptions(passedRequest.toMutableResourceRequest()));
ASSERT(!request.isNull());
const ResourceResponse& redirectResponse(passedRedirectResponse.toResourceResponse());
ASSERT(!redirectResponse.isNull());
......@@ -272,6 +271,7 @@ void ResourceLoader::willSendRequest(blink::WebURLLoader*, blink::WebURLRequest&
return;
}
applyOptions(request); // canAccessRedirect() can modify m_options so we should re-apply it.
m_host->redirectReceived(m_resource, redirectResponse);
m_resource->willSendRequest(request, redirectResponse);
if (request.isNull() || m_state == Terminated)
......@@ -456,7 +456,6 @@ void ResourceLoader::requestSynchronously()
m_connectionState = ConnectionStateStarted;
blink::WrappedResourceRequest requestIn(m_request);
requestIn.setAllowStoredCredentials(m_options.allowCredentials == AllowStoredCredentials);
blink::WebURLResponse responseOut;
responseOut.initialize();
blink::WebURLError errorOut;
......@@ -476,4 +475,10 @@ void ResourceLoader::requestSynchronously()
didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength);
}
ResourceRequest& ResourceLoader::applyOptions(ResourceRequest& request) const
{
request.setAllowStoredCredentials(m_options.allowCredentials == AllowStoredCredentials);
return request;
}
}
......@@ -93,6 +93,8 @@ private:
bool responseNeedsAccessControlCheck() const;
ResourceRequest& applyOptions(ResourceRequest&) const;
OwnPtr<blink::WebURLLoader> m_loader;
RefPtr<ResourceLoaderHost> m_host;
......
......@@ -681,10 +681,8 @@ void LinkStyle::process()
// Load stylesheets that are not needed for the rendering immediately with low priority.
FetchRequest request = builder.build(blocking);
AtomicString crossOriginMode = m_owner->fastGetAttribute(HTMLNames::crossoriginAttr);
if (!crossOriginMode.isNull()) {
StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials;
request.setCrossOriginAccessControl(document().securityOrigin(), allowCredentials);
}
if (!crossOriginMode.isNull())
request.setCrossOriginAccessControl(document().securityOrigin(), crossOriginMode);
setResource(document().fetcher()->fetchCSSStyleSheet(request));
if (!resource()) {
......
......@@ -87,7 +87,10 @@ HTMLImportChild* HTMLImportsController::load(HTMLImport* parent, HTMLImportChild
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);
if (!resource)
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