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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "modules/fetch/FetchManager.h" 6 #include "modules/fetch/FetchManager.h"
7 7
8 #include "bindings/core/v8/ExceptionState.h" 8 #include "bindings/core/v8/ExceptionState.h"
9 #include "bindings/core/v8/ScriptPromiseResolver.h" 9 #include "bindings/core/v8/ScriptPromiseResolver.h"
10 #include "bindings/core/v8/ScriptState.h" 10 #include "bindings/core/v8/ScriptState.h"
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 Vector<char> m_buffer; 148 Vector<char> m_buffer;
149 bool m_finished; 149 bool m_finished;
150 }; 150 };
151 151
152 private: 152 private:
153 Loader(ExecutionContext*, FetchManager*, ScriptPromiseResolver*, FetchReques tData*); 153 Loader(ExecutionContext*, FetchManager*, ScriptPromiseResolver*, FetchReques tData*);
154 154
155 void performBasicFetch(); 155 void performBasicFetch();
156 void performNetworkError(const String& message); 156 void performNetworkError(const String& message);
157 void performHTTPFetch(bool corsFlag, bool corsPreflightFlag); 157 void performHTTPFetch(bool corsFlag, bool corsPreflightFlag);
158 void performDataFetch();
158 void failed(const String& message); 159 void failed(const String& message);
159 void notifyFinished(); 160 void notifyFinished();
160 Document* document() const; 161 Document* document() const;
161 void loadSucceeded(); 162 void loadSucceeded();
162 163
163 RawPtrWillBeMember<FetchManager> m_fetchManager; 164 RawPtrWillBeMember<FetchManager> m_fetchManager;
164 PersistentWillBeMember<ScriptPromiseResolver> m_resolver; 165 PersistentWillBeMember<ScriptPromiseResolver> m_resolver;
165 PersistentWillBeMember<FetchRequestData> m_request; 166 PersistentWillBeMember<FetchRequestData> m_request;
166 RefPtr<ThreadableLoader> m_loader; 167 RefPtr<ThreadableLoader> m_loader;
167 bool m_failed; 168 bool m_failed;
(...skipping 27 matching lines...) Expand all
195 visitor->trace(m_resolver); 196 visitor->trace(m_resolver);
196 visitor->trace(m_request); 197 visitor->trace(m_request);
197 visitor->trace(m_integrityVerifier); 198 visitor->trace(m_integrityVerifier);
198 ContextLifecycleObserver::trace(visitor); 199 ContextLifecycleObserver::trace(visitor);
199 } 200 }
200 201
201 void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo nse& response, PassOwnPtr<WebDataConsumerHandle> handle) 202 void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo nse& response, PassOwnPtr<WebDataConsumerHandle> handle)
202 { 203 {
203 ASSERT(handle); 204 ASSERT(handle);
204 205
206 if (response.url().protocolIs("blob") && response.httpStatusCode() == 404) {
207 // "If |blob| is null, return a network error."
208 // https://fetch.spec.whatwg.org/#concept-basic-fetch
209 performNetworkError("Blob not found.");
210 return;
211 }
212
205 m_responseHttpStatusCode = response.httpStatusCode(); 213 m_responseHttpStatusCode = response.httpStatusCode();
206 214
207 // Recompute the tainting if the request was redirected to a different 215 if (response.url().protocolIsData()) {
208 // origin. 216 if (m_request->url().protocolIsData()) {
209 if (!SecurityOrigin::create(response.url())->isSameSchemeHostPort(m_request- >origin().get())) { 217 // A direct request to data.
218 m_request->setResponseTainting(FetchRequestData::BasicTainting);
219 } else {
220 // A redirect to data: scheme occured.
221 switch (m_request->mode()) {
222 case WebURLRequest::FetchRequestModeSameOrigin:
223 ASSERT_NOT_REACHED();
224 break;
225 case WebURLRequest::FetchRequestModeNoCORS:
226 m_request->setResponseTainting(FetchRequestData::OpaqueTainting) ;
227 break;
228 case WebURLRequest::FetchRequestModeCORS:
229 case WebURLRequest::FetchRequestModeCORSWithForcedPreflight:
230 performNetworkError("Fetch API cannot load " + m_request->url(). string() + ". Redirects to data: URL are allowed only when mode is \"no-cors\"." );
231 return;
232 break;
233 }
234 }
235 } else if (!SecurityOrigin::create(response.url())->isSameSchemeHostPort(m_r equest->origin().get())) {
236 // Recompute the tainting if the request was redirected to a different
237 // origin.
210 switch (m_request->mode()) { 238 switch (m_request->mode()) {
211 case WebURLRequest::FetchRequestModeSameOrigin: 239 case WebURLRequest::FetchRequestModeSameOrigin:
212 ASSERT_NOT_REACHED(); 240 ASSERT_NOT_REACHED();
213 break; 241 break;
214 case WebURLRequest::FetchRequestModeNoCORS: 242 case WebURLRequest::FetchRequestModeNoCORS:
215 m_request->setResponseTainting(FetchRequestData::OpaqueTainting); 243 m_request->setResponseTainting(FetchRequestData::OpaqueTainting);
216 break; 244 break;
217 case WebURLRequest::FetchRequestModeCORS: 245 case WebURLRequest::FetchRequestModeCORS:
218 case WebURLRequest::FetchRequestModeCORSWithForcedPreflight: 246 case WebURLRequest::FetchRequestModeCORSWithForcedPreflight:
219 m_request->setResponseTainting(FetchRequestData::CORSTainting); 247 m_request->setResponseTainting(FetchRequestData::CORSTainting);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 case FetchRequestData::CORSTainting: 291 case FetchRequestData::CORSTainting:
264 taintedResponse = responseData->createCORSFilteredResponse(); 292 taintedResponse = responseData->createCORSFilteredResponse();
265 break; 293 break;
266 case FetchRequestData::OpaqueTainting: 294 case FetchRequestData::OpaqueTainting:
267 taintedResponse = responseData->createOpaqueFilteredResponse(); 295 taintedResponse = responseData->createOpaqueFilteredResponse();
268 break; 296 break;
269 } 297 }
270 } 298 }
271 299
272 Response* r = Response::create(m_resolver->executionContext(), taintedRespon se); 300 Response* r = Response::create(m_resolver->executionContext(), taintedRespon se);
301 if (response.url().protocolIsData()) {
302 // An "Access-Control-Allow-Origin" header is added for data: URLs
303 // but no headers except for "Content-Type" should exist,
304 // according to the spec:
305 // https://fetch.spec.whatwg.org/#concept-basic-fetch
306 r->headers()->headerList()->remove("Access-Control-Allow-Origin");
307 }
273 r->headers()->setGuard(Headers::ImmutableGuard); 308 r->headers()->setGuard(Headers::ImmutableGuard);
274 309
275 if (m_request->integrity().isEmpty()) { 310 if (m_request->integrity().isEmpty()) {
276 m_resolver->resolve(r); 311 m_resolver->resolve(r);
277 m_resolver.clear(); 312 m_resolver.clear();
278 } else { 313 } else {
279 ASSERT(!m_integrityVerifier); 314 ASSERT(!m_integrityVerifier);
280 m_integrityVerifier = new SRIVerifier(handle, updater, r, this, m_reques t->integrity(), response.url()); 315 m_integrityVerifier = new SRIVerifier(handle, updater, r, this, m_reques t->integrity(), response.url());
281 } 316 }
282 } 317 }
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 } 474 }
440 } 475 }
441 476
442 void FetchManager::Loader::performBasicFetch() 477 void FetchManager::Loader::performBasicFetch()
443 { 478 {
444 // "To perform a basic fetch using |request|, switch on |request|'s url's 479 // "To perform a basic fetch using |request|, switch on |request|'s url's
445 // scheme, and run the associated steps:" 480 // scheme, and run the associated steps:"
446 if (SchemeRegistry::shouldTreatURLSchemeAsSupportingFetchAPI(m_request->url( ).protocol())) { 481 if (SchemeRegistry::shouldTreatURLSchemeAsSupportingFetchAPI(m_request->url( ).protocol())) {
447 // "Return the result of performing an HTTP fetch using |request|." 482 // "Return the result of performing an HTTP fetch using |request|."
448 performHTTPFetch(false, false); 483 performHTTPFetch(false, false);
484 } else if (m_request->url().protocolIsData()) {
485 performDataFetch();
486 } else if (m_request->url().protocolIs("blob")) {
487 performHTTPFetch(false, false);
449 } else { 488 } else {
450 // FIXME: implement other protocols. 489 // FIXME: implement other protocols.
451 performNetworkError("Fetch API cannot load " + m_request->url().string() + ". URL scheme \"" + m_request->url().protocol() + "\" is not supported."); 490 performNetworkError("Fetch API cannot load " + m_request->url().string() + ". URL scheme \"" + m_request->url().protocol() + "\" is not supported.");
452 } 491 }
453 } 492 }
454 493
455 void FetchManager::Loader::performNetworkError(const String& message) 494 void FetchManager::Loader::performNetworkError(const String& message)
456 { 495 {
457 failed(message); 496 failed(message);
458 } 497 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 case WebURLRequest::FetchRequestModeCORSWithForcedPreflight: 564 case WebURLRequest::FetchRequestModeCORSWithForcedPreflight:
526 threadableLoaderOptions.crossOriginRequestPolicy = UseAccessControl; 565 threadableLoaderOptions.crossOriginRequestPolicy = UseAccessControl;
527 break; 566 break;
528 } 567 }
529 InspectorInstrumentation::willStartFetch(executionContext(), this); 568 InspectorInstrumentation::willStartFetch(executionContext(), this);
530 m_loader = ThreadableLoader::create(*executionContext(), this, request, thre adableLoaderOptions, resourceLoaderOptions); 569 m_loader = ThreadableLoader::create(*executionContext(), this, request, thre adableLoaderOptions, resourceLoaderOptions);
531 if (!m_loader) 570 if (!m_loader)
532 performNetworkError("Can't create ThreadableLoader"); 571 performNetworkError("Can't create ThreadableLoader");
533 } 572 }
534 573
574 void FetchManager::Loader::performDataFetch()
575 {
576 ASSERT(m_request->url().protocolIsData());
577
578 ResourceRequest request(m_request->url());
579 request.setRequestContext(m_request->context());
580 request.setUseStreamOnResponse(true);
581 request.setHTTPMethod("GET");
582 request.setFetchRedirectMode(WebURLRequest::FetchRedirectModeError);
583
584 ResourceLoaderOptions resourceLoaderOptions;
585 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
586 resourceLoaderOptions.securityOrigin = m_request->origin().get();
587
588 ThreadableLoaderOptions threadableLoaderOptions;
589 threadableLoaderOptions.contentSecurityPolicyEnforcement = ContentSecurityPo licy::shouldBypassMainWorld(executionContext()) ? DoNotEnforceContentSecurityPol icy : EnforceConnectSrcDirective;
590 // We set AllowCrossOriginRequests to allow requests to data: URLs (which
591 // are considered as cross-origin) in 'same-origin' mode.
592 threadableLoaderOptions.crossOriginRequestPolicy = AllowCrossOriginRequests;
593
594 InspectorInstrumentation::willStartFetch(executionContext(), this);
595 m_loader = ThreadableLoader::create(*executionContext(), this, request, thre adableLoaderOptions, resourceLoaderOptions);
596 if (!m_loader)
597 performNetworkError("Can't create ThreadableLoader");
598 }
599
535 void FetchManager::Loader::failed(const String& message) 600 void FetchManager::Loader::failed(const String& message)
536 { 601 {
537 if (m_failed || m_finished) 602 if (m_failed || m_finished)
538 return; 603 return;
539 m_failed = true; 604 m_failed = true;
540 if (!message.isEmpty()) 605 if (!message.isEmpty())
541 executionContext()->addConsoleMessage(ConsoleMessage::create(JSMessageSo urce, ErrorMessageLevel, message)); 606 executionContext()->addConsoleMessage(ConsoleMessage::create(JSMessageSo urce, ErrorMessageLevel, message));
542 if (m_resolver) { 607 if (m_resolver) {
543 if (!m_resolver->executionContext() || m_resolver->executionContext()->a ctiveDOMObjectsAreStopped()) 608 if (!m_resolver->executionContext() || m_resolver->executionContext()->a ctiveDOMObjectsAreStopped())
544 return; 609 return;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 666
602 DEFINE_TRACE(FetchManager) 667 DEFINE_TRACE(FetchManager)
603 { 668 {
604 #if ENABLE(OILPAN) 669 #if ENABLE(OILPAN)
605 visitor->trace(m_executionContext); 670 visitor->trace(m_executionContext);
606 visitor->trace(m_loaders); 671 visitor->trace(m_loaders);
607 #endif 672 #endif
608 } 673 }
609 674
610 } // namespace blink 675 } // namespace blink
OLDNEW
« 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