@@ -25,10 +25,20 @@ const fetchParity = require('./operations/fetchParity');
2525const handleError = require ( './operations/handleError' ) ;
2626const messages = require ( './messages' ) ;
2727const { killParity } = require ( './operations/runParity' ) ;
28+ const { getLocalDappsPath } = require ( './utils/paths' ) ;
29+ const { name : appName } = require ( '../package.json' ) ;
2830
2931const { app, BrowserWindow, ipcMain, session } = electron ;
32+ const { URL } = url ;
33+
3034let mainWindow ;
3135
36+ // Disable gpu acceleration on linux
37+ // https://github.com/parity-js/shell/issues/157
38+ if ( ! [ 'darwin' , 'win32' ] . includes ( process . platform ) ) {
39+ app . disableHardwareAcceleration ( ) ;
40+ }
41+
3242function createWindow ( ) {
3343 // Will send these variables to renderers via IPC
3444 global . dirName = __dirname ;
@@ -37,13 +47,10 @@ function createWindow () {
3747
3848 mainWindow = new BrowserWindow ( {
3949 height : 800 ,
40- width : 1200
50+ width : 1200 ,
51+ webPreferences : { nodeIntegrationInWorker : true }
4152 } ) ;
4253
43- doesParityExist ( )
44- . catch ( ( ) => fetchParity ( mainWindow ) ) // Install parity if not present
45- . catch ( handleError ) ; // Errors should be handled before, this is really just in case
46-
4754 if ( cli . uiDev === true ) {
4855 // Opens http://127.0.0.1:3000 in --ui-dev mode
4956 mainWindow . loadURL ( 'http://127.0.0.1:3000' ) ;
@@ -59,6 +66,10 @@ function createWindow () {
5966 ) ;
6067 }
6168
69+ doesParityExist ( )
70+ . catch ( ( ) => fetchParity ( mainWindow ) ) // Install parity if not present
71+ . catch ( handleError ) ; // Errors should be handled before, this is really just in case
72+
6273 // Listen to messages from renderer process
6374 ipcMain . on ( 'asynchronous-message' , messages ) ;
6475
@@ -74,6 +85,90 @@ function createWindow () {
7485 callback ( { requestHeaders : details . requestHeaders } ) ;
7586 } ) ;
7687
88+ // Verify WebView Options Before Creation
89+ // https://electronjs.org/docs/tutorial/security#12-verify-webview-options-before-creation
90+ mainWindow . webContents . on ( 'will-attach-webview' , ( event , webPreferences , params ) => {
91+ // Strip away inline preload scripts, ours is at preloadURL
92+ delete webPreferences . preload ;
93+
94+ // TODO Verify that the location of webPreferences.preloadURL is:
95+ // `file://path/to/app.asar/.build/preload.js`
96+
97+ // Disable Node.js integration
98+ webPreferences . nodeIntegration = false ;
99+ webPreferences . contextIsolation = true ;
100+ } ) ;
101+
102+ // Listen to the creation of (dapp) webviews to attach event listeners to them
103+ mainWindow . webContents . on ( 'did-attach-webview' , ( event , webContents ) => {
104+ // Do not accept all kinds of web permissions (camera, location...)
105+ // https://electronjs.org/docs/tutorial/security#4-handle-session-permission-requests-from-remote-content
106+ webContents . session
107+ . setPermissionRequestHandler ( ( webContents , permission , callback ) => {
108+ // Deny all permissions for dapps
109+ return callback ( false ) ;
110+ } ) ;
111+
112+ let baseUrl ;
113+ let appId ;
114+
115+ // Derive the dapp baseUrl (.../my-dapp/) from the first URL of the webview
116+ // (.../my-dapp/index.html). The baseUrl defines what files the webview is
117+ // allowed to navigate to within the same frame.
118+ // For example, my-dapp/index.html can navigate to my-dapp/some/dir/hi.html
119+ // and then back to my-dapp/index.html
120+ webContents . once ( 'did-navigate' , ( e , initialUrl ) => {
121+ const initialURL = new URL ( initialUrl ) ;
122+
123+ appId = initialURL . searchParams . get ( 'appId' ) ;
124+
125+ initialURL . hash = '' ;
126+ initialURL . search = '' ;
127+ baseUrl = initialURL . href . substr ( 0 , initialURL . href . lastIndexOf ( '/' ) + 1 ) ;
128+ } ) ;
129+
130+ // The event handler for will-navigate needs to be set in the main process
131+ // in order to be able to prevent the navigation: https://git.io/f4SNW
132+ webContents . on ( 'will-navigate' , ( e , targetUrl ) => {
133+ e . preventDefault ( ) ;
134+
135+ if ( targetUrl . startsWith ( baseUrl ) ) {
136+ // The target resource is located inside the dapp folder: allow in-frame
137+ // navigation but enforce appId query parameter for inject.js
138+
139+ const newURL = new URL ( targetUrl ) ;
140+
141+ newURL . searchParams . set ( 'appId' , appId ) ;
142+
143+ webContents . loadURL ( newURL . href ) ;
144+ } else {
145+ // Open all links to resources outside the dapp root in the browser
146+ // (or with the default desktop app for protocols other than http)
147+
148+ electron . shell . openExternal ( targetUrl ) ;
149+ }
150+ } ) ;
151+
152+ // Block in-page requests to resources outside the dapp folder
153+ webContents . session . webRequest . onBeforeRequest ( { urls : [ 'file://*' ] } , ( details , callback ) => {
154+ if ( baseUrl &&
155+ ! details . url . startsWith ( baseUrl ) &&
156+ // dapp-dapp-visible needs to be able to display the icons of other
157+ // dapps, so as a temporary fix we allow access to all images requests
158+ details . resourceType !== 'image' ) {
159+ const sanitizedUrl = details . url . replace ( / ' / , '' ) ;
160+
161+ if ( ! webContents . isDestroyed ( ) ) {
162+ webContents . executeJavaScript ( `console.warn('Parity UI blocked a request to access ${ sanitizedUrl } ')` ) ;
163+ }
164+
165+ callback ( { cancel : true } ) ;
166+ } else {
167+ callback ( { cancel : false } ) ;
168+ }
169+ } ) ;
170+ } ) ;
171+
77172 mainWindow . on ( 'closed' , ( ) => {
78173 mainWindow = null ;
79174 } ) ;
@@ -98,3 +193,10 @@ app.on('activate', () => {
98193 createWindow ( ) ;
99194 }
100195} ) ;
196+
197+ // userData value is derived from the Electron app name by default. However,
198+ // Electron doesn't know the app name defined in package.json because we
199+ // execute Electron directly on a file. Running Electron on a folder (either
200+ // .build/ or electron/) doesn't solve the issue because the package.json
201+ // is located in the parent directory.
202+ app . setPath ( 'userData' , path . join ( app . getPath ( 'appData' ) , appName ) ) ;
0 commit comments