-
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
Open
mingyc
wants to merge
5
commits into
WICG:main
Choose a base branch
from
mingyc:sw
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| # Proposal: FileSystemSubscriptionManager | ||
|
|
||
| ## Authors | ||
|
|
||
| * [Ming-Ying Chung](https://github.com/mingyc) (Google) | ||
| * [Austin Sullivan](https://github.com/a-sully) (Google) | ||
|
|
||
| ## Background | ||
|
|
||
| The [FileSystemObserver API][fso-api] ([spec][fso-spec]) 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 | ||
| [fso-spec]: https://whatpr.org/fs/165.html#filesystemobserver | ||
|
|
||
| ## 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. Updating FileSystemObserver API to outlive Service Worker | ||
|
|
||
| #### 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, simply enabling it doesn't satisfy the goal. 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://github.com/whatwg/fs/blob/main/proposals/FileSystemObserver.md#handling-changes-made-outside-the-lifetime-of-a-filesystemobserver | ||
| [chrome-sw]: https://developer.chrome.com/blog/longer-esw-lifetimes#background | ||
|
|
||
| #### Outliving Service Worker | ||
|
|
||
| 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. | ||
| 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 2. Utilizing Service Worker Registration | ||
|
|
||
| The [ServiceWorkerRegistration][swr] 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. | ||
|
|
||
| There are already existing APIs utilizing the interface to receive notifications. | ||
| For example, `ServiceWorkerRegistration.pushManager` is the [PushManager] from the Push API that allows subscription to a push service. | ||
|
|
||
| This doc below proposes a similar interface under ServiceWorkerRegistration to allow subscribing to file system change events. | ||
|
|
||
| [swr]: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration | ||
| [PushManager]: https://developer.mozilla.org/en-US/docs/Web/API/PushManager | ||
|
|
||
| ## 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: | ||
|
|
||
| ```webidl | ||
| partial interface ServiceWorkerRegistration { | ||
| // Returns a reference to FileSystemSubscriptionManager interface, which allows | ||
| // for subscribing to specific file changes. | ||
| [SameObject] readonly attribute FileSystemSubscriptionManager fileSystem; | ||
| }; | ||
| ``` | ||
|
|
||
| It supports `subscribe()` and `unsubcribe()` to a `FileSystemHandle`, with [`FileSystemObserverObserveOptions`](https://whatpr.org/fs/165.html#dictdef-filesystemobserverobserveoptions). | ||
|
|
||
| ```webidl | ||
| // 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<undefined> subscribe(FileSystemHandle handle, | ||
| FileSystemObserverObserveOptions options = {}); | ||
| // Unsubscribes to changes to a FileSystemHandle. Returns a Promise that | ||
| // resolves when the unsubscription completes. | ||
| Promise<undefined> 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(); | ||
| }; | ||
| ``` | ||
|
|
||
| ```webidl | ||
| // Represents a subscription to changes to a FileSystemHandle. | ||
| dictionary FileSystemSubscription { | ||
| FileSystemHandle handle; | ||
| FileSystemObserverObserveOptions options; | ||
| }; | ||
| ``` | ||
|
|
||
| Second, allow service workers to fire a new type of event `FileSystemChangeEvent`, which includes a list of [`FileSystemChangeRecord`](https://whatpr.org/fs/165.html#dictdef-filesystemchangerecord). | ||
|
|
||
| ```webidl | ||
| partial interface ServiceWorkerGlobalScope { | ||
| // Fired when FileSystemSubscriptionManager observes changes. | ||
| attribute EventHandler attribute onfilesystemchange; | ||
| }; | ||
| ``` | ||
|
|
||
| ```webidl | ||
| // Represents a file system change event. | ||
| interface FileSystemChangeEvent : ExtendableEvent { | ||
| constructor(DOMString type, FileSystemChangeEventInit init); | ||
| sequence<FileSystemChangeRecord> records(); | ||
| }; | ||
|
|
||
| interface FileSystemChangeEventInit : ExtendableEvent { | ||
| required sequence<FileSystemChangeRecord> records; | ||
| } | ||
| ``` | ||
|
|
||
| ### Example: Observing Changes to a File | ||
|
|
||
| ```javascript | ||
| // main.js | ||
| const fileHandle = await window.showOpenFilePicker(); | ||
| async function observeFileChanges(fileHandle) { | ||
| const registration = await navigator.ServiceWorker.register("/service-worker.js"); | ||
| registration.fileSystem.subscribe(fileHandle); | ||
| } | ||
|
|
||
| // service-worker.js | ||
| self.addEventListener('filesystemchange', event => { | ||
| // The change record includes a handle detailing which file has changed, which | ||
| // in this case corresponds to the observed handle. | ||
| const changedFileHandle = event.records()[0].changedHandle; | ||
|
|
||
| // Since we're observing changes to a file, the `root` of the change | ||
| // record also corresponds to the observed file. | ||
| assert(await changedFileHandle.isSameEntry(event.records()[0].root)); | ||
|
|
||
| // Do something. | ||
| handleFile(changedFileHandle); | ||
| }); | ||
| ``` | ||
|
|
||
| ### 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('filesystemchange', event => { | ||
| for (const record of event.records()) { | ||
| if (record.type == "appeared" || record.type == "modified") { | ||
| // Backs up changed files. | ||
| backupFile(record.changedHandle); | ||
| } | ||
| } | ||
| }); | ||
| ``` | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.