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

EIP-1102: Add option to force-enable provider

This commit is contained in:
bitpshr 2018-10-01 20:52:31 -04:00 committed by Dan Finlay
parent c76c9ca2c8
commit 89b4aa5d62
32 changed files with 674 additions and 786 deletions

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Vystavte účty"
},
"exposeDescription": {
"message": "Vystavte účty na aktuální webové stránky. Užitečné pro starší dappy."
},
"confirmExpose": {
"message": "Opravdu chcete své účty vystavit na stávajícím webu?"
},
"confirmClear": {
"message": "Naozaj chcete vymazať schválené webové stránky?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Expose Konten"
},
"exposeDescription": {
"message": "Expose Konten auf der aktuellen Website. Nützlich für ältere Dapps."
},
"confirmExpose": {
"message": "Möchten Sie Ihre Konten wirklich der aktuellen Website zugänglich machen?"
},
"confirmClear": {
"message": "Möchten Sie die genehmigten Websites wirklich löschen?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Expose Accounts"
},
"exposeDescription": {
"message": "Expose accounts to the current website. Useful for legacy dapps."
},
"confirmExpose": {
"message": "Are you sure you want to expose your accounts to the current website?"
},
"confirmClear": {
"message": "Are you sure you want to clear approved websites?"
},
@ -14,9 +23,6 @@
"clearApprovalData": {
"message": "Clear Approval Data"
},
"approve": {
"message": "Approve"
},
"reject": {
"message": "Reject"
},
@ -890,9 +896,6 @@
"refundAddress": {
"message": "Your Refund Address"
},
"reject": {
"message": "Reject"
},
"rejectAll": {
"message": "Reject All"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Exponer cuentas"
},
"exposeDescription": {
"message": "Exponer cuentas al sitio web actual. Útil para dapps heredados."
},
"confirmExpose": {
"message": "¿Seguro que quieres exponer tus cuentas al sitio web actual?"
},
"confirmClear": {
"message": "¿Seguro que quieres borrar los sitios web aprobados?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Exposer les comptes"
},
"exposeDescription": {
"message": "Exposer des comptes sur le site Web actuel. Utile pour les dapps hérités."
},
"confirmExpose": {
"message": "Êtes-vous sûr de vouloir exposer vos comptes au site Web actuel?"
},
"confirmClear": {
"message": "Êtes-vous sûr de vouloir supprimer les sites Web approuvés?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "खातों का पर्दाफाश करें"
},
"exposeDescription": {
"message": "मौजूदा वेबसाइट पर खातों का पर्दाफाश करें। विरासत डैप्स के लिए उपयोगी।"
},
"confirmExpose": {
"message": "क्या आप वाकई अपने खातों को वर्तमान वेबसाइट पर बेनकाब करना चाहते हैं?"
},
"confirmClear": {
"message": "क्या आप वाकई अनुमोदित वेबसाइटों को साफ़ करना चाहते हैं?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Expose Accounts"
},
"exposeDescription": {
"message": "Esporre gli account al sito Web corrente. Utile per dapps legacy."
},
"confirmExpose": {
"message": "Sei sicuro di voler esporre i tuoi account al sito web corrente?"
},
"confirmClear": {
"message": "Sei sicuro di voler cancellare i siti Web approvati?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "アカウントを公開する"
},
"exposeDescription": {
"message": "アカウントを現在のウェブサイトに公開する。従来のdappsに役立ちます。"
},
"confirmExpose": {
"message": "現在のウェブサイトにアカウントを公開してもよろしいですか?"
},
"confirmClear": {
"message": "承認されたウェブサイトをクリアしてもよろしいですか?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "계정 노출"
},
"exposeDescription": {
"message": "계정을 현재 웹 사이트에 노출하십시오. 기존 dapps에 유용합니다."
},
"confirmExpose": {
"message": "계정을 현재 웹 사이트에 공개 하시겠습니까?"
},
"confirmClear": {
"message": "승인 된 웹 사이트를 삭제 하시겠습니까?"
},
@ -14,9 +23,6 @@
"clearApprovalData": {
"message": "승인 데이터 삭제"
},
"approve": {
"message": "승인하다"
},
"reject": {
"message": "받지 않다"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Expose Accounts"
},
"exposeDescription": {
"message": "Stel accounts vrij op de huidige website. Handig voor legacy dapps."
},
"confirmExpose": {
"message": "Weet u zeker dat u uw accounts wilt weergeven aan de huidige website?"
},
"confirmClear": {
"message": "Weet je zeker dat je goedgekeurde websites wilt wissen?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Ilantad ang Mga Account"
},
"exposeDescription": {
"message": "Ilantad ang mga account sa kasalukuyang website. Kapaki-pakinabang para sa mga dapps ng legacy."
},
"confirmExpose": {
"message": "Sigurado ka bang gusto mong ilantad ang iyong mga account sa kasalukuyang website?"
},
"confirmClear": {
"message": "Sigurado ka bang gusto mong i-clear ang mga naaprubahang website?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Expor contas"
},
"exposeDescription": {
"message": "Exponha contas ao site atual. Útil para dapps herdados."
},
"confirmExpose": {
"message": "Tem certeza de que deseja expor suas contas ao site atual?"
},
"confirmClear": {
"message": "Tem certeza de que deseja limpar sites aprovados?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Открыть счета"
},
"exposeDescription": {
"message": "Выводить счета на текущий веб-сайт. Полезно для старых dapps."
},
"confirmExpose": {
"message": "Вы уверены, что хотите открыть свои аккаунты на текущем веб-сайте?"
},
"confirmClear": {
"message": "Вы уверены, что хотите очистить утвержденные веб-сайты?Tem certeza de que deseja limpar sites aprovados?"
},

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "เปิดเผยบัญชี"
},
"exposeDescription": {
"message": "เปิดเผยบัญชีไปยังเว็บไซต์ปัจจุบัน มีประโยชน์สำหรับ dapps แบบเดิม"
},
"confirmExpose": {
"message": "คุณแน่ใจหรือไม่ว่าต้องการเปิดเผยบัญชีของคุณไปยังเว็บไซต์ปัจจุบัน"
},
"confirmClear": {
"message": "คุณแน่ใจหรือไม่ว่าต้องการล้างเว็บไซต์ที่ผ่านการอนุมัติ"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "கணக்குகளை அம்பலப்படுத்துங்கள்"
},
"exposeDescription": {
"message": "தற்போதைய இணையதளத்திற்கு கணக்குகளை அம்பலப்படுத்துங்கள். மரபணு டாப்ஸ் பயன்படுத்த."
},
"confirmExpose": {
"message": "நிச்சயமாக உங்கள் கணக்குகளை தற்போதைய இணையத்தளத்தில் அம்பலப்படுத்த விரும்புகிறீர்களா?"
},
"confirmClear": {
"message": "அங்கீகரிக்கப்பட்ட வலைத்தளங்களை நிச்சயமாக நீக்க விரும்புகிறீர்களா?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Hesaplarıığa Çıkar"
},
"exposeDescription": {
"message": "Hesapları mevcut web sitesine gösterin. Eski dapps için kullanışlıdır."
},
"confirmExpose": {
"message": "Hesaplarınızı mevcut web sitesine taşımak istediğinizden emin misiniz?"
},
"confirmClear": {
"message": "Onaylanmış web sitelerini silmek istediğinizden emin misiniz?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "Hiển thị tài khoản"
},
"exposeDescription": {
"message": "Hiển thị tài khoản cho trang web hiện tại. Hữu ích cho các ứng dụng cũ."
},
"confirmExpose": {
"message": "Bạn có chắc chắn muốn hiển thị tài khoản của mình cho trang web hiện tại không?"
},
"confirmClear": {
"message": "Bạn có chắc chắn muốn xóa các trang web được phê duyệt không?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "公开账户"
},
"exposeDescription": {
"message": "将帐户公开给当前网站。对传统dapps很有用。"
},
"confirmExpose": {
"message": "您确定要将帐户公开到当前网站吗?"
},
"confirmClear": {
"message": "您确定要清除已批准的网站吗?"
},

View File

@ -1,4 +1,13 @@
{
"exposeAccounts": {
"message": "公開賬戶"
},
"exposeDescription": {
"message": "將帳戶公開給當前網站。對傳統dapps很有用。"
},
"confirmExpose": {
"message": "您確定要將帳戶公開到當前網站嗎?"
},
"confirmClear": {
"message": "您確定要清除已批准的網站嗎?"
},

View File

@ -24,6 +24,7 @@ if (shouldInjectWeb3()) {
injectScript(inpageBundle)
setupStreams()
listenForProviderRequest()
checkForcedInjection()
}
/**
@ -134,10 +135,28 @@ function listenForProviderRequest () {
case 'reject-provider-request':
injectScript(`window.dispatchEvent(new CustomEvent('ethereumprovider', { detail: { error: 'User rejected provider access' }}))`)
break
case 'force-injection':
extension.storage.local.get(['forcedOrigins'], ({ forcedOrigins = [] }) => {
extension.storage.local.set({ forcedOrigins: [ ...forcedOrigins, window.location.hostname ] }, () => {
injectScript(`window.location.reload()`)
})
})
break
}
})
}
/**
* Checks the current origin to see if it exists in the extension's locally-stored list
* off user-whitelisted dapp origins. If it is, this origin will be marked as approved,
* meaning the publicConfig stream will be enabled. This is only meant to ease the transition
* to 1102 and will be removed in the future.
*/
function checkForcedInjection () {
extension.storage.local.get(['forcedOrigins'], ({ forcedOrigins = [] }) => {
originApproved = forcedOrigins.indexOf(window.location.hostname) > -1
})
}
/**
* Error handler for page to plugin stream disconnections

View File

@ -1,4 +1,5 @@
const ObservableStore = require('obs-store')
const extension = require('extensionizer')
/**
* A controller that services user-approved requests for a full Ethereum provider API
@ -26,9 +27,9 @@ class ProviderApprovalController {
*
* @param {string} origin - Origin of the window requesting full provider access
*/
handleProviderRequest (origin) {
async handleProviderRequest (origin) {
this.store.updateState({ providerRequests: [{ origin }] })
if (this.approvedOrigins[origin]) {
if (await this.isApproved(origin)) {
this.approveProviderRequest(origin)
return
}
@ -68,6 +69,7 @@ class ProviderApprovalController {
*/
clearApprovedOrigins () {
this.approvedOrigins = {}
extension.storage.local.set({ forcedOrigins: [] })
}
/**
@ -77,7 +79,18 @@ class ProviderApprovalController {
* @returns {boolean} - True if the origin has been approved
*/
isApproved (origin) {
return this.approvedOrigins[origin]
return new Promise(resolve => {
extension.storage.local.get(['forcedOrigins'], ({ forcedOrigins = [] }) => {
resolve(this.approvedOrigins[origin] || forcedOrigins.indexOf(origin) > -1)
})
})
}
/**
* Called when a user forces the exposure of a full Ethereum provider API
*/
forceInjection () {
this.platform.sendMessage({ action: 'force-injection' }, { active: true })
}
}

View File

@ -37,8 +37,12 @@ inpageProvider.enable = function () {
if (typeof detail.error !== 'undefined') {
reject(detail.error)
} else {
inpageProvider.publicConfigStore.once('update', () => {
resolve(inpageProvider.send({ method: 'eth_accounts' }).result)
inpageProvider.sendAsync({ method: 'eth_accounts', params: [] }, (error, response) => {
if (error) {
reject(error)
} else {
resolve(response.result)
}
})
}
})

View File

@ -275,7 +275,8 @@ module.exports = class MetamaskController extends EventEmitter {
getAccounts: async ({ origin }) => {
// Expose no accounts if this origin has not been approved, preventing
// account-requring RPC methods from completing successfully
if (origin !== 'MetaMask' && !this.providerApprovalController.isApproved(origin)) { return [] }
const isApproved = await this.providerApprovalController.isApproved(origin)
if (origin !== 'MetaMask' && !isApproved) { return [] }
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
const selectedAddress = this.preferencesController.getSelectedAddress()
// only show address if account is unlocked
@ -454,6 +455,7 @@ module.exports = class MetamaskController extends EventEmitter {
approveProviderRequest: providerApprovalController.approveProviderRequest.bind(providerApprovalController),
clearApprovedOrigins: providerApprovalController.clearApprovedOrigins.bind(providerApprovalController),
rejectProviderRequest: providerApprovalController.rejectProviderRequest.bind(providerApprovalController),
forceInjection: providerApprovalController.forceInjection.bind(providerApprovalController),
}
}

View File

@ -225,6 +225,31 @@ ConfigScreen.prototype.render = function () {
h('hr.horizontal-line'),
h('div', {
style: {
marginTop: '20px',
},
}, [
h('p', {
style: {
fontFamily: 'Montserrat Light',
fontSize: '13px',
},
}, 'Expose accounts to the current website. This is useful for legacy dapps.'),
h('br'),
h('button', {
style: {
alignSelf: 'center',
},
onClick (event) {
event.preventDefault()
state.dispatch(actions.forceInjection())
},
}, 'Expose accounts'),
]),
h('hr.horizontal-line'),
h('div', {
style: {
marginTop: '20px',

View File

@ -328,6 +328,7 @@ var actions = {
approveProviderRequest,
rejectProviderRequest,
clearApprovedOrigins,
forceInjection,
}
module.exports = actions
@ -2505,3 +2506,9 @@ function clearApprovedOrigins () {
background.clearApprovedOrigins()
}
}
function forceInjection () {
return (dispatch) => {
background.forceInjection()
}
}

View File

@ -0,0 +1,39 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import Modal, { ModalContent } from '../../modal'
export default class ForceInjection extends PureComponent {
static propTypes = {
hideModal: PropTypes.func.isRequired,
forceInjection: PropTypes.func.isRequired,
}
static contextTypes = {
t: PropTypes.func,
}
handleForce = () => {
const { forceInjection, hideModal } = this.props
forceInjection()
hideModal()
}
render () {
const { t } = this.context
return (
<Modal
onSubmit={this.handleForce}
onCancel={() => this.props.hideModal()}
submitText={t('ok')}
cancelText={t('nevermind')}
submitType="secondary"
>
<ModalContent
title={t('exposeAccounts')}
description={t('confirmExpose')}
/>
</Modal>
)
}
}

View File

@ -0,0 +1,16 @@
import { connect } from 'react-redux'
import { compose } from 'recompose'
import withModalProps from '../../../higher-order-components/with-modal-props'
import ForceInjectionComponent from './force-injection.component'
import { forceInjection } from '../../../actions'
const mapDispatchToProps = dispatch => {
return {
forceInjection: () => dispatch(forceInjection()),
}
}
export default compose(
withModalProps,
connect(null, mapDispatchToProps)
)(ForceInjectionComponent)

View File

@ -0,0 +1 @@
export { default } from './force-injection.container'

View File

@ -29,6 +29,7 @@ import CancelTransaction from './cancel-transaction'
import WelcomeBeta from './welcome-beta'
import RejectTransactions from './reject-transactions'
import ClearApprovedOrigins from './clear-approved-origins'
import ForceInjection from './force-injection'
const modalContainerBaseStyle = {
transform: 'translate3d(-50%, 0, 0px)',
@ -226,6 +227,19 @@ const MODALS = {
},
},
FORCE_INJECTION: {
contents: h(ForceInjection),
mobileModalStyle: {
...modalContainerMobileStyle,
},
laptopModalStyle: {
...modalContainerLaptopStyle,
},
contentStyle: {
borderRadius: '8px',
},
},
OLD_UI_NOTIFICATION_MODAL: {
contents: [
h(NotifcationModal, {

View File

@ -46,6 +46,7 @@ export default class SettingsTab extends PureComponent {
revealSeedConfirmation: PropTypes.func,
setFeatureFlagToBeta: PropTypes.func,
showClearApprovalModal: PropTypes.func,
showForceInjectionModal: PropTypes.func,
showResetAccountConfirmationModal: PropTypes.func,
warning: PropTypes.string,
history: PropTypes.object,
@ -307,6 +308,36 @@ export default class SettingsTab extends PureComponent {
)
}
renderForceInjection () {
const { t } = this.context
const { showForceInjectionModal } = this.props
return (
<div className="settings-page__content-row">
<div className="settings-page__content-item">
<span>{ t('exposeAccounts') }</span>
<span className="settings-page__content-description">
{ t('exposeDescription') }
</span>
</div>
<div className="settings-page__content-item">
<div className="settings-page__content-item-col">
<Button
type="secondary"
large
className="settings-tab__button--orange"
onClick={event => {
event.preventDefault()
showForceInjectionModal()
}}
>
{ t('exposeAccounts') }
</Button>
</div>
</div>
</div>
)
}
renderSeedWords () {
const { t } = this.context
const { history } = this.props
@ -505,6 +536,7 @@ export default class SettingsTab extends PureComponent {
{ this.renderStateLogs() }
{ this.renderSeedWords() }
{ this.renderClearApproval() }
{ this.renderForceInjection() }
{ !isMascara && this.renderOldUI() }
{ this.renderResetAccount() }
{ this.renderBlockieOptIn() }

View File

@ -60,6 +60,7 @@ const mapDispatchToProps = dispatch => {
return dispatch(setUseNativeCurrencyAsPrimaryCurrencyPreference(value))
},
showClearApprovalModal: () => dispatch(showModal({ name: 'CLEAR_APPROVED_ORIGINS' })),
showForceInjectionModal: () => dispatch(showModal({ name: 'FORCE_INJECTION' })),
}
}