diff --git a/Gruntfile.js b/Gruntfile.js index acbd04f..243c1b8 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -137,7 +137,8 @@ module.exports = function(grunt) { 'pgpbuilder/node_modules/mailbuild/node_modules/punycode/punycode.min.js', 'pgpmailer/src/*.js', 'pgpmailer/node_modules/smtpclient/src/*.js', - 'pgpmailer/node_modules/smtpclient/node_modules/stringencoding/dist/stringencoding.js' + 'pgpmailer/node_modules/smtpclient/node_modules/stringencoding/dist/stringencoding.js', + 'axe/axe.js' ], dest: 'src/lib/' }, diff --git a/package.json b/package.json index 676c51e..e8bc8fd 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,12 @@ }, "dependencies": { "crypto-lib": "https://github.com/whiteout-io/crypto-lib/tarball/v0.2.0", - "imap-client": "https://github.com/whiteout-io/imap-client/tarball/v0.3.3", + "imap-client": "https://github.com/whiteout-io/imap-client/tarball/dev/WO-420", "mailreader": "https://github.com/whiteout-io/mailreader/tarball/v0.3.3", - "pgpmailer": "https://github.com/whiteout-io/pgpmailer/tarball/v0.3.4", + "pgpmailer": "https://github.com/whiteout-io/pgpmailer/tarball/dev/WO-420", "pgpbuilder": "https://github.com/whiteout-io/pgpbuilder/tarball/v0.3.4", - "requirejs": "2.1.10" + "requirejs": "2.1.10", + "axe": "https://github.com/whiteout-io/axe/tarball/v0.0.2" }, "devDependencies": { "angularjs": "https://github.com/angular/angular.js/tarball/v1.2.8", diff --git a/src/js/app-config.js b/src/js/app-config.js index b0b7ac9..5de1335 100644 --- a/src/js/app-config.js +++ b/src/js/app-config.js @@ -77,7 +77,11 @@ define(function(require) { updatePublicKeyMsgNewKey: '{0} updated his key and may not be able to read encrypted messages sent with his old key. Update the key?', updatePublicKeyMsgRemovedKey: '{0} revoked his key and may no longer be able to read encrypted messages. Remove the key?', updatePublicKeyPosBtn: 'Yes', - updatePublicKeyNegBtn: 'No' + updatePublicKeyNegBtn: 'No', + bugReportTitle: 'Report a bug', + bugReportSubject: '[Bug] I want to report a bug', + bugReportBody: 'Steps to reproduce\n1. \n2. \n3. \n\nWhat happens?\n\n\nWhat do you expect to happen instead?\n\n\n\n== PLEASE DONT PUT ANY KEYS HERE! ==\n\n\n## Log\n\nBelow is the log. It includes your interactions with your email provider in an anonymized way from the point where you started the app for the last time. Any information provided by you will be used for the porpose of locating and fixing the bug you reported. It will be deleted subsequently. However, you can edit this log and/or remove log data in the event that something would show up.\n\n', + supportAddress: 'mail.support@whiteout.io' }; return app; diff --git a/src/js/app-controller.js b/src/js/app-controller.js index 15f5ef5..07b4c08 100644 --- a/src/js/app-controller.js +++ b/src/js/app-controller.js @@ -13,6 +13,7 @@ define(function(require) { mailreader = require('mailreader'), ImapClient = require('imap-client'), Crypto = require('js/crypto/crypto'), + axe = require('axe'), RestDAO = require('js/dao/rest-dao'), EmailDAO = require('js/dao/email-dao'), appConfig = require('js/app-config'), @@ -35,16 +36,16 @@ define(function(require) { // are we running in a cordova app or in a browser environment? if (window.cordova) { // wait for 'deviceready' event to make sure plugins are loaded - console.log('Assuming Cordova environment...'); + axe.debug('Assuming Cordova environment...'); document.addEventListener("deviceready", onDeviceReady, false); } else { // No need to wait on events... just start the app - console.log('Assuming Browser environment...'); + axe.debug('Assuming Browser environment...'); onDeviceReady(); } function onDeviceReady() { - console.log('Starting app.'); + axe.debug('Starting app.'); self.buildModules(options); @@ -144,8 +145,7 @@ define(function(require) { auth: auth, tls: { ca: [credentials.sslCert] - }, - onError: console.error + } }; pgpMailer = new PgpMailer(smtpOptions, self._pgpbuilder); @@ -159,17 +159,17 @@ define(function(require) { }, callback); } - function onImapError(err) { - console.log('IMAP error.', err); - console.log('IMAP reconnecting...'); + function onImapError(error) { + axe.debug('IMAP error.' + (error.errMsg || error.message) + (error.stack ? ('\n' + error.stack) : '')); + axe.debug('IMAP reconnecting...'); // re-init client modules on error self.onConnect(function(err) { if (err) { - console.error('IMAP reconnect failed!', err); + axe.error('IMAP reconnect failed! ' + (err.errMsg || err.message) + (err.stack ? ('\n' + err.stack) : '')); return; } - console.log('IMAP reconnect attempt complete.'); + axe.debug('IMAP reconnect attempt complete.'); }); } }; @@ -181,16 +181,16 @@ define(function(require) { // check for update and restart chrome.runtime.onUpdateAvailable.addListener(function(details) { - console.log("Updating to version " + details.version); + axe.debug("Updating to version " + details.version); chrome.runtime.reload(); }); chrome.runtime.requestUpdateCheck(function(status) { if (status === "update_found") { - console.log("Update pending..."); + axe.debug("Update pending..."); } else if (status === "no_update") { - console.log("No update found."); + axe.debug("No update found."); } else if (status === "throttled") { - console.log("Checking updates too frequently."); + axe.debug("Checking updates too frequently."); } }); }; diff --git a/src/js/controller/write.js b/src/js/controller/write.js index 4b84054..8670aff 100644 --- a/src/js/controller/write.js +++ b/src/js/controller/write.js @@ -4,6 +4,7 @@ define(function(require) { var angular = require('angular'), _ = require('underscore'), appController = require('js/app-controller'), + axe = require('axe'), aes = require('js/crypto/aes-gcm'), util = require('js/crypto/util'), str = require('js/app-config').string, @@ -40,6 +41,12 @@ define(function(require) { $scope.verify($scope.to[0]); }, + reportBug: function() { + $scope.state.lightbox = 'write'; + resetFields(); + reportBug(); + $scope.verify($scope.to[0]); + }, close: function() { $scope.state.lightbox = undefined; } @@ -64,6 +71,50 @@ define(function(require) { $scope.attachments = []; } + function reportBug() { + var dump = ''; + var appender = { + log: function(level, date, component, log) { + // add a tag for the log level + if (level === axe.DEBUG) { + dump += '[DEBUG]'; + } else if (level === axe.INFO) { + dump += '[INFO]'; + } else if (level === axe.WARN) { + dump += '[WARN]'; + } else if (level === axe.ERROR) { + dump += '[ERROR]'; + } + + dump += '[' + date.toISOString() + ']'; + + // component is optional + if (component) { + dump += '[' + component + ']'; + } + + // log may be an error or a string + dump += ' ' + (log || '').toString(); + + // if an error it is, a stack trace it has. print it, we should. + if (log.stack) { + dump += ' . Stack: ' + log.stack; + } + + dump += '\n'; + } + }; + axe.dump(appender); + + $scope.to = [{ + address: str.supportAddress + }]; + $scope.writerTitle = str.bugReportTitle; + $scope.subject = str.bugReportSubject; + $scope.body = str.bugReportBody + dump; + + } + function fillFields(re, replyAll, forward) { var replyTo, from, sentDate, body; diff --git a/src/js/crypto/crypto.js b/src/js/crypto/crypto.js index 7150966..7b09f53 100644 --- a/src/js/crypto/crypto.js +++ b/src/js/crypto/crypto.js @@ -7,7 +7,8 @@ define(function(require) { var aes = require('js/crypto/aes-gcm'), pbkdf2 = require('js/crypto/pbkdf2'), - config = require('js/app-config').config; + config = require('js/app-config').config, + axe = require('axe'); var PBKDF2_WORKER = '/crypto/pbkdf2-worker.js'; @@ -91,8 +92,8 @@ define(function(require) { options.callback(null, e.data); }; worker.onerror = function(e) { - // show error message in console - console.error('Error handling web worker: Line ' + e.lineno + ' in ' + e.filename + ': ' + e.message); + // show error message in logger + axe.error('Error handling web worker: Line ' + e.lineno + ' in ' + e.filename + ': ' + e.message); // return error options.callback({ errMsg: (e.message) ? e.message : e diff --git a/src/js/util/error.js b/src/js/util/error.js index de4b80e..699fc44 100644 --- a/src/js/util/error.js +++ b/src/js/util/error.js @@ -1,6 +1,8 @@ -define(function() { +define(function(require) { 'use strict'; + var axe = require('axe'); + var er = {}; er.attachHandler = function(scope) { scope.onError = function(options) { @@ -9,11 +11,7 @@ define(function() { return; } - if (options.stack) { - console.error(options.stack); - } else { - console.error(options); - } + axe.error((options.errMsg || options.message) + (options.stack ? ('\n' + options.stack) : '')); scope.state.dialog = { open: true, diff --git a/src/tpl/navigation.html b/src/tpl/navigation.html index d83d54a..8cc64e2 100644 --- a/src/tpl/navigation.html +++ b/src/tpl/navigation.html @@ -18,6 +18,7 @@
  • Account
  • Contacts
  • Key sync (experimental)
  • +
  • Report a bug
  • About
  • diff --git a/test/integration/main.js b/test/integration/main.js index 0564c58..ccd3062 100644 --- a/test/integration/main.js +++ b/test/integration/main.js @@ -13,12 +13,14 @@ require(['src/require-config'], function() { }); // Start the main app logic. - require(['js/app-config'], function(app) { + require(['js/app-config', 'axe'], function(app, axe) { window.Worker = undefined; // disable web workers since mocha doesn't support them app.config.workerPath = '../../src/js'; //app.config.cloudUrl = 'http://localhost:8888'; + axe.removeAppender(axe.defaultAppender); + startTests(); }); }); diff --git a/test/unit/main.js b/test/unit/main.js index 44b541e..446fe13 100644 --- a/test/unit/main.js +++ b/test/unit/main.js @@ -16,9 +16,12 @@ require(['../../src/require-config'], function() { // Start the main app logic. - require(['js/app-config'], function(app) { + require(['js/app-config', 'axe'], function(app, axe) { app.config.workerPath = '../../src/js'; + // turn off logging in the test + axe.removeAppender(axe.defaultAppender); + startTests(); }); });