|  | // 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 = `<script> | 
|  | window.onmessage = async (message) => { | 
|  | if (message.data === "Ready") { | 
|  | try { | 
|  | const ndef = new NDEFReader(); | 
|  | await ndef.makeReadOnly(); | 
|  | parent.postMessage("Failure", "*"); | 
|  | } catch (error) { | 
|  | if (error.name == "InvalidStateError") { | 
|  | parent.postMessage("Success", "*"); | 
|  | } else { | 
|  | parent.postMessage("Failure", "*"); | 
|  | } | 
|  | } | 
|  | } | 
|  | }; | 
|  | </script>`; | 
|  | 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.'); |