diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/presentation-api/controlling-ua/support | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/presentation-api/controlling-ua/support')
4 files changed, 372 insertions, 0 deletions
diff --git a/testing/web-platform/tests/presentation-api/controlling-ua/support/iframe.html b/testing/web-platform/tests/presentation-api/controlling-ua/support/iframe.html new file mode 100644 index 0000000000..e2171deaa8 --- /dev/null +++ b/testing/web-platform/tests/presentation-api/controlling-ua/support/iframe.html @@ -0,0 +1,181 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Presentation API - controlling ua - sandboxing</title> +<link rel="author" title="Francois Daoust" href="https://www.w3.org/People/#fd"> +<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs/"> +<link rel="help" href="http://w3c.github.io/presentation-api/#dom-presentationrequest-start"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../common.js"></script> +<script> + add_completion_callback((tests, status) => { + // remove unserializable attributes, then send the result to the parent window + // note: a single test result is supposed to appear here. + parent.window.postMessage(JSON.parse(JSON.stringify({ + type: 'presentation-api', test: tests[0], status: status + })), '*'); + }); + + // disable timeout for manual tests + setup({explicit_timeout: true}); + + window.onmessage = function (ev) { + try { + // Presentation URLs are relative to the "controlling-ua" folder, + // update relative URLs for this folder + var urls = presentationUrls.map(function (url) { + if (/:\/\//.test(url)) { + return url; + } + else { + return '../' + url; + } + }); + var request = null; + if (ev.data === 'create') { + try { + request = new PresentationRequest(urls); + parent.window.postMessage('success', '*'); + } + catch (err) { + parent.window.postMessage(err.name, '*'); + } + } + else if (ev.data === 'start') { + request = new PresentationRequest(urls); + request.start() + .then(function () { + parent.window.postMessage('success', '*'); + }) + .catch(function (err) { + if ((err.name === 'NotFoundError') || + (err.name === 'NotAllowedError')) { + // These errors either mean that the user dismissed the dialog + // box or that the UA could not find any available or suitable + // screen. This is equivalent of succeeding for the purpose of + // iframe tests. + parent.window.postMessage('success', '*'); + } + else { + parent.window.postMessage(err.name, '*'); + } + }); + } + else if (ev.data === 'reconnect') { + request = new PresentationRequest(urls); + request.reconnect('someid') + .then(function () { + parent.window.postMessage('success', '*'); + }) + .catch(function (err) { + parent.window.postMessage(err.name, '*'); + }); + } + else if (ev.data.match(/^reconnect\?id=(.*)$/)) { + promise_test(function (t) { + var presentationId = RegExp.$1; + var phase = -1, actual = -1, connection, waitConnection; + var description = [ + "Phase #1: Promise is resolved", + "Phase #2: 'connectionavailable' event fired", + "Phase #3: 'connect' event fired" + ].map(d => { return '(Reconnecting in a nested browsing context) ' + d; }); + + var count = function(evt) { actual++; return evt; }; + var checkPhase = function(evt) { + phase++; + assert_equals(description[actual], description[phase], 'Event order is incorrect.'); + return evt; + }; + + request = new PresentationRequest(urls); + + var eventWatcher = new EventWatcher(t, request, 'connectionavailable'); + var waitConnectionavailable = eventWatcher.wait_for('connectionavailable').then(count).then(function (evt) { + connection = connection || evt.connection; return evt; + }); + + return request.reconnect(presentationId).then(count).then(checkPhase).then(function (c) { + // Reconnecting Phase #1: Promise is resolved + connection = c; + assert_equals(connection.state, 'connecting', 'Check the initial state of the presentation connection.'); + assert_equals(connection.id, presentationId, "The same presentation ID is set to the newly created presentation connection."); + assert_true(connection instanceof PresentationConnection, 'The connection is an instance of PresentationConnection.'); + + var eventWatcher = new EventWatcher(t, connection, 'connect'); + waitConnect = eventWatcher.wait_for('connect').then(count); + + // Reconnecting Phase #2: "connectionavailable" event is fired + return waitConnectionavailable; + }).then(checkPhase).then(function (evt) { + assert_true(evt instanceof PresentationConnectionAvailableEvent, 'An event using PresentationConnectionAvailableEvent is fired.'); + assert_true(evt.isTrusted, 'The event is a trusted event.'); + assert_false(evt.bubbles, 'The event does not bubbles.'); + assert_false(evt.cancelable, 'The event is not cancelable.'); + assert_equals(evt.type, 'connectionavailable', 'The event name is "connectionavailable".'); + assert_equals(evt.target, request, 'event.target is the presentation request.'); + assert_true(evt.connection instanceof PresentationConnection, 'event.connection is a presentation connection.'); + assert_equals(evt.connection, connection, 'event.connection is set to the presentation which the promise is resolved with.'); + + // Reconnecting Phase #3: "connect" event is fired + return waitConnect; + }).then(checkPhase).then(function (evt) { + assert_true(evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event, 'A simple event is fired.'); + assert_equals(evt.type, 'connect', 'The event name is "connect".'); + assert_equals(evt.target, connection, 'event.target is the presentation connection.'); + assert_equals(connection.state, 'connected', 'The presentation connection state is set to "connected".'); + parent.window.postMessage({ type: 'presentation-api', test: { status: 0 } }, '*'); + var terminateWatcher = new EventWatcher(t, connection, 'terminate'); + + // "terminate" event is fired + return terminateWatcher.wait_for('terminate'); + }).then(function (evt) { + assert_true(evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event, 'A simple event is fired.'); + assert_equals(evt.type, 'terminate', 'The event name is "terminate".'); + assert_equals(evt.target, connection, 'event.target is the presentation connection.'); + assert_equals(connection.state, 'terminated', 'The presentation connection state is set to "terminated".'); + }); + }); + } + else if (ev.data.match(/^terminate\?id=(.*)$/)) { + var presentationId = RegExp.$1; + request = new PresentationRequest(urls); + request.reconnect(presentationId) + .then(function (c) { + parent.window.postMessage('reconnected', '*'); + c.onterminate = function(evt) { + parent.window.postMessage({ + isSimpleEvent: evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event, + type: evt.type, + checkConnection: evt.target === c, + state: c.state + }, '*'); + }; + }) + .catch(function (err) { + parent.window.postMessage(err.name, '*'); + }); + } + else if (ev.data === 'getAvailability') { + request = new PresentationRequest(urls); + request.getAvailability() + .then(function () { + parent.window.postMessage('success', '*'); + }) + .catch(function (err) { + if (err.name === 'NotSupportedError') { + parent.window.postMessage('success', '*'); + } + else { + parent.window.postMessage(err.name, '*'); + } + }); + } + } + catch (err) { + parent.window.postMessage('Could not create PresentationRequest', '*'); + } + } + parent.window.postMessage('ready', '*'); +</script> + diff --git a/testing/web-platform/tests/presentation-api/controlling-ua/support/presentation.html b/testing/web-platform/tests/presentation-api/controlling-ua/support/presentation.html new file mode 100644 index 0000000000..8ad838062f --- /dev/null +++ b/testing/web-platform/tests/presentation-api/controlling-ua/support/presentation.html @@ -0,0 +1,98 @@ +<!DOCTYPE html> + +<meta charset="utf-8"> +<link rel="author" title="Intel" href="http://www.intel.com"> +<link rel="author" title="He Yue" href="mailto:yue.he@intel.com"> +<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs/"> +<link rel="help" href="http://w3c.github.io/presentation-api/#interface-presentationconnectionlist"> +<script src="../common.js"></script> +<script src="stash.js"></script> +<script> + const message1 = '1st'; + const message2 = '2nd'; + const message3 = new Uint8Array([51, 114, 100]); // "3rd" + const message4 = new Uint8Array([52, 116, 104]); // "4th" + const message5 = new Uint8Array([108, 97, 115, 116]); // "last" + + const toUint8Array = buf => { + return buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf; + } + + // convert ArrayBuffer or Uint8Array into string + const toText = buf => { + const arr = toUint8Array(buf); + return !buf ? null : arr.reduce((result, item) => { + return result + String.fromCharCode(item); + }, ''); + } + + // compare two ArrayBuffer or Uint8Array + const compare = (a, b) => { + const p = toUint8Array(a); + const q = toUint8Array(b); + return !!p && !!q && p.every((item, index) => { return item === q[index]; }); + }; + + const stash = new Stash(stashIds.toReceiver, stashIds.toController); + + let connection, count = 0; + + const addConnection = c => { + let result = [], testCase; + connection = c; + count++; + + connection.onmessage = event => { + // PresentationConnection_send-manual.https.html + if (testCase === 'send') { + if (typeof event.data === 'string') { + result.push({ type: 'text', data: event.data }); + } + // default value of connection.binaryType is "arraybuffer" + else if(event.data instanceof ArrayBuffer) { + result.push({ type: 'binary', data: toText(event.data) }); + if (compare(event.data, message5)) { + stash.send(JSON.stringify(result)); + } + } + else { + result.push({ type: 'error' }); + } + } + }; + + stash.receive().then(data => { + testCase = data; + + // PresentationConnection_send-manual.https.html + if (testCase === 'send') { + stash.send('ok'); + } + // PresentationConnection_onmessage-manual.https.html + else if (testCase === 'onmessage') { + connection.send(message1); // string + connection.send(message2); // string + connection.send(new Blob([message3])); // Blob + connection.send(message4.buffer); // ArrayBuffer + connection.send(message5); // ArrayBufferView + stash.receive().then(data => { + connection.send(message5); + }); + } + // PresentationConnection_onclose-manual.https.html + else if (testCase === 'close') { + connection.close(); + } + }); + }; + + navigator.presentation.receiver.connectionList + .then(list => { + list.onconnectionavailable = evt => { + addConnection(evt.connection); + }; + list.connections.map(connection => { + addConnection(connection); + }); + }); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/presentation-api/controlling-ua/support/stash.js b/testing/web-platform/tests/presentation-api/controlling-ua/support/stash.js new file mode 100644 index 0000000000..616907d4f2 --- /dev/null +++ b/testing/web-platform/tests/presentation-api/controlling-ua/support/stash.js @@ -0,0 +1,83 @@ +var Stash = function(inbound, outbound) { + this.stashPath = '/presentation-api/controlling-ua/support/stash.py?id='; + this.inbound = inbound; + this.outbound = outbound; +} + +// initialize a stash on wptserve +Stash.prototype.init = function() { + return Promise.all([ + fetch(this.stashPath + this.inbound).then(response => { + return response.text(); + }), + fetch(this.stashPath + this.outbound).then(response => { + return response.text(); + }) + ]); +} + +// upload a test result to a stash on wptserve +Stash.prototype.send = function(result) { + return fetch(this.stashPath + this.outbound, { + method: 'POST', + body: JSON.stringify({ type: 'data', data: result }) + }).then(response => { + return response.text(); + }).then(text => { + return text === 'ok' ? null : Promise.reject(); + }) +}; + +// wait until a test result is uploaded to a stash on wptserve +Stash.prototype.receive = function() { + return new Promise((resolve, reject) => { + let intervalId; + const interval = 500; // msec + const polling = () => { + return fetch(this.stashPath + this.inbound).then(response => { + return response.text(); + }).then(text => { + if (text) { + try { + const json = JSON.parse(text); + if (json.type === 'data') + resolve(json.data); + else + reject(); + } catch(e) { + resolve(text); + } + clearInterval(intervalId); + } + }); + }; + intervalId = setInterval(polling, interval); + }); +}; + +// reset a stash on wptserve +Stash.prototype.stop = function() { + return Promise.all([ + fetch(this.stashPath + this.inbound).then(response => { + return response.text(); + }), + fetch(this.stashPath + this.outbound).then(response => { + return response.text(); + }) + ]).then(() => { + return Promise.all([ + fetch(this.stashPath + this.inbound, { + method: 'POST', + body: JSON.stringify({ type: 'stop' }) + }).then(response => { + return response.text(); + }), + fetch(this.stashPath + this.outbound, { + method: 'POST', + body: JSON.stringify({ type: 'stop' }) + }).then(response => { + return response.text(); + }) + ]); + }); +} diff --git a/testing/web-platform/tests/presentation-api/controlling-ua/support/stash.py b/testing/web-platform/tests/presentation-api/controlling-ua/support/stash.py new file mode 100644 index 0000000000..83653d365a --- /dev/null +++ b/testing/web-platform/tests/presentation-api/controlling-ua/support/stash.py @@ -0,0 +1,10 @@ +def main(request, response): + key = request.GET.first(b"id") + + if request.method == u"POST": + request.server.stash.put(key, request.body) + return b"ok" + else: + value = request.server.stash.take(key) + assert request.server.stash.take(key) is None + return value
\ No newline at end of file |