From 06e0ad25c851e721d1b160a5dc8de131e4ed2d6f Mon Sep 17 00:00:00 2001 From: NejcZdovc Date: Fri, 23 Feb 2018 16:00:32 +0100 Subject: [PATCH] Fixes backup keys export/import; improves print flow Resolves #13274 Resolves #7512 Resolves #7511 Resolves #11419 Auditors: Test Plan: --- app/browser/api/ledger.js | 67 ++++++++++++------- app/browser/reducers/ledgerReducer.js | 5 ++ app/browser/tabs.js | 5 ++ app/extensions/brave/about-printkeys.html | 21 ++++++ .../brave/locales/en-US/app.properties | 1 + app/renderer/about/ledger/printKeys.js | 63 +++++++++++++++++ js/about/entry.js | 3 + js/actions/appActions.js | 7 ++ js/constants/appConstants.js | 1 + js/constants/messages.js | 1 + js/lib/appUrlUtil.js | 1 + 11 files changed, 151 insertions(+), 24 deletions(-) create mode 100644 app/extensions/brave/about-printkeys.html create mode 100644 app/renderer/about/ledger/printKeys.js diff --git a/app/browser/api/ledger.js b/app/browser/api/ledger.js index 27e14967964..c60ab44a402 100644 --- a/app/browser/api/ledger.js +++ b/app/browser/api/ledger.js @@ -37,7 +37,7 @@ const config = require('../../../js/constants/buildConfig') const tabs = require('../../browser/tabs') const locale = require('../../locale') const getSetting = require('../../../js/settings').getSetting -const {fileUrl, getSourceAboutUrl, isSourceAboutUrl} = require('../../../js/lib/appUrlUtil') +const {getSourceAboutUrl, isSourceAboutUrl} = require('../../../js/lib/appUrlUtil') const urlParse = require('../../common/urlParse') const ruleSolver = require('../../extensions/brave/content/scripts/pageInformation') const request = require('../../../js/lib/request') @@ -48,6 +48,7 @@ const ledgerNotifications = require('./ledgerNotifications') const ledgerVideoCache = require('../../common/cache/ledgerVideoCache') const updater = require('../../updater') const promoCodeFirstRunStorage = require('../../promoCodeFirstRunStorage') +const appUrlUtil = require('../../../js/lib/appUrlUtil') // Caching let locationDefault = 'NOOP' @@ -250,7 +251,7 @@ const onBootStateFile = (state) => { } const promptForRecoveryKeyFile = () => { - const defaultRecoveryKeyFilePath = path.join(electron.app.getPath('userData'), '/brave_wallet_recovery.txt') + const defaultRecoveryKeyFilePath = path.join(electron.app.getPath('downloads'), '/brave_wallet_recovery.txt') if (process.env.SPECTRON) { // skip the dialog for tests console.log(`for test, trying to recover keys from path: ${defaultRecoveryKeyFilePath}`) @@ -264,7 +265,7 @@ const promptForRecoveryKeyFile = () => { extensions: [['txt']], includeAllFiles: false }, (files) => { - return (files && files.length ? files[0] : null) + appActions.onFileRecoveryKeys((files && files.length ? files[0] : null)) }) } } @@ -1049,37 +1050,54 @@ const backupKeys = (state, backupAction) => { ] const message = messageLines.join(os.EOL) - const filePath = path.join(electron.app.getPath('userData'), '/brave_wallet_recovery.txt') + const defaultFilePath = path.join(electron.app.getPath('downloads'), '/brave_wallet_recovery.txt') const fs = require('fs') - fs.writeFile(filePath, message, (err) => { - if (err) { - console.error(err) - } else { - tabs.create({url: fileUrl(filePath)}, (webContents) => { - if (backupAction === 'print') { - webContents.print({silent: false, printBackground: false}) - } else { - webContents.downloadURL(fileUrl(filePath), true) - } - }) + + if (backupAction === 'print') { + tabs.create({url: appUrlUtil.aboutUrls.get('about:printkeys')}) + return + } + + const dialog = electron.dialog + const BrowserWindow = electron.BrowserWindow + + dialog.showDialog(BrowserWindow.getFocusedWindow(), { + type: 'select-saveas-file', + defaultPath: defaultFilePath, + extensions: [['txt']], + includeAllFiles: false + }, (files) => { + const file = files && files.length ? files[0] : null + if (file) { + try { + fs.writeFileSync(file, message) + } catch (e) { + console.error('Problem saving backup keys') + } } }) } +const fileRecoveryKeys = (state, recoveryKeyFile) => { + if (!recoveryKeyFile) { + // user canceled from dialog, we abort without error + return state + } + + const result = loadKeysFromBackupFile(state, recoveryKeyFile) + const recoveryKey = result.recoveryKey || '' + state = result.state + + return recoverKeys(state, false, recoveryKey) +} + const recoverKeys = (state, useRecoveryKeyFile, key) => { let recoveryKey if (useRecoveryKeyFile) { - let recoveryKeyFile = promptForRecoveryKeyFile() - if (!recoveryKeyFile) { - // user canceled from dialog, we abort without error - return state - } - - const result = loadKeysFromBackupFile(state, recoveryKeyFile) - recoveryKey = result.recoveryKey || '' - state = result.state + promptForRecoveryKeyFile() + return state } if (!recoveryKey) { @@ -2755,6 +2773,7 @@ const getMethods = () => { claimPromotion, onPromotionResponse, getBalance, + fileRecoveryKeys, getPromotion, onPublisherTimestamp, checkVerifiedStatus, diff --git a/app/browser/reducers/ledgerReducer.js b/app/browser/reducers/ledgerReducer.js index c75ab61cf57..018f7bb29ac 100644 --- a/app/browser/reducers/ledgerReducer.js +++ b/app/browser/reducers/ledgerReducer.js @@ -54,6 +54,11 @@ const ledgerReducer = (state, action, immutableAction) => { ) break } + case appConstants.APP_ON_FILE_RECOVERY_KEYS: + { + state = ledgerApi.fileRecoveryKeys(state, action.get('file')) + break + } case appConstants.APP_SHUTTING_DOWN: { state = ledgerApi.quit(state) diff --git a/app/browser/tabs.js b/app/browser/tabs.js index b092853229a..434f5eeb9a4 100644 --- a/app/browser/tabs.js +++ b/app/browser/tabs.js @@ -307,6 +307,11 @@ const updateAboutDetails = (tabId) => { sendAboutDetails(tabId, messages.DOWNLOADS_UPDATED, { downloads: downloads.toJS() }) + } else if (location === 'about:printkeys') { + const phrase = ledgerState.getInfoProp(appState, 'passphrase') + sendAboutDetails(tabId, messages.PRINTKEYS_UPDATED, { + passphrase: phrase + }) } else if (location === 'about:passwords') { autofill.getAutofillableLogins((result) => { sendAboutDetails(tabId, messages.PASSWORD_DETAILS_UPDATED, result) diff --git a/app/extensions/brave/about-printkeys.html b/app/extensions/brave/about-printkeys.html new file mode 100644 index 00000000000..33a14a1c879 --- /dev/null +++ b/app/extensions/brave/about-printkeys.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + +
+ + diff --git a/app/extensions/brave/locales/en-US/app.properties b/app/extensions/brave/locales/en-US/app.properties index f4df1bb2d58..1c372fca4eb 100644 --- a/app/extensions/brave/locales/en-US/app.properties +++ b/app/extensions/brave/locales/en-US/app.properties @@ -186,6 +186,7 @@ phone=Phone postalCode=Postal Code prefsRestart=Do you want to restart now? preventMoreAlerts=Prevent this page from creating additional dialogs +printKeysTitle=Backup keys reconciliationNotification=Good news! Brave will pay your favorite publisher sites in less than 24 hours. redirectedResources={{redirectedResourcesSize}} Resources upgraded to HTTPS releaseNotes=Release Notes diff --git a/app/renderer/about/ledger/printKeys.js b/app/renderer/about/ledger/printKeys.js new file mode 100644 index 00000000000..beea3c99291 --- /dev/null +++ b/app/renderer/about/ledger/printKeys.js @@ -0,0 +1,63 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const React = require('react') +const format = require('date-fns/format') +const {StyleSheet, css} = require('aphrodite/no-important') +const ipc = window.chrome.ipcRenderer + +// Constants +const messages = require('../../../../js/constants/messages') + +class PrintKeys extends React.Component { + constructor (props) { + super(props) + this.state = { + passphrase: '' + } + + ipc.on(messages.PRINTKEYS_UPDATED, (e, detail) => { + if (detail) { + this.setState({ + passphrase: detail && detail.passphrase + }) + } + }) + } + + componentDidUpdate (prevProps, prevState) { + if (prevState.passphrase !== this.state.passphrase) { + setTimeout(() => { + window.print() + }, 500) + } + } + + render () { + const date = format(new Date(), 'MM/DD/YYYY') + + return
+
+
+ {date} +
+
+
+ {this.state.passphrase} +
+
+
+
+ } +} + +const styles = StyleSheet.create({ + content: { + fontWeight: '400', + color: '#3b3b3b', + fontSize: '16px' + } +}) + +module.exports = diff --git a/js/about/entry.js b/js/about/entry.js index ee701405e14..996808bfdaa 100644 --- a/js/about/entry.js +++ b/js/about/entry.js @@ -31,6 +31,9 @@ switch (getBaseUrl(getSourceAboutUrl(window.location.href))) { case 'about:bookmarks': getElementOp = import('../../app/renderer/about/bookmarks/bookmarks') break + case 'about:printkeys': + getElementOp = import('../../app/renderer/about/ledger/printKeys') + break case 'about:certerror': getElementOp = import('./certerror') break diff --git a/js/actions/appActions.js b/js/actions/appActions.js index f1fbcb330b8..be3b811bab8 100644 --- a/js/actions/appActions.js +++ b/js/actions/appActions.js @@ -1913,6 +1913,13 @@ const appActions = { }) }, + onFileRecoveryKeys: function (file) { + dispatch({ + actionType: appConstants.APP_ON_FILE_RECOVERY_KEYS, + file + }) + }, + checkReferralActivity: function () { dispatch({ actionType: appConstants.APP_CHECK_REFERRAL_ACTIVITY diff --git a/js/constants/appConstants.js b/js/constants/appConstants.js index 0594e4b5545..ac7a50981d4 100644 --- a/js/constants/appConstants.js +++ b/js/constants/appConstants.js @@ -175,6 +175,7 @@ const appConstants = { APP_ON_LEDGER_CALLBACK: _, APP_ON_TIME_UNTIL_RECONCILE: _, APP_ON_LEDGER_RUN: _, + APP_ON_FILE_RECOVERY_KEYS: _, APP_ON_NETWORK_CONNECTED: _, APP_ON_RESET_RECOVERY_STATUS: _, APP_ON_LEDGER_INIT_READ: _, diff --git a/js/constants/messages.js b/js/constants/messages.js index bd714c146c6..66f80436c47 100644 --- a/js/constants/messages.js +++ b/js/constants/messages.js @@ -96,6 +96,7 @@ const messages = { EXTENSIONS_UPDATED: _, ADBLOCK_UPDATED: _, DOWNLOADS_UPDATED: _, + PRINTKEYS_UPDATED: _, NEWTAB_DATA_UPDATED: _, VERSION_INFORMATION_UPDATED: _, // About pages from contentScript diff --git a/js/lib/appUrlUtil.js b/js/lib/appUrlUtil.js index 3543b9c83f3..6ddbcdcc1fe 100644 --- a/js/lib/appUrlUtil.js +++ b/js/lib/appUrlUtil.js @@ -115,6 +115,7 @@ module.exports.aboutUrls = new Immutable.Map({ 'about:safebrowsing': module.exports.getBraveExtUrl('about-safebrowsing.html'), 'about:styles': module.exports.getBraveExtUrl('about-styles.html'), 'about:contributions': module.exports.getBraveExtUrl('about-contributions.html'), + 'about:printkeys': module.exports.getBraveExtUrl('about-printkeys.html'), 'about:welcome': module.exports.getBraveExtUrl('about-welcome.html') })