| OLD | NEW |
| 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 25 matching lines...) Expand all Loading... |
| 36 public: | 36 public: |
| 37 static PassOwnPtrWillBeRawPtr<Loader> create(ExecutionContext* executionCont
ext, FetchManager* fetchManager, PassRefPtrWillBeRawPtr<ScriptPromiseResolver> r
esolver, FetchRequestData* request) | 37 static PassOwnPtrWillBeRawPtr<Loader> create(ExecutionContext* executionCont
ext, FetchManager* fetchManager, PassRefPtrWillBeRawPtr<ScriptPromiseResolver> r
esolver, FetchRequestData* request) |
| 38 { | 38 { |
| 39 return adoptPtrWillBeNoop(new Loader(executionContext, fetchManager, res
olver, request)); | 39 return adoptPtrWillBeNoop(new Loader(executionContext, fetchManager, res
olver, request)); |
| 40 } | 40 } |
| 41 | 41 |
| 42 ~Loader() override; | 42 ~Loader() override; |
| 43 DECLARE_VIRTUAL_TRACE(); | 43 DECLARE_VIRTUAL_TRACE(); |
| 44 | 44 |
| 45 void didReceiveResponse(unsigned long, const ResourceResponse&, PassOwnPtr<W
ebDataConsumerHandle>) override; | 45 void didReceiveResponse(unsigned long, const ResourceResponse&, PassOwnPtr<W
ebDataConsumerHandle>) override; |
| 46 void didReceiveData(const char*, unsigned) override; | |
| 47 void didFinishLoading(unsigned long, double) override; | 46 void didFinishLoading(unsigned long, double) override; |
| 48 void didFail(const ResourceError&) override; | 47 void didFail(const ResourceError&) override; |
| 49 void didFailAccessControlCheck(const ResourceError&) override; | 48 void didFailAccessControlCheck(const ResourceError&) override; |
| 50 void didFailRedirectCheck() override; | 49 void didFailRedirectCheck() override; |
| 51 | 50 |
| 52 void start(); | 51 void start(); |
| 53 void cancel(); | 52 void cancel(); |
| 54 void dispose(); | 53 void dispose(); |
| 55 | 54 |
| 56 private: | 55 private: |
| 57 class Canceller : public BodyStreamBuffer::Canceller { | |
| 58 public: | |
| 59 explicit Canceller(Loader* loader) : m_loader(loader) { } | |
| 60 void cancel() override | |
| 61 { | |
| 62 if (m_loader) | |
| 63 m_loader->cancel(); | |
| 64 } | |
| 65 | |
| 66 #if !ENABLE(OILPAN) | |
| 67 // FIXME: This function should go away once Oilpan is shipped. | |
| 68 void disconnect() { m_loader = nullptr; } | |
| 69 #endif | |
| 70 | |
| 71 DEFINE_INLINE_VIRTUAL_TRACE() | |
| 72 { | |
| 73 visitor->trace(m_loader); | |
| 74 BodyStreamBuffer::Canceller::trace(visitor); | |
| 75 } | |
| 76 | |
| 77 private: | |
| 78 // |m_loader| is a raw ptr in non-oilpan circumstance to avoid | |
| 79 // circular reference. It will be cleared when the loader is destructed. | |
| 80 RawPtrWillBeMember<Loader> m_loader; | |
| 81 }; | |
| 82 | |
| 83 | |
| 84 Loader(ExecutionContext*, FetchManager*, PassRefPtrWillBeRawPtr<ScriptPromis
eResolver>, FetchRequestData*); | 56 Loader(ExecutionContext*, FetchManager*, PassRefPtrWillBeRawPtr<ScriptPromis
eResolver>, FetchRequestData*); |
| 85 | 57 |
| 86 void performBasicFetch(); | 58 void performBasicFetch(); |
| 87 void performNetworkError(const String& message); | 59 void performNetworkError(const String& message); |
| 88 void performHTTPFetch(bool corsFlag, bool corsPreflightFlag); | 60 void performHTTPFetch(bool corsFlag, bool corsPreflightFlag); |
| 89 void failed(const String& message); | 61 void failed(const String& message); |
| 90 void notifyFinished(); | 62 void notifyFinished(); |
| 91 | 63 |
| 92 RawPtrWillBeMember<FetchManager> m_fetchManager; | 64 RawPtrWillBeMember<FetchManager> m_fetchManager; |
| 93 RefPtrWillBeMember<ScriptPromiseResolver> m_resolver; | 65 RefPtrWillBeMember<ScriptPromiseResolver> m_resolver; |
| 94 PersistentWillBeMember<FetchRequestData> m_request; | 66 PersistentWillBeMember<FetchRequestData> m_request; |
| 95 PersistentWillBeMember<BodyStreamBuffer> m_responseBuffer; | |
| 96 RefPtr<ThreadableLoader> m_loader; | 67 RefPtr<ThreadableLoader> m_loader; |
| 97 // Hold as a member in order to call |disconnect|. This member can be | |
| 98 // eliminated once Oilpan is shipped. | |
| 99 PersistentWillBeMember<Canceller> m_canceller; | |
| 100 bool m_failed; | 68 bool m_failed; |
| 101 bool m_finished; | 69 bool m_finished; |
| 102 }; | 70 }; |
| 103 | 71 |
| 104 FetchManager::Loader::Loader(ExecutionContext* executionContext, FetchManager* f
etchManager, PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver, FetchReques
tData* request) | 72 FetchManager::Loader::Loader(ExecutionContext* executionContext, FetchManager* f
etchManager, PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver, FetchReques
tData* request) |
| 105 : ContextLifecycleObserver(executionContext) | 73 : ContextLifecycleObserver(executionContext) |
| 106 , m_fetchManager(fetchManager) | 74 , m_fetchManager(fetchManager) |
| 107 , m_resolver(resolver) | 75 , m_resolver(resolver) |
| 108 , m_request(request) | 76 , m_request(request) |
| 109 , m_canceller(new Canceller(this)) | |
| 110 , m_failed(false) | 77 , m_failed(false) |
| 111 , m_finished(false) | 78 , m_finished(false) |
| 112 { | 79 { |
| 113 } | 80 } |
| 114 | 81 |
| 115 FetchManager::Loader::~Loader() | 82 FetchManager::Loader::~Loader() |
| 116 { | 83 { |
| 117 ASSERT(!m_loader); | 84 ASSERT(!m_loader); |
| 118 #if !ENABLE(OILPAN) | |
| 119 // FIXME: This should go away once Oilpan is shipped. | |
| 120 m_canceller->disconnect(); | |
| 121 #endif | |
| 122 } | 85 } |
| 123 | 86 |
| 124 DEFINE_TRACE(FetchManager::Loader) | 87 DEFINE_TRACE(FetchManager::Loader) |
| 125 { | 88 { |
| 126 visitor->trace(m_fetchManager); | 89 visitor->trace(m_fetchManager); |
| 127 visitor->trace(m_resolver); | 90 visitor->trace(m_resolver); |
| 128 visitor->trace(m_request); | 91 visitor->trace(m_request); |
| 129 visitor->trace(m_responseBuffer); | |
| 130 visitor->trace(m_canceller); | |
| 131 ContextLifecycleObserver::trace(visitor); | 92 ContextLifecycleObserver::trace(visitor); |
| 132 } | 93 } |
| 133 | 94 |
| 134 void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo
nse& response, PassOwnPtr<WebDataConsumerHandle> handle) | 95 void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo
nse& response, PassOwnPtr<WebDataConsumerHandle> handle) |
| 135 { | 96 { |
| 136 // FIXME: Use |handle|. | 97 ASSERT(handle); |
| 137 ASSERT_UNUSED(handle, !handle); | |
| 138 // Recompute the tainting if the request was redirected to a different | 98 // Recompute the tainting if the request was redirected to a different |
| 139 // origin. | 99 // origin. |
| 140 if (!SecurityOrigin::create(response.url())->isSameSchemeHostPort(m_request-
>origin().get())) { | 100 if (!SecurityOrigin::create(response.url())->isSameSchemeHostPort(m_request-
>origin().get())) { |
| 141 switch (m_request->mode()) { | 101 switch (m_request->mode()) { |
| 142 case WebURLRequest::FetchRequestModeSameOrigin: | 102 case WebURLRequest::FetchRequestModeSameOrigin: |
| 143 ASSERT_NOT_REACHED(); | 103 ASSERT_NOT_REACHED(); |
| 144 break; | 104 break; |
| 145 case WebURLRequest::FetchRequestModeNoCORS: | 105 case WebURLRequest::FetchRequestModeNoCORS: |
| 146 m_request->setResponseTainting(FetchRequestData::OpaqueTainting); | 106 m_request->setResponseTainting(FetchRequestData::OpaqueTainting); |
| 147 break; | 107 break; |
| 148 case WebURLRequest::FetchRequestModeCORS: | 108 case WebURLRequest::FetchRequestModeCORS: |
| 149 case WebURLRequest::FetchRequestModeCORSWithForcedPreflight: | 109 case WebURLRequest::FetchRequestModeCORSWithForcedPreflight: |
| 150 m_request->setResponseTainting(FetchRequestData::CORSTainting); | 110 m_request->setResponseTainting(FetchRequestData::CORSTainting); |
| 151 break; | 111 break; |
| 152 } | 112 } |
| 153 } | 113 } |
| 154 m_responseBuffer = new BodyStreamBuffer(m_canceller); | 114 FetchResponseData* responseData = FetchResponseData::createWithBuffer(BodySt
reamBuffer::create(handle, "Failed to fetch")); |
| 155 FetchResponseData* responseData = FetchResponseData::createWithBuffer(m_resp
onseBuffer); | |
| 156 responseData->setStatus(response.httpStatusCode()); | 115 responseData->setStatus(response.httpStatusCode()); |
| 157 responseData->setStatusMessage(response.httpStatusText()); | 116 responseData->setStatusMessage(response.httpStatusText()); |
| 158 for (auto& it : response.httpHeaderFields()) | 117 for (auto& it : response.httpHeaderFields()) |
| 159 responseData->headerList()->append(it.key, it.value); | 118 responseData->headerList()->append(it.key, it.value); |
| 160 responseData->setURL(response.url()); | 119 responseData->setURL(response.url()); |
| 161 responseData->setMIMEType(response.mimeType()); | 120 responseData->setMIMEType(response.mimeType()); |
| 162 | 121 |
| 163 FetchResponseData* taintedResponse = responseData; | 122 FetchResponseData* taintedResponse = responseData; |
| 164 switch (m_request->tainting()) { | 123 switch (m_request->tainting()) { |
| 165 case FetchRequestData::BasicTainting: | 124 case FetchRequestData::BasicTainting: |
| 166 taintedResponse = responseData->createBasicFilteredResponse(); | 125 taintedResponse = responseData->createBasicFilteredResponse(); |
| 167 break; | 126 break; |
| 168 case FetchRequestData::CORSTainting: | 127 case FetchRequestData::CORSTainting: |
| 169 taintedResponse = responseData->createCORSFilteredResponse(); | 128 taintedResponse = responseData->createCORSFilteredResponse(); |
| 170 break; | 129 break; |
| 171 case FetchRequestData::OpaqueTainting: | 130 case FetchRequestData::OpaqueTainting: |
| 172 taintedResponse = responseData->createOpaqueFilteredResponse(); | 131 taintedResponse = responseData->createOpaqueFilteredResponse(); |
| 173 break; | 132 break; |
| 174 } | 133 } |
| 175 Response* r = Response::create(m_resolver->executionContext(), taintedRespon
se); | 134 Response* r = Response::create(m_resolver->executionContext(), taintedRespon
se); |
| 176 r->headers()->setGuard(Headers::ImmutableGuard); | 135 r->headers()->setGuard(Headers::ImmutableGuard); |
| 177 m_resolver->resolve(r); | 136 m_resolver->resolve(r); |
| 178 m_resolver.clear(); | 137 m_resolver.clear(); |
| 179 } | 138 } |
| 180 | 139 |
| 181 void FetchManager::Loader::didReceiveData(const char* data, unsigned size) | |
| 182 { | |
| 183 m_responseBuffer->write(DOMArrayBuffer::create(data, size)); | |
| 184 } | |
| 185 | |
| 186 void FetchManager::Loader::didFinishLoading(unsigned long, double) | 140 void FetchManager::Loader::didFinishLoading(unsigned long, double) |
| 187 { | 141 { |
| 188 ASSERT(m_responseBuffer); | |
| 189 ASSERT(!m_failed); | 142 ASSERT(!m_failed); |
| 190 m_responseBuffer->close(); | |
| 191 m_responseBuffer.clear(); | |
| 192 m_finished = true; | 143 m_finished = true; |
| 193 notifyFinished(); | 144 notifyFinished(); |
| 194 } | 145 } |
| 195 | 146 |
| 196 void FetchManager::Loader::didFail(const ResourceError& error) | 147 void FetchManager::Loader::didFail(const ResourceError& error) |
| 197 { | 148 { |
| 198 if (error.isCancellation() || error.isTimeout() || error.domain() != errorDo
mainBlinkInternal) | 149 if (error.isCancellation() || error.isTimeout() || error.domain() != errorDo
mainBlinkInternal) |
| 199 failed(String()); | 150 failed(String()); |
| 200 else | 151 else |
| 201 failed("Fetch API cannot load " + error.failingURL() + ". " + error.loca
lizedDescription()); | 152 failed("Fetch API cannot load " + error.failingURL() + ". " + error.loca
lizedDescription()); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 performHTTPFetch(true, false); | 256 performHTTPFetch(true, false); |
| 306 } | 257 } |
| 307 | 258 |
| 308 void FetchManager::Loader::cancel() | 259 void FetchManager::Loader::cancel() |
| 309 { | 260 { |
| 310 m_finished = true; | 261 m_finished = true; |
| 311 if (m_loader) { | 262 if (m_loader) { |
| 312 m_loader->cancel(); | 263 m_loader->cancel(); |
| 313 m_loader.clear(); | 264 m_loader.clear(); |
| 314 } | 265 } |
| 315 if (m_responseBuffer) { | |
| 316 m_responseBuffer->close(); | |
| 317 m_responseBuffer.clear(); | |
| 318 } | |
| 319 if (m_resolver) { | 266 if (m_resolver) { |
| 320 // Note: In the current implementation this branch is never taken | 267 // Note: In the current implementation this branch is never taken |
| 321 // because this function can be called only through the body stream. | 268 // because this function can be called only through the body stream. |
| 322 ScriptState* scriptState = m_resolver->scriptState(); | 269 ScriptState* scriptState = m_resolver->scriptState(); |
| 323 ScriptState::Scope scope(scriptState); | 270 ScriptState::Scope scope(scriptState); |
| 324 m_resolver->reject(V8ThrowException::createTypeError(scriptState->isolat
e(), "fetch is cancelled")); | 271 m_resolver->reject(V8ThrowException::createTypeError(scriptState->isolat
e(), "fetch is cancelled")); |
| 325 m_resolver.clear(); | 272 m_resolver.clear(); |
| 326 } | 273 } |
| 327 | 274 |
| 328 notifyFinished(); | 275 notifyFinished(); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 | 322 |
| 376 if (m_request->method() != "GET" && m_request->method() != "HEAD") { | 323 if (m_request->method() != "GET" && m_request->method() != "HEAD") { |
| 377 RefPtr<BlobDataHandle> blobDataHandle = m_request->blobDataHandle(); | 324 RefPtr<BlobDataHandle> blobDataHandle = m_request->blobDataHandle(); |
| 378 if (blobDataHandle.get()) { | 325 if (blobDataHandle.get()) { |
| 379 RefPtr<FormData> httpBody(FormData::create()); | 326 RefPtr<FormData> httpBody(FormData::create()); |
| 380 httpBody->appendBlob(blobDataHandle->uuid(), blobDataHandle); | 327 httpBody->appendBlob(blobDataHandle->uuid(), blobDataHandle); |
| 381 request.setHTTPBody(httpBody); | 328 request.setHTTPBody(httpBody); |
| 382 } | 329 } |
| 383 } | 330 } |
| 384 | 331 |
| 332 request.setUseStreamOnResponse(true); |
| 333 |
| 385 // "2. Append `Referer`/empty byte sequence, if |HTTPRequest|'s |referrer| | 334 // "2. Append `Referer`/empty byte sequence, if |HTTPRequest|'s |referrer| |
| 386 // is none, and `Referer`/|HTTPRequest|'s referrer, serialized and utf-8 | 335 // is none, and `Referer`/|HTTPRequest|'s referrer, serialized and utf-8 |
| 387 // encoded, otherwise, to HTTPRequest's header list. | 336 // encoded, otherwise, to HTTPRequest's header list. |
| 388 // We set the referrer using workerGlobalScope's URL in | 337 // We set the referrer using workerGlobalScope's URL in |
| 389 // WorkerThreadableLoader. | 338 // WorkerThreadableLoader. |
| 390 | 339 |
| 391 // "3. Append `Host`, ..." | 340 // "3. Append `Host`, ..." |
| 392 // FIXME: Implement this when the spec is fixed. | 341 // FIXME: Implement this when the spec is fixed. |
| 393 | 342 |
| 394 // "4.If |HTTPRequest|'s force Origin header flag is set, append `Origin`/ | 343 // "4.If |HTTPRequest|'s force Origin header flag is set, append `Origin`/ |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 performNetworkError("Can't create ThreadableLoader"); | 380 performNetworkError("Can't create ThreadableLoader"); |
| 432 } | 381 } |
| 433 | 382 |
| 434 void FetchManager::Loader::failed(const String& message) | 383 void FetchManager::Loader::failed(const String& message) |
| 435 { | 384 { |
| 436 if (m_failed || m_finished) | 385 if (m_failed || m_finished) |
| 437 return; | 386 return; |
| 438 m_failed = true; | 387 m_failed = true; |
| 439 if (!message.isEmpty()) | 388 if (!message.isEmpty()) |
| 440 executionContext()->addConsoleMessage(ConsoleMessage::create(JSMessageSo
urce, ErrorMessageLevel, message)); | 389 executionContext()->addConsoleMessage(ConsoleMessage::create(JSMessageSo
urce, ErrorMessageLevel, message)); |
| 441 if (m_responseBuffer) { | 390 if (m_resolver) { |
| 442 m_responseBuffer->error(DOMException::create(NetworkError, "Failed to fe
tch")); | |
| 443 m_responseBuffer.clear(); | |
| 444 } else if (m_resolver) { | |
| 445 if (!m_resolver->executionContext() || m_resolver->executionContext()->a
ctiveDOMObjectsAreStopped()) | 391 if (!m_resolver->executionContext() || m_resolver->executionContext()->a
ctiveDOMObjectsAreStopped()) |
| 446 return; | 392 return; |
| 447 ScriptState* state = m_resolver->scriptState(); | 393 ScriptState* state = m_resolver->scriptState(); |
| 448 ScriptState::Scope scope(state); | 394 ScriptState::Scope scope(state); |
| 449 m_resolver->reject(V8ThrowException::createTypeError(state->isolate(), "
Failed to fetch")); | 395 m_resolver->reject(V8ThrowException::createTypeError(state->isolate(), "
Failed to fetch")); |
| 450 } | 396 } |
| 451 notifyFinished(); | 397 notifyFinished(); |
| 452 } | 398 } |
| 453 | 399 |
| 454 void FetchManager::Loader::notifyFinished() | 400 void FetchManager::Loader::notifyFinished() |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 | 448 |
| 503 DEFINE_TRACE(FetchManager) | 449 DEFINE_TRACE(FetchManager) |
| 504 { | 450 { |
| 505 #if ENABLE(OILPAN) | 451 #if ENABLE(OILPAN) |
| 506 visitor->trace(m_executionContext); | 452 visitor->trace(m_executionContext); |
| 507 visitor->trace(m_loaders); | 453 visitor->trace(m_loaders); |
| 508 #endif | 454 #endif |
| 509 } | 455 } |
| 510 | 456 |
| 511 } // namespace blink | 457 } // namespace blink |
| OLD | NEW |