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