-
Notifications
You must be signed in to change notification settings - Fork 56
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
Proposal: StorageArea.onChanged filters #475
Comments
No matter what the API looks like, it is useful to support multiple namespaces in StorageChangeFilter is also useful for performance. |
@polywock When you change the actual storage, instead of adding a storage changed listener, can't you just send a message to the background script when a relevant storage has changed? |
@carlosjeurissen That's a possibility I considered, but it will be inefficient and hacky for my use cases. It's almost like implementing your own
The StorageChangeFilter proposal will be significantly more efficient and developer-friendly. function handleChanges(changes) {
// handle changes
}
browser.storage.local.onChanged.addListener(handleChanges, {startsWith: ['flags:', 'global:']}) I currently use the session StorageArea for keys I want the service worker to ignore, and the local StorageArea for keys that are relevant to the background service worker. This is an okay workaround, but some of the service worker relevant keys are more suited towards a session storage. |
Another option is to have |
@xeenon I mentioned that in the very bottom of my original post. That's my backup proposal. (edit - I added header for it) The filters should also have startsWith/contains. I have dynamic storage keys that include the tabId, which can't be predicted ahead of time. |
@polywock Awesome! Sorry I missed that. I think that is the approach I would prefer. It is backward compatible, at the risk of firing the event all the time in browsers that don't support the filter, but it won't break. |
Based on the feedback from @hanguokai and @xeenon, the onChanged filters appear to be the more practical proposal. I've updated the title and original post to reflect this. |
There's a discrepancy in the names of properties: either every matcher should be a verb (i.e. Instead of prefixes and suffixes it'd be more helpful to use a subset of declarativeNetRequest's syntax for P.S. Filtering based on prefix would help Violentmonkey. We had to implement our own onChanged because our content scripts need to listen to specific changes in storage on demand, potentially in hundreds of tabs, so we couldn't rely on the browser's implementation. |
Is there a performance benefit? As mentioned by tophf, if filters are introduced, it would require a lot of different filters to cover all eventualities. browser.storage.StorageArea.onChanged.addListener(handleChanges, {startsWith: ['flags:', 'global:']});
// storage change event
// check if filter exists
// apply filter
// send to extension browser.storage.StorageArea.onChanged.addListener(handleChanges);
// storage change event
// send to extension
function handleChanges(changes) {
// apply filter
if (!changes.hasOwnProperty('xys')) { return; }
// process changes
} |
Without filters, the browser process will have to send a serialized message to every listener in all tabs, so if there are 100 tabs listening to onChange, then there will be 100 inter-process messages, which is expensive, especially if the stored object was big. |
I see.... that makes sense in case of listeners registered in content scripts. I am not familiar with the process. If it is a global event, then the number of tabs wouldn't matter. |
Since the storage is handled in a separate browser process, even one inter-process message is still wasteful, especially if the object is big. Currently, AFAIK, there's no mechanism to broadcast one message to many processes for different sites, although technically there might be such a possibilty in the OS API, but I'm not sure all platforms have such a mechanism and it may require the use of shared memory, which would make it a possible vector for privilege escalation exploits. |
I was more concerned about the lifecycle of the background service worker. The onChanged filters will provide developers with a method to optimize the service worker lifecycle, ensuring that it doesn’t initialize when it’s not necessary. browser.storage.StorageArea.onChanged.addListener(handleChanges, {startsWith: ['flags:', 'global:']});
// Service worker only loaded (or lifespan extended) for relevant storage changes. browser.storage.StorageArea.onChanged.addListener(handleChanges);
// Service worker loaded (or lifespan extended) for all storage changes. |
@oliverdunk Since the filter types were a potential concern from the Chrome team, how about this revision? interface StorageFilter {
matches?: Glob[]
excludeMatches?: Glob[]
}
browser.storage.local.onChanged.addListener(handleChanges, {matches: ['flags:*', 'global:*']}) |
Thanks for the edit. I'll need to sync with the team (I'm still not sure how keen we are to add new filters in general short term) but the shorter list definitely looks better. |
Problem
When monitoring storage changes via a service worker, all changes activate the worker, even if only a specific value matters.
Proposal
Allow StorageArea.onChanged.addListener to accept an optional StorageChangeFilter as an argument.
The text was updated successfully, but these errors were encountered: