Newer
Older
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component } from 'react';
import { FormattedMessage } from 'react-intl';
import isElectron from 'is-electron';
import { observer } from 'mobx-react';
Axel Chalon
committed
import { getBuildPath } from '../util/host';
Axel Chalon
committed
import builtinDapps from '../Dapps/dappsBuiltin.json';
import DappsStore from '../Dapps/store';
import HistoryStore from '@parity/shared/lib/mobx/historyStore';
import RequestsStore from '../DappRequests/store';
Axel Chalon
committed
import styles from './dapp.css';
@observer
export default class Dapp extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
};
static propTypes = {
params: PropTypes.object
};
state = {
app: null,
loading: true
};
store = DappsStore.get(this.context.api);
historyStore = HistoryStore.get('dapps');
requestsStore = RequestsStore.get(this.context.api)
componentWillMount () {
const { id } = this.props.params;
Axel Chalon
committed
if (!builtinDapps[id] || !builtinDapps[id].skipHistory) {
this.historyStore.add(id);
}
this.loadApp(id);
}
componentWillReceiveProps (nextProps) {
if (nextProps.params.id !== this.props.params.id) {
this.loadApp(nextProps.params.id);
}
}
handleIframe = () => {
window.addEventListener('message', this.requestsStore.receiveMessage, false);
}
handleWebview = webview => {
if (!webview) {
return;
}
// Log console.logs from webview
webview.addEventListener('console-message', e => {
console.log('[DAPP]', e.message);
});
// Open all <a target="_blank"> in browser
webview.addEventListener('new-window', (e) => {
const protocol = url.parse(e.url).protocol;
if (protocol === 'http:' || protocol === 'https:') {
const { shell } = window.require('electron');
shell.openExternal(e.url);
}
});
// Reput eventListeners when webview has finished loading dapp
webview.addEventListener('did-finish-load', () => {
this.setState({ loading: false });
});
// Listen to IPC messages from this webview. More particularly, to IPC
// messages coming from the preload.js injected in this webview.
webview.addEventListener('ipc-message', event => {
this.requestsStore.receiveMessage({
...event.args[0],
source: event.target
});
});
loadApp (id) {
this.setState({ loading: true });
this.store
.loadApp(id)
.then((app) => {
this.setState({ loading: false, app });
})
.catch(() => {
this.setState({ loading: false });
});
}
renderIframe = (src, hash) => (
<iframe
className={ styles.frame }
frameBorder={ 0 }
id='dappFrame'
name={ name }
ref={ this.handleIframe }
sandbox='allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation'
scrolling='auto'
src={ `${src}${hash}` }
/>
)
renderWebview = (src, hash) => {
const preload = `file://${path.join(
Axel Chalon
committed
getBuildPath(),
// https://electronjs.org/docs/tutorial/security#3-enable-context-isolation-for-remote-content
className={ styles.frame }
id='dappFrame'
ref={ this.handleWebview }
src={ `${src}${hash}` }
partition={ `persist:${this.state.app.id}` }
webpreferences='contextIsolation'
render () {
const { params } = this.props;
const { app, loading } = this.state;
if (loading) {
return (
<div className={ styles.full }>
<p className={ styles.loading }>
<FormattedMessage
id='dapp.loading'
defaultMessage='Loading...'
/>
</p>
</div>
);
}
if (!app) {
return (
<div className={ styles.full }>
<FormattedMessage
id='dapp.unavailable'
defaultMessage='The dapp cannot be reached'
/>
let src = `${app.localUrl}?appId=${app.id}`;
let hash = '';
if (params.details) {
hash = `#/${params.details}`;
}
? this.renderWebview(src, hash)
: this.renderIframe(src, hash);