From 9101812552f89439addfa4fbd783ec4bf6b47e0e Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 18 Jul 2016 17:57:23 -0700 Subject: inpage - add try/catch to cleanContextForImports --- app/scripts/inpage.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index f5e54cd7b..c2b445bd1 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -53,9 +53,17 @@ var __define function cleanContextForImports () { __define = global.define - delete global.define + try { + delete global.define + } catch (_) { + console.warn('MetaMask - global.define could not be deleted.') + } } function restoreContextAfterImports () { - global.define = __define + try { + global.define = __define + } catch { + console.warn('MetaMask - global.define could not be overwritten.') + } } -- cgit From b2afa16925227fbb39e30fce8f9f4bca09dec20e Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 18 Jul 2016 18:08:29 -0700 Subject: typo fix --- app/scripts/inpage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index c2b445bd1..055235671 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -63,7 +63,7 @@ function cleanContextForImports () { function restoreContextAfterImports () { try { global.define = __define - } catch { + } catch (_) { console.warn('MetaMask - global.define could not be overwritten.') } } -- cgit From 5567ea8dc5f387d971b51bd4cf46abd6e7979688 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 20 Jul 2016 10:16:18 -0700 Subject: Version 2.6.2 (#470) --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index d1a4a2f54..2c5629f7a 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -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": { -- cgit From cdd7e40545af8e62fc586f8da120e8d05ca90653 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 20 Jul 2016 14:54:07 -0700 Subject: Make injected web3 fail hard on sync methods (#471) Make injected web3 fail hard on sync methods --- app/scripts/lib/inpage-provider.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 3b6ec154f..e387be895 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -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) { -- cgit From 6658bea8d444281491718f8eee7bc3ae42f91b69 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 21 Jul 2016 10:45:32 -0700 Subject: Implement some cross-browser practices (#473) * Add mozilla plugin key to manifest * Move all chrome references into platform-checking module Addresses #453 * Add chrome global back to linter blacklist * Add tests --- app/manifest.json | 5 +++++ app/scripts/background.js | 7 ++++--- app/scripts/chromereload.js | 3 ++- app/scripts/contentscript.js | 7 ++++--- app/scripts/lib/extension-instance.js | 38 +++++++++++++++++++++++++++++++++++ app/scripts/lib/extension.js | 14 +++++++++++++ app/scripts/lib/notifications.js | 31 ++++++++++++++-------------- app/scripts/metamask-controller.js | 7 ++++--- app/scripts/popup.js | 11 +++++----- 9 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 app/scripts/lib/extension-instance.js create mode 100644 app/scripts/lib/extension.js (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 2c5629f7a..4cca79c72 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -37,6 +37,11 @@ "all_frames": false } ], + "applications": { + "gecko": { + "id": "MOZILLA_EXTENSION_ID" + } + }, "permissions": [ "notifications", "storage", diff --git a/app/scripts/background.js b/app/scripts/background.js index 801dc95cf..34c994ab7 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -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 () { diff --git a/app/scripts/chromereload.js b/app/scripts/chromereload.js index 283a131f1..cd85a8114 100644 --- a/app/scripts/chromereload.js +++ b/app/scripts/chromereload.js @@ -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) { diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 60b37284e..0ffe93e3c 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -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)) @@ -49,4 +50,4 @@ function setupStreams(){ function shouldInjectWeb3(){ var shouldInject = (window.location.href.indexOf('.pdf') === -1) return shouldInject -} \ No newline at end of file +} diff --git a/app/scripts/lib/extension-instance.js b/app/scripts/lib/extension-instance.js new file mode 100644 index 000000000..eeab6c6d0 --- /dev/null +++ b/app/scripts/lib/extension-instance.js @@ -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 diff --git a/app/scripts/lib/extension.js b/app/scripts/lib/extension.js new file mode 100644 index 000000000..4b670490f --- /dev/null +++ b/app/scripts/lib/extension.js @@ -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() diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index b6590b0e5..6c1601df1 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -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', diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 63970799d..17af4cc29 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -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 { @@ -239,19 +240,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() } } diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 2e5b98896..20be15df7 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -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 = '' - 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) } }) } -- cgit From fcd523abe4c5e8c4da7f176b2fc15578903384b7 Mon Sep 17 00:00:00 2001 From: Frankie Date: Thu, 21 Jul 2016 13:41:10 -0700 Subject: Buy button (#474) * WIP: Buy button link * Add buy eth and the buy eth warning message * Add css * Move the opening of coinbase page to background and send to faucet if on test net * Create a Warning about storeing eth * Finish Buy button and Eth store warning screen * Add to CHANGELOG * fix frankies deletion and change chrome to extension --- app/scripts/lib/config-manager.js | 10 ++++++++++ app/scripts/lib/idStore.js | 3 ++- app/scripts/metamask-controller.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index caaae8a75..d7df5343b 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -270,3 +270,13 @@ ConfigManager.prototype.getConfirmed = function () { return ('isConfirmed' in data) && data.isConfirmed } +ConfigManager.prototype.setShouldntShowWarning = function (confirmed) { + var data = this.getData() + data.isEthConfirmed = confirmed + this.setData(data) +} + +ConfigManager.prototype.getShouldntShowWarning = function () { + var data = this.getData() + return ('isEthConfirmed' in data) && data.isEthConfirmed +} diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index 2c8e9108b..c6ac55a03 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -94,6 +94,7 @@ IdentityStore.prototype.getState = function () { isUnlocked: this._isUnlocked(), seedWords: seedWords, isConfirmed: configManager.getConfirmed(), + isEthConfirmed: configManager.getShouldntShowWarning(), unconfTxs: configManager.unconfirmedTxs(), transactions: configManager.getTxList(), unconfMsgs: messageManager.unconfirmedMsgs(), @@ -199,7 +200,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone time: time, status: 'unconfirmed', } - + console.log('addUnconfirmedTransaction:', txData) // keep the onTxDoneCb around for after approval/denial (requires user interaction) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 17af4cc29..4f03ace8f 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -40,6 +40,7 @@ module.exports = class MetamaskController { setProviderType: this.setProviderType.bind(this), useEtherscanProvider: this.useEtherscanProvider.bind(this), agreeToDisclaimer: this.agreeToDisclaimer.bind(this), + agreeToEthWarning: this.agreeToEthWarning.bind(this), // forward directly to idStore createNewVault: idStore.createNewVault.bind(idStore), recoverFromSeed: idStore.recoverFromSeed.bind(idStore), @@ -56,6 +57,8 @@ module.exports = class MetamaskController { saveAccountLabel: idStore.saveAccountLabel.bind(idStore), tryPassword: idStore.tryPassword.bind(idStore), recoverSeed: idStore.recoverSeed.bind(idStore), + // coinbase + buyEth: this.buyEth.bind(this), } } @@ -237,6 +240,15 @@ module.exports = class MetamaskController { } } + agreeToEthWarning (cb) { + try { + this.configManager.setShouldntShowWarning(true) + cb() + } catch (e) { + cb(e) + } + } + // called from popup setRpcTarget (rpcTarget) { this.configManager.setRpcTarget(rpcTarget) @@ -254,6 +266,22 @@ module.exports = class MetamaskController { this.configManager.useEtherscanProvider() extension.runtime.reload() } + + buyEth (address, amount) { + if (!amount) amount = '5' + + var network = this.idStore._currentState.network + var url = `https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=${amount}&address=${address}&crypto_currency=ETH` + + if (network === '2') { + url = 'https://testfaucet.metamask.io/' + } + + extension.tabs.create({ + url, + }) + } + } function noop () {} -- cgit From 5d93e8fa7433a55e8623039887f7d2032796b451 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 21 Jul 2016 13:42:09 -0700 Subject: Version 2.7.0 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 4cca79c72..88b097f5d 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_appName__", "short_name": "Metamask", - "version": "2.6.2", + "version": "2.7.0", "manifest_version": 2, "description": "__MSG_appDescription__", "icons": { -- cgit From 0bbfedc2bf21d8c3eec17fef35e93a98a946469e Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 21 Jul 2016 16:50:51 -0700 Subject: Manifest fix for firefox-specific field (#475) * Remove firefox-only manifest.json line. * Changelog change. --- app/manifest.json | 5 ----- 1 file changed, 5 deletions(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 4cca79c72..2c5629f7a 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -37,11 +37,6 @@ "all_frames": false } ], - "applications": { - "gecko": { - "id": "MOZILLA_EXTENSION_ID" - } - }, "permissions": [ "notifications", "storage", -- cgit From f3ea891e727810ba29c6d893f27073e9e11efed2 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 25 Jul 2016 13:28:38 -0700 Subject: Allow page injection to look for cross-browser APIs appropriately --- app/scripts/contentscript.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 0ffe93e3c..43c48dd93 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -11,7 +11,8 @@ if (shouldInjectWeb3()) { function setupInjection(){ // inject in-page script var scriptTag = document.createElement('script') - scriptTag.src = extension.extension.getURL('scripts/inpage.js') + var urlGetter = extension.extension || chrome.extension + scriptTag.src = urlGetter.getURL('scripts/inpage.js') scriptTag.onload = function () { this.parentNode.removeChild(this) } var container = document.head || document.documentElement // append as first child -- cgit From b07bbc14e1dc745543c7c95d6a846a789fbf2f81 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 25 Jul 2016 13:46:33 -0700 Subject: Clean up extension polyfill abstraction --- app/scripts/contentscript.js | 21 +++++++++++++-------- app/scripts/lib/extension-instance.js | 7 +------ 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 43c48dd93..d85675e61 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -9,14 +9,19 @@ if (shouldInjectWeb3()) { } function setupInjection(){ - // inject in-page script - var scriptTag = document.createElement('script') - var urlGetter = extension.extension || chrome.extension - scriptTag.src = urlGetter.getURL('scripts/inpage.js') - scriptTag.onload = function () { this.parentNode.removeChild(this) } - var container = document.head || document.documentElement - // append as first child - container.insertBefore(scriptTag, container.children[0]) + try { + + // inject in-page script + var scriptTag = document.createElement('script') + 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 + container.insertBefore(scriptTag, container.children[0]) + + } catch (e) { + console.error('Metamask injection failed.', e) + } } function setupStreams(){ diff --git a/app/scripts/lib/extension-instance.js b/app/scripts/lib/extension-instance.js index eeab6c6d0..e0e7c948b 100644 --- a/app/scripts/lib/extension-instance.js +++ b/app/scripts/lib/extension-instance.js @@ -24,14 +24,9 @@ const apis = [ function Extension () { const _this = this - let global = window - - if (window.chrome) { - global = window.chrome - } apis.forEach(function (api) { - _this[api] = global[api] + _this[api] = chrome ? chrome[api] : window[api] || browser.extension[api] }) } -- cgit From 913a9e85bd24a286c3399ab6e9a0c47fdfbeae0d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 25 Jul 2016 16:34:29 -0700 Subject: Inject inpage script synchronously Huge thanks to the Firefox team, for their help on the issue of our long-standing inpage script race condition. http://stackoverflow.com/questions/38577656/how-can-i-make-a-firefox-add-on-contentscript-inject-and-run-a-script-before-oth The problem is that we were injecting a `script` tag and assigning its `src` attribute, which triggers an asynchronous fetch request, and does not guarantee execution order! (That was news to me!) Instead, I'm now assigning the `script` tag a `textContent` value of the script to inject, and it seems to fix the problem! There is also a Firefox-only API that could solve this whole problem in an even more elegant way, so we might want to expose a code path for that solution later on: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction Allows you to expose an object from one scope to another. There was even talk of creating a polyfill for it that does virtually what we do, message passing between contexts. --- app/scripts/contentscript.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index d85675e61..103ea5348 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -3,6 +3,17 @@ const PortStream = require('./lib/port-stream.js') const ObjectMultiplex = require('./lib/obj-multiplex') const extension = require('./lib/extension') +const fs = require('fs') +const path = require('path') +const inpageText = fs.readFileSync(__dirname + '/inpage.js').toString() + +// Eventually this streaming injection could be replaced with: +// https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction +// +// But for now that is only Firefox +// If we create a FireFox-only code path using that API, +// MetaMask will be much faster loading and performant on Firefox. + if (shouldInjectWeb3()) { setupInjection() setupStreams() @@ -14,6 +25,7 @@ function setupInjection(){ // inject in-page script var scriptTag = document.createElement('script') scriptTag.src = extension.extension.getURL('scripts/inpage.js') + scriptTag.textContent = inpageText scriptTag.onload = function () { this.parentNode.removeChild(this) } var container = document.head || document.documentElement // append as first child @@ -50,7 +62,6 @@ function setupStreams(){ pluginStream.on('close', function () { reloadStream.write({ method: 'reset' }) }) - } function shouldInjectWeb3(){ -- cgit From be74589f49bbe977f881b17a0383cafa4336d9b4 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 25 Jul 2016 17:33:22 -0700 Subject: Fix extension tests --- app/scripts/contentscript.js | 2 +- app/scripts/lib/extension-instance.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 103ea5348..1eb04059d 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -5,7 +5,7 @@ const extension = require('./lib/extension') const fs = require('fs') const path = require('path') -const inpageText = fs.readFileSync(__dirname + '/inpage.js').toString() +const inpageText = fs.readFileSync(path.join(__dirname + '/inpage.js')).toString() // Eventually this streaming injection could be replaced with: // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction diff --git a/app/scripts/lib/extension-instance.js b/app/scripts/lib/extension-instance.js index e0e7c948b..b9d0ed06d 100644 --- a/app/scripts/lib/extension-instance.js +++ b/app/scripts/lib/extension-instance.js @@ -26,7 +26,10 @@ function Extension () { const _this = this apis.forEach(function (api) { - _this[api] = chrome ? chrome[api] : window[api] || browser.extension[api] + _this[api] = chrome !== undefined && chrome[api] ? chrome[api] + : window[api] ? window[api] + : browser && browser.extension && browser.extension[api] + ? browser.extension[api] : null }) } -- cgit From b43b9f13e97258d6d546e62a2fd280b44045a610 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 25 Jul 2016 17:47:14 -0700 Subject: Fix integration tests --- app/scripts/lib/extension-instance.js | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/extension-instance.js b/app/scripts/lib/extension-instance.js index b9d0ed06d..eb3b8a1e9 100644 --- a/app/scripts/lib/extension-instance.js +++ b/app/scripts/lib/extension-instance.js @@ -26,10 +26,25 @@ function Extension () { const _this = this apis.forEach(function (api) { - _this[api] = chrome !== undefined && chrome[api] ? chrome[api] - : window[api] ? window[api] - : browser && browser.extension && browser.extension[api] - ? browser.extension[api] : null + + _this[api] = null + + try { + if (chrome[api]) { + _this[api] = chrome[api] + } + } catch (e) {} + + try { + if (window[api]) { + _this[api] = window[api] + } + } catch (e) {} + + try { + _this.api = browser.extension[api] + } catch (e) {} + }) } -- cgit From 2368c2993d44375203e0b85158bac707489d1137 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 26 Jul 2016 15:15:40 -0700 Subject: Add platform specific builds and zip tasks (#486) * Add platform specific folders to dist folder * Remove gulp hacks * Add platform specific bundling dev and dist tasks now build into platform-specific folders within the `dist` folder. Added tasks `gulp zip` and `gulp dist`. `zip` builds the platform-specific folders into platform-specific bundles within the `dist` folder. `dist` builds and then zips all at once. * Fix chrome bundle zipping * Fix broken reference in eth warning * Fix but where web3.eth.accounts are not available in firefox. * Bump changelog --- app/manifest.json | 5 +++++ app/scripts/lib/remote-store.js | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 2c5629f7a..7039caeb8 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -8,6 +8,11 @@ "16": "images/icon-16.png", "128": "images/icon-128.png" }, + "applications": { + "gecko": { + "id": "webextension@metamask.io" + } + }, "default_locale": "en", "background": { "scripts": [ diff --git a/app/scripts/lib/remote-store.js b/app/scripts/lib/remote-store.js index fbfab7bad..c81d5151c 100644 --- a/app/scripts/lib/remote-store.js +++ b/app/scripts/lib/remote-store.js @@ -52,7 +52,7 @@ HostStore.prototype.set = function (key, value) { HostStore.prototype.createStream = function () { var dnode = Dnode({ - // update: this._didUpdate.bind(this), + update: this._didUpdate.bind(this), }) dnode.on('remote', this._didConnect.bind(this)) return dnode -- cgit From 7fe3170c6f5661f588dfbd8bbc074318522091a6 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 26 Jul 2016 17:02:54 -0700 Subject: Enhance manifest details --- app/manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 95aee245c..9f49d7b52 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,9 +1,9 @@ { - "name": "__MSG_appName__", + "name": "MetaMask", "short_name": "Metamask", "version": "2.7.0", "manifest_version": 2, - "description": "__MSG_appDescription__", + "description": "Ethereum Browser Extension", "icons": { "16": "images/icon-16.png", "128": "images/icon-128.png" -- cgit From 43784e21438fe9b46bf2d77bb2c31ab3ef06614c Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 27 Jul 2016 16:49:11 -0700 Subject: Version 2.7.1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 9f49d7b52..e49511b27 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "2.7.0", + "version": "2.7.1", "manifest_version": 2, "description": "Ethereum Browser Extension", "icons": { -- cgit From 9b43ec2278a5647c427c426ed798ab90bbf093cc Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 28 Jul 2016 10:53:51 -0700 Subject: Add eth classic to provider menu --- app/scripts/chromereload.js | 1 - app/scripts/config.js | 2 ++ app/scripts/lib/config-manager.js | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/chromereload.js b/app/scripts/chromereload.js index cd85a8114..88333ba8a 100644 --- a/app/scripts/chromereload.js +++ b/app/scripts/chromereload.js @@ -30,7 +30,6 @@ // } // }; -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) { diff --git a/app/scripts/config.js b/app/scripts/config.js index f26e6778d..5f6ffd936 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -1,12 +1,14 @@ const MAINET_RPC_URL = 'https://mainnet.infura.io/' const TESTNET_RPC_URL = 'https://morden.infura.io/' const DEFAULT_RPC_URL = TESTNET_RPC_URL +const CLASSIC_RPC_URL = 'https://mainnet-nf.infura.io/' module.exports = { network: { default: DEFAULT_RPC_URL, mainnet: MAINET_RPC_URL, testnet: TESTNET_RPC_URL, + classic: CLASSIC_RPC_URL, }, } diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index d7df5343b..727cd46fc 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -4,6 +4,7 @@ const migrations = require('./migrations') const TESTNET_RPC = MetamaskConfig.network.testnet const MAINNET_RPC = MetamaskConfig.network.mainnet +const CLASSIC_RPC = MetamaskConfig.network.classic /* The config-manager is a convenience object * wrapping a pojo-migrator. @@ -144,6 +145,9 @@ ConfigManager.prototype.getCurrentRpcAddress = function () { case 'testnet': return TESTNET_RPC + case 'classic': + return CLASSIC_RPC + default: return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC } -- cgit From 5ceed48db9a7ff0655d75ac31788fdc48c8c876b Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 28 Jul 2016 11:53:33 -0700 Subject: Fix broken reference to host store.didUpdate I'd returned this line because it seemed to fix Firefox compatibility, now it seems like that wasn't the case. Removing it again. --- app/scripts/lib/remote-store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/remote-store.js b/app/scripts/lib/remote-store.js index c81d5151c..fbfab7bad 100644 --- a/app/scripts/lib/remote-store.js +++ b/app/scripts/lib/remote-store.js @@ -52,7 +52,7 @@ HostStore.prototype.set = function (key, value) { HostStore.prototype.createStream = function () { var dnode = Dnode({ - update: this._didUpdate.bind(this), + // update: this._didUpdate.bind(this), }) dnode.on('remote', this._didConnect.bind(this)) return dnode -- cgit From 019581bd1f6727486afcd3fadf1e31c90fcf02c2 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 29 Jul 2016 13:08:57 -0700 Subject: Version 2.7.2 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index e49511b27..a1074178e 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "2.7.1", + "version": "2.7.2", "manifest_version": 2, "description": "Ethereum Browser Extension", "icons": { -- cgit From c9c8fbf2ec306a62ef71eafed4fcc2353ea257f4 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 29 Jul 2016 13:27:39 -0700 Subject: Fix account selection updating --- app/scripts/metamask-controller.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 4f03ace8f..dd43ac2fc 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -165,6 +165,7 @@ module.exports = class MetamaskController { function configToPublic (state) { return { provider: state.provider, + selectedAddress: state.selectedAccount, } } // dump obj into store -- cgit From f9e81bdd997275211aeb891f2497a0b5c8a15075 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 29 Jul 2016 13:28:26 -0700 Subject: Version 2.7.3 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index a1074178e..fa71742b1 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "2.7.2", + "version": "2.7.3", "manifest_version": 2, "description": "Ethereum Browser Extension", "icons": { -- cgit From abfc5632efcc72b3ad45ec1df8bf5889f75a8472 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 10 Aug 2016 10:54:55 -0700 Subject: Fix ether warning checkbox. --- app/scripts/lib/config-manager.js | 8 ++++++-- app/scripts/metamask-controller.js | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 727cd46fc..3d84edfd0 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -274,9 +274,13 @@ ConfigManager.prototype.getConfirmed = function () { return ('isConfirmed' in data) && data.isConfirmed } -ConfigManager.prototype.setShouldntShowWarning = function (confirmed) { +ConfigManager.prototype.setShouldntShowWarning = function () { var data = this.getData() - data.isEthConfirmed = confirmed + if (data.isEthConfirmed) { + data.isEthConfirmed = !data.isEthConfirmed + } else { + data.isEthConfirmed = true + } this.setData(data) } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index dd43ac2fc..e7e96a472 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -243,7 +243,7 @@ module.exports = class MetamaskController { agreeToEthWarning (cb) { try { - this.configManager.setShouldntShowWarning(true) + this.configManager.setShouldntShowWarning() cb() } catch (e) { cb(e) -- cgit