Commit 65858927 authored by horo@chromium.org's avatar horo@chromium.org

[3/3 blink] Support redirect option of Request and "opaqueredirect" response type.

https://crbug.com/510650#c4 describes the details of the data flow.

1/3 blink: https://codereview.chromium.org/1265133002/
2/3 chromium: https://codereview.chromium.org/1271733002/
3/3 blink: This

BUG=510650,517837

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

git-svn-id: svn://svn.chromium.org/blink/trunk@200815 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 22daad5b
...@@ -82,6 +82,7 @@ promise_test(function(t) { ...@@ -82,6 +82,7 @@ promise_test(function(t) {
assert_equals(request.url, redirect_original_url, assert_equals(request.url, redirect_original_url,
'Request\'s url is the original URL'); 'Request\'s url is the original URL');
assert_equals(request.context, ''); assert_equals(request.context, '');
assert_equals(request.redirect, 'follow');
return fetch(request) return fetch(request)
.then(function(response) { .then(function(response) {
...@@ -95,6 +96,71 @@ promise_test(function(t) { ...@@ -95,6 +96,71 @@ promise_test(function(t) {
}); });
}, 'Request/response url attribute getter with redirect'); }, 'Request/response url attribute getter with redirect');
promise_test(function(t) {
var redirect_target_url =
BASE_ORIGIN + '/fetch/resources/fetch-status.php?status=200';
var redirect_original_url =
BASE_ORIGIN + '/serviceworker/resources/redirect.php?Redirect=' +
redirect_target_url;
var request = new Request(redirect_original_url, {redirect: 'manual'});
assert_equals(request.url, redirect_original_url,
'Request\'s url is the original URL');
assert_equals(request.context, '');
assert_equals(request.redirect, 'manual');
return fetch(request)
.then(function(response) {
assert_equals(response.status, 0);
assert_equals(response.type, 'opaqueredirect');
assert_equals(response.url, '');
});
}, 'Manual redirect fetch returns opaque redirect response');
promise_test(function(t) {
var redirect_target_url =
BASE_ORIGIN + '/fetch/resources/fetch-status.php?status=200';
var redirect_original_url =
BASE_ORIGIN + '/serviceworker/resources/redirect.php?Redirect=' +
redirect_target_url;
var request = new Request(redirect_original_url, {redirect: 'error'});
assert_equals(request.url, redirect_original_url,
'Request\'s url is the original URL');
assert_equals(request.context, '');
assert_equals(request.redirect, 'error');
return fetch(request)
.then(
t.unreached_func('Redirect response must cause an error when redirct' +
' mode is error.'),
function() {});
}, 'Redirect response must cause an error when redirct mode is error.');
promise_test(function(test) {
var url = BASE_ORIGIN + '/fetch/resources/doctype.html';
return fetch(new Request(url, {redirect: 'manual'}))
.then(function(response) {
assert_equals(response.status, 200);
assert_equals(response.statusText, 'OK');
assert_equals(response.url, url);
return response.text();
})
.then(function(text) { assert_equals(text, '<!DOCTYPE html>\n'); })
}, 'No-redirect fetch completes normally even if redirect mode is manual');
promise_test(function(test) {
var url = BASE_ORIGIN + '/fetch/resources/doctype.html';
return fetch(new Request(url, {redirect: 'error'}))
.then(function(response) {
assert_equals(response.status, 200);
assert_equals(response.statusText, 'OK');
assert_equals(response.url, url);
return response.text();
})
.then(function(text) { assert_equals(text, '<!DOCTYPE html>\n'); })
}, 'No-redirect fetch completes normally even if redirect mode is error');
function evalJsonp(text) { function evalJsonp(text) {
return new Promise(function(resolve) { return new Promise(function(resolve) {
var report = resolve; var report = resolve;
......
...@@ -221,6 +221,33 @@ test(function() { ...@@ -221,6 +221,33 @@ test(function() {
}); });
}, 'Request credentials test'); }, 'Request credentials test');
test(function() {
var request1 = {};
var request2 = {};
var REDIRECTS = ['follow', 'error', 'manual', '', undefined];
REDIRECTS.forEach(function(redirect1) {
var init1 = {};
if (redirect1 != undefined) { init1['redirect'] = redirect1; }
request1 = new Request(URL, init1);
assert_equals(request1.redirect, redirect1 || 'follow',
'Request.redirect should match');
request1 = new Request(request1);
assert_equals(request1.redirect, redirect1 || 'follow',
'Request.redirect should match');
REDIRECTS.forEach(function(redirect2) {
request1 = new Request(URL, init1);
var init2 = {};
if (redirect2 != undefined) {
init2['redirect'] = redirect2;
}
request2 = new Request(request1, init2);
assert_equals(request2.redirect,
redirect2 ? redirect2 : request1.redirect,
'Request.redirect should be overridden');
});
});
}, 'Request redirect test');
test(function() { test(function() {
['same-origin', 'cors', 'no-cors'].forEach(function(mode) { ['same-origin', 'cors', 'no-cors'].forEach(function(mode) {
FORBIDDEN_METHODS.forEach(function(method) { FORBIDDEN_METHODS.forEach(function(method) {
......
<!DOCTYPE html>
<title>Service Worker: FetchEvent for resources</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="../resources/get-host-info.js?pipe=sub"></script>
<script src="resources/test-helpers.js"></script>
<script>
function assert_resolves(promise, description) {
return promise.catch(function() { throw description; });
}
function assert_rejects(promise, description) {
return promise.then(
function() { throw description; },
function() {});
}
function iframe_test(url) {
return new Promise(function(resolve, reject) {
var frame = document.createElement('iframe');
// We can't catch the network error on iframe. So we use the timer.
var timer = setTimeout(function() {
reject();
frame.remove();
}, 500);
frame.src = url;
frame.onload = function() {
clearTimeout(timer);
if (frame.contentDocument.body.textContent == 'Hello world\n')
resolve();
else
reject();
frame.remove();
};
document.body.appendChild(frame);
});
}
async_test(function(t) {
var SCOPE = 'resources/fetch-request-redirect-iframe.html';
var SCRIPT = 'resources/fetch-rewrite-worker.js';
var host_info = get_host_info();
var REDIRECT_URL = host_info['HTTP_ORIGIN'] +
'/serviceworker/resources/redirect.php?Redirect=';
var IMAGE_URL = host_info['HTTP_ORIGIN'] + '/resources/square.png';
var AUDIO_URL =
host_info['HTTP_ORIGIN'] + '/media/resources/load-video.php?' +
'name=../../../../media/content/silence.oga&type=audio/ogg';
var XHR_URL = host_info['HTTP_ORIGIN'] +
'/serviceworker/resources/simple.txt';
var HTML_URL = host_info['HTTP_ORIGIN'] + '/resources/dummy.html';
var REDIRECT_TO_IMAGE_URL = REDIRECT_URL + encodeURIComponent(IMAGE_URL);
var REDIRECT_TO_AUDIO_URL = REDIRECT_URL + encodeURIComponent(AUDIO_URL);
var REDIRECT_TO_XHR_URL = REDIRECT_URL + encodeURIComponent(XHR_URL);
var REDIRECT_TO_HTML_URL = REDIRECT_URL + encodeURIComponent(HTML_URL);
var worker;
var frame;
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
.then(function(registration) {
worker = registration.installing;
return wait_for_state(t, worker, 'activated');
})
.then(function() { return with_iframe(SCOPE); })
.then(function(f) {
frame = f;
return Promise.all([
// XMLHttpRequest tests.
assert_resolves(frame.contentWindow.xhr(XHR_URL),
'Normal XHR should succeed.'),
assert_resolves(frame.contentWindow.xhr(REDIRECT_TO_XHR_URL),
'Redirected XHR should succeed.'),
assert_resolves(
frame.contentWindow.xhr(
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
'&redirect-mode=follow'),
'Redirected XHR with Request.redirect=follow should succeed.'),
assert_rejects(
frame.contentWindow.xhr(
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
'&redirect-mode=error'),
'Redirected XHR with Request.redirect=error should fail.'),
assert_rejects(
frame.contentWindow.xhr(
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
'&redirect-mode=manual'),
'Redirected XHR with Request.redirect=manual should fail.'),
// Image loading tests.
assert_resolves(frame.contentWindow.load_image(IMAGE_URL),
'Normal image resource should be loaded.'),
assert_resolves(
frame.contentWindow.load_image(REDIRECT_TO_IMAGE_URL),
'Redirected image resource should be loaded.'),
assert_resolves(
frame.contentWindow.load_image(
'./?url=' + encodeURIComponent(REDIRECT_TO_IMAGE_URL) +
'&redirect-mode=follow'),
'Loading redirected image with Request.redirect=follow should' +
' succeed.'),
assert_rejects(
frame.contentWindow.load_image(
'./?url=' + encodeURIComponent(REDIRECT_TO_IMAGE_URL) +
'&redirect-mode=error'),
'Loading redirected image with Request.redirect=error should ' +
'fail.'),
assert_rejects(
frame.contentWindow.load_image(
'./?url=' + encodeURIComponent(REDIRECT_TO_IMAGE_URL) +
'&redirect-mode=manual'),
'Loading redirected image with Request.redirect=manual should' +
' fail.'),
// Audio loading tests.
assert_resolves(frame.contentWindow.load_audio(AUDIO_URL),
'Normal audio resource should be loaded.'),
assert_resolves(
frame.contentWindow.load_audio(REDIRECT_TO_AUDIO_URL),
'Redirected audio resource should be loaded.'),
assert_resolves(
frame.contentWindow.load_audio(
'./?url=' + encodeURIComponent(REDIRECT_TO_AUDIO_URL) +
'&redirect-mode=follow'),
'Loading redirected audio with Request.redirect=follow should' +
' succeed.'),
assert_rejects(
frame.contentWindow.load_audio(
'./?url=' + encodeURIComponent(REDIRECT_TO_AUDIO_URL) +
'&redirect-mode=error'),
'Loading redirected audio with Request.redirect=error should ' +
'fail.'),
assert_rejects(
frame.contentWindow.load_audio(
'./?url=' + encodeURIComponent(REDIRECT_TO_AUDIO_URL) +
'&redirect-mode=manual'),
'Loading redirected audio with Request.redirect=manual should' +
' fail.'),
// Iframe tests.
assert_resolves(iframe_test(HTML_URL),
'Normal iframe loading should succeed.'),
assert_resolves(
iframe_test(REDIRECT_TO_HTML_URL),
'Normal redirected iframe loading should succeed.'),
assert_resolves(
iframe_test(SCOPE + '?url=' +
encodeURIComponent(REDIRECT_TO_HTML_URL) +
'&redirect-mode=follow'),
'Redirected iframe loading with Request.redirect=follow should'+
' succeed.'),
assert_rejects(
iframe_test(SCOPE + '?url=' +
encodeURIComponent(REDIRECT_TO_HTML_URL) +
'&redirect-mode=error'),
'Redirected iframe loading with Request.redirect=error should '+
'fail.'),
assert_resolves(
iframe_test(SCOPE + '?url=' +
encodeURIComponent(REDIRECT_TO_HTML_URL) +
'&redirect-mode=manual'),
'Redirected iframe loading with Request.redirect=manual should'+
' succeed.'),
]);
})
.then(function() {
frame.remove();
service_worker_unregister_and_done(t, SCOPE);
})
.catch(unreached_rejection(t));
}, 'Verify redirect mode of Fetch API and ServiceWorker FetchEvent.');
</script>
...@@ -16,6 +16,7 @@ function image_test(frame, url, cross_origin, expected_context, ...@@ -16,6 +16,7 @@ function image_test(frame, url, cross_origin, expected_context,
context: expected_context, context: expected_context,
mode: expexted_mode, mode: expexted_mode,
credentials: expected_credentials, credentials: expected_credentials,
redirect: 'follow',
message: 'Image load (url:' + message: 'Image load (url:' +
actual_url + ' cross_origin:' + cross_origin + ')' actual_url + ' cross_origin:' + cross_origin + ')'
}; };
...@@ -30,6 +31,7 @@ function script_test(frame, url, cross_origin, expected_context, ...@@ -30,6 +31,7 @@ function script_test(frame, url, cross_origin, expected_context,
context: expected_context, context: expected_context,
mode: expexted_mode, mode: expexted_mode,
credentials: expected_credentials, credentials: expected_credentials,
redirect: 'follow',
message: 'Script load (url:' + message: 'Script load (url:' +
actual_url + ' cross_origin:' + cross_origin + ')' actual_url + ' cross_origin:' + cross_origin + ')'
}; };
...@@ -44,6 +46,7 @@ function css_test(frame, url, cross_origin, expected_context, ...@@ -44,6 +46,7 @@ function css_test(frame, url, cross_origin, expected_context,
context: expected_context, context: expected_context,
mode: expexted_mode, mode: expexted_mode,
credentials: expected_credentials, credentials: expected_credentials,
redirect: 'follow',
message: 'CSS load (url:' + message: 'CSS load (url:' +
actual_url + ' cross_origin:' + cross_origin + ')' actual_url + ' cross_origin:' + cross_origin + ')'
}; };
...@@ -58,6 +61,7 @@ function font_face_test(frame, url, expected_context, expexted_mode, ...@@ -58,6 +61,7 @@ function font_face_test(frame, url, expected_context, expexted_mode,
context: expected_context, context: expected_context,
mode: expexted_mode, mode: expexted_mode,
credentials: expected_credentials, credentials: expected_credentials,
redirect: 'follow',
message: 'FontFace load (url:' + actual_url + ')' message: 'FontFace load (url:' + actual_url + ')'
}; };
return frame.contentWindow.load_font(actual_url); return frame.contentWindow.load_font(actual_url);
...@@ -71,6 +75,7 @@ function css_image_test(frame, url, type, expected_context, ...@@ -71,6 +75,7 @@ function css_image_test(frame, url, type, expected_context,
context: expected_context, context: expected_context,
mode: expexted_mode, mode: expexted_mode,
credentials: expected_credentials, credentials: expected_credentials,
redirect: 'follow',
message: 'CSSImage load (url:' + actual_url + ' type:' + type + ')' message: 'CSSImage load (url:' + actual_url + ' type:' + type + ')'
}; };
return frame.contentWindow.load_css_image(actual_url, type); return frame.contentWindow.load_css_image(actual_url, type);
...@@ -84,6 +89,7 @@ function css_image_set_test(frame, url, type, expected_context, ...@@ -84,6 +89,7 @@ function css_image_set_test(frame, url, type, expected_context,
context: expected_context, context: expected_context,
mode: expexted_mode, mode: expexted_mode,
credentials: expected_credentials, credentials: expected_credentials,
redirect: 'follow',
message: 'CSSImageSet load (url:' + actual_url + ' type:' + type + ')' message: 'CSSImageSet load (url:' + actual_url + ' type:' + type + ')'
}; };
return frame.contentWindow.load_css_image_set(actual_url, type); return frame.contentWindow.load_css_image_set(actual_url, type);
...@@ -136,6 +142,10 @@ async_test(function(t) { ...@@ -136,6 +142,10 @@ async_test(function(t) {
result.credentials, expected.credentials, result.credentials, expected.credentials,
'credentials of ' + expected.message + ' must be ' + 'credentials of ' + expected.message + ' must be ' +
expected.credentials + '.'); expected.credentials + '.');
assert_equals(
result.redirect, expected.redirect,
'redirect mode of ' + expected.message + ' must be ' +
expected.redirect + '.');
--url_count; --url_count;
delete expected_results[result.url]; delete expected_results[result.url];
if (url_count == 0) { if (url_count == 0) {
......
<script>
function xhr(url) {
return new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
request.addEventListener(
'error',
function(event) { reject(event); });
request.addEventListener(
'load',
function(event) { resolve(request.response); });
request.open('GET', url);
request.send();
});
}
function load_image(url) {
return new Promise(function(resolve, reject) {
var img = document.createElement('img');
document.body.appendChild(img);
img.onload = resolve;
img.onerror = reject;
img.src = url;
});
}
function load_audio(url) {
return new Promise(function(resolve, reject) {
var audio = document.createElement('audio');
document.body.appendChild(audio);
audio.oncanplay = resolve;
audio.onerror = reject;
audio.src = url;
});
}
</script>
...@@ -20,6 +20,7 @@ self.addEventListener('fetch', function(event) { ...@@ -20,6 +20,7 @@ self.addEventListener('fetch', function(event) {
context_clone: event.request.clone().context, context_clone: event.request.clone().context,
context_new: (new Request(event.request)).context, context_new: (new Request(event.request)).context,
mode: event.request.mode, mode: event.request.mode,
redirect: event.request.redirect,
credentials: event.request.credentials credentials: event.request.credentials
}); });
event.respondWith(Promise.reject()); event.respondWith(Promise.reject());
......
...@@ -23,6 +23,9 @@ function get_request_init(params) { ...@@ -23,6 +23,9 @@ function get_request_init(params) {
if (params['credentials']) { if (params['credentials']) {
init['credentials'] = params['credentials']; init['credentials'] = params['credentials'];
} }
if (params['redirect-mode']) {
init['redirect'] = params['redirect-mode'];
}
return init; return init;
} }
......
...@@ -500,6 +500,7 @@ interface Request ...@@ -500,6 +500,7 @@ interface Request
getter headers getter headers
getter method getter method
getter mode getter mode
getter redirect
getter referrer getter referrer
getter url getter url
method arrayBuffer method arrayBuffer
......
...@@ -633,6 +633,7 @@ Starting worker: resources/global-interface-listing.js ...@@ -633,6 +633,7 @@ Starting worker: resources/global-interface-listing.js
[Worker] getter headers [Worker] getter headers
[Worker] getter method [Worker] getter method
[Worker] getter mode [Worker] getter mode
[Worker] getter redirect
[Worker] getter referrer [Worker] getter referrer
[Worker] getter url [Worker] getter url
[Worker] method arrayBuffer [Worker] method arrayBuffer
......
...@@ -3461,6 +3461,7 @@ interface Request ...@@ -3461,6 +3461,7 @@ interface Request
getter headers getter headers
getter method getter method
getter mode getter mode
getter redirect
getter referrer getter referrer
getter url getter url
method arrayBuffer method arrayBuffer
......
...@@ -620,6 +620,7 @@ Starting worker: resources/global-interface-listing.js ...@@ -620,6 +620,7 @@ Starting worker: resources/global-interface-listing.js
[Worker] getter headers [Worker] getter headers
[Worker] getter method [Worker] getter method
[Worker] getter mode [Worker] getter mode
[Worker] getter redirect
[Worker] getter referrer [Worker] getter referrer
[Worker] getter url [Worker] getter url
[Worker] method arrayBuffer [Worker] method arrayBuffer
......
...@@ -661,6 +661,7 @@ Starting worker: resources/global-interface-listing.js ...@@ -661,6 +661,7 @@ Starting worker: resources/global-interface-listing.js
[Worker] getter headers [Worker] getter headers
[Worker] getter method [Worker] getter method
[Worker] getter mode [Worker] getter mode
[Worker] getter redirect
[Worker] getter referrer [Worker] getter referrer
[Worker] getter url [Worker] getter url
[Worker] method arrayBuffer [Worker] method arrayBuffer
......
...@@ -3895,6 +3895,7 @@ interface Request ...@@ -3895,6 +3895,7 @@ interface Request
getter headers getter headers
getter method getter method
getter mode getter mode
getter redirect
getter referrer getter referrer
getter url getter url
method arrayBuffer method arrayBuffer
......
...@@ -648,6 +648,7 @@ Starting worker: resources/global-interface-listing.js ...@@ -648,6 +648,7 @@ Starting worker: resources/global-interface-listing.js
[Worker] getter headers [Worker] getter headers
[Worker] getter method [Worker] getter method
[Worker] getter mode [Worker] getter mode
[Worker] getter redirect
[Worker] getter referrer [Worker] getter referrer
[Worker] getter url [Worker] getter url
[Worker] method arrayBuffer [Worker] method arrayBuffer
......
...@@ -427,6 +427,7 @@ interface Request ...@@ -427,6 +427,7 @@ interface Request
getter headers getter headers
getter method getter method
getter mode getter mode
getter redirect
getter referrer getter referrer
getter url getter url
method arrayBuffer method arrayBuffer
......
...@@ -413,6 +413,7 @@ Starting worker: resources/global-interface-listing.js ...@@ -413,6 +413,7 @@ Starting worker: resources/global-interface-listing.js
[Worker] getter headers [Worker] getter headers
[Worker] getter method [Worker] getter method
[Worker] getter mode [Worker] getter mode
[Worker] getter redirect
[Worker] getter referrer [Worker] getter referrer
[Worker] getter url [Worker] getter url
[Worker] method arrayBuffer [Worker] method arrayBuffer
......
...@@ -3369,6 +3369,7 @@ interface Request ...@@ -3369,6 +3369,7 @@ interface Request
getter headers getter headers
getter method getter method
getter mode getter mode
getter redirect
getter referrer getter referrer
getter url getter url
method arrayBuffer method arrayBuffer
......
...@@ -400,6 +400,7 @@ Starting worker: resources/global-interface-listing.js ...@@ -400,6 +400,7 @@ Starting worker: resources/global-interface-listing.js
[Worker] getter headers [Worker] getter headers
[Worker] getter method [Worker] getter method
[Worker] getter mode [Worker] getter mode
[Worker] getter redirect
[Worker] getter referrer [Worker] getter referrer
[Worker] getter url [Worker] getter url
[Worker] method arrayBuffer [Worker] method arrayBuffer
......
...@@ -451,6 +451,7 @@ Starting worker: resources/global-interface-listing.js ...@@ -451,6 +451,7 @@ Starting worker: resources/global-interface-listing.js
[Worker] getter headers [Worker] getter headers
[Worker] getter method [Worker] getter method
[Worker] getter mode [Worker] getter mode
[Worker] getter redirect
[Worker] getter referrer [Worker] getter referrer
[Worker] getter url [Worker] getter url
[Worker] method arrayBuffer [Worker] method arrayBuffer
......
...@@ -3842,6 +3842,7 @@ interface Request ...@@ -3842,6 +3842,7 @@ interface Request
getter headers getter headers
getter method getter method
getter mode getter mode
getter redirect
getter referrer getter referrer
getter url getter url
method arrayBuffer method arrayBuffer
......
...@@ -438,6 +438,7 @@ Starting worker: resources/global-interface-listing.js ...@@ -438,6 +438,7 @@ Starting worker: resources/global-interface-listing.js
[Worker] getter headers [Worker] getter headers
[Worker] getter method [Worker] getter method
[Worker] getter mode [Worker] getter mode
[Worker] getter redirect
[Worker] getter referrer [Worker] getter referrer
[Worker] getter url [Worker] getter url
[Worker] method arrayBuffer [Worker] method arrayBuffer
......
...@@ -49,14 +49,58 @@ ...@@ -49,14 +49,58 @@
#include "core/loader/FrameLoaderClient.h" #include "core/loader/FrameLoaderClient.h"
#include "core/loader/ThreadableLoaderClient.h" #include "core/loader/ThreadableLoaderClient.h"
#include "platform/SharedBuffer.h" #include "platform/SharedBuffer.h"
#include "platform/Task.h"
#include "platform/network/ResourceRequest.h" #include "platform/network/ResourceRequest.h"
#include "platform/weborigin/SchemeRegistry.h" #include "platform/weborigin/SchemeRegistry.h"
#include "platform/weborigin/SecurityOrigin.h" #include "platform/weborigin/SecurityOrigin.h"
#include "public/platform/Platform.h"
#include "public/platform/WebURLRequest.h" #include "public/platform/WebURLRequest.h"
#include "wtf/Assertions.h" #include "wtf/Assertions.h"
namespace blink { namespace blink {
namespace {
class EmptyDataHandle final : public WebDataConsumerHandle {
private:
class EmptyDataReader final : public WebDataConsumerHandle::Reader {
public:
explicit EmptyDataReader(WebDataConsumerHandle::Client* client) : m_factory(this)
{
Platform::current()->currentThread()->postTask(FROM_HERE, new Task(bind(&EmptyDataReader::notify, m_factory.createWeakPtr(), client)));
}
private:
Result read(void*, size_t, WebDataConsumerHandle::Flags, size_t *readSize) override
{
*readSize = 0;
return Done;
}
Result beginRead(const void** buffer, WebDataConsumerHandle::Flags, size_t *available) override
{
*available = 0;
*buffer = nullptr;
return Done;
}
Result endRead(size_t) override
{
return WebDataConsumerHandle::UnexpectedError;
}
void notify(WebDataConsumerHandle::Client* client)
{
client->didGetReadable();
}
WeakPtrFactory<EmptyDataReader> m_factory;
};
Reader* obtainReaderInternal(Client* client) override
{
return new EmptyDataReader(client);
}
const char* debugName() const override { return "EmptyDataHandle"; }
};
} // namespace
// Max number of CORS redirects handled in DocumentThreadableLoader. // Max number of CORS redirects handled in DocumentThreadableLoader.
// Same number as net/url_request/url_request.cc, and // Same number as net/url_request/url_request.cc, and
// same number as https://fetch.spec.whatwg.org/#concept-http-fetch, Step 4. // same number as https://fetch.spec.whatwg.org/#concept-http-fetch, Step 4.
...@@ -94,6 +138,7 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document& document, Threadabl ...@@ -94,6 +138,7 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document& document, Threadabl
, m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout)
, m_requestStartedSeconds(0.0) , m_requestStartedSeconds(0.0)
, m_corsRedirectLimit(kMaxCORSRedirects) , m_corsRedirectLimit(kMaxCORSRedirects)
, m_redirectMode(request.fetchRedirectMode())
{ {
ASSERT(client); ASSERT(client);
// Setting an outgoing referer is only supported in the async code path. // Setting an outgoing referer is only supported in the async code path.
...@@ -269,7 +314,25 @@ void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ ...@@ -269,7 +314,25 @@ void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ
RefPtr<DocumentThreadableLoader> protect(this); RefPtr<DocumentThreadableLoader> protect(this);
if (!isAllowedByContentSecurityPolicy(request.url(), ContentSecurityPolicy::DidRedirect)) { if (m_redirectMode == WebURLRequest::FetchRedirectModeManual) {
// We use |m_redirectMode| to check the original redirect mode.
// |request| is a new request for redirect. So we don't set the redirect
// mode of it in WebURLLoaderImpl::Context::OnReceivedRedirect().
ASSERT(request.useStreamOnResponse());
// There is no need to read the body of redirect response because there
// is no way to read the body of opaque-redirect filtered response's
// internal response.
// TODO(horo): If we support any API which expose the internal body, we
// will have to read the body. And also HTTPCache changes will be needed
// because it doesn't store the body of redirect responses.
responseReceived(resource, redirectResponse, adoptPtr(new EmptyDataHandle()));
notifyFinished(resource);
clearResource();
request = ResourceRequest();
return;
}
if (m_redirectMode == WebURLRequest::FetchRedirectModeError || !isAllowedByContentSecurityPolicy(request.url(), ContentSecurityPolicy::DidRedirect)) {
m_client->didFailRedirectCheck(); m_client->didFailRedirectCheck();
clearResource(); clearResource();
......
...@@ -170,6 +170,8 @@ class CORE_EXPORT DocumentThreadableLoader final : public ThreadableLoader, priv ...@@ -170,6 +170,8 @@ class CORE_EXPORT DocumentThreadableLoader final : public ThreadableLoader, priv
// But this value is not the max number of total redirects allowed, // But this value is not the max number of total redirects allowed,
// because same-origin redirects are not counted here. // because same-origin redirects are not counted here.
int m_corsRedirectLimit; int m_corsRedirectLimit;
const WebURLRequest::FetchRedirectMode m_redirectMode;
}; };
} // namespace blink } // namespace blink
......
...@@ -156,8 +156,15 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req ...@@ -156,8 +156,15 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Req
// TODO(yhirano): "21. If |init|'s cache member is present, set |request|'s // TODO(yhirano): "21. If |init|'s cache member is present, set |request|'s
// cache mode to it." // cache mode to it."
// TODO(horo): "22. If |init|'s redirect member is present, set |request|'s // "22. If |init|'s redirect member is present, set |request|'s redirect
// redirect mode to it." // mode to it."
if (init.redirect == "follow") {
request->setRedirect(WebURLRequest::FetchRedirectModeFollow);
} else if (init.redirect == "error") {
request->setRedirect(WebURLRequest::FetchRedirectModeError);
} else if (init.redirect == "manual") {
request->setRedirect(WebURLRequest::FetchRedirectModeManual);
}
// TODO(jww): "23. If |init|'s integrity member is present, set |request|'s // TODO(jww): "23. If |init|'s integrity member is present, set |request|'s
// integrity metadata to it." // integrity metadata to it."
......
...@@ -15,8 +15,7 @@ enum RequestContext { ...@@ -15,8 +15,7 @@ enum RequestContext {
}; };
enum RequestMode { "same-origin", "no-cors", "cors" }; enum RequestMode { "same-origin", "no-cors", "cors" };
enum RequestCredentials { "omit", "same-origin", "include" }; enum RequestCredentials { "omit", "same-origin", "include" };
// TODO(horo): Support RequestRedirect when the chromium side patch land. enum RequestRedirect { "follow", "error", "manual" };
// enum RequestRedirect { "follow", "error", "manual" };
[ [
Constructor(RequestInfo input, optional Dictionary requestInitDict), Constructor(RequestInfo input, optional Dictionary requestInitDict),
...@@ -34,8 +33,7 @@ enum RequestCredentials { "omit", "same-origin", "include" }; ...@@ -34,8 +33,7 @@ enum RequestCredentials { "omit", "same-origin", "include" };
readonly attribute DOMString referrer; readonly attribute DOMString referrer;
readonly attribute RequestMode mode; readonly attribute RequestMode mode;
readonly attribute RequestCredentials credentials; readonly attribute RequestCredentials credentials;
// TODO(horo): Support redirect attribute when the chromium side patch land. readonly attribute RequestRedirect redirect;
// readonly attribute RequestRedirect redirect;
[RaisesException] Request clone(); [RaisesException] Request clone();
}; };
......
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