| Index: Source/modules/fetch/FetchManager.cpp
|
| diff --git a/Source/modules/fetch/FetchManager.cpp b/Source/modules/fetch/FetchManager.cpp
|
| index 634370cc1daf4525dcf6ac9b0528a77a25634745..989297dbe59509b104bd2b9edd2ab7dba3c3915e 100644
|
| --- a/Source/modules/fetch/FetchManager.cpp
|
| +++ b/Source/modules/fetch/FetchManager.cpp
|
| @@ -37,6 +37,15 @@
|
|
|
| namespace blink {
|
|
|
| +namespace {
|
| +
|
| +bool IsRedirectStatusCode(int statusCode)
|
| +{
|
| + return (statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 307 || statusCode == 308);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| class FetchManager::Loader final : public NoBaseWillBeGarbageCollectedFinalized<FetchManager::Loader>, public ThreadableLoaderClient, public ContextLifecycleObserver {
|
| WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FetchManager::Loader);
|
| public:
|
| @@ -130,17 +139,39 @@ void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo
|
| responseData->setURL(response.url());
|
| responseData->setMIMEType(response.mimeType());
|
|
|
| - FetchResponseData* taintedResponse = responseData;
|
| - switch (m_request->tainting()) {
|
| - case FetchRequestData::BasicTainting:
|
| - taintedResponse = responseData->createBasicFilteredResponse();
|
| - break;
|
| - case FetchRequestData::CORSTainting:
|
| - taintedResponse = responseData->createCORSFilteredResponse();
|
| - break;
|
| - case FetchRequestData::OpaqueTainting:
|
| - taintedResponse = responseData->createOpaqueFilteredResponse();
|
| - break;
|
| + FetchResponseData* taintedResponse = nullptr;
|
| +
|
| + if (IsRedirectStatusCode(m_responseHttpStatusCode)) {
|
| + Vector<String> locations;
|
| + responseData->headerList()->getAll("location", locations);
|
| + if (locations.size() > 1) {
|
| + performNetworkError("Multiple Location header.");
|
| + return;
|
| + }
|
| + if (locations.size() == 1) {
|
| + KURL locationURL(m_request->url(), locations[0]);
|
| + if (!locationURL.isValid()) {
|
| + performNetworkError("Invalid Location header.");
|
| + return;
|
| + }
|
| + ASSERT(m_request->redirect() == WebURLRequest::FetchRedirectModeManual);
|
| + taintedResponse = responseData->createOpaqueRedirectFilteredResponse();
|
| + }
|
| + // When the location header doesn't exist, we don't treat the response
|
| + // as a redirect response, and execute tainting.
|
| + }
|
| + if (!taintedResponse) {
|
| + switch (m_request->tainting()) {
|
| + case FetchRequestData::BasicTainting:
|
| + taintedResponse = responseData->createBasicFilteredResponse();
|
| + break;
|
| + case FetchRequestData::CORSTainting:
|
| + taintedResponse = responseData->createCORSFilteredResponse();
|
| + break;
|
| + case FetchRequestData::OpaqueTainting:
|
| + taintedResponse = responseData->createOpaqueFilteredResponse();
|
| + break;
|
| + }
|
| }
|
| Response* r = Response::create(m_resolver->executionContext(), taintedResponse);
|
| r->headers()->setGuard(Headers::ImmutableGuard);
|
| @@ -335,7 +366,7 @@ void FetchManager::Loader::performHTTPFetch(bool corsFlag, bool corsPreflightFla
|
| request.setHTTPBody(httpBody);
|
| }
|
| }
|
| -
|
| + request.setFetchRedirectMode(m_request->redirect());
|
| request.setUseStreamOnResponse(true);
|
|
|
| // "2. Append `Referer`/empty byte sequence, if |HTTPRequest|'s |referrer|
|
|
|