Commit 9daf4f57 authored by Mugdha Lakhani's avatar Mugdha Lakhani Committed by Commit Bot

[BackgroundFetch] Part 2: Implement BackgroundFetchFailureReason.

This is the second part, the plumbing on the blink side.

Bug: 876691, 869918
Change-Id: I62fe4aaf37f41b5ebd341ce4731f7fda1d486feb
Reviewed-on: https://chromium-review.googlesource.com/1185015
Commit-Queue: Mugdha Lakhani <nator@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585906}
parent 57c6bb53
......@@ -200,7 +200,8 @@ blink::WebBackgroundFetchRegistration ToWebBackgroundFetchRegistration(
blink::WebString::FromUTF8(registration.developer_id),
blink::WebString::FromUTF8(registration.unique_id),
registration.upload_total, registration.uploaded,
registration.download_total, registration.downloaded, registration.state);
registration.download_total, registration.downloaded, registration.state,
registration.failure_reason);
}
// If |is_for_fetch_event| is true, some headers may be omitted according
......
......@@ -73,12 +73,18 @@ backgroundFetchTest(async (test, backgroundFetch) => {
assert_equals(registration.uploadTotal, 0);
assert_equals(registration.uploaded, 0);
assert_equals(registration.downloadTotal, 0);
assert_equals(registration.state, "pending");
assert_equals(registration.failureReason, "");
// Skip `downloaded`, as the transfer may have started already.
const {type, results} = await getMessageFromServiceWorker();
const {type, eventRegistration, results} = await getMessageFromServiceWorker();
assert_equals('backgroundfetchsuccess', type);
assert_equals(results.length, 1);
assert_equals(eventRegistration.id, registration.id);
assert_equals(eventRegistration.state, "success");
assert_equals(eventRegistration.failureReason, "");
assert_true(results[0].url.includes('resources/feature-name.txt'));
assert_equals(results[0].status, 200);
assert_equals(results[0].text, 'Background Fetch');
......
......@@ -41,6 +41,8 @@ backgroundFetchTest(async (test, backgroundFetch) => {
assert_equals(registration.uploadTotal, 0);
assert_equals(registration.uploaded, 0);
assert_equals(registration.downloadTotal, 1234);
assert_equals(registration.state, "pending");
assert_equals(registration.failureReason, "");
// Skip `downloaded`, as the transfer may have started already.
const secondRegistration = await backgroundFetch.get(registrationId);
......
......@@ -23,7 +23,7 @@ PASS BackgroundFetchRegistration interface: attribute uploaded
PASS BackgroundFetchRegistration interface: attribute downloadTotal
PASS BackgroundFetchRegistration interface: attribute downloaded
PASS BackgroundFetchRegistration interface: attribute state
FAIL BackgroundFetchRegistration interface: attribute failureReason assert_true: The prototype object must have a property "failureReason" expected true got false
PASS BackgroundFetchRegistration interface: attribute failureReason
PASS BackgroundFetchRegistration interface: attribute onprogress
PASS BackgroundFetchRegistration interface: operation abort()
FAIL BackgroundFetchRegistration interface: operation match(RequestInfo, CacheQueryOptions) assert_own_property: interface prototype object missing non-static operation expected property "match" missing
......
......@@ -23,7 +23,7 @@ PASS BackgroundFetchRegistration interface: attribute uploaded
PASS BackgroundFetchRegistration interface: attribute downloadTotal
PASS BackgroundFetchRegistration interface: attribute downloaded
PASS BackgroundFetchRegistration interface: attribute state
FAIL BackgroundFetchRegistration interface: attribute failureReason assert_true: The prototype object must have a property "failureReason" expected true got false
PASS BackgroundFetchRegistration interface: attribute failureReason
PASS BackgroundFetchRegistration interface: attribute onprogress
PASS BackgroundFetchRegistration interface: operation abort()
FAIL BackgroundFetchRegistration interface: operation match(RequestInfo, CacheQueryOptions) assert_own_property: interface prototype object missing non-static operation expected property "match" missing
......
......@@ -23,7 +23,7 @@ PASS BackgroundFetchRegistration interface: attribute uploaded
PASS BackgroundFetchRegistration interface: attribute downloadTotal
PASS BackgroundFetchRegistration interface: attribute downloaded
PASS BackgroundFetchRegistration interface: attribute state
FAIL BackgroundFetchRegistration interface: attribute failureReason assert_true: The prototype object must have a property "failureReason" expected true got false
PASS BackgroundFetchRegistration interface: attribute failureReason
PASS BackgroundFetchRegistration interface: attribute onprogress
PASS BackgroundFetchRegistration interface: operation abort()
FAIL BackgroundFetchRegistration interface: operation match(RequestInfo, CacheQueryOptions) assert_own_property: interface prototype object missing non-static operation expected property "match" missing
......
......@@ -5,6 +5,25 @@ function sendMessageToDocument(msg) {
source.postMessage(msg);
}
// This is needed to create a local javascript object identical to the
// one returned by a BackgroundFetchEvent, so that it can be serialized
// and transmitted from the service worker context to the document.
function cloneRegistration(registration) {
function deepCopy(src) {
if (typeof src !== 'object' || src === null)
return src;
var dst = Array.isArray(src) ? [] : {};
for (var property in src) {
if (typeof src[property] === 'function')
continue;
dst[property] = deepCopy(src[property]);
}
return dst;
}
return deepCopy(registration);
}
// Notify the document that the SW is registered and ready.
self.addEventListener('message', event => {
source = event.source;
......
......@@ -17,5 +17,8 @@ self.addEventListener('backgroundfetchsuccess', event => {
event.waitUntil(
event.registration.matchAll()
.then(records => Promise.all(records.map(record => getFetchResult(record))))
.then(results => sendMessageToDocument({ type: event.type, results })));
.then(results => {
const registrationCopy = cloneRegistration(event.registration);
sendMessageToDocument({ type: event.type, eventRegistration: registrationCopy, results })
}));
});
......@@ -37,6 +37,7 @@ interface BackgroundFetchRegistration : EventTarget
attribute @@toStringTag
getter downloadTotal
getter downloaded
getter failureReason
getter id
getter onprogress
getter state
......
......@@ -30,6 +30,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] attribute @@toStringTag
[Worker] getter downloadTotal
[Worker] getter downloaded
[Worker] getter failureReason
[Worker] getter id
[Worker] getter onprogress
[Worker] getter state
......
......@@ -431,6 +431,7 @@ interface BackgroundFetchRegistration : EventTarget
attribute @@toStringTag
getter downloadTotal
getter downloaded
getter failureReason
getter id
getter onprogress
getter state
......
......@@ -30,6 +30,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] attribute @@toStringTag
[Worker] getter downloadTotal
[Worker] getter downloaded
[Worker] getter failureReason
[Worker] getter id
[Worker] getter onprogress
[Worker] getter state
......
......@@ -15,20 +15,23 @@ namespace blink {
// Analogous to the following structure in the spec:
// https://wicg.github.io/background-fetch/#background-fetch-registration
struct WebBackgroundFetchRegistration {
WebBackgroundFetchRegistration(const WebString& developer_id,
const WebString& unique_id,
uint64_t upload_total,
uint64_t uploaded,
uint64_t download_total,
uint64_t downloaded,
mojom::BackgroundFetchState state)
WebBackgroundFetchRegistration(
const WebString& developer_id,
const WebString& unique_id,
uint64_t upload_total,
uint64_t uploaded,
uint64_t download_total,
uint64_t downloaded,
mojom::BackgroundFetchState state,
mojom::BackgroundFetchFailureReason failure_reason)
: developer_id(developer_id),
unique_id(unique_id),
upload_total(upload_total),
uploaded(uploaded),
download_total(download_total),
downloaded(downloaded),
state(state) {}
state(state),
failure_reason(failure_reason) {}
~WebBackgroundFetchRegistration() = default;
......@@ -39,6 +42,7 @@ struct WebBackgroundFetchRegistration {
uint64_t download_total;
uint64_t downloaded;
mojom::BackgroundFetchState state;
mojom::BackgroundFetchFailureReason failure_reason;
};
} // namespace blink
......
......@@ -30,7 +30,8 @@ BackgroundFetchRegistration::BackgroundFetchRegistration(
unsigned long long uploaded,
unsigned long long download_total,
unsigned long long downloaded,
blink::mojom::BackgroundFetchState state)
mojom::BackgroundFetchState state,
mojom::BackgroundFetchFailureReason failure_reason)
: developer_id_(developer_id),
unique_id_(unique_id),
upload_total_(upload_total),
......@@ -38,6 +39,7 @@ BackgroundFetchRegistration::BackgroundFetchRegistration(
download_total_(download_total),
downloaded_(downloaded),
state_(state),
failure_reason_(failure_reason),
observer_binding_(this) {}
BackgroundFetchRegistration::BackgroundFetchRegistration(
......@@ -50,6 +52,7 @@ BackgroundFetchRegistration::BackgroundFetchRegistration(
download_total_(web_registration.download_total),
downloaded_(web_registration.downloaded),
state_(web_registration.state),
failure_reason_(web_registration.failure_reason),
observer_binding_(this) {
DCHECK(registration);
Initialize(registration);
......@@ -253,21 +256,41 @@ void BackgroundFetchRegistration::DidAbort(
const String BackgroundFetchRegistration::state() const {
switch (state_) {
case blink::mojom::BackgroundFetchState::SUCCESS:
case mojom::BackgroundFetchState::SUCCESS:
return "success";
case blink::mojom::BackgroundFetchState::FAILURE:
case mojom::BackgroundFetchState::FAILURE:
return "failure";
case blink::mojom::BackgroundFetchState::PENDING:
case mojom::BackgroundFetchState::PENDING:
return "pending";
}
NOTREACHED();
}
const String BackgroundFetchRegistration::failureReason() const {
switch (failure_reason_) {
case mojom::BackgroundFetchFailureReason::NONE:
return "";
case mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI:
case mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER:
return "aborted";
case mojom::BackgroundFetchFailureReason::BAD_STATUS:
return "bad-status";
case mojom::BackgroundFetchFailureReason::SERVICE_WORKER_UNAVAILABLE:
case mojom::BackgroundFetchFailureReason::FETCH_ERROR:
return "fetch-error";
case mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED:
return "quota-exceeded";
case mojom::BackgroundFetchFailureReason::TOTAL_DOWNLOAD_SIZE_EXCEEDED:
return "total-download-exceeded";
}
NOTREACHED();
}
void BackgroundFetchRegistration::Dispose() {
observer_binding_.Close();
}
void BackgroundFetchRegistration::Trace(blink::Visitor* visitor) {
void BackgroundFetchRegistration::Trace(Visitor* visitor) {
visitor->Trace(registration_);
EventTargetWithInlineData::Trace(visitor);
}
......
......@@ -32,13 +32,15 @@ class BackgroundFetchRegistration final
USING_PRE_FINALIZER(BackgroundFetchRegistration, Dispose);
public:
BackgroundFetchRegistration(const String& developer_id,
const String& unique_id,
unsigned long long upload_total,
unsigned long long uploaded,
unsigned long long download_total,
unsigned long long downloaded,
mojom::BackgroundFetchState state);
BackgroundFetchRegistration(
const String& developer_id,
const String& unique_id,
unsigned long long upload_total,
unsigned long long uploaded,
unsigned long long download_total,
unsigned long long downloaded,
mojom::BackgroundFetchState state,
mojom::BackgroundFetchFailureReason failure_reason);
BackgroundFetchRegistration(
ServiceWorkerRegistration* registration,
......@@ -76,6 +78,7 @@ class BackgroundFetchRegistration final
unsigned long long downloadTotal() const;
unsigned long long downloaded() const;
const String state() const;
const String failureReason() const;
const String& unique_id() const { return unique_id_; }
......@@ -120,6 +123,7 @@ class BackgroundFetchRegistration final
unsigned long long download_total_;
unsigned long long downloaded_;
mojom::BackgroundFetchState state_;
mojom::BackgroundFetchFailureReason failure_reason_;
mojo::Binding<blink::mojom::blink::BackgroundFetchRegistrationObserver>
observer_binding_;
......
......@@ -5,6 +5,21 @@
// https://wicg.github.io/background-fetch/#background-fetch-registration
enum BackgroundFetchState { "pending", "success", "failure" };
enum BackgroundFetchFailureReason {
"",
// The operation was aborted by the user, or abort() was called.
"aborted",
// A response had a not-ok-status.
"bad-status",
// A fetch failed for other reasons, e.g. CORS, MIX, an invalid partial response,
// or a general network failure for a fetch that cannot be retried.
"fetch-error",
// Storage quota was reached during the operation.
"quota-exceeded",
// The provided downloadTotal was exceeded.
"total-download-exceeded"
};
[
Exposed=(Window,Worker),
RuntimeEnabled=BackgroundFetch
......@@ -15,11 +30,12 @@ enum BackgroundFetchState { "pending", "success", "failure" };
readonly attribute unsigned long long downloadTotal;
readonly attribute unsigned long long downloaded;
readonly attribute BackgroundFetchState state;
readonly attribute BackgroundFetchFailureReason failureReason;
attribute EventHandler onprogress;
[CallWith=ScriptState] Promise<boolean> abort();
// TODO(crbug.com/875201): Change to (Window,Worker) once we support
// match() and matchAll() for active fetches.
[CallWith=ScriptState, Exposed=ServiceWorker, RaisesException] Promise<BackgroundFetchRecord> match(RequestInfo request, optional CacheQueryOptions options);
......
......@@ -23,7 +23,7 @@ TypeConverter<blink::BackgroundFetchRegistration*,
mojo_registration->developer_id, mojo_registration->unique_id,
mojo_registration->upload_total, mojo_registration->uploaded,
mojo_registration->download_total, mojo_registration->downloaded,
mojo_registration->state);
mojo_registration->state, mojo_registration->failure_reason);
}
blink::mojom::blink::BackgroundFetchOptionsPtr TypeConverter<
......
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