diff --git a/app/scripts/auto-type/auto-type-runner.js b/app/scripts/auto-type/auto-type-runner.js index 0d3fbb96..bd99ecd8 100644 --- a/app/scripts/auto-type/auto-type-runner.js +++ b/app/scripts/auto-type/auto-type-runner.js @@ -142,8 +142,9 @@ AutoTypeRunner.Substitutions = { } }; -AutoTypeRunner.prototype.resolve = function(entry, callback) { +AutoTypeRunner.prototype.resolve = function(entry, context, callback) { this.entry = entry; + this.context = context; try { this.resolveOps(this.ops); if (!this.pendingResolvesCount) { @@ -203,6 +204,11 @@ AutoTypeRunner.prototype.resolveOp = function(op) { } return; } + if (this.context && this.context.resolved && this.context.resolved[lowerValue]) { + op.type = 'text'; + op.value = this.context.resolved[lowerValue]; + return; + } const substitution = AutoTypeRunner.Substitutions[lowerValue]; if (substitution) { // {title} @@ -363,8 +369,8 @@ AutoTypeRunner.prototype.getOtp = function(op) { if (!this.entry.otpGenerator) { return ''; } - this.entry.otpGenerator.next(otp => { - this.pendingResolved(op, otp, otp ? undefined : 'OTP error'); + this.entry.otpGenerator.next((err, otp) => { + this.pendingResolved(op, otp, err); }); return AutoTypeRunner.PendingResolve; }; diff --git a/app/scripts/auto-type/index.js b/app/scripts/auto-type/index.js index f9fc8d44..da7cacb1 100644 --- a/app/scripts/auto-type/index.js +++ b/app/scripts/auto-type/index.js @@ -34,6 +34,7 @@ const AutoType = { handleEvent(e) { const entry = (e && e.entry) || null; const sequence = (e && e.sequence) || null; + const context = (e && e.context) || null; logger.debug('Auto type event', entry); if (this.running) { logger.debug('Already running, skipping event'); @@ -41,7 +42,7 @@ const AutoType = { } if (entry) { this.hideWindow(() => { - this.runAndHandleResult({ entry, sequence }); + this.runAndHandleResult({ entry, sequence, context }); }); } else { if (this.selectEntryView) { @@ -76,13 +77,14 @@ const AutoType = { run(result, callback) { this.running = true; const sequence = result.sequence || result.entry.getEffectiveAutoTypeSeq(); + const context = result.context; logger.debug('Start', sequence); const ts = logger.ts(); try { const parser = new AutoTypeParser(sequence); const runner = parser.parse(); logger.debug('Parsed', this.printOps(runner.ops)); - runner.resolve(result.entry, err => { + runner.resolve(result.entry, context, err => { if (err) { this.running = false; logger.error('Resolve error', err); @@ -120,7 +122,7 @@ const AutoType = { try { const parser = new AutoTypeParser(sequence); const runner = parser.parse(); - runner.resolve(entry, callback); + runner.resolve(entry, null, callback); } catch (ex) { return callback(ex); } diff --git a/app/scripts/views/details/details-view.js b/app/scripts/views/details/details-view.js index d072cca4..c0744bd2 100644 --- a/app/scripts/views/details/details-view.js +++ b/app/scripts/views/details/details-view.js @@ -74,7 +74,7 @@ class DetailsView extends View { this.onKey(Keys.DOM_VK_B, this.copyUserName, KeyHandler.SHORTCUT_ACTION); this.onKey(Keys.DOM_VK_U, this.copyUrl, KeyHandler.SHORTCUT_ACTION); if (AutoType.enabled) { - this.onKey(Keys.DOM_VK_T, this.autoType, KeyHandler.SHORTCUT_ACTION); + this.onKey(Keys.DOM_VK_T, () => this.autoType(), KeyHandler.SHORTCUT_ACTION); } this.onKey( Keys.DOM_VK_DELETE, @@ -153,7 +153,7 @@ class DetailsView extends View { fieldView.render(); fieldView.on('change', this.fieldChanged.bind(this)); fieldView.on('copy', this.fieldCopied.bind(this)); - fieldView.on('autotype', this.fieldAutoType.bind(this)); + fieldView.on('autotype', e => this.autoType(e.source.model.sequence)); if (hideEmptyFields) { const value = fieldView.model.value(); if (!value || value.length === 0 || value.byteLength === 0) { @@ -486,15 +486,15 @@ class DetailsView extends View { } copyOtp() { - const otpFieldView = this.getFieldView('$otp'); + const otpField = this.getFieldView('$otp'); if (this.model.external) { - if (!otpFieldView) { + if (!otpField) { return false; } - otpFieldView.copyValue(); + otpField.copyValue(); return true; } - this.copyKeyPress(otpFieldView); + this.copyKeyPress(otpField); } showCopyTip() { @@ -946,15 +946,22 @@ class DetailsView extends View { this.views.autoType.render(); } - autoType() { - Events.emit('auto-type', { entry: this.model }); - } - - fieldAutoType(e) { - Events.emit('auto-type', { - entry: this.model, - sequence: e.source.model.sequence - }); + autoType(sequence) { + const entry = this.model; + if (entry.external && (!sequence || sequence.includes('{TOTP}'))) { + const otpField = this.getFieldView('$otp'); + otpField.refreshOtp(err => { + if (!err) { + Events.emit('auto-type', { + entry, + sequence, + context: { resolved: { totp: otpField.otpValue } } + }); + } + }); + } else { + Events.emit('auto-type', { entry, sequence }); + } } } diff --git a/app/scripts/views/fields/field-view-otp.js b/app/scripts/views/fields/field-view-otp.js index c3e13c1b..1ba7b620 100644 --- a/app/scripts/views/fields/field-view-otp.js +++ b/app/scripts/views/fields/field-view-otp.js @@ -153,17 +153,22 @@ class FieldViewOtp extends FieldViewText { } copyValue() { + this.refreshOtp(err => { + if (!err) { + super.copyValue(); + } + }); + } + + refreshOtp(callback) { if (this.model.needsTouch) { if (this.otpValue) { - return super.copyValue(); + callback(); + } else { + this.requestTouch(callback); } - this.requestTouch(err => { - if (!err) { - super.copyValue(); - } - }); } else { - super.copyValue(); + callback(); } }