function showMessage(message) {
  const messageElement = document.getElementById('msg');
  messageElement.innerHTML = message + '\n' + messageElement.innerHTML;
}

function clearMessages() {
  document.getElementById('msg').innerHTML = '';
}

function showElement(id) {
  document.getElementById(id).style.display = 'block';
}

function hideElement(id) {
  document.getElementById(id).style.display = 'none';
}

function hideElements() {
  const elements = [
    'checking',
    'installed',
    'installing',
    'uninstalling',
    'not-installed',
  ];
  for (const id of elements) {
    hideElement(id);
  }
}

async function check() {
  clearMessages();
  hideElements();
  showElement('checking');

  if (!navigator.serviceWorker) {
    hideElement('checking');
    showMessage('No service worker capability in this browser.');
    return;
  }
  
  try {
    const registration = await navigator.serviceWorker.getRegistration('app.js');
    if (!registration) {
      hideElement('checking');
      showElement('not-installed');
      return;
    }
    document.getElementById('scope').innerHTML = registration.scope;
    if (!registration.paymentManager) {
      hideElement('checking');
      showElement('not-installed');
      showMessage('No payment handler capability in this browser. Is chrome://flags/#service-worker-payment-apps enabled?');
      return;
    }
    if (!registration.paymentManager.instruments) {
      hideElement('checking');
      showElement('not-installed');
      showMessage('Payment handler is not fully implemented. Cannot set the instruments.');
      return;
    }
    const result = await registration.paymentManager.instruments.has('instrument-key');
    if (!result) {
      hideElement('checking');
      showElement('not-installed');
      showMessage('No instruments found. Did installation fail?');
      return;
    }
    const instrument = await registration.paymentManager.instruments.get('instrument-key');
    document.getElementById('method').innerHTML = instrument.method;
    hideElement('checking');
    showElement('installed');
  } catch (error) {
    hideElement('checking');
    showElement('not-installed');
    showMessage(error);
  }
}

async function install() {
  hideElements();
  showElement('installing');

  try {
    await navigator.serviceWorker.register('app.js');
    const registration = await navigator.serviceWorker.ready;
    if (!registration.paymentManager) {
      hideElement('installing');
      showMessage('No payment handler capability in this browser.');
      return;
    }
    if (!registration.paymentManager.instruments) {
      hideElement('installing');
      showMessage('Payment handler is not fully implemented. Cannot set the instruments.');
      return;
    }
    await registration.paymentManager.instruments.set('instrument-key', {
      name: 'Citi ****1234',
      icons: [{src:'card_art.png', sizes: '960x607',type: 'image/png'}],
      method: 'src-card',
    });
    await registration.paymentManager.instruments.set('instrument-key-2', {
      name: 'CapitalOne ****5678',
      icons: [{src:'card_art_2.png', sizes: '960x623',type: 'image/png'}],
      method: 'src-card',
    });
    const instrument = registration.paymentManager.instruments.get('instrument-key');
    document.getElementById('scope').innerHTML = registration.scope;
    document.getElementById('method').innerHTML = instrument.method;
    hideElement('installing');
    showElement('installed');
  } catch(error) {
    hideElement('installing');
    showMessage(error);
  }
}

function uninstall() {
  hideElements();
  showElement('uninstalling');

  navigator.serviceWorker
    .getRegistration('app.js')
    .then(registration => {
      registration
        .unregister()
        .then(result => {
          if (result) {
            hideElement('uninstalling');
            showElement('not-installed');
          } else {
            hideElement('uninstalling');
            showElement('installed');
            showMessage(
              'Service worker unregistration returned "false", which indicates that it failed.',
            );
          }
        })
        .catch(error => {
          hideElement('uninstalling');
          showMessage(error);
        });
    })
    .catch(error => {
      hideElement('uninstalling');
      showMessage(error);
    });
}

check();

@@ -2187,32 +2187,657 @@
 (error);%0A  %7D%0A%7D%0A%0A
+const publicKeyCredentialCreationOptions = %7B%0A    challenge: Uint8Array.from(%0A        'INSECURE.SHOULD-BE-A-RANDOM-STRING-FROM-SERVER', c =%3E c.charCodeAt(0)),%0A    rp: %7B%0A        name: %22rsolomakhin.github.io%22,%0A        id: %22rsolomakhin.github.io%22,%0A    %7D,%0A    user: %7B%0A        id: Uint8Array.from(%0A            %22IOFIVBNMUJ%22, c =%3E c.charCodeAt(0)),%0A        name: %22insecure-demo@rsolomakhin.github.io%22,%0A        displayName: %22Demo, Insecure%22,%0A    %7D,%0A    pubKeyCredParams: %5B%7Balg: -7, type: %22public-key%22%7D%5D,%0A    authenticatorSelection: %7B%0A        authenticatorAttachment: %22platform%22,%0A    %7D,%0A    timeout: 60000,%0A    attestation: %22none%22%0A%7D;%0A%0A
 async function i
@@ -3812,94 +3812,8 @@
 %7D);%0A
-    const instrument = registration.paymentManager.instruments.get('instrument-key');%0A
     
@@ -3927,34 +3927,224 @@
 rHTML = 
-instrument.method;
+'src-card';%0A    if (navigator.credentials && navigator.credentials.create) %7B%0A      const credential = await navigator.credentials.create(%7B%0A        publicKey: publicKeyCredentialCreationOptions%0A      %7D);%0A    %7D
 %0A    hid

Add demo webauthn registration