Skip to content
This repository has been archived by the owner on Feb 26, 2020. It is now read-only.

Commit

Permalink
Use persistent storage (#177) (#186)
Browse files Browse the repository at this point in the history
* Use persistent storage for webviews

* Update .gitlab-ci.yml

enable gitsync

* Retrieve dapp token internally

* Remove shell_requestNewToken RPC method. The token must be retrieved internally (by importing DappsRequestsStore in Parity UI), this way we can be sure that the appId is coming from a trusted source. The token, along with the appId, are now passed as query string parameters to the dapp (and to subsequent pages during in-dapp navigation)
* Use new version of @parity/api stripped of shell_requestNewToken methods that are now unused
* Use synchronous blocking methods in preload.js to maximize chances of web3/parity/ethereum objects being available directly to the dapp, before its own js executes.
  • Loading branch information
amaury1093 committed Aug 2, 2018
1 parent 1b1c17a commit 5e781f7
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 84 deletions.
1 change: 1 addition & 0 deletions .gitlab-ci.yml
Expand Up @@ -103,3 +103,4 @@ publish:snap:
- scripts/publish-snap.sh
tags:
- rust-stable
#gitsync enabled
7 changes: 5 additions & 2 deletions electron/index.js
Expand Up @@ -111,6 +111,7 @@ function createWindow () {

let baseUrl;
let appId;
let token;

// Derive the dapp baseUrl (.../my-dapp/) from the first URL of the webview
// (.../my-dapp/index.html). The baseUrl defines what files the webview is
Expand All @@ -120,7 +121,8 @@ function createWindow () {
webContents.once('did-navigate', (e, initialUrl) => {
const initialURL = new URL(initialUrl);

appId = initialURL.searchParams.get('appId');
appId = initialURL.searchParams.get('shellAppId');
token = initialURL.searchParams.get('shellToken');

initialURL.hash = '';
initialURL.search = '';
Expand All @@ -138,7 +140,8 @@ function createWindow () {

const newURL = new URL(targetUrl);

newURL.searchParams.set('appId', appId);
newURL.searchParams.set('shellAppId', appId);
newURL.searchParams.set('shellToken', token);

webContents.loadURL(newURL.href);
} else {
Expand Down
70 changes: 34 additions & 36 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -158,7 +158,7 @@
"yauzl": "2.9.1"
},
"dependencies": {
"@parity/api": "2.1.20",
"@parity/api": "2.1.24",
"@parity/mobx": "1.1.2",
"@parity/plugin-signer-account": "github:parity-js/plugin-signer-account#05294dce59b7cd7c4f1b26dc604fc6a04dd02bc8",
"@parity/plugin-signer-default": "github:parity-js/plugin-signer-default#dcf8cf23bb050070b6a691413b974b5c2d7d1ce6",
Expand Down
10 changes: 6 additions & 4 deletions src/Dapp/dapp.js
Expand Up @@ -42,7 +42,8 @@ export default class Dapp extends Component {

state = {
app: null,
loading: true
loading: true,
token: null
};

store = DappsStore.get(this.context.api);
Expand Down Expand Up @@ -111,7 +112,7 @@ export default class Dapp extends Component {
this.store
.loadApp(id)
.then((app) => {
this.setState({ loading: false, app });
this.setState({ loading: false, app, token: this.requestsStore.createToken(app.id) });
})
.catch(() => {
this.setState({ loading: false });
Expand Down Expand Up @@ -144,13 +145,14 @@ export default class Dapp extends Component {
preload={ preload }
ref={ this.handleWebview }
src={ `${src}${hash}` }
partition={ `persist:${this.state.app.id}` }
webpreferences='contextIsolation'
/>;
}

render () {
const { params } = this.props;
const { app, loading } = this.state;
const { app, loading, token } = this.state;

if (loading) {
return (
Expand Down Expand Up @@ -178,7 +180,7 @@ export default class Dapp extends Component {
);
}

let src = `${app.localUrl}?appId=${app.id}`;
let src = `${app.localUrl}?shellAppId=${app.id}&shellToken=${token}`;

let hash = '';

Expand Down
6 changes: 1 addition & 5 deletions src/DappRequests/store.js
Expand Up @@ -146,17 +146,13 @@ export default class Store {
}

createToken = appId => {
const token = sha3(`${appId}:${Date.now()}`);
const token = sha3(`${appId}:${Math.random()}:${Date.now()}`);

this.tokens[token] = appId;
return token;
};

hasValidToken = (method, appId, token) => {
if (!token) {
return method === 'shell_requestNewToken';
}

return this.tokens[token] === appId;
};

Expand Down
34 changes: 11 additions & 23 deletions src/inject.js
Expand Up @@ -17,36 +17,24 @@
import Api from '@parity/api';
import qs from 'query-string';

function getAppId () {
// Local dapps: file:///home/username/.config/parity-ui/dapps/mydapp/index.html?appId=LOCAL-dapp-name
// Local dapps served in development mode on a dedicated port: http://localhost:3001/?appId=LOCAL-dapp-name
// Built-in dapps: file://path-to-shell/.build/dapps/0x0587.../index.html?appId=dapp-name
// Built-in dapps when running Electron in dev mode: http://127.0.0.1:3000/dapps/v1/index.html?appId=dapp-name
// Network dapps: file:///home/username/.config/parity-ui/hashfetch/files/0x8075.../index.html?appId=dapp-name
const fromQuery = qs.parse(window.location.search).appId;

if (fromQuery) { return fromQuery; }

console.error('Could not find appId');
}

function initProvider () {
const appId = getAppId();
const queryParams = qs.parse(window.location.search);

// Local dapps: file:///home/username/.config/parity-ui/dapps/mydapp/index.html?appId=LOCAL-dapp-name&token=0x...
// Local dapps served in development mode on a dedicated port: http://localhost:3001/?appId=LOCAL-dapp-name&token=0x...
// Built-in dapps: file://path-to-shell/.build/dapps/0x0587.../index.html?appId=dapp-name&token=0x...
// Built-in dapps when running Electron in dev mode: http://127.0.0.1:3000/dapps/v1/index.html?appId=dapp-name&token=0x...
// Network dapps: file:///home/username/.config/parity-ui/hashfetch/files/0x8075.../index.html?appId=dapp-name&token=0x...
const appId = queryParams.shellAppId;
const token = queryParams.shellToken;

// The dapp will use the PostMessage provider, send postMessages to
// preload.js, and preload.js will relay those messages to the shell.
console.log(`Initializing provider with appId ${appId} and token ${token}`);
const ethereum = new Api.Provider.PostMessage(appId);

console.log(`Requesting API communications token for ${appId}`);

ethereum
.requestNewToken()
.then((tokenId) => {
console.log(`Received API communications token ${tokenId}`);
})
.catch((error) => {
console.error('Unable to retrieve communications token', error);
});
.setToken(token);

window.ethereum = ethereum;
window.isParity = true;
Expand Down

0 comments on commit 5e781f7

Please sign in to comment.