diff --git a/package-lock.json b/package-lock.json index 005b4291..0d634d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12440,8 +12440,9 @@ }, "node_modules/scratch-gui": { "version": "3.2.37", - "resolved": "git+ssh://git@github.com/TurboWarp/scratch-gui.git#9a589c06cdc99841e0f98b1d629d292aa0016ab0", + "resolved": "git+ssh://git@github.com/TurboWarp/scratch-gui.git#457b36f20b30744656a8956f3eb0b0dc7c30365e", "dev": true, + "license": "GPL-3.0", "dependencies": { "@microbit/microbit-universal-hex": "0.2.2", "@turbowarp/nanolog": "^0.2.0", diff --git a/src-renderer-webpack/editor/gui/desktop-hoc.jsx b/src-renderer-webpack/editor/gui/desktop-hoc.jsx index 12fa869..4b33f2d 100644 --- a/src-renderer-webpack/editor/gui/desktop-hoc.jsx +++ b/src-renderer-webpack/editor/gui/desktop-hoc.jsx @@ -11,7 +11,7 @@ import { requestNewProject } from 'scratch-gui/src/reducers/project-state'; import {setFileHandle, setUsername} from 'scratch-gui/src/reducers/tw'; -import {WrappedFileHandle} from './filesystem-api-impl'; +import {WrappedFileHandle} from './filesystem-api.js'; import {setStrings} from '../prompt/prompt.js'; let mountedOnce = false; diff --git a/src-renderer-webpack/editor/gui/filesystem-api-impl.js b/src-renderer-webpack/editor/gui/filesystem-api.js similarity index 83% rename from src-renderer-webpack/editor/gui/filesystem-api-impl.js rename to src-renderer-webpack/editor/gui/filesystem-api.js index 48a809d..a5ea229 100644 --- a/src-renderer-webpack/editor/gui/filesystem-api-impl.js +++ b/src-renderer-webpack/editor/gui/filesystem-api.js @@ -1,6 +1,10 @@ /** - * Partial reimplementation of the FileSystem API - * https://web.dev/file-system-access/ + * Partial reimplementation of the FileSystem API (https://web.dev/file-system-access/) + * + * Unlike the default FileSystem API, we can construct a file handle from an ID from + * the main process without showing the file picker. The IDs are managed by the main + * process, so malicious extensions can't abuse this to get arbitrary read/write, + * and it lets us not share full file paths which could contain eg. the user's name. */ /** @@ -100,7 +104,7 @@ class WrappedFileWritable { } } -export class WrappedFileHandle { +class WrappedFileHandle { /** * @param {number} id File ID from main. * @param {string} name Name including file extension. @@ -127,7 +131,15 @@ class AbortError extends Error { } } -window.showSaveFilePicker = async (options) => { +const showOpenFilePicker = async () => { + const result = await EditorPreload.showOpenFilePicker(); + if (result === null) { + throw new AbortError('No file selected'); + } + return [new WrappedFileHandle(result.id, result.name)]; +}; + +const showSaveFilePicker = async (options) => { const result = await EditorPreload.showSaveFilePicker(options.suggestedName); if (result === null) { throw new AbortError('No file selected'); @@ -135,10 +147,8 @@ window.showSaveFilePicker = async (options) => { return new WrappedFileHandle(result.id, result.name); }; -window.showOpenFilePicker = async () => { - const result = await EditorPreload.showOpenFilePicker(); - if (result === null) { - throw new AbortError('No file selected'); - } - return [new WrappedFileHandle(result.id, result.name)]; +export { + WrappedFileHandle, + showOpenFilePicker, + showSaveFilePicker }; diff --git a/src-renderer-webpack/editor/gui/gui.jsx b/src-renderer-webpack/editor/gui/gui.jsx index ff5ae7f..eac6f8d 100644 --- a/src-renderer-webpack/editor/gui/gui.jsx +++ b/src-renderer-webpack/editor/gui/gui.jsx @@ -5,6 +5,7 @@ import GUI, {AppStateHOC} from 'scratch-gui'; import ErrorContainerHOC from '../error/error-container-hoc.jsx'; import DesktopHOC from './desktop-hoc.jsx'; import CloudProviderHOC from './cloud-provider-hoc.jsx'; +import {showOpenFilePicker, showSaveFilePicker} from './filesystem-api.js'; import './normalize.css'; import './gui.css'; @@ -28,6 +29,9 @@ const GUIWithProps = () => ( backpackVisible backpackHost="_local_" + + showOpenFilePicker={showOpenFilePicker} + showSaveFilePicker={showSaveFilePicker} /> ); diff --git a/src-renderer-webpack/editor/gui/index.jsx b/src-renderer-webpack/editor/gui/index.jsx index 8ef7f30..fc214f9 100644 --- a/src-renderer-webpack/editor/gui/index.jsx +++ b/src-renderer-webpack/editor/gui/index.jsx @@ -2,7 +2,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; import GUI from './gui.jsx'; -import './filesystem-api-impl.js'; import './media-device-chooser-impl.js'; import '../prompt/prompt.js';