Skip to content

WIP Bugfix FXIOS-15339 [Tab management] Tab closed crashes when media presentations is present#33032

Draft
lmarceau wants to merge 3 commits intomainfrom
lm/bug-new-tab-2
Draft

WIP Bugfix FXIOS-15339 [Tab management] Tab closed crashes when media presentations is present#33032
lmarceau wants to merge 3 commits intomainfrom
lm/bug-new-tab-2

Conversation

@lmarceau
Copy link
Copy Markdown
Contributor

@lmarceau lmarceau commented Apr 10, 2026

📜 Tickets

Jira ticket
Github issue

💡 Description

⚠️ This is a WIP
We need to await the media to be closed before closing the tab. I am using async/await to do that here, since I believe this is the general direction we want to move towards in the future with all related to tabs. I need to create some follow-up ticket for this work (see comments), otherwise the PR was getting too big. I'll do that at the end before merging and adjust the ticket numbers in comment.

📝 Checklist

  • I filled in the ticket numbers and a description of my work
  • I updated the PR name to follow our PR naming guidelines
  • I ensured unit tests pass and wrote tests for new code
  • If working on UI, I checked and implemented accessibility (Dynamic Text and VoiceOver)
  • If adding telemetry, I read the data stewardship requirements and will request a data review
  • If adding or modifying strings, I read the guidelines and will request a string review from l10n
  • If needed, I updated documentation and added comments to complex code

@lmarceau lmarceau requested review from Cramsden and yoanarios April 10, 2026 19:15
store.dispatch(action)
}

// TODO: FXIOS-TODO - Make closeAllPrivateTabs async
Copy link
Copy Markdown
Contributor Author

@lmarceau lmarceau Apr 10, 2026

Choose a reason for hiding this comment

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

Need to create a ticket once this PR is approved. I think closeAllPrivateTabs should be async and the Task introduced at a higher level

copyURL(tabID: tabUUID, uuid: action.windowUUID)

case TabPeekActionType.closeTab:
// TODO: verify if this works for closing a tab from an unselected tab panel
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed the todo since this is working since a long time, and there's no ticket number

func performCloseAction(for tab: Tab) {
guard !isDragging else { return }

// TODO: FXIOS-TODO - Why do we call get tabs here, can we remove it
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Need to create a ticket for this, I don't understand what this _ = getTabs() is doing, and I am wondering if we can just remove it. Might be a side-effect needed for something else? Who knows. But having a separate task for this makes more sense than trying to bundle it here

tabsPanelTelemetry.tabClosed(mode: tab.isPrivate ? .private : .normal)
tabManager.removeTab(tab.tabUUID)

// TODO: FXIOS-TODO Make performCloseAction async
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Need to create a ticket once this PR is approved. I think performCloseAction should be async and the Task introduced at a higher level

url = currentlyOpenUrl
close()

// TODO: FXIOS-TODO Make clearAndResetTabHistory async
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Need to create a ticket once this PR is approved. I think clearAndResetTabHistory should be async and the Task introduced at a higher level

Comment on lines +610 to 613
func close() async {
await webView?.pauseAllMediaPlayback()
await webView?.closeAllMediaPresentations()
webView?.stopLoading()
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the fix for the bug. We need to await that media are closed before deiniting the tab. A completion handler version is also available, but as I said in the description I think we should move towards async/await instead. Let me know what you think


/// Remove tab option using tabUUID.
/// - Parameter tabUUID: UUID from the tab
func removeTab(_ tabUUID: TabUUID)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Basically anything that wants to remove a tab in the tab manager will be async now

@lmarceau lmarceau marked this pull request as ready for review April 10, 2026 19:28
@lmarceau lmarceau requested a review from a team as a code owner April 10, 2026 19:28
@mobiletest-ci-bot
Copy link
Copy Markdown

Warnings
⚠️ Detected tab related changes in: firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+WebViewDelegates.swift, firefox-ios/Client/TabManagement/Tab.swift, firefox-ios/Client/TabManagement/TabManager.swift, firefox-ios/Client/TabManagement/TabManagerImplementation.swift (cc @lmarceau)
Messages
📖 Project coverage: 41.0%

💪 Quality guardian

2 tests files modified. You're a champion of test coverage! 🚀

🥇 Perfect PR size

Smaller PRs are easier to review. Thanks for making life easy for reviewers! ✨

🙌 Friday high-five

Thanks for pushing us across the finish line this week! 🙌

💬 Description craftsman

Great PR description! Reviewers salute you 🫡

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+KeyCommands.swift at line 171.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+ToolBarActionMenuDelegate.swift at line 287.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+WebViewDelegates.swift at line 655.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

🦊 BrowserViewController Check

We’re tracking the size of BrowserViewController.swift to keep it healthy.

  • ✨ Change in file size: +4 lines

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift at line 3495.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift at line 126.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift at line 227.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift at line 243.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift at line 249.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/Frontend/Browser/TopTabDisplayManager.swift at line 346.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/TabManagement/Tab.swift at line 605.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

🧑‍💻 New Task {} detected

New Task {} added in file firefox-ios/Client/TabManagement/TabManagerImplementation.swift at line 881.
Please add a concurrency reviewer on your PR: @Cramsden @ih-codes @lmarceau

✅ New file code coverage

No new file detected so code coverage gate wasn't ran.

Client.app: Coverage: 39.4

File Coverage
BrowserViewController.swift 34.45% ⚠️
TabManagerMiddleware.swift 35.93% ⚠️
BrowserViewController+KeyCommands.swift 3.08% ⚠️
ApplicationHelper.swift 0.0% ⚠️
BrowserViewController+ToolBarActionMenuDelegate.swift 5.93% ⚠️
TopTabDisplayManager.swift 14.71% ⚠️
BrowserViewController+WebViewDelegates.swift 19.71% ⚠️
Tab.swift 66.54%
TabManager.swift 100.0%
TabManagerImplementation.swift 56.4%

Generated by 🚫 Danger Swift against a6958d5

Copy link
Copy Markdown
Contributor

@yoanarios yoanarios left a comment

Choose a reason for hiding this comment

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

Code looks good mostly with a couple of questions, I'm going to test and run instruments to check performance

self.tabsPanelTelemetry.tabClosed(mode: currentTab.isPrivate ? .private : .normal)
self.tabManager.removeTab(currentTab.tabUUID)
Task {
// Laurie
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.

Clean up comment 😄

// Make sure to wipe the private tabs if the user has the pref turned on and there are private tabs to remove
if shouldClearPrivateTabs(), !tab.isPrivate && !privateTabs.isEmpty {
removeAllPrivateTabs()
Task {
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.

I'm not a master of async-await yey but I think this change might introduced a problem since removeAllPrivateTabs updates tabs internally and after the call we are using tabs for the index and other actions, what do you think?

tabManager.removeTab(tab.tabUUID)

// TODO: FXIOS-TODO Make performCloseAction async
Task {
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.

async-await question here we use Task { versus Task { @MainActor because the function is marked as MainActor and should inherit the context?

webView?.pauseAllMediaPlayback {}
webView?.closeAllMediaPresentations {}
func close() async {
await webView?.pauseAllMediaPlayback()
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.

this is what originates most of the changes I guess?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah exactly!

@lmarceau
Copy link
Copy Markdown
Contributor Author

Following latest conversations with Carson and Yoana, this needs some work. We'll try some other methods instead. Changes to come soon 🤞

@lmarceau lmarceau marked this pull request as draft April 15, 2026 22:33
@lmarceau lmarceau changed the title Bugfix FXIOS-15339 [Tab management] Tab closed crashes when media presentations is present WIP Bugfix FXIOS-15339 [Tab management] Tab closed crashes when media presentations is present Apr 15, 2026
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