Commit 8981b0bd authored by Rayan Kanso's avatar Rayan Kanso Committed by Commit Bot

[Background Fetch] Throw DOMException for responseReady on abort.

According to the spec, responseReady in BackgroundFetchRecord should
throw an AbortError DOMException if the fetch was abandoned.

https://wicg.github.io/background-fetch/#create-record-objects (2.4.3)

Change-Id: Ieadf278acd061e05b8822014d0934f050fcac702
Reviewed-on: https://chromium-review.googlesource.com/c/1283692
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600769}
parent ac0b91e2
......@@ -59,4 +59,16 @@ backgroundFetchTest(async (test, backgroundFetch) => {
};
});
}, 'Calling BackgroundFetchRegistration.abort sets the correct fields and responses are still available');
\ No newline at end of file
}, 'Calling BackgroundFetchRegistration.abort sets the correct fields and responses are still available');
backgroundFetchTest(async (test, backgroundFetch) => {
const registration = await backgroundFetch.fetch(
uniqueId(), '/serviceworker/resources/slow-response.php');
assert_true(await registration.abort());
const {results} = await getMessageFromServiceWorker();
assert_equals(results.length, 1);
assert_false(results[0].response);
assert_equals(results[0].name, 'AbortError');
}, 'An aborted fetch throws a DOM exception when accessing an incomplete record', 'sw-abort.js');
\ No newline at end of file
importScripts('sw-helpers.js');
async function getFetchResult(record) {
try {
await record.responseReady;
} catch (e) {
return {
response: false,
name: e.name,
};
}
return {
response: true,
};
}
self.addEventListener('backgroundfetchabort', event => {
event.waitUntil(
event.registration.matchAll()
.then(records =>
Promise.all(records.map(record => getFetchResult(record))))
.then(results => sendMessageToDocument({results})));
});
......@@ -10,8 +10,9 @@
namespace blink {
BackgroundFetchRecord::BackgroundFetchRecord(Request* request,
Response* response)
: request_(request), response_(response) {
Response* response,
bool aborted)
: request_(request), response_(response), aborted_(aborted) {
DCHECK(request_);
}
......@@ -23,15 +24,25 @@ ScriptPromise BackgroundFetchRecord::responseReady(ScriptState* script_state) {
new ResponseReadyProperty(ExecutionContext::From(script_state), this,
ResponseReadyProperty::kResponseReady);
}
if (!response_) {
return ScriptPromise::Reject(
if (response_) {
DCHECK(response_);
response_ready_property_->Resolve(response_);
return response_ready_property_->Promise(script_state->World());
}
if (aborted_) {
return ScriptPromise::RejectWithDOMException(
script_state,
V8ThrowException::CreateTypeError(script_state->GetIsolate(),
"The response is not available."));
DOMException::Create(
DOMExceptionCode::kAbortError,
"The fetch was aborted before the record was processed."));
}
DCHECK(response_);
response_ready_property_->Resolve(response_);
return response_ready_property_->Promise(script_state->World());
return ScriptPromise::Reject(
script_state,
V8ThrowException::CreateTypeError(script_state->GetIsolate(),
"The response is not available."));
}
Request* BackgroundFetchRecord::request() const {
......
......@@ -21,8 +21,7 @@ class MODULES_EXPORT BackgroundFetchRecord final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
explicit BackgroundFetchRecord(Request* request,
Response* response = nullptr);
BackgroundFetchRecord(Request* request, Response* response, bool aborted);
~BackgroundFetchRecord() override;
Request* request() const;
......@@ -38,6 +37,9 @@ class MODULES_EXPORT BackgroundFetchRecord final : public ScriptWrappable {
Member<Request> request_;
Member<Response> response_;
Member<ResponseReadyProperty> response_ready_property_;
// Whether this record belongs to a fetch that was aborted.
bool aborted_;
};
} // namespace blink
......
......@@ -238,11 +238,19 @@ void BackgroundFetchRegistration::DidGetMatchingRequests(
HeapVector<Member<BackgroundFetchRecord>> to_return;
to_return.ReserveInitialCapacity(settled_fetches.size());
for (const auto& fetch : settled_fetches) {
BackgroundFetchRecord* record = new BackgroundFetchRecord(
Request::Create(script_state, fetch->request),
fetch->response ? Response::Create(script_state, *fetch->response)
: nullptr);
to_return.push_back(record);
Request* request = Request::Create(script_state, fetch->request);
Response* response = fetch->response
? Response::Create(script_state, *fetch->response)
: nullptr;
bool aborted =
failure_reason_ ==
mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI ||
failure_reason_ ==
mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER;
to_return.push_back(new BackgroundFetchRecord(request, response, aborted));
}
if (!return_all) {
......
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