Skip to content

Preserve per-site desktop mode preferences#8877

Open
0nko wants to merge 15 commits into
developfrom
feature/ondrej/remember-desktop-mode
Open

Preserve per-site desktop mode preferences#8877
0nko wants to merge 15 commits into
developfrom
feature/ondrej/remember-desktop-mode

Conversation

@0nko

@0nko 0nko commented Jun 15, 2026

Copy link
Copy Markdown
Member

Task/Issue URL: https://app.asana.com/1/137249556945/project/1214749231578703/task/1212541545715038?focus=true
API Proposal: https://app.asana.com/1/137249556945/project/1207418217763355/task/1215944643003573?focus=true

Description

This PR adds a per-site desktop mode preference persistence using eTLD+1 as a key (or "localhost" or an IP address). When a desktop mode is enabled on a site, it will be always used until it's either disabled or the site is cleared using the Fire button.

Steps to test this PR

  • Load some URL
  • Enable the Desktop mode
  • Notice the site is reloaded in a desktop mode
  • Open a new tab and load the same site
  • Notice it loads using the desktop mode
  • Use the fire button and delete this tab
  • On a NTP, load the same site
  • Notice it now loads in a mobile mode

Note

Medium Risk
Touches core WebView navigation (user-agent / intercept path) and new persistent local data tied to fire/clear semantics; well-tested but regressions could affect desktop vs mobile rendering per site.

Overview
Adds a new site-preferences module (Room-backed store) so “Desktop site” can be remembered per site key (eTLD+1, or raw host for localhost/IPs), gated by the rememberDesktopMode remote feature toggle.

Browser behavior: Toggling desktop/mobile in the menu writes or clears that preference; WebViewRequestInterceptor now calls isDesktopSiteEnabled(url) (suspend) so user-agent selection follows the stored choice on load. pageChanged syncs in-tab UI from the in-memory cache so desktop mode does not leak across domains.

Data clearing: Fire / clear-browser flows call clearAllButFireproofed (aligned with fireproof sites); per-domain burn also forgetDesktopMode for cleared domains.

When the feature is off, behavior stays the previous session-only in-tab desktop flag.

Reviewed by Cursor Bugbot for commit 9e8594a. Bugbot is set up for automated code reviews on this repo. Configure here.

0nko and others added 4 commits June 15, 2026 12:18
RealSitePreferencesRepository now implements two interfaces (SitePreferencesRepository
and MainProcessLifecycleObserver), so @ContributesBinding can no longer infer the bound
type. Specify it explicitly to fix the DI codegen failure in both AnvilDagger and Metro
builds (kaptGenerateStubs / Metro compile).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@landomen landomen self-assigned this Jun 16, 2026

@landomen landomen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0nko It happened multiple times that I had to force refresh the site to re-render in desktop mode after opening it. See video:

Screen_recording_20260616_103558.mp4

Comment on lines +3338 to +3341
// Persist the choice per-site. uri.host is the pre-rewrite host (e.g. m.example.com), whose eTLD+1
// (example.com) matches the key the desktop-rewritten URL produces; hosts without a registrable
// domain (IPs, localhost) fall back to the raw host. The optimistic cache update means the reload
// triggered below already sees the new value.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I'd recommend shorter comments or even skip them if code is clear

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll let Claude know.. 😁

Entity::class,
Relation::class,
DefaultBrowserPromptsAppUsageEntity::class,
SitePreferencesEntity::class,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you maybe considered creating a new module for site-preferences and a separate database? ;)

Asking because this relates to our Modularization AOI and adding new features that use AppDatabase will make it harder later to remove them. I'm not saying you need to do the new module now, just something to keep in mind.
(cc @aibrahim- )

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need a room DB for this? it seems a simple preferences store should be enough, e.g. androidx.datastore or even a SharedPreferences

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aibrahim- It seemed like a natural choice, since the settings is per-domain, which can grow indefinitely. Plus, this would allow to store other prefs per-domain in the future. But I supposed storing it as a list of domains in a DataStore would work if the list was reasonable.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@landomen Yeah, I suppose it could be a separate module. I can refactor it.

0nko and others added 6 commits June 18, 2026 10:51
# Conflicts:
#	app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt
#	app/src/test/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt
…ore the site-preferences cache is primed

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ntracts

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… remember-desktop-mode flag

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ase to version 61

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sktop-mode read

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@0nko 0nko requested a review from landomen June 18, 2026 20:29
@0nko

0nko commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

@landomen @aibrahim- I moved the site preferences to a separate module and tried to address the issue you noticed. It is now better but a site set to desktop mode occasionally still renders mobile because the desktop-UA reload is served from the HTTP cache, which can return a previously-fetched mobile copy (a forced refresh fixes it). This is a pre-existing limitation not introduced here, it is just easier to surface now that desktop mode is applied automatically on every initial load of a remembered site.

…rTest so the mocked listener returns false instead of a null Boolean

@landomen landomen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0nko Thanks for moving this to new module. I like the new API but just to follow the process, I think we need an official API proposal for this 😅

@0nko

0nko commented Jun 22, 2026

Copy link
Copy Markdown
Member Author

@landomen Thanks! For sure, just wanted you to take a look first to make sure it made sense.

Proposal: https://app.asana.com/1/137249556945/project/1207418217763355/task/1215944643003573?focus=true

# Conflicts:
#	app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt
#	app/src/test/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants