diff --git a/README.md b/README.md index 5aa8c8de..c1d4079a 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,13 @@ Configuration will be saved into Electron's userData directory: * `~/Library/Application Support/electron-mattermost` on OS X * `~/.config/electron-mattermost` on Linux +### Proxy +You can resolve the proxy by following command line options. +*Note: Authorization is not supported.* + +* `--proxy-server=:` +* `--proxy-pac-url=` + ## Testing and Development Node.js is required to test this app. diff --git a/src/browser/index.jsx b/src/browser/index.jsx index 00c7bb83..c6ecf2b4 100644 --- a/src/browser/index.jsx +++ b/src/browser/index.jsx @@ -221,6 +221,10 @@ var MattermostView = React.createClass({ webview.addEventListener('did-fail-load', function(e) { console.log(thisObj.props.name, 'webview did-fail-load', e); + if (e.errorCode === -3) { // An operation was aborted (due to user action). + return; + } + // should use permanent way to indicate var did_fail_load_notification = new Notification(`Failed to load "${thisObj.props.name}"`, { body: `ErrorCode: ${e.errorCode}`, diff --git a/src/main.js b/src/main.js index f2a1b0f1..65763dc0 100644 --- a/src/main.js +++ b/src/main.js @@ -10,6 +10,7 @@ const fs = require('fs'); const path = require('path'); var settings = require('./common/settings'); +var certificateStore = require('./main/certificateStore').load(path.resolve(app.getPath('userData'), 'certificate.json')); var appMenu = require('./main/menus/app'); var argv = require('yargs').argv; @@ -80,6 +81,38 @@ app.on('before-quit', function() { willAppQuit = true; }); +app.on('certificate-error', function(event, webContents, url, error, certificate, callback) { + if (certificateStore.isTrusted(url, certificate)) { + event.preventDefault(); + callback(true); + } + else { + var detail = `URL: ${url}\nError: ${error}`; + if (certificateStore.isExisting(url)) { + detail = `Certificate is different from previous one.\n\n` + detail; + } + + electron.dialog.showMessageBox(mainWindow, { + title: 'Certificate error', + message: `Do you trust certificate from "${certificate.issuerName}"?`, + detail: detail, + type: 'warning', + buttons: [ + 'Yes', + 'No' + ], + cancelId: 1 + }, function(response) { + if (response === 0) { + certificateStore.add(url, certificate); + certificateStore.save(); + webContents.loadURL(url); + } + }); + callback(false); + } +}); + // This method will be called when Electron has finished // initialization and is ready to create browser windows. app.on('ready', function() { diff --git a/src/main/certificateStore.js b/src/main/certificateStore.js new file mode 100644 index 00000000..da091ac6 --- /dev/null +++ b/src/main/certificateStore.js @@ -0,0 +1,62 @@ +'use strict'; + +const fs = require('fs'); +const url = require('url'); + +function comparableCertificate(certificate) { + return { + data: certificate.data.toString(), + issuerName: certificate.issuerName + }; +} + +function areEqual(certificate0, certificate1) { + if (certificate0.data !== certificate1.data) { + return false; + } + if (certificate0.issuerName !== certificate1.issuerName) { + return false; + } + return true; +} + +function getHost(targetURL) { + return url.parse(targetURL).host; +} + +var CertificateStore = function(storeFile) { + this.storeFile = storeFile + try { + this.data = JSON.parse(fs.readFileSync(storeFile, 'utf-8')); + } + catch (e) { + console.log(e); + this.data = {}; + } +}; + +CertificateStore.prototype.save = function() { + fs.writeFileSync(this.storeFile, JSON.stringify(this.data, null, ' ')); +}; + +CertificateStore.prototype.add = function(targetURL, certificate) { + this.data[getHost(targetURL)] = comparableCertificate(certificate); +}; + +CertificateStore.prototype.isExisting = function(targetURL) { + return this.data.hasOwnProperty(getHost(targetURL)); +}; + +CertificateStore.prototype.isTrusted = function(targetURL, certificate) { + var host = getHost(targetURL); + if (!this.isExisting(targetURL)) { + return false; + } + return areEqual(this.data[host], comparableCertificate(certificate)); +}; + +module.exports = { + load: function(storeFile) { + return new CertificateStore(storeFile); + } +};