/**
   * Report an error to the host application. These errors are unrecoverable (i.e. the main resource
   * is unavailable). The errorCode parameter corresponds to one of the ERROR_* constants.
   *
   * @param errorCode The error code corresponding to an ERROR_* value.
   * @param description A String describing the error.
   * @param failingUrl The url that failed to load.
   */
  public void onReceivedError(
      final int errorCode, final String description, final String failingUrl) {
    final CordovaActivity me = this;

    // If errorUrl specified, then load it
    final String errorUrl = preferences.getString("errorUrl", null);
    if ((errorUrl != null)
        && (errorUrl.startsWith("file://") || whitelist.isUrlWhiteListed(errorUrl))
        && (!failingUrl.equals(errorUrl))) {

      // Load URL on UI thread
      me.runOnUiThread(
          new Runnable() {
            public void run() {
              // Stop "app loading" spinner if showing
              me.spinnerStop();
              me.appView.showWebPage(errorUrl, false, true, null);
            }
          });
    }
    // If not, then display error dialog
    else {
      final boolean exit = !(errorCode == WebViewClient.ERROR_HOST_LOOKUP);
      me.runOnUiThread(
          new Runnable() {
            public void run() {
              if (exit) {
                me.appView.setVisibility(View.GONE);
                me.displayError(
                    "Application Error", description + " (" + failingUrl + ")", "OK", exit);
              }
            }
          });
    }
  }
 /** Display an error dialog and optionally exit application. */
 public void displayError(
     final String title, final String message, final String button, final boolean exit) {
   final CordovaActivity me = this;
   me.runOnUiThread(
       new Runnable() {
         public void run() {
           try {
             AlertDialog.Builder dlg = new AlertDialog.Builder(me);
             dlg.setMessage(message);
             dlg.setTitle(title);
             dlg.setCancelable(false);
             dlg.setPositiveButton(
                 button,
                 new AlertDialog.OnClickListener() {
                   public void onClick(DialogInterface dialog, int which) {
                     dialog.dismiss();
                     if (exit) {
                       me.endActivity();
                     }
                   }
                 });
             dlg.create();
             dlg.show();
           } catch (Exception e) {
             finish();
           }
         }
       });
 }