Electronをブラウザとして使う場合の証明書エラーとBasic認証の処理

ElectronアプリのUIは基本的にローカルのHTMLファイルを利用して作るので、パスさえ間違えなければ間違いなくHTMLをロードして表示できます。 しかし場合によっては<webview>を使って簡易ブラウザ/アプリ内ブラウザのようなものを実装することもあるかと思います。 このときに少しハマったところがあったのでメモとして残しておきます。

SSL/TLS証明書エラー

httpsを使う時にSSL/TLS証明書の検証でエラーがある場合*1、Electronは何もせず通信失敗となります。 この時appモジュールのcertificate-errorイベントが発生するので、event.preventDefault()で元の動作を止め、callback(true)を呼び出すことでエラーを無視して通信を続行することができます。 問答無用でエラーを無視してもいいですが、ユーザーに確認させたいのであれば以下のようにcallbackを非同期で呼び出すことができます。

app.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
  event.preventDefault();
  electron.dialog.showMessageBox(mainWindow, {
    title: 'Certificate error',
    message: `Do you trust certificate from "${certificate.issuerName}"?`,
    detail: `URL: ${url}\nError: ${error}`,
    type: 'warning',
    buttons: [
      'Yes',
      'No'
    ],
    cancelId: 1
  }, function(response) {
    if (response === 0) {
      callback(true);
    }
    else {
      callback(false);
    }
  });
});

Basic認証

こちらもやはり、そのままではElectronは何もしてくれません。 loginイベントが発火するので、これを使います。

// Quoted from electron.atom.io
app.on('login', function(event, webContents, request, authInfo, callback) {
  event.preventDefault();
  callback('username', 'secret');
});

こちらはかなり厄介です。 証明書エラーの時のようにユーザー名とパスワードの入力を促すダイアログを出したいところですが、Electronはテキスト入力をGUIで受け付けるためのAPIを持っていないからです。 ブラウザ側で動作するRendererプロセスであってもwindow.promptさえサポートされていません。*2

つまり、ユーザー名・パスワードの入力ダイアログはなんとかして自力で用意しなければなりません。 自分の場合はRenderer側でBootstrapを使っているので、そのダイアログを利用しようかと思っています。 あるいは入力ダイアログ専用のBrowserWindowを作成してしまうのも手かもしれません。

*1:通常のブラウザであれば警告表示になる場面、例えば自己署名証明書

*2:スレッドをブロックするからなんだとか。必要ならHTMLで入力場所作れるから十分でしょ?みたいな雰囲気を感じる https://github.com/atom/electron/issues/472