diff --git a/.github/ISSUE_TEMPLATE/---performance-issue.md b/.github/ISSUE_TEMPLATE/---performance-issue.md new file mode 100644 index 000000000..5412b9998 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---performance-issue.md @@ -0,0 +1,19 @@ +--- +name: "⌛ Performance issue" +about: Create a performance issue if the app is slow or it uses too much memory, disk space, battery, or network data +title: "" +labels: "eng:performance" +assignees: '' + +--- + +## Steps to reproduce + +### Expected behavior + +### Actual behavior + +### Device information + +* Android device: ? +* Fenix version: ? diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt index 011eee7d7..c1b65d5f2 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt @@ -11,7 +11,6 @@ import mozilla.components.browser.storage.sync.PlacesHistoryStorage import okhttp3.mockwebserver.MockWebServer import org.junit.After import org.junit.Before -import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.mozilla.fenix.helpers.AndroidAssetDispatcher @@ -165,7 +164,6 @@ class HistoryTest { } } - @Ignore("Failing test: https://github.com/mozilla-mobile/fenix/issues/12893") @Test fun deleteAllHistoryTest() { val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt index 964f65d45..5d6732cce 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt @@ -44,12 +44,6 @@ import org.mozilla.fenix.helpers.click import org.mozilla.fenix.helpers.ext.waitNotNull class BrowserRobot { - - fun verifyBrowserScreen() { - onView(ViewMatchers.withResourceName("browserLayout")) - .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) - } - fun verifyCurrentPrivateSession(context: Context) { val session = context.components.core.sessionManager.selectedSession assertTrue("Current session is private", session?.private!!) @@ -84,6 +78,10 @@ class BrowserRobot { */ fun verifyPageContent(expectedText: String) { + mDevice.waitNotNull( + Until.findObject(By.res("org.mozilla.fenix.debug:id/engineView")), + waitingTime + ) assertTrue(mDevice.findObject(UiSelector().text(expectedText)).waitForExists(waitingTime)) } @@ -145,7 +143,8 @@ class BrowserRobot { fun verifyEnhancedTrackingProtectionSwitch() = assertEnhancedTrackingProtectionSwitch() - fun clickEnhancedTrackingProtectionSwitchOffOn() = onView(withResourceName("switch_widget")).click() + fun clickEnhancedTrackingProtectionSwitchOffOn() = + onView(withResourceName("switch_widget")).click() fun verifyProtectionSettingsButton() = assertProtectionSettingsButton() @@ -191,7 +190,8 @@ class BrowserRobot { fun clickEnhancedTrackingProtectionPanel() = enhancedTrackingProtectionPanel().click() - fun verifyEnhancedTrackingProtectionPanelNotVisible() = assertEnhancedTrackingProtectionPanelNotVisible() + fun verifyEnhancedTrackingProtectionPanelNotVisible() = + assertEnhancedTrackingProtectionPanelNotVisible() fun clickContextOpenLinkInNewTab() { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) @@ -423,7 +423,8 @@ fun navURLBar() = onView(withId(R.id.mozac_browser_toolbar_url_view)) private fun assertNavURLBar() = navURLBar() .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -fun enhancedTrackingProtectionPanel() = onView(withId(R.id.mozac_browser_toolbar_tracking_protection_indicator)) +fun enhancedTrackingProtectionPanel() = + onView(withId(R.id.mozac_browser_toolbar_tracking_protection_indicator)) private fun assertEnhancedTrackingProtectionPanelNotVisible() { enhancedTrackingProtectionPanel() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HistoryRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HistoryRobot.kt index 2debc3999..85cfd7fe9 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HistoryRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HistoryRobot.kt @@ -15,6 +15,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withParent import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.uiautomator.By +import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import org.hamcrest.Matchers import org.hamcrest.Matchers.allOf @@ -31,12 +32,10 @@ class HistoryRobot { fun verifyHistoryMenuView() = assertHistoryMenuView() fun verifyEmptyHistoryView() { - mDevice.waitNotNull( - Until.findObject( - By.text("No history here") - ), - waitingTime - ) + mDevice.findObject( + UiSelector().text("No history here") + ).waitForExists(waitingTime) + assertEmptyHistoryView() } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c2dbb8fbe..dedb00946 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -282,6 +282,9 @@ + () private val swipeRefreshFeature = ViewBoundFeatureWrapper() private val webchannelIntegration = ViewBoundFeatureWrapper() - private val sitePermissionWifiIntegration = ViewBoundFeatureWrapper() + private val sitePermissionWifiIntegration = + ViewBoundFeatureWrapper() private val secureWindowFeature = ViewBoundFeatureWrapper() - private var fullScreenMediaFeature = ViewBoundFeatureWrapper() + private var fullScreenMediaFeature = + ViewBoundFeatureWrapper() private var pipFeature: PictureInPictureFeature? = null var customTabSessionId: String? = null @@ -202,7 +204,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session engineView = WeakReference(engineView), swipeRefresh = WeakReference(swipeRefresh), viewLifecycleScope = WeakReference(viewLifecycleOwner.lifecycleScope), - arguments = requireArguments() + arguments = requireArguments(), + firstContentfulHappened = ::didFirstContentfulHappen ).apply { beginAnimateInIfNecessary() } @@ -412,8 +415,10 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session } } - resumeDownloadDialogState(sessionManager.selectedSession?.id, - store, view, context, toolbarHeight) + resumeDownloadDialogState( + sessionManager.selectedSession?.id, + store, view, context, toolbarHeight + ) downloadsFeature.set( downloadFeature, @@ -506,7 +511,11 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session onNeedToRequestPermissions = { permissions -> requestPermissions(permissions, REQUEST_CODE_APP_PERMISSIONS) }, - onShouldShowRequestPermissionRationale = { shouldShowRequestPermissionRationale(it) }), + onShouldShowRequestPermissionRationale = { + shouldShowRequestPermissionRationale( + it + ) + }), owner = this, view = view ) @@ -568,6 +577,21 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session .collect { tab -> pipModeChanged(tab) } } + if (context.settings().waitToShowPageUntilFirstPaint) { + store.flowScoped(viewLifecycleOwner) { flow -> + flow.mapNotNull { state -> + state.findTabOrCustomTabOrSelectedTab( + customTabSessionId + ) + } + .ifChanged { it.content.firstContentfulPaint } + .collect { + engineView?.asView()?.isVisible = + it.content.firstContentfulPaint || it.content.progress == 100 + } + } + } + @Suppress("ConstantConditionIf") if (FeatureFlags.pullToRefreshEnabled) { val primaryTextColor = @@ -687,7 +711,12 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session val context = requireContext() val behavior = when (context.settings().toolbarPosition) { ToolbarPosition.BOTTOM -> EngineViewBottomBehavior(context, null) - ToolbarPosition.TOP -> SwipeRefreshScrollingViewBehavior(context, null, engineView, browserToolbarView) + ToolbarPosition.TOP -> SwipeRefreshScrollingViewBehavior( + context, + null, + engineView, + browserToolbarView + ) } (swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams).behavior = behavior @@ -751,12 +780,13 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session super.onStop() initUIJob?.cancel() - requireComponents.core.store.state.findTabOrCustomTabOrSelectedTab(customTabSessionId)?.let { session -> - // If we didn't enter PiP, exit full screen on stop - if (!session.content.pictureInPictureEnabled && fullScreenFeature.onBackPressed()) { - fullScreenChanged(false) + requireComponents.core.store.state.findTabOrCustomTabOrSelectedTab(customTabSessionId) + ?.let { session -> + // If we didn't enter PiP, exit full screen on stop + if (!session.content.pictureInPictureEnabled && fullScreenFeature.onBackPressed()) { + fullScreenChanged(false) + } } - } } @CallSuper @@ -950,7 +980,10 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session .setAction(getString(R.string.edit_bookmark_snackbar_action)) { nav( R.id.browserFragment, - BrowserFragmentDirections.actionGlobalBookmarkEditFragment(guid, true) + BrowserFragmentDirections.actionGlobalBookmarkEditFragment( + guid, + true + ) ) } .show() @@ -988,10 +1021,10 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session // Close find in page bar if opened findInPageIntegration.onBackPressed() FenixSnackbar.make( - view = requireView().browserLayout, - duration = Snackbar.LENGTH_SHORT, - isDisplayedWithBrowserToolbar = false - ) + view = requireView().browserLayout, + duration = Snackbar.LENGTH_SHORT, + isDisplayedWithBrowserToolbar = false + ) .setText(getString(R.string.full_screen_notification)) .show() activity?.enterToImmersiveMode() @@ -1014,6 +1047,12 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session } } + private fun didFirstContentfulHappen() = + if (!requireContext().settings().waitToShowPageUntilFirstPaint) true else + context?.components?.core?.store?.state?.findTabOrCustomTabOrSelectedTab( + customTabSessionId + )?.content?.firstContentfulPaint ?: false + /* * Dereference these views when the fragment view is destroyed to prevent memory leaks */ diff --git a/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt b/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt index 02a94f2d1..c79c53a54 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt @@ -34,7 +34,8 @@ class BrowserAnimator( private val engineView: WeakReference, private val swipeRefresh: WeakReference, private val viewLifecycleScope: WeakReference, - private val arguments: Bundle + private val arguments: Bundle, + private val firstContentfulHappened: () -> Boolean ) { private val unwrappedEngineView: EngineView? @@ -53,22 +54,9 @@ class BrowserAnimator( } doOnEnd { - unwrappedEngineView?.asView()?.visibility = View.VISIBLE - unwrappedSwipeRefresh?.background = null - arguments.putBoolean(SHOULD_ANIMATE_FLAG, false) - } - - interpolator = DecelerateInterpolator() - duration = ANIMATION_DURATION - } - - private val browserFadeInValueAnimator = ValueAnimator.ofFloat(0f, END_ANIMATOR_VALUE).apply { - addUpdateListener { - unwrappedSwipeRefresh?.alpha = it.animatedFraction - } - - doOnEnd { - unwrappedEngineView?.asView()?.visibility = View.VISIBLE + if (firstContentfulHappened()) { + unwrappedEngineView?.asView()?.visibility = View.VISIBLE + } unwrappedSwipeRefresh?.background = null arguments.putBoolean(SHOULD_ANIMATE_FLAG, false) } @@ -93,20 +81,10 @@ class BrowserAnimator( } } else { unwrappedSwipeRefresh?.alpha = 1f - unwrappedEngineView?.asView()?.visibility = View.VISIBLE - unwrappedSwipeRefresh?.background = null - } - } - - /** - * Triggers the *zoom out* browser animation to run. - */ - fun beginAnimateOut() { - viewLifecycleScope.get()?.launch(Dispatchers.Main) { - captureEngineViewAndDrawStatically { - unwrappedEngineView?.asView()?.visibility = View.GONE - browserZoomInValueAnimator.reverse() + if (firstContentfulHappened()) { + unwrappedEngineView?.asView()?.visibility = View.VISIBLE } + unwrappedSwipeRefresh?.background = null } } diff --git a/app/src/main/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactory.kt b/app/src/main/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactory.kt index 16a68787d..d101c16d1 100644 --- a/app/src/main/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactory.kt +++ b/app/src/main/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactory.kt @@ -24,7 +24,7 @@ class TrackingProtectionPolicyFactory(private val settings: Settings) { @Suppress("ComplexMethod") fun createTrackingProtectionPolicy( normalMode: Boolean = settings.shouldUseTrackingProtection, - privateMode: Boolean = true + privateMode: Boolean = settings.shouldUseTrackingProtection ): TrackingProtectionPolicy { val trackingProtectionPolicy = when { diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/LeanplumMetricsService.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/LeanplumMetricsService.kt index aa8f712c9..4d9ca393e 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/LeanplumMetricsService.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/LeanplumMetricsService.kt @@ -5,7 +5,9 @@ package org.mozilla.fenix.components.metrics import android.app.Application +import android.content.Context.MODE_PRIVATE import android.util.Log +import androidx.annotation.VisibleForTesting import com.leanplum.Leanplum import com.leanplum.LeanplumActivityHelper import com.leanplum.annotations.Parser @@ -34,7 +36,9 @@ private val Event.name: String? is Event.InteractWithSearchURLArea -> "E_Interact_With_Search_URL_Area" is Event.CollectionSaved -> "E_Collection_Created" is Event.CollectionTabRestored -> "E_Collection_Tab_Opened" - is Event.SyncAuthSignIn -> "E_Sign_In_FxA" + is Event.SyncAuthSignUp -> "E_FxA_New_Signup" + is Event.SyncAuthSignIn, Event.SyncAuthPaired, Event.SyncAuthOtherExternal -> "E_Sign_In_FxA" + is Event.SyncAuthFromShared -> "E_Sign_In_FxA_Fennec_to_Fenix" is Event.SyncAuthSignOut -> "E_Sign_Out_FxA" is Event.ClearedPrivateData -> "E_Cleared_Private_Data" is Event.DismissedOnboarding -> "E_Dismissed_Onboarding" @@ -48,7 +52,10 @@ private val Event.name: String? else -> null } -class LeanplumMetricsService(private val application: Application) : MetricsService { +class LeanplumMetricsService( + private val application: Application, + private val deviceIdGenerator: () -> String = { randomUUID().toString() } +) : MetricsService { val scope = CoroutineScope(Dispatchers.IO) var leanplumJob: Job? = null @@ -72,13 +79,27 @@ class LeanplumMetricsService(private val application: Application) : MetricsServ override val type = MetricServiceType.Marketing private val token = Token(LeanplumId, LeanplumToken) + private val preferences = application.getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE) + + @VisibleForTesting + internal val deviceId by lazy { + var deviceId = preferences.getString(DEVICE_ID_KEY, null) + + if (deviceId == null) { + deviceId = deviceIdGenerator.invoke() + preferences.edit().putString(DEVICE_ID_KEY, deviceId).apply() + } + + deviceId + } + override fun start() { if (!application.settings().isMarketingTelemetryEnabled) return Leanplum.setIsTestModeEnabled(false) Leanplum.setApplicationContext(application) - Leanplum.setDeviceId(randomUUID().toString()) + Leanplum.setDeviceId(deviceId) Parser.parseVariables(application) leanplumJob = scope.launch { @@ -87,13 +108,13 @@ class LeanplumMetricsService(private val application: Application) : MetricsServ val currentLocale = applicationSetLocale ?: Locale.getDefault() val languageCode = currentLocale.iso3LanguageOrNull - ?: currentLocale.language.let { - if (it.isNotBlank()) { - it - } else { - currentLocale.toString() + ?: currentLocale.language.let { + if (it.isNotBlank()) { + it + } else { + currentLocale.toString() + } } - } if (!isLeanplumEnabled(languageCode)) { Log.i(LOGTAG, "Leanplum is not available for this locale: $languageCode") @@ -122,18 +143,21 @@ class LeanplumMetricsService(private val application: Application) : MetricsServ } } - Leanplum.start(application, hashMapOf( - "default_browser" to MozillaProductDetector.getMozillaBrowserDefault(application).orEmpty(), - "fennec_installed" to installedApps.contains(MozillaProducts.FIREFOX.productName), - "focus_installed" to installedApps.contains(MozillaProducts.FOCUS.productName), - "klar_installed" to installedApps.contains(MozillaProducts.KLAR.productName), - "fxa_signed_in" to application.settings().fxaSignedIn, - "fxa_has_synced_items" to application.settings().fxaHasSyncedItems, - "search_widget_installed" to application.settings().searchWidgetInstalled, - "tracking_protection_enabled" to application.settings().shouldUseTrackingProtection, - "tracking_protection_setting" to trackingProtection, - "fenix" to true - )) + Leanplum.start( + application, hashMapOf( + "default_browser" to MozillaProductDetector.getMozillaBrowserDefault(application) + .orEmpty(), + "fennec_installed" to installedApps.contains(MozillaProducts.FIREFOX.productName), + "focus_installed" to installedApps.contains(MozillaProducts.FOCUS.productName), + "klar_installed" to installedApps.contains(MozillaProducts.KLAR.productName), + "fxa_signed_in" to application.settings().fxaSignedIn, + "fxa_has_synced_items" to application.settings().fxaHasSyncedItems, + "search_widget_installed" to application.settings().searchWidgetInstalled, + "tracking_protection_enabled" to application.settings().shouldUseTrackingProtection, + "tracking_protection_setting" to trackingProtection, + "fenix" to true + ) + ) withContext(Main) { LeanplumInternal.setCalledStart(true) @@ -182,7 +206,9 @@ class LeanplumMetricsService(private val application: Application) : MetricsServ get() = try { this.isO3Language - } catch (_: MissingResourceException) { null } + } catch (_: MissingResourceException) { + null + } companion object { private const val LOGTAG = "LeanplumMetricsService" @@ -193,6 +219,7 @@ class LeanplumMetricsService(private val application: Application) : MetricsServ private val LeanplumToken: String // Debug builds have a null (nullable) LEANPLUM_TOKEN get() = BuildConfig.LEANPLUM_TOKEN.orEmpty() + // Leanplum needs to be enabled for the following locales. // Irrespective of the actual device location. private val LEANPLUM_ENABLED_LOCALES = setOf( @@ -212,5 +239,8 @@ class LeanplumMetricsService(private val application: Application) : MetricsServ "ara", // Arabic "jpn" // Japanese ) + + private val PREFERENCE_NAME = "LEANPLUM_PREFERENCES" + private val DEVICE_ID_KEY = "LP_DEVICE_ID" } } diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt index e1a9df5fe..6b1bf2316 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt @@ -251,10 +251,10 @@ class BrowserToolbarView( } private fun ToolbarMenu.Item.performHapticIfNeeded(view: View) { - (this as? ToolbarMenu.Item.Reload)?.also { reload -> - if (reload.bypassCache) { - view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) - } + if (this is ToolbarMenu.Item.Reload && this.bypassCache || + this is ToolbarMenu.Item.Forward && this.viewHistory + ) { + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) } } } 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 7f6aebfa7..822888852 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -673,9 +673,13 @@ class HomeFragment : Fragment() { } private fun navigateToSearch() { - val directions = HomeFragmentDirections.actionGlobalSearch( - sessionId = null - ) + val directions = if (requireContext().settings().useNewSearchExperience) { + HomeFragmentDirections.actionGlobalSearchDialog() + } else { + HomeFragmentDirections.actionGlobalSearch( + sessionId = null + ) + } nav(R.id.homeFragment, directions, getToolbarNavOptions(requireContext())) } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingTrackingProtectionViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingTrackingProtectionViewHolder.kt index eee57c745..9d2e00013 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingTrackingProtectionViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingTrackingProtectionViewHolder.kt @@ -77,8 +77,7 @@ class OnboardingTrackingProtectionViewHolder(view: View) : RecyclerView.ViewHold private fun updateTrackingProtectionSetting(enabled: Boolean) { itemView.context.settings().shouldUseTrackingProtection = enabled with(itemView.context.components) { - val policy = core.trackingProtectionPolicyFactory - .createTrackingProtectionPolicy(enabled) + val policy = core.trackingProtectionPolicyFactory.createTrackingProtectionPolicy() useCases.settingsUseCases.updateTrackingProtection.invoke(policy) useCases.sessionUseCases.reload.invoke() } diff --git a/app/src/main/java/org/mozilla/fenix/searchdialog/SearchDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/searchdialog/SearchDialogFragment.kt new file mode 100644 index 000000000..a8a97cc32 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/searchdialog/SearchDialogFragment.kt @@ -0,0 +1,20 @@ +/* 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.searchdialog + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatDialogFragment +import org.mozilla.fenix.R + +class SearchDialogFragment : AppCompatDialogFragment() { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? = inflater.inflate(R.layout.fragment_search_dialog, container, false) +} diff --git a/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt index 6e128b7fe..c3e663104 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt @@ -6,7 +6,10 @@ package org.mozilla.fenix.settings import android.os.Bundle import androidx.preference.PreferenceFragmentCompat +import androidx.preference.SwitchPreference +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R +import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar /** @@ -21,5 +24,17 @@ class SecretSettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.secret_settings_preferences, rootKey) + + requirePreference(R.string.pref_key_use_new_search_experience).apply { + isVisible = FeatureFlags.newSearchExperience + isChecked = context.settings().useNewSearchExperience + onPreferenceChangeListener = SharedPreferenceUpdater() + } + + requirePreference(R.string.pref_key_wait_first_paint).apply { + isVisible = FeatureFlags.waitUntilPaintToDraw + isChecked = context.settings().waitToShowPageUntilFirstPaint + onPreferenceChangeListener = SharedPreferenceUpdater() + } } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt index e984b0013..029183ac5 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt @@ -64,8 +64,7 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() { preference.context.settings().shouldUseTrackingProtection = trackingProtectionOn with(preference.context.components) { - val policy = core.trackingProtectionPolicyFactory - .createTrackingProtectionPolicy(trackingProtectionOn) + val policy = core.trackingProtectionPolicyFactory.createTrackingProtectionPolicy() useCases.settingsUseCases.updateTrackingProtection(policy) useCases.sessionUseCases.reload() } diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt index 841a6717a..005a8b8fe 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt @@ -43,11 +43,6 @@ class ShareFragment : AppCompatDialogFragment() { viewModel.loadDevicesAndApps() } - override fun dismiss() { - consumePrompt { onDismiss() } - super.dismiss() - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, R.style.ShareDialogStyle) @@ -55,6 +50,7 @@ class ShareFragment : AppCompatDialogFragment() { override fun onPause() { super.onPause() + consumePrompt { onDismiss() } dismiss() } diff --git a/app/src/main/java/org/mozilla/fenix/utils/FeatureFlagPreference.kt b/app/src/main/java/org/mozilla/fenix/utils/FeatureFlagPreference.kt new file mode 100644 index 000000000..51c46e657 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/utils/FeatureFlagPreference.kt @@ -0,0 +1,25 @@ +/* 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.utils + +import mozilla.components.support.ktx.android.content.PreferencesHolder +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +fun featureFlagPreference(key: String, default: Boolean, featureFlag: Boolean): ReadWriteProperty = + FeatureFlagPreferencePreference(key, default, featureFlag) + +private class FeatureFlagPreferencePreference( + private val key: String, + private val default: Boolean, + private val featureFlag: Boolean +) : ReadWriteProperty { + + override fun getValue(thisRef: PreferencesHolder, property: KProperty<*>): Boolean = + featureFlag && thisRef.preferences.getBoolean(key, default) + + override fun setValue(thisRef: PreferencesHolder, property: KProperty<*>, value: Boolean) = + thisRef.preferences.edit().putBoolean(key, value).apply() +} diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index 910a73035..8ab5be5ec 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -26,6 +26,7 @@ import mozilla.components.support.ktx.android.content.longPreference import mozilla.components.support.ktx.android.content.stringPreference import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.Config +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.metrics.MozillaProductDetector @@ -96,6 +97,18 @@ class Settings(private val appContext: Context) : PreferencesHolder { override val preferences: SharedPreferences = appContext.getSharedPreferences(FENIX_PREFERENCES, MODE_PRIVATE) + var useNewSearchExperience by featureFlagPreference( + appContext.getPreferenceKey(R.string.pref_key_use_new_search_experience), + default = false, + featureFlag = FeatureFlags.newSearchExperience + ) + + var waitToShowPageUntilFirstPaint by featureFlagPreference( + appContext.getPreferenceKey(R.string.pref_key_wait_first_paint), + default = false, + featureFlag = FeatureFlags.waitUntilPaintToDraw + ) + var forceEnableZoom by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_accessibility_force_enable_zoom), default = false diff --git a/app/src/main/res/layout/fragment_search_dialog.xml b/app/src/main/res/layout/fragment_search_dialog.xml new file mode 100644 index 000000000..10c211752 --- /dev/null +++ b/app/src/main/res/layout/fragment_search_dialog.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 55249ba73..6d0b2265b 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -27,6 +27,10 @@ android:id="@+id/action_global_search" app:destination="@id/searchFragment" /> + + @@ -137,6 +141,11 @@ app:nullable="true" /> + + %1$s llingüetes abiertes. Toca pa cambiar a otra. + + Nome + %1$s ta producíu por Mozilla. @@ -142,12 +145,12 @@ Escaniar - - Atayos + + Motor de gueta Axustes de los motores de gueta - Y agora gueta con: + Y agora gueta con: Rellenar col enllaz del cartafueyu @@ -251,8 +254,6 @@ Ferramientes pa desendolcadores Depuración remota per USB - - Amosar los atayos de gueta Amosar les suxerencies de gueta @@ -558,7 +559,7 @@ Desanicióse %1$s - + Desaniciáronse los marcadores DESFACER @@ -734,6 +735,10 @@ ÑEGAR ¿De xuru que quies desaniciar %1$s? + + Desaniciar esta llingüeta va desaniciar tola coleición. Pues crear coleiciones nueves en cualesquier momentu. + + ¿Desaniciar %1$s? Desaniciar @@ -1319,9 +1324,6 @@ Yá esiste un aniciu de sesión con esi nome d\'usuariu - - - Coneuta con una cuenta de Firefox. Volvi autenticate, por favor. diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index a828debb0..017095b7c 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -34,8 +34,18 @@ Název Vybrat sbírku + + Opustit režim výběru Uložit vybrané panely do sbírky + + Panel %1$s byl vybrán + + Výběr panelu %1$s zrušen + + Režim výběru ukončen + + Vstoupili jste do režimu výběru panelů pro jejich uložení do sbírky Vybráno @@ -1268,6 +1278,8 @@ Tady se zobrazí přihlašovací údaje, které se nebudou ukládat. Pro následující servery se nebudou přihlašovací údaje ukládat. + + Odebrat všechny výjimky Hledat přihlašovací údaje diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 7ee372f8e..c9f4f23aa 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -175,8 +175,8 @@ Scannen - - Suchmaschine + + Suchmaschine Suchmaschinen-Einstellungen @@ -1490,9 +1490,7 @@ Es existieren bereits Zugangsdaten mit diesem Benutzernamen - - Mit einem Firefox-Konto verbinden. - + Weiteres Gerät verbinden. Bitte erneut authentifizieren. @@ -1513,13 +1511,4 @@ Ok, verstanden - - - Suchmaschinen - - Suchen mit - - Einmalig suchen mit: - - Kürzel für die Suche anzeigen diff --git a/app/src/main/res/values-dsb/strings.xml b/app/src/main/res/values-dsb/strings.xml index 4b95de4b1..7150cb04c 100644 --- a/app/src/main/res/values-dsb/strings.xml +++ b/app/src/main/res/values-dsb/strings.xml @@ -171,8 +171,8 @@ Scannowaś - - Pytnica + + Pytnica Nastajenja pytnicow @@ -1461,9 +1461,7 @@ Pśizjawjenje z tym wužywaŕskim mjenim južo esistěrujo - - Z kontom Firefox zwězaś. - + Z drugim rědom zwězaś. Pšosym awtentificěrujśo znowego. @@ -1485,13 +1483,4 @@ W pórěźe, som zrozměł - - - Skrotconki - - Pytaś z - - Něnto pytaś z: - - Pytańske skrotconki pokazaś diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 4410c1bd1..544767997 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -1212,6 +1212,9 @@ Μιλήστε τώρα + + Υπάρχει ήδη σύνδεση με αυτό το όνομα χρήστη + Συνδεθείτε με ένα λογαριασμό Firefox. diff --git a/app/src/main/res/values-es-rAR/strings.xml b/app/src/main/res/values-es-rAR/strings.xml index a610d0c58..ab809da03 100644 --- a/app/src/main/res/values-es-rAR/strings.xml +++ b/app/src/main/res/values-es-rAR/strings.xml @@ -173,8 +173,8 @@ Escanear - - Buscador + + Motor de búsqueda Configuración del buscador @@ -1477,9 +1477,7 @@ Ya existe un inicio de sesión con ese nombre de usuario - - Conectate con una cuenta de Firefox. - + Conectar otro dispositivo. Volver a autenticar. @@ -1501,13 +1499,4 @@ Listo, lo entendí. - - - Atajos - - Buscar con - - Esta vez buscar con: - - Mostrar atajos de teclado para búsquedas diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 8004e9980..15970f7ce 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -170,8 +170,8 @@ Skeniraj - - Tražilica + + Tražilica Traži postavke tražilice @@ -1472,9 +1472,7 @@ Prijava s tim korisničkim imenom već postoji - - Poveži s Firefox računom. - + Poveži drugi uređaj. Ponovite autorizaciju. @@ -1496,13 +1494,4 @@ U redu, shvaćam - - - Prečaci - - Traži pomoću - - Ovaj put traži pomoću: - - Prikaži prečace za pretraživanje diff --git a/app/src/main/res/values-hsb/strings.xml b/app/src/main/res/values-hsb/strings.xml index 94089fe56..4b4f1ecc4 100644 --- a/app/src/main/res/values-hsb/strings.xml +++ b/app/src/main/res/values-hsb/strings.xml @@ -171,8 +171,8 @@ Skenować - - Pytawa + + Pytawa Nastajenja pytawy @@ -1460,9 +1460,7 @@ Přizjewjenje z tym wužiwarskim mjenom hižo eksistuje. - - Z kontom Firefox zwjazać. - + Z druhim gratom zwjazać. Prošu awtentifikujće znowa. @@ -1483,13 +1481,4 @@ W porjadku, sym zrozumił - - - Skrótšenki - - Pytać z - - Nětko pytać z: - - Pytanske skrótšenki pokazać diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 7074492e3..6ee82aee9 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -169,8 +169,8 @@ סריקה - - מנוע חיפוש + + מנוע חיפוש הגדרות מנוע חיפוש @@ -1436,9 +1436,7 @@ כבר קיימת כניסה עם שם משתמש זה - - נא להתחבר עם חשבון Firefox. - + נא לחבר מכשיר נוסף. נא להפעיל סנכרון לשוניות. @@ -1455,13 +1453,4 @@ בסדר, הבנתי - - - קיצורי דרך - - חיפוש באמצעות - - הפעם, לחפש באמצעות: - - הצגת קיצורי דרך לחיפוש diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index cb7f8862b..db2edf695 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -173,8 +173,8 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Snirem - - Amsedday n unadi + + Amsedday unadi Iɣewwaṛen n umsedday n unadi @@ -1471,9 +1471,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Anekcam s yisem-agi n useqdac yella yakan - - Qqen s umiḍan Firefox. - + Qqen ibenk-nniḍen. Ma ulac aɣilif, ales asesteb. @@ -1495,13 +1493,4 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara IH, awi-t-id - - - Inegzumen - - Nadi s - - Tikkelt-agi, nadi s: - - Sken anadi n yinegzumen diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 59a446665..f6124eb83 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -180,8 +180,8 @@ 스캔 - - 검색 엔진 + + 검색 엔진 검색 엔진 설정 @@ -289,7 +289,7 @@ 데이터 수집 - 개인정보 보호정책 + 개인정보처리방침 개발자 도구 @@ -1083,7 +1083,7 @@      - 개인정보 보호정책 읽기 + 개인정보처리방침 읽기 닫기 @@ -1237,7 +1237,7 @@ 충돌 - 개인정보 보호정책 + 개인정보처리방침 권리 읽기 @@ -1507,9 +1507,7 @@ 해당 사용자 이름을 가진 로그인이 이미 존재합니다 - - Firefox 계정으로 연결하세요. - + 다른 기기를 연결하세요. 다시 인증하세요. @@ -1531,14 +1529,4 @@ 확인 - - - 바로 가기 - - 검색 - - - 이번만 검색: - - 검색 바로 가기 표시 diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 062805d70..ca3aa0bac 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -174,8 +174,8 @@ Skann - - Søkemotor + + Søkemotor Innstillinger for søkemotor @@ -1481,9 +1481,7 @@ En innlogging med det brukernavnet eksisterer allerede - - Koble til en Firefox-konto. - + Koble til en annen enhet. Autentiser på nytt. @@ -1504,13 +1502,4 @@ OK, jeg skjønner - - - Snarveier - - Søk med - - Denne gangen, søk med: - - Vis søkesnarveier diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index adcc99381..7cf425cce 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -27,6 +27,9 @@ %1$s open tabbladen. Tik om tussen tabbladen te wisselen. + + %1$d geselecteerd + %1$s is gemaakt door Mozilla. diff --git a/app/src/main/res/values-nn-rNO/strings.xml b/app/src/main/res/values-nn-rNO/strings.xml index 59e1be8ba..a21745707 100644 --- a/app/src/main/res/values-nn-rNO/strings.xml +++ b/app/src/main/res/values-nn-rNO/strings.xml @@ -173,8 +173,8 @@ Skann - - Søkjemotor + + Søkjemotor Innstillingar for søkjemotor @@ -1472,9 +1472,7 @@ Ei innlogging med dette brukarnamnet finst allereie - - Kople til med ein Firefox Account. - + Kople til ei anna eining. Godkjenn på nytt. @@ -1495,13 +1493,4 @@ OK, eg forstår det - - - Snarvegar - - Søk med - - Denne gong, søk med: - - Vis søkjesnarvegar diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index c106bcf56..4aec39057 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -172,8 +172,8 @@ Digitalizar - - Motor de pesquisa + + Motor de pesquisa Definições do motor de pesquisa @@ -1466,9 +1466,7 @@ Já existe uma credencial com este nome. - - Associar uma conta Firefox. - + Associar outro dispositivo. Por favor, autentique-se novamente. @@ -1489,13 +1487,4 @@ OK, percebi - - - Atalhos - - Pesquisar com - - Desta vez, pesquisar com: - - Mostrar atalhos de pesquisa diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 3a0e30d4c..22b40c421 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -25,6 +25,29 @@ %1$s отворених језичака. Додирните за пребацивање језичака. + + %1$d изабран + + Додај нову збирку + + Назив + + Изабери збирку + + Изађите из режима вишеструког избора + + Сачувајте одабране језичке у збирку + + Изабран је %1$s + + Избор %1$s је отказан + + Изашли сте из режима вишеструког избора + + Ушли сте у режим вишеструког избора, одаберите језичке за чување у збирци + + Изабрано + %1$s производи Mozilla. @@ -146,8 +169,8 @@ Скенирај - - Претраживач + + Претраживач Подешавања претраживача @@ -508,6 +531,9 @@ %1$s (приватни режим) + + Сачувај + Обриши историјат @@ -1436,9 +1462,7 @@ Пријава са овим корисничким именом већ постоји - - Повежите са Firefox налогом. - + Повежите други уређај. Поново потврдите идентитет. @@ -1460,13 +1484,4 @@ Важи, разумем - - - Пречице - - Претражи са - - Овај пут потражи користећи: - - Пречице за претрагу diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index 7abf7773a..0502f7e5a 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -173,8 +173,8 @@ Skanna - - Sökmotor + + Sökmotor Inställningar för sökmotor @@ -1473,9 +1473,7 @@ En inloggning med det användarnamnet finns redan - - Anslut med ett Firefox-konto. - + Anslut en annan enhet. Bekräfta igen. @@ -1496,14 +1494,4 @@ Ok, jag förstår - - - Genvägar - - Sök med - - - Denna gång, sök med: - - Visa sökgenvägar diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 4f4eafd84..c3b139465 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -172,8 +172,8 @@ Сканувати - - Засіб пошуку + + Засіб пошуку Налаштування пошукових засобів @@ -1474,9 +1474,7 @@ Запис з таким іменем користувача вже існує - - Під’єднатися до облікового запису Firefox. - + Під’єднати інший пристрій. Повторіть автентифікацію. @@ -1497,14 +1495,4 @@ Гаразд, зрозуміло - - - Ярлики - - - Шукати з - - Цього разу шукати з: - - Посилання на пошукові засоби diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 56aba91dd..700697231 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -173,7 +173,9 @@ pref_key_migrating_from_firefox_nightly_tip pref_key_migrating_from_fenix_tip - pref_key_new_tab_tray + pref_key_use_new_search_experience + + pref_key_wait_first_paint pref_key_debug_settings diff --git a/app/src/main/res/values/static_strings.xml b/app/src/main/res/values/static_strings.xml index cac5c60b5..e51388ca3 100644 --- a/app/src/main/res/values/static_strings.xml +++ b/app/src/main/res/values/static_strings.xml @@ -32,7 +32,10 @@ Secret Settings - Use New Tab Tray + + Use New Search Experience + + Wait Until First Paint To Show Page Content link diff --git a/app/src/main/res/xml/secret_settings_preferences.xml b/app/src/main/res/xml/secret_settings_preferences.xml index 4972b9ab8..e8e2f95d9 100644 --- a/app/src/main/res/xml/secret_settings_preferences.xml +++ b/app/src/main/res/xml/secret_settings_preferences.xml @@ -3,4 +3,15 @@ - 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/. --> + xmlns:app="http://schemas.android.com/apk/res-auto"> + + + diff --git a/app/src/test/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactoryTest.kt b/app/src/test/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactoryTest.kt index 94f1ae5f2..2344bf4b8 100644 --- a/app/src/test/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactoryTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactoryTest.kt @@ -198,6 +198,18 @@ class TrackingProtectionPolicyFactoryTest { // `normalMode = true, privateMode = true` can never be shown to the user } + @Test + fun `factory should follow global ETP settings by default`() { + var useETPFactory = TrackingProtectionPolicyFactory(mockSettings(useTrackingProtection = true)) + var policy = useETPFactory.createTrackingProtectionPolicy() + assertTrue(policy.useForPrivateSessions) + assertTrue(policy.useForRegularSessions) + + useETPFactory = TrackingProtectionPolicyFactory(mockSettings(useTrackingProtection = false)) + policy = useETPFactory.createTrackingProtectionPolicy() + assertEquals(policy, EngineSession.TrackingProtectionPolicy.none()) + } + @Test fun `custom tabs should respect their privacy rules`() { val allSettings = listOf( @@ -315,10 +327,12 @@ class TrackingProtectionPolicyFactoryTest { private fun mockSettings( useStrict: Boolean = false, - useCustom: Boolean = false + useCustom: Boolean = false, + useTrackingProtection: Boolean = false ): Settings = mockk { every { useStrictTrackingProtection } returns useStrict every { useCustomTrackingProtection } returns useCustom + every { shouldUseTrackingProtection } returns useTrackingProtection } @Suppress("LongParameterList") diff --git a/app/src/test/java/org/mozilla/fenix/components/metrics/LeanplumMetricsServiceTest.kt b/app/src/test/java/org/mozilla/fenix/components/metrics/LeanplumMetricsServiceTest.kt new file mode 100644 index 000000000..6027a100a --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/components/metrics/LeanplumMetricsServiceTest.kt @@ -0,0 +1,42 @@ +/* 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.components.metrics + +import android.content.Context.MODE_PRIVATE +import mozilla.components.support.test.robolectric.testContext +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.ext.application +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner + +@RunWith(FenixRobolectricTestRunner::class) +class LeanplumMetricsServiceTest { + @Test + fun `deviceId is only generated on first run`() { + var callCount = 0 + val idGenerator = { + callCount++ + "TEST_DEVICE_ID" + } + + val sharedPreferences = testContext.application.getSharedPreferences( + "LEANPLUM_PREFERENCES", + MODE_PRIVATE + ) + + assertNull(sharedPreferences.getString("LP_DEVICE_ID", null)) + + val leanplumMetricService = LeanplumMetricsService(testContext.application, idGenerator) + assertEquals("TEST_DEVICE_ID", leanplumMetricService.deviceId) + + val leanplumMetricService2 = LeanplumMetricsService(testContext.application, idGenerator) + assertEquals("TEST_DEVICE_ID", leanplumMetricService2.deviceId) + assertEquals(1, callCount) + + assertEquals("TEST_DEVICE_ID", sharedPreferences.getString("LP_DEVICE_ID", "")) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/helpers/FenixRobolectricTestApplication.kt b/app/src/test/java/org/mozilla/fenix/helpers/FenixRobolectricTestApplication.kt index 9e35eef29..076d13cf8 100644 --- a/app/src/test/java/org/mozilla/fenix/helpers/FenixRobolectricTestApplication.kt +++ b/app/src/test/java/org/mozilla/fenix/helpers/FenixRobolectricTestApplication.kt @@ -4,7 +4,6 @@ package org.mozilla.fenix.helpers -import kotlinx.coroutines.ExperimentalCoroutinesApi import org.mozilla.fenix.FenixApplication import org.mozilla.fenix.components.TestComponents @@ -17,8 +16,9 @@ class FenixRobolectricTestApplication : FenixApplication() { override val components = TestComponents(this) + override fun initializeGlean() = Unit + override fun setupInAllProcesses() = Unit - @ExperimentalCoroutinesApi override fun setupInMainProcessOnly() = Unit } diff --git a/buildSrc/src/main/java/AndroidComponents.kt b/buildSrc/src/main/java/AndroidComponents.kt index c3bbb8715..2c41963a7 100644 --- a/buildSrc/src/main/java/AndroidComponents.kt +++ b/buildSrc/src/main/java/AndroidComponents.kt @@ -3,5 +3,5 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ object AndroidComponents { - const val VERSION = "53.0.20200803131508" + const val VERSION = "53.0.20200804130112" } diff --git a/docs/mma.md b/docs/mma.md index 14d8e2be7..4db6157ae 100644 --- a/docs/mma.md +++ b/docs/mma.md @@ -215,12 +215,22 @@ Here is the list of current Events sent, which can be found here in the code bas `E_Collection_Tab_Opened` The user opened a tab from a previously created collection #4626 - + + + `E_FxA_New_Signup` + The user completed the signup process to new FxA account + #4626 + `E_Sign_In_FxA` The user successfully signed in to FxA #4626 - + + + `E_Sign_In_FxA_Fennec_to_Fenix` + The user successfully signed in to FxA using previously signed in Fennec account + #4626 + `E_Sign_Out_FxA` The user successfully signed out of FxA diff --git a/taskcluster/fenix_taskgraph/target_tasks.py b/taskcluster/fenix_taskgraph/target_tasks.py index 66242ebff..f947a4fb0 100644 --- a/taskcluster/fenix_taskgraph/target_tasks.py +++ b/taskcluster/fenix_taskgraph/target_tasks.py @@ -21,6 +21,12 @@ def target_tasks_default(full_task_graph, parameters, graph_config): # TODO Use shipping-phase once we retire github-releases def filter(task, parameters): + # Mark-as-shipped is always red on github-release and it confuses people. + # This task cannot be green if we kick off a release through github-releases, so + # let's exlude that task there. + if task.kind == "mark-as-shipped" and parameters["tasks_for"] == "github-release": + return False + return task.attributes.get("release-type", "") == parameters["release_type"] return [l for l, t in full_task_graph.tasks.iteritems() if filter(t, parameters)]