Steps to reproduce:
- Open Fenix (or GeckoViewExample)
- Enable strict antitracking/ETP (to enable the content blocker).
- Navigate to rottentomatoes.com
- Confirm that tracking content is being blocked. In Fenix this can be easily seen in the lock icon in the URL bar in the details, whereas in GeckoViewExample, a small gap at the top of the page (where an ad will otherwise appear) will remain empty when blocking is working.
- Navigate on the same tab to twitter.com
- On Fenix, confirm that tracking content is NOT being blocked as it should be (on GVE there is no simple UI/way to tell).
- Navigate on the same tab to rottentomatoes.com
- Confirm that tracking content is still NOT being blocked (see step 4 for details).
Very curiously, not all websites seem to trigger this bug. Twitter.com and Facebook.com do, but others may not. However, once it is broken, the user must toggle a setting in the UI like strict mode (more info on this shortly), or open a new tab to get it working again.
This was originally reported in https://github.com/mozilla-mobile/fenix/issues/26059, and
several of us have been digging around to discover what's happening. We're not sure when the bug regressed, or what regressed it; it looks like it may have been a surprisingly long time ago.
Note that this affects more than just the content blocker. These features are also broken:
- the anti-tracking content blocker used in Strict mode (useTrackingProtection flag)
- PWA display mode support (displayMode flag)
- display desktop page mode (viewportMode flag)
- custom user-agent string (customUserAgent flag)
Evidently browsingContexts need to have these flags set by GeckoView to keep these features working. The only place where this seems to be done is in GeckoViewSettings.onSettingsUpdate(), but this is not called during navigations, only when a tab is first created, or when a setting is changed in the UI.
I've made a trivial patch which also triggers onSettingsUpdate when onLocationChange begins to be handled, which fixes this. I'm not at all sure if it's the best fix here, but it's a start.
As for why this broke, I suspect that one of these things had to be true at some point, otherwise the current code would never have worked:
- onSettingsUpdate was once called each time a navigation happened, and so was able to update the browsingContext.
- The flags were once carried over to new browsingContexts across navigations in some lower-level code, and so did not have to be re-set.
- browsingContexts somehow did not change before, so the flags did not need to be re-set in the first place.
(Special thanks also to owlish, tihuang, and amoya for their help with the investigations here as well!)