// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * Namespace object for the client side code.
 */
var client = new Object();

/**
 * Port to contact the policy's callback server.
 */
client.policyCallbackPort = 5199;

client.cryptohome_init_pkcs11 = false;

/**
 * Initialize the client.
 */
client.onLoad =
function onLoad() {
  client.modalShade = document.getElementById('modal-shade');
  client.loadManifest();
};

client.onManifestLoaded =
function onManifestLoaded() {
  client.loadSessionId();
}

client.onSessionIdLoaded =
function onSessionIdLoaded() {
  client.loadInfo();
}

/**
 * Called when client.initPkcs11() completes successfully.
 */
client.onPkcs11Ready =
function onPkcs11Ready() {
  client.loadTokens();
  client.loadCertificates();
};

/**
 * Return the last line of a newline delimited log, skipping blank lines.
 */
client.getLastLogLine =
function getLastLogLine(log) {
  var ary = log.split(/\r?\n/);
  for (var i = 1; i < ary.length; ++i) {
    if (ary[ary.length - i])
      return ary[ary.length - i];
  }

  return '';
}

client.reload =
function reload() {
  document.location.href = document.location.pathname + "?reload";
}

/**
 * Get a url to a resource inside the extension.
 *
 * @param {string} url The path portion of the URL you are interested in.
 */
client.getURL =
function getURL(url) {
  if (typeof 'chrome' != undefined && chrome.extension)
    return chrome.extension.getURL(url);

  return url;
};

/**
 * Load the manifest.json file for this extension.
 *
 */
client.loadManifest =
function loadManifest() {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function () {
    if (this.readyState != 4)
      return;

    if (this.status == 0 || this.status == 200) {
      // Status was 0 in early versions of Chrome.
      client.manifest = JSON.parse(this.responseText);
      console.log('manifest: ' + this.responseText);
      client.onManifestLoaded();
    }
  };

  xhr.open('GET', client.getURL('manifest.json'));
  xhr.send();
};

/**
 * Load the session-id.json file for this session of entd.
 *
 */
client.loadSessionId =
function loadSessionId() {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function () {
    if (this.readyState != 4)
      return;

    if (this.status == 0 || this.status == 200) {
      // Status was 0 in earlier versions of Chrome.
      if (this.responseText != "") {
        client.session_id = JSON.parse(this.responseText);
      } else {
        // Assume an old Chrome OS is being used with this extension.
        console.log('no session-id.json - old chrome os?');
        client.session_id = { session_id: '' }
      }
      console.log('session_id: ' + this.responseText);
      client.onSessionIdLoaded();
    }
  };

  xhr.open('GET', client.getURL('session-id.json'));
  xhr.send();
};

/**
 * Load the basic information from the enterprise daemon.
 *
 * This invokes cb:info and populates the user interface with the results.
 */
client.loadInfo =
function loadInfo() {
  var daemonError = false;
  var pkcs11Error = false;
  var tpmError = false;

  function oncomplete(retval) {
    var ready = false;

    if (retval instanceof client.CallbackSuccess) {
      $("#entd-status").
        text('Ready').
        attr('status', 'green');

      $('#policy-status').
        text(retval.data.description + ', ' + retval.data.version);

      $('#user-status').
        text(retval.data.username);

      if ('systemVersion' in retval.data) {
        var board = 'Unknown hardware';
        if ('lsbRelease' in retval.data &&
            'CHROMEOS_RELEASE_BOARD' in retval.data.lsbRelease) {
          board = retval.data.lsbRelease.CHROMEOS_RELEASE_BOARD;
        }
        $('#system-info').text('Chrome OS ' +
                               retval.data.systemVersion.join('.') + ', ' +
                               board);
      } else {
        $('#system-info').text('Chrome OS earlier than 0.14');
      }

      var pkcs11 = retval.data.pkcs11;
      if (pkcs11.state != 'stop:ready') {
        $("#pkcs11-status").
          text('Waiting...').
          attr('status', 'red');

        if (!pkcs11Error) {
          pkcs11Error = true;
          client.showError(
            'PKCS#11 services have not started, you may need to clear your ' +
            'TPM to recover.', 'Error',
            { details: 'current state: ' + pkcs11.state + '\n' +
              pkcs11.log });
        }
      } else {
        $("#pkcs11-status").
          text('Ready').
          attr('status', 'green');

        // Use presence of isTokenReady to determine if
        // cryptohome_init_pkcs11 is true.
        // TODO(crosbug.com/14277): Remove this conditional and code
        // to recognize if TPM has been initialized (only check token).
        client.cryptohome_init_pkcs11 = 'isTokenReady' in pkcs11;

        if (retval.data.isLibcrosLoaded && !retval.data.tpm.isEnabled) {
          if (!tpmError) {
            client.showError("Your TPM is not enabled.  Please enable " +
                             "it in the BIOS.");
            $('#entd-message').
              text('Please reboot and enable your TPM.').
              attr('status', 'red');
            tpmError = true;
          }
        } else if (retval.data.isLibcrosLoaded && !retval.data.tpm.isReady) {
          if (!tpmError) {
            var options = { details: JSON.stringify(retval.data.tpm) };
            if (retval.data.tpm.isBeingOwned) {
              client.showAlert('Please wait while your TPM is owned.  This ' +
                               'dialog should go away on its own when the ' +
                               'process completes.', 'Alert', options);
            } else if (!retval.data.tpm.isEnabled) {
              client.showError('Your TPM is not enabled.  Please enable it ' +
                               'in your BIOS settings.', 'Error', options);
            } else {
              client.showError('Your TPM is not properly configured.  Please ' +
                               'clear your TPM and try again.', 'Error',
                               options);
            }

            $('#entd-message').
              text('Waiting for TPM.').
              attr('status', 'red');
            tpmError = true;
          }
        } else if (retval.data.isLibcrosLoaded &&
                   client.cryptohome_init_pkcs11 &&
                   !pkcs11.isTokenReady) {
          if (!tpmError) {
            client.showAlert('Please wait while your TPM Token is being ' +
                             'created.  This dialog should go away on its ' +
                             'own when the process completes.', 'Alert',
                             options);
            $('#entd-message').
              text('Waiting for TPM Token.').
              attr('status', 'red');
            tpmError = true;
          }
        } else {
          ready = true;
        }
      }
    } else {
      $("#entd-status").
        text('Waiting...').
        attr('status', 'red');

      $("#pkcs11-status").
        text('Unknown');

      if (!daemonError) {
        daemonError = true;
        var msg;

        if (document.location.search.match(/reload/)) {
          msg = 'Please wait while the Enterprise Daemon restarts.';
        } else {
          msg = 'The Enterprise Daemon has not started.  Make sure you have ' +
              'approved an enterprise certificate authority, and log out or ' +
              'reboot after installing the policy and approving.';
        }

        client.showError(msg, 'Error', { details: JSON.stringify(retval) } );
      }
    }

    if (ready) {
      if (retval.data.browserPolicyChanged) {
        $('#entd-message').
            text('Your browser settings have been changed, you ' +
                 'must log out before they take effect.').
            attr('status', 'red');
      } else {
        $('#entd-message').text('');
      }

      client.hideModal();
      client.onPkcs11Ready();
    } else {
      setTimeout(function () {
          client.invokePolicyCallback('info', null, oncomplete);
      }, 2000);
    }
  }

  client.invokePolicyCallback('info', null, oncomplete);
};

/**
 * Load token information from the enterprise daemon and update the UI with
 * the results.
 */
client.loadTokens =
function loadTokens() {
  function oncomplete(retval) {
    if (retval instanceof client.CallbackSuccess) {
      if (client.tokens) {
        // If we've loaded certificates at least once, then just
        // update the existing UI.
        client.refreshTokens(retval.data.tokenList);
      } else {
        // Otherwise we have to create it from scratch.
        client.resetTokens(retval.data.tokenList);
      }
    } else {
      throw new Error('Callback failed: ' + retval);
    }
  }

  client.invokePolicyCallback('listTokens', null, oncomplete);
};

/**
 * Load the list of certificates for this policy.
 *
 * If the certificate list has not already been loaded, this create the initial
 * UI for each known certificate.  If it has been loaded, this will update
 * the UI to reflect the current state.
 */
client.loadCertificates =
function loadCertificates() {
  function oncomplete(retval) {
    if (retval instanceof client.CallbackSuccess) {
      if (client.certificates) {
        // If we've loaded certificates at least once, then just
        // update the existing UI.
        client.refreshCertificates(retval.data);
      } else {
        // Otherwise we have to create it from scratch.
        client.resetCertificates(retval.data);
      }
    } else {
      throw new Error('Callback failed: ' + retval);
    }
  }

  client.invokePolicyCallback('listCertificates', null, oncomplete);
};

/**
 * Initiate a certificate installation.
 *
 * This causes the certificate progress dialog to be shown, and manages
 * the asynchronous installation of a certificate.
 */
client.installCert =
function installCert(cert, variables) {
  var key = cert.key;

  // Called for any kind of error from the enterprise daemon.
  function onerror(retval) {
    if (retval instanceof client.CallbackError) {
      client.hideModal(function () {
          if (retval && retval.arg_ && retval.arg_.variables &&
              retval.arg_.variables.password) {
            retval.arg_.variables.password = '** PASSWORD WAS HERE **';
          }
          client.showError(retval.data, 'Error',
                           { details: JSON.stringify(retval) });
        });
    } else {
      // Status changes are known via certificate status.  Refreshing.
      client.invokePolicyCallback('listCertificates', null, oncomplete_list);
    }
  };

  // Called when we get an updated list of certificates.
  function oncomplete_list(retval) {
    if (retval instanceof client.CallbackError)
      return onerror(retval);

    client.refreshCertificates(retval.data);
    cert = retval.data[key];
    if (!cert)
      return alert("No cert: " + key);

    if (cert.state == 'stop:key') {
      // Key generation is done, proceed to CSR generation.
      $('#cert-status').find('.cert-key').attr('status', 'green');
      $('#cert-status').find('.cert-csr').attr('status', 'progress');
    } else if (cert.state == 'stop:csr') {
      // CSR is done, now fetch the cert.
      $('#cert-status').find('.cert-key').attr('status', 'green');
      $('#cert-status').find('.cert-csr').attr('status', 'green');
      $('#cert-status').find('.cert-request').attr('status', 'progress');
      client.invokePolicyCallback('getCert', { certificateId: cert.id },
                                  onerror);
    } else if (cert.state == 'stop:cert') {
      // Cert is fetched, configure the network.
      $('#cert-status').find('.cert-request').attr('status', 'green');
      $('#cert-status').find('.cert-install').attr('status', 'progress');
      client.invokePolicyCallback('installCert', { certificateId: cert.id },
                                  onerror);
    } else if (cert.state == 'stop:ready') {
      $('#cert-status').find('.cert-install').attr('status', 'green');
      client.showSuccess('Your certificate has been installed',
                         'Certificate Installed');
      return;
    } else if (cert.state == 'stop:error') {
      client.showCertDetails(cert);
      return;
    }

    setTimeout(function () {
        client.invokePolicyCallback('listCertificates', null,
                                    oncomplete_list);
      }, 1000);
  };

  client.showCertProgress(cert);

  $('#cert-status').find('.cert-key').attr('status', 'progress');

  client.invokePolicyCallback(
      'initiateCSR', { certificateId: cert.id, variables: variables },
      onerror);
}

/**
 * Initiate a token initialization.
 *
 * This causes the token initialization progress dialog to be shown, and manages
 * the asynchronous initialization of a token.
 * TODO(crosbug.com/14277): Remove token initialization UI.
 */
client.initToken =
function initToken(token, force) {
  var slotId = token.slotId;

  // Called for any kind of error from the enterprise daemon.
  function onerror(retval) {
    if (retval instanceof client.CallbackError)
      client.showError('There was an error initializing your token. ' +
                       'If the problem persists, clear your TPM and try ' +
                       'again.', 'Error',
                       { details: JSON.stringify(retval) });
  };

  // Called when we get an updated list of tokens.
  function oncomplete_list(retval) {
    if (retval instanceof client.CallbackError)
      return onerror(retval);

    client.tokens = retval.data.tokenList;
    client.refreshTokens(client.tokens);

    token = retval.data.tokenList[slotId];
    if (!token)
      return alert("No token: " + slotId);

    if (token.state == 'stop:init') {
      // Initialization is done, reset the SO pin.
      $('.status.token-init').attr('status', 'green');
      $('.status.token-so').attr('status', 'progress');
      client.invokePolicyCallback('setSoPin', { slotId: token.slotId },
                                  onerror);
    } else if (token.state == 'stop:so-pin') {
      // SO pin is set, set the user pin.
      $('.status.token-so').attr('status', 'green');
      $('.status.token-user').attr('status', 'progress');
      client.invokePolicyCallback('setUserPin', { slotId: token.slotId },
                                  onerror);
    } else if (token.state == 'stop:ready') {
      // User pin is set, all done.
      $('.status.token-user').attr('status', 'green');
      client.showSuccess('The PKCS#11 token has been successfully ' +
                         'initialized. You may now install certificates.',
                         'Token Initialized');
      client.onPkcs11Ready();
      return;
    } else if (token.state == 'stop:error') {
      // If the token failed to initialize, it might be left in a broken
      // state.  This can happen if the hardware times out.  We ask entd
      // to restart, because it should be able to detect the broken token
      // and delete it.
      client.invokePolicyCallback("restart");
      client.showTokenDetails(token, { okCallback: client.reload });
      return;
    }

    setTimeout(function () {
        client.invokePolicyCallback('listTokens', null,
                                    oncomplete_list);
      }, 1000);
  };

  if (!force && token.state == 'stop:ready') {
    client.showQuery('Re-initializing this token will remove all keys ' +
                     'and certificates from the device.  Would you like ' +
                     'to continue?', 'Re-Initialize?',
                     { okCallback: function () {
                         client.initToken(token, true);
                     }});
    return;
  }

  client.showTokenProgress(token);
  $('.status.token-init').attr('status', 'progress');
  client.invokePolicyCallback('initToken', { slotId: token.slotId },
                              onerror);

  // This needs to happen on a timeout, or sometimes the listTokens returns
  // before the initToken.
  setTimeout(function () {
    client.invokePolicyCallback('listTokens', null, oncomplete_list);
  }, 1000);
}

/**
 * Invoked when the 'Install' (sometimes shown as 'Reinstall') button is
 * clicked.
 *
 * @param {string} id The certificate id for the certificate whose button was
 *   clicked.
 */
client.onCertInstall_ =
function onCertInstall_(cert) {
  var tokenOk = false;

  for (var i = 0; i < client.tokens.length; ++i) {
    if (client.tokens[i].state == "stop:ready")
      tokenOk = true;
  }

  if (!tokenOk) {
    client.showAlert("Please initialize your token first");
    return;
  }

  if (cert.userVariables) {
    client.showCertQuery(cert);
  } else {
    client.installCert(cert);
  }
};

/**
 * Called when a user clicks on the 'Initialize' button on a token.
 */
client.onTokenClick_ =
function onTokenClick_(token) {
  client.initToken(token);
}

/**
 * Called when a user clicks on the 'Ok' button in an alert dialog.
 */
client.onAlertOk_ =
function onAlertOk() {
  client.hideModal(client.modalContext.okCallback);
}

/**
 * Called when a user clicks on the 'Cancel' button in an alert dialog.
 */
client.onAlertCancel_ =
function onAlertCancel() {
  client.hideModal(client.modalContext.cancelCallback);
}

client.isModalVisible =
function isModalVisible() {
  return $('#modal-shade').css('display') == 'inherit';
}

/**
 * Common code for showing different kinds of modal alerts.
 *
 * This animates the dialog on screen.  If you want to do something after the
 * animation completes, use the callback parameter.
 *
 * Don't call this directly.  Instead use client.showAlert(), showSuccess(),
 * showError(), showQuery(), or invent your own.
 *
 * @param {string} dialogQuery A jquery path to the dialog box to be shown.
 *   The element identified by this query should be a direct child of
 *   the #modal-shade element.
 * @param {function} callback The function to invoke when the dialog is shown.
 */
client.showModal_ =
function showModal_(dialogQuery, callback) {
  var container = $('#modal-shade');
  var dialog = $(dialogQuery, container)[0];

  if (!dialog)
    throw new Error('Unknown modal dialog: ' + dialogQuery);

  container.children().each(function(index, element) {
      $(element).css('display', (element == dialog ? 'inherit' : 'none'));
    });

  container.css('display', 'inherit');

  setTimeout(function () {
      container.css('top', '0%');
      var firstInput = $('input', dialog)[0];
      if (firstInput)
        firstInput.focus();

      if (typeof callback == 'function')
        callback();
    }, 1);
}

/**
 * Called when a user clicks the "Details" link in a modal alert.
 */
client.toggleDetails =
function toggleDetails() {
  var details = $('textarea.dialog-details')[0];
  if ($(details).css('display') == 'none') {
    $('a.dialog-details').text('Hide Details');
    $('textarea.dialog-details').css('display', 'inherit' );
    setTimeout(function () {
        $('textarea.dialog-details').css('height', '7em');
      }, 1);
  } else {
    $('a.dialog-details').text('Show Details');
    $('textarea.dialog-details').css('height', '0em' );
    setTimeout(function () {
        $('textarea.dialog-details').css('display', 'none');
      }, 250);
  }
}

/**
 * Hide any modal dialog box.
 *
 * This animates the dialog box off screen, rather than instantly hiding the
 * dialog.  If you want to do something after the dialog is hidden (like
 * display another dialog box) then you should make use of the callback
 * parameter.
 *
 * @param {function} callback The function to invoke once the dialog box is
 *   hidden.
 */
client.hideModal =
function hideModal(callback) {
  client.modalContext = null;

  var container = $('#modal-shade');

  container.css('left', '-100%');

  // There is a transition associated with the change in 'left', this timeout
  // waits until that's done before resetting the dialog.
  setTimeout(function () {
      var transition = container.css('-webkit-transition');

      // Clear the transition so we can move the dialog back to the top of
      // the page without waiting for the transition.
      container.css('-webkit-transition', '');

      // Setting webkit-transition doesn't take effect in chrome until this
      // call completes, so we need this 1ms timeout.
      setTimeout(function () {
       container.css({ display: 'none', top: '-100%', 'left': '0%',
                       '-webkit-transition': transition });
       if (typeof callback == "function") {
         // We reset the transition, so we need another 1ms time to make it
         // take effect.
         setTimeout(callback, 1);
       }
      }, 1);
    }, 250);
};

/**
 * Show a modal "Alert" style dialog box.
 *
 * Graphic is a yellow "!", box has a single "Ok" button.
 *
 * This function is also used as a base for the other alert-like dialogs,
 * showSuccess(), showError(), and showQuery().
 *
 * @param {string} message The message to be displayed in the main part of
 *   the dialog box.  This will be displayed in a large font, so should be
 *   kept relatively short.
 * @param {string} title Optional.  The title of the alert.  Defaults to
 *   'Alert'.
 * @param {Object} options Optional.  May contain the following properties:
 *   - okCallback {function} The function to call if the user clicks "Ok".
 *   - cancelCallback {function} The function to call if the user clicks
 *       "Cancel". (Only valid for client.showQuery).
 *   - details {string} A string containing a more detailed message.  This
 *       will enable the "Details" link in the dialog, which will reveal
 *       the detail message in a read-only textarea.
 */
client.showAlert =
function showAlert(message, title, options) {
  if (client.isModalVisible()) {
    client.hideModal(function () { client.showAlert(message, title, options) });
    return;
  }

  client.modalContext = {
    okCallback: (options && options.okCallback || null),
    cancelCallback: (options && options.cancelCallback || null),
  };

  options = options || {};

  var alertDialog = $('#alert-dialog');
  client.showModal_(alertDialog, options.showCallback);

  $('.dialog-title', alertDialog).text(title || 'Alert');
  $('.dialog-message', alertDialog).text(message || 'NO MESSAGE PROVIDED');
  $('.dialog-ok', alertDialog).css('display', 'inherit');
  $('.dialog-cancel', alertDialog).css('display', 'none');
  $('.dialog-graphic', alertDialog).text('!').attr('status', '');

  if (options.details) {
    $('a.dialog-details', alertDialog).
      css('display', 'inherit').
      text('Show Details');
  } else {
    $('a.dialog-details', alertDialog).css('display', 'none');
  }

  $('textarea.dialog-details', alertDialog).
    css({ display: 'none', height: '0em' }).
    text(options.details);
}

/**
 * Show a modal "Query" style dialog box.
 *
 * Graphic is a green "?", box has an "Ok" button and a "Cancel" button.
 */
client.showQuery =
function showQuery(message, title, options) {
  if (client.isModalVisible()) {
    client.hideModal(function () {
        client.showQuery(message, title, options)
    });
    return;
  }

  client.showAlert(message, title, options);

  $('#alert-dialog .dialog-graphic').
    html('?').
    attr('status', 'success');

  $('#alert-dialog .dialog-cancel').css('display', 'inherit');
}

/**
 * Show a modal "Success" style dialog box.
 *
 * Graphic is a green check mark, box has a single "Ok" button.
 */
client.showSuccess =
function showSuccess(message, title, options) {
  if (client.isModalVisible()) {
    client.hideModal(function () {
      client.showSuccess(message, title, options)
    });
    return;
  }

  client.showAlert(message, title, options);

  $('#alert-dialog .dialog-graphic').
    html('&#x2714;'). // unicode "heavy check"
    attr('status', 'success');
}

/**
 * Show a modal "Error" style dialog box.
 *
 * Graphic is a red "X", box has a single "Ok" button.
 */
client.showError =
function showError(message, title, options) {
  if (client.isModalVisible()) {
    client.hideModal(function () {
        client.showError(message, title, options)
    });
    return;
  }

  client.showAlert(message, title || 'Error', options);

  $('#alert-dialog .dialog-graphic').
    html('&#x2718;'). // unicode "heavy ballot x"
    attr('status', 'error');
}

/**
 * Show the details for a given token in a modal dialog box.
 *
 * Shows the token details in a modal Error, Success, or Alert box, depending
 * on the state of the token.
 */
client.showTokenDetails =
function showTokenDetails(token, options) {
  var options = options || {};

  options.details = '';
  if (token.log)
    options.details += token.log + '\n';

  options.details += 'current state: ' + token.state +
    '\nslotId: ' + token.slotId + '\nflags: ';

  for (var key in token.flags) {
    if (token.flags[key])
      options.details += '\n* ' + key;
  }

  if (token.state == 'stop:error') {
    var msg = client.getLastLogLine(token.log);
    if (!msg)
      msg = 'There was an error initializing your token.';

    client.showError(msg, 'Error', options);
    return;
  }

  if (token.state == 'stop:ready') {
    client.showSuccess('Token is initialized', 'Token Information', options);
    return;
  }

  client.showAlert('Token is not initialized: ' + token.state,
                   'Token Information', options);
}

/**
 * Shows the Token Progress dialog.
 */
client.showTokenProgress =
function showTokenProgress(token) {
  $('#token-status').find('.status').attr('status', 'pending');
  $('#token-desc').text(token.manufacturerID + ', ' + token.model);
  $('#token-slot').text(token.slotId);
  client.showModal_('#token-status');
}

/**
 * Show the details for a given certificate in a modal dialog box.
 *
 * Shows the certificate details in a modal Error, Success, or Alert box,
 * depending on the state of the certificate.
 */
client.showCertDetails =
function showCertDetails(cert) {
  var options = { details: '' };
  if (cert.log)
    options.details += cert.log + '\n';

  options.details += 'current state: ' + cert.state;

  if (cert.state == 'stop:error') {
    var msg = client.getLastLogLine(cert.log);
    if (!msg)
      msg = 'There was an error installing your certificate';
    client.showError(msg, 'Error', options);
    return;
  }

  if (cert.state == 'stop:ready') {
    client.showSuccess('Certificate is installed', 'Certificate Information',
                       options);
    return;
  }

  client.showAlert('Certificate is not installed',
                   'Certificate Information', options);
}

/**
 * Shows the Certificate Progress dialog.
 */
client.showCertProgress =
function showCertProgress(cert) {
  $('#cert-status').find('.status').attr('status', 'pending');
  $('#cert-status-label').text(cert.label);
  client.showModal_('#cert-status');
}

/**
 * Show the modal dialog box used to collect user variables.
 *
 * @param {Object} cert The certificate object that should be associated with
 *  the modal dialog.
 */
client.showCertQuery =
function showCertQuery(cert) {
  client.modalContext = { cert: cert };

  $('#user-vars').empty();

  var firstInput;

  for (var key in cert.userVariables) {
    var uservar = cert.userVariables[key];

    var html = util.replaceVars(
        '<li>%(label) <input name="%(varname)" id="uservar:%(varname)" ' +
        'type="%(type)">',
        { label: uservar.label || key,
          varname: key,
          type: (uservar.type == 'password' ? 'password' : 'text')
        });

    $('#user-vars').append(html);
  }

  $('#cert-query-label').text(cert.label);

  client.showModal_('#cert-query');
};

/**
 * Called when the 'Submit' button is clicked on the cert dialog.
 */
client.onCertSubmit_ =
function onCertSubmit() {
  var cert = client.modalContext.cert;

  var variables = {};
  var valid = true;

  for (var key in cert.userVariables) {
    var input = document.getElementById('uservar:' + key);
    if (!input.value) {
      input.setAttribute('class', 'invalid');
      valid = false;
    } else {
      input.setAttribute('class', '');
      variables[key] = input.value;
    }
  }

  if (!valid)
    return;

  client.hideModal(function () { client.installCert(cert, variables) });
};

/**
 * Called when the 'Cancel' button is clicked on the cert dialog.
 */
client.onCertCancel_ =
function onModalCancel() {
  client.hideModal();
};

/**
 * Clear the token list UI and repopulate it.
 *
 * @param {Array} tokens The list of known tokens.
 */
client.resetTokens =
function resetTokens(tokens) {
  client.tokens = tokens;

  $('#token-list').empty();
  client.refreshTokens(tokens);
};

/**
 * Synchronize the existing token list UI with the known list of tokens.
 *
 * @param {Array} tokens The list of known tokens.
 */
client.refreshTokens =
function refreshTokens(tokens) {
  for (var i = 0; i < tokens.length; ++i) {
    var rv = $('#token-' + tokens[i].slotId);
    if (rv[0]) {
      client.refreshToken(rv[0], tokens[i]);
    } else {
      client.renderToken(tokens[i]);
    }
  }
};

/**
 * Create UI for a given token.
 *
 * @param {Object} token The target token.
 */
client.renderToken =
function renderToken(token) {
  var li = document.createElement('li');
  li.className = 'token';
  li.setAttribute('id', 'token-' + token.slotId);

  $(li).html(
      '<table width="100%">' +
      '<tr><td><span class="desc"></span> (<span class="label"></span>)</td>' +
      '<td rowspan="2" width="1%"><button class="init-button">Initialize' +
      '</button></td></tr><tr><td class="status"></td></tr></table>');

  $(li).find('button').click(function () {
      client.onTokenClick_(client.tokens[token.slotId]);
  });

  $(li).find('.status').click(function () {
      client.showTokenDetails(client.tokens[token.slotId]);
  });

  client.refreshToken(li, token);

  $('#token-list').append(li);
}

/**
 * Refresh UI for a given token.
 *
 * @param {Object} token The target token.
 */
client.refreshToken =
function refreshToken(li, token) {
  var status;
  if (token.state == 'stop:ready') {
    color = 'green';
    status = 'Initialized.';
  } else if (!token.flags.TOKEN_INITIALIZED) {
    color = 'red';
    status = 'Not initialized.';
  } else if (token.flags.SO_PIN_TO_BE_CHANGED ||
             token.flags.USER_PIN_TO_BE_CHANGED) {
    color = 'red';
    status = 'PINs not initialized.';
  } else {
    color = 'red';
    status = 'Token error';
  }

  $('.desc', li).text(token.manufacturerID + ', ' + token.model);
  $('.label', li).text(token.label || 'Unlabeled');
  $('.status', li).attr('status', color);
  $('.status', li).text(status);
  if (client.cryptohome_init_pkcs11) {
    // If automatic initialization is enabled, do not give the user
    // the option to initialize.
    $('.init-button', li).css('display', 'none');
  } else {
    $('button', li).text(color == 'red' ? 'Initialize' : 'Reinitialize');
  }
}

/**
 * Create the UI for a list of certificates.
 *
 * This will destroy any existing cert UI before proceeding.
 *
 * @param {Array} certs The list of known certificates.
 */
client.resetCertificates =
function resetCertificates(certs) {
  client.certificates = {};
  for (var key in certs) {
    // The certificates coming from the server have keys that don't match
    // their ids (key != cert.id), because the server is being careful not
    // to let keys and default object properties collide.  We don't care much
    // about the collisions here, and having key == cert.id is useful to us.
    var cert = certs[key];
    client.certificates[cert.id] = cert;
  }

  var list = document.getElementById('cert-list');
  while (list.firstChild)
    list.removeChild(list.firstChild);

  client.refreshCertificates(certs);
};

/**
 * Refresh the UI for a list of certificates.
 *
 * Creates the UI if it doesn't exist.
 *
 * @param {Array} certs The list of known certificates.
 */
client.refreshCertificates =
function refreshCertificates(certs) {
  for (var key in certs) {
    var cert = certs[key];
    var li = document.getElementById('cert:' + cert.id);
    if (li)
      client.refreshCertificate(li, cert);
    else
      client.renderCertificate(cert);
  }
};

/**
 * Refresh the UI for a given certificate.
 *
 * @param {DOMListItem} li The 'li' element containing the certificate UI.
 * @param {Object} cert The object representing the current state of the
 *    certificate.
 */
client.refreshCertificate =
function refreshCertificate(li, cert) {
  var ok = false;
  var status;
  if (cert.state == 'stop:ready') {
    ok = true;
    status = 'Installed.';
  } else if (cert.state == 'stop:error') {
    status = 'Error installing certificate.';
  } else {
    status = 'Not installed.';
  }

  $('.label', li).text(cert.label);
  $('.status', li).text(status).
    attr('status', ok ? 'green' : 'red');
  $('button', li).text(ok ? 'Reinstall' : 'Install');

  return;
};

/**
 * Create the UI for a given certificate.
 *
 * This code intentionally takes the long way around, building each
 * element by hand, rather than using innerHTML, in order to avoid some
 * potential content injection expoits.
 *
 * @param {Object} cert The object representing the current state of the
 *    certificate.
 */
client.renderCertificate =
function renderCertificate(cert) {
  // The placeholder text ('<label>', etc) gets replaced later by
  // refreshCertificate().

  var li = document.createElement('li');
  li.setAttribute('class', 'cert');
  li.setAttribute('id', 'cert:' + cert.id);

  li.innerHTML = '<table width="100%">' +
  '<tr><td class="label" width="100%"></td>' +
  '    <td rowspan="2" valign="center" align="right" width="1%"><button></td>' +
  '</tr><tr><td class="status" width="100%"></td></tr>';

  $('button', li).click(function() {
      client.onCertInstall_(client.certificates[cert.id])
  });

  $(li).find('.status').click(function () {
      client.showCertDetails(client.certificates[cert.id]);
  });

  $('#cert-list').append(li);
  client.refreshCertificate(li, cert);
};

/**
 * Invoke a remote policy callback function.
 *
 * When the callback completes, the oncomplete function will be called with
 * a single parameter.  The parameter will be an instance of
 * client.CallbackSuccess or client.CallbackError, depending on the result
 * of the callback.  The 'data' property of that object will contain more
 * details.
 *
 * @param {string} name The name of the callback to invoke.
 * @param {Object} arg The argument object for the callback.
 * @param {function(object)} oncomplete A function to invoke when the callback
 *     is complete.
 */
client.invokePolicyCallback =
function invokePolicyCallback(name, arg, oncomplete) {
  var xhr = new XMLHttpRequest();

  xhr.onreadystatechange = function () {
    if (this.readyState != 4)
      return;

    if (this.status == 200) {
      console.log(this.responseText);
      var retval = JSON.parse(this.responseText);
      var param;

      if (typeof retval == 'object') {
        if (retval.status == 'success') {
          param = new client.CallbackSuccess(name, arg, retval);
        } else if (retval.status == 'error') {
          param = new client.CallbackError(name, arg, retval);
        }
      }

      if (!param) {
        param = new client.CallbackError
            (name, arg,
             'Unexpected response to callback: ' + name + ': ' +
             JSON.stringify(retval));
      }
    } else {
      param = new client.CallbackError(
          name, arg,
          { msg: 'Error invoking callback: ' + name + ': http status: ' +
            this.status } );
    }

    param.xhrStatus = xhr.status;
    if (typeof oncomplete == "function")
      oncomplete(param);
  };

  xhr.open('POST', 'http://127.0.0.1:' + client.policyCallbackPort +
           '/dispatch');
  xhr.setRequestHeader('X-Entd-Request',
                       client.manifest.requestHeaderValue || 'magic');
  xhr.setRequestHeader('X-Entd-Session-Id', client.session_id.session_id);
  xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
  xhr.send(JSON.stringify({'function': name, 'argument': arg}));
};

/**
 * client.CallbackSuccess constructor.
 *
 * An instance of this class holds the return value of a successful policy
 * callback.  The data property of this object will contain the return
 * value of the callback.
 *
 * @param {string} name The name of the callback that returned this data.
 * @param {Object} arg The argument object originally passed to the callback.
 * @param {Object} data The data returned by the callback.
 */
client.CallbackSuccess =
function CallbackSuccess(name, arg, data) {
  this.init_(name, arg, data)
};

client.CallbackSuccess.prototype.init_ =
function init_(name, arg, rv) {
  this.name_ = name;
  this.arg_ = arg;

  this.toString = function toString() {
    return '[' + this.constructor.name + ': ' + JSON.stringify(this) + ']';
  };

  for (var key in rv)
      this[key] = rv[key];
};

/**
 * client.CallbackError constructor.
 *
 * An instance of this class holds the return value of an unsuccessful policy
 * callback.  The data property of this object will contain the return
 * value of the callback.
 *
 * @param {string} name The name of the callback that returned this data.
 * @param {Object} arg The argument object originally passed to the callback.
 * @param {Object} data The data returned by the callback.
 */
client.CallbackError =
function CallbackError(name, arg, data) {
  this.init_(name, arg, data);
};

client.CallbackError.prototype.init_ = client.CallbackSuccess.prototype.init_;
