Skip to content

Conversation

@pull
Copy link

@pull pull bot commented Aug 19, 2021

See Commits and Changes for more details.


Created by pull[bot]

Can you help keep this open source service alive? 💖 Please sponsor : )

nalcalag and others added 22 commits November 4, 2025 18:20
Task/Issue URL:
https://app.asana.com/1/137249556945/project/72649045549333/task/1210985220483936?focus=true

### Description
Implement switch feature in Subscription Settings

### Steps to test this PR
_Pre steps_

- [x] Apply patch from
https://app.asana.com/1/137249556945/project/1209991789468715/task/1210448620621729?focus=true

_Free Trial_
- [x] Install from branch
- [x] Purchase a test monthly subscription (Free Trial)
- [x] Go to Subscription Settings Screen
- [x] Check switch option is not available

_Upgrade_
- [x] Cancel and wait until Free Trial expires **OR** wait until free
trial is renewed to a paid monthly subscription
- [x] If expired after canceled, purchase a monthly subscription again
- [x] Go to Subscription Settings
- [x] Check Switch option is there with updated text "Switch to Yearly
and Save 16%"
- [x] Check "Manage Plan and Payment Options" item is also updated
- [x] Select Switch option
- [x] Check copy/price/currency is correct for upgrade option
- [x] Test closing dialog and selecting "Keep monthly plan" dismiss
dialog
- [x] Select "Switch to Yearly.."
- [x] Check switch is done correctly
- [x] Check subscription settings screen data is updated as soon as
switch is success

_Downgrade_
- [x] Now, you see yearly data in Subscription Settings screen
- [x] Check Switch updated text is just "Switch plan"
- [x] Select Switch option
- [x] Check copy/price/currency is correct for downgrade option
- [x] Test closing dialog and selecting "Keep Yearly Plan" dismiss
dialog
- [x] Select "Switch to Monthly.."
- [x] Check switch is done correctly
- [x] Check subscription settings screen data is updated as soon as
switch is success

_Dynamic currency_
- [x] Open switch dialog
- [x] Check currency matches your Google Play account ($, £, €, etc.)

_Expired_
- [x] Cancel subscription and wait for it to expire
- [x] Go to Subscription Settings
- [x] Check switch option is not available anymore

_FF disabled_
- [x] Purchase a new subscription
- [x] Go to Settings > Feature Flag Inventory
- [x] Disable `supportsSwitchSubscription` FF
- [x] Go back to Subscription Settings screen
- [x] Check Switch option is not available

### UI changes
| Before  | After |
| ------ | ----- |
<img width="378" height="845" alt="Screenshot 2025-10-31 at 13 29 05"
src="https://github.com/user-attachments/assets/2fec2709-89a1-477d-9e53-98692e008d41"
/>|<img width="381" height="845" alt="Screenshot 2025-10-30 at 14 47 37"
src="https://github.com/user-attachments/assets/f8d56e39-5c17-44ec-a862-fe0c580553e1"
/>|

| Upgrade  | Downgrade |
| ------ | ----- |
<img width="378" height="835" alt="Screenshot 2025-10-30 at 14 40 11"
src="https://github.com/user-attachments/assets/d8ce6907-dd6e-41bd-bf4a-4ff6e7963215"
/>|<img width="379" height="841" alt="Screenshot 2025-10-30 at 14 47 47"
src="https://github.com/user-attachments/assets/19537c2f-c07c-4b09-80eb-e2054a6a9012"
/>|

---------

Co-authored-by: Lukasz Macionczyk <lukasz.macionczyk@gmail.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1200204095367872/task/1211816347754330?focus=true

### Description

- Removes `JobInfoSchedulerService` from the manifest merger

### Steps to test this PR

- [ ] Testing steps in task
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207418217763355/task/1211565479656355?focus=true

### Description

This PR adds the last integration of the split omnibar to the address
bar:
- When the split omnibar type is selected, the top omnibar buttons are
hidden
- The mock toolbar must show the split omnibar when loading

### Steps to test this PR

_Omnibar button_
- [ ] Enable the `splitOmnibar` flag 
- [ ] Go to Settings -> Appearance
- [ ] Select the split omnibar
- [ ] Go back to the browser
- [ ] Notice the buttons next to the address bar are gone

_Mock split toolbar_
- [ ] Restart the app
- [ ] While the app is loading, notice the mock top bar and bottom
navigation bar are displayed until the app's loaded
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207418217763355/task/1211819634741598?focus=true

### Description

This PR removes the `newToolbarFeature` feature flag and all the
associated logic.

### Steps to test this PR

_Top omnibar_
- [ ] Set the omnibar position to TOP
- [ ] Go to the tab switcher
- [ ] Verify all the buttons work as expected
- [ ] Verify the menu items work as expected
- [ ] Verify the selection mode works (tap on Select tabs in the menu)
as expected
- [ ] Verify the tab scrolling works as expected (create many tabs in
the developer mode)

_Bottom omnibar_
- [ ] Set the omnibar position to BOTTOM
- [ ] Go to the tab switcher
- [ ] Verify all the buttons work as expected
- [ ] Verify the menu items work as expected
- [ ] Verify the selection mode works (tap on Select tabs in the menu)
as expected
- [ ] Verify the tab scrolling works as expected (create many tabs in
the developer mode)
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1202552961248957/task/1211716560268930?focus=true

### Description
Move all ADS related modules under the same folder

### Steps to test this PR

_Smoke tests_
- [x] Open the app installing the Play flavour
- [x] Play around to verify nothing is broken

_Play Flavour_
- [x] Open the app installing the Play flavour
- [x] Navigate to settings
- [x] Verify that the ADS Preview feature is not visible

_Internal Flavour_
- [x] Open the app installing the Internal flavour
- [x] Navigate to settings
- [x] Verify that the ADS Preview feature is visible
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211766964402360?focus=true

### Description
Adds error handling for when PIR encrypted database fails to decrypt and
we can't access the data.

### Steps to test this PR
See
https://app.asana.com/1/137249556945/task/1211824590968188?focus=true

### UI changes
A new error dialog when opening PIR. See
https://app.asana.com/1/137249556945/task/1211824590968188?focus=true
Task/Issue URL: https://app.asana.com/1/137249556945/project/72649045549333/task/1211755269770778?focus=true 

### Description

### Steps to test this PR

_Feature 1_
- [ ] Apply [patch](https://duckduckgo-my.sharepoint.com/:u:/p/cbarreiro/EQzRDGHt8VVNicoRG-pU560BBVo07vUHvuprNNcneF9Qgg?e=SJ0f8h)
- [ ] Fresh install
- [ ] Filter logs by "Cris"
- [ ] Load http://privacy-test-pages.site/security/badware/malware-download.html and refresh page
- [ ] Check logs for
    - [ ] `Blob downloads listener received WebViewCompat message: webViewCompat Ping:http://privacy-test-pages.site/security/badware/malware-download.html 10ms`. Validates `jsSendsInitialPing` and `jsInitialPingDelay`
    - [ ] `delaying response by 10 ms`. Validates `initialPingDelay`
    - [ ] `Posting response Pong from Native`. Validates `replyToInitialPing`
    - [ ] `Sending message PageStarted using reply proxy`. Validates `sendMessageOnPageStarted` and `sendMessagesUsingReplyProxy`
    - [ ] `Blob downloads listener received WebViewCompat message: webViewCompat PageStarted from ddgBlobDownloadObj`. Validates `useBlobDownloadsMessageListener` and `jsRepliesToNativeMessages`
- [ ] Open context menu
- [ ] Check logs for
    - [ ] `Sending message ContextMenuOpened using reply proxy`. Validates `sendMessageOnContextMenuOpen`
    - [ ] `Blob downloads listener received WebViewCompat message: webViewCompat ContextMenuOpened from ddgBlobDownloadObj`. Validates `useBlobDownloadsMessageListener` and `jsRepliesToNativeMessages`
- [ ] Test blob downloads still work

_Feature 2_
- [ ] Apply [patch
](https://duckduckgo-my.sharepoint.com/:u:/p/cbarreiro/EeK6GQN0aK9Fola1TnxLnnABPCzKOQpmcEN5jd5JUNSDuQ?e=xdS2SB)
- [ ] Fresh install
- [ ] Filter logs by "Cris"
- [ ] Load http://privacy-test-pages.site/security/badware/malware-download.html and refresh page
- [ ] Check logs for
    - [ ] `webViewCompat message received: webViewCompat Ping:http://privacy-test-pages.site/security/badware/malware-download.html 10ms`. Validates `initialPingDelay` 10ms, `jsSendsInitialPing` enabled,  and `useBlobDownloadsMessageListener` disabled
    - [ ] No log for `delaying response by 10 ms` nor `Posting response Pong from Native`. Validates `replyToInitialPing` disabled
    - [ ] No log for `Sending message PageStarted...`. Validates `sendMessageOnPageStarted` disabled
- [ ] Open context menu
- [ ] Check no logs for `Sending message ContextMenuOpened...`. Validates `sendMessageOnContextMenuOpen` disabled

_Feature 3_
- [ ] Apply [patch](https://duckduckgo-my.sharepoint.com/:u:/p/cbarreiro/EZsVUIl3CNVFkgn4cJYwuLQBdrNHa8ONEHu_264GHUYoVg?e=ZMA438)
- [ ] Fresh install
- [ ] Filter logs by "Cris"
- [ ] Load http://privacy-test-pages.site/security/badware/malware-download.html and refresh page
- [ ] Check logs for
    - [ ] `webViewCompat message received: webViewCompat Ping:http://privacy-test-pages.site/security/badware/malware-download.html 10ms`. Validates `initialPingDelay` 10ms, `jsSendsInitialPing` enabled,  and `useBlobDownloadsMessageListener` disabled
    - [ ] No log for `delaying response by 10 ms` nor `Posting response Pong from Native`. Validates `replyToInitialPing` disabled
    - [ ] No log for `Sending message PageStarted...`. Validates `sendMessageOnPageStarted` disabled
- [ ] Open context menu
- [ ] Check logs for `Sending message ContextMenuOpened not using reply proxy`. Validates `sendMessageOnContextMenuOpen` enabled and `sendMessagesUsingReplyProxy` disabled

### UI changes
| Before  | After |
| ------ | ----- |
!(Upload before screenshot)|(Upload after screenshot)|
… features (#7061)

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

### Description
Adds a daily pixel that report WebView support for `MULTI_PROFILE` and
`DELETE_BROWSING_DATA` features.

### Steps to test this PR

- [ ] Set your logcat to filter for: `message:webview_capabilities`
- [ ] Launch the app.
- [ ] Verify that `webview_capabilities` pixel is not sent.
- [ ] Go to developer settings and enable `reportWebViewCapabilities`.
- [ ] Force close and restart the app.
- [ ] Verify that `webview_capabilities` pixel is sent with params:
`version={your webview version}, multi_profile={true/false},
delete_browsing_data={true/false}, petal=true`
- [ ] Background and reopen the app.
- [ ] Verify that `webview_capabilities` pixel is ignored.
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1202552961248957/task/1211852239322423?focus=true

### Description

### Steps to test this PR

- [x] Tests should pass
- [ ]

### No UI changes
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1174433894299346/task/1211834986565997?focus=true

### Description
This PR adds a FF for the new full screen mode. No functionality has
been added to it.

### Steps to test this PR

_Internal flavour_
- [x] Install internal flavour
- [x] Navigate to AI Features
- [x] Verify “Full Screen Mode” toggle is visible

_Play flavour_
- [x] Install Play flavour
- [x] Navigate to AI Features
- [x] Verify “Full Screen Mode” toggle is not visible
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207908166761516/task/1211756086814103?focus=true

### Description

Added support for sending subscription events to ContentScopeScripts.
This enables real-time updates to the SERP settings when DuckChat
settings change. The implementation includes:

- Created a new `ContentScopeScriptsSubscriptionEventPlugin` interface
to allow features to provide subscription event data
- Added a plugin point for subscription event plugins
- Implemented a DuckChat-specific plugin that sends the enabled state to
Content Scope Scripts
- Added subscription event channels and flows in both
BrowserTabViewModel and SettingsWebViewViewModel
- Set up observers in BrowserTabFragment and SettingsWebViewActivity to
send events to Content Scope Scripts

### Steps to test this PR

_DuckChat Settings Sync_ _from_ _Browser_

- [x] Enable `serpSettingsSync`​ feature toggle
- [x] Do a search e.g. "FPL"
- [x] Open Settings -> AI Features
- [x] Disable/enable Duck.AI
- [x] Navigate back to SERP
- [x] Verify that the subscription event is sent to Content Scope
Scripts (check logs for "SERP-Settings: Sending subscription event
data") with the correct state
- [x] Open Settings -> AI Features
- [x] Disable/enable Duck.AI
- [x] Verify that the subscription event is sent to Content Scope
Scripts (check logs for "SERP-Settings: Sending subscription event
data") with the correct state

_DuckChat Settings Sync_ _from_ _SettingsWebView_

- [x] Enable `serpSettingsSync`​ feature toggle
- [x] Open Settings -> AI Features
- [x] Note the current state of Duck.AI
- [x] Click "Search Assist Settings"
- [x] Press back
- [x] Verify that the subscription event is sent to Content Scope
Scripts (check logs for "SERP-Settings: Sending subscription event
data") with the correct state
- [x] Disable/enable Duck.AI
- [x] Click "Search Assist Settings"
- [x] Press back
- [x] Verify that the subscription event is sent to Content Scope
Scripts (check logs for "SERP-Settings: Sending subscription event
data") with the correct state



### UI changes

N/A
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1210594645151737/task/1211375666072192?focus=true

### Description
Removes `webTrackingProtectionsGrid` feature flag / killswitch that has
been enabled by default since launching the feature in September

### Steps to test this PR

_Web Tracking Protection Grid_
- [x] Go to Settings -> Web Tracking Protection
- [x] Verify you see a grid of cards 

### UI changes
Removes the old UI variant

---------

Co-authored-by: Dax The Translator <daxmobile@duckduckgo.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211841662615810?focus=true

### Description

- Moves `InputModeTabLayout` to the `browser-ui` module

### Steps to test this PR

- [ ] Open the Input Screen
- [ ] Verify that the Input Mode Widget renders correctly in light and
dark mode
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211841661898284?focus=true

### Description

- Adds the Input Mode toggle to voice search
- Respects the current tab when launched from the Input Screen
- Remembers last used mode everywhere else
- Adds a "Voice Search" setting to "Duck.ai Shortcuts" to enable/disable
the feature
- Adds a `duckAiVoiceSearch` feature toggle set to `INTERNAL`

### Steps to test this PR

_Unfocussed state_
- [ ] Enable Private Voice Search
- [ ] Tap the Voice Search icon in the omnibar on unfocussed state
- [ ] Verify that the toggle is set is set to Search
- [ ] Say something
- [ ] Verify that a Search is completed
- [ ] Tap the Voice Search icon in the omnibar
- [ ] Toggle to Duck.ai
- [ ] Say something
- [ ] Verify that a Duck.ai query is completed
- [ ] Tap the Voice Search icon in the omnibar
- [ ] Verify that Duck.ai is pre-selected

_Input Screen_
- [ ] Go to the Search tab on the Input Screen
- [ ] Tap the Voice Search button
- [ ] Verify that the toggle is set is set to Search
- [ ] Say something
- [ ] Verify that a Search is completed
- [ ] Switch to Duck.ai tab
- [ ] Tap the Voice Search button
- [ ] Verify that the toggle is set is set to Duck.ai
- [ ] Say something
- [ ] Verify that a Duck.ai query is completed
- [ ] While still on the Duck.ai tab, tap the Voice Search button
- [ ] Toggle to Search
- [ ] Say something
- [ ] Verify that a Search is completed

_Disabled_
- [ ] Disable “Voice Search” in “Duck.ai Shortcuts”
- [ ] Verify that the toggle is no longer visible
- [ ] Re-enable and disable Duck.ai
- [ ] Verify that the toggle is no longer visible

_playDebug_
- [ ] Build `playDebug`
- [ ] Verify that the “Voice Search" setting is not visible
- [ ] Verify that the toggle is not visible in voice search

### UI changes
| Before  | After |
| ------ | ----- |
<img width="1080" height="2340" alt="voice_disabled_dark"
src="https://github.com/user-attachments/assets/d7aeed84-ee78-4e13-8b75-539e25d41162"
/>|<img width="1080" height="2340" alt="voice_search_dark"
src="https://github.com/user-attachments/assets/afeb6637-f4bc-4a54-a1e9-6d889400a157"
/>

| Before  | After |
| ------ | ----- |
<img width="1080" height="2340" alt="Screenshot_20251106_153250"
src="https://github.com/user-attachments/assets/e385938f-d5ad-4d52-a5fd-f0088d501604"
/>|<img width="1080" height="2340" alt="voice_setting_dark"
src="https://github.com/user-attachments/assets/7c0331b5-017d-4463-9aa0-083b2977a2e6"
/>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211863634389611?focus=true

### Description

- Adds pixels when completing a voice search using the Input Mode toggle
and canceling a voice search

### Steps to test this PR

- [ ] Submit a “Search” voice search
- [ ] Verify `Pixel sent: m_voice_search_serp_done with params:
{source=browser} {}`
- [ ] Submit a “Duck.ai” voice search
- [ ] Verify `Pixel sent: m_voice_search_aichat_done with params:
{source=browser} {}`
- [ ] Cancel a voice search
- [ ] Verify `Pixel sent: m_voice_search_cancelled with params:
{source=browser} {}`

_Disabled_
- [ ] Disable “Voice Search” in “Duck.ai Shortcuts"
- [ ] Go to the Input Screen
- [ ] Submit a “Search” voice search
- [ ] Verify not sent `Pixel sent: m_voice_search_serp_done with params:
{source=browser} {}`
- [ ] Submit a “Duck.ai” voice search
- [ ] Verify not sent `Pixel sent: m_voice_search_aichat_done with
params: {source=browser} {}`
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207418217763355/task/1211869964241175?focus=true

### Description

Only show the keyboard when opening a tab for the first time.

### Steps to test this PR

- [ ] Create a new NTP
- [ ] Notice the keyboard pops up
- [ ] Switch to a different tab
- [ ] Come back to the NTP
- [ ] Notice the keyboard does not pop up
- [ ] While on a NTP, go to settings (or any other screen)
- [ ] Come back to the NTP
- [ ] Notice the keyboard does not pop up
- Automated content scope scripts dependency update

This PR updates the content scope scripts dependency to the latest
available version and copies the necessary files.

Tests will only run if something has changed in the
`node_modules/@duckduckgo/content-scope-scripts` folder.

If only the package version has changed, there is no need to run the
tests.

If tests have failed, see
https://app.asana.com/0/1202561462274611/1203986899650836/f for further
information on what to do next.

_`content-scope-scripts` folder update_
- [ ] All tests must pass
- [ ] Privacy tests must pass

_Only `content-scope-scripts` package update_
- [ ] All tests must pass
- [ ] Privacy tests do not need to run

Co-authored-by: daxmobile <daxmobile@users.noreply.github.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1202552961248957/task/1211500171306010?focus=true

### Description
Scope
- Create attributed-metrics module
- Add database to store events
- Connect with FF: enable/disable client
- Connect with Atb, privacy config
- Handles initialization and returning users checks
- Handles expiry date to disable client

### Steps to test this PR

While testing this PR you need to add the following in your logcat
filter:
`tag~:"AttributedMetrics"`

_Feature 1_
- [x] We need fresh install (including removing DDG folder in file
system)
- [x] open the app
- [x] wait for privacy config download, since we need atb init
- [x] Detected new install not reinstall Log: `New install detected,
attributed metrics active`
- [x] Log: `Client status running: true...`
- [x] Skip onboarding and go to browser 
- [x] Access feature flag inventory
- [x] Disable `attributedMetrics` FF
- [x] restart the app
- [x] See in the log `Privacy config downloaded, attributed metrics
enabled: false` (that should disable the client)
- [x] and log `Client status running: false -> isActive: true,
isEnabled: false...`

_Feature 2_
- [x] fresh install but keep DDG folder
- [x] open the app
- [x] wait for privacy config download, since we need atb init
- [x] check logs for `App reinstall detected, attributed metrics will
not be active`
- [x] and `Client status running: false -> isActive: false, isEnabled:
true...`

### UI changes
| Before  | After |
| ------ | ----- |
!(Upload before screenshot)|(Upload after screenshot)|
…ling (#7081)

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

### Description
Moves the feature flag checks to `io` instead of `main`. This is
triggered from `MainProcessLifecycleObserver` so is an important hot
path for app launch / ANR prevention.

### Steps to test this PR
- QA optional
- [ ] [optional]: add a log statement to
`FirstPartyCookiesModifierWorker.doWork()` and make sure it continues to
fire with this change in place when the process is created
- [ ] [optional]: verify the `StrictMode` violation warning no longer
shows on app process creation

Co-authored-by: Craig Russell <1336281+CDRussell@users.noreply.github.com>
github-actions bot and others added 30 commits December 9, 2025 12:30
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1157893581871903/task/1212289736589845?focus=true

### Description
Translations PR

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds localized `duckAiFullScreenModeTitle` and
`duckAiFullScreenModeDescription` across many locales and removes their
prior definitions from `values/donottranslate.xml`.
> 
> - **Localization**:
> - Add translations for `duckAiFullScreenModeTitle` and
`duckAiFullScreenModeDescription` in `values-*/strings-duckchat.xml`
(bg, cs, da, de, el, es, et, fi, fr, hr, hu, it, lt, lv, nb, nl, pl, pt,
ro, ru, sk, sl, sv, tr, and base `values`).
> - **Resources cleanup**:
> - Remove non-translatable definitions from `values/donottranslate.xml`
and move English strings into `values/strings-duckchat.xml`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
60cc0e4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Dax The Translator <daxmobile@duckduckgo.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1202552961248957/task/1212315779149991?focus=true

### Description

- Update existing screen search mode E2E tests after enabling short URL
option.
- Update existing bookmarks E2E tests after enabling short URL option,
the tap on the omnibar was based on the URL and not on the view id.

### Steps to test this PR

- [x] Make sure bookmarks maestro tests are passing `maestro test
.maestro/bookmarks`
- [x] Make sure input screen maestro tests are passing `maestro test
.maestro/input_screen`
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1212358376159786?focus=true

### Description
This PR removes obsolete languages from fastlane to match Play Store

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Removes obsolete localized changelog entries in Android fastlane
metadata to align with Play Store locales.
> 
> - **Fastlane Android metadata**:
> - **Changelogs pruned/updated** in
`fastlane/metadata/android/*/changelogs/default.txt` to match Play Store
locales:
>     - `ca/`, `id/`, `ja-JP/`, `ko-KR/`, `zh-CN/`, `zh-TW/`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6f1f28c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
- Automated content scope scripts dependency update

This PR updates the content scope scripts dependency to the latest
available version and copies the necessary files.

Tests will only run if something has changed in the
`node_modules/@duckduckgo/content-scope-scripts` folder.

If only the package version has changed, there is no need to run the
tests.

If tests have failed, see
https://app.asana.com/0/1202561462274611/1203986899650836/f for further
information on what to do next.

_`content-scope-scripts` folder update_
- [ ] All tests must pass
- [ ] Privacy tests must pass

_Only `content-scope-scripts` package update_
- [x] All tests must pass
- [x] Privacy tests do not need to run

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates `@duckduckgo/content-scope-scripts` from `12.8.0` to `12.9.0`
in `package.json` and `package-lock.json`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d15530c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: daxmobile <daxmobile@users.noreply.github.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1211755763011422?focus=true

### Description

- This is no longer needed since Duck.ai is currently tied to the
`BrowserActivity` using `DuckChatWebViewFragment`

### Steps to test this PR

- [ ] Open Duck.ai
- [ ] Verify that it is launched correctly

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Deletes the standalone DuckChatWebViewActivity and shifts
opening/closing Duck.ai to BrowserNav with updated session handling;
cleans up manifest and tests.
> 
> - **DuckChat flow**:
> - Remove `DuckChatWebViewActivity` and
`DuckChatWebViewActivityViewModel` (and related tests).
> - In `RealDuckChat`, drop `keepSession` and standalone activity path;
always use `BrowserNav.openDuckChat/closeDuckChat`.
> - Adjust session logic: `hasSessionActive` now based on
`hasActiveSession()` unless `forceNewSession`.
> - Remove `DuckChatWebViewActivityWithParams` usage and
`startDuckChatActivity` helper.
> - **Manifest**:
> - Delete `com.duckduckgo.duckchat.impl.ui.DuckChatWebViewActivity`
entry.
> - **Tests**:
> - Update `RealDuckChatTest` to assert `BrowserNav` intents and
active-session behavior; remove obsolete WebView activity tests.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6957e7a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207908166761516/task/1212319857962708?focus=true

  ### Description
Remove all onboarding design experiment code (Buck and BB variants).
This cleanup removes ~10,500 lines of dead code including:
  - Experiment manager classes and helpers
  - BB/Buck layout variants and drawables
  - Experiment-specific Lottie animations and fonts
  - Related test files
  - Lint baseline entries for removed files

  ### Steps to test this PR

  _Onboarding Flow_
  - [x] Fresh install app and complete full onboarding flow
- [x] Fresh install app and complete full onboarding flow dismissing
dialogs

  _Regression_
- [ ] Run Maestro tests in `.maestro/onboarding/` and
`.maestro/preonboarding/`
  - [x] Verify no visual regressions in browser tab UI

  ### UI changes
  No UI changes - removes unused experiment code only.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Remove onboarding design experiment references and tests, and
normalize a related raw JSON resource.
> 
> - **Onboarding/CTA**:
> - Remove references to `OnboardingDesignExperimentManager` from
`CtaTest`, `OnboardingDaxDialogTests`, and `WelcomePageViewModelTest`.
> - Adjust constructors/usages to no longer require experiment manager;
update expectations accordingly.
> - **Tests**:
> - Delete experiment-related test suites:
`OnboardingDesignExperimentManagerTest.kt`,
`OnboardingDesignExperimentCountDataStoreTest.kt`, and
`OnboardingExperimentFireAnimationHelperTest.kt`.
> - **Resources**:
> - Normalize `app/src/main/res/raw/ob_4_popup.json` content (compact
JSON formatting).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a5d8636. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1212319857962711?focus=true

### Description

Remove the strings associated with the onboarding experiment 

### Steps to test this PR

- [ ] Check strings removed
- [ ] Build and run project

### UI changes
N/A

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Removes legacy BB/Buck onboarding experiment strings from strings.xml
across all locales.
> 
> - **Resources (i18n)**:
> - Remove BB/Buck onboarding experiment strings (e.g.,
`onboardingBubbleExperimentSearchDaxDialogDescription`,
`highlightsPreOnboardingDaxDialog*`, `bbOnboarding*`
titles/descriptions/plurals) from `app/src/main/res/values*/strings.xml`
(default and multiple locale folders).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4985b4e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Dax The Translator <daxmobile@duckduckgo.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/608920331025315/task/1212317879744549?focus=true

### Description
Follow-up to #7181 to move
pixel sending logic inside `AtbInitializer` instead of having a separate
class for it.

### Steps to test this PR

Add logcat filter: `message~:"Waiting for referrer|Initializing
ATB|Variants update|Initialized ATB|ull referrer stri|Result
determined|for referrer|posting initial|WebView passkey support|wv|timed
out|AtbInitializer|Pixel interceptor:
.*atb_pre_initializer_plugin_timeout|Pixel interceptor:
.*timeout_atb_pre_initializer_plugin|interceptor.*timeout_waiting_for_referrer"`

#### Happy path
- [x] Fresh install `playDebug` variant and launch the app
- [x] Verify you see logs for:
```
AtbInitializer: About to initialize ATB; running 3 pre ATB initialization plugins
AtbInitializer: Running pre-ATB init plugin [ReinstallAtbListener]
AtbInitializer: Running pre-ATB init plugin [AuraExperimentManager]
AtbInitializer: Running pre-ATB init plugin [PlayStoreAppReferrerStateListener]
```


#### Force timeout in pre-ATB-init plugin

- [x] Apply patch from [Patch: pre-ATB init plugin
timeout](https://app.asana.com/1/137249556945/task/1212197533093320?focus=true)
- [x] Fresh install and launch app
- [x] Verify you see pixel in logs for
`timeout_atb_pre_initializer_plugin` with param
`plugin=ReinstallAtbListener`


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Moves ATB pre-initializer timeout pixel firing into `AtbInitializer`,
removes `AtbInitializationPluginPixelSender`, updates DI and tests, and
registers pixel param removal plugin with `StatisticsPixelName`.
> 
> - **Statistics**:
> - Inlines pixel firing on pre-ATB init plugin timeout inside
`AtbInitializer.onPluginTimeout`, using `Pixel.fire` and error log.
> - Removes `AtbInitializationPluginPixelSender` and its implementation.
> - Adds `AtbInitializerPluginPixelParamRemovalPlugin` in
`StatisticsPixelName` to strip ATB param for
`timeout_atb_pre_initializer_plugin`.
> - **DI**:
> - Updates constructor and providers to inject `Pixel` into
`AtbInitializer` (replacing `AtbInitializationPluginPixelSender`) in
`StubStatisticsModule.kt`.
> - **Tests**:
> - Adjusts `AtbInitializerTest` to verify `Pixel.fire` for timeout and
not-called cases; retains existing ATB initialization behavior checks.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
977da29. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Craig Russell <1336281+CDRussell@users.noreply.github.com>
…ort inbox (#7332)

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

### Description
Clean up kill switch useSubscriptionSupport and removed all legacy
support inbox + email support

### Steps to test this PR

- [x] Install develop branch
- [x] Obtain a subscription
- [x] Go to Settings > Subscription Settings > Send feedback
- [x] Choose “Report a problem"
- [x] Choose any category and subcategory
- [x] Verify that you see the Contact Support Link and it opens the
support website
- [x] Install from this branch
- [x] Attempt to report a problem from Subscription Settings
- [x] Verify that you see the Contact Support Link and it opens the
support website
- [x] Attempt to report a problem from VPN > Send feedback
- [x] Verify that you see the Contact Support Link and it opens the
support website
- [x] Attempt to report a problem from Settings > Send feedback >
Subscription
- [x] Verify that you see the Contact Support Link and it opens the
support website


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Removes the subscription support inbox and email-based feedback,
always shows the Contact Support link, and simplifies feedback
submission to only send pixels with corresponding API, UI, strings, and
tests cleaned up.
> 
> - **Feedback UX/UI**:
> - Remove email input from `content_feedback_submit.xml` and related
logic; `SubscriptionFeedbackSubmitFragment.Listener.onUserSubmit` now
accepts only `description`.
> - Always show "Contact Support" link on problem reports; remove
conditional toggle usage.
> - Drop failure toast/handling; only success toast remains in
`SubscriptionFeedbackActivity`.
> - **ViewModel/Logic**:
> - `SubscriptionFeedbackViewModel` no longer sends feedback to a
support inbox; it only emits pixels and `FeedbackCompleted`.
> - Remove `FeedbackFailed` command and all email/support-inbox related
code and wiring.
> - **API/Services**:
>   - Delete `SubscriptionSupportInbox` implementation and test fake.
> - Remove `SubscriptionsService.feedback(...)`, `FeedbackBody`, and
`FeedbackResponse` models.
> - **Feature Flags**:
>   - Remove `useSubscriptionSupport` toggle from `PrivacyProFeature`.
> - **Resources/Localization**:
> - Delete email-related and failure strings across all locales;
keep/ensure "Contact Support" copy.
> - **Tests**:
> - Update `SubscriptionFeedbackViewModelTest` to reflect pixel-only
submission and completed command; remove inbox-dependent tests.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3dd60a1. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1205648422731273/task/1212344118527513?focus=true

### Description

This PR instruments restore subscription operation with a new wide
event.

### Steps to test this PR

Prerequisites
- Apply patch from
https://app.asana.com/1/137249556945/project/1209991789468715/task/1210448620621729?focus=true
- Clean install

#### Successful restore using Google Play
- [x] Purchase a test subscription
- [x] Remove subscription from device
- [x] Go to app settings -> I have a subscription -> google play
- [x] Verify in logcat that `wide_subscription-restore` event has been
sent with `status=SUCCESS` and `restore_platform=google_play`

#### Successful restore using email address
- [x] Purchase a test subscription
- [x] Ensure an email address is linked to the subscription
- [x] Remove subscription from device
- [x] Go to app settings -> I have a subscription -> email
- [x] Proceed with the restore flow until success page is shown
- [x] Verify in logcat that `wide_subscription-restore` event has been
sent with `status=SUCCESS` and `restore_platform=email_address`

#### Unsuccessful restore using Google Play
- [x] Cancel any active subscription, wait for it to expire and remove
from device.
- [x] Go to app settings -> I have a subscription -> google play
- [x] Verify in logcat that `wide_subscription-restore` event has been
sent with `status=FAILURE` and `restore_platform=google_play`

#### Unsuccessful restore using email address
- [x] Go to app settings -> I have a subscription -> email
- [x] Close the app, kill the app process.
- [x] Launch the app
- [ ] Verify in logcat that `wide_subscription-restore` event has been
sent with `status=FAILURE` and `restore_platform=email_address`

#### Successful restore using Google Play when attempting to purchase
new subscription
- [x] Purchase a test subscription
- [x] Remove subscription from device
- [x] Attempt to purchase new subscription
- [x] Verify in logcat that `wide_subscription-restore` event has been
sent with `status=SUCCESS` and `restore_platform=google_play` and
`is_purchase_attempt=true`

#### Unsuccessful restore using Google Play when attempting to purchase
new subscription
- [x] Cancel any active subscription, wait for it to expire and remove
from device.
- [x] Purchase new subscription
- [x] Verify in logcat that `wide_subscription-restore` event has been
sent with `status=FAILURE` and `restore_platform=google_play` and
`is_purchase_attempt=true`

### No UI changes

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Instruments the subscription restore flow (Google Play/email) with a
new wide event, integrates it in manager and UI, and adds tests and
pixel definitions.
> 
> - **Wide Event & Pixels**
> - Add `PixelDefinitions/pixels/wide_subscription_restore.json5`
defining `subscription-restore` wide pixel with `restore_platform`,
`is_purchase_attempt`, `restore_latency_ms_bucketed`, failure reason,
and email-step markers.
> - Implement `SubscriptionRestoreWideEvent`
(`SubscriptionRestoreWideEventImpl`) to start/finish flows, record
latency, and report success/failure.
> - **Backend Integration**
> - Wire `SubscriptionRestoreWideEvent` into `RealSubscriptionsManager`
to track restore during purchase attempts; add helper
`recoverSubscriptionFromStoreOnPurchaseAttempt`.
> - Improve store login failure message in
`recoverSubscriptionFromStore` and add feature flag
`sendSubscriptionRestoreWideEvent()` to `PrivacyProFeature`.
> - **UI Integration**
> - Update `RestoreSubscriptionViewModel` to emit wide events on
store/email restore start and on success/failure.
> - **Tests**
> - Add `SubscriptionRestoreWideEventTest` covering flow
start/success/failure, interval handling, caching, and feature toggle.
> - Update `RealSubscriptionsManagerTest` and
`RestoreSubscriptionViewModelTest` to inject and verify new wide event
behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1cbf653. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1212347629297471?focus=true

### Description

- Fixes an issue where mic permissions were not handled correctly when
requested by site and app permissions were set to “Ask every time” or
“Don’t allow”.

### Steps to test this PR

- [ ] Testing steps in task



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a toggleable check that only grants site microphone access for
`duck.ai`/`duckduckgo.com` when Android `RECORD_AUDIO` and
`MODIFY_AUDIO_SETTINGS` are granted, with wiring and tests updated.
> 
> - **Site permissions logic**:
> - Feature-gate mic permission handling via
`MicrophoneSitePermissionsDomainRecoveryFeature` (default enabled).
> - For `RESOURCE_AUDIO_CAPTURE` on `duck.ai`/`duckduckgo.com`,
auto-accept only if Android `RECORD_AUDIO` and `MODIFY_AUDIO_SETTINGS`
are granted; otherwise exclude from auto-accept.
> - Inject `Context` and use `ContextCompat.checkSelfPermission`; add
`AUDIO_CAPTURE_PERMISSION_DOMAINS` list.
> - **Feature toggle**:
> - New remote feature interface
`MicrophoneSitePermissionsDomainRecoveryFeature` contributed to
`AppScope` with default `TRUE`.
> - **Tests**:
> - Update `SitePermissionsManagerTest` to inject `Context` and fake
toggle; default toggle set to disabled in tests; constructor adjusted
accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fd2bd04. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/0/488551667048375/1212377286441500/f

 ----- 
- Automated content scope scripts dependency update

This PR updates the content scope scripts dependency to the latest
available version and copies the necessary files.

Tests will only run if something has changed in the
`node_modules/@duckduckgo/content-scope-scripts` folder.

If only the package version has changed, there is no need to run the
tests.

If tests have failed, see
https://app.asana.com/0/1202561462274611/1203986899650836/f for further
information on what to do next.

_`content-scope-scripts` folder update_
- [ ] All tests must pass
- [ ] Privacy tests must pass

_Only `content-scope-scripts` package update_
- [x] All tests must pass
- [x] Privacy tests do not need to run

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates content-scope-scripts to 12.10.0 and refreshes lockfile
(including @types/node to 25.0.0).
> 
> - **Dependencies**:
> - Bump `@duckduckgo/content-scope-scripts` from `12.9.0` to `12.10.0`
in `package.json` and lockfile.
> - Update lockfile resolution hash for
`@duckduckgo/content-scope-scripts`.
>   - Bump `@types/node` from `24.10.2` to `25.0.0` in lockfile.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
279b73d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: daxmobile <daxmobile@users.noreply.github.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1210594645151737/task/1212389758584564?focus=true

### Description
Fixes the pre-onboarding maestro test to account for an additional step

### Steps to test this PR
Run `maestro test
.maestro/onboarding/onboarding_dismiss_all_dialogs.yaml`

### UI changes
No UI changes

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates the pre-onboarding Maestro test to handle an additional AI
chat step in the onboarding flow.
> 
> - **E2E Tests**:
>   - Update `/.maestro/shared/pre_onboarding.yaml`:
> - Add `tapOn: "next"` and `assertVisible` for `".*want easy access to
private AI chat?.*"` to cover new onboarding step.
>     - Ensure flow continues to final `".*Try a search!.*"` screen.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f153631. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1203581873609357/task/1212381653445207?focus=true

### Description
Adds missing unit tests for the core PIR classes.

### Steps to test this PR
Ensure the unit tests pass

### UI changes
No UI changes

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Add comprehensive unit tests across PIR core components and fix zip
extraction to create parent directories before writing files.
> 
> - **Tests**:
> - Add extensive unit tests for `RealBrokerDataDownloader`,
`RealBrokerStepsParser`, `RealCaptchaResolver`,
`RealNativeBrokerActionHandler`, `RealPirActionsRunner`,
`RealPirActionsRunnerStateEngine`, `RealPirEmailConfirmationJobsRunner`,
and `RealPirEmailConfirmation` covering success/edge/error paths and
event/side-effect flows.
> - **Bug Fix**:
> - In `brokers/BrokerDataDownloader.extractJsonFilesFromResponse`,
ensure `outputFile.parentFile?.mkdirs()` is called before writing files
from the ZIP to handle nested paths.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
bf7bd77. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1203581873609357/task/1212381653445208?focus=true

### Description
Adds missing unit tests for the JS event handlers.

### Steps to test this PR
Ensure the unit tests pass

### UI changes
No UI changes

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds extensive unit tests covering PIR JS event handlers (state
transitions, side effects, pixels, retries) and fixes a handler class
name; also simplifies retry decision logic.
> 
> - **Tests (new, extensive)**:
> - `BrokerActionFailedEventHandlerTest`: verifies retry limits,
expectation-only retries for scans, failure pixel emission.
> - `BrokerStepCompletedEventHandlerTest`: validates success/failure
outcomes, email confirmation flow, stage timing, and state resets.
> - `CaptchaInfoReceivedEventHandlerTest`: asserts transaction ID
handling, next-action progression, and pixel emission for opt-out.
> - `EmailReceivedEventHandlerTest`: ensures email propagation to
`ExtractedProfile`, generated email state, pixel emission, and next
action.
> - `ErrorReceivedHandlerTest`: maps various errors to
`BrokerActionFailed` with no retry; state remains unchanged.
> - `ExecuteBrokerStepActionEventHandlerTest`: covers side effects
(`PushJsAction`, `LoadUrl`, captcha/email flows), delays, pixels, and
data sourcing.
> - `ExecuteNextBrokerStepEventHandlerTest`: starts next broker step,
emits start pixels, resets indices, completes execution when done.
> - `LoadUrlCompleteEventHandlerTest` / `LoadUrlFailedEventHandlerTest`:
handle initial/recovery URLs, advance/abort flows, and retries.
> - `RetryAwaitCaptchaSolutionEventHandlerTest` /
`RetryGetCaptchaSolutionEventHandlerTest`: increment attempts and
re-dispatch side effects.
> - `StartedEventHandlerTest`: initializes attempt ID and kicks off
initial URL load.
> - **Minor fixes**:
> - Rename `CaptchaInforReceivedEventHandler` to
`CaptchaInfoReceivedEventHandler`.
> - Simplify `shouldRetryFailedAction` with an expression `return` while
preserving behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
55bc3fd. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1203581873609357/task/1212381653445209?focus=true

### Description
Adds missing unit tests for the remaining PIR classes.

### Steps to test this PR
Ensure the unit tests pass

### UI changes
No UI changes

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Add comprehensive unit tests across PIR utils, pixels, scan scheduler,
JS action processor, and auth interceptor.
> 
> - **Tests**:
> - **Common**: `PirUtilsTest` for `splitIntoParts`,
`ExtractedProfile.toParams`, parent profile matching, and profile
`matches` logic.
>   - **Pixels**:
> - `PirPixelInterceptorTest`: ensures `metadata` is appended only to
`pir_internal_*` pixels with correct Base64-encoded fields and preserves
existing params.
> - `RealPirPixelSenderTest`: verifies pixels fired with expected
parameters for scans, opt-outs, email confirmation, errors, stats, and
dashboard events.
> - **Scan**: `RealPirScanSchedulerTest` validates scheduling/canceling
of `PirScheduledScanRemoteWorker`, `PirEmailConfirmationRemoteWorker`,
`PirCustomStatsWorker`, event logging, and ordering.
> - **Scripts**: `RealBrokerActionProcessorTest` checks JS messaging
registration, action dispatch, and success/error callback parsing.
> - **Service**: `PirAuthInterceptorTest` confirms Authorization header
injection for `@PirAuthRequired`, null-token error, and pass-through
otherwise.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
937e282. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207418217763355/task/1212237599845918?focus=true

### Description

This PR adds a new `FireDataStore`, which allows to store automatic and
manual data-clearing options. There is a new `FireClearOption` enum that
has 3 options: `TABS`, `DATA` and `DUCKAI_CHATS`.

### Steps to test this PR

- [ ] Make sure the unit tests pass

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a DataStore-backed FireDataStore to manage manual and automatic
clear options (incl. when), a new FireClearOption enum, DI module, and
unit tests with legacy settings migration.
> 
> - **Fire clearing storage**:
> - Add `FireDataStore` interface and `SharedPreferencesFireDataStore`
implementation backed by `DataStore<Preferences>`.
> - Manage separate option sets for `manual` and `automatic` clearing:
flows, getters, setters, add/remove, and selection checks.
> - Persist "when to clear" via `getAutomaticallyClearWhenOption*` with
migration from legacy `SettingsDataStore` (`ClearWhatOption`,
`ClearWhenOption`).
> - Parse/validate persisted enums; default manual options to `TABS` +
`DATA` and fallback to legacy for automatic.
> - **DI/Module**:
> - Provide qualified `@FireData` `DataStore` via `FireDataStoreModule`
using `preferencesDataStore` (`fire_clearing_preferences`).
> - **Models**:
>   - Introduce `FireClearOption` enum: `TABS`, `DATA`, `DUCKAI_CHATS`.
> - **Tests**:
> - Add comprehensive unit tests covering flows, add/remove,
independence of manual vs automatic sets, and legacy migration for both
"what" and "when".
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b4a869f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/1/137249556945/project/1207418217763355/task/1212237610087258?focus=true

### Description

This PR just adds a new feature flag that will be used in subsequent
PRs.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds `moreGranularDataClearingOptions` feature flag (default false) to
`AndroidBrowserConfigFeature` for fire dialog/data clearing options.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
717cf32. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… new step end-to-end-robintest workflow (#7322)

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

### Description
Added a new navigation test to verify that the app correctly handles
duck:// schema links to the search engine results page (SERP) with a
search query. The test ensures that when a user clicks a `duck://` link
with a search query parameter, the app properly opens and displays the
search query in the omnibar.

This test was added as a separate step in the End-to-End tests (Robin)
workflow.

### Steps to test this PR

_Deeplink Functionality_
- [x] Run the deeplink_to_serp_with_query.yaml test both locally and on
the maestro cloud

Test run:
https://app.maestro.dev/project/proj_01htg54rdtfwx8rgbzv03cxkpf/maestro-test/flow/run_01kc1jpy6ve1m9ykcg2whrnbzb

### UI changes
No UI changes, only additional test coverage.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a Maestro flow to validate duck:// SERP query handling and runs
it in the end-to-end Robin workflow via the navigationTest tag.
> 
> - **Tests**:
> - Add `.maestro/deeplink/deeplink_to_serp_with_query.yaml` to validate
`duck://` SERP link opens with the query shown in `omnibarTextInput`
(with retries, clean launch, and onboarding skipped).
> - **CI**:
> - Update `.github/workflows/end-to-end-robintest.yml` to include a new
"Deeplink tests" Maestro Cloud step running `include-tags:
navigationTest`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
35bce88. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…7331)

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

### Description

We want to remove index parameter in the existing pixels
 `m_autocomplete_click_phrase` and `m_autocomplete_click_website`

Revert commit 4fdeb94 that introduce
this specific parameter.

### Steps to test this PR

- [x] Open the app, focus on the omnibar and type in a query.
- [x] Verify that clicking on a search suggestion sends an
`m_autocomplete_click_phrase` pixel without `search_suggestion_index`
parameter.
- [x] Verify that clicking on a website search suggestion sends an
`m_autocomplete_click_website` pixel without `search_suggestion_index`
parameter.
Task/Issue URL:
https://app.asana.com/1/137249556945/project/715106103902962/task/1211782086400063?focus=true

### Description

When you are using the omnibar in bottom position, the margin between
the omnibar and the bottom of the screen should be defined at 8dp, and
not at 4dp.


### Steps to test this PR

_Checking top margin with bottom bar_
- [x] Start the application
- [x] Go to Settings -> Appearance -> Select bottom bar
- [x] Come back to the browser screen 
- [x] Check the top margin is bigger now than before

_Checking bottom margin with top bar_
- [x] Start the application
- [x] Go to Settings -> Appearance -> Select top bar
- [x] Come back to the browser screen 
- [x] Check the top margin is bigger now than before

_Checking bottom margin with split bar_
- [x] Start the application
- [x] Go to Settings -> Appearance -> Select split bar
- [x] Come back to the browser screen 
- [x] Check the top margin is bigger now than before

_Checking omnibar usage outside browser screen_
- [x] Start the application
- [x] Go to Duck.ai screen
- [x] Check the omnibar has the same size than the browser omnibar
without breaking UI

_Checking native toolbar_
- [ ] Start the application
- [x] Open bookmarks screen
- [ ] Check the toolbar has the same size than the browser omnibar
without breaking UI

### UI changes

| Before  | After |
| ------ | ----- |
<img width="1080" height="257" alt="image"
src="https://github.com/user-attachments/assets/af6ee473-cc75-45ac-8433-bc5f6184d654"
/> | <img width="1080" height="269" alt="image"
src="https://github.com/user-attachments/assets/12309956-a48f-4ff6-96d4-f60c59ba79db"
/>
<img width="1080" height="240" alt="image"
src="https://github.com/user-attachments/assets/17f0e58d-050a-4016-a42c-312faa25cae9"
/> | <img width="1080" height="247" alt="image"
src="https://github.com/user-attachments/assets/a16a2248-17f2-4fe6-bf0e-599b0b7fd8a7"
/>
<img width="1080" height="251" alt="image"
src="https://github.com/user-attachments/assets/6e72613f-cea4-41e9-8e79-7018005d4ac1"
/> | <img width="1080" height="258" alt="image"
src="https://github.com/user-attachments/assets/3c49fef3-89c1-42d0-9139-4879ab825625"
/>
<img width="1080" height="249" alt="image"
src="https://github.com/user-attachments/assets/759be51f-e0b0-452b-934d-208f1e678852"
/> | <img width="1080" height="249" alt="image"
src="https://github.com/user-attachments/assets/e53fce70-2403-446d-86a5-711fec78988f"
/>
<img width="1080" height="258" alt="image"
src="https://github.com/user-attachments/assets/dab07a4b-225b-4449-9cfe-b82f6e6c9412"
/> | <img width="1080" height="252" alt="image"
src="https://github.com/user-attachments/assets/be6bbbe0-7e85-41aa-8d39-d2618c96271f"
/>
<img width="1080" height="238" alt="image"
src="https://github.com/user-attachments/assets/a142f2f2-3333-4964-a8b3-8266a2d41068"
/> | <img width="1080" height="253" alt="image"
src="https://github.com/user-attachments/assets/b5fcc2b2-24c8-4a73-973b-90a887433f54"
/>
<img width="1080" height="353" alt="image"
src="https://github.com/user-attachments/assets/2b7d7fc6-81cf-4437-a278-43593195aaed"
/> | <img width="1080" height="362" alt="image"
src="https://github.com/user-attachments/assets/6d04aa57-1ece-44e5-9dd2-99976b922791"
/>
<img width="1080" height="377" alt="image"
src="https://github.com/user-attachments/assets/88d92a14-4d1a-4d92-8f49-2292b59f7a63"
/> | <img width="1080" height="385" alt="image"
src="https://github.com/user-attachments/assets/4433092d-01d8-4d26-8715-c77e9f8cd4f0"
/>
<img width="1080" height="352" alt="image"
src="https://github.com/user-attachments/assets/31927a20-2c29-479e-82e6-ad2fc30f20b3"
/> | <img width="1080" height="361" alt="image"
src="https://github.com/user-attachments/assets/19eb926b-725c-46f9-b94e-742ba3ed6906"
/>
<img width="1080" height="259" alt="image"
src="https://github.com/user-attachments/assets/3111f43d-ca8f-4e14-9f31-f6d1227ffdb7"
/> | <img width="1080" height="261" alt="image"
src="https://github.com/user-attachments/assets/3881a18a-fe98-4549-9ff9-86d3d0dc016a"
/>
<img width="1080" height="258" alt="image"
src="https://github.com/user-attachments/assets/ccfbf67e-d511-4e34-a045-4b6c3e8d9590"
/> | <img width="1080" height="254" alt="image"
src="https://github.com/user-attachments/assets/c5060b32-bb62-4dba-97fe-5d385d9d7172"
/>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1212086611627295?focus=true

### Description
Migrate site-permissions to DatabaseProvider

### Steps to test this PR

_Feature 1_
- [x] Smoke test site permissions

### UI changes
| Before  | After |
| ------ | ----- |
!(Upload before screenshot)|(Upload after screenshot)|

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Replaces direct Room setup with DatabaseProvider-based initialization
and updates migrations list; adds data-store-api dependency.
> 
> - **Site Permissions Impl**:
> - **DI**: Replace `Room.databaseBuilder` with
`DatabaseProvider.buildRoomDatabase` using `RoomDatabaseConfig` and
`ALL_MIGRATIONS`.
>   - **Build**: Add dependency on `:data-store-api` in `build.gradle`.
> - **Store**:
> - Change `ALL_MIGRATIONS` from array to `listOf(...)` to align with
new provider API.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
529b6f8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1212390044385514?focus=true

### Description
Marks the flag InternalAlwaysEnabled

### Steps to test this PR
QA-optional

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Change `pirBeta` feature toggle default from `FALSE` to `INTERNAL` in
`PirRemoteFeatures`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
dffefa4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Task/Issue URL:
https://app.asana.com/0/488551667048375/1212400157764298/f

 ----- 
- Automated content scope scripts dependency update

This PR updates the content scope scripts dependency to the latest
available version and copies the necessary files.

Tests will only run if something has changed in the
`node_modules/@duckduckgo/content-scope-scripts` folder.

If only the package version has changed, there is no need to run the
tests.

If tests have failed, see
https://app.asana.com/0/1202561462274611/1203986899650836/f for further
information on what to do next.

_`content-scope-scripts` folder update_
- [x] All tests must pass
- [x] Privacy tests must pass

_Only `content-scope-scripts` package update_
- [ ] All tests must pass
- [ ] Privacy tests do not need to run

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates @duckduckgo/content-scope-scripts to 12.12.0 and syncs built
assets, adding Firefox features and a shared messaging transport.
> 
> - **Dependencies**:
> - Bump `@duckduckgo/content-scope-scripts` to `12.12.0` in
`package.json`.
> - **Content-scope-scripts build updates (android bundles)**:
> - Firefox feature set now includes `webInterferenceDetection` and
`breakageReporting` in `adsjsContentScope.js`, `autofillImport.js`,
`brokerProtection.js`, `contentScope.js`.
> - Messaging: switch to a shared `SendMessageMessagingTransport` via
`getSharedMessagingTransport()`.
> - Minor robustness/comment tweaks: guarded Web Share shim,
`screenLockFix` descriptor note, WeakSet for DOM refs, event handler
pattern docs.
> - **Docs**:
> - In `README.md`, replace "NPM commands" section with a "Contributing"
section linking to `CONTRIBUTING.md`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f5dc90d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: daxmobile <daxmobile@users.noreply.github.com>
Task/Issue URL:
https://app.asana.com/1/137249556945/project/488551667048375/task/1212392784625805?focus=true

### Description
Fixed the link for duck ai help center in the feedback flow

### Steps to test this PR
QA-Optional
Video:
https://app.asana.com/app/asana/-/get_asset?asset_id=1212401965736899

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates the Duck AI subscriber-only help URL constant in
FeedbackHelpUrlProvider.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
cc0716f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.