-
Notifications
You must be signed in to change notification settings - Fork 65
Propose FileSystemSubscriptionManager #457
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| # Proposal: FileSystemSubscriptionManager | ||
|
|
||
| ## Authors | ||
|
|
||
| * Ming-Ying Chung (<[email protected]>) | ||
| * Austin Sullivan (<[email protected]>) | ||
|
|
||
| ## Background | ||
|
|
||
| The [FileSystemObserver API][fso-api] allows browsing context to receive records of changes for the observed files or directories. However, changes which occur while the website has no open tabs are not visible to the website. | ||
|
|
||
| This document proposes integrating file system change observing with service worker registration, such that a service worker may be woken up on a change to the local file system. | ||
|
|
||
| [fso-api]: https://chromestatus.com/feature/4622243656630272 | ||
|
|
||
| ## Goal | ||
|
|
||
| Allow web applications that do not have an open tab to quickly respond to changes to registered files and directories on the local file system. | ||
|
|
||
| ## Discussion | ||
|
|
||
| ### Option 1. Enabling FileSystemObserver in Service Worker | ||
|
|
||
| By [current design][fso], an instance of FileSystemObserver should only report changes which occur while the observer is connected and the website has an open & active tab. | ||
|
|
||
| Enabling creations of FileSystemObserver in ServiceWorker will tie its lifetime with ServiceWorkerGlobalScope. Users might expect such observers to continue to watch files in the background. However, in browser implementation, service workers that haven’t received new events in a certain period of time, e.g. [30s in Chrome][chrome-sw], will likely be terminated. | ||
|
|
||
| Hence, this approach might only work for websites that either can ensure a long-running service worker or are not really interested in using service worker registration for observing the file change events after the websites are closed. | ||
|
|
||
| [fso]: https://docs.google.com/document/d/11o4HaslFwQxKIjJw0M9LAkkZp2ikCNwA9vvYsjA657w/edit?tab=t.0#heading=h.kktfoyrlhtnv | ||
mingyc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| [chrome-sw]: https://developer.chrome.com/blog/longer-esw-lifetimes#background | ||
|
|
||
| ### Option 2. Updating FileSystemObserver API to outlive Service Worker | ||
|
|
||
| Another approach is to ask what if updating FileSystemObserver to allow it to outlive without the limit of running in ServiceWorkerGlobalScope? | ||
|
|
||
| If such an option is implemented, there needs to be mechanisms to | ||
| Tell when the browser should stop watching file changes. | ||
mingyc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Handle file changes happen after the service worker is already terminated but the website is still open. Possibly needs a way to wake up a new service worker. | ||
|
|
||
| There are existing mechanisms to auto wake up new service workers. Hence the next option. | ||
|
|
||
| ### Option 3. Utilizing Service Worker Registration | ||
|
|
||
| The ServiceWorkerRegistration interface represents registration of a service worker for a specific origin and scope. The browser maintains a persistent list of active ServiceWorkerRegistration even when the associated service worker is not actively running, and will wake up new service workers if a registered event happens. | ||
|
|
||
| ## Proposed API | ||
|
|
||
| ### Web IDL | ||
|
|
||
| First, define a new interface FileSystemSubscriptionManager that will be held under every ServiceWorkerRegistration, which manages subscriptions to changes to file systems: | ||
|
|
||
| ```idl | ||
mingyc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| partial interface ServiceWorkerRegistration { | ||
| // Returns a reference to FileSystemSubscriptionManager interface, which allows | ||
| // for subscribing to specific file changes. | ||
| [SameObject] readonly attribute FileSystemSubscriptionManager fileSystem; | ||
| }; | ||
| ``` | ||
|
|
||
| ```idl | ||
| // Provides methods for managing file system subscriptions. | ||
| interface FileSystemSubscriptionManager { | ||
| // Subscribes to changes to a FileSystemHandle with the browser with specific | ||
| // options. Returns a Promise that resolves when the subscription completes. | ||
| Promise<void> subscribe(FileSystemHandle handle, | ||
mingyc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| FileSystemObserverObserverOptions options = {}); | ||
mingyc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // Unsubscribes to changes to a FileSystemHandle. Returns a Promise that | ||
| // resolves when the unsubscription completes. | ||
| Promise<void> unsubscribe(FileSystemHandle handle); | ||
|
||
| // Returns a Promise that resolves with a list of FileSystemSubscription | ||
| // representing all the current file system subscriptions with the browser. | ||
| Promise<sequence<FileSystemSubscription>> getSubscriptions(); | ||
| }; | ||
| ``` | ||
|
|
||
| ```idl | ||
| // Represents a subscription to changes to a FileSystemHandle. | ||
| interface FileSystemSubscription { | ||
mingyc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| required FileSystemHandle handle; | ||
mingyc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| FileSystemObserverObserverOptions? options = null; | ||
| }; | ||
| ``` | ||
|
|
||
| Second, allow service workers to fire a new type of event FileSystemChangeEvent, which includes a list of FileSystemChangeRecord. | ||
|
|
||
| ```idl | ||
| partial interface ServiceWorkerGlobalScope { | ||
| // Fired when FileSystemSubscriptionManager observes changes. | ||
| attribute EventHandler attribute onfilesystemchange; | ||
| }; | ||
| ``` | ||
|
|
||
| ```idl | ||
| // Represents a file system change event. | ||
| interface FileSystemChangeEvent : ExtendableEvent { | ||
| constructor(DOMString type, FileSystemChangeEventInit init); | ||
| readonly attribute sequence<FileSystemChangeRecord> records; | ||
mingyc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
mingyc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }; | ||
|
|
||
| interface FileSystemChangeEventInit : ExtendableEvent { | ||
| required sequence<FileSystemChangeRecord> records; | ||
| } | ||
| ``` | ||
|
|
||
| ### Example: Observing Changes to a Directory | ||
|
|
||
| ```javascript | ||
mingyc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // main.js | ||
| const directoryHandle = await window.showDirectoryPicker(); | ||
| async function observeDirectoryChanges(directoryHandle) { | ||
| const registration = await navigator.ServiceWorker.register("/service-worker.js"); | ||
| registration.fileSystem.subscribe(directoryHandle, {recursive: true}); | ||
| } | ||
|
|
||
| // service-worker.js | ||
| self.addEventListener('onfilesystemchange', event => { | ||
| for (const record of event.records) { | ||
| assert(await directoryHandle.IsSameEntry(record.root)); | ||
mingyc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| handleRecord(record); | ||
| } | ||
| }); | ||
| ``` | ||
Uh oh!
There was an error while loading. Please reload this page.