Feature: catchall domains - e.g. *.google.com - #2912
Conversation
99e5f07 to
9668e7b
Compare
|
Does the code have I fallback when Furthermore, thank for this updated version. It solves the problem discussed by @dannycolin in #2352 (comment). |
No the current implementation does not provide a fallback. Instead, the minimum required Firefox version is increased to See the change to the min version here: https://github.com/mozilla/multi-account-containers/pull/2912/changes#diff-6bc2c0b5164076a1b57b067398be19a40d2b8efa3428b03504562ea88593866cR37 |
|
Instead of bumping the minimum required version to 153, would it be feasible to hide the UI and feature when the feature is unavailable? That enables users of older Firefox versions to use other features of MAC. In particular, Firefox ESR 115 continues to be supported for a while for older Windows versions (until at least the start of the next year according to https://whattrainisitnow.com/calendar/). Firefox ESR 140 is also still supported, albeit only for a few months more. Fortunately the latest ESR is Firefox ESR 153, which is not too coincidentally the release that includes publicSuffix support. |
|
Makes sense, I will look at updating this PR to disable the catchall domains functionality on earlier Firefox versions. |
However if we wait until March 2027 a "disable the catchall domains functionality on earlier Firefox versions" isn't needed. |
|
I have updated this PR as follows:
|
Should be FYI: Although the patch "bumps" the version from 91.1.0 to 115.0, there is effectively no change in supported versions, because the addition of |
| try { | ||
| const domainName = browser.publicSuffix.getDomain( | ||
| hostname, | ||
| { allowUnknownSuffix: true, encoding: "display" }, |
There was a problem hiding this comment.
"display" should be used for display only, not as a storage key. Otherwise changes to display rules (by browser updates) would change the storage key and cause associations to be lost.
There was a problem hiding this comment.
Agreed. This will require converting the stored domains from punycode to display when showing the domains in the UI. Since there is currently no API available for doing this type of encoding conversion, we will need to call publicSuffix.getDomain(domain, { encoding: "display" }) again on each stored domain. See a relevant discussion on this topic here: w3c/webextensions#1012 (comment)
| const domainMatchKeys = domainManager.getDomainMatchKeys(pageUrl); | ||
| const siteStoreKey = this.getSiteStoreKey(pageUrl); | ||
| const storageResponse = await this.area.get([...domainMatchKeys, siteStoreKey]); | ||
| const domainStoreKey = domainMatchKeys.find(key => key in storageResponse); |
There was a problem hiding this comment.
Shouldn't you try to select the longest matching domain instead of an arbitrary one? Especially with the specified lookup order on the previous line (domainMatchKeys before siteStoreKeys), the implementation would end up preferring catchall domains over specific domains.
There was a problem hiding this comment.
This is intentional, so that the user is only prompted "Open this site in your assigned Container?" once for an enabled catchall domain, and not every time a new subdomain is visited. See my comment here #2912 (comment)
| this.storageArea.get(pageUrl).then((siteSettings) => { | ||
| this.storageArea.match(pageUrl).then(([siteStoreKey, siteSettings]) => { | ||
| if (siteSettings) { | ||
| siteSettings.neverAsk = true; |
There was a problem hiding this comment.
Not sure if I'm reading the code right, but could it be that the UI is prompting for a specific site, and then ends up saving the decision for the catchall? That would be surprising if it is the case.
There was a problem hiding this comment.
This is intentional, to avoid showing the user the "Open this site in your assigned Container?" screen every time they browse to a new subdomain with an enabled catchall domain. I.e. if the user clicks "Remember my decision for this site", it then applies to all subdomains. We could change the wording in the prompt to "Remember my decision for all sites in this domain" when a catchall domain is in effect.
The alternative is to:
- Show the prompt each time a new subdomain of an enabled catchall domain is visited (this may become annoying?)
- If the user then clicks "Remember my decision for this site", a new site entry will need to be added in storage for that subdomain, to hold the "never ask" setting
| const pageUrl = m.pageUrl; | ||
| if (m.neverAsk === true) { | ||
| if (m.defaultContainer === true) { | ||
| this.storageArea.remove(pageUrl); |
There was a problem hiding this comment.
Does this need to account for catchalls as well?
There was a problem hiding this comment.
Well spotted, I had overlooked this. Just as in #2912 (comment) , the same consideration applies here: do we re-prompt the user for every subdomain of an enabled catchall domain, or do we change the wording to "Remember my decision for all sites in this domain"?
If we re-prompt the user for every subdomain, then the implementation here becomes more complicated: we will need to store a list of subdomains to be explicitly excluded from an enabled catchall domain.
| .reverse(); | ||
| }, | ||
|
|
||
| getDomainNameFromStoreKey(domainStoreKey) { |
There was a problem hiding this comment.
I'd expect the getDomainNameFromStoreKey implementation to be completely neutral if publicSuffix is unavailable, but there is no isEnabled check here. Shouldn't we add an isEnabled check here?
There was a problem hiding this comment.
We still need this, even when catchall-domains are disabled, to distinguish storage entries that are catchall-domains from those that are plain sites.
It is theoretically possible for a user to use different browser versions on different devices: one browser may support catchall-domains, the other may not. Due to syncing, a device that does not support catchall-domains may still have those catchall-domain entries in storage. Those entries need to be detectable so that they can be filtered out, otherwise they will end up being displayed in the UI as if they are plain sites. Your comment here has highlighted a bug in my implementation that this filtering-out is currently not done, and so I will need to update the getDomainsAndAssignments() method here: https://github.com/mozilla/multi-account-containers/pull/2912/changes#diff-1ffae9dff098547503a2394dc0bede4c2b4bcbbbdcea33cbbd9aea05d2a8d70fR66
FYI - the storage key format for catchall-domains and plain sites is intentionally identical, so that syncing of the storage entries is done automatically for both catchall-domains and plain sites. Storage key examples:
| Storage Key | Type |
|---|---|
siteContainerMap@@_www.amazon.com |
Plain site |
siteContainerMap@@_*.amazon.com |
Catchall domain |
| // The container we have in the assignment map isn't present any | ||
| // more so lets remove it then continue the existing load | ||
| if (siteSettings && !container) { | ||
| if (siteSettings && !siteSettings.isDomain && !container) { |
There was a problem hiding this comment.
Why is the "clean up when container isn't present anymore" logic conditional on !siteSettings.isDomain? With the proposed logic you'd fall through below, to reloadPageInContainer with an invalid cookieStoreId.
There was a problem hiding this comment.
Agreed: as with plain sites, this should abort if a container is missing. I will make the change.
However, in my view this existing code is dangerous: deleting assignments silently while a user is browsing. What if the container is temporarily unavailable due to a syncing issue or some other glitch?
It may be better to keep the assignments to the phantom container, and show the container in the UI with special highlighting, allowing the user to manually delete it, or else reinstate it.
Note that user assignments suddenly going missing is a commonly-reported bug with MAC, e.g.: #2901 and also https://chat.mozilla.org/#/room/#containers:mozilla.org This silent deletion of assignments while browsing may be contributing to that issue.
However, I do note other bug reports about deleted containers reappearing, e.g. #2682 While fixing that is important, my view is that doing so silently by deleting missing containers in onBeforeRequest is not the best solution.
| if (pageUrlorUrlKey.includes("siteContainerMap@@_")) return pageUrlorUrlKey; | ||
| const url = new window.URL(pageUrlorUrlKey); | ||
| const domainName = this.getDomainNameFromHostname(url.hostname); | ||
| return domainName ? this.getDomainStoreKeyFromHostname(domainName) : null; |
There was a problem hiding this comment.
getDomainStoreKeyFromHostname is not defined anywhere. In fact... this whole function getDomainStoreKey does not have any callers, so it is dead code.
There was a problem hiding this comment.
Agreed, I will remove this method.
| // "siteContainerMap@@_*.amazonaws.com", | ||
| // ] | ||
| const labels = domainName.split("."); | ||
| let suffix = labels.pop(); |
There was a problem hiding this comment.
This logic here appears to return keys that are not valid domain names. There are public suffices with more than 3 parts, e.g. act.edu.au and edu.au and au are all public suffixes. Is it OK to return such domains here? (I haven't checked other places, would be good to double check as well).
There was a problem hiding this comment.
getDomainMatchKeysFromName() is used when determining if the user has enabled a catchall-domain for a site.
The problem this method addresses is that a site may have more than one possible public suffix, and therefore more than one possible catchall-domain. When determining if the user has enabled a catchall-domain for a site, we need to try all possible public suffixes.
E.g. the user browses to site www.mysite.s3.us-west-1.amazonaws.com:
| Public Suffix | Catchall Domain Key to Try |
|---|---|
s3.us-west-1.amazonaws.com |
*.mysite.s3.us-west-1.amazonaws.com |
com |
*.amazonaws.com |
If we don't check for all possible catchall-domains, a bug would manifest if the user:
- Browses to
banana.amazonaws.com - Adds it to container
Amazon - Uses the UI to enable catchall-domain
*.amazonaws.comin the same container - Browses to
www.mysite.s3.us-west-1.amazonaws.comin a new tab - The longest catchall-domain for this site is
*.mysite.s3.us-west-1.amazonaws.com, therefore a lookup of this key in storage would not find enabled catchall-domain*.amazonaws.com
The publicSuffix API provides a method for obtaining the longest registrable domain for a site, but not all possible registrable domains.
Therefore as a workaround, this method creates an array of all possible catchall-domain-keys by removing leading domain labels one-at-a-time. This array is then used for a single storage lookup, and the first match is used.
Note that the returned catchall-domain-key array may indeed contain redundant candidates such as *.act.edu.au and *.edu.au, however these will never match anything in storage since the UI provides no way for the user to actually add these.
| "gecko": { | ||
| "id": "@testpilot-containers", | ||
| "strict_min_version": "91.1.0", | ||
| "strict_min_version": "115.0.0", |
There was a problem hiding this comment.
As noted at #2912 (comment) this should be 115.0, not 115.0.0
| "strict_min_version": "115.0.0", | |
| "strict_min_version": "115.0", |
There was a problem hiding this comment.
Noted, I will change this.
Before submitting your pull request
npm testand all tests passed.Description
Adds the ability to assign all subdomains of a domain to a container.
The list of domains is automatically updated as new sites are assigned to a container. This feature is made possible by the new
publicSuffixAPI that is due to be released in Firefox 153.mac-domains.mov
Type of change
Select all that apply.
Tag issues related to this pull request: