diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 710612080..453756274 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -31,6 +31,7 @@ import mozilla.components.support.ktx.kotlin.isUrl import mozilla.components.support.ktx.kotlin.toNormalizedUrl import mozilla.components.support.utils.SafeIntent import mozilla.components.support.utils.toSafeIntent +import org.mozilla.fenix.browser.UriOpenedObserver import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager @@ -220,7 +221,7 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback fun openToBrowser(from: BrowserDirection, customTabSessionId: String? = null) { if (sessionObserver == null) - sessionObserver = subscribeToSessions() + sessionObserver = UriOpenedObserver(this) if (navHost.navController.alreadyOnDestination(R.id.browserFragment)) return @IdRes val fragmentId = if (from.fragmentId != 0) from.fragmentId else null @@ -309,43 +310,6 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback return DefaultThemeManager(browsingModeManager.mode, this) } - @Suppress("ComplexMethod") - private fun subscribeToSessions(): SessionManager.Observer { - val singleSessionObserver = object : Session.Observer { - var urlLoading: String? = null - - override fun onLoadingStateChanged(session: Session, loading: Boolean) { - if (loading) { - urlLoading = session.url - } else if (urlLoading != null && !session.private) { - components.analytics.metrics.track(Event.UriOpened) - } - } - } - - return object : SessionManager.Observer { - override fun onAllSessionsRemoved() { - components.core.sessionManager.sessions.forEach { - it.unregister(singleSessionObserver) - } - } - - override fun onSessionAdded(session: Session) { - session.register(singleSessionObserver, this@HomeActivity) - } - - override fun onSessionRemoved(session: Session) { - session.unregister(singleSessionObserver) - } - - override fun onSessionsRestored() { - components.core.sessionManager.sessions.forEach { - it.register(singleSessionObserver, this@HomeActivity) - } - } - }.also { components.core.sessionManager.register(it, this) } - } - override fun onTabsShared(tabsSize: Int) { getRootView()?.let { FenixSnackbar.make(it, Snackbar.LENGTH_SHORT).setText( diff --git a/app/src/main/java/org/mozilla/fenix/browser/UriOpenedObserver.kt b/app/src/main/java/org/mozilla/fenix/browser/UriOpenedObserver.kt new file mode 100644 index 000000000..ba839864d --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/browser/UriOpenedObserver.kt @@ -0,0 +1,65 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.browser + +import androidx.annotation.VisibleForTesting +import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.LifecycleOwner +import mozilla.components.browser.session.Session +import mozilla.components.browser.session.SessionManager +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.components.metrics.MetricController +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.metrics + +class UriOpenedObserver( + private val owner: LifecycleOwner, + private val sessionManager: SessionManager, + private val metrics: MetricController +) : SessionManager.Observer { + + constructor(activity: FragmentActivity) : this( + activity, + activity.components.core.sessionManager, + activity.metrics + ) + + init { + sessionManager.register(this, owner) + } + + @VisibleForTesting + internal val singleSessionObserver = object : Session.Observer { + private var urlLoading: String? = null + + override fun onLoadingStateChanged(session: Session, loading: Boolean) { + if (loading) { + urlLoading = session.url + } else if (urlLoading != null && !session.private) { + metrics.track(Event.UriOpened) + } + } + } + + override fun onAllSessionsRemoved() { + sessionManager.sessions.forEach { + it.unregister(singleSessionObserver) + } + } + + override fun onSessionAdded(session: Session) { + session.register(singleSessionObserver, owner) + } + + override fun onSessionRemoved(session: Session) { + session.unregister(singleSessionObserver) + } + + override fun onSessionsRestored() { + sessionManager.sessions.forEach { + it.register(singleSessionObserver, owner) + } + } +} diff --git a/app/src/test/java/org/mozilla/fenix/browser/UriOpenedObserverTest.kt b/app/src/test/java/org/mozilla/fenix/browser/UriOpenedObserverTest.kt new file mode 100644 index 000000000..5dee9558f --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/browser/UriOpenedObserverTest.kt @@ -0,0 +1,62 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.browser + +import androidx.lifecycle.LifecycleOwner +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import mozilla.components.browser.session.Session +import mozilla.components.browser.session.SessionManager +import org.junit.Before +import org.junit.Test +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.components.metrics.MetricController + +class UriOpenedObserverTest { + + private lateinit var owner: LifecycleOwner + private lateinit var sessionManager: SessionManager + private lateinit var metrics: MetricController + + @Before + fun setup() { + owner = mockk(relaxed = true) + sessionManager = mockk(relaxed = true) + metrics = mockk(relaxed = true) + } + + @Test + fun `registers self as observer`() { + val observer = UriOpenedObserver(owner, sessionManager, metrics) + verify { sessionManager.register(observer, owner) } + } + + @Test + fun `registers single session observer`() { + val observer = UriOpenedObserver(owner, sessionManager, metrics) + val session: Session = mockk(relaxed = true) + + observer.onSessionAdded(session) + verify { session.register(observer.singleSessionObserver, owner) } + + observer.onSessionRemoved(session) + verify { session.unregister(observer.singleSessionObserver) } + } + + @Test + fun `tracks that a url was loaded`() { + val observer = UriOpenedObserver(owner, sessionManager, metrics).singleSessionObserver + val session: Session = mockk(relaxed = true) + every { session.url } returns "https://mozilla.com" + + observer.onLoadingStateChanged(session, loading = false) + verify(exactly = 0) { metrics.track(Event.UriOpened) } + + observer.onLoadingStateChanged(session, loading = true) + observer.onLoadingStateChanged(session, loading = false) + verify { metrics.track(Event.UriOpened) } + } +}