Commit 6e65af76 authored by peter's avatar peter Committed by Commit bot

Implement BackgroundFetchManager::{get, fetch}()

This CL implements the get() and fetch() methods for Background Fetch.
The BackgroundFetchRegistration interface and BackgroundFetchOptions
and IconDefinition dictionary types are added too.

The method has not been hooked up with the browser process yet, as the
Mojo interface has not been implemented yet.

Tests are provided, and will be moved to the WPT directory once it has
been approved upstream:
  https://github.com/w3c/web-platform-tests/pull/5094

BUG=692534

Review-Url: https://codereview.chromium.org/2745543002
Cr-Commit-Position: refs/heads/master@{#456144}
parent 04ab58bf
<!doctype html>
<meta charset="utf-8">
<title>Background Fetch API: fetch() tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/serviceworker/resources/test-helpers.js"></script>
<h1>BackgroundFetchManager.fetch()</h1>
<p>This test validates the behaviour of the fetch() method.</p>
<!-- TODO(peter): Move this to the WPT directory when it's merged. -->
<script>
'use strict';
const workerUrl = 'resources/empty-worker.js';
const scope = 'resources/scope/' + location.pathname;
promise_test(function(test) {
return service_worker_unregister_and_register(test, workerUrl, scope)
.then(registration => {
assert_equals(null, registration.active);
return registration.backgroundFetch.fetch('tag', ['resources/non-existing-file.png']);
})
.then(unreached_fulfillment(test), error => {
assert_equals(error.name, 'TypeError');
});
}, 'BackgroundFetchManager.fetch() requires an activated Service Worker.');
promise_test(function(test) {
const tag = 'my-background-fetch';
const options = {
icons: [
{
src: 'resources/non-existing-large-icon.png',
sizes: '256x256',
type: 'image/png'
},
{
src: 'resources/non-existing-small-icon.jpg',
sizes: '64x64',
type: 'image/jpg'
}
],
title: 'My Background Fetch',
totalDownloadSize: 1024
};
let registration = null;
return service_worker_unregister_and_register(test, workerUrl, scope)
.then(r => {
registration = r;
return wait_for_state(test, r.installing, 'activated');
})
.then(() => registration.backgroundFetch.fetch(tag, ['resources/non-existing-file.png'], options))
.then(backgroundFetchRegistration => {
assert_true(backgroundFetchRegistration instanceof BackgroundFetchRegistration);
assert_equals(backgroundFetchRegistration.tag, tag);
assert_object_equals(backgroundFetchRegistration.icons, options.icons);
assert_equals(backgroundFetchRegistration.totalDownloadSize, options.totalDownloadSize);
assert_equals(backgroundFetchRegistration.title, options.title);
});
}, 'BackgroundFetchManager.fetch() returns a BackgroundFetchRegistration object.');
</script>
<!doctype html>
<meta charset="utf-8">
<title>Background Fetch API: get() tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/serviceworker/resources/test-helpers.js"></script>
<h1>BackgroundFetchManager.get()</h1>
<p>This test validates the behaviour of the get() method.</p>
<!-- TODO(peter): Move this to the WPT directory when it's merged. -->
<script>
'use strict';
const workerUrl = 'resources/empty-worker.js';
const scope = 'resources/scope/' + location.pathname;
promise_test(function(test) {
return service_worker_unregister_and_register(test, workerUrl, scope)
.then(registration => {
assert_equals(null, registration.active);
return registration.backgroundFetch.get('tag');
})
.then(unreached_fulfillment(test), error => {
assert_equals(error.name, 'TypeError');
});
}, 'BackgroundFetchManager.get() requires an activated Service Worker.');
promise_test(function(test) {
let registration = null;
return service_worker_unregister_and_register(test, workerUrl, scope)
.then(r => {
registration = r;
return wait_for_state(test, r.installing, 'activated');
})
.then(() => registration.backgroundFetch.get('invalid-fetch-tag'))
.then(backgroundFetchRegistration => {
assert_equals(backgroundFetchRegistration, null);
});
}, 'BackgroundFetchManager.get() returns NULL for non-existing fetches.');
</script>
<!doctype html>
<meta charset="utf-8">
<title>Background Fetch API: getTags() tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/serviceworker/resources/test-helpers.js"></script>
<h1>BackgroundFetchManager.getTags()</h1>
<p>This test validates the behaviour of the getTags() method.</p>
<!-- TODO(peter): Move this to the WPT directory when it's merged. -->
<script>
'use strict';
const workerUrl = 'resources/empty-worker.js';
const scope = 'resources/scope/' + location.pathname;
promise_test(function(test) {
return service_worker_unregister_and_register(test, workerUrl, scope)
.then(registration => {
assert_equals(null, registration.active);
return registration.backgroundFetch.getTags();
})
.then(unreached_fulfillment(test), error => {
assert_equals(error.name, 'TypeError');
});
}, 'BackgroundFetchManager.getTags() requires an activated Service Worker.');
promise_test(function(test) {
let registration = null;
return service_worker_unregister_and_register(test, workerUrl, scope)
.then(r => {
registration = r;
return wait_for_state(test, r.installing, 'activated');
})
.then(() => registration.backgroundFetch.getTags())
.then(tags => {
assert_true(Array.isArray(tags));
assert_equals(tags.length, 0);
});
}, 'BackgroundFetchManager.getTags() returns an empty sequence by default.');
</script>
<!doctype html>
<html>
<head>
<title>Background Fetch: BackgroundFetchManager.getTags() behaviour.</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="../serviceworker/resources/test-helpers.js"></script>
</head>
<body>
<script>
// TODO(peter): Remove this test when the IDL harness test has landed as
// part of web platform tests.
test(function() {
assert_own_property(self, 'BackgroundFetchManager', 'BackgroundFetchManager needs to be exposed as a global.');
// TODO(peter): Test for the `fetch` method.
// TODO(peter): Test for the `get` method.
assert_own_property(BackgroundFetchManager.prototype, 'getTags');
}, 'BackgroundFetchManager should be exposed and have the expected interface in a Document.');
// TODO(peter): Move this to a WPT test when the getTags() function is able
// to reflect in-progress background fetches.
promise_test(async function(test) {
const workerUrl = 'resources/empty-worker.js';
const scope = 'resources/scope/' + location.pathname;
const registration = await service_worker_unregister_and_register(test, workerUrl, scope);
await wait_for_state(test, registration.installing, 'activated');
try {
await registration.backgroundFetch.getTags();
assert_unreached('getTags() is expected to throw.');
} catch (exception) {
assert_equals(exception.name, 'NotSupportedError');
assert_equals(exception.message, 'Not implemented yet.');
}
}, 'Change-detector test for the getTags() function.');
</script>
</body>
</html>
interface BackgroundFetchManager interface BackgroundFetchManager
method constructor method constructor
method fetch
method get
method getTags method getTags
interface BackgroundFetchRegistration
getter icons
getter tag
getter title
getter totalDownloadSize
method abort
method constructor
interface BarcodeDetector interface BarcodeDetector
method constructor method constructor
method detect method detect
......
interface BackgroundFetchManager interface BackgroundFetchManager
method constructor method constructor
method fetch
method get
method getTags method getTags
interface BackgroundFetchRegistration
getter icons
getter tag
getter title
getter totalDownloadSize
method abort
method constructor
interface BarcodeDetector interface BarcodeDetector
method constructor method constructor
method detect method detect
......
...@@ -8,7 +8,17 @@ Starting worker: resources/global-interface-listing.js ...@@ -8,7 +8,17 @@ Starting worker: resources/global-interface-listing.js
[Worker] interface BackgroundFetchManager [Worker] interface BackgroundFetchManager
[Worker] attribute @@toStringTag [Worker] attribute @@toStringTag
[Worker] method constructor [Worker] method constructor
[Worker] method fetch
[Worker] method get
[Worker] method getTags [Worker] method getTags
[Worker] interface BackgroundFetchRegistration
[Worker] attribute @@toStringTag
[Worker] getter icons
[Worker] getter tag
[Worker] getter title
[Worker] getter totalDownloadSize
[Worker] method abort
[Worker] method constructor
[Worker] interface BarcodeDetector [Worker] interface BarcodeDetector
[Worker] attribute @@toStringTag [Worker] attribute @@toStringTag
[Worker] method constructor [Worker] method constructor
......
...@@ -261,7 +261,17 @@ interface AuthenticationAssertion ...@@ -261,7 +261,17 @@ interface AuthenticationAssertion
interface BackgroundFetchManager interface BackgroundFetchManager
attribute @@toStringTag attribute @@toStringTag
method constructor method constructor
method fetch
method get
method getTags method getTags
interface BackgroundFetchRegistration
attribute @@toStringTag
getter icons
getter tag
getter title
getter totalDownloadSize
method abort
method constructor
interface BarProp interface BarProp
attribute @@toStringTag attribute @@toStringTag
getter visible getter visible
......
...@@ -8,7 +8,17 @@ Starting worker: resources/global-interface-listing.js ...@@ -8,7 +8,17 @@ Starting worker: resources/global-interface-listing.js
[Worker] interface BackgroundFetchManager [Worker] interface BackgroundFetchManager
[Worker] attribute @@toStringTag [Worker] attribute @@toStringTag
[Worker] method constructor [Worker] method constructor
[Worker] method fetch
[Worker] method get
[Worker] method getTags [Worker] method getTags
[Worker] interface BackgroundFetchRegistration
[Worker] attribute @@toStringTag
[Worker] getter icons
[Worker] getter tag
[Worker] getter title
[Worker] getter totalDownloadSize
[Worker] method abort
[Worker] method constructor
[Worker] interface BarcodeDetector [Worker] interface BarcodeDetector
[Worker] attribute @@toStringTag [Worker] attribute @@toStringTag
[Worker] method constructor [Worker] method constructor
......
...@@ -8,6 +8,8 @@ blink_modules_sources("background_fetch") { ...@@ -8,6 +8,8 @@ blink_modules_sources("background_fetch") {
sources = [ sources = [
"BackgroundFetchManager.cpp", "BackgroundFetchManager.cpp",
"BackgroundFetchManager.h", "BackgroundFetchManager.h",
"BackgroundFetchRegistration.cpp",
"BackgroundFetchRegistration.h",
"ServiceWorkerRegistrationBackgroundFetch.cpp", "ServiceWorkerRegistrationBackgroundFetch.cpp",
"ServiceWorkerRegistrationBackgroundFetch.h", "ServiceWorkerRegistrationBackgroundFetch.h",
] ]
......
...@@ -4,8 +4,11 @@ ...@@ -4,8 +4,11 @@
#include "modules/background_fetch/BackgroundFetchManager.h" #include "modules/background_fetch/BackgroundFetchManager.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "bindings/core/v8/ScriptState.h" #include "bindings/core/v8/ScriptState.h"
#include "core/dom/DOMException.h" #include "bindings/core/v8/V8ThrowException.h"
#include "modules/background_fetch/BackgroundFetchOptions.h"
#include "modules/background_fetch/BackgroundFetchRegistration.h"
#include "modules/serviceworkers/ServiceWorkerRegistration.h" #include "modules/serviceworkers/ServiceWorkerRegistration.h"
namespace blink { namespace blink {
...@@ -16,10 +19,70 @@ BackgroundFetchManager::BackgroundFetchManager( ...@@ -16,10 +19,70 @@ BackgroundFetchManager::BackgroundFetchManager(
DCHECK(registration); DCHECK(registration);
} }
ScriptPromise BackgroundFetchManager::fetch(
ScriptState* scriptState,
String tag,
HeapVector<RequestOrUSVString> requests,
const BackgroundFetchOptions& options) {
if (!m_registration->active()) {
return ScriptPromise::reject(
scriptState,
V8ThrowException::createTypeError(scriptState->isolate(),
"No active registration available on "
"the ServiceWorkerRegistration."));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
ScriptPromise promise = resolver->promise();
// TODO(peter): Register the fetch() with the browser process. The reject
// cases there are storage errors and duplicated registrations for the `tag`
// given the `m_registration`.
BackgroundFetchRegistration* registration = new BackgroundFetchRegistration(
m_registration.get(), tag, options.icons(), options.totalDownloadSize(),
options.title());
resolver->resolve(registration);
return promise;
}
ScriptPromise BackgroundFetchManager::get(ScriptState* scriptState,
String tag) {
if (!m_registration->active()) {
return ScriptPromise::reject(
scriptState,
V8ThrowException::createTypeError(scriptState->isolate(),
"No active registration available on "
"the ServiceWorkerRegistration."));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
ScriptPromise promise = resolver->promise();
// TODO(peter): Get the background fetch registration for `tag` from the
// browser process. There may not be one.
resolver->resolve(v8::Null(scriptState->isolate()));
return promise;
}
ScriptPromise BackgroundFetchManager::getTags(ScriptState* scriptState) { ScriptPromise BackgroundFetchManager::getTags(ScriptState* scriptState) {
return ScriptPromise::rejectWithDOMException( if (!m_registration->active()) {
scriptState, return ScriptPromise::reject(
DOMException::create(NotSupportedError, "Not implemented yet.")); scriptState,
V8ThrowException::createTypeError(scriptState->isolate(),
"No active registration available on "
"the ServiceWorkerRegistration."));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
ScriptPromise promise = resolver->promise();
// TODO(peter): Get a list of tags from the browser process.
resolver->resolve(Vector<String>());
return promise;
} }
DEFINE_TRACE(BackgroundFetchManager) { DEFINE_TRACE(BackgroundFetchManager) {
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
namespace blink { namespace blink {
class BackgroundFetchOptions;
class RequestOrUSVString;
class ScriptState; class ScriptState;
class ServiceWorkerRegistration; class ServiceWorkerRegistration;
...@@ -28,6 +30,12 @@ class BackgroundFetchManager final ...@@ -28,6 +30,12 @@ class BackgroundFetchManager final
return new BackgroundFetchManager(registration); return new BackgroundFetchManager(registration);
} }
// Web Exposed methods defined in the IDL file.
ScriptPromise fetch(ScriptState*,
String tag,
HeapVector<RequestOrUSVString> requests,
const BackgroundFetchOptions&);
ScriptPromise get(ScriptState*, String tag);
ScriptPromise getTags(ScriptState*); ScriptPromise getTags(ScriptState*);
DECLARE_TRACE(); DECLARE_TRACE();
......
...@@ -8,8 +8,10 @@ ...@@ -8,8 +8,10 @@
Exposed=(Window,Worker), Exposed=(Window,Worker),
RuntimeEnabled=BackgroundFetch RuntimeEnabled=BackgroundFetch
] interface BackgroundFetchManager { ] interface BackgroundFetchManager {
// TODO(peter): Implement the `fetch` method. // TODO(peter): The `requests` argument of `fetch()` should accept either an
// TODO(peter): Implement the `get` method. // individual RequestInfo, or a sequence of them.
[CallWith=ScriptState] Promise<BackgroundFetchRegistration> fetch(DOMString tag, sequence<RequestInfo> requests, optional BackgroundFetchOptions options);
[CallWith=ScriptState] Promise<BackgroundFetchRegistration?> get(DOMString tag);
[CallWith=ScriptState] Promise<FrozenArray<DOMString>> getTags(); [CallWith=ScriptState] Promise<FrozenArray<DOMString>> getTags();
}; };
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// https://wicg.github.io/background-fetch/#background-fetch-manager
dictionary BackgroundFetchOptions {
sequence<IconDefinition> icons;
DOMString title;
long totalDownloadSize;
};
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modules/background_fetch/BackgroundFetchRegistration.h"
#include "modules/background_fetch/IconDefinition.h"
#include "modules/serviceworkers/ServiceWorkerRegistration.h"
namespace blink {
BackgroundFetchRegistration::BackgroundFetchRegistration(
ServiceWorkerRegistration* registration,
String tag,
HeapVector<IconDefinition> icons,
long long totalDownloadSize,
String title)
: m_registration(registration),
m_tag(tag),
m_icons(icons),
m_totalDownloadSize(totalDownloadSize),
m_title(title) {}
BackgroundFetchRegistration::~BackgroundFetchRegistration() = default;
String BackgroundFetchRegistration::tag() const {
return m_tag;
}
HeapVector<IconDefinition> BackgroundFetchRegistration::icons() const {
return m_icons;
}
long long BackgroundFetchRegistration::totalDownloadSize() const {
return m_totalDownloadSize;
}
String BackgroundFetchRegistration::title() const {
return m_title;
}
void BackgroundFetchRegistration::abort() {
// TODO(peter): Implement the ability to abort the active background fetch
// for the |m_registration| identified by the |m_tag|.
}
DEFINE_TRACE(BackgroundFetchRegistration) {
visitor->trace(m_registration);
visitor->trace(m_icons);
}
} // namespace blink
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BackgroundFetchRegistration_h
#define BackgroundFetchRegistration_h
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptWrappable.h"
#include "platform/heap/GarbageCollected.h"
#include "platform/heap/Handle.h"
#include "wtf/text/WTFString.h"
namespace blink {
class IconDefinition;
class ServiceWorkerRegistration;
// Represents an individual Background Fetch registration. Gives developers
// access to its properties, options, and enables them to abort the fetch.
class BackgroundFetchRegistration final
: public GarbageCollectedFinalized<BackgroundFetchRegistration>,
public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
BackgroundFetchRegistration(ServiceWorkerRegistration*,
String tag,
HeapVector<IconDefinition> icons,
long long totalDownloadSize,
String title);
~BackgroundFetchRegistration();
String tag() const;
HeapVector<IconDefinition> icons() const;
long long totalDownloadSize() const;
String title() const;
void abort();
DECLARE_TRACE();
private:
Member<ServiceWorkerRegistration> m_registration;
String m_tag;
HeapVector<IconDefinition> m_icons;
long long m_totalDownloadSize;
String m_title;
};
} // namespace blink
#endif // BackgroundFetchRegistration_h
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
[
Exposed=(Window,Worker),
RuntimeEnabled=BackgroundFetch
] interface BackgroundFetchRegistration {
readonly attribute DOMString tag;
readonly attribute FrozenArray<IconDefinition> icons;
readonly attribute long totalDownloadSize;
readonly attribute DOMString title;
// TODO(crbug.com/699957): Implement the `fetches` attribute.
void abort();
};
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// https://wicg.github.io/background-fetch/#background-fetch-manager
dictionary IconDefinition {
DOMString src;
DOMString sizes;
DOMString type;
};
...@@ -42,6 +42,7 @@ modules_idl_files = ...@@ -42,6 +42,7 @@ modules_idl_files =
"app_banner/AppBannerPromptResult.idl", "app_banner/AppBannerPromptResult.idl",
"app_banner/BeforeInstallPromptEvent.idl", "app_banner/BeforeInstallPromptEvent.idl",
"background_fetch/BackgroundFetchManager.idl", "background_fetch/BackgroundFetchManager.idl",
"background_fetch/BackgroundFetchRegistration.idl",
"background_sync/SyncEvent.idl", "background_sync/SyncEvent.idl",
"background_sync/SyncManager.idl", "background_sync/SyncManager.idl",
"battery/BatteryManager.idl", "battery/BatteryManager.idl",
...@@ -392,6 +393,8 @@ modules_idl_files = ...@@ -392,6 +393,8 @@ modules_idl_files =
modules_dictionary_idl_files = modules_dictionary_idl_files =
get_path_info([ get_path_info([
"app_banner/BeforeInstallPromptEventInit.idl", "app_banner/BeforeInstallPromptEventInit.idl",
"background_fetch/BackgroundFetchOptions.idl",
"background_fetch/IconDefinition.idl",
"background_sync/SyncEventInit.idl", "background_sync/SyncEventInit.idl",
"bluetooth/BluetoothScanFilterInit.idl", "bluetooth/BluetoothScanFilterInit.idl",
"bluetooth/RequestDeviceOptions.idl", "bluetooth/RequestDeviceOptions.idl",
...@@ -684,6 +687,10 @@ generated_modules_dictionary_files = [ ...@@ -684,6 +687,10 @@ generated_modules_dictionary_files = [
# from the .idl file list(s). # from the .idl file list(s).
"$blink_modules_output_dir/app_banner/BeforeInstallPromptEventInit.cpp", "$blink_modules_output_dir/app_banner/BeforeInstallPromptEventInit.cpp",
"$blink_modules_output_dir/app_banner/BeforeInstallPromptEventInit.h", "$blink_modules_output_dir/app_banner/BeforeInstallPromptEventInit.h",
"$blink_modules_output_dir/background_fetch/BackgroundFetchOptions.cpp",
"$blink_modules_output_dir/background_fetch/BackgroundFetchOptions.h",
"$blink_modules_output_dir/background_fetch/IconDefinition.cpp",
"$blink_modules_output_dir/background_fetch/IconDefinition.h",
"$blink_modules_output_dir/background_sync/SyncEventInit.cpp", "$blink_modules_output_dir/background_sync/SyncEventInit.cpp",
"$blink_modules_output_dir/background_sync/SyncEventInit.h", "$blink_modules_output_dir/background_sync/SyncEventInit.h",
"$blink_modules_output_dir/bluetooth/BluetoothScanFilterInit.cpp", "$blink_modules_output_dir/bluetooth/BluetoothScanFilterInit.cpp",
......
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