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

Commit

Permalink
Parse and load local dapps directly from filesystem (#141)
Browse files Browse the repository at this point in the history
* Set electron name to 'Parity-UI'

Electron stores the user data by default in `~/.config/<app name>`

The app name is retrieved from the package.json when Electron is
run on a folder (e.g. `electron .`); default app name 'Electron'
is used if Electron is run directly on a script, as is the case.

Electron can be run either on .build/ or on .electron/ (dev),
so it's not practical to use package.json to set the app name
(.electron/ has no package.json); hence it's better in our case
to define it in the code.

* Parse & load local dapps directly from filesystem (userData folder)

* Fix dapp icon URL

* Remove synchronous file operations

* Reorganise util/host.js

* Fix tests

* Use package.json to get Electron app name

* Remove unused arguments
  • Loading branch information
axelchalon authored and amaury1093 committed Jun 14, 2018
1 parent 2a0a396 commit 5ad324f
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 78 deletions.
20 changes: 20 additions & 0 deletions electron/index.js
Expand Up @@ -15,8 +15,10 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

const electron = require('electron');
const fs = require('fs');
const path = require('path');
const url = require('url');
const util = require('util');

const addMenu = require('./menu');
const { cli } = require('./cli');
Expand All @@ -25,8 +27,14 @@ const fetchParity = require('./operations/fetchParity');
const handleError = require('./operations/handleError');
const messages = require('./messages');
const { killParity } = require('./operations/runParity');
const { getLocalDappsPath } = require('./utils/paths');
const { name: appName } = require('../package.json');

const { app, BrowserWindow, ipcMain, session } = electron;

const fsExists = util.promisify(fs.stat); // eslint-disable-line
const fsMkdir = util.promisify(fs.mkdir);

let mainWindow;

function createWindow () {
Expand All @@ -40,6 +48,11 @@ function createWindow () {
width: 1200
});

const localDappsPath = getLocalDappsPath();

fsExists(localDappsPath)
.catch(() => fsMkdir(localDappsPath));

doesParityExist()
.catch(() => fetchParity(mainWindow)) // Install parity if not present
.catch(handleError); // Errors should be handled before, this is really just in case
Expand Down Expand Up @@ -128,3 +141,10 @@ app.on('activate', () => {
createWindow();
}
});

// userData value is derived from the Electron app name by default. However,
// Electron doesn't know the app name defined in package.json because we
// execute Electron directly on a file. Running Electron on a folder (either
// .build/ or electron/) doesn't solve the issue because the package.json
// is located in the parent directory.
app.setPath('userData', path.join(app.getPath('appData'), appName));
7 changes: 4 additions & 3 deletions electron/utils/parityPath.js
Expand Up @@ -16,10 +16,11 @@

const { app } = require('electron');

const parityPath = `${app.getPath('userData')}/parity${process.platform === 'win32' ? '.exe' : ''}`;

// TODO parityPath is now in the Application Data folder by default, it would
// be nice to first look if /usr/bin/parity exists (and return that as
// parityPath). For now we keep Application Data as parityPath.
// See https://github.com/parity-js/shell/issues/66
module.exports = () => parityPath;

// We cannot use app.getPath('userData') outside of the exports because
// it would then be executed before app.setPath('userData') in index.js
module.exports = () => `${app.getPath('userData')}/parity${process.platform === 'win32' ? '.exe' : ''}`;
26 changes: 26 additions & 0 deletions electron/utils/paths.js
@@ -0,0 +1,26 @@
// 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/>.

const path = require('path');
const electron = require('electron');

module.exports = {
getLocalDappsPath: () => {
const userData = electron.app.getPath('userData');

return path.join(userData, 'dapps');
}
};
21 changes: 2 additions & 19 deletions src/Dapp/dapp.js
Expand Up @@ -174,30 +174,13 @@ export default class Dapp extends Component {

switch (app.type) {
case 'local':
src = app.localUrl
? `${app.localUrl}?appId=${app.id}`
: `${dappsUrl}/${app.id}/`;
case 'builtin':
src = `${app.localUrl}?appId=${app.id}`;
break;

case 'network':
src = `${dappsUrl}/${app.contentHash}/`;
break;

default:
let dapphost = process.env.DAPPS_URL || (
process.env.NODE_ENV === 'production'
? `${dappsUrl}/ui`
: ''
);

if (dapphost === '/') {
dapphost = '';
}

src = window.location.protocol === 'file:'
? `dapps/${app.id}/index.html`
: `${dapphost}/dapps/${app.id}/index.html`;
break;
}

let hash = '';
Expand Down
14 changes: 0 additions & 14 deletions src/Dapps/dappsBuiltin.json
@@ -1,7 +1,6 @@
[
{
"id": "v1",
"url": "v1",
"name": "Parity Wallet",
"package": "@parity/dapp-wallet",
"description": "Parity Wallet and Account management tools",
Expand All @@ -11,7 +10,6 @@
},
{
"id": "0x889d3403834b4ef359448575dcd6d77334330edaecc66a77051483f3a498ab6e",
"url": "dappMethods",
"src": "DappMethods",
"name": "Dapp Method Permissions",
"package": "@parity/dapp-dapp-methods",
Expand All @@ -22,7 +20,6 @@
},
{
"id": "0xa48bd8fd56c90c899135281967a6cf90865c221b46f27f9fbe2a236d74a64ea2",
"url": "dappVisible",
"src": "DappVisible",
"name": "Browse Dapps",
"package": "@parity/dapp-dapp-visible",
Expand All @@ -33,7 +30,6 @@
},
{
"id": "0xcd423760c9650eb549b1615f6cf96d420e32aadcea2ff5fe11c26457244adcc1",
"url": "status",
"src": "Status",
"name": "Node Status",
"package": "@parity/dapp-status",
Expand All @@ -44,7 +40,6 @@
},
{
"id": "0x89682fd2c0ffa4ff53a8dc2c5f6a65c6e31de8f659fa2935a07a678e711a58a3",
"url": "develop",
"src": "Develop",
"name": "Develop Contracts",
"package": "@parity/dapp-develop",
Expand All @@ -54,7 +49,6 @@
"visible": true
},
{
"url": "chaindeploy",
"name": "Chain Deployment",
"package": "@parity/dapp-chaindeploy",
"description": "Deploy all basic contracts, names & applications to the network",
Expand All @@ -65,7 +59,6 @@
},
{
"id": "0xa635a9326814bded464190eddf0bdb90ce92d40ea2359cf553ea80e3c5a4076c",
"url": "console",
"name": "Parity/Web3 console",
"package": "@parity/dapp-console",
"description": "A Javascript development console complete with web3 and parity objects",
Expand All @@ -76,7 +69,6 @@
},
{
"id": "0xf9f2d620c2e08f83e45555247146c62185e4ab7cf82a4b9002a265a0d020348f",
"url": "tokendeploy",
"name": "Token Deployment",
"package": "@parity/dapp-tokendeploy",
"description": "Deploy new basic tokens that you are able to send around",
Expand All @@ -86,7 +78,6 @@
},
{
"id": "0xd1adaede68d344519025e2ff574650cd99d3830fe6d274c7a7843cdc00e17938",
"url": "registry",
"name": "Registry",
"package": "@parity/dapp-registry",
"description": "A global registry of addresses on the network",
Expand All @@ -96,7 +87,6 @@
},
{
"id": "0x0a8048117e51e964628d0f2d26342b3cd915248b59bcce2721e1d05f5cfa2208",
"url": "tokenreg",
"name": "Token Registry",
"package": "@parity/dapp-tokenreg",
"description": "A registry of transactable tokens on the network",
Expand All @@ -106,7 +96,6 @@
},
{
"id": "0xf49089046f53f5d2e5f3513c1c32f5ff57d986e46309a42d2b249070e4e72c46",
"url": "signaturereg",
"name": "Method Registry",
"package": "@parity/dapp-signaturereg",
"description": "A registry of method signatures for lookups on transactions",
Expand All @@ -116,7 +105,6 @@
},
{
"id": "0x058740ee9a5a3fb9f1cfa10752baec87e09cc45cd7027fd54708271aca300c75",
"url": "githubhint",
"name": "GitHub Hint",
"package": "@parity/dapp-githubhint",
"description": "A mapping of GitHub URLs to hashes for use in contracts as references",
Expand All @@ -127,7 +115,6 @@
},
{
"id": "0xae74ad174b95cdbd01c88ac5b73a296d33e9088fc2a200e76bcedf3a94a7815d",
"url": "localtx",
"name": "TxQueue Viewer",
"package": "@parity/dapp-localtx",
"description": "Have a peek at the internals of your node's transaction queue",
Expand All @@ -137,7 +124,6 @@
},
{
"id": "0x7bbc4f1a27628781b96213e781a1b8eec6982c1db8fac739af6e4c5a55862c03",
"url": "dappreg",
"name": "Dapp Registration",
"package": "@parity/dapp-dappreg",
"description": "Enables the registration and content management of dapps on the network",
Expand Down
4 changes: 2 additions & 2 deletions src/Dapps/store.js
Expand Up @@ -181,7 +181,7 @@ export default class DappsStore extends EventEmitter {
return Promise.resolve(this._cachedApps[BUILTIN_APPS_KEY]);
}

this._cachedApps[BUILTIN_APPS_KEY] = fetchBuiltinApps(this._api)
this._cachedApps[BUILTIN_APPS_KEY] = fetchBuiltinApps()
.then((apps) => {
this._cachedApps[BUILTIN_APPS_KEY] = apps;
return apps;
Expand All @@ -191,7 +191,7 @@ export default class DappsStore extends EventEmitter {
}

fetchLocalApps () {
return fetchLocalApps(this._api);
return fetchLocalApps();
}

fetchRegistryAppIds (force = false) {
Expand Down
20 changes: 6 additions & 14 deletions src/inject.js
Expand Up @@ -18,27 +18,19 @@ import Api from '@parity/api';
import qs from 'query-string';

function getAppId () {
// Built-in dapps: file://path-to-shell/.build/dapps/0x0587.../index.html
// Built-in dapps when running Electron in dev mode: http://127.0.0.1:3000/dapps/v1/index.html
const [, id] = window.location.pathname.match(/dapps\/([^/]+)\//) || [];
// 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
const fromQuery = qs.parse(window.location.search).appId;

if (id) { return id; }
if (fromQuery) { return fromQuery; }

// Dapps installed from the registry and served by Parity: http://127.0.0.1:8545/ff19...
const [hash] = window.location.pathname.match(/(0x)?[a-f0-9]{64}/i) || [];

if (hash) { return hash; }

// Dapps served in development mode on a dedicated port: http://localhost:3001/?appId=dapp-name
const fromQuery = qs.parse(window.location.search).appId;

if (fromQuery) { return fromQuery; }

// Dapps built locally and served by Parity: http://127.0.0.1:8545/dapp-name
const [, fromParity] = window.location.pathname.match(/^\/?([^/]+)\/?$/) || [];

if (fromParity) { return fromParity; }

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

Expand Down

0 comments on commit 5ad324f

Please sign in to comment.