@stlite/desktop 0.21.2 → 0.21.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/build/electron/main.js +60 -10
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -25,8 +25,8 @@ Convert your [Streamlit](https://streamlit.io/) application into a desktop app w
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@stlite/desktop": "^0.21.0",
|
|
28
|
-
"electron": "
|
|
29
|
-
"electron-builder": "^23.
|
|
28
|
+
"electron": "^22.0.0",
|
|
29
|
+
"electron-builder": "^23.6.0"
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
```
|
|
@@ -49,3 +49,12 @@ Convert your [Streamlit](https://streamlit.io/) application into a desktop app w
|
|
|
49
49
|
- This command is just a wrapper of `electron` command as you can see at the `"scripts"` field in the `package.json`. It launches Electron and starts the app with `./build/electron/main.js`, which is specified at the `"main"` field in the `package.json`.
|
|
50
50
|
9. Run `npm run dist` or `yarn dist` for packaging.
|
|
51
51
|
- This command bundles the `./build` directory created in the step above into application files (`.app`, `.exe`, `.dmg` etc.) in the `./dist` directory. To customize the built app, e.g. setting the icon, follow the [`electron-builder`](https://www.electron.build/) instructions.
|
|
52
|
+
|
|
53
|
+
## Use the latest version of Electron
|
|
54
|
+
|
|
55
|
+
To make your app secure, be sure to use the latest version of Electron.
|
|
56
|
+
This is [announced](https://www.electronjs.org/docs/latest/tutorial/security#16-use-a-current-version-of-electron) as one of the security best practices in the Electron document too.
|
|
57
|
+
|
|
58
|
+
## Limitations
|
|
59
|
+
|
|
60
|
+
- Navigation to external resources like `st.markdown("[link](https://streamlit.io/)")` does not work for security. See https://github.com/whitphx/stlite/pull/445 and let us know if you have use cases where you have to use such external links.
|
package/build/electron/main.js
CHANGED
|
@@ -18,31 +18,48 @@ const createWindow = () => {
|
|
|
18
18
|
height: 720,
|
|
19
19
|
webPreferences: {
|
|
20
20
|
preload: path.join(__dirname, "preload.js"),
|
|
21
|
+
sandbox: true, // https://www.electronjs.org/docs/latest/tutorial/security#4-enable-process-sandboxing
|
|
21
22
|
},
|
|
22
23
|
});
|
|
24
|
+
const indexUrl = electron_1.app.isPackaged || process.env.NODE_ENV === "production"
|
|
25
|
+
? "file:///index.html"
|
|
26
|
+
: "http://localhost:3000/";
|
|
27
|
+
// Check the IPC sender in every callback below,
|
|
28
|
+
// following the security best practice, "17. Validate the sender of all IPC messages."
|
|
29
|
+
// https://www.electronjs.org/docs/latest/tutorial/security#17-validate-the-sender-of-all-ipc-messages
|
|
30
|
+
const isValidIpcSender = (frame) => {
|
|
31
|
+
return frame.url === indexUrl;
|
|
32
|
+
};
|
|
23
33
|
electron_1.ipcMain.handle("readSitePackagesSnapshot", (ev) => {
|
|
34
|
+
if (!isValidIpcSender(ev.senderFrame)) {
|
|
35
|
+
throw new Error("Invalid IPC sender");
|
|
36
|
+
}
|
|
24
37
|
// This archive file has to be created by ./bin/dump_snapshot.ts
|
|
25
38
|
const archiveFilePath = path.resolve(__dirname, "../site-packages-snapshot.tar.gz");
|
|
26
39
|
return fsPromises.readFile(archiveFilePath);
|
|
27
40
|
});
|
|
28
41
|
electron_1.ipcMain.handle("readStreamlitAppDirectory", async (ev) => {
|
|
42
|
+
if (!isValidIpcSender(ev.senderFrame)) {
|
|
43
|
+
throw new Error("Invalid IPC sender");
|
|
44
|
+
}
|
|
29
45
|
const streamlitAppDir = path.resolve(__dirname, "../streamlit_app");
|
|
30
46
|
return (0, file_1.walkRead)(streamlitAppDir);
|
|
31
47
|
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
else {
|
|
40
|
-
mainWindow.loadURL("http://localhost:3000");
|
|
41
|
-
}
|
|
48
|
+
// Even when the entrypoint is a local file like the production build,
|
|
49
|
+
// we use .loadURL() with an absolute URL with the `file://` schema
|
|
50
|
+
// instead of passing a file path to .loadFile()
|
|
51
|
+
// because absolute URLs with the file:// scheme will be resolved
|
|
52
|
+
// to absolute file paths based on the special handler
|
|
53
|
+
// registered through `interceptFileProtocol` below.
|
|
54
|
+
mainWindow.loadURL(indexUrl);
|
|
42
55
|
if (!electron_1.app.isPackaged) {
|
|
43
56
|
mainWindow.webContents.openDevTools();
|
|
44
57
|
}
|
|
45
58
|
};
|
|
59
|
+
// Enable process sandboxing globally (https://www.electronjs.org/docs/latest/tutorial/sandbox#enabling-the-sandbox-globally),
|
|
60
|
+
// following the security best practice, "4. Enable process sandboxing."
|
|
61
|
+
// https://www.electronjs.org/docs/latest/tutorial/security#4-enable-process-sandboxing
|
|
62
|
+
electron_1.app.enableSandbox();
|
|
46
63
|
// This method will be called when Electron has finished
|
|
47
64
|
// initialization and is ready to create browser windows.
|
|
48
65
|
// Some APIs can only be used after this event occurs.
|
|
@@ -77,3 +94,36 @@ electron_1.app.on("window-all-closed", () => {
|
|
|
77
94
|
if (process.platform !== "darwin")
|
|
78
95
|
electron_1.app.quit();
|
|
79
96
|
});
|
|
97
|
+
electron_1.app.on("web-contents-created", (event, contents) => {
|
|
98
|
+
// Intercepts webView creation events and forbid all,
|
|
99
|
+
// following the security best practice, "12. Verify WebView options before creation."
|
|
100
|
+
// https://www.electronjs.org/docs/latest/tutorial/security#12-verify-webview-options-before-creation
|
|
101
|
+
contents.on("will-attach-webview", (event, webPreferences, params) => {
|
|
102
|
+
// Cancels all webView creation request
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
});
|
|
105
|
+
// Intercepts navigation and forbid all,
|
|
106
|
+
// following the security best practice, "13. Disable or limit navigation."
|
|
107
|
+
// https://www.electronjs.org/docs/latest/tutorial/security#13-disable-or-limit-navigation
|
|
108
|
+
contents.on("will-navigate", (event, navigationUrl) => {
|
|
109
|
+
console.debug("will-navigate", navigationUrl);
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
});
|
|
112
|
+
// Limit new windows creation,
|
|
113
|
+
// following the security best practice, "14. Disable or limit creation of new windows."
|
|
114
|
+
// https://www.electronjs.org/docs/latest/tutorial/security#14-disable-or-limit-creation-of-new-windows
|
|
115
|
+
contents.setWindowOpenHandler(({ url }) => {
|
|
116
|
+
console.error("Opening a new window is not allowed.");
|
|
117
|
+
// TODO: Implement `isSafeForExternalOpen()` below with a configurable allowed list.
|
|
118
|
+
// We'll ask the operating system
|
|
119
|
+
// to open this event's url in the default browser.
|
|
120
|
+
// DON'T pass an arbitrary URL to `shell.openExternal()` here
|
|
121
|
+
// as advised at "15. Do not use shell.openExternal with untrusted content."
|
|
122
|
+
// if (isSafeForExternalOpen(url)) {
|
|
123
|
+
// setImmediate(() => {
|
|
124
|
+
// shell.openExternal(url)
|
|
125
|
+
// })
|
|
126
|
+
// }
|
|
127
|
+
return { action: "deny" };
|
|
128
|
+
});
|
|
129
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stlite/desktop",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.3",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "/",
|
|
6
6
|
"main": "./build/electron/main.js",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@craco/craco": "^6.1.2",
|
|
60
|
-
"@stlite/common": "^0.21.
|
|
61
|
-
"@stlite/kernel": "^0.21.
|
|
60
|
+
"@stlite/common": "^0.21.3",
|
|
61
|
+
"@stlite/kernel": "^0.21.3",
|
|
62
62
|
"@testing-library/react": "^11.2.7",
|
|
63
63
|
"@testing-library/user-event": "^13.1.9",
|
|
64
64
|
"@types/jest": "^26.0.19",
|
|
@@ -66,8 +66,8 @@
|
|
|
66
66
|
"@types/react": "^17.0.7",
|
|
67
67
|
"@types/react-dom": "^17.0.5",
|
|
68
68
|
"@types/yargs": "^17.0.13",
|
|
69
|
-
"electron": "
|
|
70
|
-
"electron-builder": "^23.
|
|
69
|
+
"electron": "^22.0.0",
|
|
70
|
+
"electron-builder": "^23.6.0",
|
|
71
71
|
"electron-reload": "^2.0.0-alpha.1",
|
|
72
72
|
"esbuild": "^0.16.6",
|
|
73
73
|
"raw-loader": "^4.0.2",
|