1
- import { join , dirname , extname , isAbsolute } from 'path' ;
2
-
3
- import { fileURLToPath } from 'url' ;
4
- import { log , dangerousAPI } from './lib/logger.js' ;
5
-
6
- import Chromium from './browser/chromium.js' ;
7
- import Firefox from './browser/firefox.js' ;
8
-
9
- import * as ExtensionsAPI from './extensions.js' ;
10
- import LocalHTTP from './lib/local/http.js' ;
11
- import { findBrowserPath , getBrowserType } from './lib/browserPaths.js' ;
12
-
13
- process . versions . gluon = '0.14.0-alpha.0 ' ;
14
-
15
- const __filename = fileURLToPath ( import . meta. url ) ;
16
- const __dirname = dirname ( __filename ) ;
17
-
18
- const getFriendlyName = whichBrowser => whichBrowser [ 0 ] . toUpperCase ( ) + whichBrowser . slice ( 1 ) . replace ( / [ a - z ] _ [ a - z ] / g, _ => _ [ 0 ] + ' ' + _ [ 2 ] . toUpperCase ( ) ) ;
19
-
20
- const ranJsDir = ! process . argv [ 1 ] ? __dirname : ( extname ( process . argv [ 1 ] ) ? dirname ( process . argv [ 1 ] ) : process . argv [ 1 ] ) ;
21
- const getDataPath = browser => join ( ranJsDir , 'gluon_data' , browser ) ;
22
-
23
- const portRange = [ 10000 , 60000 ] ;
24
- const generatePort = ( ) => ( Math . floor ( Math . random ( ) * ( portRange [ 1 ] - portRange [ 0 ] + 1 ) ) + portRange [ 0 ] ) ;
25
-
26
- // default CSP policy. tl;dr: allow everything if same-origin, and allow all mostly non-dangerous things for all domains (images, css, requests)
27
- const defaultCSP = [ 'upgrade-insecure-requests' ] . concat (
28
- [ 'default-src' ] . map ( x => `${ x } 'self' 'unsafe-inline'` )
29
- ) . concat (
30
- [ 'connect-src' , 'font-src' , 'img-src' , 'media-src' , 'style-src' , 'form-action' ] . map ( x => `${ x } https: data: blob: 'unsafe-inline'` )
31
- ) . join ( '; ' ) ;
32
-
33
- const startBrowser = async ( url , parentDir , { allowHTTP = false , allowNavigation = 'same-origin' , windowSize, forceBrowser, forceEngine, localCSP = defaultCSP , devtools, userAgent, incognito } ) => {
34
- const [ browserPath , browserName ] = await findBrowserPath ( forceBrowser , forceEngine ) ;
35
- if ( ! browserPath ) {
36
- throw new Error ( 'Failed to find a usable browser installed' ) ;
37
- }
38
-
39
- const browserFriendlyName = getFriendlyName ( browserName ) ;
40
- const browserType = getBrowserType ( browserName ) ;
41
-
42
- let dataPath = getDataPath ( browserName ) ;
43
- if ( incognito ) dataPath = join ( dataPath , 'incognito-' + Math . random ( ) . toString ( ) . slice ( 2 ) ) ;
44
-
45
- log ( 'found browser' , browserName , `(${ browserType } based)` , 'at path:' , browserPath ) ;
46
- log ( 'data path:' , dataPath ) ;
47
-
48
- const openingLocal = ! url . includes ( '://' ) && ! url . includes ( 'data:' ) ;
49
- const localUrl = browserType === 'firefox' ? `http://localhost:${ generatePort ( ) } ` : 'https://app.gluon' ;
50
- const basePath = isAbsolute ( url ) ? url : join ( parentDir , url ) ;
51
-
52
- const closeHandlers = [ ] ;
53
- if ( openingLocal && browserType === 'firefox' ) closeHandlers . push ( await LocalHTTP ( { url : localUrl , basePath, csp : localCSP } ) ) ;
54
-
55
- const Window = await ( browserType === 'firefox' ? Firefox : Chromium ) ( {
56
- dataPath,
57
- browserPath
58
- } , {
59
- url : openingLocal ? localUrl : url ,
60
- windowSize,
61
- allowHTTP,
62
- extensions : ExtensionsAPI . _extensions [ browserType ] ,
63
- devtools : devtools === false ? process . argv . includes ( '--enable-devtools' ) : true ,
64
- userAgent
65
- } , {
66
- browserName : browserFriendlyName ,
67
- url : openingLocal ? localUrl : url ,
68
- basePath,
69
- openingLocal,
70
- closeHandlers,
71
- browserType,
72
- dataPath,
73
- allowNavigation,
74
- localCSP
75
- } ) ;
76
-
77
- return Window ;
78
- } ;
79
-
80
- // get parent directory of where function was called from
81
- const getParentDir = ( ) => {
82
- let place = ( new Error ( ) ) . stack . split ( '\n' ) [ 3 ] . slice ( 7 ) . trim ( ) . split ( ':' ) . slice ( 0 , - 2 ) . join ( ':' ) ;
83
- if ( place . includes ( '(' ) && place . includes ( ')' ) ) {
84
- place = place . split ( '(' ) . slice ( 1 ) . join ( '(' )
85
- }
86
-
87
- if ( place . startsWith ( 'file://' ) ) place = fileURLToPath ( place ) ;
88
- return dirname ( place ) ;
89
- } ;
90
-
91
- const checkForDangerousOptions = ( { allowHTTP, allowNavigation, localCSP } ) => {
92
- if ( allowHTTP === true ) dangerousAPI ( 'Gluon.open' , 'allowHTTP' , 'true' ) ;
93
- if ( allowNavigation === true ) dangerousAPI ( 'Gluon.open' , 'allowNavigation' , 'true' ) ;
94
- if ( localCSP === '' ) dangerousAPI ( 'Gluon.open' , 'localCSP' , '\'\'' ) ;
95
- } ;
96
-
97
- export const open = async ( url , opts = { } ) => {
98
- const { allowHTTP = false } = opts ;
99
-
100
- if ( allowHTTP !== true && url . startsWith ( 'http://' ) ) throw new Error ( `HTTP URLs are blocked by default. Please use HTTPS, or if not possible, enable the 'allowHTTP' option.` ) ;
101
-
102
- checkForDangerousOptions ( opts ) ;
103
- log ( 'starting browser...' ) ;
104
-
105
- const Browser = await startBrowser ( url , getParentDir ( ) , opts ) ;
106
-
107
- return Browser ;
108
- } ;
109
-
110
- export const extensions = {
111
- add : ExtensionsAPI . add ,
112
- remove : ExtensionsAPI . remove
113
- } ;
114
-
1
+ import { join , dirname , extname , isAbsolute } from 'path' ;
2
+
3
+ import { fileURLToPath } from 'url' ;
4
+ import { log , dangerousAPI } from './lib/logger.js' ;
5
+
6
+ import Chromium from './browser/chromium.js' ;
7
+ import Firefox from './browser/firefox.js' ;
8
+
9
+ import * as ExtensionsAPI from './extensions.js' ;
10
+ import LocalHTTP from './lib/local/http.js' ;
11
+ import { findBrowserPath , getBrowserType } from './lib/browserPaths.js' ;
12
+
13
+ process . versions . gluon = '0.14.0' ;
14
+
15
+ const __filename = fileURLToPath ( import . meta. url ) ;
16
+ const __dirname = dirname ( __filename ) ;
17
+
18
+ const getFriendlyName = whichBrowser => whichBrowser [ 0 ] . toUpperCase ( ) + whichBrowser . slice ( 1 ) . replace ( / [ a - z ] _ [ a - z ] / g, _ => _ [ 0 ] + ' ' + _ [ 2 ] . toUpperCase ( ) ) ;
19
+
20
+ const ranJsDir = ! process . argv [ 1 ] ? __dirname : ( extname ( process . argv [ 1 ] ) ? dirname ( process . argv [ 1 ] ) : process . argv [ 1 ] ) ;
21
+ const getDataPath = browser => join ( ranJsDir , 'gluon_data' , browser ) ;
22
+
23
+ const portRange = [ 10000 , 60000 ] ;
24
+ const generatePort = ( ) => ( Math . floor ( Math . random ( ) * ( portRange [ 1 ] - portRange [ 0 ] + 1 ) ) + portRange [ 0 ] ) ;
25
+
26
+ // default CSP policy. tl;dr: allow everything if same-origin, and allow all mostly non-dangerous things for all domains (images, css, requests)
27
+ const defaultCSP = [ 'upgrade-insecure-requests' ] . concat (
28
+ [ 'default-src' ] . map ( x => `${ x } 'self' 'unsafe-inline'` )
29
+ ) . concat (
30
+ [ 'connect-src' , 'font-src' , 'img-src' , 'media-src' , 'style-src' , 'form-action' ] . map ( x => `${ x } https: data: blob: 'unsafe-inline'` )
31
+ ) . join ( '; ' ) ;
32
+
33
+ const startBrowser = async ( url , parentDir , { allowHTTP = false , allowNavigation = 'same-origin' , windowSize, forceBrowser, forceEngine, localCSP = defaultCSP , devtools, userAgent, incognito } ) => {
34
+ const [ browserPath , browserName ] = await findBrowserPath ( forceBrowser , forceEngine ) ;
35
+ if ( ! browserPath ) {
36
+ throw new Error ( 'Failed to find a usable browser installed' ) ;
37
+ }
38
+
39
+ const browserFriendlyName = getFriendlyName ( browserName ) ;
40
+ const browserType = getBrowserType ( browserName ) ;
41
+
42
+ let dataPath = getDataPath ( browserName ) ;
43
+ if ( incognito ) dataPath = join ( dataPath , 'incognito-' + Math . random ( ) . toString ( ) . slice ( 2 ) ) ;
44
+
45
+ log ( 'found browser' , browserName , `(${ browserType } based)` , 'at path:' , browserPath ) ;
46
+ log ( 'data path:' , dataPath ) ;
47
+
48
+ const openingLocal = ! url . includes ( '://' ) && ! url . includes ( 'data:' ) ;
49
+ const localUrl = browserType === 'firefox' ? `http://localhost:${ generatePort ( ) } ` : 'https://app.gluon' ;
50
+ const basePath = isAbsolute ( url ) ? url : join ( parentDir , url ) ;
51
+
52
+ const closeHandlers = [ ] ;
53
+ if ( openingLocal && browserType === 'firefox' ) closeHandlers . push ( await LocalHTTP ( { url : localUrl , basePath, csp : localCSP } ) ) ;
54
+
55
+ const Window = await ( browserType === 'firefox' ? Firefox : Chromium ) ( {
56
+ dataPath,
57
+ browserPath
58
+ } , {
59
+ url : openingLocal ? localUrl : url ,
60
+ windowSize,
61
+ allowHTTP,
62
+ extensions : ExtensionsAPI . _extensions [ browserType ] ,
63
+ devtools : devtools === false ? process . argv . includes ( '--enable-devtools' ) : true ,
64
+ userAgent
65
+ } , {
66
+ browserName : browserFriendlyName ,
67
+ url : openingLocal ? localUrl : url ,
68
+ basePath,
69
+ openingLocal,
70
+ closeHandlers,
71
+ browserType,
72
+ dataPath,
73
+ allowNavigation,
74
+ localCSP
75
+ } ) ;
76
+
77
+ return Window ;
78
+ } ;
79
+
80
+ // get parent directory of where function was called from
81
+ const getParentDir = ( ) => {
82
+ let place = ( new Error ( ) ) . stack . split ( '\n' ) [ 3 ] . slice ( 7 ) . trim ( ) . split ( ':' ) . slice ( 0 , - 2 ) . join ( ':' ) ;
83
+ if ( place . includes ( '(' ) && place . includes ( ')' ) ) {
84
+ place = place . split ( '(' ) . slice ( 1 ) . join ( '(' )
85
+ }
86
+
87
+ if ( place . startsWith ( 'file://' ) ) place = fileURLToPath ( place ) ;
88
+ return dirname ( place ) ;
89
+ } ;
90
+
91
+ const checkForDangerousOptions = ( { allowHTTP, allowNavigation, localCSP } ) => {
92
+ if ( allowHTTP === true ) dangerousAPI ( 'Gluon.open' , 'allowHTTP' , 'true' ) ;
93
+ if ( allowNavigation === true ) dangerousAPI ( 'Gluon.open' , 'allowNavigation' , 'true' ) ;
94
+ if ( localCSP === '' ) dangerousAPI ( 'Gluon.open' , 'localCSP' , '\'\'' ) ;
95
+ } ;
96
+
97
+ export const open = async ( url , opts = { } ) => {
98
+ const { allowHTTP = false } = opts ;
99
+
100
+ if ( allowHTTP !== true && url . startsWith ( 'http://' ) ) throw new Error ( `HTTP URLs are blocked by default. Please use HTTPS, or if not possible, enable the 'allowHTTP' option.` ) ;
101
+
102
+ checkForDangerousOptions ( opts ) ;
103
+ log ( 'starting browser...' ) ;
104
+
105
+ const Browser = await startBrowser ( url , getParentDir ( ) , opts ) ;
106
+
107
+ return Browser ;
108
+ } ;
109
+
110
+ export const extensions = {
111
+ add : ExtensionsAPI . add ,
112
+ remove : ExtensionsAPI . remove
113
+ } ;
114
+
115
115
export { default as openAbout } from "./menus/about.js" ;
0 commit comments