mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-19 09:25:34 +00:00
[fenix] For https://github.com/mozilla-mobile/fenix/issues/9100 - Private browsing notification fixes
Co-authored-by: Seef <Saif Dara>
This commit is contained in:
parent
4f08a54d60
commit
8a13fbbfb3
@ -43,7 +43,6 @@ import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.perf.StartupTimeline
|
||||
import org.mozilla.fenix.push.PushFxaIntegration
|
||||
import org.mozilla.fenix.push.WebPushEngineIntegration
|
||||
import org.mozilla.fenix.session.NotificationSessionObserver
|
||||
import org.mozilla.fenix.session.PerformanceActivityLifecycleCallbacks
|
||||
import org.mozilla.fenix.session.VisibilityLifecycleCallback
|
||||
import org.mozilla.fenix.utils.BrowsersCache
|
||||
@ -157,9 +156,6 @@ open class FenixApplication : LocaleAwareApplication() {
|
||||
visibilityLifecycleCallback = VisibilityLifecycleCallback(getSystemService())
|
||||
registerActivityLifecycleCallbacks(visibilityLifecycleCallback)
|
||||
|
||||
val privateNotificationObserver = NotificationSessionObserver(this)
|
||||
privateNotificationObserver.start()
|
||||
|
||||
// Storage maintenance disabled, for now, as it was interfering with background migrations.
|
||||
// See https://github.com/mozilla-mobile/fenix/issues/7227 for context.
|
||||
// if ((System.currentTimeMillis() - settings().lastPlacesStorageMaintenance) > ONE_DAY_MILLIS) {
|
||||
|
@ -74,6 +74,7 @@ import org.mozilla.fenix.library.history.HistoryFragmentDirections
|
||||
import org.mozilla.fenix.perf.Performance
|
||||
import org.mozilla.fenix.perf.StartupTimeline
|
||||
import org.mozilla.fenix.search.SearchFragmentDirections
|
||||
import org.mozilla.fenix.session.NotificationSessionObserver
|
||||
import org.mozilla.fenix.settings.SettingsFragmentDirections
|
||||
import org.mozilla.fenix.settings.TrackingProtectionFragmentDirections
|
||||
import org.mozilla.fenix.settings.about.AboutFragmentDirections
|
||||
@ -154,6 +155,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
||||
|
||||
sessionObserver = UriOpenedObserver(this)
|
||||
|
||||
checkPrivateShortcutEntryPoint(intent)
|
||||
val privateNotificationObserver = NotificationSessionObserver(this)
|
||||
privateNotificationObserver.start()
|
||||
|
||||
if (isActivityColdStarted(intent, savedInstanceState)) {
|
||||
externalSourceIntentProcessors.any { it.process(intent, navHost.navController, this.intent) }
|
||||
}
|
||||
@ -176,6 +181,11 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
||||
StartupTimeline.homeActivityLifecycleObserver
|
||||
)
|
||||
StartupTimeline.onActivityCreateEndHome(this)
|
||||
|
||||
if (shouldAddToRecentsScreen(intent)) {
|
||||
intent.removeExtra(START_IN_RECENTS_SCREEN)
|
||||
moveTaskToBack(true)
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@ -313,6 +323,30 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
||||
return settings().lastKnownMode
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the activity should be pushed to be backstack (i.e., 'minimized' to the recents
|
||||
* screen) upon starting.
|
||||
* @param intent - The intent that started this activity. Is checked for having the 'START_IN_RECENTS_SCREEN'-extra.
|
||||
* @return true if the activity should be started and pushed to the recents screen, false otherwise.
|
||||
*/
|
||||
private fun shouldAddToRecentsScreen(intent: Intent?): Boolean {
|
||||
intent?.toSafeIntent()?.let {
|
||||
return it.getBooleanExtra(START_IN_RECENTS_SCREEN, false)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun checkPrivateShortcutEntryPoint(intent: Intent) {
|
||||
if (intent.hasExtra(OPEN_TO_SEARCH) &&
|
||||
(intent.getStringExtra(OPEN_TO_SEARCH) ==
|
||||
StartSearchIntentProcessor.STATIC_SHORTCUT_NEW_PRIVATE_TAB ||
|
||||
intent.getStringExtra(OPEN_TO_SEARCH) ==
|
||||
StartSearchIntentProcessor.PRIVATE_BROWSING_PINNED_SHORTCUT)
|
||||
) {
|
||||
NotificationSessionObserver.isStartedFromPrivateShortcut = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupThemeAndBrowsingMode(mode: BrowsingMode) {
|
||||
settings().lastKnownMode = mode
|
||||
browsingModeManager = createBrowsingModeManager(mode)
|
||||
@ -499,5 +533,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
||||
const val EXTRA_DELETE_PRIVATE_TABS = "notification_delete_and_open"
|
||||
const val EXTRA_OPENED_FROM_NOTIFICATION = "notification_open"
|
||||
const val delay = 5000L
|
||||
const val START_IN_RECENTS_SCREEN = "start_in_recents_screen"
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ class NotificationSessionObserver(
|
||||
.ifChanged()
|
||||
.collect { hasPrivateTabs ->
|
||||
if (hasPrivateTabs) {
|
||||
notificationService.start(context)
|
||||
notificationService.start(context, isStartedFromPrivateShortcut)
|
||||
started = true
|
||||
} else if (started) {
|
||||
notificationService.stop(context)
|
||||
@ -47,4 +47,8 @@ class NotificationSessionObserver(
|
||||
fun stop() {
|
||||
scope?.cancel()
|
||||
}
|
||||
|
||||
companion object {
|
||||
var isStartedFromPrivateShortcut = false
|
||||
}
|
||||
}
|
||||
|
@ -37,32 +37,41 @@ import org.mozilla.fenix.ext.sessionsOfType
|
||||
*/
|
||||
class SessionNotificationService : Service() {
|
||||
|
||||
private var isStartedFromPrivateShortcut: Boolean = false
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
val action = intent.action ?: return Service.START_NOT_STICKY
|
||||
val action = intent.action ?: return START_NOT_STICKY
|
||||
|
||||
when (action) {
|
||||
ACTION_START -> {
|
||||
isStartedFromPrivateShortcut = intent.getBooleanExtra(STARTED_FROM_PRIVATE_SHORTCUT, false)
|
||||
createNotificationChannelIfNeeded()
|
||||
startForeground(NOTIFICATION_ID, buildNotification())
|
||||
}
|
||||
|
||||
ACTION_ERASE -> {
|
||||
metrics.track(Event.PrivateBrowsingNotificationTapped)
|
||||
components.core.sessionManager.removeAndCloseAllPrivateSessions()
|
||||
|
||||
if (!VisibilityLifecycleCallback.finishAndRemoveTaskIfInBackground(this)) {
|
||||
startActivity(
|
||||
Intent(this, HomeActivity::class.java).apply {
|
||||
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
)
|
||||
val homeScreenIntent = Intent(this, HomeActivity::class.java)
|
||||
val intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
homeScreenIntent.apply {
|
||||
setFlags(intentFlags)
|
||||
putExtra(HomeActivity.PRIVATE_BROWSING_MODE, isStartedFromPrivateShortcut)
|
||||
}
|
||||
if (VisibilityLifecycleCallback.finishAndRemoveTaskIfInBackground(this)) {
|
||||
// Set start mode to be in background (recents screen)
|
||||
homeScreenIntent.apply {
|
||||
putExtra(HomeActivity.START_IN_RECENTS_SCREEN, true)
|
||||
}
|
||||
}
|
||||
startActivity(homeScreenIntent)
|
||||
components.core.sessionManager.removeAndCloseAllPrivateSessions()
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException("Unknown intent: $intent")
|
||||
}
|
||||
|
||||
return Service.START_NOT_STICKY
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
override fun onTaskRemoved(rootIntent: Intent) {
|
||||
@ -125,13 +134,18 @@ class SessionNotificationService : Service() {
|
||||
companion object {
|
||||
private const val NOTIFICATION_ID = 83
|
||||
private const val NOTIFICATION_CHANNEL_ID = "browsing-session"
|
||||
private const val STARTED_FROM_PRIVATE_SHORTCUT = "STARTED_FROM_PRIVATE_SHORTCUT"
|
||||
|
||||
private const val ACTION_START = "start"
|
||||
private const val ACTION_ERASE = "erase"
|
||||
|
||||
internal fun start(context: Context) {
|
||||
internal fun start(
|
||||
context: Context,
|
||||
startedFromPrivateShortcut: Boolean
|
||||
) {
|
||||
val intent = Intent(context, SessionNotificationService::class.java)
|
||||
intent.action = ACTION_START
|
||||
intent.putExtra(STARTED_FROM_PRIVATE_SHORTCUT, startedFromPrivateShortcut)
|
||||
|
||||
// From Focus #2901: The application is crashing due to the service not calling `startForeground`
|
||||
// before it times out. This is a speculative fix to decrease the time between these two
|
||||
|
@ -25,6 +25,13 @@ class VisibilityLifecycleCallback(private val activityManager: ActivityManager?)
|
||||
*/
|
||||
private var activitiesInStartedState: Int = 0
|
||||
|
||||
/**
|
||||
* Finishes and removes the list of AppTasks only if the application is in the background.
|
||||
* The application is considered to be in the background if it has at least 1 Activity in the
|
||||
* started state
|
||||
* @return True if application is in background (also finishes and removes all AppTasks),
|
||||
* false otherwise
|
||||
*/
|
||||
private fun finishAndRemoveTaskIfInBackground(): Boolean {
|
||||
if (activitiesInStartedState == 0) {
|
||||
activityManager?.let {
|
||||
@ -59,6 +66,9 @@ class VisibilityLifecycleCallback(private val activityManager: ActivityManager?)
|
||||
/**
|
||||
* If all activities of this app are in the background then finish and remove all tasks. After
|
||||
* that the app won't show up in "recent apps" anymore.
|
||||
*
|
||||
* @return True if application is in background (and consequently, finishes and removes all tasks),
|
||||
* false otherwise.
|
||||
*/
|
||||
internal fun finishAndRemoveTaskIfInBackground(context: Context): Boolean {
|
||||
return (context.applicationContext as FenixApplication)
|
||||
|
@ -35,6 +35,7 @@ class NotificationSessionObserverTest {
|
||||
store = BrowserStore()
|
||||
every { context.components.core.store } returns store
|
||||
observer = NotificationSessionObserver(context, notificationService)
|
||||
NotificationSessionObserver.isStartedFromPrivateShortcut = false
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -44,7 +45,7 @@ class NotificationSessionObserverTest {
|
||||
store.dispatch(TabListAction.AddTabAction(privateSession)).join()
|
||||
|
||||
observer.start()
|
||||
verify(exactly = 1) { notificationService.start(context) }
|
||||
verify(exactly = 1) { notificationService.start(context, false) }
|
||||
confirmVerified(notificationService)
|
||||
}
|
||||
|
||||
@ -57,10 +58,10 @@ class NotificationSessionObserverTest {
|
||||
verify { notificationService wasNot Called }
|
||||
|
||||
store.dispatch(TabListAction.AddTabAction(normalSession)).join()
|
||||
verify(exactly = 0) { notificationService.start(context) }
|
||||
verify(exactly = 0) { notificationService.start(context, false) }
|
||||
|
||||
store.dispatch(CustomTabListAction.AddCustomTabAction(customSession)).join()
|
||||
verify(exactly = 0) { notificationService.start(context) }
|
||||
verify(exactly = 0) { notificationService.start(context, false) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -74,9 +75,9 @@ class NotificationSessionObserverTest {
|
||||
verify { notificationService wasNot Called }
|
||||
|
||||
store.dispatch(CustomTabListAction.AddCustomTabAction(privateCustomSession)).join()
|
||||
verify(exactly = 0) { notificationService.start(context) }
|
||||
verify(exactly = 0) { notificationService.start(context, false) }
|
||||
|
||||
store.dispatch(CustomTabListAction.AddCustomTabAction(customSession)).join()
|
||||
verify(exactly = 0) { notificationService.start(context) }
|
||||
verify(exactly = 0) { notificationService.start(context, false) }
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user