1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-22 17:33:23 +01:00

Merge branch 'master' into usd-conversion

This commit is contained in:
Kevin Serrano 2016-07-21 11:30:57 -07:00
commit 7b85802a0f
18 changed files with 178 additions and 39 deletions

1
.eslintignore Normal file
View File

@ -0,0 +1 @@
app/scripts/lib/extension-instance.js

View File

@ -23,7 +23,6 @@
],
"globals": {
"chrome": true,
"document": false,
"navigator": false,
"web3": true,

View File

@ -2,6 +2,10 @@
## Current Master
- MetaMask now throws descriptive errors when apps try to use synchronous web3 methods.
## 2.6.2 2016-07-20
- Fixed bug that would prevent the plugin from reopening on the first try after receiving a new transaction while locked.
- Fixed bug that would render 0 ETH as a non-exact amount.

View File

@ -1,7 +1,7 @@
{
"name": "__MSG_appName__",
"short_name": "Metamask",
"version": "2.6.1",
"version": "2.6.2",
"manifest_version": 2,
"description": "__MSG_appDescription__",
"icons": {
@ -37,6 +37,11 @@
"all_frames": false
}
],
"applications": {
"gecko": {
"id": "MOZILLA_EXTENSION_ID"
}
},
"permissions": [
"notifications",
"storage",

View File

@ -9,6 +9,7 @@ const createMsgNotification = require('./lib/notifications.js').createMsgNotific
const messageManager = require('./lib/message-manager')
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
const MetamaskController = require('./metamask-controller')
const extension = require('./lib/extension')
const STORAGE_KEY = 'metamask-config'
@ -65,7 +66,7 @@ function showUnconfirmedTx (txParams, txData, onTxDoneCb) {
// connect to other contexts
//
chrome.runtime.onConnect.addListener(connectRemote)
extension.runtime.onConnect.addListener(connectRemote)
function connectRemote (remotePort) {
var isMetaMaskInternalProcess = (remotePort.name === 'popup')
var portStream = new PortStream(remotePort)
@ -133,8 +134,8 @@ function updateBadge (state) {
if (count) {
label = String(count)
}
chrome.browserAction.setBadgeText({ text: label })
chrome.browserAction.setBadgeBackgroundColor({ color: '#506F8B' })
extension.browserAction.setBadgeText({ text: label })
extension.browserAction.setBadgeBackgroundColor({ color: '#506F8B' })
}
function loadData () {

View File

@ -25,11 +25,12 @@
// if (e.data) {
// var data = JSON.parse(e.data);
// if (data && data.command === 'reload') {
// chrome.runtime.reload();
// extension.runtime.reload();
// }
// }
// };
const extension = require('./lib/extension')
window.LiveReloadOptions = { host: 'localhost' };
(function e (t, n, r) { function s (o, u) { if (!n[o]) { if (!t[o]) { var a = typeof require === 'function' && require; if (!u && a) return a(o, !0); if (i) return i(o, !0); var f = new Error("Cannot find module '" + o + "'"); throw f.code = 'MODULE_NOT_FOUND', f } var l = n[o] = {exports: {}}; t[o][0].call(l.exports, function (e) { var n = t[o][1][e]; return s(n ? n : e) }, l, l.exports, e, t, n, r) } return n[o].exports } var i = typeof require === 'function' && require; for (var o = 0; o < r.length; o++)s(r[o]); return s })({1: [function (require, module, exports) {

View File

@ -1,6 +1,7 @@
const LocalMessageDuplexStream = require('./lib/local-message-stream.js')
const PortStream = require('./lib/port-stream.js')
const ObjectMultiplex = require('./lib/obj-multiplex')
const extension = require('./lib/extension')
if (shouldInjectWeb3()) {
setupInjection()
@ -10,7 +11,7 @@ if (shouldInjectWeb3()) {
function setupInjection(){
// inject in-page script
var scriptTag = document.createElement('script')
scriptTag.src = chrome.extension.getURL('scripts/inpage.js')
scriptTag.src = extension.extension.getURL('scripts/inpage.js')
scriptTag.onload = function () { this.parentNode.removeChild(this) }
var container = document.head || document.documentElement
// append as first child
@ -25,7 +26,7 @@ function setupStreams(){
target: 'inpage',
})
pageStream.on('error', console.error.bind(console))
var pluginPort = chrome.runtime.connect({name: 'contentscript'})
var pluginPort = extension.runtime.connect({name: 'contentscript'})
var pluginStream = new PortStream(pluginPort)
pluginStream.on('error', console.error.bind(console))

View File

@ -53,9 +53,17 @@ var __define
function cleanContextForImports () {
__define = global.define
try {
delete global.define
} catch (_) {
console.warn('MetaMask - global.define could not be deleted.')
}
}
function restoreContextAfterImports () {
try {
global.define = __define
} catch (_) {
console.warn('MetaMask - global.define could not be overwritten.')
}
}

View File

@ -0,0 +1,38 @@
const apis = [
'alarms',
'bookmarks',
'browserAction',
'commands',
'contextMenus',
'cookies',
'downloads',
'events',
'extension',
'extensionTypes',
'history',
'i18n',
'idle',
'notifications',
'pageAction',
'runtime',
'storage',
'tabs',
'webNavigation',
'webRequest',
'windows',
]
function Extension () {
const _this = this
let global = window
if (window.chrome) {
global = window.chrome
}
apis.forEach(function (api) {
_this[api] = global[api]
})
}
module.exports = Extension

View File

@ -0,0 +1,14 @@
/* Extension.js
*
* A module for unifying browser differences in the WebExtension API.
*
* Initially implemented because Chrome hides all of their WebExtension API
* behind a global `chrome` variable, but we'd like to start grooming
* the code-base for cross-browser extension support.
*
* You can read more about the WebExtension API here:
* https://developer.mozilla.org/en-US/Add-ons/WebExtensions
*/
const Extension = require('./extension-instance')
module.exports = new Extension()

View File

@ -107,7 +107,15 @@ function createSyncProvider (providerConfig) {
syncProviderUrl = MetamaskConfig.network.default
}
}
return new HttpProvider(syncProviderUrl)
const provider = new HttpProvider(syncProviderUrl)
// Stubbing out the send method to throw on sync methods:
provider.send = function() {
var message = 'The MetaMask Web3 object does not support synchronous methods. See https://github.com/MetaMask/faq#all-async---think-of-metamask-as-a-light-client for details.'
throw new Error(message)
}
return provider
}
function remoteStoreWithLocalStorageCache (storageKey) {

View File

@ -7,6 +7,7 @@ const h = require('react-hyperscript')
const PendingTxDetails = require('../../../ui/app/components/pending-tx-details')
const PendingMsgDetails = require('../../../ui/app/components/pending-msg-details')
const MetaMaskUiCss = require('../../../ui/css')
const extension = require('./extension')
var notificationHandlers = {}
const notifications = {
@ -20,34 +21,34 @@ window.METAMASK_NOTIFIER = notifications
setupListeners()
function setupListeners () {
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!chrome.notifications) return console.error('Chrome notifications API missing...')
// guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!extension.notifications) return console.error('Chrome notifications API missing...')
// notification button press
chrome.notifications.onButtonClicked.addListener(function (notificationId, buttonIndex) {
extension.notifications.onButtonClicked.addListener(function (notificationId, buttonIndex) {
var handlers = notificationHandlers[notificationId]
if (buttonIndex === 0) {
handlers.confirm()
} else {
handlers.cancel()
}
chrome.notifications.clear(notificationId)
extension.notifications.clear(notificationId)
})
// notification teardown
chrome.notifications.onClosed.addListener(function (notificationId) {
extension.notifications.onClosed.addListener(function (notificationId) {
delete notificationHandlers[notificationId]
})
}
// creation helper
function createUnlockRequestNotification (opts) {
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!chrome.notifications) return console.error('Chrome notifications API missing...')
// guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!extension.notifications) return console.error('Chrome notifications API missing...')
var message = 'An Ethereum app has requested a signature. Please unlock your account.'
var id = createId()
chrome.notifications.create(id, {
extension.notifications.create(id, {
type: 'basic',
iconUrl: '/images/icon-128.png',
title: opts.title,
@ -56,8 +57,8 @@ function createUnlockRequestNotification (opts) {
}
function createTxNotification (state) {
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!chrome.notifications) return console.error('Chrome notifications API missing...')
// guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!extension.notifications) return console.error('Chrome notifications API missing...')
renderTxNotificationSVG(state, function (err, notificationSvgSource) {
if (err) throw err
@ -70,8 +71,8 @@ function createTxNotification (state) {
}
function createMsgNotification (state) {
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!chrome.notifications) return console.error('Chrome notifications API missing...')
// guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!extension.notifications) return console.error('Chrome notifications API missing...')
renderMsgNotificationSVG(state, function (err, notificationSvgSource) {
if (err) throw err
@ -84,11 +85,11 @@ function createMsgNotification (state) {
}
function showNotification (state) {
// guard for chrome bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!chrome.notifications) return console.error('Chrome notifications API missing...')
// guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236
if (!extension.notifications) return console.error('Chrome notifications API missing...')
var id = createId()
chrome.notifications.create(id, {
extension.notifications.create(id, {
type: 'image',
requireInteraction: true,
iconUrl: '/images/icon-128.png',

View File

@ -6,6 +6,7 @@ const messageManager = require('./lib/message-manager')
const HostStore = require('./lib/remote-store.js').HostStore
const Web3 = require('web3')
const ConfigManager = require('./lib/config-manager')
const extension = require('./lib/extension')
module.exports = class MetamaskController {
@ -254,19 +255,19 @@ module.exports = class MetamaskController {
// called from popup
setRpcTarget (rpcTarget) {
this.configManager.setRpcTarget(rpcTarget)
chrome.runtime.reload()
extension.runtime.reload()
this.idStore.getNetwork()
}
setProviderType (type) {
this.configManager.setProviderType(type)
chrome.runtime.reload()
extension.runtime.reload()
this.idStore.getNetwork()
}
useEtherscanProvider () {
this.configManager.useEtherscanProvider()
chrome.runtime.reload()
extension.runtime.reload()
}
}

View File

@ -9,6 +9,7 @@ const injectCss = require('inject-css')
const PortStream = require('./lib/port-stream.js')
const StreamProvider = require('web3-stream-provider')
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
const extension = require('./lib/extension')
// setup app
var css = MetaMaskUiCss()
@ -21,7 +22,7 @@ async.parallel({
function connectToAccountManager (cb) {
// setup communication with background
var pluginPort = chrome.runtime.connect({name: 'popup'})
var pluginPort = extension.runtime.connect({name: 'popup'})
var portStream = new PortStream(pluginPort)
// setup multiplexing
var mx = setupMultiplex(portStream)
@ -55,8 +56,8 @@ function setupControllerConnection (stream, cb) {
function getCurrentDomain (cb) {
const unknown = '<unknown>'
if (!chrome.tabs) return cb(null, unknown)
chrome.tabs.query({active: true, currentWindow: true}, function (results) {
if (!extension.tabs) return cb(null, unknown)
extension.tabs.query({active: true, currentWindow: true}, function (results) {
var activeTab = results[0]
var currentUrl = activeTab && activeTab.url
var currentDomain = url.parse(currentUrl).host
@ -68,9 +69,9 @@ function getCurrentDomain (cb) {
}
function clearNotifications(){
chrome.notifications.getAll(function (object) {
extension.notifications.getAll(function (object) {
for (let notification in object){
chrome.notifications.clear(notification)
extension.notifications.clear(notification)
}
})
}

15
docs/state_dump.md Normal file
View File

@ -0,0 +1,15 @@
# How to take a State Dump
Sometimes a UI bug is hard to reproduce, but we'd like to rapidly develop against the application state that caused the bug.
In this case, a MetaMask developer will sometimes ask a user with a bug to perform a "state dump", so we can use some internal tools to reproduce and fix the bug.
To take a state dump, follow these steps:
1. Get the MetaMask popup to the point where it shows the bug (the developer will probably specify exactly where).
2. Right click on the extension popup UI, and in the menu, click "Inspect". This will open the developer tools.
3. In case it isn't already selected, click the "Console" tab in the new Developer Tools window.
4. In the console, type this command exactly: `logState()`. This should print a bunch of JSON text into your console.
5. Copy that printed JSON text
6. *Optional*: Annonymize that text if you'd like (you may change all instances of an account address to another valid account address, for example) We may automate the anonymization in the future.
7. Send that JSON text to the developer, ideally pasting it in the issue regarding the bug.

View File

@ -0,0 +1,39 @@
var assert = require('assert')
var sinon = require('sinon')
const ethUtil = require('ethereumjs-util')
var path = require('path')
var Extension = require(path.join(__dirname, '..', '..', 'app', 'scripts', 'lib', 'extension-instance.js'))
describe('extension', function() {
describe('with chrome global', function() {
let extension
beforeEach(function() {
window.chrome = {
alarms: 'foo'
}
extension = new Extension()
})
it('should use the chrome global apis', function() {
assert.equal(extension.alarms, 'foo')
})
})
describe('without chrome global', function() {
let extension
beforeEach(function() {
window.chrome = undefined
window.alarms = 'foo'
extension = new Extension()
})
it('should use the global apis', function() {
assert.equal(extension.alarms, 'foo')
})
})
})

View File

@ -7,6 +7,7 @@ const addressSummary = require('../util').addressSummary
const explorerLink = require('../../lib/explorer-link')
const CopyButton = require('./copyButton')
const vreme = new (require('vreme'))
const extension = require('../../../app/scripts/lib/extension')
const TransactionIcon = require('./transaction-list-item-icon')
@ -49,7 +50,7 @@ TransactionListItem.prototype.render = function () {
if (!transaction.hash || !isLinkable) return
var url = explorerLink(transaction.hash, parseInt(network))
chrome.tabs.create({ url })
extension.tabs.create({ url })
},
style: {
padding: '20px 0',

View File

@ -3,6 +3,7 @@ const Component = require('react').Component
const h = require('react-hyperscript')
const connect = require('react-redux').connect
const actions = require('./actions')
const extension = require('../../app/scripts/lib/extension')
module.exports = connect(mapStateToProps)(InfoScreen)
@ -19,7 +20,7 @@ InfoScreen.prototype.render = function () {
var state = this.props
var manifest
try {
manifest = chrome.runtime.getManifest()
manifest = extension.runtime.getManifest()
} catch (e) {
manifest = { version: '2.0.0' }
}
@ -105,7 +106,7 @@ InfoScreen.prototype.render = function () {
h('a.info', {
target: '_blank',
style: { width: '85vw' },
onClick () { chrome.tabs.create({url: 'mailto:help@metamask.io?subject=Feedback'}) },
onClick () { extension.tabs.create({url: 'mailto:help@metamask.io?subject=Feedback'}) },
}, 'Email us any questions or comments!'),
]),
@ -124,5 +125,5 @@ InfoScreen.prototype.render = function () {
}
InfoScreen.prototype.navigateTo = function (url) {
chrome.tabs.create({ url })
extension.tabs.create({ url })
}