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

Add JSDoc to various background scripts

This commit is contained in:
bitpshr 2018-04-18 17:02:08 -04:00
parent 7e21fc2aa7
commit c9f83fe8bc
6 changed files with 205 additions and 70 deletions

View File

@ -15,7 +15,41 @@ const BETA_UI_NETWORK_TYPE = 'networkBeta'
global.METAMASK_DEBUG = process.env.METAMASK_DEBUG global.METAMASK_DEBUG = process.env.METAMASK_DEBUG
module.exports = { /**
* @typedef {Object} UrlConfig
* @property {string} localhost URL of local RPC provider
* @property {string} mainnet URL of mainnet RPC provider
* @property {string} ropsten URL of Ropsten testnet RPC provider
* @property {string} kovan URL of Kovan testnet RPC provider
* @property {string} rinkeby URL of Rinkeby testnet RPC provider
*/
/**
* @typedef {Object} NameConfig
* @property {string} 3 URL of local RPC provider
* @property {string} 4 URL of mainnet RPC provider
* @property {string} 42 URL of Ropsten testnet RPC provider
*/
/**
* @typedef {Object} EnumConfig
* @property {string} DEFAULT_RPC Default network provider URL
* @property {string} OLD_UI_NETWORK_TYPE
* @property {string} BETA_UI_NETWORK_TYPE
*/
/**
* @typedef {Object} Config
* @property {UrlConfig} network Network configuration parameters
* @property {UrlConfig} networkBeta Beta UI network configuration parameters
* @property {NameConfig} networkNames Network name configuration parameters
* @property {EnumConfig} enums Application-wide string constants
*/
/**
* @type {Config} Application configuration object
**/
const config = {
network: { network: {
localhost: LOCALHOST_RPC_URL, localhost: LOCALHOST_RPC_URL,
mainnet: MAINET_RPC_URL, mainnet: MAINET_RPC_URL,
@ -23,7 +57,6 @@ module.exports = {
kovan: KOVAN_RPC_URL, kovan: KOVAN_RPC_URL,
rinkeby: RINKEBY_RPC_URL, rinkeby: RINKEBY_RPC_URL,
}, },
// Used for beta UI
networkBeta: { networkBeta: {
localhost: LOCALHOST_RPC_URL, localhost: LOCALHOST_RPC_URL,
mainnet: MAINET_RPC_URL_BETA, mainnet: MAINET_RPC_URL_BETA,
@ -42,3 +75,5 @@ module.exports = {
BETA_UI_NETWORK_TYPE, BETA_UI_NETWORK_TYPE,
}, },
} }
module.exports = config

View File

@ -23,6 +23,9 @@ if (shouldInjectWeb3()) {
setupStreams() setupStreams()
} }
/**
* Creates a script tag that injects inpage.js
*/
function setupInjection () { function setupInjection () {
try { try {
// inject in-page script // inject in-page script
@ -37,6 +40,10 @@ function setupInjection () {
} }
} }
/**
* Sets up two-way communication streams between the
* browser extension and local per-page browser context
*/
function setupStreams () { function setupStreams () {
// setup communication to page and plugin // setup communication to page and plugin
const pageStream = new LocalMessageDuplexStream({ const pageStream = new LocalMessageDuplexStream({
@ -89,17 +96,34 @@ function setupStreams () {
mux.ignoreStream('publicConfig') mux.ignoreStream('publicConfig')
} }
/**
* Error handler for page to plugin stream disconnections
*
* @param {string} remoteLabel Remote stream name
* @param {Error} err Stream connection error
*/
function logStreamDisconnectWarning (remoteLabel, err) { function logStreamDisconnectWarning (remoteLabel, err) {
let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}` let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}`
if (err) warningMsg += '\n' + err.stack if (err) warningMsg += '\n' + err.stack
console.warn(warningMsg) console.warn(warningMsg)
} }
/**
* Determines if Web3 should be injected
*
* @returns {boolean} True of Web3 should be injected
*/
function shouldInjectWeb3 () { function shouldInjectWeb3 () {
return doctypeCheck() && suffixCheck() return doctypeCheck() && suffixCheck()
&& documentElementCheck() && !blacklistedDomainCheck() && documentElementCheck() && !blacklistedDomainCheck()
} }
/**
* Checks the doctype of the current document if it exists
*
* @returns {boolean} True if the doctype is html or if none exists
*/
function doctypeCheck () { function doctypeCheck () {
const doctype = window.document.doctype const doctype = window.document.doctype
if (doctype) { if (doctype) {
@ -109,6 +133,11 @@ function doctypeCheck () {
} }
} }
/**
* Checks the current document extension
*
* @returns {boolean} True if the current extension is not prohibited
*/
function suffixCheck () { function suffixCheck () {
var prohibitedTypes = ['xml', 'pdf'] var prohibitedTypes = ['xml', 'pdf']
var currentUrl = window.location.href var currentUrl = window.location.href
@ -122,6 +151,11 @@ function suffixCheck () {
return true return true
} }
/**
* Checks the documentElement of the current document
*
* @returns {boolean} True if the documentElement is an html node or if none exists
*/
function documentElementCheck () { function documentElementCheck () {
var documentElement = document.documentElement.nodeName var documentElement = document.documentElement.nodeName
if (documentElement) { if (documentElement) {
@ -130,6 +164,11 @@ function documentElementCheck () {
return true return true
} }
/**
* Checks if the current domain is blacklisted
*
* @returns {boolean} True if the current domain is blacklisted
*/
function blacklistedDomainCheck () { function blacklistedDomainCheck () {
var blacklistedDomains = [ var blacklistedDomains = [
'uscourts.gov', 'uscourts.gov',
@ -148,6 +187,9 @@ function blacklistedDomainCheck () {
return false return false
} }
/**
* Redirects the current page to a phishing information page
*/
function redirectToPhishingWarning () { 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'

View File

@ -1,69 +1,97 @@
const asmcrypto = require('asmcrypto.js') const asmcrypto = require('asmcrypto.js')
const Unibabel = require('browserify-unibabel') const Unibabel = require('browserify-unibabel')
/**
* A Microsoft Edge-specific encryption class that exposes
* the interface expected by eth-keykeyring-controller
*/
class EdgeEncryptor { class EdgeEncryptor {
/**
* Encrypts an arbitrary JavaScript object to cypher text
*
* @param {string} password Password used to unlock a cryptographic key
* @param {Object} dataObject Data to encrypt
* @returns {Object} Object containing cypher text, generation vectors, and salt
*/
encrypt (password, dataObject) {
var salt = this._generateSalt()
return this._keyFromPassword(password, salt)
.then(function (key) {
var data = JSON.stringify(dataObject)
var dataBuffer = Unibabel.utf8ToBuffer(data)
var vector = global.crypto.getRandomValues(new Uint8Array(16))
var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector)
encrypt (password, dataObject) { var buffer = new Uint8Array(resultbuffer)
var vectorStr = Unibabel.bufferToBase64(vector)
var vaultStr = Unibabel.bufferToBase64(buffer)
return JSON.stringify({
data: vaultStr,
iv: vectorStr,
salt: salt,
})
})
}
var salt = this._generateSalt() /**
return this._keyFromPassword(password, salt) * Decrypts an arbitrary JavaScript object from cypher text
.then(function (key) { *
* @param {string} password Password used to unlock a cryptographic key
* @param {string} text Cypher text of an encrypted JavaScript object
* @returns {Promise<Object>} Promise resolving to copy of decrypted JavaScript object
*/
decrypt (password, text) {
const payload = JSON.parse(text)
const salt = payload.salt
return this._keyFromPassword(password, salt)
.then(function (key) {
const encryptedData = Unibabel.base64ToBuffer(payload.data)
const vector = Unibabel.base64ToBuffer(payload.iv)
return new Promise((resolve, reject) => {
var result
try {
result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector)
} catch (err) {
return reject(new Error('Incorrect password'))
}
const decryptedData = new Uint8Array(result)
const decryptedStr = Unibabel.bufferToUtf8(decryptedData)
const decryptedObj = JSON.parse(decryptedStr)
resolve(decryptedObj)
})
})
}
var data = JSON.stringify(dataObject) /**
var dataBuffer = Unibabel.utf8ToBuffer(data) * Retrieves a cryptographic key using a password
var vector = global.crypto.getRandomValues(new Uint8Array(16)) *
var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector) * @private
* @param {string} password Password used to unlock a cryptographic key
* @param {string} salt Random base-64 data
* @returns {Promise<Object>} Promise resolving to a derived key
*/
_keyFromPassword (password, salt) {
var buffer = new Uint8Array(resultbuffer) var passBuffer = Unibabel.utf8ToBuffer(password)
var vectorStr = Unibabel.bufferToBase64(vector) var saltBuffer = Unibabel.base64ToBuffer(salt)
var vaultStr = Unibabel.bufferToBase64(buffer) return new Promise((resolve) => {
return JSON.stringify({ var key = asmcrypto.PBKDF2_HMAC_SHA256.bytes(passBuffer, saltBuffer, 10000)
data: vaultStr, resolve(key)
iv: vectorStr, })
salt: salt, }
})
})
}
decrypt (password, text) { /**
* Generates random base-64 encoded data
const payload = JSON.parse(text) *
const salt = payload.salt * @private
return this._keyFromPassword(password, salt) * @returns {string} Randomized base-64 encoded data
.then(function (key) { */
const encryptedData = Unibabel.base64ToBuffer(payload.data) _generateSalt (byteCount = 32) {
const vector = Unibabel.base64ToBuffer(payload.iv) var view = new Uint8Array(byteCount)
return new Promise((resolve, reject) => { global.crypto.getRandomValues(view)
var result var b64encoded = btoa(String.fromCharCode.apply(null, view))
try { return b64encoded
result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector) }
} catch (err) {
return reject(new Error('Incorrect password'))
}
const decryptedData = new Uint8Array(result)
const decryptedStr = Unibabel.bufferToUtf8(decryptedData)
const decryptedObj = JSON.parse(decryptedStr)
resolve(decryptedObj)
})
})
}
_keyFromPassword (password, salt) {
var passBuffer = Unibabel.utf8ToBuffer(password)
var saltBuffer = Unibabel.base64ToBuffer(salt)
return new Promise((resolve) => {
var key = asmcrypto.PBKDF2_HMAC_SHA256.bytes(passBuffer, saltBuffer, 10000)
resolve(key)
})
}
_generateSalt (byteCount = 32) {
var view = new Uint8Array(byteCount)
global.crypto.getRandomValues(view)
var b64encoded = btoa(String.fromCharCode.apply(null, view))
return b64encoded
}
} }
module.exports = EdgeEncryptor module.exports = EdgeEncryptor

View File

@ -2,10 +2,16 @@
const env = process.env.METAMASK_ENV const env = process.env.METAMASK_ENV
const METAMASK_DEBUG = process.env.METAMASK_DEBUG const METAMASK_DEBUG = process.env.METAMASK_DEBUG
// /**
// The default state of MetaMask * @typedef {Object} FirstTimeState
// * @property {Object} config Initial configuration parameters
module.exports = { * @property {Object} NetworkController Network controller state
*/
/**
* @type {FirstTimeState} The default state of MetaMask
*/
const initialState = {
config: {}, config: {},
NetworkController: { NetworkController: {
provider: { provider: {
@ -13,3 +19,5 @@ module.exports = {
}, },
}, },
} }
module.exports = initialState

View File

@ -42,20 +42,18 @@ log.debug('MetaMask - injected web3')
setupDappAutoReload(web3, inpageProvider.publicConfigStore) setupDappAutoReload(web3, inpageProvider.publicConfigStore)
// set web3 defaultAccount // set web3 defaultAccount
inpageProvider.publicConfigStore.subscribe(function (state) { inpageProvider.publicConfigStore.subscribe(function (state) {
web3.eth.defaultAccount = state.selectedAddress web3.eth.defaultAccount = state.selectedAddress
}) })
//
// util
//
// need to make sure we aren't affected by overlapping namespaces // need to make sure we aren't affected by overlapping namespaces
// and that we dont affect the app with our namespace // and that we dont affect the app with our namespace
// mostly a fix for web3's BigNumber if AMD's "define" is defined... // mostly a fix for web3's BigNumber if AMD's "define" is defined...
var __define var __define
/**
* Caches reference to global define object and deletes it
*/
function cleanContextForImports () { function cleanContextForImports () {
__define = global.define __define = global.define
try { try {
@ -65,6 +63,9 @@ function cleanContextForImports () {
} }
} }
/**
* Restores global define object from cached reference
*/
function restoreContextAfterImports () { function restoreContextAfterImports () {
try { try {
global.define = __define global.define = __define

View File

@ -7,10 +7,14 @@ const launchMetamaskUi = require('../../ui')
const StreamProvider = require('web3-stream-provider') const StreamProvider = require('web3-stream-provider')
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
module.exports = initializePopup module.exports = initializePopup
/**
* Asynchronously initializes the MetaMask popup UI
*
* @param {{ container: Element, connectionStream: any }} config Popup configuration object
* @param {Function} cb Called when initialization is comlete
*/
function initializePopup ({ container, connectionStream }, cb) { function initializePopup ({ container, connectionStream }, cb) {
// setup app // setup app
async.waterfall([ async.waterfall([
@ -19,6 +23,12 @@ function initializePopup ({ container, connectionStream }, cb) {
], cb) ], cb)
} }
/**
* Establishes streamed connections to background scripts and a Web3 provider
*
* @param {any} connectionStream PortStream instance establishing a background connection
* @param {Function} cb Called when controller connection is established
*/
function connectToAccountManager (connectionStream, cb) { function connectToAccountManager (connectionStream, cb) {
// setup communication with background // setup communication with background
// setup multiplexing // setup multiplexing
@ -28,6 +38,11 @@ function connectToAccountManager (connectionStream, cb) {
setupWeb3Connection(mx.createStream('provider')) setupWeb3Connection(mx.createStream('provider'))
} }
/**
* Establishes a streamed connection to a Web3 provider
*
* @param {any} connectionStream PortStream instance establishing a background connection
*/
function setupWeb3Connection (connectionStream) { function setupWeb3Connection (connectionStream) {
var providerStream = new StreamProvider() var providerStream = new StreamProvider()
providerStream.pipe(connectionStream).pipe(providerStream) providerStream.pipe(connectionStream).pipe(providerStream)
@ -38,6 +53,12 @@ function setupWeb3Connection (connectionStream) {
global.eth = new Eth(providerStream) global.eth = new Eth(providerStream)
} }
/**
* Establishes a streamed connection to the background account manager
*
* @param {any} connectionStream PortStream instance establishing a background connection
* @param {Function} cb Called when the remote account manager connection is established
*/
function setupControllerConnection (connectionStream, cb) { function setupControllerConnection (connectionStream, cb) {
// this is a really sneaky way of adding EventEmitter api // this is a really sneaky way of adding EventEmitter api
// to a bi-directional dnode instance // to a bi-directional dnode instance