Commit 2c01022c authored by Simon Chae's avatar Simon Chae Committed by Jeff Boek
Browse files

For #8153: Allow web-ext to open new tabs in correct browsing mode

parent 5e4ef202
......@@ -304,7 +304,7 @@ open class FenixApplication : LocaleAwareApplication() {
components.core.store,
onNewTabOverride = {
_, engineSession, url ->
val session = Session(url)
val session = Session(url, components.browsingModeManager.mode.isPrivate)
components.core.sessionManager.add(session, true, engineSession)
session.id
},
......
......@@ -40,8 +40,7 @@ import mozilla.components.support.utils.toSafeIntent
import mozilla.components.support.webextensions.WebExtensionPopupFeature
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
import org.mozilla.fenix.browser.browsingmode.BrowsingModeListener
import org.mozilla.fenix.components.metrics.BreadcrumbsRecorder
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.exceptions.ExceptionsFragmentDirections
......@@ -74,7 +73,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
private var webExtScope: CoroutineScope? = null
lateinit var themeManager: ThemeManager
lateinit var browsingModeManager: BrowsingModeManager
private val browsingModeManager get() = components.browsingModeManager
private var sessionObserver: SessionManager.Observer? = null
......@@ -99,6 +98,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
)
}
private val browsingModeListener = object : BrowsingModeListener {
override fun onBrowsingModeChange(newMode: BrowsingMode) {
themeManager.currentTheme = newMode
}
}
override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
if (overrideConfiguration != null) {
val uiMode = overrideConfiguration.uiMode
......@@ -161,6 +166,16 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
hotStartMonitor.onPostResumeFinalMethodCall()
}
final override fun onStart() {
super.onStart()
browsingModeManager.registerBrowsingModeListener(browsingModeListener)
}
final override fun onStop() {
super.onStop()
browsingModeManager.unregisterBrowsingModeListener()
}
final override fun onPause() {
super.onPause()
......@@ -237,7 +252,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
private fun setupThemeAndBrowsingMode(mode: BrowsingMode) {
settings().lastKnownMode = mode
browsingModeManager = createBrowsingModeManager(mode)
browsingModeManager.mode = mode
themeManager = createThemeManager()
themeManager.setActivityTheme(this)
themeManager.applyStatusBarTheme(this)
......@@ -374,12 +389,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
}
}
protected open fun createBrowsingModeManager(initialMode: BrowsingMode): BrowsingModeManager {
return DefaultBrowsingModeManager(initialMode) { newMode ->
themeManager.currentTheme = newMode
}
}
protected open fun createThemeManager(): ThemeManager {
return DefaultThemeManager(browsingModeManager.mode, this)
}
......
......@@ -160,10 +160,10 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
navController = findNavController(),
readerModeController = DefaultReaderModeController(
readerViewFeature,
(activity as HomeActivity).browsingModeManager.mode.isPrivate,
requireComponents.browsingModeManager.mode.isPrivate,
view.readerViewControlsBar
),
browsingModeManager = (activity as HomeActivity).browsingModeManager,
browsingModeManager = requireComponents.browsingModeManager,
sessionManager = requireComponents.core.sessionManager,
findInPageLauncher = { findInPageIntegration.withFeature { it.launch() } },
browserLayout = view.browserLayout,
......
......@@ -31,19 +31,32 @@ interface BrowsingModeManager {
var mode: BrowsingMode
}
interface BrowsingModeListener {
fun onBrowsingModeChange(newMode: BrowsingMode)
}
/**
* Wraps a [BrowsingMode] and executes a callback whenever [mode] is updated.
*/
class DefaultBrowsingModeManager(
private var _mode: BrowsingMode,
private val modeDidChange: (BrowsingMode) -> Unit
private var _mode: BrowsingMode = BrowsingMode.Normal
) : BrowsingModeManager {
private var _browsingModeListener: BrowsingModeListener? = null
fun registerBrowsingModeListener(browsingModeListener: BrowsingModeListener) {
_browsingModeListener = browsingModeListener
}
fun unregisterBrowsingModeListener() {
_browsingModeListener = null
}
override var mode: BrowsingMode
get() = _mode
set(value) {
_mode = value
modeDidChange(value)
_browsingModeListener?.onBrowsingModeChange(value)
Settings.instance?.lastKnownMode = value
}
}
......@@ -12,6 +12,7 @@ import mozilla.components.feature.addons.update.DefaultAddonUpdater
import mozilla.components.feature.tabs.TabsUseCases
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
import mozilla.components.support.migration.state.MigrationStore
import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager
import org.mozilla.fenix.test.Mockable
import org.mozilla.fenix.utils.ClipboardHandler
import java.util.concurrent.TimeUnit
......@@ -71,6 +72,8 @@ class Components(private val context: Context) {
AddonManager(core.store, core.engine, addonCollectionProvider, addonUpdater)
}
val browsingModeManager by lazy { DefaultBrowsingModeManager() }
val tabsUseCases: TabsUseCases by lazy { TabsUseCases(core.sessionManager) }
val analytics by lazy { Analytics(context) }
......
......@@ -22,10 +22,8 @@ import mozilla.components.browser.menu.item.BrowserMenuItemToolbar
import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager
import mozilla.components.concept.storage.BookmarksStorage
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.ext.asActivity
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.utils.Settings
......@@ -130,8 +128,8 @@ class DefaultToolbarMenu(
private val menuItems by lazy {
// Predicates that are called once, during screen init
val shouldShowSaveToCollection = (context.asActivity() as? HomeActivity)
?.browsingModeManager?.mode == BrowsingMode.Normal
val shouldShowSaveToCollection =
context.components.browsingModeManager.mode == BrowsingMode.Normal
val shouldDeleteDataOnQuit = Settings.getInstance(context)
.shouldDeleteBrowsingDataOnQuit
......
......@@ -27,7 +27,6 @@ import mozilla.components.lib.state.ext.consumeFrom
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import mozilla.components.support.ktx.android.arch.lifecycle.addObservers
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.BaseBrowserFragment
import org.mozilla.fenix.browser.CustomTabContextMenuCandidate
......@@ -69,7 +68,7 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler
activity = activity,
engineLayout = view.swipeRefresh,
onItemTapped = { browserInteractor.onBrowserToolbarMenuItemTapped(it) },
isPrivate = (activity as HomeActivity).browsingModeManager.mode.isPrivate,
isPrivate = requireComponents.browsingModeManager.mode.isPrivate,
shouldReverseItems = !activity.settings().shouldUseBottomToolbar
),
owner = this,
......
......@@ -106,7 +106,7 @@ class HomeFragment : Fragment() {
}
}
private val browsingModeManager get() = (activity as HomeActivity).browsingModeManager
private val browsingModeManager get() = requireComponents.browsingModeManager
private var homeAppBarOffset = 0
private val singleSessionObserver = object : Session.Observer {
override fun onTitleChanged(session: Session, title: String) {
......
......@@ -15,6 +15,7 @@ import org.mozilla.fenix.GlobalDirections
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.ext.alreadyOnDestination
import org.mozilla.fenix.ext.components
/**
* Deep links in the form of `fenix://host` open different parts of the app.
......@@ -56,7 +57,7 @@ class DeepLinkIntentProcessor(
private fun handleDeepLinkSideEffects(deepLink: Uri) {
when (deepLink.host) {
"enable_private_browsing" -> {
activity.browsingModeManager.mode = BrowsingMode.Private
activity.components.browsingModeManager.mode = BrowsingMode.Private
}
"make_default_browser" -> {
if (SDK_INT >= Build.VERSION_CODES.N) {
......
......@@ -5,10 +5,10 @@
package org.mozilla.fenix.library
import androidx.fragment.app.Fragment
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.hideToolbar
import org.mozilla.fenix.ext.requireComponents
abstract class LibraryPageFragment<T> : Fragment() {
......@@ -24,7 +24,7 @@ abstract class LibraryPageFragment<T> : Fragment() {
}
}
(activity as HomeActivity).browsingModeManager.mode = BrowsingMode.fromBoolean(private)
requireComponents.browsingModeManager.mode = BrowsingMode.fromBoolean(private)
hideToolbar()
}
}
......@@ -56,7 +56,7 @@ class DefaultBookmarkController(
private val services: Services = activity.components.services
override fun handleBookmarkTapped(item: BookmarkNode) {
openInNewTab(item.url!!, true, BrowserDirection.FromBookmarks, activity.browsingModeManager.mode)
openInNewTab(item.url!!, true, BrowserDirection.FromBookmarks, context.components.browsingModeManager.mode)
}
override fun handleBookmarkExpand(folder: BookmarkNode) {
......@@ -117,7 +117,7 @@ class DefaultBookmarkController(
) {
invokePendingDeletion.invoke()
with(activity) {
browsingModeManager.mode = mode
components.browsingModeManager.mode = mode
openToBrowserAndLoad(searchTermOrURL, newTab, from)
}
}
......
......@@ -169,7 +169,7 @@ class HistoryFragment : LibraryPageFragment<HistoryItem>(), UserInteractionHandl
}
(activity as HomeActivity).apply {
browsingModeManager.mode = BrowsingMode.Private
components.browsingModeManager.mode = BrowsingMode.Private
supportActionBar?.hide()
}
nav(
......
......@@ -88,7 +88,7 @@ class DefaultSearchController(
store.dispatch(
SearchFragmentAction.AllowSearchSuggestionsInPrivateModePrompt(
text.isNotEmpty() &&
(context as HomeActivity).browsingModeManager.mode.isPrivate &&
context.components.browsingModeManager.mode.isPrivate &&
!context.settings().shouldShowSearchSuggestionsInPrivate &&
!context.settings().showSearchSuggestionsInPrivateOnboardingFinished
)
......
......@@ -87,7 +87,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
)
val showSearchSuggestions =
if ((activity as HomeActivity).browsingModeManager.mode.isPrivate) {
if (requireComponents.browsingModeManager.mode.isPrivate) {
requireContext().settings().shouldShowSearchSuggestions &&
requireContext().settings().shouldShowSearchSuggestionsInPrivate
} else {
......@@ -130,7 +130,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
view.toolbar_component_wrapper,
searchInteractor,
historyStorageProvider(),
(activity as HomeActivity).browsingModeManager.mode.isPrivate
requireComponents.browsingModeManager.mode.isPrivate
)
val urlView = toolbarView.view
......
......@@ -28,9 +28,7 @@ import mozilla.components.feature.session.SessionUseCases
import mozilla.components.feature.tabs.TabsUseCases
import mozilla.components.support.ktx.android.content.getColorFromAttr
import mozilla.components.support.ktx.android.view.hideKeyboard
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.asActivity
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.search.SearchEngineSource
import org.mozilla.fenix.search.SearchFragmentState
......@@ -304,10 +302,7 @@ class AwesomeBarView(
return providersToRemove
}
private fun isBrowsingModePrivate(): Boolean {
return (container.context.asActivity() as? HomeActivity)?.browsingModeManager?.mode?.isPrivate
?: false
}
private fun isBrowsingModePrivate(): Boolean = container.context.components.browsingModeManager.mode.isPrivate
private fun getSelectedSearchSuggestionProvider(state: SearchFragmentState): SearchSuggestionProvider? {
return when (state.searchEngineSource) {
......
......@@ -4,40 +4,42 @@
package org.mozilla.fenix.browser.browsingmode
import io.mockk.MockKAnnotations
import io.mockk.impl.annotations.MockK
import io.mockk.verify
import mozilla.components.support.test.any
import mozilla.components.support.test.mock
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
class DefaultBrowsingModeManagerTest {
@MockK(relaxed = true) lateinit var callback: (BrowsingMode) -> Unit
lateinit var manager: BrowsingModeManager
lateinit var manager: DefaultBrowsingModeManager
private val initMode = BrowsingMode.Normal
@Before
fun before() {
MockKAnnotations.init(this)
manager = DefaultBrowsingModeManager(initMode, callback)
manager = DefaultBrowsingModeManager(initMode)
}
@Test
fun `WHEN mode is updated THEN callback is invoked`() {
verify(exactly = 0) { callback.invoke(any()) }
val browsingModeListener: BrowsingModeListener = mock()
manager.registerBrowsingModeListener(browsingModeListener)
verify(browsingModeListener, times(0)).onBrowsingModeChange(any())
manager.mode = BrowsingMode.Private
manager.mode = BrowsingMode.Private
manager.mode = BrowsingMode.Private
verify(exactly = 3) { callback.invoke(any()) }
verify(browsingModeListener, times(3)).onBrowsingModeChange(any())
manager.mode = BrowsingMode.Normal
manager.mode = BrowsingMode.Normal
verify(exactly = 5) { callback.invoke(any()) }
verify(browsingModeListener, times(5)).onBrowsingModeChange(any())
}
@Test
......
......@@ -8,6 +8,7 @@ import android.content.Context
import io.mockk.mockk
import mozilla.components.support.test.mock
import org.mockito.Mockito.`when`
import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager
import org.mozilla.fenix.utils.ClipboardHandler
class TestComponents(private val context: Context) : Components(context) {
......@@ -38,5 +39,7 @@ class TestComponents(private val context: Context) : Components(context) {
}
override val analytics by lazy { Analytics(context) }
override val browsingModeManager by lazy { DefaultBrowsingModeManager() }
override val clipboardHandler by lazy { ClipboardHandler(context) }
}
......@@ -8,6 +8,7 @@ import android.content.Intent
import androidx.core.net.toUri
import androidx.navigation.NavController
import io.mockk.Called
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import org.junit.Assert.assertFalse
......@@ -20,6 +21,8 @@ import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.TestApplication
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager
import org.mozilla.fenix.ext.components
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
......@@ -114,9 +117,12 @@ class DeepLinkIntentProcessorTest {
@Test
fun `process enable_private_browsing deep link`() {
val browsingModeManager: DefaultBrowsingModeManager = mockk(relaxed = true)
every { activity.components.browsingModeManager } returns browsingModeManager
assertTrue(processor.process(testIntent("fenix://enable_private_browsing"), navController, out))
verify { activity.browsingModeManager.mode = BrowsingMode.Private }
verify { browsingModeManager.mode = BrowsingMode.Private }
verify { navController.navigate(NavGraphDirections.actionGlobalHomeFragment()) }
verify { out wasNot Called }
}
......
......@@ -109,16 +109,16 @@ class BookmarkControllerTest {
@Test
fun `handleBookmarkTapped should respect browsing mode`() {
// if in normal mode, should be in normal mode
every { homeActivity.browsingModeManager.mode } returns BrowsingMode.Normal
every { context.components.browsingModeManager.mode } returns BrowsingMode.Normal
controller.handleBookmarkTapped(item)
assertEquals(BrowsingMode.Normal, homeActivity.browsingModeManager.mode)
assertEquals(BrowsingMode.Normal, context.components.browsingModeManager.mode)
// if in private mode, should be in private mode
every { homeActivity.browsingModeManager.mode } returns BrowsingMode.Private
every { context.components.browsingModeManager.mode } returns BrowsingMode.Private
controller.handleBookmarkTapped(item)
assertEquals(BrowsingMode.Private, homeActivity.browsingModeManager.mode)
assertEquals(BrowsingMode.Private, context.components.browsingModeManager.mode)
}
@Test
......@@ -204,7 +204,7 @@ class BookmarkControllerTest {
verifyOrder {
invokePendingDeletion.invoke()
homeActivity.browsingModeManager.mode = BrowsingMode.Normal
homeActivity.components.browsingModeManager.mode = BrowsingMode.Normal
homeActivity.openToBrowserAndLoad(item.url!!, true, BrowserDirection.FromBookmarks)
}
}
......@@ -215,7 +215,7 @@ class BookmarkControllerTest {
verifyOrder {
invokePendingDeletion.invoke()
homeActivity.browsingModeManager.mode = BrowsingMode.Private
homeActivity.components.browsingModeManager.mode = BrowsingMode.Private
homeActivity.openToBrowserAndLoad(item.url!!, true, BrowserDirection.FromBookmarks)
}
}
......
......@@ -24,8 +24,10 @@ import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.FenixApplication
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.TestApplication
import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.searchengine.CustomSearchEngineStore.PREF_FILE_SEARCH_ENGINES
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.metrics
import org.mozilla.fenix.ext.searchEngineManager
import org.mozilla.fenix.ext.settings
......@@ -108,6 +110,9 @@ class SearchInteractorTest {
val context: HomeActivity = mockk(relaxed = true)
val settings = testContext.settings().apply { testContext.settings().clear() }
val browsingModeManager: DefaultBrowsingModeManager = mockk(relaxed = true)
every { context.components.browsingModeManager } returns browsingModeManager
mockkObject(Settings)
every { Settings.getInstance(context = context) } returns settings
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment