diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 97fb25474..250eaa7da 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -622,7 +622,8 @@ class HomeFragment : Fragment() { dialog.cancel() } setPositiveButton(R.string.tab_collection_dialog_positive) { dialog: DialogInterface, _ -> - viewLifecycleOwner.lifecycleScope.launch(IO) { + // Use fragment's lifecycle; the view may be gone by the time dialog is interacted with. + lifecycleScope.launch(IO) { context.components.core.tabCollectionStorage.removeCollection(tabCollection) context.components.analytics.metrics.track(Event.CollectionRemoved) }.invokeOnCompletion { diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt index 18c19943e..f976a39fa 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt @@ -365,7 +365,8 @@ class BookmarkFragment : LibraryPageFragment(), UserInteractionHan pendingBookmarkDeletionJob = getDeleteOperation(Event.RemoveBookmarkFolder) dialog.dismiss() val snackbarMessage = getRemoveBookmarksSnackBarMessage(selected, containsFolders = true) - viewLifecycleOwner.lifecycleScope.allowUndo( + // Use fragment's lifecycle; the view may be gone by the time dialog is interacted with. + lifecycleScope.allowUndo( requireView(), snackbarMessage, getString(R.string.bookmark_undo_deletion), diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/edit/EditBookmarkFragment.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/edit/EditBookmarkFragment.kt index c7de31c64..db2e3f71b 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/edit/EditBookmarkFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/edit/EditBookmarkFragment.kt @@ -182,7 +182,8 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { dialog.cancel() } setPositiveButton(R.string.tab_collection_dialog_positive) { dialog: DialogInterface, _ -> - viewLifecycleOwner.lifecycleScope.launch(IO) { + // Use fragment's lifecycle; the view may be gone by the time dialog is interacted with. + lifecycleScope.launch(IO) { requireComponents.core.bookmarksStorage.deleteNode(args.guidToEdit) requireComponents.analytics.metrics.track(Event.RemoveBookmark) diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt index f4714615a..a158eecc9 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt @@ -267,7 +267,8 @@ class HistoryFragment : LibraryPageFragment(), UserInteractionHandl } setPositiveButton(R.string.delete_browsing_data_prompt_allow) { dialog: DialogInterface, _ -> historyStore.dispatch(HistoryFragmentAction.EnterDeletionMode) - viewLifecycleOwner.lifecycleScope.launch(IO) { + // Use fragment's lifecycle; the view may be gone by the time dialog is interacted with. + lifecycleScope.launch(IO) { requireComponents.analytics.metrics.track(Event.HistoryAllItemsRemoved) requireComponents.core.store.dispatch(RecentlyClosedAction.RemoveAllClosedTabAction) requireComponents.core.historyStorage.deleteEverything() diff --git a/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt index 8ccc5ff87..45e73998d 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt @@ -233,7 +233,8 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { setNegativeButton(getString(R.string.logins_warning_dialog_later)) { _: DialogInterface, _ -> SyncEnginesStorage(context).setStatus(SyncEngine.Passwords, newValue) - viewLifecycleOwner.lifecycleScope.launch { + // Use fragment's lifecycle; the view may be gone by the time dialog is interacted with. + lifecycleScope.launch { context.components.backgroundServices.accountManager.syncNow(SyncReason.EngineChange) } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/deletebrowsingdata/DeleteBrowsingDataFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/deletebrowsingdata/DeleteBrowsingDataFragment.kt index 77f867494..95732ce21 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/deletebrowsingdata/DeleteBrowsingDataFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/deletebrowsingdata/DeleteBrowsingDataFragment.kt @@ -142,7 +142,7 @@ class DeleteBrowsingDataFragment : Fragment(R.layout.fragment_delete_browsing_da private fun deleteSelected() { startDeletion() - viewLifecycleOwner.lifecycleScope.launch(IO) { + lifecycleScope.launch(IO) { getCheckboxes().mapIndexed { i, v -> if (v.isChecked) { when (i) { diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/controller/SavedLoginsStorageController.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/controller/SavedLoginsStorageController.kt index bd1bbe96a..5257c73f8 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/controller/SavedLoginsStorageController.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/controller/SavedLoginsStorageController.kt @@ -30,7 +30,7 @@ import org.mozilla.fenix.settings.logins.mapToSavedLogin */ open class SavedLoginsStorageController( private val passwordsStorage: SyncableLoginsStorage, - private val viewLifecycleScope: CoroutineScope, + private val lifecycleScope: CoroutineScope, private val navController: NavController, private val loginsFragmentStore: LoginsFragmentStore, private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO @@ -40,7 +40,7 @@ open class SavedLoginsStorageController( fun delete(loginId: String) { var deleteLoginJob: Deferred? = null - val deleteJob = viewLifecycleScope.launch(ioDispatcher) { + val deleteJob = lifecycleScope.launch(ioDispatcher) { deleteLoginJob = async { passwordsStorage.delete(loginId) } @@ -58,7 +58,7 @@ open class SavedLoginsStorageController( fun save(loginId: String, usernameText: String, passwordText: String) { var saveLoginJob: Deferred? = null - viewLifecycleScope.launch(ioDispatcher) { + lifecycleScope.launch(ioDispatcher) { saveLoginJob = async { // must retrieve from storage to get the httpsRealm and formActionOrigin val oldLogin = passwordsStorage.get(loginId) @@ -124,7 +124,7 @@ open class SavedLoginsStorageController( fun findPotentialDuplicates(loginId: String) { var deferredLogin: Deferred>? = null - val fetchLoginJob = viewLifecycleScope.launch(ioDispatcher) { + val fetchLoginJob = lifecycleScope.launch(ioDispatcher) { deferredLogin = async { val login = getLogin(loginId) passwordsStorage.getPotentialDupesIgnoringUsername(login!!) @@ -150,7 +150,7 @@ open class SavedLoginsStorageController( fun fetchLoginDetails(loginId: String) { var deferredLogin: Deferred>? = null - val fetchLoginJob = viewLifecycleScope.launch(ioDispatcher) { + val fetchLoginJob = lifecycleScope.launch(ioDispatcher) { deferredLogin = async { passwordsStorage.list() } @@ -178,7 +178,7 @@ open class SavedLoginsStorageController( fun handleLoadAndMapLogins() { var deferredLogins: Deferred>? = null - val fetchLoginsJob = viewLifecycleScope.launch(ioDispatcher) { + val fetchLoginsJob = lifecycleScope.launch(ioDispatcher) { deferredLogins = async { passwordsStorage.list() } diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/EditLoginFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/EditLoginFragment.kt index 62a624169..fccf33aa9 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/EditLoginFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/EditLoginFragment.kt @@ -76,7 +76,7 @@ class EditLoginFragment : Fragment(R.layout.fragment_edit_login) { interactor = EditLoginInteractor( SavedLoginsStorageController( passwordsStorage = requireContext().components.core.passwordsStorage, - viewLifecycleScope = viewLifecycleOwner.lifecycleScope, + lifecycleScope = lifecycleScope, navController = findNavController(), loginsFragmentStore = loginsFragmentStore ) diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/LoginDetailFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/LoginDetailFragment.kt index 7120c0fe0..63fe12c87 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/LoginDetailFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/LoginDetailFragment.kt @@ -86,7 +86,7 @@ class LoginDetailFragment : Fragment(R.layout.fragment_login_detail) { interactor = LoginDetailInteractor( SavedLoginsStorageController( passwordsStorage = requireContext().components.core.passwordsStorage, - viewLifecycleScope = viewLifecycleOwner.lifecycleScope, + lifecycleScope = lifecycleScope, navController = findNavController(), loginsFragmentStore = savedLoginsStore ) diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsFragment.kt index dc50cc445..130e856a6 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsFragment.kt @@ -92,7 +92,7 @@ class SavedLoginsFragment : Fragment() { savedLoginsStorageController = SavedLoginsStorageController( passwordsStorage = requireContext().components.core.passwordsStorage, - viewLifecycleScope = viewLifecycleOwner.lifecycleScope, + lifecycleScope = viewLifecycleOwner.lifecycleScope, navController = findNavController(), loginsFragmentStore = savedLoginsStore ) diff --git a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsDetailsExceptionsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsDetailsExceptionsFragment.kt index 9ad2a5f1a..8e68407b2 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsDetailsExceptionsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsDetailsExceptionsFragment.kt @@ -92,7 +92,8 @@ class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat() { } private fun clearSitePermissions() { - viewLifecycleOwner.lifecycleScope.launch(IO) { + // Use fragment's lifecycle; the view may be gone by the time dialog is interacted with. + lifecycleScope.launch(IO) { requireContext().components.core.permissionStorage.deleteSitePermissions(sitePermissions) withContext(Main) { requireView().findNavController().popBackStack() diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayDialogFragment.kt index 858be4e76..624b10e4c 100644 --- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayDialogFragment.kt @@ -417,7 +417,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler AlertDialog.Builder(it).setTitle(R.string.tab_tray_add_new_collection) .setView(customLayout).setPositiveButton(android.R.string.ok) { dialog, _ -> - viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { + lifecycleScope.launch(Dispatchers.IO) { tabCollectionStorage.createCollection( collectionNameEditText.text.toString(), sessionList diff --git a/app/src/test/java/org/mozilla/fenix/settings/logins/SavedLoginsStorageControllerTest.kt b/app/src/test/java/org/mozilla/fenix/settings/logins/SavedLoginsStorageControllerTest.kt index d29acb3ed..e06dc6641 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/logins/SavedLoginsStorageControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/logins/SavedLoginsStorageControllerTest.kt @@ -54,7 +54,7 @@ class SavedLoginsStorageControllerTest { controller = SavedLoginsStorageController( passwordsStorage = passwordsStorage, - viewLifecycleScope = scope, + lifecycleScope = scope, navController = navController, loginsFragmentStore = loginsFragmentStore, ioDispatcher = ioDispatcher