diff --git a/package.json b/package.json index 89d74c15..a1ac62ed 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "build:dev": "node .electron-vue/build.js", "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js", "dev": "node .electron-vue/dev-runner.js", - "e2e": "npm run pack && mocha --timeout 10000 test/e2e", + "e2e": "npm run pack && cross-env MARKTEXT_EXIT_ON_ERROR=1 mocha --timeout 10000 test/e2e", "lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src test", "lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter --fix src test", "pack": "npm run pack:main && npm run pack:renderer", diff --git a/src/main/exceptionHandler.js b/src/main/exceptionHandler.js index f72b6d24..c7df4f60 100644 --- a/src/main/exceptionHandler.js +++ b/src/main/exceptionHandler.js @@ -17,12 +17,12 @@ const ERROR_MSG_RENDERER = 'An unexpected error occurred in the renderer process // main process error handler process.on('uncaughtException', error => { - handleError(ERROR_MSG_MAIN, error) + handleError(ERROR_MSG_MAIN, error, 'main') }) // renderer process error handler ipcMain.on('AGANI::handle-renderer-error', (e, error) => { - handleError(ERROR_MSG_RENDERER, error) + handleError(ERROR_MSG_RENDERER, error, 'renderer') }) // start crashReporter to save core dumps to temporary folder @@ -44,16 +44,19 @@ const bundleException = (error, type) => { } } -const handleError = (title, error) => { +const handleError = (title, error, type) => { const { message, stack } = error // log error - const info = bundleException(error, 'renderer') + const info = bundleException(error, type) console.error(info) log(JSON.stringify(info, null, 2)) if (EXIT_ON_ERROR) { + console.log('Mark Text was terminated due to an unexpected error (MARKTEXT_EXIT_ON_ERROR variable was set)!') process.exit(1) + // eslint, don't lie to me, the return statement is important! + return // eslint-disable-line no-unreachable } else if (!SHOW_ERROR_DIALOG) { return } diff --git a/src/renderer/main.js b/src/renderer/main.js index 9b43a11d..95cb0769 100644 --- a/src/renderer/main.js +++ b/src/renderer/main.js @@ -1,6 +1,6 @@ import Vue from 'vue' import axios from 'axios' -import { ipcRenderer } from 'electron' +import { crashReporter, ipcRenderer } from 'electron' import lang from 'element-ui/lib/locale/lang/en' import locale from 'element-ui/lib/locale' import App from './app' @@ -20,6 +20,14 @@ sourceMapSupport.install({ hookRequire: false }) +// Start crash reporter to save core dumps for the renderer process +crashReporter.start({ + companyName: 'marktext', + productName: 'marktext', + submitURL: 'http://0.0.0.0/', + uploadToServer: false +}) + // Register renderer error handler window.addEventListener('error', event => { const { message, name, stack } = event.error diff --git a/test/e2e/data/xss.md b/test/e2e/data/xss.md new file mode 100644 index 00000000..b5b75417 --- /dev/null +++ b/test/e2e/data/xss.md @@ -0,0 +1,24 @@ +# XSS Tests + + + + + + + + + + + + + + + + + + + + + diff --git a/test/e2e/specs/Launch.spec.js b/test/e2e/specs/Launch.spec.js index 64c871aa..7d08a980 100644 --- a/test/e2e/specs/Launch.spec.js +++ b/test/e2e/specs/Launch.spec.js @@ -7,14 +7,10 @@ describe('Launch', function () { it('shows the proper application title', function () { return this.app.client.getTitle() .then(title => { - if (process.platform === 'darwin') { - const result = /^Mark Text|Untitled-1$/.test(title) - if (!result) { - console.error(`AssertionError: expected '${title}' to equal 'Mark Text' or 'Untitled-1'`) - expect(false).to.equal(true) - } - } else { - expect(title).to.equal('Untitled-1') + const result = /^Mark Text|Untitled-1$/.test(title) + if (!result) { + console.error(`AssertionError: expected '${title}' to equal 'Mark Text' or 'Untitled-1'`) + expect(false).to.equal(true) } }) }) diff --git a/test/e2e/specs/xss.spec.js b/test/e2e/specs/xss.spec.js new file mode 100644 index 00000000..be438a02 --- /dev/null +++ b/test/e2e/specs/xss.spec.js @@ -0,0 +1,21 @@ +import utils from '../utils' + +describe('Cross-site Scripting Test', function () { + beforeEach(utils.beforeXss) + afterEach(utils.afterEach) + + it('Load malicious document', function (done) { + setTimeout(() => { + // If a test fails, an exception is thrown. + + // TODO: The process is not terminated if a test fails because the connection to Electron is lost (spectron bug?). + // I think thats not a problem as long as you kill the process. + // Message: + // chrome not reachable + // Error: Request timed out after the element was still found on the page. + // at execute(, "require") - api.js:63:26 + + done() + }, 3000) + }) +}) diff --git a/test/e2e/utils.js b/test/e2e/utils.js index c13253f9..bfe9b935 100644 --- a/test/e2e/utils.js +++ b/test/e2e/utils.js @@ -18,5 +18,15 @@ export default { waitTimeout: 20000 }) return this.app.start() + }, + beforeXss () { + this.timeout(20000) + this.app = new Application({ + path: electron, + args: ['dist/electron/main.js', 'test/e2e/data/xss.md'], + startTimeout: 20000, + waitTimeout: 20000 + }) + return this.app.start() } }