diff options
author | kumavis <kumavis@users.noreply.github.com> | 2019-05-04 01:32:05 +0800 |
---|---|---|
committer | Frankie <frankie.diamond@gmail.com> | 2019-05-04 01:32:05 +0800 |
commit | 2845398c3d824e5da1830ba7905ffdbf8149cf9e (patch) | |
tree | a95ca83b7cf8ac42cef5ad08d29e8240f8bf1e30 /app/scripts/metamask-controller.js | |
parent | 2ff522604b2a5f45697087613de5efb9bba58790 (diff) | |
download | tangerine-wallet-browser-2845398c3d824e5da1830ba7905ffdbf8149cf9e.tar tangerine-wallet-browser-2845398c3d824e5da1830ba7905ffdbf8149cf9e.tar.gz tangerine-wallet-browser-2845398c3d824e5da1830ba7905ffdbf8149cf9e.tar.bz2 tangerine-wallet-browser-2845398c3d824e5da1830ba7905ffdbf8149cf9e.tar.lz tangerine-wallet-browser-2845398c3d824e5da1830ba7905ffdbf8149cf9e.tar.xz tangerine-wallet-browser-2845398c3d824e5da1830ba7905ffdbf8149cf9e.tar.zst tangerine-wallet-browser-2845398c3d824e5da1830ba7905ffdbf8149cf9e.zip |
Refactor ProviderApprovalController to use rpc and publicConfigStore (#6410)
* Ensure home screen does not render if there are unapproved txs (#6501)
* Ensure that the confirm screen renders before the home screen if there are unapproved txs.
* Only render confirm screen before home screen on mount.
* inpage - revert _metamask api to isEnabled isApproved isUnlocked
Diffstat (limited to 'app/scripts/metamask-controller.js')
-rw-r--r-- | app/scripts/metamask-controller.js | 102 |
1 files changed, 80 insertions, 22 deletions
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index be2090f63..7d666ae88 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -7,8 +7,10 @@ const EventEmitter = require('events') const pump = require('pump') const Dnode = require('dnode') +const pify = require('pify') const ObservableStore = require('obs-store') const ComposableObservableStore = require('./lib/ComposableObservableStore') +const createDnodeRemoteGetter = require('./lib/createDnodeRemoteGetter') const asStream = require('obs-store/lib/asStream') const AccountTracker = require('./lib/account-tracker') const RpcEngine = require('json-rpc-engine') @@ -87,7 +89,7 @@ module.exports = class MetamaskController extends EventEmitter { this.createVaultMutex = new Mutex() // network store - this.networkController = new NetworkController(initState.NetworkController, this.platform) + this.networkController = new NetworkController(initState.NetworkController) // preferences controller this.preferencesController = new PreferencesController({ @@ -235,15 +237,17 @@ module.exports = class MetamaskController extends EventEmitter { this.messageManager = new MessageManager() this.personalMessageManager = new PersonalMessageManager() this.typedMessageManager = new TypedMessageManager({ networkController: this.networkController }) - this.publicConfigStore = this.initPublicConfigStore() + + // ensure isClientOpenAndUnlocked is updated when memState updates + this.on('update', (memState) => { + this.isClientOpenAndUnlocked = memState.isUnlocked && this._isClientOpen + }) this.providerApprovalController = new ProviderApprovalController({ closePopup: opts.closePopup, keyringController: this.keyringController, openPopup: opts.openPopup, - platform: opts.platform, preferencesController: this.preferencesController, - publicConfigStore: this.publicConfigStore, }) this.store.updateStructure({ @@ -322,22 +326,32 @@ module.exports = class MetamaskController extends EventEmitter { * Constructor helper: initialize a public config store. * This store is used to make some config info available to Dapps synchronously. */ - initPublicConfigStore () { - // get init state + createPublicConfigStore ({ checkIsEnabled }) { + // subset of state for metamask inpage provider const publicConfigStore = new ObservableStore() - // memStore -> transform -> publicConfigStore - this.on('update', (memState) => { - this.isClientOpenAndUnlocked = memState.isUnlocked && this._isClientOpen + // setup memStore subscription hooks + this.on('update', updatePublicConfigStore) + updatePublicConfigStore(this.getState()) + + publicConfigStore.destroy = () => { + this.removeEventListener('update', updatePublicConfigStore) + } + + function updatePublicConfigStore (memState) { const publicState = selectPublicState(memState) publicConfigStore.putState(publicState) - }) + } - function selectPublicState (memState) { + function selectPublicState ({ isUnlocked, selectedAddress, network, completedOnboarding }) { + const isEnabled = checkIsEnabled() + const isReady = isUnlocked && isEnabled const result = { - selectedAddress: memState.isUnlocked ? memState.selectedAddress : undefined, - networkVersion: memState.network, - onboardingcomplete: memState.completedOnboarding, + isUnlocked, + isEnabled, + selectedAddress: isReady ? selectedAddress : undefined, + networkVersion: network, + onboardingcomplete: completedOnboarding, } return result } @@ -477,9 +491,10 @@ module.exports = class MetamaskController extends EventEmitter { signTypedMessage: nodeify(this.signTypedMessage, this), cancelTypedMessage: this.cancelTypedMessage.bind(this), - approveProviderRequest: providerApprovalController.approveProviderRequest.bind(providerApprovalController), + // provider approval + approveProviderRequestByOrigin: providerApprovalController.approveProviderRequestByOrigin.bind(providerApprovalController), + rejectProviderRequestByOrigin: providerApprovalController.rejectProviderRequestByOrigin.bind(providerApprovalController), clearApprovedOrigins: providerApprovalController.clearApprovedOrigins.bind(providerApprovalController), - rejectProviderRequest: providerApprovalController.rejectProviderRequest.bind(providerApprovalController), } } @@ -1296,8 +1311,9 @@ module.exports = class MetamaskController extends EventEmitter { // setup multiplexing const mux = setupMultiplex(connectionStream) // connect features - this.setupProviderConnection(mux.createStream('provider'), originDomain) - this.setupPublicConfig(mux.createStream('publicConfig')) + const publicApi = this.setupPublicApi(mux.createStream('publicApi'), originDomain) + this.setupProviderConnection(mux.createStream('provider'), originDomain, publicApi) + this.setupPublicConfig(mux.createStream('publicConfig'), originDomain) } /** @@ -1370,7 +1386,7 @@ module.exports = class MetamaskController extends EventEmitter { * @param {*} outStream - The stream to provide over. * @param {string} origin - The URI of the requesting resource. */ - setupProviderConnection (outStream, origin) { + setupProviderConnection (outStream, origin, publicApi) { // setup json rpc engine stack const engine = new RpcEngine() const provider = this.provider @@ -1390,6 +1406,11 @@ module.exports = class MetamaskController extends EventEmitter { engine.push(subscriptionManager.middleware) // watch asset engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController)) + // requestAccounts + engine.push(this.providerApprovalController.createMiddleware({ + origin, + getSiteMetadata: publicApi && publicApi.getSiteMetadata, + })) // forward to metamask primary provider engine.push(providerAsMiddleware(provider)) @@ -1418,12 +1439,18 @@ module.exports = class MetamaskController extends EventEmitter { * * @param {*} outStream - The stream to provide public config over. */ - setupPublicConfig (outStream) { - const configStream = asStream(this.publicConfigStore) + setupPublicConfig (outStream, originDomain) { + const configStore = this.createPublicConfigStore({ + // check the providerApprovalController's approvedOrigins + checkIsEnabled: () => this.providerApprovalController.shouldExposeAccounts(originDomain), + }) + const configStream = asStream(configStore) + pump( configStream, outStream, (err) => { + configStore.destroy() configStream.destroy() if (err) log.error(err) } @@ -1431,6 +1458,38 @@ module.exports = class MetamaskController extends EventEmitter { } /** + * A method for providing our public api over a stream. + * This includes a method for setting site metadata like title and image + * + * @param {*} outStream - The stream to provide the api over. + */ + setupPublicApi (outStream, originDomain) { + const dnode = Dnode() + // connect dnode api to remote connection + pump( + outStream, + dnode, + outStream, + (err) => { + // report any error + if (err) log.error(err) + } + ) + + const getRemote = createDnodeRemoteGetter(dnode) + + const publicApi = { + // wrap with an await remote + getSiteMetadata: async () => { + const remote = await getRemote() + return await pify(remote.getSiteMetadata)() + }, + } + + return publicApi + } + + /** * Handle a KeyringController update * @param {object} state the KC state * @return {Promise<void>} @@ -1734,7 +1793,6 @@ module.exports = class MetamaskController extends EventEmitter { * Locks MetaMask */ setLocked () { - this.providerApprovalController.setLocked() return this.keyringController.setLocked() } } |