diff --git a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt index 154dfc996..13ca500bd 100644 --- a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt +++ b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -129,6 +129,10 @@ open class FenixApplication : LocaleAwareApplication(), Provider { private val logger = Logger("FenixApplication") + internal val isDeviceRamAboveThreshold by lazy { + isDeviceRamAboveThreshold() + } + open val components by lazy { Components(this) } var visibilityLifecycleCallback: VisibilityLifecycleCallback? = null @@ -698,7 +702,6 @@ open class FenixApplication : LocaleAwareApplication(), Provider { settings: Settings, browsersCache: BrowsersCache = BrowsersCache, mozillaProductDetector: MozillaProductDetector = MozillaProductDetector, - isDeviceRamAboveThreshold: Boolean = isDeviceRamAboveThreshold(), ) { setPreferenceMetrics(settings) with(Metrics) { diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 5bb405819..a56ff7b48 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -949,6 +949,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { * value of [searchTermOrURL]). * * @param flags Flags that will be used when loading the URL (not applied to searches). + * @param additionalHeaders The extra headers to use when loading the URL. */ @Suppress("LongParameterList") fun openToBrowserAndLoad( @@ -961,9 +962,19 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none(), requestDesktopMode: Boolean = false, historyMetadata: HistoryMetadataKey? = null, + additionalHeaders: Map? = null, ) { openToBrowser(from, customTabSessionId) - load(searchTermOrURL, newTab, engine, forceSearch, flags, requestDesktopMode, historyMetadata) + load( + searchTermOrURL = searchTermOrURL, + newTab = newTab, + engine = engine, + forceSearch = forceSearch, + flags = flags, + requestDesktopMode = requestDesktopMode, + historyMetadata = historyMetadata, + additionalHeaders = additionalHeaders, + ) } fun openToBrowser(from: BrowserDirection, customTabSessionId: String? = null) { @@ -1042,6 +1053,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { * @param flags Flags that will be used when loading the URL (not applied to searches). * @param historyMetadata The [HistoryMetadataKey] of the new tab in case this tab * was opened from history. + * @param additionalHeaders The extra headers to use when loading the URL. */ private fun load( searchTermOrURL: String, @@ -1051,6 +1063,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none(), requestDesktopMode: Boolean = false, historyMetadata: HistoryMetadataKey? = null, + additionalHeaders: Map? = null, ) { val startTime = components.core.engine.profiler?.getProfilerTime() val mode = browsingModeManager.mode @@ -1090,13 +1103,20 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { components.useCases.searchUseCases.newTabSearch } searchUseCase.invoke( - searchTermOrURL, - SessionState.Source.Internal.UserEntered, - true, + searchTerms = searchTermOrURL, + source = SessionState.Source.Internal.UserEntered, + selected = true, searchEngine = engine, + flags = flags, + additionalHeaders = additionalHeaders, ) } else { - components.useCases.searchUseCases.defaultSearch.invoke(searchTermOrURL, engine) + components.useCases.searchUseCases.defaultSearch.invoke( + searchTerms = searchTermOrURL, + searchEngine = engine, + flags = flags, + additionalHeaders = additionalHeaders, + ) } } diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt index 89018d378..9590d9b75 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt @@ -28,9 +28,11 @@ import org.mozilla.fenix.R import org.mozilla.fenix.components.Core import org.mozilla.fenix.components.metrics.MetricsUtils import org.mozilla.fenix.crashes.CrashListActivity +import org.mozilla.fenix.ext.application import org.mozilla.fenix.ext.navigateSafe import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.telemetryName +import org.mozilla.fenix.search.awesomebar.AwesomeBarView.Companion.GOOGLE_SEARCH_ENGINE_NAME import org.mozilla.fenix.search.toolbar.SearchSelectorInteractor import org.mozilla.fenix.search.toolbar.SearchSelectorMenu import org.mozilla.fenix.settings.SupportUtils @@ -109,6 +111,12 @@ class SearchDialogController( val searchEngine = fragmentStore.state.searchEngineSource.searchEngine val isDefaultEngine = searchEngine == fragmentStore.state.defaultEngine + val additionalHeaders = getAdditionalHeaders(searchEngine) + val flags = if (additionalHeaders.isNullOrEmpty()) { + LoadUrlFlags.none() + } else { + LoadUrlFlags.select(LoadUrlFlags.ALLOW_ADDITIONAL_HEADERS) + } activity.openToBrowserAndLoad( searchTermOrURL = url, @@ -116,7 +124,9 @@ class SearchDialogController( from = BrowserDirection.FromSearchDialog, engine = searchEngine, forceSearch = !isDefaultEngine, + flags = flags, requestDesktopMode = fromHomeScreen && activity.settings().openNextTabInDesktopMode, + additionalHeaders = additionalHeaders, ) if (url.isUrl() || searchEngine == null) { @@ -180,6 +190,12 @@ class SearchDialogController( clearToolbarFocus() val searchEngine = fragmentStore.state.searchEngineSource.searchEngine + val additionalHeaders = getAdditionalHeaders(searchEngine) + val flags = if (additionalHeaders.isNullOrEmpty()) { + LoadUrlFlags.none() + } else { + LoadUrlFlags.select(LoadUrlFlags.ALLOW_ADDITIONAL_HEADERS) + } activity.openToBrowserAndLoad( searchTermOrURL = searchTerms, @@ -187,6 +203,8 @@ class SearchDialogController( from = BrowserDirection.FromSearchDialog, engine = searchEngine, forceSearch = true, + flags = flags, + additionalHeaders = additionalHeaders, ) val searchAccessPoint = when (fragmentStore.state.searchAccessPoint) { @@ -322,4 +340,20 @@ class SearchDialogController( create().withCenterAlignedButtons() } } + + private fun getAdditionalHeaders(searchEngine: SearchEngine?): Map? { + if (searchEngine?.name != GOOGLE_SEARCH_ENGINE_NAME) { + return null + } + + val value = if (activity.applicationContext.application.isDeviceRamAboveThreshold) { + "1" + } else { + "0" + } + + return mapOf( + "X-Search-Subdivision" to value, + ) + } } diff --git a/app/src/test/java/org/mozilla/fenix/FenixApplicationTest.kt b/app/src/test/java/org/mozilla/fenix/FenixApplicationTest.kt index 984546cc3..d30adaa4e 100644 --- a/app/src/test/java/org/mozilla/fenix/FenixApplicationTest.kt +++ b/app/src/test/java/org/mozilla/fenix/FenixApplicationTest.kt @@ -144,6 +144,7 @@ class FenixApplicationTest { every { settings.showContileFeature } returns true every { application.reportHomeScreenMetrics(settings) } just Runs every { settings.inactiveTabsAreEnabled } returns true + every { application.isDeviceRamAboveThreshold } returns true assertTrue(settings.contileContextId.isEmpty()) assertNull(TopSites.contextId.testGetValue()) @@ -153,7 +154,6 @@ class FenixApplicationTest { settings = settings, browsersCache = browsersCache, mozillaProductDetector = mozillaProductDetector, - isDeviceRamAboveThreshold = true, ) // Verify that browser defaults metrics are set. diff --git a/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt b/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt index 481220799..1bdd24e80 100644 --- a/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt @@ -48,9 +48,11 @@ import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.Core import org.mozilla.fenix.components.metrics.MetricsUtils +import org.mozilla.fenix.ext.application import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.search.SearchDialogFragmentDirections.Companion.actionGlobalAddonsManagementFragment import org.mozilla.fenix.search.SearchDialogFragmentDirections.Companion.actionGlobalSearchEngineFragment +import org.mozilla.fenix.search.awesomebar.AwesomeBarView.Companion.GOOGLE_SEARCH_ENGINE_NAME import org.mozilla.fenix.search.toolbar.SearchSelectorMenu import org.mozilla.fenix.settings.SupportUtils import org.mozilla.fenix.utils.Settings @@ -88,6 +90,7 @@ class SearchDialogControllerTest { ) every { store.state.tabId } returns "test-tab-id" every { store.state.searchEngineSource.searchEngine } returns searchEngine + every { searchEngine.name } returns "" every { searchEngine.type } returns SearchEngine.Type.BUNDLED every { navController.currentDestination } returns mockk { every { id } returns R.id.searchDialogFragment @@ -116,6 +119,8 @@ class SearchDialogControllerTest { from = BrowserDirection.FromSearchDialog, engine = searchEngine, forceSearch = false, + flags = EngineSession.LoadUrlFlags.none(), + additionalHeaders = null, ) } @@ -141,6 +146,8 @@ class SearchDialogControllerTest { from = BrowserDirection.FromSearchDialog, engine = searchEngine, forceSearch = true, + flags = EngineSession.LoadUrlFlags.none(), + additionalHeaders = null, ) } @@ -150,6 +157,58 @@ class SearchDialogControllerTest { assertEquals("false", snapshot.single().extra?.getValue("autocomplete")) } + @Test + fun `GIVEN Google search engine is selected and device ram is above threshold WHEN url is committed THEN perform search`() { + val searchTerm = "coffee" + assertNull(Events.enteredUrl.testGetValue()) + + every { searchEngine.name } returns GOOGLE_SEARCH_ENGINE_NAME + every { store.state.defaultEngine } returns searchEngine + every { activity.applicationContext.application.isDeviceRamAboveThreshold } returns true + + createController().handleUrlCommitted(searchTerm) + + verify { + activity.openToBrowserAndLoad( + searchTermOrURL = searchTerm, + newTab = false, + from = BrowserDirection.FromSearchDialog, + engine = searchEngine, + forceSearch = false, + flags = EngineSession.LoadUrlFlags.select(EngineSession.LoadUrlFlags.ALLOW_ADDITIONAL_HEADERS), + additionalHeaders = mapOf( + "X-Search-Subdivision" to "1", + ), + ) + } + } + + @Test + fun `GIVEN Google search engine is selected and device ram is below threshold WHEN url is committed THEN perform search`() { + val searchTerm = "coffee" + assertNull(Events.enteredUrl.testGetValue()) + + every { searchEngine.name } returns GOOGLE_SEARCH_ENGINE_NAME + every { store.state.defaultEngine } returns searchEngine + every { activity.applicationContext.application.isDeviceRamAboveThreshold } returns false + + createController().handleUrlCommitted(searchTerm) + + verify { + activity.openToBrowserAndLoad( + searchTermOrURL = searchTerm, + newTab = false, + from = BrowserDirection.FromSearchDialog, + engine = searchEngine, + forceSearch = false, + flags = EngineSession.LoadUrlFlags.select(EngineSession.LoadUrlFlags.ALLOW_ADDITIONAL_HEADERS), + additionalHeaders = mapOf( + "X-Search-Subdivision" to "0", + ), + ) + } + } + @Test fun handleBlankUrlCommitted() { val url = "" @@ -177,6 +236,8 @@ class SearchDialogControllerTest { from = BrowserDirection.FromSearchDialog, engine = searchEngine, forceSearch = true, + flags = EngineSession.LoadUrlFlags.none(), + additionalHeaders = null, ) } } @@ -243,6 +304,8 @@ class SearchDialogControllerTest { newTab = false, from = BrowserDirection.FromSearchDialog, engine = searchEngine, + flags = EngineSession.LoadUrlFlags.none(), + additionalHeaders = null, ) } @@ -400,6 +463,8 @@ class SearchDialogControllerTest { from = BrowserDirection.FromSearchDialog, engine = searchEngine, forceSearch = true, + flags = EngineSession.LoadUrlFlags.none(), + additionalHeaders = null, ) } }