// META: script=resources/nfc-helpers.js // NDEFReader.makeReadOnly method // https://w3c.github.io/web-nfc/#dom-ndefreader-makereadonly 'use strict'; const invalid_signals = ['string', 123, {}, true, Symbol(), () => {}, self]; nfc_test(async t => { await test_driver.set_permission({name: 'nfc'}, 'denied'); const ndef = new NDEFReader(); await promise_rejects_dom(t, 'NotAllowedError', ndef.makeReadOnly()); }, 'NDEFReader.makeReadOnly should fail if user permission is not granted.'); // We do not provide NFC mock here to simulate that there has no available // implementation for NFC Mojo interface. nfc_test(async (t, mockNFC) => { mockNFC.simulateClosedPipe(); const ndef = new NDEFReader(); await promise_rejects_dom(t, 'NotSupportedError', ndef.makeReadOnly()); }, 'NDEFReader.makeReadOnly should fail if no implementation for NFC Mojo interface is available.'); nfc_test(async (t, mockNFC) => { const ndef = new NDEFReader(); const controller = new AbortController(); // Make sure makeReadOnly is pending mockNFC.setPendingMakeReadOnlyCompleted(false); const p = ndef.makeReadOnly({signal: controller.signal}); const rejected = promise_rejects_dom(t, 'AbortError', p); let callback_called = false; await new Promise(resolve => { t.step_timeout(() => { callback_called = true; controller.abort(); resolve(); }, 10); }); await rejected; assert_true(callback_called, 'timeout should have caused the abort'); }, 'NDEFReader.makeReadOnly should fail if request is aborted before makeReadOnly happends.'); nfc_test(async t => { const ndef = new NDEFReader(); const controller = new AbortController(); assert_false(controller.signal.aborted); controller.abort(); assert_true(controller.signal.aborted); await promise_rejects_dom( t, 'AbortError', ndef.makeReadOnly({signal: controller.signal})); }, 'NDEFReader.makeReadOnly should fail if signal is already aborted.'); nfc_test(async t => { const ndef = new NDEFReader(); const promises = []; invalid_signals.forEach(invalid_signal => { promises.push(promise_rejects_js( t, TypeError, ndef.makeReadOnly({signal: invalid_signal}))); }); await Promise.all(promises); }, 'NDEFReader.write should fail if signal is not an AbortSignal.'); nfc_test(async (t, mockNFC) => { const ndef1 = new NDEFReader(); const ndef2 = new NDEFReader(); const controller = new AbortController(); const p1 = ndef1.makeReadOnly({signal: controller.signal}); // Even though makeReadOnly request is grantable, // this abort should be processed synchronously. controller.abort(); await promise_rejects_dom(t, 'AbortError', p1); await ndef2.makeReadOnly(); }, 'Synchronously signaled abort.'); nfc_test(async (t, mockNFC) => { const ndef = new NDEFReader(); mockNFC.setHWStatus(NFCHWStatus.DISABLED); await promise_rejects_dom(t, 'NotReadableError', ndef.makeReadOnly()); }, 'NDEFReader.makeReadOnly should fail when NFC HW is disabled.'); nfc_test(async (t, mockNFC) => { const ndef = new NDEFReader(); mockNFC.setHWStatus(NFCHWStatus.NOT_SUPPORTED); await promise_rejects_dom(t, 'NotSupportedError', ndef.makeReadOnly()); }, 'NDEFReader.makeReadOnly should fail when NFC HW is not supported.'); nfc_test(async () => { await new Promise((resolve, reject) => { const iframe = document.createElement('iframe'); iframe.srcdoc = ``; iframe.onload = () => iframe.contentWindow.postMessage('Ready', '*'); document.body.appendChild(iframe); window.onmessage = message => { if (message.data == 'Success') { resolve(); } else if (message.data == 'Failure') { reject(); } } }); }, 'Test that WebNFC API is not accessible from iframe context.'); nfc_test(async () => { const ndef = new NDEFReader(); await ndef.makeReadOnly(); }, 'NDEFReader.makeReadOnly should succeed when NFC HW is enabled'); nfc_test(async (t, mockNFC) => { const ndef1 = new NDEFReader(); const ndef2 = new NDEFReader(); // Make sure the first makeReadOnly will be pending. mockNFC.setPendingMakeReadOnlyCompleted(false); const p1 = ndef1.makeReadOnly(); const p2 = ndef2.makeReadOnly(); await promise_rejects_dom(t, 'AbortError', p1); await p2; }, 'NDEFReader.makeReadOnly should replace all previously configured makeReadOnly operations.'); nfc_test(async () => { const ndef = new NDEFReader(); const controller1 = new AbortController(); await ndef.makeReadOnly({signal: controller1.signal}); const controller2 = new AbortController(); const promise = ndef.makeReadOnly({signal: controller2.signal}); controller1.abort(); await promise; }, 'NDEFReader.makeReadOnly signals are independent.'); nfc_test(async (t, mockNFC) => { // Make sure the makeReadOnly will be pending in the mock. mockNFC.setPendingMakeReadOnlyCompleted(false); const ndef1 = new NDEFReader(); const promise = ndef1.makeReadOnly(); // Just to make sure the makeReadOnly() request has already reached to the // mock. const ndef2 = new NDEFReader(); await ndef2.scan(); mockNFC.simulateNonNDEFTagDiscovered(); await promise_rejects_dom(t, 'NotSupportedError', promise); }, 'NDEFReader.makeReadOnly should fail when the NFC device coming up does not expose \ NDEF technology.'); nfc_test(async (t, mockNFC) => { const ndef = new NDEFReader(); mockNFC.simulateDataTransferFails(); await promise_rejects_dom(t, 'NetworkError', ndef.makeReadOnly()); }, 'NDEFReader.makeReadOnly should fail with NetworkError when NFC data transfer fails.');