From 87349c17a19655a6e274cb6e03e0d6e5bfdc04dc Mon Sep 17 00:00:00 2001 From: Mozilla L10n Automation Bot Date: Thu, 13 Aug 2020 00:10:27 +0000 Subject: [PATCH 01/33] Import l10n. --- app/src/main/res/values-de/strings.xml | 2 ++ app/src/main/res/values-dsb/strings.xml | 2 ++ app/src/main/res/values-es-rAR/strings.xml | 2 ++ app/src/main/res/values-fa/strings.xml | 12 ++++++++++++ app/src/main/res/values-hsb/strings.xml | 2 ++ app/src/main/res/values-iw/strings.xml | 2 ++ app/src/main/res/values-ko/strings.xml | 2 ++ app/src/main/res/values-nb-rNO/strings.xml | 2 ++ app/src/main/res/values-pt-rPT/strings.xml | 2 ++ app/src/main/res/values-sl/strings.xml | 2 ++ app/src/main/res/values-sv-rSE/strings.xml | 2 ++ app/src/main/res/values-uk/strings.xml | 2 ++ 12 files changed, 34 insertions(+) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index c9f4f23aa8..0f83777594 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -309,6 +309,8 @@ Links in Apps öffnen + + Externer Download-Manager Add-ons diff --git a/app/src/main/res/values-dsb/strings.xml b/app/src/main/res/values-dsb/strings.xml index 7150cb04c1..1b8a93faf6 100644 --- a/app/src/main/res/values-dsb/strings.xml +++ b/app/src/main/res/values-dsb/strings.xml @@ -303,6 +303,8 @@ Wótkaze w nałoženjach wócyniś + + Eksterny zastojnik ześěgnjenjow Dodanki diff --git a/app/src/main/res/values-es-rAR/strings.xml b/app/src/main/res/values-es-rAR/strings.xml index 23f1445a2c..4f6cfc449e 100644 --- a/app/src/main/res/values-es-rAR/strings.xml +++ b/app/src/main/res/values-es-rAR/strings.xml @@ -308,6 +308,8 @@ Abrir enlaces en aplicaciones + + Administrador de descargas externo Complementos diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index e88907ca54..005aa5c0a6 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -24,6 +24,16 @@ %1$s زبانه‌های باز. برای تغییر زبانه‌ها ضربه بزنید. + + %1$d انتخاب شد + + افزودن مجموعه جدید + + نام + + انتخاب مجموعه + + %1$s انتخاب شد انتخاب شده @@ -577,6 +587,8 @@ انتخاب پوشه آيا از حذف اين پوشه مطمئن هستيد؟ + + %s موارد انتخاب شده را حذف می کند. %1$s حذف شد diff --git a/app/src/main/res/values-hsb/strings.xml b/app/src/main/res/values-hsb/strings.xml index 4b4f1ecc4c..fa59d193c0 100644 --- a/app/src/main/res/values-hsb/strings.xml +++ b/app/src/main/res/values-hsb/strings.xml @@ -303,6 +303,8 @@ Wotkazy w nałoženjach wočinić + + Eksterny zrjadowak sćehnjenjow Přidatki diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 6ee82aee9f..192a5bcf37 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -299,6 +299,8 @@ פתיחת קישורים ביישומונים + + מנהל הורדות חיצוני תוספות diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 6250bd7889..e2a23d73f2 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -314,6 +314,8 @@ 앱에서 링크 열기 + + 외부 다운로드 관리자 부가 기능 diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index ca3aa0bacd..d2dffbbf0d 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -305,6 +305,8 @@ Kontoinnstillinger Åpne lenker i apper + + Ekstern nedlastingsbehandler Utvidelser diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 4aec39057a..f4e8d49707 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -303,6 +303,8 @@ Definições da conta Abrir ligações em aplicações + + Gestor de transferências externo Extras diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 32462293be..1170b3e0b8 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -294,6 +294,8 @@ Odpiraj povezave v aplikacijah + + Zunanji upravitelj prenosov Dodatki diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index 0502f7e5a7..d9c1ed78cd 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -306,6 +306,8 @@ Öppna länkar i appar + + Extern filhämtare Tillägg diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index c3b1394653..561caa2dcf 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -308,6 +308,8 @@ Відкривати посилання в програмах + + Зовнішній менеджер завантажень Додатки From 0356d867845af282acc771659266b44f790dd6e0 Mon Sep 17 00:00:00 2001 From: Shen Date: Wed, 12 Aug 2020 18:11:12 -0700 Subject: [PATCH 02/33] For #12976 - Show infinity symbol in the tab counter when the count is greater than 99 --- .../java/org/mozilla/fenix/tabtray/TabTrayView.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt index d0d9034474..3be06f0849 100644 --- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt +++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt @@ -39,9 +39,13 @@ import mozilla.components.browser.tabstray.TabViewHolder import mozilla.components.support.ktx.android.util.dpToPx import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.components.toolbar.TabCounter.Companion.INFINITE_CHAR_PADDING_BOTTOM +import org.mozilla.fenix.components.toolbar.TabCounter.Companion.MAX_VISIBLE_TABS +import org.mozilla.fenix.components.toolbar.TabCounter.Companion.SO_MANY_TABS_OPEN import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.tabtray.SaveToCollectionsButtonAdapter.MultiselectModeChange +import java.text.NumberFormat /** * View that contains and configures the BrowserAwesomeBar @@ -372,7 +376,7 @@ class TabTrayView( } view.tab_tray_overflow.isVisible = !hasNoTabs - counter_text.text = "${browserState.normalTabs.size}" + counter_text.text = updateTabCounter(browserState.normalTabs.size) updateTabCounterContentDescription(browserState.normalTabs.size) adjustNewTabButtonsForNormalMode() @@ -457,6 +461,14 @@ class TabTrayView( } } + private fun updateTabCounter(count: Int): String { + if (count > MAX_VISIBLE_TABS) { + counter_text.setPadding(0, 0, 0, INFINITE_CHAR_PADDING_BOTTOM) + return SO_MANY_TABS_OPEN + } + return NumberFormat.getInstance().format(count.toLong()) + } + fun setTopOffset(landscape: Boolean) { val topOffset = if (landscape) { 0 From f0a045f9b97cae1b7ed5180ec90981d02b40de8e Mon Sep 17 00:00:00 2001 From: "codrut.topliceanu" Date: Thu, 13 Aug 2020 10:01:55 +0300 Subject: [PATCH 03/33] For #13390 - Fix for stuck readerMode appearance controls --- .../mozilla/fenix/browser/readermode/ReaderModeController.kt | 5 ++++- .../browser/readermode/DefaultReaderModeControllerTest.kt | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/mozilla/fenix/browser/readermode/ReaderModeController.kt b/app/src/main/java/org/mozilla/fenix/browser/readermode/ReaderModeController.kt index a148f65e7a..4f1de82d04 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/readermode/ReaderModeController.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/readermode/ReaderModeController.kt @@ -27,7 +27,10 @@ class DefaultReaderModeController( private val isPrivate: Boolean = false ) : ReaderModeController { override fun hideReaderView() { - readerViewFeature.withFeature { it.hideReaderView() } + readerViewFeature.withFeature { + it.hideReaderView() + it.hideControls() + } } override fun showReaderView() { diff --git a/app/src/test/java/org/mozilla/fenix/browser/readermode/DefaultReaderModeControllerTest.kt b/app/src/test/java/org/mozilla/fenix/browser/readermode/DefaultReaderModeControllerTest.kt index 56a48b4c10..bb8e3e3a56 100644 --- a/app/src/test/java/org/mozilla/fenix/browser/readermode/DefaultReaderModeControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/browser/readermode/DefaultReaderModeControllerTest.kt @@ -54,6 +54,7 @@ class DefaultReaderModeControllerTest { every { readerViewFeature.hideReaderView() } returns Unit every { readerViewFeature.showReaderView() } returns Unit every { readerViewFeature.showControls() } returns Unit + every { readerViewFeature.hideControls() } returns Unit } @Test @@ -61,6 +62,7 @@ class DefaultReaderModeControllerTest { val controller = DefaultReaderModeController(featureWrapper, readerViewControlsBar) controller.hideReaderView() verify { readerViewFeature.hideReaderView() } + verify { readerViewFeature.hideControls() } } @Test From 4542b4b93454f25f8891469cff981971a9eb37c4 Mon Sep 17 00:00:00 2001 From: Oana Horvath Date: Thu, 13 Aug 2020 19:20:47 +0300 Subject: [PATCH 04/33] Closes #12778: re-arranged the steps in closeTabTest and closePrivateTabTest (#13810) --- .../mozilla/fenix/ui/TabbedBrowsingTest.kt | 80 +++++++++++++------ 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt index 3470db229d..059d47e4f4 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt @@ -10,13 +10,13 @@ import okhttp3.mockwebserver.MockWebServer import org.junit.After import org.junit.Before import org.junit.BeforeClass -import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.sendSingleTapToScreen +import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.navigationToolbar import org.mozilla.fenix.ui.robots.notificationShade @@ -148,7 +148,6 @@ class TabbedBrowsingTest { } @Test - @Ignore("For some reason this intermittently fails with the drawer :(") fun closeTabTest() { var genericURLS = TestAssetHelper.getGenericAssets(mockWebServer) @@ -161,25 +160,39 @@ class TabbedBrowsingTest { closeTabViaXButton("Test_Page_${index + 1}") verifySnackBarText("Tab closed") snackBarButtonClick("UNDO") -// verifyExistingOpenTabs("Test_Page_${index + 1}") -// verifyCloseTabsButton("Test_Page_${index + 1}") -// swipeTabRight("Test_Page_${index + 1}") -// verifySnackBarText("Tab closed") -// snackBarButtonClick("UNDO") -// verifyExistingOpenTabs("Test_Page_${index + 1}") -// verifyCloseTabsButton("Test_Page_${index + 1}") -// swipeTabLeft("Test_Page_${index + 1}") -// verifySnackBarText("Tab closed") -// snackBarButtonClick("UNDO") + } + + mDevice.waitForIdle() + + browserScreen { + }.openTabDrawer { + verifyExistingOpenTabs("Test_Page_${index + 1}") + swipeTabRight("Test_Page_${index + 1}") + verifySnackBarText("Tab closed") + snackBarButtonClick("UNDO") + } + + mDevice.waitForIdle() + + browserScreen { + }.openTabDrawer { + verifyExistingOpenTabs("Test_Page_${index + 1}") + swipeTabLeft("Test_Page_${index + 1}") + verifySnackBarText("Tab closed") + snackBarButtonClick("UNDO") + } + + mDevice.waitForIdle() + + browserScreen { + }.openTabDrawer { verifyExistingOpenTabs("Test_Page_${index + 1}") - verifyCloseTabsButton("Test_Page_${index + 1}") }.openHomeScreen { } } } @Test - @Ignore("For some reason this intermittently fails with the drawer :(") fun closePrivateTabTest() { var genericURLS = TestAssetHelper.getGenericAssets(mockWebServer) @@ -193,19 +206,34 @@ class TabbedBrowsingTest { closeTabViaXButton("Test_Page_${index + 1}") verifySnackBarText("Private tab closed") snackBarButtonClick("UNDO") -// verifyExistingOpenTabs("Test_Page_${index + 1}") -// verifyCloseTabsButton("Test_Page_${index + 1}") -// swipeTabRight("Test_Page_${index + 1}") -// verifySnackBarText("Private tab closed") -// snackBarButtonClick("UNDO") -// verifyExistingOpenTabs("Test_Page_${index + 1}") -// verifyCloseTabsButton("Test_Page_${index + 1}") -// swipeTabLeft("Test_Page_${index + 1}") -// verifySnackBarText("Private tab closed") -// snackBarButtonClick("UNDO") + } + + mDevice.waitForIdle() + + browserScreen { + }.openTabDrawer { + verifyExistingOpenTabs("Test_Page_${index + 1}") + swipeTabRight("Test_Page_${index + 1}") + verifySnackBarText("Private tab closed") + snackBarButtonClick("UNDO") + } + + mDevice.waitForIdle() + + browserScreen { + }.openTabDrawer { verifyExistingOpenTabs("Test_Page_${index + 1}") - verifyCloseTabsButton("Test_Page_${index + 1}") - }.openHomeScreen { + swipeTabLeft("Test_Page_${index + 1}") + verifySnackBarText("Private tab closed") + snackBarButtonClick("UNDO") + } + + mDevice.waitForIdle() + + browserScreen { + }.openTabDrawer { + verifyExistingOpenTabs("Test_Page_${index + 1}") + closeTabViaXButton("Test_Page_${index + 1}") } } } From 7f9ddfe051e7d6e0469db9a1672df6e2fd9335c9 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Mon, 10 Aug 2020 12:35:39 -0700 Subject: [PATCH 05/33] For #13404: Update Android lint URL --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a236dc1911..3ea76aa37a 100644 --- a/build.gradle +++ b/build.gradle @@ -198,5 +198,5 @@ tasks.register("githubLintDetektDetails", GithubDetailsTask) { } tasks.register("githubLintAndroidDetails", GithubDetailsTask) { - text = "### [Android Lint Results]({reportsUrl}/lint-results-geckoNightlyDebug.html)" + text = "### [Android Lint Results]({reportsUrl}/lint-results-debug.html)" } From d9ffac0c890c0d58cd62f00693a45322c030f96d Mon Sep 17 00:00:00 2001 From: Kainalu Hagiwara Date: Mon, 10 Aug 2020 10:43:30 -0700 Subject: [PATCH 06/33] For #13405 - Use toolbar location relative to the whole screen instead of window. --- .../fenix/browser/ToolbarGestureHandler.kt | 3 ++- .../main/java/org/mozilla/fenix/ext/View.kt | 14 ++++++++++++++ .../java/org/mozilla/fenix/ext/ViewTest.kt | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/mozilla/fenix/browser/ToolbarGestureHandler.kt b/app/src/main/java/org/mozilla/fenix/browser/ToolbarGestureHandler.kt index ccd2b3ce4e..cd507391b0 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/ToolbarGestureHandler.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/ToolbarGestureHandler.kt @@ -23,6 +23,7 @@ import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.support.ktx.android.util.dpToPx import mozilla.components.support.ktx.android.view.getRectWithViewLocation +import org.mozilla.fenix.ext.getRectWithScreenLocation import org.mozilla.fenix.ext.getWindowInsets import org.mozilla.fenix.ext.isKeyboardVisible import org.mozilla.fenix.ext.sessionsOfType @@ -304,7 +305,7 @@ class ToolbarGestureHandler( } private fun PointF.isInToolbar(): Boolean { - val toolbarLocation = toolbarLayout.getRectWithViewLocation() + val toolbarLocation = toolbarLayout.getRectWithScreenLocation() // In Android 10, the system gesture touch area overlaps the bottom of the toolbar, so // lets make our swipe area taller by that amount activity.window.decorView.getWindowInsets()?.let { insets -> diff --git a/app/src/main/java/org/mozilla/fenix/ext/View.kt b/app/src/main/java/org/mozilla/fenix/ext/View.kt index 05c2e8de7f..683d9b65df 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/View.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/View.kt @@ -31,6 +31,20 @@ fun View.removeTouchDelegate() { } } +/** + * Fills a [Rect] with data about a view's location in the screen. + * + * @see View.getLocationOnScreen + * @see View.getRectWithViewLocation for a version of this that is relative to a window +*/ +fun View.getRectWithScreenLocation(): Rect { + val locationOnScreen = IntArray(2).apply { getLocationOnScreen(this) } + return Rect(locationOnScreen[0], + locationOnScreen[1], + locationOnScreen[0] + width, + locationOnScreen[1] + height) +} + /** * A safer version of [ViewCompat.getRootWindowInsets] that does not throw a NullPointerException * if the view is not attached. diff --git a/app/src/test/java/org/mozilla/fenix/ext/ViewTest.kt b/app/src/test/java/org/mozilla/fenix/ext/ViewTest.kt index c9da170fb3..003312d3d2 100644 --- a/app/src/test/java/org/mozilla/fenix/ext/ViewTest.kt +++ b/app/src/test/java/org/mozilla/fenix/ext/ViewTest.kt @@ -148,4 +148,22 @@ class ViewTest { every { view.getKeyboardHeight() } returns 100 assertEquals(true, view.isKeyboardVisible()) } + + @Test + fun `getRectWithScreenLocation should transform getLocationInScreen method values`() { + val locationOnScreen = slot() + every { view.getLocationOnScreen(capture(locationOnScreen)) } answers { + locationOnScreen.captured[0] = 100 + locationOnScreen.captured[1] = 200 + } + every { view.width } returns 150 + every { view.height } returns 250 + + val outRect = view.getRectWithScreenLocation() + + assertEquals(100, outRect.left) + assertEquals(200, outRect.top) + assertEquals(250, outRect.right) + assertEquals(450, outRect.bottom) + } } From b4e053d60a8845ca4638e2f431c1ef8c7547e8f0 Mon Sep 17 00:00:00 2001 From: Mozilla L10n Automation Bot Date: Fri, 14 Aug 2020 00:10:30 +0000 Subject: [PATCH 07/33] Import l10n. --- app/src/main/res/values-ast/strings.xml | 4 +++- app/src/main/res/values-cy/strings.xml | 2 ++ app/src/main/res/values-en-rCA/strings.xml | 2 ++ app/src/main/res/values-es-rCL/strings.xml | 2 ++ app/src/main/res/values-fi/strings.xml | 2 ++ app/src/main/res/values-gn/strings.xml | 2 ++ app/src/main/res/values-hu/strings.xml | 2 ++ app/src/main/res/values-in/strings.xml | 2 ++ app/src/main/res/values-kk/strings.xml | 2 ++ app/src/main/res/values-nl/strings.xml | 2 ++ app/src/main/res/values-nn-rNO/strings.xml | 2 ++ app/src/main/res/values-pt-rBR/strings.xml | 2 ++ app/src/main/res/values-sr/strings.xml | 2 ++ app/src/main/res/values-su/strings.xml | 2 ++ app/src/main/res/values-te/strings.xml | 2 ++ app/src/main/res/values-zh-rCN/strings.xml | 2 ++ app/src/main/res/values-zh-rTW/strings.xml | 2 ++ 17 files changed, 35 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml index 1387dbe99e..8c7b958a42 100644 --- a/app/src/main/res/values-ast/strings.xml +++ b/app/src/main/res/values-ast/strings.xml @@ -46,13 +46,15 @@ ¿Amestar un atayu p\'abrir llingüetes privaes dende la pantalla d\'aniciu? - + Amestalu Non, gracies Accedi aína a Firefox col amiestu d\'un widget a la pantalla d\'aniciu. + + Amestalu Agora non diff --git a/app/src/main/res/values-cy/strings.xml b/app/src/main/res/values-cy/strings.xml index 3da2999437..af2206f290 100644 --- a/app/src/main/res/values-cy/strings.xml +++ b/app/src/main/res/values-cy/strings.xml @@ -303,6 +303,8 @@ Agor dolenni mewn apiau + + Rheolwr llwytho i lawr allanol Ychwanegion diff --git a/app/src/main/res/values-en-rCA/strings.xml b/app/src/main/res/values-en-rCA/strings.xml index 3f822e18cc..802e6fc47f 100644 --- a/app/src/main/res/values-en-rCA/strings.xml +++ b/app/src/main/res/values-en-rCA/strings.xml @@ -301,6 +301,8 @@ Open links in apps + + External download manager Add-ons diff --git a/app/src/main/res/values-es-rCL/strings.xml b/app/src/main/res/values-es-rCL/strings.xml index b8815f6d69..6f846985e4 100644 --- a/app/src/main/res/values-es-rCL/strings.xml +++ b/app/src/main/res/values-es-rCL/strings.xml @@ -301,6 +301,8 @@ Abrir enlaces en aplicaciones + + Administrador de descargas externo Complementos diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 2637b586e2..e9d89f345a 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -308,6 +308,8 @@ Avaa linkit sovelluksissa + + Erillinen latausten hallinta Lisäosat diff --git a/app/src/main/res/values-gn/strings.xml b/app/src/main/res/values-gn/strings.xml index 8977f2b824..c27355f4cd 100644 --- a/app/src/main/res/values-gn/strings.xml +++ b/app/src/main/res/values-gn/strings.xml @@ -306,6 +306,8 @@ Mba’ete ñemboheko Embojuruja juajuha tembipuru’ípe + + Mboguejy okaygua ñangarekoha Moĩmbaha diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 62beca7dec..0984041a70 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -305,6 +305,8 @@ Hivatkozások megnyitása alkalmazásokban + + Külső letöltéskezelő Kiegészítők diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 45bb400306..b12c2a8e59 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -311,6 +311,8 @@ Buka tautan di aplikasi + + Pengelola unduhan eksternal Pengaya diff --git a/app/src/main/res/values-kk/strings.xml b/app/src/main/res/values-kk/strings.xml index 15fc42e337..4ab4831cf7 100644 --- a/app/src/main/res/values-kk/strings.xml +++ b/app/src/main/res/values-kk/strings.xml @@ -297,6 +297,8 @@ Тіркелгі баптаулары Сілтемелерді қолданбаларда ашу + + Сыртқы жүктеу менеджері Қосымшалар diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 69114513e8..071f252b1c 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -302,6 +302,8 @@ Koppelingen openen in apps + + Externe downloadbeheerder Add-ons diff --git a/app/src/main/res/values-nn-rNO/strings.xml b/app/src/main/res/values-nn-rNO/strings.xml index a21745707a..a7224cceda 100644 --- a/app/src/main/res/values-nn-rNO/strings.xml +++ b/app/src/main/res/values-nn-rNO/strings.xml @@ -306,6 +306,8 @@ Kontoinnstillingar Opne lenker i appar + + Ekstern nedlastingshandterar Tillegg diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index ef5a2e67b4..d56093c00f 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -302,6 +302,8 @@ Abrir links em aplicativos + + Gerenciador de downloads externo Extensões diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 22b40c4216..4a21201b27 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -301,6 +301,8 @@ Подешавања налога Отвори везе у апликацијама + + Спољни менаџер преузимања Додаци diff --git a/app/src/main/res/values-su/strings.xml b/app/src/main/res/values-su/strings.xml index 40d2e00256..884215ed10 100644 --- a/app/src/main/res/values-su/strings.xml +++ b/app/src/main/res/values-su/strings.xml @@ -303,6 +303,8 @@ Buka tutumbu dina aplikasi + + Manajer undeuran éksternal Émbohan diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index 4b05e418b1..28da2a258a 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -303,6 +303,8 @@ లంకెలను అనువర్తనాల్లో తెరువు + + బయటి దింపుకోలు నిర్వాహకి పొడగింతలు diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 8523ffe4ed..7d999b36e8 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -313,6 +313,8 @@ 在应用程序中打开链接 + + 外部下载管理器 附加组件 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 5802a91297..eb51e4f246 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -309,6 +309,8 @@ 用 App 開啟鏈結 + + 外部下載管理員 附加元件 From 4ba4b589dea1c466a8f4f2d18d95aea7099ca799 Mon Sep 17 00:00:00 2001 From: Jonathan Almeida Date: Thu, 13 Aug 2020 22:47:30 -0400 Subject: [PATCH 08/33] For #13293: Show Add To Collections after tabs load --- app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt index 3be06f0849..8e8781e65a 100644 --- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt +++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt @@ -137,12 +137,14 @@ class TabTrayView( setTopOffset(startingInLandscape) + val concatAdapter = ConcatAdapter(tabsAdapter) + view.tabsTray.apply { layoutManager = LinearLayoutManager(container.context).apply { reverseLayout = true stackFromEnd = true } - adapter = ConcatAdapter(collectionsButtonAdapter, tabsAdapter) + adapter = concatAdapter tabsTouchHelper = TabsTouchHelper( observable = tabsAdapter, @@ -153,6 +155,9 @@ class TabTrayView( tabsAdapter.tabTrayInteractor = interactor tabsAdapter.onTabsUpdated = { + // Put the 'Add to collections' button after the tabs have loaded. + concatAdapter.addAdapter(0, collectionsButtonAdapter) + if (hasAccessibilityEnabled) { tabsAdapter.notifyDataSetChanged() } From e9da7768944db53a689f5befc306c09705a22d26 Mon Sep 17 00:00:00 2001 From: Mickey Moz <33347735+MickeyMoz@users.noreply.github.com> Date: Fri, 14 Aug 2020 16:47:53 +0200 Subject: [PATCH 09/33] Update Android Components version to 54.0.20200813130057. (#13796) --- buildSrc/src/main/java/AndroidComponents.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/java/AndroidComponents.kt b/buildSrc/src/main/java/AndroidComponents.kt index 7ceac88cb7..0f94869b4f 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 = "54.0.20200812130143" + const val VERSION = "54.0.20200813130057" } From fce6b4488e7ea45191616d2a26509238b2ba7a47 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Fri, 14 Aug 2020 08:04:21 -0700 Subject: [PATCH 10/33] For #13176: Remove race condition for shortcuts (#13815) --- .../java/org/mozilla/fenix/shortcut/CreateShortcutFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/mozilla/fenix/shortcut/CreateShortcutFragment.kt b/app/src/main/java/org/mozilla/fenix/shortcut/CreateShortcutFragment.kt index eddbfc32ae..9918a677e2 100644 --- a/app/src/main/java/org/mozilla/fenix/shortcut/CreateShortcutFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/shortcut/CreateShortcutFragment.kt @@ -42,7 +42,7 @@ class CreateShortcutFragment : DialogFragment() { cancel_button.setOnClickListener { dismiss() } add_button.setOnClickListener { val text = shortcut_text.text.toString() - viewLifecycleOwner.lifecycleScope.launch { + requireActivity().lifecycleScope.launch { requireComponents.useCases.webAppUseCases.addToHomescreen(text) } dismiss() From c7611b529cd5f5e1d94abc2f3c9bc41848b91592 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Thu, 6 Aug 2020 10:57:45 -0700 Subject: [PATCH 11/33] For #13357: Validate PWA manifest folder --- .../customtabs/FennecWebAppIntentProcessor.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessor.kt b/app/src/main/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessor.kt index db76b423c6..a2b96eb57b 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessor.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessor.kt @@ -102,10 +102,13 @@ class FennecWebAppIntentProcessor( internal fun fromFile(path: String?): WebAppManifest? { if (path.isNullOrEmpty()) return null + val file = File(path) + if (!file.isUnderFennecManifestDirectory()) return null + return try { // Gecko in Fennec added some add some additional data, such as cached_icon, in // the toplevel object. The actual web app manifest is in the "manifest" field. - val manifest = JSONObject(File(path).readText()) + val manifest = JSONObject(file.readText()) val manifestField = manifest.getJSONObject("manifest") WebAppManifestParser().parse(manifestField).getOrNull() @@ -114,12 +117,27 @@ class FennecWebAppIntentProcessor( } } + /** + * Fennec manifests should be located in /mozilla//manifests/ + */ + private fun File.isUnderFennecManifestDirectory(): Boolean { + val manifestsDir = canonicalFile.parentFile + // Check that manifest is in a folder named "manifests" + return manifestsDir == null || manifestsDir.name != "manifests" || + // Check that the folder two levels up is named "mozilla" + manifestsDir.parentFile?.parentFile != getMozillaDirectory() + } + private fun createFallbackCustomTabConfig(): CustomTabConfig { return CustomTabConfig( toolbarColor = ContextCompat.getColor(context, R.color.toolbar_center_gradient_normal_theme) ) } + private fun getMozillaDirectory(): File { + return File(context.filesDir, "mozilla") + } + companion object { const val ACTION_FENNEC_WEBAPP = "org.mozilla.gecko.WEBAPP" const val EXTRA_FENNEC_MANIFEST_PATH = "MANIFEST_PATH" From 88f01731d7dd6fb9820190e05c35d98c728ef4d0 Mon Sep 17 00:00:00 2001 From: Arturo Mejia Date: Fri, 14 Aug 2020 10:29:37 -0400 Subject: [PATCH 12/33] For issue #13827: "Set as default browser" option disappears from Settings. --- .../main/java/org/mozilla/fenix/settings/SettingsFragment.kt | 3 ++- app/src/main/res/xml/preferences.xml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index ee9bc6fb6a..f74e27bb4a 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -302,7 +302,8 @@ class SettingsFragment : PreferenceFragmentCompat() { private fun setupPreferences() { val leakKey = getPreferenceKey(R.string.pref_key_leakcanary) val debuggingKey = getPreferenceKey(R.string.pref_key_remote_debugging) - val preferenceExternalDownloadManager = requirePreference(R.string.pref_key_make_default_browser) + val preferenceExternalDownloadManager = + requirePreference(R.string.pref_key_external_download_manager) val preferenceLeakCanary = findPreference(leakKey) val preferenceRemoteDebugging = findPreference(debuggingKey) val preferenceMakeDefaultBrowser = requirePreference(R.string.pref_key_make_default_browser) diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 04de027207..f3bf4c39bc 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -136,7 +136,8 @@ android:defaultValue="false" android:icon="@drawable/ic_download" android:key="@string/pref_key_external_download_manager" - android:title="@string/preferences_external_download_manager" /> + android:title="@string/preferences_external_download_manager" + app:isPreferenceVisible="false"/> Date: Fri, 14 Aug 2020 09:48:46 -0700 Subject: [PATCH 13/33] Clear button (#13842) Co-authored-by: Darren --- .../main/java/org/mozilla/fenix/utils/ClearableEditText.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/mozilla/fenix/utils/ClearableEditText.kt b/app/src/main/java/org/mozilla/fenix/utils/ClearableEditText.kt index aad4bf7ced..e2e7464bdd 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/ClearableEditText.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/ClearableEditText.kt @@ -46,7 +46,9 @@ class ClearableEditText @JvmOverloads constructor( * Displays a clear icon if text has been entered. */ override fun onTextChanged(text: CharSequence?, start: Int, lengthBefore: Int, lengthAfter: Int) { - val drawable = if (shouldShowClearButton(lengthAfter)) { + // lengthAfter has inconsistent behaviour when there are spaces in the entered text, so we'll use text.length. + val textLength = text?.length ?: 0 + val drawable = if (shouldShowClearButton(textLength)) { AppCompatResources.getDrawable(context, R.drawable.ic_clear)?.apply { colorFilter = createBlendModeColorFilterCompat(context.getColorFromAttr(R.attr.primaryText), SRC_IN) } From 3086d8a6945f25a7ed66babd27507846278cdd51 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Fri, 7 Aug 2020 15:24:11 -0700 Subject: [PATCH 14/33] Add test for search dialog controller --- .../SearchDialogControllerTest.kt | 320 ++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 app/src/test/java/org/mozilla/fenix/searchdialog/SearchDialogControllerTest.kt diff --git a/app/src/test/java/org/mozilla/fenix/searchdialog/SearchDialogControllerTest.kt b/app/src/test/java/org/mozilla/fenix/searchdialog/SearchDialogControllerTest.kt new file mode 100644 index 0000000000..cfa3649c67 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/searchdialog/SearchDialogControllerTest.kt @@ -0,0 +1,320 @@ +/* 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 androidx.navigation.NavController +import androidx.navigation.NavDirections +import io.mockk.MockKAnnotations +import io.mockk.Runs +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.just +import io.mockk.mockk +import io.mockk.mockkObject +import io.mockk.unmockkObject +import io.mockk.verify +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runBlockingTest +import mozilla.components.browser.search.SearchEngine +import mozilla.components.browser.session.Session +import mozilla.components.browser.session.SessionManager +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.mozilla.fenix.BrowserDirection +import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.R +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.components.metrics.MetricController +import org.mozilla.fenix.components.metrics.MetricsUtils +import org.mozilla.fenix.ext.navigateSafe +import org.mozilla.fenix.search.SearchFragmentAction +import org.mozilla.fenix.settings.SupportUtils +import org.mozilla.fenix.utils.Settings + +@ExperimentalCoroutinesApi +class SearchDialogControllerTest { + + @MockK(relaxed = true) private lateinit var activity: HomeActivity + @MockK(relaxed = true) private lateinit var store: SearchDialogFragmentStore + @MockK(relaxed = true) private lateinit var navController: NavController + @MockK private lateinit var searchEngine: SearchEngine + @MockK(relaxed = true) private lateinit var metrics: MetricController + @MockK(relaxed = true) private lateinit var settings: Settings + @MockK private lateinit var sessionManager: SessionManager + @MockK(relaxed = true) private lateinit var clearToolbarFocus: () -> Unit + + private lateinit var controller: SearchDialogController + + @Before + fun setUp() { + MockKAnnotations.init(this) + mockkObject(MetricsUtils) + + every { store.state.tabId } returns "test-tab-id" + every { store.state.searchEngineSource.searchEngine } returns searchEngine + every { sessionManager.select(any()) } just Runs + every { MetricsUtils.createSearchEvent(searchEngine, activity, any()) } returns null + + controller = SearchDialogController( + activity = activity, + sessionManager = sessionManager, + store = store, + navController = navController, + settings = settings, + metrics = metrics, + clearToolbarFocus = clearToolbarFocus + ) + } + + @After + fun teardown() { + unmockkObject(MetricsUtils) + } + + @Test + fun handleUrlCommitted() { + val url = "https://www.google.com/" + + controller.handleUrlCommitted(url) + + verify { + activity.openToBrowserAndLoad( + searchTermOrURL = url, + newTab = false, + from = BrowserDirection.FromSearchDialog, + engine = searchEngine + ) + } + verify { metrics.track(Event.EnteredUrl(false)) } + } + + @Test + fun handleSearchCommitted() { + val searchTerm = "Firefox" + + controller.handleUrlCommitted(searchTerm) + + verify { + activity.openToBrowserAndLoad( + searchTermOrURL = searchTerm, + newTab = false, + from = BrowserDirection.FromSearchDialog, + engine = searchEngine + ) + } + verify { settings.incrementActiveSearchCount() } + } + + @Test + fun handleCrashesUrlCommitted() { + val url = "about:crashes" + every { activity.packageName } returns "org.mozilla.fenix" + + controller.handleUrlCommitted(url) + + verify { + activity.startActivity(any()) + } + } + + @Test + fun handleMozillaUrlCommitted() { + val url = "moz://a" + + controller.handleUrlCommitted(url) + + verify { + activity.openToBrowserAndLoad( + searchTermOrURL = SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.MANIFESTO), + newTab = false, + from = BrowserDirection.FromSearchDialog, + engine = searchEngine + ) + } + verify { metrics.track(Event.EnteredUrl(false)) } + } + + @Test + fun handleEditingCancelled() = runBlockingTest { + controller.handleEditingCancelled() + + verify { + clearToolbarFocus() + } + } + + @Test + fun handleTextChangedNonEmpty() { + val text = "fenix" + + controller.handleTextChanged(text) + + verify { store.dispatch(SearchFragmentAction.UpdateQuery(text)) } + } + + @Test + fun handleTextChangedEmpty() { + val text = "" + + controller.handleTextChanged(text) + + verify { store.dispatch(SearchFragmentAction.UpdateQuery(text)) } + } + + @Test + fun `show search shortcuts when setting enabled AND query empty`() { + val text = "" + every { settings.shouldShowSearchShortcuts } returns true + + controller.handleTextChanged(text) + + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(true)) } + } + + @Test + fun `show search shortcuts when setting enabled AND query equals url`() { + val text = "mozilla.org" + every { store.state.url } returns "mozilla.org" + every { settings.shouldShowSearchShortcuts } returns true + + controller.handleTextChanged(text) + + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(true)) } + } + + @Test + fun `do not show search shortcuts when setting enabled AND query non-empty`() { + val text = "mozilla" + + controller.handleTextChanged(text) + + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) } + } + + @Test + fun `do not show search shortcuts when setting disabled AND query empty AND url not matching query`() { + every { settings.shouldShowSearchShortcuts } returns false + + val text = "" + + controller.handleTextChanged(text) + + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) } + } + + @Test + fun `do not show search shortcuts when setting disabled AND query non-empty`() { + every { settings.shouldShowSearchShortcuts } returns false + + val text = "mozilla" + + controller.handleTextChanged(text) + + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) } + } + + @Test + fun handleUrlTapped() { + val url = "https://www.google.com/" + + controller.handleUrlTapped(url) + + verify { + activity.openToBrowserAndLoad( + searchTermOrURL = url, + newTab = false, + from = BrowserDirection.FromSearchDialog + ) + } + verify { metrics.track(Event.EnteredUrl(false)) } + } + + @Test + fun handleSearchTermsTapped() { + val searchTerms = "fenix" + + controller.handleSearchTermsTapped(searchTerms) + + verify { + activity.openToBrowserAndLoad( + searchTermOrURL = searchTerms, + newTab = false, + from = BrowserDirection.FromSearchDialog, + engine = searchEngine, + forceSearch = true + ) + } + } + + @Test + fun handleSearchShortcutEngineSelected() { + val searchEngine: SearchEngine = mockk(relaxed = true) + + controller.handleSearchShortcutEngineSelected(searchEngine) + + verify { store.dispatch(SearchFragmentAction.SearchShortcutEngineSelected(searchEngine)) } + verify { metrics.track(Event.SearchShortcutSelected(searchEngine, false)) } + } + + @Test + fun handleClickSearchEngineSettings() { + val directions: NavDirections = + SearchDialogFragmentDirections.actionGlobalSearchEngineFragment() + + controller.handleClickSearchEngineSettings() + + verify { navController.navigateSafe(R.id.searchEngineFragment, directions) } + } + + @Test + fun handleSearchShortcutsButtonClicked_alreadyOpen() { + every { store.state.showSearchShortcuts } returns true + + controller.handleSearchShortcutsButtonClicked() + + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(false)) } + } + + @Test + fun handleSearchShortcutsButtonClicked_notYetOpen() { + every { store.state.showSearchShortcuts } returns false + + controller.handleSearchShortcutsButtonClicked() + + verify { store.dispatch(SearchFragmentAction.ShowSearchShortcutEnginePicker(true)) } + } + + @Test + fun handleExistingSessionSelected() { + val session = mockk() + + controller.handleExistingSessionSelected(session) + + verify { sessionManager.select(session) } + verify { activity.openToBrowser(from = BrowserDirection.FromSearchDialog) } + } + + @Test + fun handleExistingSessionSelected_tabId_nullSession() { + every { sessionManager.findSessionById("tab-id") } returns null + + controller.handleExistingSessionSelected("tab-id") + + verify(inverse = true) { sessionManager.select(any()) } + verify(inverse = true) { activity.openToBrowser(from = BrowserDirection.FromSearchDialog) } + } + + @Test + fun handleExistingSessionSelected_tabId() { + val session = mockk() + every { sessionManager.findSessionById("tab-id") } returns session + + controller.handleExistingSessionSelected("tab-id") + + verify { sessionManager.select(any()) } + verify { activity.openToBrowser(from = BrowserDirection.FromSearchDialog) } + } +} From 1fab28f0432aa76e7c370130a47762b3b23d1624 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Fri, 7 Aug 2020 15:24:31 -0700 Subject: [PATCH 15/33] Add createInitialSearchFragmentState function --- .../mozilla/fenix/search/SearchFragment.kt | 58 ++++------------- .../fenix/search/SearchFragmentStore.kt | 50 +++++++++++++++ .../fenix/search/ext/SearchEngineProvider.kt | 17 +++++ .../searchdialog/SearchDialogFragment.kt | 64 ++++--------------- 4 files changed, 90 insertions(+), 99 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/search/ext/SearchEngineProvider.kt diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt b/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt index bae126a1e5..d407a8d913 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt @@ -30,7 +30,6 @@ import kotlinx.android.synthetic.main.fragment_search.* import kotlinx.android.synthetic.main.fragment_search.view.* import kotlinx.android.synthetic.main.search_suggestions_onboarding.view.* import kotlinx.coroutines.ExperimentalCoroutinesApi -import mozilla.components.browser.state.selector.findTab import mozilla.components.browser.toolbar.BrowserToolbar import mozilla.components.concept.storage.HistoryStorage import mozilla.components.feature.qr.QrFeature @@ -55,6 +54,7 @@ import org.mozilla.fenix.ext.hideToolbar import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.settings import org.mozilla.fenix.search.awesomebar.AwesomeBarView +import org.mozilla.fenix.search.ext.areShortcutsAvailable import org.mozilla.fenix.search.toolbar.ToolbarView import org.mozilla.fenix.settings.SupportUtils import org.mozilla.fenix.settings.registerOnSharedPreferenceChangeListener @@ -71,14 +71,6 @@ class SearchFragment : Fragment(), UserInteractionHandler { private val speechIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) - private fun shouldShowSearchSuggestions(isPrivate: Boolean): Boolean = - if (isPrivate) { - requireContext().settings().shouldShowSearchSuggestions && - requireContext().settings().shouldShowSearchSuggestionsInPrivate - } else { - requireContext().settings().shouldShowSearchSuggestions - } - @Suppress("LongMethod") override fun onCreateView( inflater: LayoutInflater, @@ -89,38 +81,18 @@ class SearchFragment : Fragment(), UserInteractionHandler { val settings = activity.settings() val args by navArgs() - val tabId = args.sessionId - val tab = tabId?.let { requireComponents.core.store.state.findTab(it) } - val view = inflater.inflate(R.layout.fragment_search, container, false) - val url = tab?.content?.url.orEmpty() - val currentSearchEngine = SearchEngineSource.Default( - requireComponents.search.provider.getDefaultEngine(requireContext()) - ) val isPrivate = activity.browsingModeManager.mode.isPrivate requireComponents.analytics.metrics.track(Event.InteractWithSearchURLArea) - val areShortcutsAvailable = areShortcutsAvailable() searchStore = StoreProvider.get(this) { SearchFragmentStore( - SearchFragmentState( - query = url, - url = url, - searchTerms = tab?.content?.searchTerms.orEmpty(), - searchEngineSource = currentSearchEngine, - defaultEngineSource = currentSearchEngine, - showSearchSuggestions = shouldShowSearchSuggestions(isPrivate), - showSearchSuggestionsHint = false, - showSearchShortcuts = settings.shouldShowSearchShortcuts && - url.isEmpty() && - areShortcutsAvailable, - areShortcutsAvailable = areShortcutsAvailable, - showClipboardSuggestions = settings.shouldShowClipboardSuggestions, - showHistorySuggestions = settings.shouldShowHistorySuggestions, - showBookmarkSuggestions = settings.shouldShowBookmarkSuggestions, - tabId = tabId, + createInitialSearchFragmentState( + activity, + requireComponents, + tabId = args.sessionId, pastedText = args.pastedText, searchAccessPoint = args.searchAccessPoint ) @@ -165,7 +137,7 @@ class SearchFragment : Fragment(), UserInteractionHandler { ContextCompat.getDrawable(requireContext(), R.drawable.ic_microphone)!!, requireContext().getString(R.string.voice_search_content_description), visible = { - currentSearchEngine.searchEngine.identifier.contains("google") && + searchStore.state.searchEngineSource.searchEngine.identifier.contains("google") && speechIsAvailable() && settings.shouldShowVoiceSearch }, @@ -343,10 +315,11 @@ class SearchFragment : Fragment(), UserInteractionHandler { override fun onResume() { super.onResume() + val provider = requireComponents.search.provider + // The user has the option to go to 'Shortcuts' -> 'Search engine settings' to modify the default search engine. // When returning from that settings screen we need to update it to account for any changes. - val currentDefaultEngine = - requireComponents.search.provider.getDefaultEngine(requireContext()) + val currentDefaultEngine = provider.getDefaultEngine(requireContext()) if (searchStore.state.defaultEngineSource.searchEngine != currentDefaultEngine) { searchStore.dispatch( @@ -356,7 +329,7 @@ class SearchFragment : Fragment(), UserInteractionHandler { } // Users can from this fragment go to install/uninstall search engines and then return. - val areShortcutsAvailable = areShortcutsAvailable() + val areShortcutsAvailable = provider.areShortcutsAvailable(requireContext()) if (searchStore.state.areShortcutsAvailable != areShortcutsAvailable) { searchStore.dispatch(SearchFragmentAction.UpdateShortcutsAvailability(areShortcutsAvailable)) } @@ -367,7 +340,7 @@ class SearchFragment : Fragment(), UserInteractionHandler { updateClipboardSuggestion( searchStore.state, - requireContext().components.clipboardHandler.url + requireComponents.clipboardHandler.url ) permissionDidUpdate = false @@ -470,16 +443,7 @@ class SearchFragment : Fragment(), UserInteractionHandler { } } - /** - * Return if the user has *at least 2* installed search engines. - * Useful to decide whether to show / enable certain functionalities. - */ - private fun areShortcutsAvailable() = - requireContext().components.search.provider.installedSearchEngines(requireContext()) - .list.size >= MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS - companion object { private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1 - private const val MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS = 2 } } diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt b/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt index 4bf57c5226..ac5996a91e 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt @@ -5,10 +5,15 @@ package org.mozilla.fenix.search import mozilla.components.browser.search.SearchEngine +import mozilla.components.browser.state.selector.findTab import mozilla.components.lib.state.Action import mozilla.components.lib.state.State import mozilla.components.lib.state.Store +import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.components.Components import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.search.ext.areShortcutsAvailable /** * The [Store] for holding the [SearchFragmentState] and applying [SearchFragmentAction]s. @@ -66,6 +71,51 @@ data class SearchFragmentState( val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint? ) : State +fun createInitialSearchFragmentState( + activity: HomeActivity, + components: Components, + tabId: String?, + pastedText: String?, + searchAccessPoint: Event.PerformedSearch.SearchAccessPoint +): SearchFragmentState { + val settings = components.settings + val tab = tabId?.let { components.core.store.state.findTab(it) } + + val url = tab?.content?.url.orEmpty() + val currentSearchEngine = SearchEngineSource.Default( + components.search.provider.getDefaultEngine(activity) + ) + + val browsingMode = activity.browsingModeManager.mode + val areShortcutsAvailable = components.search.provider.areShortcutsAvailable(activity) + + val shouldShowSearchSuggestions = when (browsingMode) { + BrowsingMode.Normal -> settings.shouldShowSearchSuggestions + BrowsingMode.Private -> + settings.shouldShowSearchSuggestions && settings.shouldShowSearchSuggestionsInPrivate + } + + return SearchFragmentState( + query = url, + url = url, + searchTerms = tab?.content?.searchTerms.orEmpty(), + searchEngineSource = currentSearchEngine, + defaultEngineSource = currentSearchEngine, + showSearchSuggestions = shouldShowSearchSuggestions, + showSearchSuggestionsHint = false, + showSearchShortcuts = url.isEmpty() && + areShortcutsAvailable && + settings.shouldShowSearchShortcuts, + areShortcutsAvailable = areShortcutsAvailable, + showClipboardSuggestions = settings.shouldShowClipboardSuggestions, + showHistorySuggestions = settings.shouldShowHistorySuggestions, + showBookmarkSuggestions = settings.shouldShowBookmarkSuggestions, + tabId = tabId, + pastedText = pastedText, + searchAccessPoint = searchAccessPoint + ) +} + /** * Actions to dispatch through the `SearchStore` to modify `SearchState` through the reducer. */ diff --git a/app/src/main/java/org/mozilla/fenix/search/ext/SearchEngineProvider.kt b/app/src/main/java/org/mozilla/fenix/search/ext/SearchEngineProvider.kt new file mode 100644 index 0000000000..cbb598fd87 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/search/ext/SearchEngineProvider.kt @@ -0,0 +1,17 @@ +/* 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.search.ext + +import android.content.Context +import org.mozilla.fenix.components.searchengine.FenixSearchEngineProvider + +private const val MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS = 2 + +/** + * Return if the user has *at least 2* installed search engines. + * Useful to decide whether to show / enable certain functionalities. + */ +fun FenixSearchEngineProvider.areShortcutsAvailable(context: Context) = + installedSearchEngines(context).list.size >= MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS diff --git a/app/src/main/java/org/mozilla/fenix/searchdialog/SearchDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/searchdialog/SearchDialogFragment.kt index 41ca59eacb..9c869aa814 100644 --- a/app/src/main/java/org/mozilla/fenix/searchdialog/SearchDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/searchdialog/SearchDialogFragment.kt @@ -19,33 +19,22 @@ import androidx.navigation.fragment.navArgs import kotlinx.android.synthetic.main.fragment_search.view.* import kotlinx.android.synthetic.main.fragment_search_dialog.* import kotlinx.coroutines.ExperimentalCoroutinesApi -import mozilla.components.browser.state.selector.findTab import mozilla.components.lib.state.ext.consumeFrom import mozilla.components.support.base.feature.UserInteractionHandler import mozilla.components.support.ktx.android.view.hideKeyboard import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.components.toolbar.ToolbarPosition -import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.search.SearchEngineSource -import org.mozilla.fenix.search.SearchFragmentState import org.mozilla.fenix.search.SearchFragmentStore import org.mozilla.fenix.search.SearchInteractor import org.mozilla.fenix.search.awesomebar.AwesomeBarView +import org.mozilla.fenix.search.createInitialSearchFragmentState import org.mozilla.fenix.search.toolbar.ToolbarView -import org.mozilla.fenix.utils.Settings typealias SearchDialogFragmentStore = SearchFragmentStore typealias SearchDialogInteractor = SearchInteractor -fun Settings.shouldShowSearchSuggestions(isPrivate: Boolean): Boolean { - return if (isPrivate) { - shouldShowSearchSuggestions && shouldShowSearchSuggestionsInPrivate - } else { - shouldShowSearchSuggestions - } -} class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { @@ -72,8 +61,18 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { container: ViewGroup?, savedInstanceState: Bundle? ): View? { + val args by navArgs() val view = inflater.inflate(R.layout.fragment_search_dialog, container, false) - store = SearchDialogFragmentStore(setUpState()) + + store = SearchDialogFragmentStore( + createInitialSearchFragmentState( + activity as HomeActivity, + requireComponents, + tabId = args.sessionId, + pastedText = args.pastedText, + searchAccessPoint = args.searchAccessPoint + ) + ) interactor = SearchDialogInteractor( SearchDialogController( @@ -146,43 +145,4 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { return true } - - private fun setUpState(): SearchFragmentState { - val activity = activity as HomeActivity - val settings = activity.settings() - val args by navArgs() - val tabId = args.sessionId - val tab = tabId?.let { requireComponents.core.store.state.findTab(it) } - val url = tab?.content?.url.orEmpty() - val currentSearchEngine = SearchEngineSource.Default( - requireComponents.search.provider.getDefaultEngine(requireContext()) - ) - val isPrivate = activity.browsingModeManager.mode.isPrivate - val areShortcutsAvailable = - requireContext().components.search.provider.installedSearchEngines(requireContext()) - .list.size >= MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS - return SearchFragmentState( - query = url, - url = url, - searchTerms = tab?.content?.searchTerms.orEmpty(), - searchEngineSource = currentSearchEngine, - defaultEngineSource = currentSearchEngine, - showSearchSuggestions = settings.shouldShowSearchSuggestions(isPrivate), - showSearchSuggestionsHint = false, - showSearchShortcuts = settings.shouldShowSearchShortcuts && - url.isEmpty() && - areShortcutsAvailable, - areShortcutsAvailable = areShortcutsAvailable, - showClipboardSuggestions = settings.shouldShowClipboardSuggestions, - showHistorySuggestions = settings.shouldShowHistorySuggestions, - showBookmarkSuggestions = settings.shouldShowBookmarkSuggestions, - tabId = tabId, - pastedText = args.pastedText, - searchAccessPoint = args.searchAccessPoint - ) - } - - companion object { - private const val MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS = 2 - } } From 0aab7a806a0748e5344ccd7357da68e49cfaa71a Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Fri, 7 Aug 2020 15:58:58 -0700 Subject: [PATCH 16/33] Add test for createInitialSearchFragmentState --- .../fenix/search/SearchFragmentStoreTest.kt | 134 +++++++++++++++++- 1 file changed, 128 insertions(+), 6 deletions(-) diff --git a/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt b/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt index 00b50a0a0d..39c65111df 100644 --- a/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt @@ -4,20 +4,144 @@ package org.mozilla.fenix.search +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.MockK import io.mockk.mockk import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking import mozilla.components.browser.search.SearchEngine +import mozilla.components.browser.search.provider.SearchEngineList +import mozilla.components.browser.state.state.BrowserState +import mozilla.components.browser.state.state.ContentState +import mozilla.components.browser.state.state.TabSessionState import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotSame import org.junit.Assert.assertTrue +import org.junit.Before import org.junit.Test -import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager +import org.mozilla.fenix.components.Components +import org.mozilla.fenix.components.metrics.Event.PerformedSearch.SearchAccessPoint +import org.mozilla.fenix.components.searchengine.FenixSearchEngineProvider +import org.mozilla.fenix.utils.Settings @ExperimentalCoroutinesApi class SearchFragmentStoreTest { + @MockK private lateinit var searchEngine: SearchEngine + @MockK private lateinit var searchProvider: FenixSearchEngineProvider + @MockK private lateinit var activity: HomeActivity + @MockK(relaxed = true) private lateinit var components: Components + @MockK(relaxed = true) private lateinit var settings: Settings + + @Before + fun setup() { + MockKAnnotations.init(this) + every { activity.browsingModeManager } returns object : BrowsingModeManager { + override var mode: BrowsingMode = BrowsingMode.Normal + } + every { components.settings } returns settings + every { components.search.provider } returns searchProvider + every { searchProvider.getDefaultEngine(activity) } returns searchEngine + every { searchProvider.installedSearchEngines(activity) } returns SearchEngineList( + list = listOf(mockk(), mockk()), + default = searchEngine + ) + } + + @Test + fun `createInitialSearchFragmentState with no tab`() { + activity.browsingModeManager.mode = BrowsingMode.Normal + every { components.core.store.state } returns BrowserState() + every { settings.shouldShowSearchShortcuts } returns true + + val expected = SearchFragmentState( + query = "", + url = "", + searchTerms = "", + searchEngineSource = SearchEngineSource.Default(searchEngine), + defaultEngineSource = SearchEngineSource.Default(searchEngine), + showSearchSuggestions = false, + showSearchSuggestionsHint = false, + showSearchShortcuts = true, + areShortcutsAvailable = true, + showClipboardSuggestions = false, + showHistorySuggestions = false, + showBookmarkSuggestions = false, + tabId = null, + pastedText = "pastedText", + searchAccessPoint = SearchAccessPoint.ACTION + ) + + assertEquals( + expected, + createInitialSearchFragmentState( + activity, + components, + tabId = null, + pastedText = "pastedText", + searchAccessPoint = SearchAccessPoint.ACTION + ) + ) + assertEquals( + expected.copy(tabId = "tabId"), + createInitialSearchFragmentState( + activity, + components, + tabId = "tabId", + pastedText = "pastedText", + searchAccessPoint = SearchAccessPoint.ACTION + ) + ) + } + + @Test + fun `createInitialSearchFragmentState with tab`() { + activity.browsingModeManager.mode = BrowsingMode.Private + every { components.core.store.state } returns BrowserState( + tabs = listOf( + TabSessionState( + id = "tabId", + content = ContentState( + url = "https://example.com", + searchTerms = "search terms" + ) + ) + ) + ) + + assertEquals( + SearchFragmentState( + query = "https://example.com", + url = "https://example.com", + searchTerms = "search terms", + searchEngineSource = SearchEngineSource.Default(searchEngine), + defaultEngineSource = SearchEngineSource.Default(searchEngine), + showSearchSuggestions = false, + showSearchSuggestionsHint = false, + showSearchShortcuts = false, + areShortcutsAvailable = true, + showClipboardSuggestions = false, + showHistorySuggestions = false, + showBookmarkSuggestions = false, + tabId = "tabId", + pastedText = "", + searchAccessPoint = SearchAccessPoint.SHORTCUT + ), + createInitialSearchFragmentState( + activity, + components, + tabId = "tabId", + pastedText = "", + searchAccessPoint = SearchAccessPoint.SHORTCUT + ) + ) + } + @Test fun updateQuery() = runBlocking { val initialState = emptyDefaultState() @@ -33,7 +157,6 @@ class SearchFragmentStoreTest { fun selectSearchShortcutEngine() = runBlocking { val initialState = emptyDefaultState() val store = SearchFragmentStore(initialState) - val searchEngine: SearchEngine = mockk() store.dispatch(SearchFragmentAction.SearchShortcutEngineSelected(searchEngine)).join() assertNotSame(initialState, store.state) @@ -91,11 +214,10 @@ class SearchFragmentStoreTest { fun selectNewDefaultEngine() = runBlocking { val initialState = emptyDefaultState() val store = SearchFragmentStore(initialState) - val engine = mockk() - store.dispatch(SearchFragmentAction.SelectNewDefaultSearchEngine(engine)).join() + store.dispatch(SearchFragmentAction.SelectNewDefaultSearchEngine(searchEngine)).join() assertNotSame(initialState, store.state) - assertEquals(SearchEngineSource.Default(engine), store.state.searchEngineSource) + assertEquals(SearchEngineSource.Default(searchEngine), store.state.searchEngineSource) } private fun emptyDefaultState(): SearchFragmentState = SearchFragmentState( @@ -112,6 +234,6 @@ class SearchFragmentStoreTest { showClipboardSuggestions = false, showHistorySuggestions = false, showBookmarkSuggestions = false, - searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.NONE + searchAccessPoint = SearchAccessPoint.NONE ) } From 6d8cfe1a508e448f49fbce41f2af6b49c587e82a Mon Sep 17 00:00:00 2001 From: Kainalu Hagiwara Date: Tue, 4 Aug 2020 16:26:03 -0700 Subject: [PATCH 17/33] For #13156, #13280 - Use payloads to bind bookmark viewholders. Change the DiffUtil callback for bookmarks to use the generated equals() method instead of only checking the title and url fields. This prevents the BookmarkNode in our state from getting out of sync with the BookmarkNode the viewholder is bound to. --- .../library/bookmarks/BookmarkAdapter.kt | 42 ++++++++++++++++++- .../fenix/library/bookmarks/BookmarkView.kt | 4 -- .../viewholders/BookmarkFolderViewHolder.kt | 31 ++++++++++---- .../viewholders/BookmarkItemViewHolder.kt | 42 ++++++++++++++----- .../viewholders/BookmarkNodeViewHolder.kt | 7 ++++ .../BookmarkSeparatorViewHolder.kt | 9 ++++ 6 files changed, 110 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt index 8aafaaed15..ffcea74552 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt @@ -59,9 +59,20 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto old[oldItemPosition].guid == new[newItemPosition].guid override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = + oldMode::class == newMode::class && old[oldItemPosition] in oldMode.selectedItems == new[newItemPosition] in newMode.selectedItems && - old[oldItemPosition].title == new[newItemPosition].title && - old[oldItemPosition].url == new[newItemPosition].url + old[oldItemPosition] == new[newItemPosition] + + override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? { + val oldItem = old[oldItemPosition] + val newItem = new[newItemPosition] + return BookmarkPayload( + titleChanged = oldItem.title != newItem.title, + urlChanged = oldItem.url != newItem.url, + selectedChanged = oldItem in oldMode.selectedItems != newItem in newMode.selectedItems, + modeChanged = oldMode::class != newMode::class + ) + } override fun getOldListSize(): Int = old.size override fun getNewListSize(): Int = new.size @@ -90,9 +101,36 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto override fun getItemCount(): Int = tree.size + override fun onBindViewHolder( + holder: BookmarkNodeViewHolder, + position: Int, + payloads: MutableList + ) { + if (payloads.isNotEmpty() && payloads[0] is BookmarkPayload) { + holder.bind(tree[position], mode, payloads[0] as BookmarkPayload) + } else { + super.onBindViewHolder(holder, position, payloads) + } + } + override fun onBindViewHolder(holder: BookmarkNodeViewHolder, position: Int) { holder.bind(tree[position], mode) } } +/** + * A RecyclerView Adapter payload class that contains information about changes to a [BookmarkNode]. + * + * @property titleChanged true if there has been a change to [BookmarkNode.title]. + * @property urlChanged true if there has been a change to [BookmarkNode.url]. + * @property selectedChanged true if there has been a change in the BookmarkNode's selected state. + * @property modeChanged true if there has been a change in the state's mode type. + */ +data class BookmarkPayload( + val titleChanged: Boolean, + val urlChanged: Boolean, + val selectedChanged: Boolean, + val modeChanged: Boolean +) + fun BookmarkNode.inRoots() = enumValues().any { it.id == guid } diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkView.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkView.kt index b9f3c6911b..6d4b0c690e 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkView.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkView.kt @@ -139,7 +139,6 @@ class BookmarkView( } fun update(state: BookmarkFragmentState) { - val oldMode = mode tree = state.tree if (state.mode != mode) { mode = state.mode @@ -149,9 +148,6 @@ class BookmarkView( } bookmarkAdapter.updateData(state.tree, mode) - if (state.mode != oldMode) { - bookmarkAdapter.notifyDataSetChanged() - } when (mode) { is BookmarkFragmentState.Mode.Normal -> { diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt index 5941dc4da0..70e418b989 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt @@ -14,6 +14,7 @@ import org.mozilla.fenix.ext.showAndEnable import org.mozilla.fenix.library.LibrarySiteItemView import org.mozilla.fenix.library.SelectionHolder import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState +import org.mozilla.fenix.library.bookmarks.BookmarkPayload import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor import org.mozilla.fenix.library.bookmarks.inRoots @@ -28,28 +29,39 @@ class BookmarkFolderViewHolder( override var item: BookmarkNode? = null + init { + containerView.displayAs(LibrarySiteItemView.ItemType.FOLDER) + } + override fun bind( item: BookmarkNode, mode: BookmarkFragmentState.Mode ) { - this.item = item + bind(item, mode, BookmarkPayload(true, true, true, true)) + } - containerView.displayAs(LibrarySiteItemView.ItemType.FOLDER) + override fun bind(item: BookmarkNode, mode: BookmarkFragmentState.Mode, payload: BookmarkPayload) { + this.item = item setSelectionListeners(item, selectionHolder) if (!item.inRoots()) { setupMenu(item) - if (mode is BookmarkFragmentState.Mode.Selecting) { - containerView.overflowView.hideAndDisable() - } else { - containerView.overflowView.showAndEnable() + if (payload.modeChanged) { + if (mode is BookmarkFragmentState.Mode.Selecting) { + containerView.overflowView.hideAndDisable() + } else { + containerView.overflowView.showAndEnable() + } } } else { containerView.overflowView.visibility = View.GONE } - containerView.changeSelected(item in selectionHolder.selectedItems) + if (payload.selectedChanged) { + containerView.changeSelected(item in selectionHolder.selectedItems) + } + containerView.iconView.setImageDrawable( AppCompatResources.getDrawable( containerView.context, @@ -63,6 +75,9 @@ class BookmarkFolderViewHolder( ) } ) - containerView.titleView.text = item.title + + if (payload.titleChanged) { + containerView.titleView.text = item.title + } } } diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt index 6ef5f87a38..840b716ef6 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt @@ -10,6 +10,7 @@ import org.mozilla.fenix.ext.showAndEnable import org.mozilla.fenix.library.LibrarySiteItemView import org.mozilla.fenix.library.SelectionHolder import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState +import org.mozilla.fenix.library.bookmarks.BookmarkPayload import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor /** @@ -23,27 +24,46 @@ class BookmarkItemViewHolder( override var item: BookmarkNode? = null + init { + containerView.displayAs(LibrarySiteItemView.ItemType.SITE) + } + override fun bind( item: BookmarkNode, mode: BookmarkFragmentState.Mode ) { + bind(item, mode, BookmarkPayload(true, true, true, true)) + } + + override fun bind(item: BookmarkNode, mode: BookmarkFragmentState.Mode, payload: BookmarkPayload) { this.item = item - containerView.displayAs(LibrarySiteItemView.ItemType.SITE) + setupMenu(item) - if (mode is BookmarkFragmentState.Mode.Selecting) { - containerView.overflowView.hideAndDisable() - } else { - containerView.overflowView.showAndEnable() + if (payload.modeChanged) { + if (mode is BookmarkFragmentState.Mode.Selecting) { + containerView.overflowView.hideAndDisable() + } else { + containerView.overflowView.showAndEnable() + } } - setupMenu(item) - containerView.titleView.text = if (item.title.isNullOrBlank()) item.url else item.title - containerView.urlView.text = item.url - setSelectionListeners(item, selectionHolder) + if (payload.selectedChanged) { + containerView.changeSelected(item in selectionHolder.selectedItems) + } + + if (payload.titleChanged) { + containerView.titleView.text = if (item.title.isNullOrBlank()) item.url else item.title + } else if (payload.urlChanged && item.title.isNullOrBlank()) { + containerView.titleView.text = item.url + } + + if (payload.urlChanged) { + containerView.urlView.text = item.url + setColorsAndIcons(item.url) + } - containerView.changeSelected(item in selectionHolder.selectedItems) - setColorsAndIcons(item.url) + setSelectionListeners(item, selectionHolder) } private fun setColorsAndIcons(url: String?) { diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkNodeViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkNodeViewHolder.kt index 9e6d7caeef..7513234672 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkNodeViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkNodeViewHolder.kt @@ -11,6 +11,7 @@ import org.mozilla.fenix.library.LibrarySiteItemView import org.mozilla.fenix.library.SelectionHolder import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState import org.mozilla.fenix.library.bookmarks.BookmarkItemMenu +import org.mozilla.fenix.library.bookmarks.BookmarkPayload import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor /** @@ -28,6 +29,12 @@ abstract class BookmarkNodeViewHolder( mode: BookmarkFragmentState.Mode ) + abstract fun bind( + item: BookmarkNode, + mode: BookmarkFragmentState.Mode, + payload: BookmarkPayload + ) + protected fun setSelectionListeners(item: BookmarkNode, selectionHolder: SelectionHolder) { containerView.setSelectionInteractor(item, selectionHolder, interactor) } diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkSeparatorViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkSeparatorViewHolder.kt index daafbf0bac..d1789fa941 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkSeparatorViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkSeparatorViewHolder.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.library.bookmarks.viewholders import mozilla.components.concept.storage.BookmarkNode import org.mozilla.fenix.library.LibrarySiteItemView import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState +import org.mozilla.fenix.library.bookmarks.BookmarkPayload import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor /** @@ -27,4 +28,12 @@ class BookmarkSeparatorViewHolder( containerView.displayAs(LibrarySiteItemView.ItemType.SEPARATOR) setupMenu(item) } + + override fun bind( + item: BookmarkNode, + mode: BookmarkFragmentState.Mode, + payload: BookmarkPayload + ) { + bind(item, mode) + } } From b1db1cf9767a9a5851fac97ffcaefafbf22067ef Mon Sep 17 00:00:00 2001 From: Kainalu Hagiwara Date: Wed, 5 Aug 2020 10:00:54 -0700 Subject: [PATCH 18/33] Add tests for Bookmarks DiffUtil and ViewHolders. --- .../library/bookmarks/BookmarkAdapter.kt | 4 +- .../viewholders/BookmarkItemViewHolder.kt | 4 +- .../library/bookmarks/BookmarkAdapterTest.kt | 62 +++++++- .../BookmarkFolderViewHolderTest.kt | 91 +++++++++++ .../viewholders/BookmarkItemViewHolderTest.kt | 147 ++++++++++++++++++ 5 files changed, 305 insertions(+), 3 deletions(-) create mode 100644 app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolderTest.kt create mode 100644 app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolderTest.kt diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt index ffcea74552..e191bffa39 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.library.bookmarks import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.VisibleForTesting import androidx.core.view.isVisible import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView @@ -49,7 +50,8 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto diffUtil.dispatchUpdatesTo(this) } - private class BookmarkDiffUtil( + @VisibleForTesting + internal class BookmarkDiffUtil( val old: List, val new: List, val oldMode: BookmarkFragmentState.Mode, diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt index 840b716ef6..b97fe86c75 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.library.bookmarks.viewholders +import androidx.annotation.VisibleForTesting import mozilla.components.concept.storage.BookmarkNode import org.mozilla.fenix.ext.hideAndDisable import org.mozilla.fenix.ext.showAndEnable @@ -66,7 +67,8 @@ class BookmarkItemViewHolder( setSelectionListeners(item, selectionHolder) } - private fun setColorsAndIcons(url: String?) { + @VisibleForTesting + internal fun setColorsAndIcons(url: String?) { if (url != null && url.startsWith("http")) { containerView.loadFavicon(url) } else { diff --git a/app/src/test/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapterTest.kt b/app/src/test/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapterTest.kt index 12ae932ed2..b80e584a7f 100644 --- a/app/src/test/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapterTest.kt +++ b/app/src/test/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapterTest.kt @@ -9,6 +9,8 @@ import io.mockk.spyk import io.mockk.verifyOrder import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.BookmarkNodeType +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -19,6 +21,16 @@ internal class BookmarkAdapterTest { private lateinit var bookmarkAdapter: BookmarkAdapter + private val item = BookmarkNode( + BookmarkNodeType.ITEM, + "456", + "123", + 0, + "Mozilla", + "http://mozilla.org", + null + ) + @Before fun setup() { bookmarkAdapter = spyk( @@ -30,7 +42,7 @@ internal class BookmarkAdapterTest { fun `update adapter from tree of bookmark nodes, null tree returns empty list`() { val tree = BookmarkNode( BookmarkNodeType.FOLDER, "123", null, 0, "Mobile", null, listOf( - BookmarkNode(BookmarkNodeType.ITEM, "456", "123", 0, "Mozilla", "http://mozilla.org", null), + item, BookmarkNode(BookmarkNodeType.SEPARATOR, "789", "123", 1, null, null, null), BookmarkNode( BookmarkNodeType.ITEM, @@ -52,4 +64,52 @@ internal class BookmarkAdapterTest { bookmarkAdapter.notifyItemRangeRemoved(0, 3) } } + + @Test + fun `items are the same if they have the same guids`() { + assertTrue(createSingleItemDiffUtil(item, item).areItemsTheSame(0, 0)) + assertTrue( + createSingleItemDiffUtil( + item, + item.copy(title = "Wikipedia.org", url = "https://www.wikipedia.org") + ).areItemsTheSame(0, 0) + ) + assertFalse( + createSingleItemDiffUtil( + item, + item.copy(guid = "111") + ).areItemsTheSame(0, 0) + ) + } + + @Test + fun `equal items have same contents unless their selected state changes`() { + assertTrue(createSingleItemDiffUtil(item, item).areContentsTheSame(0, 0)) + assertFalse( + createSingleItemDiffUtil(item, item.copy(position = 1)).areContentsTheSame(0, 0) + ) + assertFalse( + createSingleItemDiffUtil( + item, + item, + oldMode = BookmarkFragmentState.Mode.Selecting(setOf(item)) + ).areContentsTheSame(0, 0) + ) + assertFalse( + createSingleItemDiffUtil( + item, + item, + newMode = BookmarkFragmentState.Mode.Selecting(setOf(item)) + ).areContentsTheSame(0, 0) + ) + } + + private fun createSingleItemDiffUtil( + oldItem: BookmarkNode, + newItem: BookmarkNode, + oldMode: BookmarkFragmentState.Mode = BookmarkFragmentState.Mode.Normal(), + newMode: BookmarkFragmentState.Mode = BookmarkFragmentState.Mode.Normal() + ): BookmarkAdapter.BookmarkDiffUtil { + return BookmarkAdapter.BookmarkDiffUtil(listOf(oldItem), listOf(newItem), oldMode, newMode) + } } diff --git a/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolderTest.kt new file mode 100644 index 0000000000..e622dbf209 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolderTest.kt @@ -0,0 +1,91 @@ +/* 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.library.bookmarks.viewholders + +import androidx.appcompat.content.res.AppCompatResources +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.verify +import mozilla.components.concept.storage.BookmarkNode +import mozilla.components.concept.storage.BookmarkNodeType +import org.junit.Before +import org.junit.Test +import org.mozilla.fenix.ext.hideAndDisable +import org.mozilla.fenix.ext.showAndEnable +import org.mozilla.fenix.library.LibrarySiteItemView +import org.mozilla.fenix.library.SelectionHolder +import org.mozilla.fenix.library.bookmarks.BookmarkFragmentInteractor +import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState +import org.mozilla.fenix.library.bookmarks.BookmarkPayload + +class BookmarkFolderViewHolderTest { + + @MockK + private lateinit var interactor: BookmarkFragmentInteractor + @MockK(relaxed = true) + private lateinit var siteItemView: LibrarySiteItemView + @MockK(relaxed = true) + private lateinit var selectionHolder: SelectionHolder + private lateinit var holder: BookmarkFolderViewHolder + + private val folder = BookmarkNode( + type = BookmarkNodeType.FOLDER, + guid = "456", + parentGuid = "123", + position = 0, + title = "Folder", + url = null, + children = listOf() + ) + + @Before + fun setup() { + MockKAnnotations.init(this) + + mockkStatic(AppCompatResources::class) + every { AppCompatResources.getDrawable(any(), any()) } returns mockk(relaxed = true) + + holder = BookmarkFolderViewHolder(siteItemView, interactor, selectionHolder) + } + + @Test + fun `binds title and selected state`() { + holder.bind(folder, BookmarkFragmentState.Mode.Normal()) + + verify { + siteItemView.titleView.text = folder.title + siteItemView.overflowView.showAndEnable() + siteItemView.changeSelected(false) + } + + every { selectionHolder.selectedItems } returns setOf(folder) + holder.bind(folder, BookmarkFragmentState.Mode.Selecting(setOf(folder))) + + verify { + siteItemView.titleView.text = folder.title + siteItemView.overflowView.hideAndDisable() + siteItemView.changeSelected(true) + } + } + + @Test + fun `bind with payload of no changes does not rebind views`() { + holder.bind( + folder, + BookmarkFragmentState.Mode.Normal(), + BookmarkPayload(false, false, false, false) + ) + + verify(inverse = true) { + siteItemView.titleView.text = folder.title + siteItemView.overflowView.showAndEnable() + siteItemView.overflowView.hideAndDisable() + siteItemView.changeSelected(any()) + } + } +} diff --git a/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolderTest.kt new file mode 100644 index 0000000000..36d64172b9 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolderTest.kt @@ -0,0 +1,147 @@ +/* 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.library.bookmarks.viewholders + +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.verify +import mozilla.components.concept.storage.BookmarkNode +import mozilla.components.concept.storage.BookmarkNodeType +import org.junit.Before +import org.junit.Test +import org.mozilla.fenix.ext.hideAndDisable +import org.mozilla.fenix.ext.showAndEnable +import org.mozilla.fenix.library.LibrarySiteItemView +import org.mozilla.fenix.library.SelectionHolder +import org.mozilla.fenix.library.bookmarks.BookmarkFragmentInteractor +import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState +import org.mozilla.fenix.library.bookmarks.BookmarkPayload + +class BookmarkItemViewHolderTest { + + @MockK + private lateinit var interactor: BookmarkFragmentInteractor + + @MockK(relaxed = true) + private lateinit var siteItemView: LibrarySiteItemView + + @MockK(relaxed = true) + private lateinit var selectionHolder: SelectionHolder + private lateinit var holder: BookmarkItemViewHolder + + private val item = BookmarkNode( + type = BookmarkNodeType.ITEM, + guid = "456", + parentGuid = "123", + position = 0, + title = "Mozilla", + url = "https://www.mozilla.org", + children = listOf() + ) + + @Before + fun setup() { + MockKAnnotations.init(this) + holder = BookmarkItemViewHolder(siteItemView, interactor, selectionHolder) + } + + @Test + fun `binds views for unselected item`() { + holder.bind(item, BookmarkFragmentState.Mode.Normal()) + + verify { + siteItemView.setSelectionInteractor(item, selectionHolder, interactor) + siteItemView.titleView.text = item.title + siteItemView.urlView.text = item.url + siteItemView.overflowView.showAndEnable() + siteItemView.changeSelected(false) + holder.setColorsAndIcons(item.url) + } + } + + @Test + fun `binds views for selected item`() { + every { selectionHolder.selectedItems } returns setOf(item) + holder.bind(item, BookmarkFragmentState.Mode.Selecting(setOf(item))) + + verify { + siteItemView.setSelectionInteractor(item, selectionHolder, interactor) + siteItemView.titleView.text = item.title + siteItemView.urlView.text = item.url + siteItemView.overflowView.hideAndDisable() + siteItemView.changeSelected(true) + holder.setColorsAndIcons(item.url) + } + } + + @Test + fun `bind with payload of no changes does not rebind views`() { + holder.bind( + item, + BookmarkFragmentState.Mode.Normal(), + BookmarkPayload(false, false, false, false) + ) + + verify(inverse = true) { + siteItemView.titleView.text = item.title + siteItemView.urlView.text = item.url + siteItemView.overflowView.showAndEnable() + siteItemView.overflowView.hideAndDisable() + siteItemView.changeSelected(any()) + holder.setColorsAndIcons(item.url) + } + } + + @Test + fun `binding an item with a null title uses the url as the title`() { + val item = item.copy(title = null) + holder.bind(item, BookmarkFragmentState.Mode.Normal()) + + verify { siteItemView.titleView.text = item.url } + } + + @Test + fun `binding an item with a blank title uses the url as the title`() { + val item = item.copy(title = " ") + holder.bind(item, BookmarkFragmentState.Mode.Normal()) + + verify { siteItemView.titleView.text = item.url } + } + + @Test + fun `rebinds title if item title is null and the item url has changed`() { + val item = item.copy(title = null) + holder.bind( + item, + BookmarkFragmentState.Mode.Normal(), + BookmarkPayload( + titleChanged = false, + urlChanged = true, + selectedChanged = false, + modeChanged = false + ) + ) + + verify { siteItemView.titleView.text = item.url } + } + + @Test + fun `rebinds title if item title is blank and the item url has changed`() { + val item = item.copy(title = " ") + holder.bind( + item, + BookmarkFragmentState.Mode.Normal(), + BookmarkPayload( + titleChanged = false, + urlChanged = true, + selectedChanged = false, + modeChanged = false + ) + ) + + verify { siteItemView.titleView.text = item.url } + } +} From 1ad9da09b0df0e91da52816c4268a6dcdde626fd Mon Sep 17 00:00:00 2001 From: Kainalu Hagiwara Date: Thu, 6 Aug 2020 12:22:53 -0700 Subject: [PATCH 19/33] Remove selection holder from bookmark viewholder constructors. Now that we're passing the mode to the viewholders in their bind methods, there's no real need to pass them into their constructors. This also allows us to remove the indirection of having the adapter implement the SelectionHolder interface and have the mode implement it directly. --- .../fenix/library/bookmarks/BookmarkAdapter.kt | 10 ++++------ .../library/bookmarks/BookmarkFragmentStore.kt | 5 +++-- .../viewholders/BookmarkFolderViewHolder.kt | 8 +++----- .../viewholders/BookmarkItemViewHolder.kt | 8 +++----- .../viewholders/BookmarkFolderViewHolderTest.kt | 6 +----- .../viewholders/BookmarkItemViewHolderTest.kt | 17 +++++++---------- 6 files changed, 21 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt index e191bffa39..a91bc6277b 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkAdapter.kt @@ -16,18 +16,16 @@ import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.BookmarkNodeType import org.mozilla.fenix.R import org.mozilla.fenix.library.LibrarySiteItemView -import org.mozilla.fenix.library.SelectionHolder import org.mozilla.fenix.library.bookmarks.viewholders.BookmarkFolderViewHolder import org.mozilla.fenix.library.bookmarks.viewholders.BookmarkItemViewHolder import org.mozilla.fenix.library.bookmarks.viewholders.BookmarkNodeViewHolder import org.mozilla.fenix.library.bookmarks.viewholders.BookmarkSeparatorViewHolder -class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteractor) : - RecyclerView.Adapter(), SelectionHolder { +class BookmarkAdapter(private val emptyView: View, private val interactor: BookmarkViewInteractor) : + RecyclerView.Adapter() { private var tree: List = listOf() private var mode: BookmarkFragmentState.Mode = BookmarkFragmentState.Mode.Normal() - override val selectedItems: Set get() = mode.selectedItems private var isFirstRun = true fun updateData(tree: BookmarkNode?, mode: BookmarkFragmentState.Mode) { @@ -85,8 +83,8 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto .inflate(R.layout.bookmark_list_item, parent, false) as LibrarySiteItemView return when (viewType) { - LibrarySiteItemView.ItemType.SITE.ordinal -> BookmarkItemViewHolder(view, interactor, this) - LibrarySiteItemView.ItemType.FOLDER.ordinal -> BookmarkFolderViewHolder(view, interactor, this) + LibrarySiteItemView.ItemType.SITE.ordinal -> BookmarkItemViewHolder(view, interactor) + LibrarySiteItemView.ItemType.FOLDER.ordinal -> BookmarkFolderViewHolder(view, interactor) LibrarySiteItemView.ItemType.SEPARATOR.ordinal -> BookmarkSeparatorViewHolder(view, interactor) else -> throw IllegalStateException("ViewType $viewType does not match to a ViewHolder") } diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragmentStore.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragmentStore.kt index e1c4a8f432..a14a5c023c 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragmentStore.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragmentStore.kt @@ -9,6 +9,7 @@ import mozilla.components.concept.storage.BookmarkNode import mozilla.components.lib.state.Action import mozilla.components.lib.state.State import mozilla.components.lib.state.Store +import org.mozilla.fenix.library.SelectionHolder class BookmarkFragmentStore( initialState: BookmarkFragmentState @@ -32,8 +33,8 @@ data class BookmarkFragmentState( val isLoading: Boolean = true, val isSwipeToRefreshEnabled: Boolean = true ) : State { - sealed class Mode { - open val selectedItems = emptySet() + sealed class Mode : SelectionHolder { + override val selectedItems = emptySet() data class Normal(val showMenu: Boolean = true) : Mode() data class Selecting(override val selectedItems: Set) : Mode() diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt index 70e418b989..8c6eda9afa 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt @@ -12,7 +12,6 @@ import org.mozilla.fenix.R import org.mozilla.fenix.ext.hideAndDisable import org.mozilla.fenix.ext.showAndEnable import org.mozilla.fenix.library.LibrarySiteItemView -import org.mozilla.fenix.library.SelectionHolder import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState import org.mozilla.fenix.library.bookmarks.BookmarkPayload import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor @@ -23,8 +22,7 @@ import org.mozilla.fenix.library.bookmarks.inRoots */ class BookmarkFolderViewHolder( view: LibrarySiteItemView, - interactor: BookmarkViewInteractor, - private val selectionHolder: SelectionHolder + interactor: BookmarkViewInteractor ) : BookmarkNodeViewHolder(view, interactor) { override var item: BookmarkNode? = null @@ -43,7 +41,7 @@ class BookmarkFolderViewHolder( override fun bind(item: BookmarkNode, mode: BookmarkFragmentState.Mode, payload: BookmarkPayload) { this.item = item - setSelectionListeners(item, selectionHolder) + setSelectionListeners(item, mode) if (!item.inRoots()) { setupMenu(item) @@ -59,7 +57,7 @@ class BookmarkFolderViewHolder( } if (payload.selectedChanged) { - containerView.changeSelected(item in selectionHolder.selectedItems) + containerView.changeSelected(item in mode.selectedItems) } containerView.iconView.setImageDrawable( diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt index b97fe86c75..ec1a9a5b49 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt @@ -9,7 +9,6 @@ import mozilla.components.concept.storage.BookmarkNode import org.mozilla.fenix.ext.hideAndDisable import org.mozilla.fenix.ext.showAndEnable import org.mozilla.fenix.library.LibrarySiteItemView -import org.mozilla.fenix.library.SelectionHolder import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState import org.mozilla.fenix.library.bookmarks.BookmarkPayload import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor @@ -19,8 +18,7 @@ import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor */ class BookmarkItemViewHolder( view: LibrarySiteItemView, - interactor: BookmarkViewInteractor, - private val selectionHolder: SelectionHolder + interactor: BookmarkViewInteractor ) : BookmarkNodeViewHolder(view, interactor) { override var item: BookmarkNode? = null @@ -50,7 +48,7 @@ class BookmarkItemViewHolder( } if (payload.selectedChanged) { - containerView.changeSelected(item in selectionHolder.selectedItems) + containerView.changeSelected(item in mode.selectedItems) } if (payload.titleChanged) { @@ -64,7 +62,7 @@ class BookmarkItemViewHolder( setColorsAndIcons(item.url) } - setSelectionListeners(item, selectionHolder) + setSelectionListeners(item, mode) } @VisibleForTesting diff --git a/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolderTest.kt index e622dbf209..64d1c914e8 100644 --- a/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolderTest.kt @@ -18,7 +18,6 @@ import org.junit.Test import org.mozilla.fenix.ext.hideAndDisable import org.mozilla.fenix.ext.showAndEnable import org.mozilla.fenix.library.LibrarySiteItemView -import org.mozilla.fenix.library.SelectionHolder import org.mozilla.fenix.library.bookmarks.BookmarkFragmentInteractor import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState import org.mozilla.fenix.library.bookmarks.BookmarkPayload @@ -29,8 +28,6 @@ class BookmarkFolderViewHolderTest { private lateinit var interactor: BookmarkFragmentInteractor @MockK(relaxed = true) private lateinit var siteItemView: LibrarySiteItemView - @MockK(relaxed = true) - private lateinit var selectionHolder: SelectionHolder private lateinit var holder: BookmarkFolderViewHolder private val folder = BookmarkNode( @@ -50,7 +47,7 @@ class BookmarkFolderViewHolderTest { mockkStatic(AppCompatResources::class) every { AppCompatResources.getDrawable(any(), any()) } returns mockk(relaxed = true) - holder = BookmarkFolderViewHolder(siteItemView, interactor, selectionHolder) + holder = BookmarkFolderViewHolder(siteItemView, interactor) } @Test @@ -63,7 +60,6 @@ class BookmarkFolderViewHolderTest { siteItemView.changeSelected(false) } - every { selectionHolder.selectedItems } returns setOf(folder) holder.bind(folder, BookmarkFragmentState.Mode.Selecting(setOf(folder))) verify { diff --git a/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolderTest.kt index 36d64172b9..0a1cd2f2dd 100644 --- a/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolderTest.kt @@ -5,7 +5,6 @@ package org.mozilla.fenix.library.bookmarks.viewholders import io.mockk.MockKAnnotations -import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.verify import mozilla.components.concept.storage.BookmarkNode @@ -15,7 +14,6 @@ import org.junit.Test import org.mozilla.fenix.ext.hideAndDisable import org.mozilla.fenix.ext.showAndEnable import org.mozilla.fenix.library.LibrarySiteItemView -import org.mozilla.fenix.library.SelectionHolder import org.mozilla.fenix.library.bookmarks.BookmarkFragmentInteractor import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState import org.mozilla.fenix.library.bookmarks.BookmarkPayload @@ -28,8 +26,6 @@ class BookmarkItemViewHolderTest { @MockK(relaxed = true) private lateinit var siteItemView: LibrarySiteItemView - @MockK(relaxed = true) - private lateinit var selectionHolder: SelectionHolder private lateinit var holder: BookmarkItemViewHolder private val item = BookmarkNode( @@ -45,15 +41,16 @@ class BookmarkItemViewHolderTest { @Before fun setup() { MockKAnnotations.init(this) - holder = BookmarkItemViewHolder(siteItemView, interactor, selectionHolder) + holder = BookmarkItemViewHolder(siteItemView, interactor) } @Test fun `binds views for unselected item`() { - holder.bind(item, BookmarkFragmentState.Mode.Normal()) + val mode = BookmarkFragmentState.Mode.Normal() + holder.bind(item, mode) verify { - siteItemView.setSelectionInteractor(item, selectionHolder, interactor) + siteItemView.setSelectionInteractor(item, mode, interactor) siteItemView.titleView.text = item.title siteItemView.urlView.text = item.url siteItemView.overflowView.showAndEnable() @@ -64,11 +61,11 @@ class BookmarkItemViewHolderTest { @Test fun `binds views for selected item`() { - every { selectionHolder.selectedItems } returns setOf(item) - holder.bind(item, BookmarkFragmentState.Mode.Selecting(setOf(item))) + val mode = BookmarkFragmentState.Mode.Selecting(setOf(item)) + holder.bind(item, mode) verify { - siteItemView.setSelectionInteractor(item, selectionHolder, interactor) + siteItemView.setSelectionInteractor(item, mode, interactor) siteItemView.titleView.text = item.title siteItemView.urlView.text = item.url siteItemView.overflowView.hideAndDisable() From da1579b36119e16800b12c5d33b110c0313d1be7 Mon Sep 17 00:00:00 2001 From: Roger Yang Date: Fri, 14 Aug 2020 16:09:36 -0400 Subject: [PATCH 20/33] Closes #13459: Pass DefaultLoadUrlUseCase to AppLinksFeature (#13460) --- .../main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index c48c7f73db..836b4755dd 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -438,7 +438,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session sessionManager = sessionManager, sessionId = customTabSessionId, fragmentManager = parentFragmentManager, - launchInApp = { context.settings().openLinksInExternalApp } + launchInApp = { context.settings().openLinksInExternalApp }, + loadUrlUseCase = context.components.useCases.sessionUseCases.loadUrl ), owner = this, view = view From 57e557fd182cfb82a84b88c5a3ee6621cacbe4b1 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Fri, 14 Aug 2020 16:08:41 -0700 Subject: [PATCH 21/33] Use AC version of PrivateNotificationService (#12459) --- app/src/main/AndroidManifest.xml | 2 +- .../java/org/mozilla/fenix/HomeActivity.kt | 13 +- .../session/NotificationSessionObserver.kt | 51 ----- .../session/PrivateNotificationService.kt | 66 +++++++ .../session/SessionNotificationService.kt | 174 ------------------ .../NotificationSessionObserverTest.kt | 87 --------- .../session/PrivateNotificationServiceTest.kt | 64 +++++++ .../session/SessionNotificationServiceTest.kt | 27 --- 8 files changed, 140 insertions(+), 344 deletions(-) delete mode 100644 app/src/main/java/org/mozilla/fenix/session/NotificationSessionObserver.kt create mode 100644 app/src/main/java/org/mozilla/fenix/session/PrivateNotificationService.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/session/SessionNotificationService.kt delete mode 100644 app/src/test/java/org/mozilla/fenix/session/NotificationSessionObserverTest.kt create mode 100644 app/src/test/java/org/mozilla/fenix/session/PrivateNotificationServiceTest.kt delete mode 100644 app/src/test/java/org/mozilla/fenix/session/SessionNotificationServiceTest.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bb20352e09..8258893266 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -260,7 +260,7 @@ android:resource="@xml/search_widget_info" /> - ? = null private var isToolbarInflated = false @@ -174,7 +175,11 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { sessionObserver = UriOpenedObserver(this) checkPrivateShortcutEntryPoint(intent) - privateNotificationObserver = NotificationSessionObserver(applicationContext).also { + privateNotificationObserver = PrivateNotificationFeature( + applicationContext, + components.core.store, + PrivateNotificationService::class + ).also { it.start() } @@ -479,7 +484,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { intent.getStringExtra(OPEN_TO_SEARCH) == StartSearchIntentProcessor.PRIVATE_BROWSING_PINNED_SHORTCUT) ) { - NotificationSessionObserver.isStartedFromPrivateShortcut = true + PrivateNotificationService.isStartedFromPrivateShortcut = true } } diff --git a/app/src/main/java/org/mozilla/fenix/session/NotificationSessionObserver.kt b/app/src/main/java/org/mozilla/fenix/session/NotificationSessionObserver.kt deleted file mode 100644 index 7b6f494106..0000000000 --- a/app/src/main/java/org/mozilla/fenix/session/NotificationSessionObserver.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* 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.session - -import android.content.Context -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.cancel -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.flow.map -import mozilla.components.browser.state.selector.privateTabs -import mozilla.components.lib.state.ext.flowScoped -import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged -import org.mozilla.fenix.ext.components - -/** - * This observer starts and stops the service to show a notification - * indicating that a private tab is open. - */ -class NotificationSessionObserver( - private val applicationContext: Context, - private val notificationService: SessionNotificationService.Companion = SessionNotificationService -) { - - private var scope: CoroutineScope? = null - - @ExperimentalCoroutinesApi - fun start() { - scope = applicationContext.components.core.store.flowScoped { flow -> - flow.map { state -> state.privateTabs.isNotEmpty() } - .ifChanged() - .collect { hasPrivateTabs -> - if (hasPrivateTabs) { - notificationService.start(applicationContext, isStartedFromPrivateShortcut) - } else if (SessionNotificationService.started) { - notificationService.stop(applicationContext) - } - } - } - } - - fun stop() { - scope?.cancel() - } - - companion object { - var isStartedFromPrivateShortcut = false - } -} diff --git a/app/src/main/java/org/mozilla/fenix/session/PrivateNotificationService.kt b/app/src/main/java/org/mozilla/fenix/session/PrivateNotificationService.kt new file mode 100644 index 0000000000..d38101c763 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/session/PrivateNotificationService.kt @@ -0,0 +1,66 @@ +/* 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.session + +import android.content.Intent +import androidx.core.app.NotificationCompat +import androidx.core.content.ContextCompat +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.feature.privatemode.notification.AbstractPrivateNotificationService +import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.R +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.metrics + +/** + * Manages notifications for private tabs. + * + * Private tab notifications solve two problems for us: + * 1 - They allow users to interact with us from outside of the app (example: by closing all + * private tabs). + * 2 - The notification will keep our process alive, allowing us to keep private tabs in memory. + * + * As long as a session is active this service will keep its notification alive. + */ +class PrivateNotificationService : AbstractPrivateNotificationService() { + + override val store: BrowserStore by lazy { components.core.store } + + override fun NotificationCompat.Builder.buildNotification() { + setSmallIcon(R.drawable.ic_pbm_notification) + setContentTitle(getString(R.string.app_name_private_4, getString(R.string.app_name))) + setContentText(getString(R.string.notification_pbm_delete_text_2)) + color = ContextCompat.getColor(this@PrivateNotificationService, R.color.pbm_notification_color) + } + + override fun erasePrivateTabs() { + metrics.track(Event.PrivateBrowsingNotificationTapped) + + val homeScreenIntent = Intent(this, HomeActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + 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) + super.erasePrivateTabs() + } + + companion object { + + /** + * Global used by [HomeActivity] to figure out if normal mode or private mode + * should be used after closing all private tabs. + */ + var isStartedFromPrivateShortcut = false + } +} diff --git a/app/src/main/java/org/mozilla/fenix/session/SessionNotificationService.kt b/app/src/main/java/org/mozilla/fenix/session/SessionNotificationService.kt deleted file mode 100644 index e85411b202..0000000000 --- a/app/src/main/java/org/mozilla/fenix/session/SessionNotificationService.kt +++ /dev/null @@ -1,174 +0,0 @@ -/* 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.session - -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.app.PendingIntent -import android.app.Service -import android.content.Context -import android.content.Intent -import android.os.Build -import android.os.IBinder -import androidx.core.app.NotificationCompat -import androidx.core.content.ContextCompat -import androidx.core.content.getSystemService -import mozilla.components.browser.session.SessionManager -import mozilla.components.support.utils.ThreadUtils -import org.mozilla.fenix.HomeActivity -import org.mozilla.fenix.R -import org.mozilla.fenix.components.metrics.Event -import org.mozilla.fenix.ext.components -import org.mozilla.fenix.ext.metrics -import org.mozilla.fenix.ext.sessionsOfType - -/** - * Manages notifications for private tabs. - * - * Private tab notifications solve two problems for us: - * 1 - They allow users to interact with us from outside of the app (example: by closing all - * private tabs). - * 2 - The notification will keep our process alive, allowing us to keep private tabs in memory. - * - * As long as a session is active this service will keep its notification alive. - */ -class SessionNotificationService : Service() { - - private var isStartedFromPrivateShortcut: Boolean = false - - override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { - 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) - - 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 START_NOT_STICKY - } - - override fun onTaskRemoved(rootIntent: Intent) { - components.core.sessionManager.removeAndCloseAllPrivateSessions() - - stopForeground(true) - stopSelf() - } - - private fun buildNotification(): Notification { - return NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) - .setOngoing(true) - .setSmallIcon(R.drawable.ic_pbm_notification) - .setContentTitle(getString(R.string.app_name_private_4, getString(R.string.app_name))) - .setContentText(getString(R.string.notification_pbm_delete_text_2)) - .setContentIntent(createNotificationIntent()) - .setVisibility(NotificationCompat.VISIBILITY_SECRET) - .setShowWhen(false) - .setLocalOnly(true) - .setColor(ContextCompat.getColor(this, R.color.pbm_notification_color)) - .build() - } - - private fun createNotificationIntent(): PendingIntent { - val intent = Intent(this, SessionNotificationService::class.java) - intent.action = ACTION_ERASE - - return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_ONE_SHOT) - } - - private fun createNotificationChannelIfNeeded() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - // Notification channels are only available on Android O or higher. - return - } - - val notificationManager = getSystemService() ?: return - - val notificationChannelName = getString(R.string.notification_pbm_channel_name) - - val channel = NotificationChannel( - NOTIFICATION_CHANNEL_ID, notificationChannelName, NotificationManager.IMPORTANCE_MIN - ) - channel.importance = NotificationManager.IMPORTANCE_LOW - channel.enableLights(false) - channel.enableVibration(false) - channel.setShowBadge(false) - - notificationManager.createNotificationChannel(channel) - } - - private fun SessionManager.removeAndCloseAllPrivateSessions() { - sessionsOfType(private = true).forEach { remove(it) } - } - - override fun onBind(intent: Intent): IBinder? { - return null - } - - 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 var started = false - - 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 - // calls by running this after potentially expensive calls in FocusApplication.onCreate and - // BrowserFragment.inflateView by posting it to the end of the main thread. - ThreadUtils.postToMainThread(Runnable { - context.startService(intent) - }) - - started = true - } - - internal fun stop(context: Context) { - val intent = Intent(context, SessionNotificationService::class.java) - - // We want to make sure we always call stop after start. So we're - // putting these actions on the same sequential run queue. - ThreadUtils.postToMainThread(Runnable { - context.stopService(intent) - }) - - started = false - } - } -} diff --git a/app/src/test/java/org/mozilla/fenix/session/NotificationSessionObserverTest.kt b/app/src/test/java/org/mozilla/fenix/session/NotificationSessionObserverTest.kt deleted file mode 100644 index 87d462ecf2..0000000000 --- a/app/src/test/java/org/mozilla/fenix/session/NotificationSessionObserverTest.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* 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.session - -import android.content.Context -import io.mockk.Called -import io.mockk.MockKAnnotations -import io.mockk.confirmVerified -import io.mockk.every -import io.mockk.impl.annotations.MockK -import io.mockk.verify -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.runBlocking -import mozilla.components.browser.state.action.CustomTabListAction -import mozilla.components.browser.state.action.TabListAction -import mozilla.components.browser.state.state.createCustomTab -import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mozilla.fenix.ext.components -import org.mozilla.fenix.helpers.FenixRobolectricTestRunner - -@ExperimentalCoroutinesApi -@RunWith(FenixRobolectricTestRunner::class) -class NotificationSessionObserverTest { - - private lateinit var observer: NotificationSessionObserver - private lateinit var store: BrowserStore - @MockK private lateinit var context: Context - @MockK(relaxed = true) private lateinit var notificationService: SessionNotificationService.Companion - - @Before - fun before() { - MockKAnnotations.init(this) - store = BrowserStore() - every { context.components.core.store } returns store - observer = NotificationSessionObserver(context, notificationService) - NotificationSessionObserver.isStartedFromPrivateShortcut = false - } - - @Test - fun `GIVEN session is private and non-custom WHEN it is added THEN notification service should be started`() = runBlocking { - val privateSession = createTab("https://firefox.com", private = true) - - store.dispatch(TabListAction.AddTabAction(privateSession)).join() - - observer.start() - verify(exactly = 1) { notificationService.start(context, false) } - confirmVerified(notificationService) - } - - @Test - fun `GIVEN session is not private WHEN it is added THEN notification service should not be started`() = runBlocking { - val normalSession = createTab("https://firefox.com") - val customSession = createCustomTab("https://firefox.com") - - observer.start() - verify { notificationService wasNot Called } - - store.dispatch(TabListAction.AddTabAction(normalSession)).join() - verify(exactly = 0) { notificationService.start(context, false) } - - store.dispatch(CustomTabListAction.AddCustomTabAction(customSession)).join() - verify(exactly = 0) { notificationService.start(context, false) } - } - - @Test - fun `GIVEN session is custom tab WHEN it is added THEN notification service should not be started`() = runBlocking { - val privateCustomSession = createCustomTab("https://firefox.com").let { - it.copy(content = it.content.copy(private = true)) - } - val customSession = createCustomTab("https://firefox.com") - - observer.start() - verify { notificationService wasNot Called } - - store.dispatch(CustomTabListAction.AddCustomTabAction(privateCustomSession)).join() - verify(exactly = 0) { notificationService.start(context, false) } - - store.dispatch(CustomTabListAction.AddCustomTabAction(customSession)).join() - verify(exactly = 0) { notificationService.start(context, false) } - } -} diff --git a/app/src/test/java/org/mozilla/fenix/session/PrivateNotificationServiceTest.kt b/app/src/test/java/org/mozilla/fenix/session/PrivateNotificationServiceTest.kt new file mode 100644 index 0000000000..d0267c53d4 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/session/PrivateNotificationServiceTest.kt @@ -0,0 +1,64 @@ +/* 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.session + +import android.content.ComponentName +import android.content.Intent +import io.mockk.every +import io.mockk.mockk +import mozilla.components.feature.privatemode.notification.AbstractPrivateNotificationService.Companion.ACTION_ERASE +import mozilla.components.support.test.robolectric.testContext +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.HomeActivity.Companion.PRIVATE_BROWSING_MODE +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner +import org.robolectric.Robolectric +import org.robolectric.Shadows.shadowOf +import org.robolectric.android.controller.ServiceController + +@RunWith(FenixRobolectricTestRunner::class) +class PrivateNotificationServiceTest { + + private lateinit var controller: ServiceController + + @Before + fun setup() { + val store = testContext.components.core.store + every { store.dispatch(any()) } returns mockk() + + controller = Robolectric.buildService( + PrivateNotificationService::class.java, + Intent(ACTION_ERASE) + ) + } + + @Test + fun `service opens home activity with PBM flag set to true`() { + PrivateNotificationService.isStartedFromPrivateShortcut = true + val service = shadowOf(controller.get()) + controller.startCommand(0, 0) + + val intent = service.nextStartedActivity + assertEquals(ComponentName(testContext, HomeActivity::class.java), intent.component) + assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK, intent.flags) + assertEquals(true, intent.extras?.getBoolean(PRIVATE_BROWSING_MODE)) + } + + @Test + fun `service opens home activity with PBM flag set to false`() { + PrivateNotificationService.isStartedFromPrivateShortcut = false + val service = shadowOf(controller.get()) + controller.startCommand(0, 0) + + val intent = service.nextStartedActivity + assertEquals(ComponentName(testContext, HomeActivity::class.java), intent.component) + assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK, intent.flags) + assertEquals(false, intent.extras?.getBoolean(PRIVATE_BROWSING_MODE)) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/session/SessionNotificationServiceTest.kt b/app/src/test/java/org/mozilla/fenix/session/SessionNotificationServiceTest.kt deleted file mode 100644 index 2a9e5bccd1..0000000000 --- a/app/src/test/java/org/mozilla/fenix/session/SessionNotificationServiceTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* 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.session - -import mozilla.components.support.test.robolectric.testContext -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith -import org.mozilla.fenix.helpers.FenixRobolectricTestRunner - -@RunWith(FenixRobolectricTestRunner::class) -class SessionNotificationServiceTest { - - @Test - fun `Service keeps tracked of started state`() { - assertFalse(SessionNotificationService.started) - - SessionNotificationService.start(testContext, false) - assertTrue(SessionNotificationService.started) - - SessionNotificationService.stop(testContext) - assertFalse(SessionNotificationService.started) - } -} From 2e61425f2be12a61bd2e7a516d0523aeef20c259 Mon Sep 17 00:00:00 2001 From: Simon Chae Date: Mon, 10 Aug 2020 14:12:33 -0400 Subject: [PATCH 22/33] For #13256: Set add-on settings tab mode based on BrowsingModeManager --- .../mozilla/fenix/addons/InstalledAddonDetailsFragment.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt index 99da89b5ad..49cf693d34 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt @@ -18,10 +18,10 @@ import com.google.android.material.switchmaterial.SwitchMaterial import kotlinx.android.synthetic.main.fragment_installed_add_on_details.view.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import mozilla.components.browser.state.selector.selectedTab import mozilla.components.feature.addons.Addon import mozilla.components.feature.addons.AddonManagerException import mozilla.components.feature.addons.ui.translatedName +import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.showToolbar @@ -189,8 +189,7 @@ class InstalledAddonDetailsFragment : Fragment() { val directions = if (addon.installedState?.openOptionsPageInTab == true) { val components = it.context.components val shouldCreatePrivateSession = - components.core.store.state.selectedTab?.content?.private - ?: components.settings.openLinksInAPrivateTab + (activity as HomeActivity).browsingModeManager.mode.isPrivate if (shouldCreatePrivateSession) { components.useCases.tabsUseCases.addPrivateTab(settingUrl) From a04b91ee3c17ba2a8e42a11007f21be831d564fa Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Fri, 14 Aug 2020 16:44:09 -0700 Subject: [PATCH 23/33] =?UTF-8?q?FNX-14513=20=E2=81=83=20For=20#12862:=20U?= =?UTF-8?q?se=20concept-menu=20in=20library=20(#13332)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fenix/library/LibrarySiteItemView.kt | 14 +-- .../library/bookmarks/BookmarkItemMenu.kt | 110 +++++++++++------- .../viewholders/BookmarkFolderViewHolder.kt | 2 +- .../viewholders/BookmarkItemViewHolder.kt | 2 +- .../viewholders/BookmarkNodeViewHolder.kt | 29 +++-- .../BookmarkSeparatorViewHolder.kt | 2 +- .../fenix/library/history/HistoryItemMenu.kt | 62 ++++++---- .../viewholders/HistoryListItemViewHolder.kt | 3 +- .../library/bookmarks/BookmarkItemMenuTest.kt | 98 ++++++++++++++++ .../library/history/HistoryItemMenuTest.kt | 76 ++++++++++++ 10 files changed, 307 insertions(+), 91 deletions(-) create mode 100644 app/src/test/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenuTest.kt create mode 100644 app/src/test/java/org/mozilla/fenix/library/history/HistoryItemMenuTest.kt diff --git a/app/src/main/java/org/mozilla/fenix/library/LibrarySiteItemView.kt b/app/src/main/java/org/mozilla/fenix/library/LibrarySiteItemView.kt index 6c6b1915dc..a90fb42319 100644 --- a/app/src/main/java/org/mozilla/fenix/library/LibrarySiteItemView.kt +++ b/app/src/main/java/org/mozilla/fenix/library/LibrarySiteItemView.kt @@ -13,8 +13,8 @@ import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import kotlinx.android.synthetic.main.library_site_item.view.* -import mozilla.components.browser.menu.BrowserMenu -import mozilla.components.browser.menu.BrowserMenuBuilder +import mozilla.components.concept.menu.MenuController +import mozilla.components.concept.menu.Orientation import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.increaseTapArea @@ -48,10 +48,6 @@ interface SelectionHolder { val selectedItems: Set } -interface LibraryItemMenu { - val menuBuilder: BrowserMenuBuilder -} - class LibrarySiteItemView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, @@ -102,11 +98,11 @@ class LibrarySiteItemView @JvmOverloads constructor( context.components.core.icons.loadIntoView(favicon, url) } - fun attachMenu(menu: LibraryItemMenu) { + fun attachMenu(menuController: MenuController) { overflow_menu.setOnClickListener { - menu.menuBuilder.build(context).show( + menuController.show( anchor = it, - orientation = BrowserMenu.Orientation.DOWN + orientation = Orientation.DOWN ) } } diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenu.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenu.kt index 7473ef740c..5d0c93d668 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenu.kt @@ -5,65 +5,89 @@ package org.mozilla.fenix.library.bookmarks import android.content.Context -import mozilla.components.browser.menu.BrowserMenuBuilder -import mozilla.components.browser.menu.item.SimpleBrowserMenuItem -import mozilla.components.concept.storage.BookmarkNode +import androidx.annotation.VisibleForTesting +import mozilla.components.browser.menu2.BrowserMenuController +import mozilla.components.concept.menu.MenuController +import mozilla.components.concept.menu.candidate.TextMenuCandidate +import mozilla.components.concept.menu.candidate.TextStyle import mozilla.components.concept.storage.BookmarkNodeType +import mozilla.components.support.ktx.android.content.getColorFromAttr import org.mozilla.fenix.R -import org.mozilla.fenix.library.LibraryItemMenu -import org.mozilla.fenix.theme.ThemeManager class BookmarkItemMenu( private val context: Context, - private val item: BookmarkNode, - private val onItemTapped: (BookmarkItemMenu.Item) -> Unit = {} -) : LibraryItemMenu { + private val onItemTapped: (Item) -> Unit +) { - sealed class Item { - object Edit : Item() - object Select : Item() - object Copy : Item() - object Share : Item() - object OpenInNewTab : Item() - object OpenInPrivateTab : Item() - object Delete : Item() + enum class Item { + Edit, + Copy, + Share, + OpenInNewTab, + OpenInPrivateTab, + Delete; } - override val menuBuilder by lazy { BrowserMenuBuilder(menuItems) } + val menuController: MenuController by lazy { BrowserMenuController() } - private val menuItems by lazy { - listOfNotNull( - if (item.type in listOf(BookmarkNodeType.ITEM, BookmarkNodeType.FOLDER)) { - SimpleBrowserMenuItem(context.getString(R.string.bookmark_menu_edit_button)) { - onItemTapped.invoke(BookmarkItemMenu.Item.Edit) + @VisibleForTesting + internal fun menuItems(itemType: BookmarkNodeType): List { + return listOfNotNull( + if (itemType != BookmarkNodeType.SEPARATOR) { + TextMenuCandidate( + text = context.getString(R.string.bookmark_menu_edit_button) + ) { + onItemTapped.invoke(Item.Edit) } - } else null, - if (item.type == BookmarkNodeType.ITEM) { - SimpleBrowserMenuItem(context.getString(R.string.bookmark_menu_copy_button)) { - onItemTapped.invoke(BookmarkItemMenu.Item.Copy) + } else { + null + }, + if (itemType == BookmarkNodeType.ITEM) { + TextMenuCandidate( + text = context.getString(R.string.bookmark_menu_copy_button) + ) { + onItemTapped.invoke(Item.Copy) } - } else null, - if (item.type == BookmarkNodeType.ITEM) { - SimpleBrowserMenuItem(context.getString(R.string.bookmark_menu_share_button)) { - onItemTapped.invoke(BookmarkItemMenu.Item.Share) + } else { + null + }, + if (itemType == BookmarkNodeType.ITEM) { + TextMenuCandidate( + text = context.getString(R.string.bookmark_menu_share_button) + ) { + onItemTapped.invoke(Item.Share) } - } else null, - if (item.type == BookmarkNodeType.ITEM) { - SimpleBrowserMenuItem(context.getString(R.string.bookmark_menu_open_in_new_tab_button)) { - onItemTapped.invoke(BookmarkItemMenu.Item.OpenInNewTab) + } else { + null + }, + if (itemType == BookmarkNodeType.ITEM) { + TextMenuCandidate( + text = context.getString(R.string.bookmark_menu_open_in_new_tab_button) + ) { + onItemTapped.invoke(Item.OpenInNewTab) } - } else null, - if (item.type == BookmarkNodeType.ITEM) { - SimpleBrowserMenuItem(context.getString(R.string.bookmark_menu_open_in_private_tab_button)) { - onItemTapped.invoke(BookmarkItemMenu.Item.OpenInPrivateTab) + } else { + null + }, + if (itemType == BookmarkNodeType.ITEM) { + TextMenuCandidate( + text = context.getString(R.string.bookmark_menu_open_in_private_tab_button) + ) { + onItemTapped.invoke(Item.OpenInPrivateTab) } - } else null, - SimpleBrowserMenuItem( - context.getString(R.string.bookmark_menu_delete_button), - textColorResource = ThemeManager.resolveAttribute(R.attr.destructive, context) + } else { + null + }, + TextMenuCandidate( + text = context.getString(R.string.bookmark_menu_delete_button), + textStyle = TextStyle(color = context.getColorFromAttr(R.attr.destructive)) ) { - onItemTapped.invoke(BookmarkItemMenu.Item.Delete) + onItemTapped.invoke(Item.Delete) } ) } + + fun updateMenu(itemType: BookmarkNodeType) { + menuController.submitList(menuItems(itemType)) + } } diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt index 8c6eda9afa..9d62e3bcd5 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkFolderViewHolder.kt @@ -44,7 +44,7 @@ class BookmarkFolderViewHolder( setSelectionListeners(item, mode) if (!item.inRoots()) { - setupMenu(item) + updateMenu(item.type) if (payload.modeChanged) { if (mode is BookmarkFragmentState.Mode.Selecting) { containerView.overflowView.hideAndDisable() diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt index ec1a9a5b49..1af60ec265 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkItemViewHolder.kt @@ -37,7 +37,7 @@ class BookmarkItemViewHolder( override fun bind(item: BookmarkNode, mode: BookmarkFragmentState.Mode, payload: BookmarkPayload) { this.item = item - setupMenu(item) + updateMenu(item.type) if (payload.modeChanged) { if (mode is BookmarkFragmentState.Mode.Selecting) { diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkNodeViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkNodeViewHolder.kt index 7513234672..e04f713fa3 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkNodeViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkNodeViewHolder.kt @@ -5,29 +5,32 @@ package org.mozilla.fenix.library.bookmarks.viewholders import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.extensions.LayoutContainer import mozilla.components.concept.storage.BookmarkNode +import mozilla.components.concept.storage.BookmarkNodeType import org.mozilla.fenix.library.LibrarySiteItemView import org.mozilla.fenix.library.SelectionHolder import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState import org.mozilla.fenix.library.bookmarks.BookmarkItemMenu import org.mozilla.fenix.library.bookmarks.BookmarkPayload import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor +import org.mozilla.fenix.utils.Do /** * Base class for bookmark node view holders. */ abstract class BookmarkNodeViewHolder( - override val containerView: LibrarySiteItemView, + protected val containerView: LibrarySiteItemView, private val interactor: BookmarkViewInteractor -) : RecyclerView.ViewHolder(containerView), LayoutContainer { +) : RecyclerView.ViewHolder(containerView) { abstract var item: BookmarkNode? + private lateinit var menu: BookmarkItemMenu - abstract fun bind( - item: BookmarkNode, - mode: BookmarkFragmentState.Mode - ) + init { + setupMenu() + } + + abstract fun bind(item: BookmarkNode, mode: BookmarkFragmentState.Mode) abstract fun bind( item: BookmarkNode, @@ -39,11 +42,11 @@ abstract class BookmarkNodeViewHolder( containerView.setSelectionInteractor(item, selectionHolder, interactor) } - protected fun setupMenu(item: BookmarkNode) { - val bookmarkItemMenu = BookmarkItemMenu(containerView.context, item) { - when (it) { + private fun setupMenu() { + menu = BookmarkItemMenu(containerView.context) { menuItem -> + val item = this.item ?: return@BookmarkItemMenu + Do exhaustive when (menuItem) { BookmarkItemMenu.Item.Edit -> interactor.onEditPressed(item) - BookmarkItemMenu.Item.Select -> interactor.select(item) BookmarkItemMenu.Item.Copy -> interactor.onCopyPressed(item) BookmarkItemMenu.Item.Share -> interactor.onSharePressed(item) BookmarkItemMenu.Item.OpenInNewTab -> interactor.onOpenInNormalTab(item) @@ -52,6 +55,8 @@ abstract class BookmarkNodeViewHolder( } } - containerView.attachMenu(bookmarkItemMenu) + containerView.attachMenu(menu.menuController) } + + protected fun updateMenu(itemType: BookmarkNodeType) = menu.updateMenu(itemType) } diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkSeparatorViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkSeparatorViewHolder.kt index d1789fa941..2000f75815 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkSeparatorViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/viewholders/BookmarkSeparatorViewHolder.kt @@ -26,7 +26,7 @@ class BookmarkSeparatorViewHolder( ) { this.item = item containerView.displayAs(LibrarySiteItemView.ItemType.SEPARATOR) - setupMenu(item) + updateMenu(item.type) } override fun bind( diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryItemMenu.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryItemMenu.kt index 7e638c7868..d4e99d5f99 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryItemMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryItemMenu.kt @@ -5,43 +5,61 @@ package org.mozilla.fenix.library.history import android.content.Context -import mozilla.components.browser.menu.BrowserMenuBuilder -import mozilla.components.browser.menu.item.SimpleBrowserMenuItem +import androidx.annotation.VisibleForTesting +import mozilla.components.browser.menu2.BrowserMenuController +import mozilla.components.concept.menu.MenuController +import mozilla.components.concept.menu.candidate.TextMenuCandidate +import mozilla.components.concept.menu.candidate.TextStyle +import mozilla.components.support.ktx.android.content.getColorFromAttr import org.mozilla.fenix.R -import org.mozilla.fenix.library.LibraryItemMenu -import org.mozilla.fenix.theme.ThemeManager class HistoryItemMenu( private val context: Context, - private val onItemTapped: (Item) -> Unit = {} -) : LibraryItemMenu { - sealed class Item { - object Copy : Item() - object Share : Item() - object OpenInNewTab : Item() - object OpenInPrivateTab : Item() - object Delete : Item() + private val onItemTapped: (Item) -> Unit +) { + + enum class Item { + Copy, + Share, + OpenInNewTab, + OpenInPrivateTab, + Delete; } - override val menuBuilder by lazy { BrowserMenuBuilder(menuItems) } + val menuController: MenuController by lazy { + BrowserMenuController().apply { + submitList(menuItems()) + } + } - private val menuItems by lazy { - listOfNotNull( - SimpleBrowserMenuItem(context.getString(R.string.history_menu_copy_button)) { + @VisibleForTesting + internal fun menuItems(): List { + return listOf( + TextMenuCandidate( + text = context.getString(R.string.history_menu_copy_button) + ) { onItemTapped.invoke(Item.Copy) }, - SimpleBrowserMenuItem(context.getString(R.string.history_menu_share_button)) { + TextMenuCandidate( + text = context.getString(R.string.history_menu_share_button) + ) { onItemTapped.invoke(Item.Share) }, - SimpleBrowserMenuItem(context.getString(R.string.history_menu_open_in_new_tab_button)) { + TextMenuCandidate( + text = context.getString(R.string.history_menu_open_in_new_tab_button) + ) { onItemTapped.invoke(Item.OpenInNewTab) }, - SimpleBrowserMenuItem(context.getString(R.string.history_menu_open_in_private_tab_button)) { + TextMenuCandidate( + text = context.getString(R.string.history_menu_open_in_private_tab_button) + ) { onItemTapped.invoke(Item.OpenInPrivateTab) }, - SimpleBrowserMenuItem( - context.getString(R.string.history_delete_item), - textColorResource = ThemeManager.resolveAttribute(R.attr.destructive, context) + TextMenuCandidate( + text = context.getString(R.string.history_delete_item), + textStyle = TextStyle( + color = context.getColorFromAttr(R.attr.destructive) + ) ) { onItemTapped.invoke(Item.Delete) } diff --git a/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt index 762f72aa9a..f833507e99 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt @@ -110,7 +110,6 @@ class HistoryListItemViewHolder( private fun setupMenu() { val historyMenu = HistoryItemMenu(itemView.context) { val item = this.item ?: return@HistoryItemMenu - Do exhaustive when (it) { HistoryItemMenu.Item.Copy -> historyInteractor.onCopyPressed(item) HistoryItemMenu.Item.Share -> historyInteractor.onSharePressed(item) @@ -120,7 +119,7 @@ class HistoryListItemViewHolder( } } - itemView.history_layout.attachMenu(historyMenu) + itemView.history_layout.attachMenu(historyMenu.menuController) } companion object { diff --git a/app/src/test/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenuTest.kt b/app/src/test/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenuTest.kt new file mode 100644 index 0000000000..8840e24516 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/library/bookmarks/BookmarkItemMenuTest.kt @@ -0,0 +1,98 @@ +/* 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.library.bookmarks + +import android.content.Context +import androidx.appcompat.view.ContextThemeWrapper +import io.mockk.mockk +import io.mockk.verify +import mozilla.components.concept.menu.candidate.TextStyle +import mozilla.components.concept.storage.BookmarkNodeType +import mozilla.components.support.ktx.android.content.getColorFromAttr +import mozilla.components.support.test.robolectric.testContext +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner +import org.mozilla.fenix.library.bookmarks.BookmarkItemMenu.Item + +@RunWith(FenixRobolectricTestRunner::class) +class BookmarkItemMenuTest { + + private lateinit var context: Context + private lateinit var onItemTapped: (Item) -> Unit + private lateinit var menu: BookmarkItemMenu + + @Before + fun setup() { + context = ContextThemeWrapper(testContext, R.style.NormalTheme) + onItemTapped = mockk(relaxed = true) + menu = BookmarkItemMenu(context, onItemTapped) + } + + @Test + fun `delete item has special styling`() { + val deleteItem = menu.menuItems(BookmarkNodeType.SEPARATOR).last() + assertEquals("Delete", deleteItem.text) + assertEquals( + TextStyle(color = context.getColorFromAttr(R.attr.destructive)), + deleteItem.textStyle + ) + + deleteItem.onClick() + verify { onItemTapped(Item.Delete) } + } + + @Test + fun `edit item appears for folders`() { + val folderItems = menu.menuItems(BookmarkNodeType.FOLDER) + assertEquals(2, folderItems.size) + val (edit, delete) = folderItems + + assertEquals("Edit", edit.text) + edit.onClick() + verify { onItemTapped(Item.Edit) } + + assertEquals("Delete", delete.text) + } + + @Test + fun `all item appears for sites`() { + val siteItems = menu.menuItems(BookmarkNodeType.ITEM) + assertEquals(6, siteItems.size) + val (edit, copy, share, openInNewTab, openInPrivateTab, delete) = siteItems + + assertEquals("Edit", edit.text) + assertEquals("Copy", copy.text) + assertEquals("Share", share.text) + assertEquals("Open in new tab", openInNewTab.text) + assertEquals("Open in private tab", openInPrivateTab.text) + assertEquals("Delete", delete.text) + + edit.onClick() + verify { onItemTapped(Item.Edit) } + + copy.onClick() + verify { onItemTapped(Item.Copy) } + + share.onClick() + verify { onItemTapped(Item.Share) } + + openInNewTab.onClick() + verify { onItemTapped(Item.OpenInNewTab) } + + openInPrivateTab.onClick() + verify { onItemTapped(Item.OpenInPrivateTab) } + + delete.onClick() + verify { onItemTapped(Item.Delete) } + } + + private operator fun List.component6(): T { + return get(5) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/library/history/HistoryItemMenuTest.kt b/app/src/test/java/org/mozilla/fenix/library/history/HistoryItemMenuTest.kt new file mode 100644 index 0000000000..356c464d86 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/library/history/HistoryItemMenuTest.kt @@ -0,0 +1,76 @@ +/* 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.library.history + +import android.content.Context +import androidx.appcompat.view.ContextThemeWrapper +import io.mockk.mockk +import io.mockk.verify +import mozilla.components.concept.menu.candidate.TextStyle +import mozilla.components.support.ktx.android.content.getColorFromAttr +import mozilla.components.support.test.robolectric.testContext +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner +import org.mozilla.fenix.library.history.HistoryItemMenu.Item + +@RunWith(FenixRobolectricTestRunner::class) +class HistoryItemMenuTest { + + private lateinit var context: Context + private lateinit var onItemTapped: (Item) -> Unit + private lateinit var menu: HistoryItemMenu + + @Before + fun setup() { + context = ContextThemeWrapper(testContext, R.style.NormalTheme) + onItemTapped = mockk(relaxed = true) + menu = HistoryItemMenu(context, onItemTapped) + } + + @Test + fun `delete item has special styling`() { + val deleteItem = menu.menuItems().last() + assertEquals("Delete", deleteItem.text) + assertEquals( + TextStyle(color = context.getColorFromAttr(R.attr.destructive)), + deleteItem.textStyle + ) + + deleteItem.onClick() + verify { onItemTapped(Item.Delete) } + } + + @Test + fun `builds menu items`() { + val items = menu.menuItems() + assertEquals(5, items.size) + val (copy, share, openInNewTab, openInPrivateTab, delete) = items + + assertEquals("Copy", copy.text) + assertEquals("Share", share.text) + assertEquals("Open in new tab", openInNewTab.text) + assertEquals("Open in private tab", openInPrivateTab.text) + assertEquals("Delete", delete.text) + + copy.onClick() + verify { onItemTapped(Item.Copy) } + + share.onClick() + verify { onItemTapped(Item.Share) } + + openInNewTab.onClick() + verify { onItemTapped(Item.OpenInNewTab) } + + openInPrivateTab.onClick() + verify { onItemTapped(Item.OpenInPrivateTab) } + + delete.onClick() + verify { onItemTapped(Item.Delete) } + } +} From 4b85f3e53b6e9e148e0b6308c29e091e90f44fae Mon Sep 17 00:00:00 2001 From: Sachin Date: Sun, 16 Aug 2020 22:46:41 -0700 Subject: [PATCH 24/33] for #11364 added a resetAfter for onboarding variable inside HomeFragment to avoid random system strictmode violations during UI testing. (#13811) --- app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 ad91e03301..1becb7b8d7 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -146,7 +146,9 @@ class HomeFragment : Fragment() { private val store: BrowserStore get() = requireComponents.core.store - private val onboarding by lazy { FenixOnboarding(requireContext()) } + private val onboarding by lazy { StrictMode.allowThreadDiskReads().resetPoliciesAfter { + FenixOnboarding(requireContext()) } } + private lateinit var homeFragmentStore: HomeFragmentStore private var _sessionControlInteractor: SessionControlInteractor? = null protected val sessionControlInteractor: SessionControlInteractor From 95498367e5f88a4f95d5374f9e051a9f63cbd402 Mon Sep 17 00:00:00 2001 From: Mozilla L10n Automation Bot Date: Mon, 17 Aug 2020 00:13:52 +0000 Subject: [PATCH 25/33] Import l10n. --- app/src/main/res/values-ast/strings.xml | 18 ++++++++ app/src/main/res/values-el/strings.xml | 31 +++++++------ app/src/main/res/values-en-rGB/strings.xml | 19 +++----- app/src/main/res/values-fr/strings.xml | 2 + app/src/main/res/values-hr/strings.xml | 2 + app/src/main/res/values-it/strings.xml | 2 + app/src/main/res/values-iw/strings.xml | 3 ++ app/src/main/res/values-ka/strings.xml | 2 + app/src/main/res/values-ko/strings.xml | 8 ++-- app/src/main/res/values-lt/strings.xml | 51 +++++++++++++++------- app/src/main/res/values-oc/strings.xml | 7 +++ app/src/main/res/values-pa-rIN/strings.xml | 19 +++----- app/src/main/res/values-pl/strings.xml | 2 + app/src/main/res/values-pt-rBR/strings.xml | 34 +++++++-------- app/src/main/res/values-ro/strings.xml | 2 + app/src/main/res/values-ru/strings.xml | 2 + app/src/main/res/values-sk/strings.xml | 2 + app/src/main/res/values-tr/strings.xml | 2 + app/src/main/res/values-ur/strings.xml | 2 + app/src/main/res/values-vi/strings.xml | 2 + 20 files changed, 133 insertions(+), 79 deletions(-) diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml index 8c7b958a42..94f1bff1b3 100644 --- a/app/src/main/res/values-ast/strings.xml +++ b/app/src/main/res/values-ast/strings.xml @@ -25,6 +25,8 @@ %1$s llingüetes abiertes. Toca pa cambiar a otra. + + %1$d esbillaes Nome @@ -272,6 +274,8 @@ Axustes de la cuenta Abrir los enllaces nes aplicaciones + + Xestor de descargues esternu Complementos @@ -351,6 +355,8 @@ Informador de casques + + Serviciu d\'allugamientu de Mozilla Informe de salú de %s @@ -472,6 +478,8 @@ Desaniciar l\'historial ¿De xuru que quies llimpiar l\'historial? + + Desanicióse %1$s Copiar @@ -511,6 +519,10 @@ ¿De xuru que quies desaniciar esta carpeta? + + %s va desaniciar los elementos esbillaos. + + Desanicióse %1$s Amestar una carpeta @@ -552,6 +564,8 @@ NOME Amiestu d\'una carpeta + + Esbilla d\'una carpeta Ha tener un títulu @@ -563,6 +577,8 @@ Desanicióse %1$s Desaniciáronse los marcadores + + Desaniciando les carpetes esbillaes DESFACER @@ -1143,6 +1159,8 @@ Equí van amosase los anicios de sesión y contraseñes que nun se guarden Los anicios de sesión y contraseñes d\'estos sitios nun van guardase. + + Desaniciar toles esceiciones Guetar anicios de sesión diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 544767997d..81bc9bbb3f 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -147,8 +147,8 @@ Σάρωση - - Μηχανή αναζήτησης + + Μηχανή αναζήτησης Ρυθμίσεις μηχανής αναζήτησης @@ -542,6 +542,8 @@ Επιλογή φακέλου Θέλετε σίγουρα να διαγράψετε αυτό το φάκελο; + + Το %s θα διαγράψει τα επιλεγμένα στοιχεία. Ο φάκελος "%1$s" διαγράφηκε @@ -1011,6 +1013,11 @@ Βιβλιοθήκες που χρησιμοποιούμε + + Μενού εντοπισμού σφαλμάτων: απομένουν %1$d κλικ για ενεργοποίηση + Το μενού εντοπισμού σφαλμάτων ενεργοποιήθηκε + 1 καρτέλα @@ -1061,6 +1068,8 @@ Σύνδεση στο Sync Αποθηκευμένες συνδέσεις + + Οι συνδέσεις που αποθηκεύετε ή συγχρονίζετε στο %s θα εμφανίζονται εδώ. Μάθετε περισσότερα σχετικά με το Sync. @@ -1109,6 +1118,8 @@ Αργότερα Ρύθμιση τώρα + + Ξεκλειδώστε τη συσκευή σας Όνομα (Α-Ω) @@ -1150,6 +1161,9 @@ Σφάλμα σύνδεσης στο “%s” + + Δημιουργήθηκε to %s + Καλώς ορίσατε στο νέο %s @@ -1216,9 +1230,7 @@ Υπάρχει ήδη σύνδεση με αυτό το όνομα χρήστη - - Συνδεθείτε με ένα λογαριασμό Firefox. - + Συνδέστε μια άλλη συσκευή. Παρακαλούμε επαληθεύστε ξανά την ταυτότητά σας. @@ -1231,13 +1243,4 @@ OK, το κατάλαβα - - - Συντομεύσεις - - Αναζήτηση με - - Αυτή τη φορά, αναζήτηση με: - - Εμφάνιση συντομεύσεων αναζήτησης diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index d5fcf68e3e..f866ebdc92 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -169,8 +169,8 @@ Scan - - Search Engine + + Search engine Search engine settings @@ -301,6 +301,8 @@ Open links in apps + + External download manager Add-ons @@ -1448,9 +1450,7 @@ A login with that username already exists - - Connect with a Firefox Account. - + Connect another device. Please re-authenticate. @@ -1471,13 +1471,4 @@ OK, Got It - - - Shortcuts - - Search with - - This time, search with: - - Show search shortcuts diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 07fcfa93fa..6ea3f53e8f 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -306,6 +306,8 @@ Ouvrir les liens dans des applications + + Gestionnaire de téléchargement externe Modules complémentaires diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index b1b97162b0..933406e255 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -302,6 +302,8 @@ Otvori poveznice u aplikacijama + + Vanjski upravitelj preuzimanja Dodaci diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index f0eb7997c4..1a4446c165 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -309,6 +309,8 @@ Apri collegamenti nelle app + + Gestore download esterno Componenti aggiuntivi diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 192a5bcf37..f9091f2fd8 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -1447,6 +1447,9 @@ הצגת רשימת הלשוניות מהמכשירים האחרים שלך. + + יש להתחבר כדי לסנכרן + הגעת למכסת האתרים המובילים diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 0c5b22d42b..455117f63d 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -301,6 +301,8 @@ ანგარიშის პარამეტრები ბმულების გახსნა პროგრამებში + + ჩამოტვირთვის გარეშე მმართველი დამატებები diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index e2a23d73f2..f3974fac72 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -1186,9 +1186,9 @@ 사용자 지정 탭에서만 - 크립토마이너 + 암호화폐 채굴기 - 핑거프린터 + 디지털 지문 차단됨 허용됨 @@ -1201,11 +1201,11 @@ 광고 네트워크 및 분석 회사가 여러 사이트에서 사용자 탐색 데이터를 컴파일하는데 사용하는 쿠키를 차단합니다. - 크립토마이너 + 암호화폐 채굴기 악의적인 스크립트가 디지털 통화를 채굴하기 위해 기기에 액세스하는 것을 방지합니다. - 핑거프린터 + 디지털 지문 추적 목적으로 사용할 수 있는 사용자 기기에 대해 고유하게 식별 가능한 데이터가 수집되지 않도록합니다. diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index e88ab49ec4..030068790d 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -25,6 +25,29 @@ %1$s atvertos kortelės. Bakstelėkite, norėdami pereiti tarp kortelių. + + Pasirinkta %1$d + + Pridėti naują rinkinį + + Pavadinimas + + Pasirinkite rinkinį + + Išeiti iš daugelio pasirinkimų veiksenos + + Įtraukti pažymėtas korteles į rinkinį + + Pažymėta %1$s + + Atžymėta %1$s + + Išeita iš daugelio pasirinkimų veiksenos + + Įjungta daugelio pasirinkimų veiksena, pažymėtos kortelės bus įtrauktos į rinkinį + + Pažymėta + „%1$s“ kūrėjai yra „Mozilla“. @@ -147,10 +170,12 @@ Nuskaityti - - Ieškyklė + + Ieškyklė Ieškyklės nuostatos + + Šįkart ieškoti su: Atverti saitą iš iškarpinės @@ -276,6 +301,8 @@ Paskyros nuostatos Atverti saitus programose + + Išorinė atsiuntimų tvarkytuvė Priedai @@ -509,6 +536,9 @@ „%1$s“ (privačioji veiksena) + + Įrašyti + Išvalyti žurnalą @@ -1245,6 +1275,8 @@ Šių svetainių prisijungimai ir slaptažodžiai nebus įrašomi. + + Pašalinti visas išimtis Ieškoti prisijungimų @@ -1441,9 +1473,7 @@ Prisijungimas su tokiu naudotojo vardu jau yra - - Prisijunkite su „Firefox“ paskyra. - + Susiekite kitą įrenginį. Prisijunkite iš naujo. @@ -1465,15 +1495,4 @@ Gerai, supratau - - - Leistukai - - Ieškoti per - - Šįkart ieškoti su: - - - Rodyti paieškos leistukus - diff --git a/app/src/main/res/values-oc/strings.xml b/app/src/main/res/values-oc/strings.xml index 539783b217..02acdde8c6 100644 --- a/app/src/main/res/values-oc/strings.xml +++ b/app/src/main/res/values-oc/strings.xml @@ -300,6 +300,8 @@ Paramètres del compte Dobrir los ligams dins las aplicacions + + Gestionari de telecargament extèrn Moduls complementaris @@ -992,6 +994,11 @@ In English this is an idiom for "choose a side as in an argument or fight" but it is ok to make this more literally about "choosing a position in a physical space --> Prenètz posicion + + Navegatz d’un biais privat + + Dobrir un sol onglet privat : tocatz l’icòna %s. Dobrir los paramètres diff --git a/app/src/main/res/values-pa-rIN/strings.xml b/app/src/main/res/values-pa-rIN/strings.xml index 980a4498ca..39f37630a8 100644 --- a/app/src/main/res/values-pa-rIN/strings.xml +++ b/app/src/main/res/values-pa-rIN/strings.xml @@ -175,8 +175,8 @@ ਸਕੈਨ ਕਰੋ - - ਖੋਜ ਇੰਜਣ + + ਖੋਜ ਇੰਜਣ ਖੋਜ ਇੰਜਣ ਸੈਟਿੰਗਾਂ @@ -308,6 +308,8 @@ ਲਿੰਕ ਐਪਾਂ ਵਿੱਚ ਖੋਲ੍ਹੋ + + ਬਾਹਰੀ ਡਾਊਨਲੋਡ ਮੈਨੇਜਰ ਐਡ-ਆਨ @@ -1471,9 +1473,7 @@ ਉਸ ਵਰਤੋਂਕਾਰ ਨਾਲ ਲਾਗਇਨ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ - - Firefox Account ਨਾਲ ਕਨੈਕਟ ਕਰੋ। - + ਹੋਰ ਡਿਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰੋ। ਮੁੜ-ਪ੍ਰਮਾਣਿਤ ਕਰੋ। @@ -1494,13 +1494,4 @@ ਠੀਕ ਹੈ, ਸਮਝ ਗਏ - - - ਸ਼ਾਰਟਕੱਟ - - ਇਸ ਨਾਲ ਖੋਜੋ - - ਇਸ ਵੇਲੇ, ਇਸ ਨਾਲ ਖੋਜੋ: - - ਖੋਜ ਸ਼ਾਰਟਕੱਟ ਵੇਖਾਓ diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 12a58500e9..d4e9db57c6 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -306,6 +306,8 @@ Otwieranie odnośników w aplikacjach + + Zewnętrzny menedżer pobierania Dodatki diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index d56093c00f..746d7cb074 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -541,7 +541,7 @@ Limpar histórico - Tem certeza que deseja limpar seu histórico? + Tem certeza que quer limpar o histórico? Histórico excluído @@ -601,7 +601,7 @@ Selecionar pasta - Tem certeza que deseja excluir esta pasta? + Tem certeza que quer excluir esta pasta? O %s excluirá os itens selecionados. @@ -861,7 +861,7 @@ NEGAR - Tem certeza que deseja excluir %1$s? + Tem certeza que quer excluir %1$s? Excluir esta aba também excluirá toda a coleção. Você pode criar novas coleções quando quiser. @@ -987,7 +987,7 @@ - Você está conectado como %s em outro navegador Firefox neste celular. Deseja entrar com esta conta? + Você está conectado como %s em outro navegador Firefox neste celular. Quer entrar com esta conta? Sim, entrar @@ -1008,26 +1008,26 @@ Padrão (predefinido) - Bloqueia menos rastreadores. Páginas são carregadas normalmente. + Bloqueia menos rastreadores. As páginas são carregadas normalmente. Rigoroso (recomendado) Rigoroso - Bloqueia mais rastreadores, anúncios e notificações. Páginas são carregadas mais rápido, mas algumas coisas podem não funcionar. + Bloqueia mais rastreadores, anúncios e notificações. As páginas são carregadas mais rápido, mas algumas coisas podem não funcionar. Escolha uma posição - Experimente navegar com apenas uma mão, usando a barra de ferramentas embaixo, ou a mova para o alto. + Experimente navegar usando apenas uma mão com a barra de ferramentas embaixo, ou a mova para o alto. Navegue com privacidade - Para abrir uma aba privativa só uma vez: Toque no ícone %s. + Para abrir manualmente uma aba privativa, toque no ícone %s. - Para abrir abas privativas todas as vezes: Mude a configuração da navegação privativa. + Para sempre abrir abas privativas, mude as configurações de navegação privativa. Abrir configurações @@ -1051,7 +1051,7 @@ Escolha um tema - Se quiser economizar bateria e poupar sua visão, use o modo escuro. + Se quiser poupar sua vista e economizar bateria, use o modo escuro. Automático @@ -1108,13 +1108,13 @@ Padrão (predefinido) - Bloqueia menos rastreadores. Páginas são carregadas normalmente. + Bloqueia menos rastreadores. As páginas são carregadas normalmente. O que é bloqueado pela proteção padrão contra rastreamento Rigoroso - Bloqueia mais rastreadores, anúncios e notificações. Páginas são carregadas mais rápido, mas algumas coisas podem não funcionar. + Bloqueia mais rastreadores, anúncios e notificações. As páginas são carregadas mais rápido, mas algumas coisas podem não funcionar. O que é bloqueado pela proteção rigorosa contra rastreamento @@ -1414,17 +1414,17 @@ Conexão não segura - Tem certeza que deseja limpar todas as permissões de todos os sites? + Tem certeza que quer limpar todas as permissões de todos os sites? - Tem certeza que deseja limpar todas as permissões deste site? + Tem certeza que quer limpar todas as permissões deste site? - Tem certeza que deseja limpar esta permissão deste site? + Tem certeza que quer limpar esta permissão deste site? Nenhuma exceção de sites Artigos populares - Tem certeza que deseja excluir este favorito? + Tem certeza que quer excluir este favorito? Adicionar preferido Editar - Tem certeza de que deseja excluir esta conta? + Tem certeza que quer excluir esta conta? Excluir diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 1aaf58253f..2275cf7494 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -298,6 +298,8 @@ Setările contului Deschide linkuri în aplicații + + Manager extern pentru descărcări Suplimente diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 811b7f814e..1c5b5a113c 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -311,6 +311,8 @@ Открывать ссылки в приложениях + + Внешний менеджер загрузок Дополнения diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 08ca671847..a794930a3b 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -308,6 +308,8 @@ Otvárať odkazy v aplikáciách + + Externý správca preberania súborov Doplnky diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index d70877b7f4..ad95390c93 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -304,6 +304,8 @@ Bağlantıları uygulamalarda aç + + Harici indirme yöneticisi Eklentiler diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index e4fd25403b..b8a0b512d3 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -301,6 +301,8 @@ ایپس میں ربط کھولیں + + بیرونی ڈاؤن لوڈ مینیجر ایڈ اون diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 02a89d376c..27b3c2b41c 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -302,6 +302,8 @@ Mở liên kết trong ứng dụng + + Trình quản lý tải xuống bên ngoài Tiện ích From 4a20607f8b931ec65442280fdb70522e3b292478 Mon Sep 17 00:00:00 2001 From: "codrut.topliceanu" Date: Sun, 9 Aug 2020 14:56:42 +0300 Subject: [PATCH 26/33] For #8625 - Label for search engine radio buttons --- app/src/main/res/layout/search_engine_radio_button.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/search_engine_radio_button.xml b/app/src/main/res/layout/search_engine_radio_button.xml index 74cf2c2ba6..a2d1026c11 100644 --- a/app/src/main/res/layout/search_engine_radio_button.xml +++ b/app/src/main/res/layout/search_engine_radio_button.xml @@ -10,12 +10,12 @@ android:minHeight="@dimen/radio_button_preference_height" android:background="?android:selectableItemBackground" android:clickable="true" + android:labelFor="@+id/radio_button" android:focusable="true"> From 5d14688448a40050a8ec42f05365051b596e440f Mon Sep 17 00:00:00 2001 From: Arturo Mejia Date: Fri, 14 Aug 2020 11:26:03 -0400 Subject: [PATCH 27/33] For issue #12796: Ensure Cookie purging is only active in nightly or debug. --- .../TrackingProtectionPolicyFactory.kt | 22 ++++++-- .../TrackingProtectionPolicyFactoryTest.kt | 54 +++++++++++++++++++ 2 files changed, 72 insertions(+), 4 deletions(-) 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 d101c16d1b..9a0853e43d 100644 --- a/app/src/main/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactory.kt +++ b/app/src/main/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactory.kt @@ -4,7 +4,10 @@ package org.mozilla.fenix.components +import androidx.annotation.VisibleForTesting import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy +import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicyForSessionTypes +import org.mozilla.fenix.Config import org.mozilla.fenix.utils.Settings /** @@ -34,9 +37,9 @@ class TrackingProtectionPolicyFactory(private val settings: Settings) { } return when { - normalMode && privateMode -> trackingProtectionPolicy - normalMode && !privateMode -> trackingProtectionPolicy.forRegularSessionsOnly() - !normalMode && privateMode -> trackingProtectionPolicy.forPrivateSessionsOnly() + normalMode && privateMode -> trackingProtectionPolicy.adaptPolicyToChannel() + normalMode && !privateMode -> trackingProtectionPolicy.adaptPolicyToChannel().forRegularSessionsOnly() + !normalMode && privateMode -> trackingProtectionPolicy.adaptPolicyToChannel().forPrivateSessionsOnly() else -> TrackingProtectionPolicy.none() } } @@ -44,7 +47,8 @@ class TrackingProtectionPolicyFactory(private val settings: Settings) { private fun createCustomTrackingProtectionPolicy(): TrackingProtectionPolicy { return TrackingProtectionPolicy.select( cookiePolicy = getCustomCookiePolicy(), - trackingCategories = getCustomTrackingCategories() + trackingCategories = getCustomTrackingCategories(), + cookiePurging = Config.channel.isNightlyOrDebug ).let { if (settings.blockTrackingContentSelectionInCustomTrackingProtection == "private") { it.forPrivateSessionsOnly() @@ -91,3 +95,13 @@ class TrackingProtectionPolicyFactory(private val settings: Settings) { return categories.toTypedArray() } } + +@VisibleForTesting +internal fun TrackingProtectionPolicyForSessionTypes.adaptPolicyToChannel(): TrackingProtectionPolicyForSessionTypes { + return TrackingProtectionPolicy.select( + trackingCategories = trackingCategories, + cookiePolicy = cookiePolicy, + strictSocialTrackingProtection = strictSocialTrackingProtection, + cookiePurging = Config.channel.isNightlyOrDebug + ) +} 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 2344bf4b82..9289859d2e 100644 --- a/app/src/test/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactoryTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/TrackingProtectionPolicyFactoryTest.kt @@ -2,7 +2,9 @@ package org.mozilla.fenix.components import io.mockk.every import io.mockk.mockk +import io.mockk.mockkObject import mozilla.components.concept.engine.EngineSession +import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy import mozilla.components.support.test.robolectric.testContext import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals @@ -10,7 +12,9 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.Config import org.mozilla.fenix.R +import org.mozilla.fenix.ReleaseChannel import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.helpers.FenixRobolectricTestRunner @@ -87,6 +91,56 @@ class TrackingProtectionPolicyFactoryTest { expected.assertPolicyEquals(always, checkPrivacy = false) } + @Test + fun `cookiePurging must be available ONLY in nightly or debug`() { + mockkObject(Config) + for (channel in ReleaseChannel.values()) { + every { Config.channel } returns channel + + val shouldCookiePurgingActive = channel.isNightlyOrDebug + val customSetting = + settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "all") + val stringSetting = mockSettings(useStrict = true) + val recommendedSetting = mockSettings(useTrackingProtection = true) + + for (setting in arrayOf(recommendedSetting, stringSetting, customSetting)) { + val factory = TrackingProtectionPolicyFactory(setting) + val privateOnly = + factory.createTrackingProtectionPolicy(normalMode = false, privateMode = true) + val normalOnly = + factory.createTrackingProtectionPolicy(normalMode = true, privateMode = false) + val always = + factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true) + + assertEquals(shouldCookiePurgingActive, privateOnly.cookiePurging) + assertEquals(shouldCookiePurgingActive, normalOnly.cookiePurging) + assertEquals(shouldCookiePurgingActive, always.cookiePurging) + } + } + } + + @Test + fun `adaptPolicyToChannel MUST only update properties that have changed per given channel`() { + mockkObject(Config) + + val policies = arrayOf( + TrackingProtectionPolicy.strict(), TrackingProtectionPolicy.recommended(), + TrackingProtectionPolicy.select() + ) + + for (channel in ReleaseChannel.values()) { + every { Config.channel } returns channel + + val shouldCookiePurgingActive = channel.isNightlyOrDebug + + for (policy in policies) { + val adaptedPolicy = policy.adaptPolicyToChannel() + policy.assertPolicyEquals(adaptedPolicy, checkPrivacy = false) + assertEquals(shouldCookiePurgingActive, adaptedPolicy.cookiePurging) + } + } + } + @Test fun `GIVEN custom policy WHEN cookie policy social THEN tracking policy should have cookie policy allow non-trackers`() { val expected = EngineSession.TrackingProtectionPolicy.select( From 453dc58ddd64580626fd4abd7e977b421d3b07e7 Mon Sep 17 00:00:00 2001 From: MickeyMoz Date: Mon, 17 Aug 2020 14:05:58 +0000 Subject: [PATCH 28/33] Update Android Components version to 54.0.20200814130102. --- buildSrc/src/main/java/AndroidComponents.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/java/AndroidComponents.kt b/buildSrc/src/main/java/AndroidComponents.kt index 0f94869b4f..c429e7980e 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 = "54.0.20200813130057" + const val VERSION = "54.0.20200814130102" } From 1e223a8a5334f99302de8b6906065fef0594472a Mon Sep 17 00:00:00 2001 From: mcarare Date: Mon, 17 Aug 2020 17:41:58 +0300 Subject: [PATCH 29/33] For #13761: Add a11y change listener after toolbar is initialised. Also removed it before reference is removed in onDestroy. --- .../java/org/mozilla/fenix/browser/BaseBrowserFragment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 836b4755dd..cfad148597 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -188,6 +188,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session final override fun onViewCreated(view: View, savedInstanceState: Bundle?) { browserInitialized = initializeUI(view) != null + requireContext().accessibilityManager.addAccessibilityStateChangeListener(this) } @Suppress("ComplexMethod", "LongMethod") @@ -756,7 +757,6 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session super.onStart() requireComponents.core.sessionManager.register(this, this, autoPause = true) sitePermissionWifiIntegration.get()?.maybeAddWifiConnectedListener() - requireContext().accessibilityManager.addAccessibilityStateChangeListener(this) } @CallSuper @@ -1062,9 +1062,9 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session */ override fun onDestroyView() { super.onDestroyView() + requireContext().accessibilityManager.removeAccessibilityStateChangeListener(this) _browserToolbarView = null _browserInteractor = null - requireContext().accessibilityManager.removeAccessibilityStateChangeListener(this) } companion object { From 54c24016ba32e565fc1bbcc2ad5c545b0bee9ddf Mon Sep 17 00:00:00 2001 From: ekager Date: Tue, 4 Aug 2020 17:07:36 -0400 Subject: [PATCH 30/33] For #13251 - Use bottomSheetCallback in multiselect mode --- .../org/mozilla/fenix/tabtray/TabTrayView.kt | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt index 8e8781e65a..9b78836ff3 100644 --- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt +++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt @@ -45,6 +45,7 @@ import org.mozilla.fenix.components.toolbar.TabCounter.Companion.SO_MANY_TABS_OP import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.tabtray.SaveToCollectionsButtonAdapter.MultiselectModeChange +import org.mozilla.fenix.tabtray.TabTrayDialogFragmentState.Mode import java.text.NumberFormat /** @@ -75,7 +76,6 @@ class TabTrayView( private val tabTrayItemMenu: TabTrayItemMenu private var menu: BrowserMenu? = null - private val bottomSheetCallback: BottomSheetBehavior.BottomSheetCallback private var tabsTouchHelper: TabsTouchHelper private val collectionsButtonAdapter = SaveToCollectionsButtonAdapter(interactor, isPrivate) @@ -89,9 +89,9 @@ class TabTrayView( toggleFabText(isPrivate) - bottomSheetCallback = object : BottomSheetBehavior.BottomSheetCallback() { + behavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { override fun onSlide(bottomSheet: View, slideOffset: Float) { - if (!hasAccessibilityEnabled) { + if (interactor.onModeRequested() is Mode.Normal && !hasAccessibilityEnabled) { if (slideOffset >= SLIDE_OFFSET) { fabView.new_tab_button.show() } else { @@ -106,9 +106,7 @@ class TabTrayView( interactor.onTabTrayDismissed() } } - } - - behavior.addBottomSheetCallback(bottomSheetCallback) + }) val selectedTabIndex = if (!isPrivate) { DEFAULT_TAB_ID @@ -275,17 +273,17 @@ class TabTrayView( override fun onTabUnselected(tab: TabLayout.Tab?) { /*noop*/ } - var mode: TabTrayDialogFragmentState.Mode = TabTrayDialogFragmentState.Mode.Normal + var mode: Mode = Mode.Normal private set fun updateState(state: TabTrayDialogFragmentState) { val oldMode = mode if (oldMode::class != state.mode::class) { - updateTabsForMultiselectModeChanged(state.mode is TabTrayDialogFragmentState.Mode.MultiSelect) + updateTabsForMultiselectModeChanged(state.mode is Mode.MultiSelect) if (view.context.settings().accessibilityServicesEnabled) { view.announceForAccessibility( - if (state.mode == TabTrayDialogFragmentState.Mode.Normal) view.context.getString( + if (state.mode == Mode.Normal) view.context.getString( R.string.tab_tray_exit_multiselect_content_description ) else view.context.getString(R.string.tab_tray_enter_multiselect_content_description) ) @@ -294,20 +292,18 @@ class TabTrayView( mode = state.mode when (state.mode) { - TabTrayDialogFragmentState.Mode.Normal -> { + Mode.Normal -> { view.tabsTray.apply { tabsTouchHelper.attachToRecyclerView(this) } - behavior.addBottomSheetCallback(bottomSheetCallback) toggleUIMultiselect(multiselect = false) updateUINormalMode(state.browserState) } - is TabTrayDialogFragmentState.Mode.MultiSelect -> { + is Mode.MultiSelect -> { // Disable swipe to delete while in multiselect tabsTouchHelper.attachToRecyclerView(null) - behavior.removeBottomSheetCallback(bottomSheetCallback) toggleUIMultiselect(multiselect = true) From 1816fbf49f7dc1a6be2b0c2e1f51c02c1fcc4bb2 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Mon, 10 Aug 2020 09:11:42 -0400 Subject: [PATCH 31/33] Bug 1608838: Add data sensitivity metadata --- app/metrics.yaml | 524 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 524 insertions(+) diff --git a/app/metrics.yaml b/app/metrics.yaml index 5a15283cbd..230f67c14a 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -34,6 +34,8 @@ events: - https://github.com/mozilla-mobile/fenix/issues/11830 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12114#pullrequestreview-445245341 + data_sensitivity: + - interaction notification_emails: - esmyth@mozilla.com - perf-android-fe@mozilla.com @@ -78,6 +80,8 @@ events: - https://github.com/mozilla-mobile/fenix/issues/10616 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 + data_sensitivity: + - interaction notification_emails: - telemetry-client-dev@mozilla.com - fenix-core@mozilla.com @@ -95,6 +99,8 @@ events: - https://github.com/mozilla-mobile/fenix/issues/959 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -111,6 +117,8 @@ events: - https://github.com/mozilla-mobile/fenix/issues/959 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -133,6 +141,8 @@ events: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 - https://github.com/mozilla-mobile/fenix/pull/1677 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -156,6 +166,8 @@ events: - https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708 - https://github.com/mozilla-mobile/fenix/pull/5098#issuecomment-529658996 - https://github.com/mozilla-mobile/fenix/pull/6310 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -175,6 +187,8 @@ events: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1785 - https://github.com/mozilla-mobile/fenix/pull/8314 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -213,6 +227,9 @@ events: - https://github.com/mozilla-mobile/fenix/pull/6352 - https://github.com/mozilla-mobile/fenix/pull/6601 - https://github.com/mozilla-mobile/fenix/pull/6746 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -224,6 +241,8 @@ events: - https://github.com/mozilla-mobile/fenix/issues/5021 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5090 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -239,6 +258,8 @@ events: - https://github.com/mozilla-mobile/fenix/issues/5737 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5975 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -257,6 +278,8 @@ events: - https://github.com/mozilla-mobile/fenix/issues/11442 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11533 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -270,6 +293,8 @@ onboarding: - https://github.com/mozilla-mobile/fenix/issues/10824 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -282,6 +307,8 @@ onboarding: - https://github.com/mozilla-mobile/fenix/issues/10824 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -294,6 +321,8 @@ onboarding: - https://github.com/mozilla-mobile/fenix/issues/10824 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -306,6 +335,8 @@ onboarding: - https://github.com/mozilla-mobile/fenix/issues/10824 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -323,6 +354,8 @@ onboarding: - https://github.com/mozilla-mobile/fenix/issues/10824 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -340,6 +373,8 @@ onboarding: - https://github.com/mozilla-mobile/fenix/issues/10824 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -352,6 +387,8 @@ onboarding: - https://github.com/mozilla-mobile/fenix/issues/10824 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -369,6 +406,8 @@ onboarding: - https://github.com/mozilla-mobile/fenix/issues/10824 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -381,6 +420,8 @@ onboarding: - https://github.com/mozilla-mobile/fenix/issues/10824 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -416,6 +457,8 @@ toolbar_settings: - https://github.com/mozilla-mobile/fenix/issues/6054 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6608 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -429,6 +472,8 @@ crash_reporter: - https://github.com/mozilla-mobile/fenix/issues/1040 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -445,6 +490,8 @@ crash_reporter: - https://github.com/mozilla-mobile/fenix/issues/1040 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -467,6 +514,8 @@ context_menu: - https://github.com/mozilla-mobile/fenix/issues/957 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -480,6 +529,8 @@ login_dialog: - https://github.com/mozilla-mobile/fenix/issues/9730 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13050 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2021-02-01" @@ -491,6 +542,8 @@ login_dialog: - https://github.com/mozilla-mobile/fenix/issues/9730 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13050 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2021-02-01" @@ -502,6 +555,8 @@ login_dialog: - https://github.com/mozilla-mobile/fenix/issues/9730 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13050 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2021-02-01" @@ -513,6 +568,8 @@ login_dialog: - https://github.com/mozilla-mobile/fenix/issues/9730 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13050 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2021-02-01" @@ -526,6 +583,8 @@ find_in_page: - https://github.com/mozilla-mobile/fenix/issues/1036 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -537,6 +596,8 @@ find_in_page: - https://github.com/mozilla-mobile/fenix/issues/1036 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -548,6 +609,8 @@ find_in_page: - https://github.com/mozilla-mobile/fenix/issues/1036 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -564,6 +627,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/960 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -582,6 +647,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/8125 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9556 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -596,6 +663,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/8125 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9556 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -618,6 +687,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/11909 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11982#pullrequestreview-437963817 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-12-01" @@ -633,6 +704,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/11909 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11982#pullrequestreview-437963817 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-12-01" @@ -658,6 +731,9 @@ metrics: - https://github.com/mozilla-mobile/fenix/pull/1677 - https://github.com/mozilla-mobile/fenix/pull/5216 - https://github.com/mozilla-mobile/fenix/pull/7310 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -676,6 +752,9 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1953/ - https://github.com/mozilla-mobile/fenix/pull/5216 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -692,6 +771,9 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1953/ - https://github.com/mozilla-mobile/fenix/pull/5216 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -709,6 +791,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/9136 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5579 + data_sensitivity: + - technical notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -726,6 +810,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/9136 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9253 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -743,6 +829,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/9136 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9253 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -760,6 +848,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/9136 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9253 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -774,6 +864,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/6054 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6608 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -788,6 +880,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/9488 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10958 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -806,6 +900,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/11479 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12024 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -820,6 +916,8 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/11479 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12024 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -836,6 +934,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -850,6 +950,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -866,6 +968,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -881,6 +985,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -895,6 +1001,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -909,6 +1017,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -923,6 +1033,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -937,6 +1049,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -951,6 +1065,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -965,6 +1081,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -981,6 +1099,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -995,6 +1115,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1010,6 +1132,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1024,6 +1148,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1039,6 +1165,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1053,6 +1181,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11446 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1067,6 +1197,8 @@ preferences: - https://github.com/mozilla-mobile/fenix/issues/11118 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11446 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1087,6 +1219,9 @@ search.default_engine: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1606 - https://github.com/mozilla-mobile/fenix/pull/5216 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1105,6 +1240,9 @@ search.default_engine: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1606 - https://github.com/mozilla-mobile/fenix/pull/5216 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1124,6 +1262,9 @@ search.default_engine: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1606 - https://github.com/mozilla-mobile/fenix/pull/5216 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1137,6 +1278,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1148,6 +1291,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1159,6 +1304,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1170,6 +1317,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1181,6 +1330,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1192,6 +1343,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1203,6 +1356,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1214,6 +1369,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1225,6 +1382,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1236,6 +1395,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1247,6 +1408,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/974 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1258,6 +1421,8 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/3174 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3724 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1271,6 +1436,8 @@ custom_tab: - https://github.com/mozilla-mobile/fenix/issues/977 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1697 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1282,6 +1449,8 @@ custom_tab: - https://github.com/mozilla-mobile/fenix/issues/977 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1697 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1293,6 +1462,8 @@ custom_tab: - https://github.com/mozilla-mobile/fenix/issues/977 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1697 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1311,6 +1482,8 @@ activation: - https://bugzilla.mozilla.org/1501822 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1707#issuecomment-486972209 + data_sensitivity: + - highly_sensitive notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1326,6 +1499,8 @@ activation: - https://bugzilla.mozilla.org/1538011 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1707#issuecomment-486972209 + data_sensitivity: + - highly_sensitive notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1341,6 +1516,8 @@ qr_scanner: - https://github.com/mozilla-mobile/fenix/issues/1857 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1353,6 +1530,8 @@ qr_scanner: - https://github.com/mozilla-mobile/fenix/issues/1857 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1365,6 +1544,8 @@ qr_scanner: - https://github.com/mozilla-mobile/fenix/issues/1857 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1377,6 +1558,8 @@ qr_scanner: - https://github.com/mozilla-mobile/fenix/issues/1857 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1393,6 +1576,8 @@ error_page: - https://github.com/mozilla-mobile/fenix/issues/1242 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2491#issuecomment-492414486 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1406,6 +1591,8 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/1190 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1417,6 +1604,8 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/1190 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1429,6 +1618,8 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/9834 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9835#pullrequestreview-398641844 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1440,6 +1631,8 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/9834 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9835#pullrequestreview-398641844 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1452,6 +1645,8 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/1190 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1464,6 +1659,8 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/1190 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1475,6 +1672,9 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/4971 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1487,6 +1687,9 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/4971 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1499,6 +1702,9 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/4971 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1511,6 +1717,9 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/4971 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1523,6 +1732,9 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/4971 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1534,6 +1746,8 @@ sync_auth: - https://github.com/mozilla-mobile/fenix/issues/1190 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1547,6 +1761,8 @@ sync_account: - https://github.com/mozilla-mobile/fenix/issues/1190 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1558,6 +1774,8 @@ sync_account: - https://github.com/mozilla-mobile/fenix/issues/1190 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1569,6 +1787,8 @@ sync_account: - https://github.com/mozilla-mobile/fenix/issues/1190 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1580,6 +1800,8 @@ sync_account: - https://github.com/mozilla-mobile/fenix/issues/4908 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5106 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1591,6 +1813,8 @@ sync_account: - https://github.com/mozilla-mobile/fenix/issues/4908 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5106 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1604,6 +1828,8 @@ history: - https://github.com/mozilla-mobile/fenix/issues/2362 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3940 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1615,6 +1841,8 @@ history: - https://github.com/mozilla-mobile/fenix/issues/2362 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3940 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1626,6 +1854,8 @@ history: - https://github.com/mozilla-mobile/fenix/issues/2362 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3940 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1637,6 +1867,8 @@ history: - https://github.com/mozilla-mobile/fenix/issues/2362 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3940 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1648,6 +1880,8 @@ history: - https://github.com/mozilla-mobile/fenix/issues/2362 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3940 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1664,6 +1898,8 @@ tip: - https://github.com/mozilla-mobile/fenix/issues/9328 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9836 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1678,6 +1914,8 @@ tip: - https://github.com/mozilla-mobile/fenix/issues/9328 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9836 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1692,6 +1930,8 @@ tip: - https://github.com/mozilla-mobile/fenix/issues/9328 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9836 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1705,6 +1945,8 @@ reader_mode: - https://github.com/mozilla-mobile/fenix/issues/2267 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3941 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1716,6 +1958,8 @@ reader_mode: - https://github.com/mozilla-mobile/fenix/issues/2267 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3941 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1727,6 +1971,8 @@ reader_mode: - https://github.com/mozilla-mobile/fenix/issues/2267 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4328 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1738,6 +1984,8 @@ reader_mode: - https://github.com/mozilla-mobile/fenix/issues/2267 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3941 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1751,6 +1999,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1762,6 +2012,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1773,6 +2025,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1784,6 +2038,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1795,6 +2051,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1806,6 +2064,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1817,6 +2077,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1828,6 +2090,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1839,6 +2103,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1851,6 +2117,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1863,6 +2131,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1875,6 +2145,8 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/11273 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1888,6 +2160,9 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1899,6 +2174,9 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1910,6 +2188,9 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1921,6 +2202,9 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1932,6 +2216,9 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1943,6 +2230,9 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1959,6 +2249,9 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1975,6 +2268,9 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1987,6 +2283,9 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -1998,6 +2297,8 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4358 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2009,6 +2310,8 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4358 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2022,6 +2325,8 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4358 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2038,6 +2343,8 @@ collections: - https://github.com/mozilla-mobile/fenix/issues/969 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4539 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2052,6 +2359,8 @@ search_widget: - https://github.com/mozilla-mobile/fenix/issues/4457 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4714 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2063,6 +2372,8 @@ search_widget: - https://github.com/mozilla-mobile/fenix/issues/4457 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4714 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2076,6 +2387,8 @@ search_widget_cfr: - https://github.com/mozilla-mobile/fenix/issues/9488 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10958 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2087,6 +2400,8 @@ search_widget_cfr: - https://github.com/mozilla-mobile/fenix/issues/9488 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10958 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2098,6 +2413,8 @@ search_widget_cfr: - https://github.com/mozilla-mobile/fenix/issues/9488 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10958 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2110,6 +2427,8 @@ search_widget_cfr: - https://github.com/mozilla-mobile/fenix/issues/9488 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10958 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2124,6 +2443,8 @@ private_browsing_mode: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4968 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2136,6 +2457,8 @@ private_browsing_mode: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4968 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2147,6 +2470,8 @@ private_browsing_mode: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4968 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2158,6 +2483,8 @@ private_browsing_mode: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4968 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2170,6 +2497,8 @@ private_browsing_mode: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4968 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2184,6 +2513,8 @@ contextual_hint.tracking_protection: - https://github.com/mozilla-mobile/fenix/issues/9625 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11923 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2197,6 +2528,8 @@ contextual_hint.tracking_protection: - https://github.com/mozilla-mobile/fenix/issues/9625 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11923 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2209,6 +2542,8 @@ contextual_hint.tracking_protection: - https://github.com/mozilla-mobile/fenix/issues/9625 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11923 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2221,6 +2556,8 @@ contextual_hint.tracking_protection: - https://github.com/mozilla-mobile/fenix/issues/9625 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11923 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2235,6 +2572,8 @@ tracking_protection: - https://github.com/mozilla-mobile/fenix/issues/5312 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2246,6 +2585,8 @@ tracking_protection: - https://github.com/mozilla-mobile/fenix/issues/5312 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2257,6 +2598,8 @@ tracking_protection: - https://github.com/mozilla-mobile/fenix/issues/5312 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2269,6 +2612,8 @@ tracking_protection: - https://github.com/mozilla-mobile/fenix/issues/5312 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2280,6 +2625,8 @@ tracking_protection: - https://github.com/mozilla-mobile/fenix/issues/5312 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2297,6 +2644,8 @@ tracking_protection: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 - https://github.com/mozilla-mobile/fenix/pull/11383 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2310,6 +2659,8 @@ private_browsing_shortcut: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2322,6 +2673,8 @@ private_browsing_shortcut: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2334,6 +2687,8 @@ private_browsing_shortcut: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2346,6 +2701,8 @@ private_browsing_shortcut: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2358,6 +2715,8 @@ private_browsing_shortcut: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2370,6 +2729,8 @@ private_browsing_shortcut: - https://github.com/mozilla-mobile/fenix/issues/4658 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2383,6 +2744,8 @@ tab: - https://github.com/mozilla-mobile/fenix/issues/5197 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5266 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2396,6 +2759,8 @@ tab: - https://github.com/mozilla-mobile/fenix/issues/5197 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5266 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2409,6 +2774,8 @@ media_notification: - https://github.com/mozilla-mobile/fenix/issues/5197 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5520 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2420,6 +2787,8 @@ media_notification: - https://github.com/mozilla-mobile/fenix/issues/5197 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5520 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2433,6 +2802,8 @@ media_state: - https://github.com/mozilla-mobile/fenix/issues/5705 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6463 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2444,6 +2815,8 @@ media_state: - https://github.com/mozilla-mobile/fenix/issues/5705 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6463 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2455,6 +2828,8 @@ media_state: - https://github.com/mozilla-mobile/fenix/issues/5705 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6463 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2468,6 +2843,8 @@ logins: - https://github.com/mozilla-mobile/fenix/issues/5586 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6352 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2479,6 +2856,8 @@ logins: - https://github.com/mozilla-mobile/fenix/issues/5586 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6352 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2490,6 +2869,8 @@ logins: - https://github.com/mozilla-mobile/fenix/issues/5586 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6352 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2501,6 +2882,8 @@ logins: - https://github.com/mozilla-mobile/fenix/issues/5586 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6352 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2517,6 +2900,8 @@ logins: - https://github.com/mozilla-mobile/fenix/issues/5586 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/7767 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2528,6 +2913,8 @@ logins: - https://github.com/mozilla-mobile/fenix/issues/10173 data_reviews: - https://github.com/mozilla-mobile/fenix/issues/11208 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2539,6 +2926,8 @@ logins: - https://github.com/mozilla-mobile/fenix/issues/10173 data_reviews: - https://github.com/mozilla-mobile/fenix/issues/11208 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2550,6 +2939,8 @@ logins: - https://github.com/mozilla-mobile/fenix/issues/10173 data_reviews: - https://github.com/mozilla-mobile/fenix/issues/11208 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2563,6 +2954,8 @@ download_notification: - https://github.com/mozilla-mobile/fenix/issues/5583 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6554 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2574,6 +2967,8 @@ download_notification: - https://github.com/mozilla-mobile/fenix/issues/5583 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6554 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2585,6 +2980,8 @@ download_notification: - https://github.com/mozilla-mobile/fenix/issues/5583 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6554 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2597,6 +2994,8 @@ download_notification: - https://github.com/mozilla-mobile/fenix/issues/5583 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6554 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2608,6 +3007,8 @@ download_notification: - https://github.com/mozilla-mobile/fenix/issues/5583 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6554 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2619,6 +3020,8 @@ download_notification: - https://github.com/mozilla-mobile/fenix/issues/5583 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6554 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2631,6 +3034,8 @@ download_notification: - https://github.com/mozilla-mobile/fenix/issues/5583 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6554 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2644,6 +3049,8 @@ user_specified_search_engines: - https://github.com/mozilla-mobile/fenix/issues/5884 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6918 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2658,6 +3065,8 @@ user_specified_search_engines: - https://github.com/mozilla-mobile/fenix/issues/7881 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6918 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2671,6 +3080,9 @@ search_suggestions: - https://github.com/mozilla-mobile/fenix/issues/6070 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6746 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2684,6 +3096,8 @@ voice_search: - https://github.com/mozilla-mobile/fenix/issues/10465 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10785 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2697,6 +3111,8 @@ top_sites: - https://github.com/mozilla-mobile/fenix/issues/8125 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10752 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2708,6 +3124,8 @@ top_sites: - https://github.com/mozilla-mobile/fenix/issues/6757 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/7523 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2719,6 +3137,8 @@ top_sites: - https://github.com/mozilla-mobile/fenix/issues/6757 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/7523 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2730,6 +3150,8 @@ top_sites: - https://github.com/mozilla-mobile/fenix/issues/6757 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/7523 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2743,6 +3165,8 @@ about_page: - https://github.com/mozilla-mobile/fenix/issues/6834 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8047 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2754,6 +3178,8 @@ about_page: - https://github.com/mozilla-mobile/fenix/issues/6834 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8047 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2765,6 +3191,8 @@ about_page: - https://github.com/mozilla-mobile/fenix/issues/6834 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8047 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2776,6 +3204,8 @@ about_page: - https://github.com/mozilla-mobile/fenix/issues/6834 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8047 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2787,6 +3217,8 @@ about_page: - https://github.com/mozilla-mobile/fenix/issues/6834 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8047 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2805,6 +3237,8 @@ app_theme: - https://github.com/mozilla-mobile/fenix/issues/7289 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/7968 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2818,6 +3252,8 @@ pocket: - https://github.com/mozilla-mobile/fenix/issues/8126 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8098 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2832,6 +3268,8 @@ pocket: - https://github.com/mozilla-mobile/fenix/issues/8126 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8098 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2847,6 +3285,9 @@ first_session: - https://github.com/mozilla-mobile/fenix/issues/7295 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2860,6 +3301,9 @@ first_session: - https://github.com/mozilla-mobile/fenix/issues/7295 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2873,6 +3317,9 @@ first_session: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586480836 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2886,6 +3333,9 @@ first_session: - https://github.com/mozilla-mobile/fenix/issues/7295 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2901,6 +3351,9 @@ first_session: - https://github.com/mozilla-mobile/fenix/issues/7295 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2917,6 +3370,8 @@ browser.search: - https://github.com/mozilla-mobile/fenix/issues/6558 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10112 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2931,6 +3386,8 @@ browser.search: - https://github.com/mozilla-mobile/fenix/issues/6558 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10112 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2944,6 +3401,8 @@ browser.search: - https://github.com/mozilla-mobile/fenix/issues/6557 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10167 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2957,6 +3416,8 @@ addons: - https://github.com/mozilla-mobile/fenix/issues/6174 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8318 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2972,6 +3433,8 @@ addons: - https://github.com/mozilla-mobile/fenix/issues/6174 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8318 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2985,6 +3448,8 @@ addons: - https://github.com/mozilla-mobile/fenix/issues/6174 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8318 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -2998,6 +3463,8 @@ addons: - https://github.com/mozilla-mobile/fenix/issues/6174 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8318 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -3011,6 +3478,8 @@ addons: - https://github.com/mozilla-mobile/fenix/issues/8920 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11080 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -3024,6 +3493,8 @@ addons: - https://github.com/mozilla-mobile/fenix/issues/8920 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11080 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2020-10-01" @@ -3048,6 +3519,8 @@ startup.timeline: - https://github.com/mozilla-mobile/fenix/issues/8803 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626 + data_sensitivity: + - technical notification_emails: - perf-android-fe@mozilla.com - mcomella@mozilla.com @@ -3064,6 +3537,8 @@ startup.timeline: - https://github.com/mozilla-mobile/fenix/issues/8803 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626 + data_sensitivity: + - technical notification_emails: - perf-android-fe@mozilla.com - mcomella@mozilla.com @@ -3080,6 +3555,8 @@ startup.timeline: - https://github.com/mozilla-mobile/fenix/issues/10434 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10481 + data_sensitivity: + - technical notification_emails: - perf-android-fe@mozilla.com - mcomella@mozilla.com @@ -3096,6 +3573,8 @@ startup.timeline: - https://github.com/mozilla-mobile/fenix/issues/8803 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626 + data_sensitivity: + - technical notification_emails: - perf-android-fe@mozilla.com - mcomella@mozilla.com @@ -3113,6 +3592,9 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - gkruglov@mozilla.com @@ -3128,6 +3610,9 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - gkruglov@mozilla.com @@ -3143,6 +3628,9 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - gkruglov@mozilla.com @@ -3158,6 +3646,9 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - gkruglov@mozilla.com @@ -3173,6 +3664,9 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - gkruglov@mozilla.com @@ -3188,6 +3682,9 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - gkruglov@mozilla.com @@ -3203,6 +3700,9 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - gkruglov@mozilla.com @@ -3216,6 +3716,8 @@ autoplay: - https://github.com/mozilla-mobile/fenix/issues/11579 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13041#issuecomment-665777411 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2021-02-01" @@ -3233,6 +3735,8 @@ autoplay: - https://github.com/mozilla-mobile/fenix/issues/11579 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13041#issuecomment-665777411 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com expires: "2021-02-01" @@ -3251,6 +3755,9 @@ storage.stats: - https://github.com/mozilla-mobile/fenix/issues/12802 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - perf-android-fe@mozilla.com @@ -3272,6 +3779,9 @@ storage.stats: - https://github.com/mozilla-mobile/fenix/issues/12802 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - perf-android-fe@mozilla.com @@ -3290,6 +3800,9 @@ storage.stats: - https://github.com/mozilla-mobile/fenix/issues/12802 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - perf-android-fe@mozilla.com @@ -3310,6 +3823,9 @@ storage.stats: - https://github.com/mozilla-mobile/fenix/issues/12802 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732 + data_sensitivity: + - technical + - interaction notification_emails: - fenix-core@mozilla.com - perf-android-fe@mozilla.com @@ -3325,6 +3841,8 @@ progressive_web_app: - https://github.com/mozilla-mobile/fenix/issues/10261 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11859 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -3337,6 +3855,8 @@ progressive_web_app: - https://github.com/mozilla-mobile/fenix/issues/10261 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11859 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -3353,6 +3873,8 @@ progressive_web_app: - https://github.com/mozilla-mobile/fenix/issues/10261 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11859 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com @@ -3369,6 +3891,8 @@ progressive_web_app: - https://github.com/mozilla-mobile/fenix/issues/10261 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11859 + data_sensitivity: + - interaction notification_emails: - fenix-core@mozilla.com - erichards@mozilla.com From a6481cc8978db01dcbf253c46c04a70daf75f085 Mon Sep 17 00:00:00 2001 From: Mozilla L10n Automation Bot Date: Tue, 18 Aug 2020 00:14:06 +0000 Subject: [PATCH 32/33] Import l10n. --- app/src/main/res/values-kab/strings.xml | 2 ++ app/src/main/res/values-ko/strings.xml | 48 ++++++++++++------------- app/src/main/res/values-nl/strings.xml | 2 ++ 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index db2edf6953..82e05af33b 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -306,6 +306,8 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ldi iseɣwan deg isnasen + + Amsefrak n usider azɣaray Izegrar diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index f3974fac72..1e8c7fdedd 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -30,16 +30,16 @@ %1$d개 선택됨 - 새 컬렉션 추가 + 새 모음집 추가 이름 - 컬렉션 선택 + 모음집 선택 다중 선택 모드 종료 - 선택한 탭을 컬렉션에 저장 + 선택한 탭을 모음집에 저장 %1$s 선택됨 @@ -49,7 +49,7 @@ 다중 선택 모드 종료됨 - 다중 선택 모드로 전환됨, 컬렉션에 저장할 탭을 선택하세요 + 다중 선택 모드로 전환됨, 모음집에 저장할 탭을 선택하세요 선택됨 @@ -137,7 +137,7 @@ 새 탭 - 컬렉션에 저장 + 모음집에 저장 공유 @@ -497,7 +497,7 @@ 탭 열기 - 컬렉션에 저장 + 모음집에 저장 모든 탭 공유 @@ -509,7 +509,7 @@ 탭 모드 전환 - 컬렉션에서 탭 삭제 + 모음집에서 탭 삭제 탭 닫기 @@ -521,7 +521,7 @@ 탭 공유 - 탭을 컬렉션에 저장 + 탭을 모음집에 저장 탭 메뉴 @@ -536,11 +536,11 @@ 현재 세션 이미지 - 컬렉션에 저장 + 모음집에 저장 - 컬렉션 삭제 + 모음집 삭제 - 컬렉션 이름 변경 + 모음집 이름 변경 열린 탭 @@ -751,25 +751,25 @@ - 컬렉션 + 모음집 - 컬렉션 메뉴 + 모음집 메뉴 - 중요한 것들을 모으세요 + 중요한 것들 수집하기 - 나중에 빠르게 액세스 할 수 있도록 유사한 검색, 사이트 및 탭을 그룹화하세요. + 나중에 빠르게 접근할 수 있도록 유사한 검색, 사이트 및 탭을 모아 보세요. 탭 선택 - 컬렉션 선택 + 모음집 선택 - 컬렉션 이름 + 모음집 이름 - 새 컬렉션 추가 + 새 모음집 추가 모두 선택 @@ -790,7 +790,7 @@ 탭이 저장되었습니다! - 컬렉션 저장됨! + 모음집 저장됨! 탭이 저장되었습니다! @@ -804,7 +804,7 @@ 보기 - 컬렉션 %d개 + 모음집 %d개 @@ -864,10 +864,10 @@ 제공: - 컬렉션 삭제됨 + 모음집 삭제됨 - 컬렉션 이름 변경됨 + 모음집 이름 변경됨 탭 삭제됨 @@ -904,9 +904,9 @@ %1$s 파일을 삭제하시겠습니까? - 이 탭을 삭제하면 전체 컬렉션이 삭제됩니다. 언제든지 새 컬렉션을 만들 수 있습니다. + 이 탭을 삭제하면 전체 모음집이 삭제됩니다. 언제든지 새 모음집을 만들 수 있습니다. - %1$s 컬렉션을 삭제하시겠습니까? + %1$s 모음집을 삭제하시겠습니까? 삭제 diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 071f252b1c..573324abff 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -40,6 +40,8 @@ Geselecteerde tabbladen in collectie opslaan %1$s geselecteerd + + Selectie %1$s ongedaan gemaakt Geselecteerd From 2743c37b40788e67ef6813fd8af412e1eb36987b Mon Sep 17 00:00:00 2001 From: Gilbert Gilb's Date: Thu, 13 Aug 2020 01:09:59 +0200 Subject: [PATCH 33/33] Add custom Activity to show libraries licenses. As Google's library for showing licences isn't open-source, this commit reimplements its main Activity. This is in prevision to having an OSS flavor of fenix. We chose to not introduce dependencies to third-party libraries such as AboutLibraries for now, and we'll stick to using Google's gradle plugin for the dependencies extraction. Fixes #7584 See also #162 --- app/build.gradle | 1 - app/src/main/AndroidManifest.xml | 9 +- .../fenix/settings/about/AboutFragment.kt | 10 +- .../settings/about/AboutLibrariesActivity.kt | 120 ++++++++++++++++++ .../res/layout/about_libraries_activity.xml | 25 ++++ .../about/AboutLibrariesActivityTest.kt | 45 +++++++ buildSrc/src/main/java/Dependencies.kt | 2 - 7 files changed, 194 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/settings/about/AboutLibrariesActivity.kt create mode 100644 app/src/main/res/layout/about_libraries_activity.xml create mode 100644 app/src/test/java/org/mozilla/fenix/settings/about/AboutLibrariesActivityTest.kt diff --git a/app/build.gradle b/app/build.gradle index 2035810be8..0fc4e940c6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -330,7 +330,6 @@ dependencies { implementation Deps.androidx_coordinatorlayout implementation Deps.sentry - implementation Deps.osslicenses_library implementation Deps.leanplum_core implementation Deps.leanplum_fcm diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8258893266..554e111268 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -228,13 +228,8 @@ - - - + diff --git a/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt index ece022c027..3fd152943d 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt @@ -13,7 +13,6 @@ import android.view.ViewGroup import androidx.core.content.pm.PackageInfoCompat import androidx.fragment.app.Fragment import androidx.recyclerview.widget.DividerItemDecoration -import com.google.android.gms.oss.licenses.OssLicensesMenuActivity import kotlinx.android.synthetic.main.fragment_about.* import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.BuildConfig @@ -168,13 +167,8 @@ class AboutFragment : Fragment(), AboutPageListener { } private fun openLibrariesPage() { - startActivity(Intent(context, OssLicensesMenuActivity::class.java)) - OssLicensesMenuActivity.setActivityTitle( - getString( - R.string.open_source_licenses_title, - appName - ) - ) + val intent = Intent(requireContext(), AboutLibrariesActivity::class.java) + startActivity(intent) } override fun onAboutItemClicked(item: AboutItem) { diff --git a/app/src/main/java/org/mozilla/fenix/settings/about/AboutLibrariesActivity.kt b/app/src/main/java/org/mozilla/fenix/settings/about/AboutLibrariesActivity.kt new file mode 100644 index 0000000000..bf69fb2f3a --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/settings/about/AboutLibrariesActivity.kt @@ -0,0 +1,120 @@ +/* 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.settings.about + +import android.graphics.Typeface +import android.os.Bundle +import android.text.util.Linkify +import android.widget.ArrayAdapter +import android.widget.ListView +import android.widget.TextView +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import org.mozilla.fenix.R +import java.nio.charset.Charset +import java.util.Locale + +/** + * Displays the licenses of all the libraries used by Fenix. + * + * This is a re-implementation of play-services-oss-licenses library. + * We can't use the official implementation in the OSS flavor of Fenix + * because it is proprietary and closed-source. + * + * There are popular FLOSS alternatives to Google's plugin and library + * such as AboutLibraries (https://github.com/mikepenz/AboutLibraries) + * but we considered the risk of introducing such third-party dependency + * to Fenix too high. Therefore, we use Google's gradle plugin to + * extract the dependencies and their licenses, and this activity + * to show the extracted licenses to the end-user. + */ +class AboutLibrariesActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val appName = getString(R.string.app_name) + title = getString(R.string.open_source_licenses_title, appName) + setContentView(R.layout.about_libraries_activity) + + setSupportActionBar(findViewById(R.id.toolbar)) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.setDisplayShowHomeEnabled(true) + + setupLibrariesListView() + } + + override fun onSupportNavigateUp(): Boolean { + onBackPressed() + return true + } + + private fun setupLibrariesListView() { + val libraries = parseLibraries() + val listView = findViewById(R.id.about_libraries_listview) + listView.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, libraries) + listView.setOnItemClickListener { _, _, position, _ -> + showLicenseDialog(libraries[position]) + } + } + + private fun parseLibraries(): List { + /* + The gradle plugin "oss-licenses-plugin" creates two "raw" resources: + + - third_party_licenses which is the binary concatenation of all the licenses text for + all the libraries. License texts can either be an URL to a license file or just the + raw text of the license. + + - third_party_licenses_metadata which contains one dependency per line formatted in + the following way: "[start_offset]:[length] [name]" + + [start_offset] : first byte in third_party_licenses that contains the license + text for this library. + [length] : length of the license text for this library in + third_party_licenses. + [name] : either the name of the library, or its artifact name. + + See https://github.com/google/play-services-plugins/tree/master/oss-licenses-plugin + */ + val licensesData = resources + .openRawResource(R.raw.third_party_licenses) + .readBytes() + val licensesMetadataReader = resources + .openRawResource(R.raw.third_party_license_metadata) + .bufferedReader() + + return licensesMetadataReader.use { reader -> reader.readLines() }.map { line -> + val (section, name) = line.split(" ", limit = 2) + val (startOffset, length) = section.split(":", limit = 2).map(String::toInt) + val licenseData = licensesData.sliceArray(startOffset until startOffset + length) + val licenseText = licenseData.toString(Charset.forName("UTF-8")) + LibraryItem(name, licenseText) + }.sortedBy { item -> item.name.toLowerCase(Locale.ROOT) } + } + + private fun showLicenseDialog(libraryItem: LibraryItem) { + val dialog = AlertDialog.Builder(this) + .setTitle(libraryItem.name) + .setMessage(libraryItem.license) + .create() + dialog.show() + + val textView = dialog.findViewById(android.R.id.message)!! + Linkify.addLinks(textView, Linkify.ALL) + textView.linksClickable = true + textView.textSize = LICENSE_TEXT_SIZE + textView.typeface = Typeface.MONOSPACE + } + + companion object { + private const val LICENSE_TEXT_SIZE = 10F + } +} + +private class LibraryItem(val name: String, val license: String) { + override fun toString(): String { + return name + } +} diff --git a/app/src/main/res/layout/about_libraries_activity.xml b/app/src/main/res/layout/about_libraries_activity.xml new file mode 100644 index 0000000000..bf23bb4377 --- /dev/null +++ b/app/src/main/res/layout/about_libraries_activity.xml @@ -0,0 +1,25 @@ + + + + + + + diff --git a/app/src/test/java/org/mozilla/fenix/settings/about/AboutLibrariesActivityTest.kt b/app/src/test/java/org/mozilla/fenix/settings/about/AboutLibrariesActivityTest.kt new file mode 100644 index 0000000000..140dc44aeb --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/settings/about/AboutLibrariesActivityTest.kt @@ -0,0 +1,45 @@ +/* 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.settings.about + +import android.widget.ListView +import android.widget.TextView +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner +import org.robolectric.Robolectric +import org.robolectric.Shadows.shadowOf +import org.robolectric.shadows.ShadowAlertDialog + +@RunWith(FenixRobolectricTestRunner::class) +class AboutLibrariesActivityTest { + @Test + fun `activity should display licenses`() { + val activity = Robolectric.buildActivity(AboutLibrariesActivity::class.java).create().get() + val listView = activity.findViewById(R.id.about_libraries_listview) + + assertTrue(0 < listView.count) + } + + @Test + fun `item click should open license dialog`() { + val activity = Robolectric.buildActivity(AboutLibrariesActivity::class.java).create().get() + + val listView = activity.findViewById(R.id.about_libraries_listview) + val listViewShadow = shadowOf(listView) + listViewShadow.clickFirstItemContainingText("org.mozilla.geckoview:geckoview") + + val alertDialogShadow = ShadowAlertDialog.getLatestDialog() + assertTrue(alertDialogShadow.isShowing) + + val alertDialogText = alertDialogShadow + .findViewById(android.R.id.message) + .text + .toString() + assertTrue(alertDialogText.contains("MPL")) + } +} diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 876e537dd3..40933b3c02 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -10,7 +10,6 @@ object Versions { const val leakcanary = "2.4" const val leanplum = "5.4.0" const val osslicenses_plugin = "0.9.5" - const val osslicenses_library = "17.0.0" const val detekt = "1.9.1" const val androidx_appcompat = "1.2.0-rc01" @@ -59,7 +58,6 @@ object Deps { const val allopen = "org.jetbrains.kotlin:kotlin-allopen:${Versions.kotlin}" const val osslicenses_plugin = "com.google.android.gms:oss-licenses-plugin:${Versions.osslicenses_plugin}" - const val osslicenses_library = "com.google.android.gms:play-services-oss-licenses:${Versions.osslicenses_library}" const val mozilla_concept_engine = "org.mozilla.components:concept-engine:${Versions.mozilla_android_components}" const val mozilla_concept_menu = "org.mozilla.components:concept-menu:${Versions.mozilla_android_components}"