-
Notifications
You must be signed in to change notification settings - Fork 63
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
Use storage.sync APIs to sync preferences accross browser using Firefox Sync. #31
Conversation
In case you were wondering it is safe to use storage.sync even if users don't have sync activated. Also the backend is SQLite rather than a JSON file in the profile. |
Hi, thanks for the PR. Syncing everything is not possible since it would also sync stuff that's only valid in the local browser. So that would need to still be stored in the local storage. Also, how would switching from local to sync affect existing installations? Is some sort of migration needed or does it just work? |
Thank you for noticing that. I am going to split the storage and only store preferences inside the sync backend then.
I handle the migration by checking the local storage in case the sync storage is empty. |
Ah, now I see how the migration is done, cool.
I'd also say that only storing preferences in sync is the way to go, yeah. |
I understand that babel stage2 is probably/unfortunately needed to support the spread operator with webpack - but I really don't want to ship the whole codebase converted to stage2 just to have a slightly cleaner default preference detection/merge in the src-file. So if you could please change that accordingly and remove babel stage2 again. Other than that it looks good to me. Will test it manually to make sure everything works correct. |
Yes I quite agree, do you know if there is another way for webpack not to raise a syntax error with the spread operator since Firefox handles it? |
According to acornjs/acorn@5aa2e73 it should be in the next release of webpack. |
Would stage3 work for you? |
Adding the |
All it does is:
|
// set preferences defaults if not present | ||
if (!this.local.preferences) { | ||
if (!Object.keys(this.preferences).length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will always be true for a fresh installation if I'm not mistaken. Since this is the migration path it should additionally check whether this.local.preferences
exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually that's what is done the next line, when we create this.preferences we make sure to override default preferences with the local ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you install the Add-on the first time after this change is published, this.local.preferences
will be undefined
and the migration happening is not needed. It will only happen once; but still - it should be a migration-path, not something that runs on every first time install.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I see now - it actually does two things. For one it sets the preferences to default on first time install - which is wanted behavior. And additionally it migrates this.local.preferences
if available. Could you please check explicitly for this.local.preferences
inside this if and only do the migration if it exists? Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can but it doesn't cost anything to do it if it doesn't exists :)
@@ -35,33 +36,30 @@ class Storage { | |||
try { | |||
let storagePersistNeeded = false; | |||
this.local = await browser.storage.local.get(); | |||
this.preferences = await browser.storage.sync.get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I like explicit over implicit, so I'd actually prefer this.sync
here - which would as a side-effect make it possible that we could store something else besides preferences into sync without having to implement a migration-path again.
But since I'm not sure what else could be stored to sync, I'd also be OK with leaving it as it is.
} | ||
|
||
// Make sure to default missing preferences with default value | ||
this.preferences = {...this.preferencesDefault, ...this.preferences}; | ||
|
||
if (storagePersistNeeded) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a new preferencesDefault key is added this will no longer automatically set to true and thus the new preference default will not be available on the options page since the options page accesses storage directly - tho still local and not sync.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good find 🥇 should we use storage there too or switch to sync?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not exactly sure what you mean - could you please elaborate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you with "use storage" meant to require/import the storage.js
in the options page - then I'd say that's not that easy and I don't see the point of doing that since you could only reuse the code, but not access the actual background storage from the options page, afaik. Changing it to sync
sounds good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean using the storage.js interface to save the preferences.
It is a bit sad to let the preference page know about the underlying storage but I understand it might not be trivial to do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you would want to abstract it away, the way to go would imho be sending a message to the background to request the storage. The same is already done when saving the preferences.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that's what I had in mind, should I give it a try?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you like to, sure.
Something that just came to my mind. I've never used Firefox Sync - is it possible to deactivate for particular Add-ons? Like if someone has Sync configured but wants different preferences for an Add-on on a particular machine - would that be possible or would the Add-on have to implement that itself? |
You can deactivate sync for add-ons with Firefox Sync but if you don't it will always sync the preferences stored in |
I wonder how other Add-ons handle that - do they have a setting to disable syncing or do they just say: "if you enable Firefox Sync for Add-ons, your preferences will be synced, that's it"? :D |
Yes I guess the later :) |
Well, just checked uBlock Origin and it has an Actually, having it as an opt-in preference sounds really good to me. What do you think? |
IMHO I would rather go for the opt-out one, but I guess it depends what take we have on the default preferences 😂 |
I think it doesn't make sense to have a setting and not only because I am lazy implementing it but also because once you've configured your website rules and click rules there is no point not syncing them if you use the same sync account with add-on synchronization between them. |
The thing with opt-out is, that if you have Firefox Sync enabled and install the Add-on, it instantly syncs storage.sync - and if you then actually opt-out the Add-on can't really just delete everything in storage.sync because how do you know what got stored by your or by other machines? That would get complicated to keep a state. So you might end up with data in the cloud that you didn't want to have there in the first place. On the other hand you could argue that if you activated Firefox Sync including Add-ons, you probably want exactly that and I agree with you that being able to sync preferences (like website rules) is really useful. Personally I'm on the data-protection end of the spectrum though and thus would want to avoid handing out data without explicit permission. Which is actually one of the reasons I made this Add-on with "Automatic Mode" enabled per default in the first place (don't want to hand out my cookies and localstorage to anyone if it's not an explicit permanent container :D). |
The data saved in the cloud is encrypted |
Yeah, and if what I've read is correct your sync gets wiped if you change your password because it's needed to use the key to decrypt. Which is a strong signal that Mozilla takes security and privacy seriously - one of the reasons why I use Firefox. But "data-protection" also means giving users a choice. Even the strongest encryption might one day be broken - so if I want to keep data safe, I might want to decide that particular data should never leave my machine. Which is why I don't use Firefox Sync. Of course - Temporary Containers preferences aren't that important - but for me it's also a matter of principle. |
Yes I understand, then maybe we should fix this as wontfix. |
My standpoint is just that I don't want to sync by default - having a preference to opt-in sync is absolutely something I want to add. If you don't feel like putting more work into this PR because of that, that's absolutely OK. When I find the time to work on this feature I'm going to build on top what you've committed so far - if that's not OK for you, just let me know. Thanks for getting involved and sorry that it didn't went like you expected it to. |
I totally understand, don't worry about it. I thought I would be able to contribute it but I spent way too much time on it today, so I would rather close this than let it rot forever. You've been really helpful and thank your for your nice feedback, it's been a nice experience working with you on that PR today. I think if I were to work on it again I would have started from scratch the other way around:
In a way it is simpler than this PR alltogether :) |
Happy to hear that! Yeah, interesting and insightful PR for me too. Maybe until next time. :) |
Fixes #30