1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

camera working back and forth

This commit is contained in:
brunobar79 2018-07-23 21:27:51 -04:00
parent 0209148609
commit f7ad978474
8 changed files with 116 additions and 95 deletions

View File

@ -6,6 +6,7 @@ const PongStream = require('ping-pong-stream/pong')
const ObjectMultiplex = require('obj-multiplex') const ObjectMultiplex = require('obj-multiplex')
const extension = require('extensionizer') const extension = require('extensionizer')
const PortStream = require('./lib/port-stream.js') const PortStream = require('./lib/port-stream.js')
const Instascan = require('instascan')
const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString() const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString()
const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('inpage.js') + '\n' const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('inpage.js') + '\n'
@ -199,3 +200,49 @@ function redirectToPhishingWarning () {
console.log('MetaMask - redirecting to phishing warning') console.log('MetaMask - redirecting to phishing warning')
window.location.href = 'https://metamask.io/phishing.html' window.location.href = 'https://metamask.io/phishing.html'
} }
function initQrCodeScanner () {
// Append preview div
const preview = document.createElement('div')
preview.id = 'metamask-preview-wrapper'
preview.style = 'position:absolute; top: 20px; left: 20px; width: 300px; height: 300px; overflow: hidden; z-index: 999999999;'
const previewVideo = document.createElement('video')
previewVideo.id = 'metamask-preview-video'
previewVideo.style = 'width: 100%; height: 100%; object-fit: none; margin-left: -10%; margin-top: 10%;'
preview.appendChild(previewVideo)
document.body.appendChild(preview)
console.log('injected')
const scanner = new Instascan.Scanner({
video: document.getElementById('metamask-preview-video'),
backgroundScan: false,
continuous: true,
})
scanner.addListener('scan', function (content) {
console.log('QR-SCANNER: got code (IN-PAGE)', content)
scanner.stop().then(_ => {
console.log('QR-SCANNER: stopped scanner and sending msg (IN-PAGE)', content)
extension.runtime.sendMessage({
action: 'qr-code-scanner-data',
data: content,
})
console.log('QR-SCANNER: message sent (IN-PAGE)', content)
document.getElementById('metamask-preview-wrapper').parentElement.removeChild(document.getElementById('metamask-preview-wrapper'))
})
})
Instascan.Camera.getCameras().then(function (cameras) {
if (cameras.length > 0) {
scanner.start(cameras[0])
} else {
console.error('No cameras found.')
}
}).catch(function (e) {
console.error(e)
})
}
extension.runtime.onMessage.addListener(({ action }) => {
console.log('QR-SCANNER: message received (IN-PAGE)', action)
initQrCodeScanner()
})
console.log('QR-SCANNER: now listening (IN-PAGE)')

View File

@ -5,7 +5,6 @@ const log = require('loglevel')
const LocalMessageDuplexStream = require('post-message-stream') const LocalMessageDuplexStream = require('post-message-stream')
const setupDappAutoReload = require('./lib/auto-reload.js') const setupDappAutoReload = require('./lib/auto-reload.js')
const MetamaskInpageProvider = require('./lib/inpage-provider.js') const MetamaskInpageProvider = require('./lib/inpage-provider.js')
const Instascan = require('instascan')
restoreContextAfterImports() restoreContextAfterImports()
log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn') log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn')
@ -98,40 +97,3 @@ function restoreContextAfterImports () {
} }
} }
function initCameraScanner () {
// Append preview div
const preview = document.createElement('div')
preview.id = 'metamask-preview-wrapper'
preview.style = 'position:absolute; top: 20px; left: 20px; width: 300px; height: 300px; overflow: hidden; z-index: 999999999;'
const previewVideo = document.createElement('video')
previewVideo.id = 'metamask-preview-video'
previewVideo.style = 'width: 100%; height: 100%; object-fit: none; margin-left: -10%; margin-top: 10%;'
preview.appendChild(previewVideo)
document.body.appendChild(preview)
console.log('injected')
const scanner = new Instascan.Scanner({
video: document.getElementById('metamask-preview-video'),
backgroundScan: false,
continuous: true,
})
scanner.addListener('scan', function (content) {
alert(content)
scanner.stop().then(_ => {
document.getElementById('metamask-preview-wrapper').parentElement.removeChild(document.getElementById('metamask-preview-wrapper'))
})
})
Instascan.Camera.getCameras().then(function (cameras) {
if (cameras.length > 0) {
scanner.start(cameras[0])
} else {
console.error('No cameras found.')
}
}).catch(function (e) {
console.error(e)
})
}
setTimeout(_ => {
console.log('injecting...')
initCameraScanner()
}, 3000)

View File

@ -380,6 +380,9 @@ module.exports = class MetamaskController extends EventEmitter {
// TREZOR // TREZOR
unlockTrezorAccount: nodeify(this.unlockTrezorAccount, this), unlockTrezorAccount: nodeify(this.unlockTrezorAccount, this),
// QR code scanner
scanQrCode: nodeify(this.scanQrCode, this),
// vault management // vault management
submitPassword: nodeify(this.submitPassword, this), submitPassword: nodeify(this.submitPassword, this),
@ -655,6 +658,25 @@ module.exports = class MetamaskController extends EventEmitter {
return { ...keyState, identities } return { ...keyState, identities }
} }
scanQrCode () {
return new Promise((resolve, reject) => {
console.log('QR-SCANNER: intializing QR code scanner feature (MM controller)')
// Tell contentscript to inject the QR reader
this.platform.sendMessage('qr-code-scanner-init')
console.log('QR-SCANNER: message to initialize has been sent (MM controller)')
// Wait for the scanner to send something back
this.platform.addMessageListener(({ action, data }) => {
console.log('QR-SCANNER: message received (MM controller)', action, data)
if (action && action === 'qr-code-scanner-data') {
const normalizedAddress = data.replace('ethereum:', '')
console.log('QR-SCANNER: resolving promise!', normalizedAddress)
return Promise.resolve(normalizedAddress)
}
})
console.log('QR-SCANNER: now listening (MM controller)')
})
}
// //
// Account Management // Account Management

View File

@ -1,5 +1,4 @@
const extension = require('extensionizer') const extension = require('extensionizer')
const explorerLink = require('etherscan-link').createExplorerLink
class ExtensionPlatform { class ExtensionPlatform {
@ -18,11 +17,8 @@ class ExtensionPlatform {
return extension.runtime.getManifest().version return extension.runtime.getManifest().version
} }
openExtensionInBrowser (route = null) { openExtensionInBrowser () {
let extensionURL = extension.runtime.getURL('home.html') const extensionURL = extension.runtime.getURL('home.html')
if (route) {
extensionURL += `#${route}`
}
this.openWindow({ url: extensionURL }) this.openWindow({ url: extensionURL })
} }
@ -36,58 +32,17 @@ class ExtensionPlatform {
} }
} }
showTransactionNotification (txMeta) { addMessageListener (cb) {
extension.runtime.onMessage.addListener(cb)
const status = txMeta.status
if (status === 'confirmed') {
this._showConfirmedTransaction(txMeta)
} else if (status === 'failed') {
this._showFailedTransaction(txMeta)
}
} }
_showConfirmedTransaction (txMeta) { sendMessage (message, query = {}) {
extension.tabs.query(query, tabs => {
this._subscribeToNotificationClicked() const activeTab = tabs.filter(tab => tab.active)[0]
extension.tabs.sendMessage(activeTab.id, message)
const url = explorerLink(txMeta.hash, parseInt(txMeta.metamaskNetworkId)) console.log('QR-SCANNER: message sent to tab', message, activeTab)
const nonce = parseInt(txMeta.txParams.nonce, 16)
const title = 'Confirmed transaction'
const message = `Transaction ${nonce} confirmed! View on EtherScan`
this._showNotification(title, message, url)
}
_showFailedTransaction (txMeta) {
const nonce = parseInt(txMeta.txParams.nonce, 16)
const title = 'Failed transaction'
const message = `Transaction ${nonce} failed! ${txMeta.err.message}`
this._showNotification(title, message)
}
_showNotification (title, message, url) {
extension.notifications.create(
url,
{
'type': 'basic',
'title': title,
'iconUrl': extension.extension.getURL('../../images/icon-64.png'),
'message': message,
}) })
} }
_subscribeToNotificationClicked () {
if (!extension.notifications.onClicked.hasListener(this._viewOnEtherScan)) {
extension.notifications.onClicked.addListener(this._viewOnEtherScan)
}
}
_viewOnEtherScan (txId) {
if (txId.startsWith('http://')) {
global.metamaskController.platform.openWindow({ url: txId })
}
}
} }
module.exports = ExtensionPlatform module.exports = ExtensionPlatform

View File

@ -302,6 +302,7 @@ var actions = {
CLEAR_PENDING_TOKENS: 'CLEAR_PENDING_TOKENS', CLEAR_PENDING_TOKENS: 'CLEAR_PENDING_TOKENS',
setPendingTokens, setPendingTokens,
clearPendingTokens, clearPendingTokens,
scanQrCode,
} }
module.exports = actions module.exports = actions
@ -2194,3 +2195,23 @@ function clearPendingTokens () {
type: actions.CLEAR_PENDING_TOKENS, type: actions.CLEAR_PENDING_TOKENS,
} }
} }
function scanQrCode () {
log.debug(`background.scanQrCode`)
return (dispatch, getState) => {
dispatch(actions.showLoadingIndication())
return new Promise((resolve, reject) => {
background.scanQrCode((err, data) => {
log.debug(`background.scanQrCode resolved!`, err, data)
if (err) {
log.error(err)
dispatch(actions.displayWarning(err.message))
return reject(err)
}
dispatch(actions.hideLoadingIndication())
return resolve(data)
})
})
}
}

View File

@ -11,6 +11,7 @@ export default class SendContent extends Component {
static propTypes = { static propTypes = {
updateGas: PropTypes.func, updateGas: PropTypes.func,
scanQrCode: PropTypes.func,
}; };
render () { render () {
@ -19,6 +20,7 @@ export default class SendContent extends Component {
<div className="send-v2__form"> <div className="send-v2__form">
<SendFromRow /> <SendFromRow />
<SendToRow updateGas={(updateData) => this.props.updateGas(updateData)} /> <SendToRow updateGas={(updateData) => this.props.updateGas(updateData)} />
<button onClick={_ => this.props.scanQrCode() }>or scan a QR code</button>
<SendAmountRow updateGas={(updateData) => this.props.updateGas(updateData)} /> <SendAmountRow updateGas={(updateData) => this.props.updateGas(updateData)} />
<SendGasRow /> <SendGasRow />
<SendHexDataRow /> <SendHexDataRow />

View File

@ -38,12 +38,19 @@ export default class SendTransactionScreen extends PersistentForm {
updateAndSetGasTotal: PropTypes.func, updateAndSetGasTotal: PropTypes.func,
updateSendErrors: PropTypes.func, updateSendErrors: PropTypes.func,
updateSendTokenBalance: PropTypes.func, updateSendTokenBalance: PropTypes.func,
scanQrCode: PropTypes.func,
}; };
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
}; };
scanQrCode = async () => {
const scannedAddress = await this.props.scanQrCode()
console.log('QR-SCANNER: Got address (UI)', scannedAddress)
this.updateGas({ to: scannedAddress })
}
updateGas ({ to: updatedToAddress, amount: value } = {}) { updateGas ({ to: updatedToAddress, amount: value } = {}) {
const { const {
amount, amount,
@ -170,7 +177,10 @@ export default class SendTransactionScreen extends PersistentForm {
return ( return (
<div className="page-container"> <div className="page-container">
<SendHeader history={history}/> <SendHeader history={history}/>
<SendContent updateGas={(updateData) => this.updateGas(updateData)}/> <SendContent
updateGas={(updateData) => this.updateGas(updateData)}
scanQrCode={_ => this.scanQrCode()}
/>
<SendFooter history={history}/> <SendFooter history={history}/>
</div> </div>
) )

View File

@ -26,6 +26,7 @@ import {
updateSendTokenBalance, updateSendTokenBalance,
updateGasData, updateGasData,
setGasTotal, setGasTotal,
scanQrCode,
} from '../../actions' } from '../../actions'
import { import {
resetSendState, resetSendState,
@ -89,5 +90,6 @@ function mapDispatchToProps (dispatch) {
}, },
updateSendErrors: newError => dispatch(updateSendErrors(newError)), updateSendErrors: newError => dispatch(updateSendErrors(newError)),
resetSendState: () => dispatch(resetSendState()), resetSendState: () => dispatch(resetSendState()),
scanQrCode: () => dispatch(scanQrCode()),
} }
} }