summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/credential-management/support/otpcredential-helper.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/credential-management/support/otpcredential-helper.js')
-rw-r--r--testing/web-platform/tests/credential-management/support/otpcredential-helper.js114
1 files changed, 114 insertions, 0 deletions
diff --git a/testing/web-platform/tests/credential-management/support/otpcredential-helper.js b/testing/web-platform/tests/credential-management/support/otpcredential-helper.js
new file mode 100644
index 0000000000..e07e9f5be3
--- /dev/null
+++ b/testing/web-platform/tests/credential-management/support/otpcredential-helper.js
@@ -0,0 +1,114 @@
+// These tests rely on the User Agent providing an implementation of
+// MockWebOTPService.
+//
+// In Chromium-based browsers this implementation is provided by a polyfill
+// in order to reduce the amount of test-only code shipped to users. To enable
+// these tests the browser must be run with these options:
+// // --enable-blink-features=MojoJS,MojoJSTest
+
+import {isChromiumBased} from '/resources/test-only-api.m.js';
+
+/**
+ * This enumeration is used by WebOTP WPTs to control mock backend behavior.
+ * See MockWebOTPService below.
+ */
+export const Status = {
+ SUCCESS: 0,
+ UNHANDLED_REQUEST: 1,
+ CANCELLED: 2,
+ ABORTED: 3,
+};
+
+/**
+ * A interface which must be implemented by browsers to support WebOTP WPTs.
+ */
+export class MockWebOTPService {
+ /**
+ * Accepts a function to be invoked in response to the next OTP request
+ * received by the mock. The (optionally async) function, when executed, must
+ * return an object with a `status` field holding one of the `Status` values
+ * defined above, and -- if successful -- an `otp` field containing a
+ * simulated OTP string.
+ *
+ * Tests will call this method directly to inject specific response behavior
+ * into the browser-specific mock implementation.
+ */
+ async handleNextOTPRequest(responseFunc) {}
+}
+
+/**
+ * Returns a Promise resolving to a browser-specific MockWebOTPService subclass
+ * instance if one is available.
+ */
+async function createBrowserSpecificMockImpl() {
+ if (isChromiumBased) {
+ return await createChromiumMockImpl();
+ }
+ throw new Error('Unsupported browser.');
+}
+
+const asyncMock = createBrowserSpecificMockImpl();
+
+export function expectOTPRequest() {
+ return {
+ async andReturn(callback) {
+ const mock = await asyncMock;
+ mock.handleNextOTPRequest(callback);
+ }
+ }
+}
+
+/**
+ * Instantiates a Chromium-specific subclass of MockWebOTPService.
+ */
+async function createChromiumMockImpl() {
+ const {SmsStatus, WebOTPService, WebOTPServiceReceiver} = await import(
+ '/gen/third_party/blink/public/mojom/sms/webotp_service.mojom.m.js');
+ const MockWebOTPServiceChromium = class extends MockWebOTPService {
+ constructor() {
+ super();
+ this.mojoReceiver_ = new WebOTPServiceReceiver(this);
+ this.interceptor_ =
+ new MojoInterfaceInterceptor(WebOTPService.$interfaceName);
+ this.interceptor_.oninterfacerequest = (e) => {
+ this.mojoReceiver_.$.bindHandle(e.handle);
+ };
+ this.interceptor_.start();
+ this.requestHandlers_ = [];
+ Object.freeze(this);
+ }
+
+ handleNextOTPRequest(responseFunc) {
+ this.requestHandlers_.push(responseFunc);
+ }
+
+ async receive() {
+ if (this.requestHandlers_.length == 0) {
+ throw new Error('Mock received unexpected OTP request.');
+ }
+
+ const responseFunc = this.requestHandlers_.shift();
+ const response = await responseFunc();
+ switch (response.status) {
+ case Status.SUCCESS:
+ if (typeof response.otp != 'string') {
+ throw new Error('Mock success results require an OTP string.');
+ }
+ return {status: SmsStatus.kSuccess, otp: response.otp};
+ case Status.UNHANDLED_REQUEST:
+ return {status: SmsStatus.kUnhandledRequest};
+ case Status.CANCELLED:
+ return {status: SmsStatus.kCancelled};
+ case Status.ABORTED:
+ return {status: SmsStatus.kAborted};
+ default:
+ throw new Error(
+ `Mock result contains unknown status: ${response.status}`);
+ }
+ }
+
+ async abort() {}
+ };
+ return new MockWebOTPServiceChromium();
+}
+