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

Unified Diff: Source/modules/fetch/FetchManager.cpp

Issue 1283163003: [Fetch][WIP] Support blob:, about:, and data: URLs. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Cleanup. Created 5 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « LayoutTests/http/tests/fetch/workers/thorough/scheme-data-other-https.html ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/modules/fetch/FetchManager.cpp
diff --git a/Source/modules/fetch/FetchManager.cpp b/Source/modules/fetch/FetchManager.cpp
index e6739b2eef20b54b1537a0e9ab3f33c0c818acd8..71c21cf4fd30e3ddad8d3a8a4490f756f58af679 100644
--- a/Source/modules/fetch/FetchManager.cpp
+++ b/Source/modules/fetch/FetchManager.cpp
@@ -155,6 +155,7 @@ private:
void performBasicFetch();
void performNetworkError(const String& message);
void performHTTPFetch(bool corsFlag, bool corsPreflightFlag);
+ void performDataFetch();
void failed(const String& message);
void notifyFinished();
Document* document() const;
@@ -202,11 +203,38 @@ void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo
{
ASSERT(handle);
+ if (response.url().protocolIs("blob") && response.httpStatusCode() == 404) {
+ // "If |blob| is null, return a network error."
+ // https://fetch.spec.whatwg.org/#concept-basic-fetch
+ performNetworkError("Blob not found.");
+ return;
+ }
+
m_responseHttpStatusCode = response.httpStatusCode();
- // Recompute the tainting if the request was redirected to a different
- // origin.
- if (!SecurityOrigin::create(response.url())->isSameSchemeHostPort(m_request->origin().get())) {
+ if (response.url().protocolIsData()) {
+ if (m_request->url().protocolIsData()) {
+ // A direct request to data.
+ m_request->setResponseTainting(FetchRequestData::BasicTainting);
+ } else {
+ // A redirect to data: scheme occured.
+ switch (m_request->mode()) {
+ case WebURLRequest::FetchRequestModeSameOrigin:
+ ASSERT_NOT_REACHED();
+ break;
+ case WebURLRequest::FetchRequestModeNoCORS:
+ m_request->setResponseTainting(FetchRequestData::OpaqueTainting);
+ break;
+ case WebURLRequest::FetchRequestModeCORS:
+ case WebURLRequest::FetchRequestModeCORSWithForcedPreflight:
+ performNetworkError("Fetch API cannot load " + m_request->url().string() + ". Redirects to data: URL are allowed only when mode is \"no-cors\".");
+ return;
+ break;
+ }
+ }
+ } else if (!SecurityOrigin::create(response.url())->isSameSchemeHostPort(m_request->origin().get())) {
+ // Recompute the tainting if the request was redirected to a different
+ // origin.
switch (m_request->mode()) {
case WebURLRequest::FetchRequestModeSameOrigin:
ASSERT_NOT_REACHED();
@@ -270,6 +298,13 @@ void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo
}
Response* r = Response::create(m_resolver->executionContext(), taintedResponse);
+ if (response.url().protocolIsData()) {
+ // An "Access-Control-Allow-Origin" header is added for data: URLs
+ // but no headers except for "Content-Type" should exist,
+ // according to the spec:
+ // https://fetch.spec.whatwg.org/#concept-basic-fetch
+ r->headers()->headerList()->remove("Access-Control-Allow-Origin");
+ }
r->headers()->setGuard(Headers::ImmutableGuard);
if (m_request->integrity().isEmpty()) {
@@ -446,6 +481,10 @@ void FetchManager::Loader::performBasicFetch()
if (SchemeRegistry::shouldTreatURLSchemeAsSupportingFetchAPI(m_request->url().protocol())) {
// "Return the result of performing an HTTP fetch using |request|."
performHTTPFetch(false, false);
+ } else if (m_request->url().protocolIsData()) {
+ performDataFetch();
+ } else if (m_request->url().protocolIs("blob")) {
+ performHTTPFetch(false, false);
} else {
// FIXME: implement other protocols.
performNetworkError("Fetch API cannot load " + m_request->url().string() + ". URL scheme \"" + m_request->url().protocol() + "\" is not supported.");
@@ -532,6 +571,32 @@ void FetchManager::Loader::performHTTPFetch(bool corsFlag, bool corsPreflightFla
performNetworkError("Can't create ThreadableLoader");
}
+void FetchManager::Loader::performDataFetch()
+{
+ ASSERT(m_request->url().protocolIsData());
+
+ ResourceRequest request(m_request->url());
+ request.setRequestContext(m_request->context());
+ request.setUseStreamOnResponse(true);
+ request.setHTTPMethod("GET");
+ request.setFetchRedirectMode(WebURLRequest::FetchRedirectModeError);
+
+ ResourceLoaderOptions resourceLoaderOptions;
+ resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
+ resourceLoaderOptions.securityOrigin = m_request->origin().get();
+
+ ThreadableLoaderOptions threadableLoaderOptions;
+ threadableLoaderOptions.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) ? DoNotEnforceContentSecurityPolicy : EnforceConnectSrcDirective;
+ // We set AllowCrossOriginRequests to allow requests to data: URLs (which
+ // are considered as cross-origin) in 'same-origin' mode.
+ threadableLoaderOptions.crossOriginRequestPolicy = AllowCrossOriginRequests;
+
+ InspectorInstrumentation::willStartFetch(executionContext(), this);
+ m_loader = ThreadableLoader::create(*executionContext(), this, request, threadableLoaderOptions, resourceLoaderOptions);
+ if (!m_loader)
+ performNetworkError("Can't create ThreadableLoader");
+}
+
void FetchManager::Loader::failed(const String& message)
{
if (m_failed || m_finished)
« no previous file with comments | « LayoutTests/http/tests/fetch/workers/thorough/scheme-data-other-https.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698