Skip to content

Fire Mode: Add BrowserMode with plumbing#8478

Merged
0nko merged 29 commits into
developfrom
feature/ondrej/fire-mode-browser-mode
May 15, 2026
Merged

Fire Mode: Add BrowserMode with plumbing#8478
0nko merged 29 commits into
developfrom
feature/ondrej/fire-mode-browser-mode

Conversation

@0nko
Copy link
Copy Markdown
Member

@0nko 0nko commented May 7, 2026

Task/Issue URL: https://app.asana.com/1/137249556945/project/1207418217763355/task/1214579513091724?focus=true

Description

This PR adds the new BrowserMode and the related interfaces and their concrete implementations:

  • BrowserModeStateHolder that exposes enum class BrowserMode { REGULAR, FIRE }, which is the single source of truth for current mode. Theming overlay, tab switcher VM, mode-toggle pill, sync entry points, repository providers — all observe this Flow.
  • Adds FireModeAvailability that checks the feature flag and the WebView feature support
  • Adds BrowserMode plumbing to the main entry points

Related API proposal: https://app.asana.com/1/137249556945/project/1207418217763355/task/1214579944546013?focus=true

Steps to test this PR

Smoke testing that the app is launched correctly and opening an external link works as expected is sufficient.


Note

Medium Risk
Touches core BrowserActivity intent processing and tab creation, adding mode-based recreation and deferred-intent handling which could affect external link/widget/shortcut launches. New mode plumbing is guarded by availability checks but has broad surface area across entry points.

Overview
Introduces a new cross-module BrowserMode concept (REGULAR/FIRE) with a BrowserModeStateHolder source-of-truth and an app implementation (RealBrowserModeStateHolder).

Updates BrowserActivity and tab creation to be mode-aware (adapter/BrowserTabFragment arguments, DuckChat fragment args), and recreates the activity on mode changes; external entry-point intents can now be stamped as LAUNCH_REQUIRES_REGULAR_MODE and, if received while in FIRE, are deferred across a FIRE→REGULAR switch before processing.

Adds a new fire-mode-api/fire-mode-impl with FireModeAvailability (feature flag + WebView MultiProfile capability), wires it into BrowserViewModel.switchToMode, and updates numerous launch points (widgets, shortcuts, onboarding/settings/internal screens, tests) to pass a BrowserLaunchSource and correctly stamp intents.

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

@0nko 0nko requested a review from CDRussell May 7, 2026 13:51
Copy link
Copy Markdown
Member Author

0nko commented May 7, 2026

Comment thread app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt
@0nko 0nko force-pushed the feature/ondrej/fire-mode-browser-mode branch 2 times, most recently from 5656af4 to 48c2480 Compare May 11, 2026 17:38
Copy link
Copy Markdown
Member

@CDRussell CDRussell left a comment

Choose a reason for hiding this comment

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

@0nko there are two main things that need done here:

  1. consider all the ways the app can launch with an Intent and map carefully which will result in REGULAR mode being enforced. more details: #8478 (comment)
  2. feature flag around all of this! this is a majorly critical codepath and any mistakes here could be painful to pin down (e.g, intermittent feedback that something is weird) and we should be able to disable a single feature flag to get back to existing behavior if there are any problems.

Comment thread duckchat/duckchat-impl/build.gradle Outdated
* comes up. Survives the mode-switch [recreate] via [onSaveInstanceState]; consumed by
* [BrowserStateRenderer.showWebContent].
*/
private var pendingExternalIntent: Intent? = null
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is this only used for an Intent received while in fire mode like the comment says? If so, maybe add that to the name of it to make it clearer.

this new thing is confusing because we also already have a similar concept for lastIntent where it similarly has a deferred processing step inside of showWebContent like the one you've added for pendingExternalIntent

it's not clear what relationship these two transient intents share with each other, nor the order in which they should be processed if both exist. I don't have a concrete suggestion yet for improving, but flagging as a point of confusion in case you can come up with a good way of combining these and/or making it clearer how each relate to the other.

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.

is this only used for an Intent received while in fire mode like the comment says? If so, maybe add that to the name of it to make it clearer.

Yeah, pendingExternalIntent is only written in launchNewSearchOrQuery behind shouldSwitchToRegularModeBeforeProcessingIntent(), which gates on currentMode == FIRE. I can rename it to make the trigger explicit, something like pendingFireToRegularIntent.

this new thing is confusing because we also already have a similar concept for lastIntent where it similarly has a deferred processing step inside of showWebContent like the one you've added for pendingExternalIntent

lastIntent defers until automatic data clearing is finished and uses a different lifecycle (it has to survive the clearer Job in the same Activity instance, whereas pendingExternalIntent has to survive the Activity recreation and is saved).

I can rename both flags to make their purpose explicit or I can try to think about a bigger refactoring.. Let me know what you think.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I can rename both flags to make their purpose explicit or I can try to think about a bigger refactoring

I think the main thing is to understand the relationship between the two, if there is one. e.g., are they mutually exclusive? if not, what happens if both are set, does one need to be processed before the other etc...?

I don't know the answers to these because it's not clear in code yet. If you think you can make it clearer with renaming and comments, that sounds ok to me, thanks.

Comment thread app/src/main/java/com/duckduckgo/app/browser/BrowserViewModel.kt Outdated
Comment thread app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt Outdated
Comment thread app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt
@0nko 0nko requested a review from CDRussell May 13, 2026 17:01
@0nko
Copy link
Copy Markdown
Member Author

0nko commented May 13, 2026

Thanks @CDRussell! This took longer than I expected because there are browser launch points all over the place.

  1. Please see my comment here.
  2. This was already handled implicitly: when the FF is off, the current mode is always Regular, so the external link intent wouldn't cause the Activity restart. But I added explicit checks anyway, just to be safe.

Ready for another round.

Comment thread app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c560a7b. Configure here.

Comment thread app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt
* limitations under the License.
*/

@file:SuppressLint("NoImplImportsInAppModule")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why is this needed?

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.

Supresses the lint error for the com.duckduckgo.duckchat.impl.ui.DuckChatWebViewFragment.Companion.* keys that are being used for arguments. This was an pre-existing issue that should eventually get fixed but it's unrelated to this change, aside from adding another key.

@0nko 0nko requested a review from CDRussell May 15, 2026 11:57
@0nko 0nko merged commit 2908a38 into develop May 15, 2026
19 checks passed
@0nko 0nko deleted the feature/ondrej/fire-mode-browser-mode branch May 15, 2026 12:29
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.

2 participants