v125
parent
d46b64ddc0
commit
331c06960a
|
@ -83,9 +83,11 @@ projects:
|
||||||
- support-rusthttp
|
- support-rusthttp
|
||||||
- support-rustlog
|
- support-rustlog
|
||||||
- support-test
|
- support-test
|
||||||
|
- support-test-fakes
|
||||||
- support-test-libstate
|
- support-test-libstate
|
||||||
- support-utils
|
- support-utils
|
||||||
- support-webextensions
|
- support-webextensions
|
||||||
|
- tooling-lint
|
||||||
- ui-autocomplete
|
- ui-autocomplete
|
||||||
- ui-colors
|
- ui-colors
|
||||||
- ui-icons
|
- ui-icons
|
||||||
|
|
|
@ -54,6 +54,12 @@ jobs:
|
||||||
gradle-executable: /usr/bin/time
|
gradle-executable: /usr/bin/time
|
||||||
arguments: -v ./gradlew app:assemblefenixForkRelease -x lintVitalFenixForkRelease -PversionName=${{ env.VERSION_NAME }} --stacktrace
|
arguments: -v ./gradlew app:assemblefenixForkRelease -x lintVitalFenixForkRelease -PversionName=${{ env.VERSION_NAME }} --stacktrace
|
||||||
|
|
||||||
|
- name: Setup build tool version variable
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
BUILD_TOOL_VERSION=$(ls /usr/local/lib/android/sdk/build-tools/ | tail -n 1)
|
||||||
|
echo "BUILD_TOOL_VERSION=$BUILD_TOOL_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Create signed APKs
|
- name: Create signed APKs
|
||||||
uses: abhijitvalluri/sign-apks@v0.8
|
uses: abhijitvalluri/sign-apks@v0.8
|
||||||
with:
|
with:
|
||||||
|
@ -62,6 +68,8 @@ jobs:
|
||||||
alias: ${{ secrets.DEBUG_ALIAS }}
|
alias: ${{ secrets.DEBUG_ALIAS }}
|
||||||
keyStorePassword: ${{ secrets.DEBUG_KEY_STORE_PASSWORD }}
|
keyStorePassword: ${{ secrets.DEBUG_KEY_STORE_PASSWORD }}
|
||||||
keyPassword: ${{ secrets.DEBUG_KEY_PASSWORD }}
|
keyPassword: ${{ secrets.DEBUG_KEY_PASSWORD }}
|
||||||
|
env:
|
||||||
|
BUILD_TOOLS_VERSION: ${{ env.BUILD_TOOL_VERSION }}
|
||||||
|
|
||||||
- name: Upload arm64 apk
|
- name: Upload arm64 apk
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
|
|
0
.github/workflows/disabled_workflows/build-contributor-pr.yml
vendored
Normal file → Executable file
0
.github/workflows/disabled_workflows/build-contributor-pr.yml
vendored
Normal file → Executable file
0
.github/workflows/disabled_workflows/fenix-sync-strings.yml
vendored
Normal file → Executable file
0
.github/workflows/disabled_workflows/fenix-sync-strings.yml
vendored
Normal file → Executable file
0
.github/workflows/disabled_workflows/fenix-update-nimbus-experiments.yml
vendored
Normal file → Executable file
0
.github/workflows/disabled_workflows/fenix-update-nimbus-experiments.yml
vendored
Normal file → Executable file
0
.github/workflows/disabled_workflows/glean-probe-scraper.yml
vendored
Normal file → Executable file
0
.github/workflows/disabled_workflows/glean-probe-scraper.yml
vendored
Normal file → Executable file
0
.github/workflows/disabled_workflows/reopen-for-qa-needed.yml
vendored
Normal file → Executable file
0
.github/workflows/disabled_workflows/reopen-for-qa-needed.yml
vendored
Normal file → Executable file
|
@ -52,6 +52,12 @@ jobs:
|
||||||
gradle-executable: /usr/bin/time
|
gradle-executable: /usr/bin/time
|
||||||
arguments: -v ./gradlew app:assemblefenixForkRelease -x lintVitalFenixForkRelease -PversionName=${{ env.VERSION_NAME }} --stacktrace
|
arguments: -v ./gradlew app:assemblefenixForkRelease -x lintVitalFenixForkRelease -PversionName=${{ env.VERSION_NAME }} --stacktrace
|
||||||
|
|
||||||
|
- name: Setup build tool version variable
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
BUILD_TOOL_VERSION=$(ls /usr/local/lib/android/sdk/build-tools/ | tail -n 1)
|
||||||
|
echo "BUILD_TOOL_VERSION=$BUILD_TOOL_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Create signed APKs
|
- name: Create signed APKs
|
||||||
if: "contains(toJSON(github.event.ref_type), 'tag') && contains(toJSON(github.event.ref), 'iceraven')"
|
if: "contains(toJSON(github.event.ref_type), 'tag') && contains(toJSON(github.event.ref), 'iceraven')"
|
||||||
uses: abhijitvalluri/sign-apks@v0.8
|
uses: abhijitvalluri/sign-apks@v0.8
|
||||||
|
@ -61,6 +67,8 @@ jobs:
|
||||||
alias: ${{ secrets.DEBUG_ALIAS }}
|
alias: ${{ secrets.DEBUG_ALIAS }}
|
||||||
keyStorePassword: ${{ secrets.DEBUG_KEY_STORE_PASSWORD }}
|
keyStorePassword: ${{ secrets.DEBUG_KEY_STORE_PASSWORD }}
|
||||||
keyPassword: ${{ secrets.DEBUG_KEY_PASSWORD }}
|
keyPassword: ${{ secrets.DEBUG_KEY_PASSWORD }}
|
||||||
|
env:
|
||||||
|
BUILD_TOOLS_VERSION: ${{ env.BUILD_TOOL_VERSION }}
|
||||||
|
|
||||||
- name: Create changelog
|
- name: Create changelog
|
||||||
if: "contains(toJSON(github.event.ref_type), 'tag') && contains(toJSON(github.event.ref), 'iceraven')"
|
if: "contains(toJSON(github.event.ref_type), 'tag') && contains(toJSON(github.event.ref), 'iceraven')"
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
From 50f614cd20872910fe17df6644bc7f0d0f31c1eb Mon Sep 17 00:00:00 2001
|
|
||||||
From: harvey186 <harvey186@hotmail.com>
|
|
||||||
Date: Sun, 14 Apr 2024 11:34:30 +0200
|
|
||||||
Subject: [PATCH] LeOSearch
|
|
||||||
|
|
||||||
---
|
|
||||||
.../org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt
|
|
||||||
index dd74241ac..a44cb97ab 100644
|
|
||||||
--- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt
|
|
||||||
+++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt
|
|
||||||
@@ -101,7 +101,7 @@ class SettingsSubMenuSearchRobot {
|
|
||||||
}
|
|
||||||
|
|
||||||
fun verifyDefaultSearchEngineList() {
|
|
||||||
- defaultSearchEngineOption("Google")
|
|
||||||
+ defaultSearchEngineOption("LeOSearch")
|
|
||||||
.check(matches(hasSibling(withId(R.id.engine_icon))))
|
|
||||||
.check(matches(isDisplayed()))
|
|
||||||
defaultSearchEngineOption("LeOSearch")
|
|
||||||
--
|
|
||||||
2.34.1
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
From de5949e762ba7806b8489b0c937d259273228ff8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: harvey186 <harvey186@hotmail.com>
|
|
||||||
Date: Wed, 21 Feb 2024 13:11:06 +0100
|
|
||||||
Subject: [PATCH] build-gradle
|
|
||||||
|
|
||||||
---
|
|
||||||
app/build.gradle | 6 +-
|
|
||||||
patches/0001-components-search.patch | 1048 ++++++++++++++++++++++++++
|
|
||||||
patches/0010-search.patch | 29 +
|
|
||||||
1 files changed, 1080 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/app/build.gradle b/app/build.gradle
|
|
||||||
index 567ac156c..aea2716eb 100644
|
|
||||||
--- a/app/build.gradle
|
|
||||||
+++ b/app/build.gradle
|
|
||||||
@@ -335,8 +335,8 @@ android.applicationVariants.configureEach { variant ->
|
|
||||||
// same version code. Therefore we need to have different version codes for our ARM and x86
|
|
||||||
// builds.
|
|
||||||
|
|
||||||
- def versionName = variant.buildType.name == 'nightly' ? Config.nightlyVersionName() : Config.releaseVersionName(project)
|
|
||||||
- println("versionName override: $versionName")
|
|
||||||
+ //def versionName = variant.buildType.name == 'nightly' ? Config.nightlyVersionName() : Config.releaseVersionName(project)
|
|
||||||
+ //println("versionName override: $versionName")
|
|
||||||
|
|
||||||
variant.outputs.each { output ->
|
|
||||||
def isMozillaOnline = project.hasProperty("mozillaOnline") || gradle.hasProperty("localProperties.mozillaOnline")
|
|
||||||
@@ -934,4 +934,4 @@ def getSupportedLocales() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable expiration by major version.
|
|
||||||
-ext.gleanExpireByVersion = Config.majorVersion()
|
|
||||||
+ext.gleanExpireByVersion = 26
|
|
||||||
--
|
|
||||||
2.34.1
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
From 1c53b4145a4b7a232b5085aa1f7bff33526393fc Mon Sep 17 00:00:00 2001
|
|
||||||
From: harvey186 <harvey186@hotmail.com>
|
|
||||||
Date: Sun, 14 Apr 2024 12:52:24 +0200
|
|
||||||
Subject: [PATCH] bild_gradle
|
|
||||||
|
|
||||||
---
|
|
||||||
0001-strings.patch | 20441 +++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
app/build.gradle | 8 +-
|
|
||||||
2 files changed, 20445 insertions(+), 4 deletions(-)
|
|
||||||
create mode 100644 0001-strings.patch
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/app/build.gradle b/app/build.gradle
|
|
||||||
index 530e1c88c..17c4822b6 100644
|
|
||||||
--- a/app/build.gradle
|
|
||||||
+++ b/app/build.gradle
|
|
||||||
@@ -31,7 +31,7 @@ android {
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
- applicationId "io.github.forkmaintainers"
|
|
||||||
+ applicationId "com.leos"
|
|
||||||
minSdkVersion config.minSdkVersion
|
|
||||||
compileSdk config.compileSdkVersion
|
|
||||||
targetSdkVersion config.targetSdkVersion
|
|
||||||
@@ -180,11 +180,11 @@ android {
|
|
||||||
}
|
|
||||||
forkRelease releaseTemplate >> {
|
|
||||||
buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
|
|
||||||
- applicationIdSuffix ".iceraven"
|
|
||||||
- def deepLinkSchemeValue = "iceraven"
|
|
||||||
+ applicationIdSuffix ".leosium"
|
|
||||||
+ def deepLinkSchemeValue = "leosium"
|
|
||||||
buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\""
|
|
||||||
manifestPlaceholders.putAll([
|
|
||||||
- "sharedUserId": "io.github.forkmaintainers.iceraven.sharedID",
|
|
||||||
+ "sharedUserId": "io.github.forkmaintainers.leosium.sharedID",
|
|
||||||
"deepLinkScheme": deepLinkSchemeValue,
|
|
||||||
])
|
|
||||||
// Use custom default allowed addon list
|
|
||||||
--
|
|
||||||
2.34.1
|
|
||||||
|
|
18460
0004-icons.patch
18460
0004-icons.patch
File diff suppressed because it is too large
Load Diff
3330
0005-icon.patch
3330
0005-icon.patch
File diff suppressed because it is too large
Load Diff
|
@ -1,29 +0,0 @@
|
||||||
From 014067d5ccbbe58339ec673f353d400c33c055ff Mon Sep 17 00:00:00 2001
|
|
||||||
From: harvey186 <harvey186@hotmail.com>
|
|
||||||
Date: Wed, 21 Feb 2024 13:07:19 +0100
|
|
||||||
Subject: [PATCH] components-search
|
|
||||||
|
|
||||||
---
|
|
||||||
android-components | 2 +-
|
|
||||||
.../mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt | 5 +----
|
|
||||||
1 files changed, 2 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt
|
|
||||||
index dd74241ac..310e0dbab 100644
|
|
||||||
--- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt
|
|
||||||
+++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt
|
|
||||||
@@ -101,10 +101,7 @@ class SettingsSubMenuSearchRobot {
|
|
||||||
}
|
|
||||||
|
|
||||||
fun verifyDefaultSearchEngineList() {
|
|
||||||
- defaultSearchEngineOption("Google")
|
|
||||||
- .check(matches(hasSibling(withId(R.id.engine_icon))))
|
|
||||||
- .check(matches(isDisplayed()))
|
|
||||||
- defaultSearchEngineOption("LeOSearch")
|
|
||||||
+ defaultSearchEngineOption("LeOSearch")
|
|
||||||
.check(matches(hasSibling(withId(R.id.engine_icon))))
|
|
||||||
.check(matches(isDisplayed()))
|
|
||||||
defaultSearchEngineOption("DuckDuckGo")
|
|
||||||
--
|
|
||||||
2.34.1
|
|
||||||
|
|
3398
0011-Search.patch
3398
0011-Search.patch
File diff suppressed because it is too large
Load Diff
|
@ -1,40 +0,0 @@
|
||||||
From 2f480d829bff77f40594a12e84b1af483d65c9f5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: harvey186 <harvey186@hotmail.com>
|
|
||||||
Date: Wed, 21 Feb 2024 13:17:21 +0100
|
|
||||||
Subject: [PATCH] AddOn_HomeFragment
|
|
||||||
|
|
||||||
---
|
|
||||||
.../java/org/mozilla/fenix/addons/AddonsManagementFragment.kt | 4 ----
|
|
||||||
app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt | 1 -
|
|
||||||
2 files changed, 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/app/src/main/java/org/mozilla/fenix/addons/AddonsManagementFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/AddonsManagementFragment.kt
|
|
||||||
index cee42dabc..9ec00fb5b 100644
|
|
||||||
--- a/app/src/main/java/org/mozilla/fenix/addons/AddonsManagementFragment.kt
|
|
||||||
+++ b/app/src/main/java/org/mozilla/fenix/addons/AddonsManagementFragment.kt
|
|
||||||
@@ -142,10 +142,6 @@ class AddonsManagementFragment : Fragment(R.layout.fragment_add_ons_management)
|
|
||||||
showAlertDialog()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
- R.id.addons_sideload -> {
|
|
||||||
- installFromFile()
|
|
||||||
- true
|
|
||||||
- }
|
|
||||||
R.id.search -> {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
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 6ed9c9620..056677d96 100644
|
|
||||||
--- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
|
|
||||||
+++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
|
|
||||||
@@ -480,7 +480,6 @@ class HomeFragment : Fragment() {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
- showTopRecentSites = settings.showTopRecentSites,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.34.1
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
18005
0017-Browser_Text.patch
18005
0017-Browser_Text.patch
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,8 @@
|
||||||
# LeOSium Browser! [![CI](https://github.com/fork-maintainers/iceraven-browser/actions/workflows/ci.yml/badge.svg)](https://github.com/fork-maintainers/iceraven-browser/actions/workflows/ci.yml) ![Release](https://img.shields.io/github/v/release/fork-maintainers/iceraven-browser)
|
# Iceraven Browser! [![CI](https://github.com/fork-maintainers/iceraven-browser/actions/workflows/ci.yml/badge.svg)](https://github.com/fork-maintainers/iceraven-browser/actions/workflows/ci.yml) ![Release](https://img.shields.io/github/v/release/fork-maintainers/iceraven-browser)
|
||||||
|
|
||||||
Definitely not brought to you by Mozilla!
|
Definitely not brought to you by Mozilla!
|
||||||
|
|
||||||
LeOSium Browser is a web browser for Android, based on [Mozilla's Fenix version of Firefox](https://github.com/mozilla-mobile/fenix/), [GeckoView](https://mozilla.github.io/geckoview/) and [Mozilla Android Components](https://mozac.org/).
|
Iceraven Browser is a web browser for Android, based on [Mozilla's Fenix version of Firefox](https://github.com/mozilla-mobile/fenix/), [GeckoView](https://mozilla.github.io/geckoview/) and [Mozilla Android Components](https://mozac.org/).
|
||||||
|
|
||||||
Our goal is to be a close fork of the new Firefox for Android that seeks to provide users with more options, more opportunities to customize (including a broad extension library), and more information about the pages they visit and how their browsers are interacting with those pages.
|
Our goal is to be a close fork of the new Firefox for Android that seeks to provide users with more options, more opportunities to customize (including a broad extension library), and more information about the pages they visit and how their browsers are interacting with those pages.
|
||||||
|
|
||||||
|
@ -11,15 +11,15 @@ Notable features include:
|
||||||
* The ability to *attempt* to install a much longer list of add-ons than Mozilla's Fenix version of Firefox accepts. Currently the browser queries [this AMO collection](https://addons.mozilla.org/en-US/firefox/collections/16201230/What-I-want-on-Fenix/) **Most of them will not work**, because they depend on code that Mozilla is still working on writing in `android-components`, but you may attempt to install them. If you don't see an add-on you want, you can [request it](https://github.com/fork-maintainers/iceraven-browser/issues/new).
|
* The ability to *attempt* to install a much longer list of add-ons than Mozilla's Fenix version of Firefox accepts. Currently the browser queries [this AMO collection](https://addons.mozilla.org/en-US/firefox/collections/16201230/What-I-want-on-Fenix/) **Most of them will not work**, because they depend on code that Mozilla is still working on writing in `android-components`, but you may attempt to install them. If you don't see an add-on you want, you can [request it](https://github.com/fork-maintainers/iceraven-browser/issues/new).
|
||||||
* Option to suspend tabs to avoid being killed for memory (https://bugzilla.mozilla.org/show_bug.cgi?id=1807364)
|
* Option to suspend tabs to avoid being killed for memory (https://bugzilla.mozilla.org/show_bug.cgi?id=1807364)
|
||||||
* Option not to display recently visited websites at HomePage
|
* Option not to display recently visited websites at HomePage
|
||||||
* **No warranties or guarantees of security or updates or even stability**! Note that LeOSium Browser includes some unstable code written by Mozilla, with our own added modifications on top, all shipped with the stable version of GeckoView engine. Hence, the browser may contain bugs introduced upstream. Binaries are currently built automatically by our Github release automation. These binaries are signed with a debug key. When we finally publish this somewhere official like F-droid, we will sign the apks with a proper key suitable for public release. Due to the current way we create the releases and sign them, you may not want to rely on such "alpha" quality software as your primary web browser, as it will have bugs. So, use this browser only if you are comfortable with these limitations/potential risks.
|
* **No warranties or guarantees of security or updates or even stability**! Note that Iceraven Browser includes some unstable code written by Mozilla, with our own added modifications on top, all shipped with the stable version of GeckoView engine. Hence, the browser may contain bugs introduced upstream. Binaries are currently built automatically by our Github release automation. These binaries are signed with a debug key. When we finally publish this somewhere official like F-droid, we will sign the apks with a proper key suitable for public release. Due to the current way we create the releases and sign them, you may not want to rely on such "alpha" quality software as your primary web browser, as it will have bugs. So, use this browser only if you are comfortable with these limitations/potential risks.
|
||||||
|
|
||||||
**Note/Disclaimer:** LeOSium Browser could not exist without the hardworking folks at the Mozilla Corporation who work on the Mozilla Android Components and Firefox projects, but it is not an official Mozilla product, and is not provided, endorsed, vetted, approved, or secured by Mozilla.
|
**Note/Disclaimer:** Iceraven Browser could not exist without the hardworking folks at the Mozilla Corporation who work on the Mozilla Android Components and Firefox projects, but it is not an official Mozilla product, and is not provided, endorsed, vetted, approved, or secured by Mozilla.
|
||||||
|
|
||||||
In addition, we intend to try to cut down on telemetry and proprietary code to as great of an extent as possible as long as doing so does not compromise the user experience or make the fork too hard to maintain. Right now, we believe that no telemetry should be being sent to Mozilla anymore, but we cannot guarantee this; data may still be sent. Because of the way we have implemented this, the app may still appear to contain trackers when analyzed by tools that look for the presence of known tracking libraries. These detected trackers should actually be non-functional substitutes, many of which are sourced [from here](https://gitlab.com/relan/fennecbuild/-/blob/master/fenix-liberate.patch). **If you catch the app actually sending data to Mozilla, Adjust, Leanplum, Firebase, or any other such service, please open an issue!** Presumably any data that reaches Mozilla is governed by Mozilla's privacy policy, but as LeOSium Browser is, again **not a Mozilla product**, we can make no promises.
|
In addition, we intend to try to cut down on telemetry and proprietary code to as great of an extent as possible as long as doing so does not compromise the user experience or make the fork too hard to maintain. Right now, we believe that no telemetry should be being sent to Mozilla anymore, but we cannot guarantee this; data may still be sent. Because of the way we have implemented this, the app may still appear to contain trackers when analyzed by tools that look for the presence of known tracking libraries. These detected trackers should actually be non-functional substitutes, many of which are sourced [from here](https://gitlab.com/relan/fennecbuild/-/blob/master/fenix-liberate.patch). **If you catch the app actually sending data to Mozilla, Adjust, Leanplum, Firebase, or any other such service, please open an issue!** Presumably any data that reaches Mozilla is governed by Mozilla's privacy policy, but as Iceraven Browser is, again **not a Mozilla product**, we can make no promises.
|
||||||
|
|
||||||
LeOSium Browser combines the power of Fenix (of which we are a fork) and the spirit of Fennec, with a respectful nod toward the grand tradition of Netscape Navigator, from which all Gecko-based projects came, including the earliest of our predecessors, the old Mozilla Phoenix and Mozilla Firefox desktop browsers.
|
Iceraven Browser combines the power of Fenix (of which we are a fork) and the spirit of Fennec, with a respectful nod toward the grand tradition of Netscape Navigator, from which all Gecko-based projects came, including the earliest of our predecessors, the old Mozilla Phoenix and Mozilla Firefox desktop browsers.
|
||||||
|
|
||||||
That said, LeOSium Browser is an independent all-volunteer project, and has no affiliation with Netscape, Netscape Navigator, Mozilla, Mozilla Firefox, Mozila Phoenix, Debian, Debian Iceweasel, Parabola GNU/Linux-libre Iceweasel, America Online, or Verizon, among others. :) Basically, if you don't like the browser, it's not their fault. :)
|
That said, Iceraven Browser is an independent all-volunteer project, and has no affiliation with Netscape, Netscape Navigator, Mozilla, Mozilla Firefox, Mozila Phoenix, Debian, Debian Iceweasel, Parabola GNU/Linux-libre Iceweasel, America Online, or Verizon, among others. :) Basically, if you don't like the browser, it's not their fault. :)
|
||||||
|
|
||||||
## 📥 Installation
|
## 📥 Installation
|
||||||
|
|
||||||
|
@ -27,9 +27,11 @@ Right now, releases are published as `.apk` files, through Github. You should do
|
||||||
|
|
||||||
1. **Determine what version you need**. If you have a newer, 64-bit device, or a device with more than 4 GB of memory, you probably want the `arm64-v8a` version. **Any ordinary phone or tablet should be able to use the `armeabi-v7a` version**, but it will be limited to using no more than 4 GB of memory. You almost certainly don't want the `x86` or `x86_64` versions; they are in case you are running Android on a PC.
|
1. **Determine what version you need**. If you have a newer, 64-bit device, or a device with more than 4 GB of memory, you probably want the `arm64-v8a` version. **Any ordinary phone or tablet should be able to use the `armeabi-v7a` version**, but it will be limited to using no more than 4 GB of memory. You almost certainly don't want the `x86` or `x86_64` versions; they are in case you are running Android on a PC.
|
||||||
|
|
||||||
3. **Install the APK**. You will need to enable installation of apps from "unknown" (to Google) sources, and installatiuon of apps *by* whatever app you used to open the downloaded APK (i.e. your browser or file manager). Android will try to dissuade you from doing this, and suggest that it is dangerous. LeOSium is a browser for people who enjoy danger.
|
2. [**Download the APK for the latest release from the Releases page**](https://github.com/fork-maintainers/iceraven-browser/releases). Make sure to pick the version you chose in step 1.
|
||||||
|
|
||||||
4. **Enjoy LeOSium**. Make sure to install the add-ons that are essential for you in the main menu under "Add-Ons". You may want to set LeOSium as your device's default browser app. If you do this, it will be able to provide so-called "Chrome" [custom tabs](https://developers.google.com/web/android/custom-tabs) for other applications, allowing you to use your add-ons there.
|
3. **Install the APK**. You will need to enable installation of apps from "unknown" (to Google) sources, and installatiuon of apps *by* whatever app you used to open the downloaded APK (i.e. your browser or file manager). Android will try to dissuade you from doing this, and suggest that it is dangerous. Iceraven is a browser for people who enjoy danger.
|
||||||
|
|
||||||
|
4. **Enjoy Iceraven**. Make sure to install the add-ons that are essential for you in the main menu under "Add-Ons". You may want to set Iceraven as your device's default browser app. If you do this, it will be able to provide so-called "Chrome" [custom tabs](https://developers.google.com/web/android/custom-tabs) for other applications, allowing you to use your add-ons there.
|
||||||
|
|
||||||
## 🔨 Building
|
## 🔨 Building
|
||||||
|
|
||||||
|
@ -76,7 +78,7 @@ cd iceraven-browser
|
||||||
echo "autosignReleaseWithDebugKey=" >> local.properties
|
echo "autosignReleaseWithDebugKey=" >> local.properties
|
||||||
```
|
```
|
||||||
|
|
||||||
6. Build the project. To build the LeOSium-branded release APKs, you can do:
|
6. Build the project. To build the Iceraven-branded release APKs, you can do:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./gradlew app:assemblefenixForkRelease -PversionName="$(git describe --tags HEAD)"
|
./gradlew app:assemblefenixForkRelease -PversionName="$(git describe --tags HEAD)"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 96c21391b62d8b02ddddb0b86fa1e4702efa24f9
|
Subproject commit f03a5f2688acc3faffe488c75cea6658d079fea3
|
|
@ -96,7 +96,7 @@ android {
|
||||||
|
|
||||||
// Changing the build config can cause files that depend on BuildConfig.java to recompile
|
// Changing the build config can cause files that depend on BuildConfig.java to recompile
|
||||||
// so we only set the git hash in release builds to avoid possible recompilation in debug builds.
|
// so we only set the git hash in release builds to avoid possible recompilation in debug builds.
|
||||||
buildConfigField "String", "GIT_HASH", "\"${Config.getGitHash()}\""
|
// buildConfigField "String", "GIT_HASH", "\"${Config.getGitHash()}\""
|
||||||
|
|
||||||
if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) {
|
if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) {
|
||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
|
@ -252,11 +252,6 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_17
|
|
||||||
targetCompatibility JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
bundle {
|
bundle {
|
||||||
// Profiler issues require us to temporarily package native code compressed to
|
// Profiler issues require us to temporarily package native code compressed to
|
||||||
// match the previous APK packaging.
|
// match the previous APK packaging.
|
||||||
|
@ -335,8 +330,8 @@ android.applicationVariants.configureEach { variant ->
|
||||||
// same version code. Therefore we need to have different version codes for our ARM and x86
|
// same version code. Therefore we need to have different version codes for our ARM and x86
|
||||||
// builds.
|
// builds.
|
||||||
|
|
||||||
//def versionName = variant.buildType.name == 'nightly' ? Config.nightlyVersionName() : Config.releaseVersionName(project)
|
// def versionName = variant.buildType.name == 'nightly' ? Config.nightlyVersionName() : Config.releaseVersionName(project)
|
||||||
//println("versionName override: $versionName")
|
// println("versionName override: $versionName")
|
||||||
|
|
||||||
variant.outputs.each { output ->
|
variant.outputs.each { output ->
|
||||||
def isMozillaOnline = project.hasProperty("mozillaOnline") || gradle.hasProperty("localProperties.mozillaOnline")
|
def isMozillaOnline = project.hasProperty("mozillaOnline") || gradle.hasProperty("localProperties.mozillaOnline")
|
||||||
|
@ -559,6 +554,9 @@ tasks.withType(KotlinCompile).configureEach {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation platform(ComponentsDependencies.androidx_compose_bom)
|
||||||
|
androidTestImplementation platform(ComponentsDependencies.androidx_compose_bom)
|
||||||
|
|
||||||
implementation project(':browser-engine-gecko')
|
implementation project(':browser-engine-gecko')
|
||||||
|
|
||||||
implementation ComponentsDependencies.kotlin_coroutines
|
implementation ComponentsDependencies.kotlin_coroutines
|
||||||
|
@ -658,6 +656,7 @@ dependencies {
|
||||||
implementation project(':lib-crash-sentry')
|
implementation project(':lib-crash-sentry')
|
||||||
implementation project(':lib-state')
|
implementation project(':lib-state')
|
||||||
implementation project(':lib-dataprotect')
|
implementation project(':lib-dataprotect')
|
||||||
|
testImplementation project(':support-test-fakes')
|
||||||
|
|
||||||
debugImplementation ComponentsDependencies.leakcanary
|
debugImplementation ComponentsDependencies.leakcanary
|
||||||
forkDebugImplementation ComponentsDependencies.leakcanary
|
forkDebugImplementation ComponentsDependencies.leakcanary
|
||||||
|
@ -753,6 +752,7 @@ dependencies {
|
||||||
testImplementation "org.mozilla.telemetry:glean-native-forUnitTests:${project.ext.glean_version}"
|
testImplementation "org.mozilla.telemetry:glean-native-forUnitTests:${project.ext.glean_version}"
|
||||||
|
|
||||||
lintChecks project(":mozilla-lint-rules")
|
lintChecks project(":mozilla-lint-rules")
|
||||||
|
lintChecks project(':tooling-lint')
|
||||||
}
|
}
|
||||||
|
|
||||||
protobuf {
|
protobuf {
|
||||||
|
|
|
@ -29,9 +29,10 @@ import:
|
||||||
text: default_browser_experiment_card_text
|
text: default_browser_experiment_card_text
|
||||||
surface: homescreen
|
surface: homescreen
|
||||||
action: "MAKE_DEFAULT_BROWSER"
|
action: "MAKE_DEFAULT_BROWSER"
|
||||||
trigger:
|
trigger-if-all:
|
||||||
- I_AM_NOT_DEFAULT_BROWSER
|
|
||||||
- USER_ESTABLISHED_INSTALL
|
- USER_ESTABLISHED_INSTALL
|
||||||
|
exclude-if-any:
|
||||||
|
- I_AM_DEFAULT_BROWSER
|
||||||
style: PERSISTENT
|
style: PERSISTENT
|
||||||
button-label: preferences_set_as_default_browser
|
button-label: preferences_set_as_default_browser
|
||||||
|
|
||||||
|
@ -47,7 +48,8 @@ import:
|
||||||
text: nimbus_notification_default_browser_text
|
text: nimbus_notification_default_browser_text
|
||||||
surface: notification
|
surface: notification
|
||||||
style: NOTIFICATION
|
style: NOTIFICATION
|
||||||
trigger:
|
trigger-if-all:
|
||||||
- I_AM_NOT_DEFAULT_BROWSER
|
|
||||||
- DAY_3_AFTER_INSTALL
|
- DAY_3_AFTER_INSTALL
|
||||||
|
exclude-if-any:
|
||||||
|
- I_AM_DEFAULT_BROWSER
|
||||||
action: MAKE_DEFAULT_BROWSER
|
action: MAKE_DEFAULT_BROWSER
|
||||||
|
|
|
@ -854,6 +854,29 @@ events:
|
||||||
notification_emails:
|
notification_emails:
|
||||||
- android-probes@mozilla.com
|
- android-probes@mozilla.com
|
||||||
expires: never
|
expires: never
|
||||||
|
translations_action:
|
||||||
|
type: event
|
||||||
|
description: |
|
||||||
|
An area inside the translations feature was tapped.
|
||||||
|
The name of the translations area that the user tapped is stored in extras with the
|
||||||
|
key `item`.
|
||||||
|
extra_keys:
|
||||||
|
item:
|
||||||
|
description: |
|
||||||
|
A string containing the name of the item the user tapped. These items
|
||||||
|
include:
|
||||||
|
main_flow_toolbar, main_flow_browser, page_settings, global_settings,
|
||||||
|
global_lang_settings, global_site_settings, downloads
|
||||||
|
type: string
|
||||||
|
bugs:
|
||||||
|
- https://bugzilla.mozilla.org/show_bug.cgi?id=1883968
|
||||||
|
data_reviews:
|
||||||
|
- https://bugzilla.mozilla.org/show_bug.cgi?id=1883968#c6
|
||||||
|
data_sensitivity:
|
||||||
|
- interaction
|
||||||
|
notification_emails:
|
||||||
|
- android-probes@mozilla.com
|
||||||
|
expires: never
|
||||||
|
|
||||||
splash_screen:
|
splash_screen:
|
||||||
first_launch_extended:
|
first_launch_extended:
|
||||||
|
@ -2654,25 +2677,6 @@ metrics:
|
||||||
metadata:
|
metadata:
|
||||||
tags:
|
tags:
|
||||||
- Experiments
|
- Experiments
|
||||||
font_list_json:
|
|
||||||
type: text
|
|
||||||
lifetime: ping
|
|
||||||
description: |
|
|
||||||
A JSON blob representing the installed fonts
|
|
||||||
send_in_pings:
|
|
||||||
- font-list
|
|
||||||
bugs:
|
|
||||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858193
|
|
||||||
data_reviews:
|
|
||||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858193#c2
|
|
||||||
data_sensitivity:
|
|
||||||
# Text metrics are _required_ to be web_activity or highly_sensitive, so even though this
|
|
||||||
# is more like 'technical' (per the Data Review), I'm marking highly sensitive.
|
|
||||||
- highly_sensitive
|
|
||||||
notification_emails:
|
|
||||||
- android-probes@mozilla.com
|
|
||||||
- tom@mozilla.com
|
|
||||||
expires: 124
|
|
||||||
|
|
||||||
customize_home:
|
customize_home:
|
||||||
most_visited_sites:
|
most_visited_sites:
|
||||||
|
|
|
@ -377,6 +377,50 @@ features:
|
||||||
type: Int
|
type: Int
|
||||||
default: 1
|
default: 1
|
||||||
|
|
||||||
|
translations:
|
||||||
|
description: The feature that allows on-device translations of web content.
|
||||||
|
variables:
|
||||||
|
main-flow-toolbar-enabled:
|
||||||
|
description: >
|
||||||
|
Show the primary toolbar entry point into the translations feature. (Translations icon on URL toolbar.)
|
||||||
|
type: Boolean
|
||||||
|
default: false
|
||||||
|
main-flow-browser-menu-enabled:
|
||||||
|
description: >
|
||||||
|
Show the browser menu entry point into the translations feature. ('Translate Page' on browser menu.)
|
||||||
|
type: Boolean
|
||||||
|
default: false
|
||||||
|
page-settings-enabled:
|
||||||
|
description: >
|
||||||
|
Show the page settings entry point within the translations feature. (Gear icon on the translations main flow page.)
|
||||||
|
'main-flow-toolbar-enabled' or 'main-flow-browser-menu-enabled' must also be enabled for users to access this feature.
|
||||||
|
type: Boolean
|
||||||
|
default: false
|
||||||
|
global-settings-enabled:
|
||||||
|
description: >
|
||||||
|
Show the global settings entry point within the translations feature. ('Translation Settings' on the page settings view.)
|
||||||
|
'page-settings-enabled' must also be enabled for users to access this feature.
|
||||||
|
type: Boolean
|
||||||
|
default: false
|
||||||
|
global-lang-settings-enabled:
|
||||||
|
description: >
|
||||||
|
Show the global language options entry point for automatically translating. ('Automatic Translation' on the global settings view.)
|
||||||
|
'global-settings-enabled' must also be enabled for users to access this feature.
|
||||||
|
type: Boolean
|
||||||
|
default: false
|
||||||
|
global-site-settings-enabled:
|
||||||
|
description: >
|
||||||
|
Show the global never translate this site options entry point for site management. ('Never translate these sites' on the global settings view.)
|
||||||
|
'global-settings-enabled' must also be enabled for users to access this feature.
|
||||||
|
type: Boolean
|
||||||
|
default: false
|
||||||
|
downloads-enabled:
|
||||||
|
description: >
|
||||||
|
Show the global language model download options entry point for translations. ('Download languages' on the global settings view.)
|
||||||
|
'global-settings-enabled' must also be enabled for users to access this feature.
|
||||||
|
type: Boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
types:
|
types:
|
||||||
objects: {}
|
objects: {}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ features:
|
||||||
|
|
||||||
add-search-widget:
|
add-search-widget:
|
||||||
card-type: add-search-widget
|
card-type: add-search-widget
|
||||||
enabled: false
|
|
||||||
title: juno_onboarding_add_search_widget_title
|
title: juno_onboarding_add_search_widget_title
|
||||||
body: juno_onboarding_add_search_widget_description
|
body: juno_onboarding_add_search_widget_description
|
||||||
image-res: ic_onboarding_search_widget
|
image-res: ic_onboarding_search_widget
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,5 @@
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<script src="jquery-3.4.1.slim.min.js"></script>
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
function setCookie(newVal){
|
function setCookie(newVal){
|
||||||
|
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
0
app/src/androidTest/java/org/mozilla/fenix/components/FontParserTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/components/FontParserTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/customannotations/SmokeTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/customannotations/SmokeTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/GenericExperimentIntegrationTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/GenericExperimentIntegrationTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/Pipfile
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/Pipfile
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/Pipfile.lock
generated
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/Pipfile.lock
generated
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/SurveyExperimentIntegrationTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/SurveyExperimentIntegrationTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/__init__.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/__init__.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/conftest.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/conftest.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/generate_smoke_tests.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/generate_smoke_tests.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/gradlewbuild.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/gradlewbuild.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/models/__init__.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/models/__init__.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/models/models.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/models/models.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/pytest.ini
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/pytest.ini
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/tests/__init__.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/tests/__init__.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/tests/test_generic_scenarios.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/tests/test_generic_scenarios.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/tests/test_survey_messages.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/tests/test_survey_messages.py
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/variables.yaml
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/experimentintegration/variables.yaml
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/extensions/ExtensionProcessTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/extensions/ExtensionProcessTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/glean/BaselinePingTest.kt
Normal file → Executable file
0
app/src/androidTest/java/org/mozilla/fenix/glean/BaselinePingTest.kt
Normal file → Executable file
326
app/src/androidTest/java/org/mozilla/fenix/helpers/AppAndSystemHelper.kt
Normal file → Executable file
326
app/src/androidTest/java/org/mozilla/fenix/helpers/AppAndSystemHelper.kt
Normal file → Executable file
|
@ -34,15 +34,21 @@ import androidx.test.uiautomator.UiSelector
|
||||||
import androidx.test.uiautomator.Until
|
import androidx.test.uiautomator.Until
|
||||||
import junit.framework.AssertionFailedError
|
import junit.framework.AssertionFailedError
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import mozilla.appservices.places.BookmarkRoot
|
||||||
|
import mozilla.components.browser.storage.sync.PlacesBookmarksStorage
|
||||||
|
import mozilla.components.browser.storage.sync.PlacesHistoryStorage
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.mozilla.fenix.Config
|
import org.mozilla.fenix.Config
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
|
import org.mozilla.fenix.components.PermissionStorage
|
||||||
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
|
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
|
||||||
import org.mozilla.fenix.helpers.Constants.PackageName.PIXEL_LAUNCHER
|
import org.mozilla.fenix.helpers.Constants.PackageName.PIXEL_LAUNCHER
|
||||||
import org.mozilla.fenix.helpers.Constants.PackageName.YOUTUBE_APP
|
import org.mozilla.fenix.helpers.Constants.PackageName.YOUTUBE_APP
|
||||||
import org.mozilla.fenix.helpers.Constants.TAG
|
import org.mozilla.fenix.helpers.Constants.TAG
|
||||||
|
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
|
||||||
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
|
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
|
||||||
|
import org.mozilla.fenix.helpers.TestHelper.appContext
|
||||||
import org.mozilla.fenix.helpers.TestHelper.mDevice
|
import org.mozilla.fenix.helpers.TestHelper.mDevice
|
||||||
import org.mozilla.fenix.helpers.ext.waitNotNull
|
import org.mozilla.fenix.helpers.ext.waitNotNull
|
||||||
import org.mozilla.fenix.helpers.idlingresource.NetworkConnectionIdlingResource
|
import org.mozilla.fenix.helpers.idlingresource.NetworkConnectionIdlingResource
|
||||||
|
@ -53,11 +59,20 @@ import java.util.Locale
|
||||||
|
|
||||||
object AppAndSystemHelper {
|
object AppAndSystemHelper {
|
||||||
|
|
||||||
|
private val bookmarksStorage = PlacesBookmarksStorage(appContext.applicationContext)
|
||||||
|
suspend fun bookmarks() = bookmarksStorage.getTree(BookmarkRoot.Mobile.id)?.children
|
||||||
fun getPermissionAllowID(): String {
|
fun getPermissionAllowID(): String {
|
||||||
|
Log.i(TAG, "getPermissionAllowID: Trying to get the permission button resource ID based on API.")
|
||||||
return when
|
return when
|
||||||
(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
|
(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
|
||||||
true -> "com.android.permissioncontroller"
|
true -> {
|
||||||
false -> "com.android.packageinstaller"
|
Log.i(TAG, "getPermissionAllowID: Getting the permission button resource ID for API ${Build.VERSION.SDK_INT}.")
|
||||||
|
"com.android.permissioncontroller"
|
||||||
|
}
|
||||||
|
false -> {
|
||||||
|
Log.i(TAG, "getPermissionAllowID: Getting the permission button resource ID for API ${Build.VERSION.SDK_INT}.")
|
||||||
|
"com.android.packageinstaller"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,31 +84,36 @@ object AppAndSystemHelper {
|
||||||
*/
|
*/
|
||||||
fun deleteDownloadedFileOnStorage(fileName: String) {
|
fun deleteDownloadedFileOnStorage(fileName: String) {
|
||||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
|
||||||
|
Log.i(TAG, "deleteDownloadedFileOnStorage: Trying to delete file from API ${Build.VERSION.SDK_INT}.")
|
||||||
val storageManager: StorageManager? =
|
val storageManager: StorageManager? =
|
||||||
TestHelper.appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
|
appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
|
||||||
val storageVolumes = storageManager!!.storageVolumes
|
val storageVolumes = storageManager!!.storageVolumes
|
||||||
val storageVolume: StorageVolume = storageVolumes[0]
|
val storageVolume: StorageVolume = storageVolumes[0]
|
||||||
val file = File(storageVolume.directory!!.path + "/Download/" + fileName)
|
val file = File(storageVolume.directory!!.path + "/Download/" + fileName)
|
||||||
try {
|
try {
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
|
Log.i(TAG, "deleteDownloadedFileOnStorage: The file exists. Trying to delete $fileName, try 1.")
|
||||||
file.delete()
|
file.delete()
|
||||||
Log.d("TestLog", "File delete try 1")
|
Assert.assertFalse("$TAG deleteDownloadedFileOnStorage: The $fileName file was not deleted", file.exists())
|
||||||
Assert.assertFalse("The file was not deleted", file.exists())
|
Log.i(TAG, "deleteDownloadedFileOnStorage: Verified the $fileName file was deleted.")
|
||||||
}
|
}
|
||||||
} catch (e: AssertionError) {
|
} catch (e: AssertionError) {
|
||||||
|
Log.i(TAG, "deleteDownloadedFileOnStorage: AssertionError caught. Retrying to delete the file.")
|
||||||
file.delete()
|
file.delete()
|
||||||
Log.d("TestLog", "File delete retried")
|
Log.i(TAG, "deleteDownloadedFileOnStorage: Retrying to delete $fileName.")
|
||||||
Assert.assertFalse("The file was not deleted", file.exists())
|
Assert.assertFalse("$TAG deleteDownloadedFileOnStorage: The file was not deleted", file.exists())
|
||||||
|
Log.i(TAG, "deleteDownloadedFileOnStorage: Verified the $fileName file was deleted, try 2.")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
|
Log.i(TAG, "deleteDownloadedFileOnStorage: Trying to delete file from API ${Build.VERSION.SDK_INT}.")
|
||||||
val downloadedFile = File(
|
val downloadedFile = File(
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
|
||||||
fileName,
|
fileName,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (downloadedFile.exists()) {
|
if (downloadedFile.exists()) {
|
||||||
Log.i(TAG, "deleteDownloadedFileOnStorage: Verifying if $downloadedFile exists.")
|
Log.i(TAG, "deleteDownloadedFileOnStorage: The file exists. Trying to delete the file.")
|
||||||
downloadedFile.delete()
|
downloadedFile.delete()
|
||||||
Log.i(TAG, "deleteDownloadedFileOnStorage: $downloadedFile deleted.")
|
Log.i(TAG, "deleteDownloadedFileOnStorage: $downloadedFile deleted.")
|
||||||
}
|
}
|
||||||
|
@ -107,38 +127,55 @@ object AppAndSystemHelper {
|
||||||
* Environment.getExternalStorageDirectory() is deprecated starting with API 29.
|
* Environment.getExternalStorageDirectory() is deprecated starting with API 29.
|
||||||
*/
|
*/
|
||||||
fun clearDownloadsFolder() {
|
fun clearDownloadsFolder() {
|
||||||
|
Log.i(TAG, "clearDownloadsFolder: Detected API ${Build.VERSION.SDK_INT}")
|
||||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
|
||||||
Log.i(TAG, "clearDownloadsFolder: API > 29")
|
|
||||||
val storageManager: StorageManager? =
|
val storageManager: StorageManager? =
|
||||||
TestHelper.appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
|
appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager?
|
||||||
val storageVolumes = storageManager!!.storageVolumes
|
val storageVolumes = storageManager!!.storageVolumes
|
||||||
val storageVolume: StorageVolume = storageVolumes[0]
|
val storageVolume: StorageVolume = storageVolumes[0]
|
||||||
val downloadsFolder = File(storageVolume.directory!!.path + "/Download/")
|
val downloadsFolder = File(storageVolume.directory!!.path + "/Download/")
|
||||||
|
|
||||||
// Check if the downloads folder exists
|
// Check if the downloads folder exists
|
||||||
if (downloadsFolder.exists() && downloadsFolder.isDirectory) {
|
if (downloadsFolder.exists() && downloadsFolder.isDirectory) {
|
||||||
Log.i(TAG, "clearDownloadsFolder: Verified that \"DOWNLOADS\" folder exists")
|
Log.i(TAG, "clearDownloadsFolder: Verified that \"DOWNLOADS\" folder exists.")
|
||||||
val files = downloadsFolder.listFiles()
|
var files = downloadsFolder.listFiles()
|
||||||
|
|
||||||
// Check if the folder is not empty
|
// Check if the folder is not empty
|
||||||
if (files != null && files.isNotEmpty()) {
|
if (files != null && files.isNotEmpty()) {
|
||||||
Log.i(
|
Log.i(
|
||||||
TAG,
|
TAG,
|
||||||
"clearDownloadsFolder: Verified that \"DOWNLOADS\" folder is not empty",
|
"clearDownloadsFolder: Before cleanup: Downloads storage contains: ${files.size} file(s).",
|
||||||
)
|
)
|
||||||
// Delete all files in the folder
|
// Delete all files in the folder
|
||||||
for (file in files) {
|
for (file in files!!) {
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"clearDownloadsFolder: Trying to delete $file from \"DOWNLOADS\" folder.",
|
||||||
|
)
|
||||||
file.delete()
|
file.delete()
|
||||||
Log.i(TAG, "clearDownloadsFolder: Deleted $file from \"DOWNLOADS\" folder")
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"clearDownloadsFolder: Deleted $file from \"DOWNLOADS\" folder.",
|
||||||
|
)
|
||||||
|
files = downloadsFolder.listFiles()
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"clearDownloadsFolder: After cleanup: Downloads storage contains: ${files?.size} file(s).",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"clearDownloadsFolder: Downloads storage is empty.",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
Log.i(TAG, "clearDownloadsFolder: API <= 29")
|
|
||||||
Log.i(TAG, "clearDownloadsFolder: Verifying if any download files exist.")
|
Log.i(TAG, "clearDownloadsFolder: Verifying if any download files exist.")
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
||||||
.listFiles()?.forEach {
|
.listFiles()?.forEach {
|
||||||
|
Log.i(TAG, "clearDownloadsFolder: Trying to delete from storage: $it.")
|
||||||
it.delete()
|
it.delete()
|
||||||
Log.i(TAG, "clearDownloadsFolder: Download file $it deleted.")
|
Log.i(TAG, "clearDownloadsFolder: Download file $it deleted.")
|
||||||
}
|
}
|
||||||
|
@ -146,33 +183,106 @@ object AppAndSystemHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun deleteHistoryStorage() {
|
||||||
|
val historyStorage = PlacesHistoryStorage(appContext.applicationContext)
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"deleteHistoryStorage before cleanup: History storage contains: ${historyStorage.getVisited()}",
|
||||||
|
)
|
||||||
|
if (historyStorage.getVisited().isNotEmpty()) {
|
||||||
|
Log.i(TAG, "deleteHistoryStorage: Trying to delete all history storage.")
|
||||||
|
historyStorage.deleteEverything()
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"deleteHistoryStorage after cleanup: History storage contains: ${historyStorage.getVisited()}",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun deleteBookmarksStorage() {
|
||||||
|
val bookmarks = bookmarks()
|
||||||
|
Log.i(TAG, "deleteBookmarksStorage before cleanup: Bookmarks storage contains: $bookmarks")
|
||||||
|
if (bookmarks?.isNotEmpty() == true) {
|
||||||
|
bookmarks.forEach {
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"deleteBookmarksStorage: Trying to delete $it bookmark from storage.",
|
||||||
|
)
|
||||||
|
bookmarksStorage.deleteNode(it.guid)
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"deleteBookmarksStorage: Bookmark deleted. Bookmarks storage contains: ${bookmarks()}",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun deletePermissionsStorage() {
|
||||||
|
val permissionStorage = PermissionStorage(appContext.applicationContext)
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"deletePermissionsStorage: Trying to delete permissions. Permissions storage contains: ${permissionStorage.getSitePermissionsPaged()}",
|
||||||
|
)
|
||||||
|
permissionStorage.deleteAllSitePermissions()
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"deletePermissionsStorage: Permissions deleted. Permissions storage contains: ${permissionStorage.getSitePermissionsPaged()}",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun setNetworkEnabled(enabled: Boolean) {
|
fun setNetworkEnabled(enabled: Boolean) {
|
||||||
val networkDisconnectedIdlingResource = NetworkConnectionIdlingResource(false)
|
val networkDisconnectedIdlingResource = NetworkConnectionIdlingResource(false)
|
||||||
val networkConnectedIdlingResource = NetworkConnectionIdlingResource(true)
|
val networkConnectedIdlingResource = NetworkConnectionIdlingResource(true)
|
||||||
|
|
||||||
when (enabled) {
|
when (enabled) {
|
||||||
true -> {
|
true -> {
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"setNetworkEnabled: Trying to enable the network connection.",
|
||||||
|
)
|
||||||
mDevice.executeShellCommand("svc data enable")
|
mDevice.executeShellCommand("svc data enable")
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"setNetworkEnabled: Data network connection enable command sent.",
|
||||||
|
)
|
||||||
mDevice.executeShellCommand("svc wifi enable")
|
mDevice.executeShellCommand("svc wifi enable")
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"setNetworkEnabled: Wifi network connection enable command sent.",
|
||||||
|
)
|
||||||
|
|
||||||
// Wait for network connection to be completely enabled
|
// Wait for network connection to be completely enabled
|
||||||
|
Log.i(TAG, "setNetworkEnabled: Waiting for connection to be enabled.")
|
||||||
IdlingRegistry.getInstance().register(networkConnectedIdlingResource)
|
IdlingRegistry.getInstance().register(networkConnectedIdlingResource)
|
||||||
Espresso.onIdle {
|
Espresso.onIdle {
|
||||||
IdlingRegistry.getInstance().unregister(networkConnectedIdlingResource)
|
IdlingRegistry.getInstance().unregister(networkConnectedIdlingResource)
|
||||||
}
|
}
|
||||||
Log.i(TAG, "setNetworkEnabled: Network connection was enabled")
|
Log.i(TAG, "setNetworkEnabled: Network connection was enabled.")
|
||||||
}
|
}
|
||||||
|
|
||||||
false -> {
|
false -> {
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"setNetworkEnabled: Trying to disable the network connection.",
|
||||||
|
)
|
||||||
mDevice.executeShellCommand("svc data disable")
|
mDevice.executeShellCommand("svc data disable")
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"setNetworkEnabled: Data network connection disable command sent.",
|
||||||
|
)
|
||||||
mDevice.executeShellCommand("svc wifi disable")
|
mDevice.executeShellCommand("svc wifi disable")
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"setNetworkEnabled: Wifi network connection disable command sent.",
|
||||||
|
)
|
||||||
|
|
||||||
// Wait for network connection to be completely disabled
|
// Wait for network connection to be completely disabled
|
||||||
|
Log.i(TAG, "setNetworkEnabled: Waiting for connection to be disabled.")
|
||||||
IdlingRegistry.getInstance().register(networkDisconnectedIdlingResource)
|
IdlingRegistry.getInstance().register(networkDisconnectedIdlingResource)
|
||||||
Espresso.onIdle {
|
Espresso.onIdle {
|
||||||
IdlingRegistry.getInstance().unregister(networkDisconnectedIdlingResource)
|
IdlingRegistry.getInstance().unregister(networkDisconnectedIdlingResource)
|
||||||
}
|
}
|
||||||
Log.i(TAG, "setNetworkEnabled: Network connection was disabled")
|
Log.i(TAG, "setNetworkEnabled: Network connection was disabled.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,6 +292,8 @@ object AppAndSystemHelper {
|
||||||
return try {
|
return try {
|
||||||
val packageManager = InstrumentationRegistry.getInstrumentation().context.packageManager
|
val packageManager = InstrumentationRegistry.getInstrumentation().context.packageManager
|
||||||
packageManager.getApplicationInfo(packageName, 0).enabled
|
packageManager.getApplicationInfo(packageName, 0).enabled
|
||||||
|
Log.i(TAG, "isPackageInstalled: $packageName is installed.")
|
||||||
|
true
|
||||||
} catch (e: PackageManager.NameNotFoundException) {
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
Log.i(TAG, "isPackageInstalled: $packageName is not installed - ${e.message}")
|
Log.i(TAG, "isPackageInstalled: $packageName is not installed - ${e.message}")
|
||||||
false
|
false
|
||||||
|
@ -190,18 +302,18 @@ object AppAndSystemHelper {
|
||||||
|
|
||||||
fun assertExternalAppOpens(appPackageName: String) {
|
fun assertExternalAppOpens(appPackageName: String) {
|
||||||
if (isPackageInstalled(appPackageName)) {
|
if (isPackageInstalled(appPackageName)) {
|
||||||
Log.i(TAG, "assertExternalAppOpens: $appPackageName is installed on device")
|
|
||||||
try {
|
try {
|
||||||
Log.i(TAG, "assertExternalAppOpens: Try block")
|
Log.i(TAG, "assertExternalAppOpens: Trying to check the intent sent.")
|
||||||
intended(toPackage(appPackageName))
|
intended(toPackage(appPackageName))
|
||||||
Log.i(TAG, "assertExternalAppOpens: Matched intent to $appPackageName")
|
Log.i(TAG, "assertExternalAppOpens: Matched open intent to $appPackageName.")
|
||||||
} catch (e: AssertionFailedError) {
|
} catch (e: AssertionFailedError) {
|
||||||
Log.i(TAG, "assertExternalAppOpens: Catch block - ${e.message}")
|
Log.i(TAG, "assertExternalAppOpens: Intent match failure. ${e.message}")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Log.i(TAG, "assertExternalAppOpens: Trying to verify the \"Could not open file\" message.")
|
||||||
mDevice.waitNotNull(
|
mDevice.waitNotNull(
|
||||||
Until.findObject(By.text("Could not open file")),
|
Until.findObject(By.text("Could not open file")),
|
||||||
TestAssetHelper.waitingTime,
|
waitingTime,
|
||||||
)
|
)
|
||||||
Log.i(TAG, "assertExternalAppOpens: Verified \"Could not open file\" message")
|
Log.i(TAG, "assertExternalAppOpens: Verified \"Could not open file\" message")
|
||||||
}
|
}
|
||||||
|
@ -209,17 +321,28 @@ object AppAndSystemHelper {
|
||||||
|
|
||||||
fun assertNativeAppOpens(appPackageName: String, url: String = "") {
|
fun assertNativeAppOpens(appPackageName: String, url: String = "") {
|
||||||
if (isPackageInstalled(appPackageName)) {
|
if (isPackageInstalled(appPackageName)) {
|
||||||
mDevice.waitForIdle(TestAssetHelper.waitingTimeShort)
|
Log.i(TAG, "assertNativeAppOpens: Waiting for the device to be idle $waitingTimeShort ms.")
|
||||||
|
mDevice.waitForIdle(waitingTimeShort)
|
||||||
|
Log.i(TAG, "assertNativeAppOpens: Waited for the device to be idle $waitingTimeShort ms.")
|
||||||
|
Log.i(TAG, "assertNativeAppOpens: Trying to match the app package name is matched.")
|
||||||
Assert.assertTrue(
|
Assert.assertTrue(
|
||||||
TestHelper.mDevice.findObject(UiSelector().packageName(appPackageName))
|
"$TAG $appPackageName not found",
|
||||||
.waitForExists(TestAssetHelper.waitingTime),
|
mDevice.findObject(UiSelector().packageName(appPackageName))
|
||||||
|
.waitForExists(waitingTime),
|
||||||
)
|
)
|
||||||
|
Log.i(TAG, "assertNativeAppOpens: App package name matched.")
|
||||||
} else {
|
} else {
|
||||||
|
Log.i(TAG, "assertNativeAppOpens: Trying to verify the page redirect URL.")
|
||||||
BrowserRobot().verifyUrl(url)
|
BrowserRobot().verifyUrl(url)
|
||||||
|
Log.i(TAG, "assertNativeAppOpens: Verified the page redirect URL.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun assertYoutubeAppOpens() = intended(toPackage(YOUTUBE_APP))
|
fun assertYoutubeAppOpens() {
|
||||||
|
Log.i(TAG, "assertYoutubeAppOpens: Trying to check the intent to YouTube.")
|
||||||
|
intended(toPackage(YOUTUBE_APP))
|
||||||
|
Log.i(TAG, "assertYoutubeAppOpens: Verified the intent matches YouTube.")
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the latest activity of the application is used for custom tabs or PWAs.
|
* Checks whether the latest activity of the application is used for custom tabs or PWAs.
|
||||||
|
@ -227,11 +350,16 @@ object AppAndSystemHelper {
|
||||||
* @return Boolean value that helps us know if the current activity supports custom tabs or PWAs.
|
* @return Boolean value that helps us know if the current activity supports custom tabs or PWAs.
|
||||||
*/
|
*/
|
||||||
fun isExternalAppBrowserActivityInCurrentTask(): Boolean {
|
fun isExternalAppBrowserActivityInCurrentTask(): Boolean {
|
||||||
Log.i(TAG, "Trying to verify that the latest activity of the application is used for custom tabs or PWAs")
|
val activityManager = appContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||||
val activityManager = TestHelper.appContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
|
||||||
|
|
||||||
mDevice.waitForIdle(TestAssetHelper.waitingTimeShort)
|
Log.i(TAG, "isExternalAppBrowserActivityInCurrentTask: Waiting for the device to be idle for $waitingTimeShort ms")
|
||||||
|
mDevice.waitForIdle(waitingTimeShort)
|
||||||
|
Log.i(TAG, "isExternalAppBrowserActivityInCurrentTask: Waited for the device to be idle for $waitingTimeShort ms")
|
||||||
|
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"isExternalAppBrowserActivityInCurrentTask: Trying to verify that the latest activity of the application is used for custom tabs or PWAs",
|
||||||
|
)
|
||||||
return activityManager.appTasks[0].taskInfo.topActivity!!.className == ExternalAppBrowserActivity::class.java.name
|
return activityManager.appTasks[0].taskInfo.topActivity!!.className == ExternalAppBrowserActivity::class.java.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,14 +374,18 @@ object AppAndSystemHelper {
|
||||||
testBlock: () -> Unit,
|
testBlock: () -> Unit,
|
||||||
) {
|
) {
|
||||||
idlingResources.forEach {
|
idlingResources.forEach {
|
||||||
|
Log.i(TAG, "registerAndCleanupIdlingResources: Trying to register idling resource $it.")
|
||||||
IdlingRegistry.getInstance().register(it)
|
IdlingRegistry.getInstance().register(it)
|
||||||
|
Log.i(TAG, "registerAndCleanupIdlingResources: Registered idling resource $it.")
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
testBlock()
|
testBlock()
|
||||||
} finally {
|
} finally {
|
||||||
idlingResources.forEach {
|
idlingResources.forEach {
|
||||||
|
Log.i(TAG, "registerAndCleanupIdlingResources: Trying to unregister idling resource $it.")
|
||||||
IdlingRegistry.getInstance().unregister(it)
|
IdlingRegistry.getInstance().unregister(it)
|
||||||
|
Log.i(TAG, "registerAndCleanupIdlingResources: Unregistered idling resource $it.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,18 +403,26 @@ object AppAndSystemHelper {
|
||||||
)
|
)
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
if (whileUsingTheAppPermissionButton.waitForExists(TestAssetHelper.waitingTimeShort)) {
|
if (whileUsingTheAppPermissionButton.waitForExists(waitingTimeShort)) {
|
||||||
|
Log.i(TAG, "grantSystemPermission: Trying to click the \"While using the app\" button.")
|
||||||
whileUsingTheAppPermissionButton.click()
|
whileUsingTheAppPermissionButton.click()
|
||||||
} else if (allowPermissionButton.waitForExists(TestAssetHelper.waitingTimeShort)) {
|
Log.i(TAG, "grantSystemPermission: Clicked the \"While using the app\" button.")
|
||||||
|
} else if (allowPermissionButton.waitForExists(waitingTimeShort)) {
|
||||||
|
Log.i(TAG, "grantSystemPermission: Trying to click the \"Allow\" button.")
|
||||||
allowPermissionButton.click()
|
allowPermissionButton.click()
|
||||||
|
Log.i(TAG, "grantSystemPermission: Clicked the \"Allow\" button.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Permission deny dialogs differ on various Android APIs
|
// Permission deny dialogs differ on various Android APIs
|
||||||
fun denyPermission() {
|
fun denyPermission() {
|
||||||
mDevice.findObject(UiSelector().textContains("Deny")).waitForExists(TestAssetHelper.waitingTime)
|
Log.i(TAG, "denyPermission: Waiting $waitingTime ms for the \"Deny\" button to exist.")
|
||||||
|
mDevice.findObject(UiSelector().textContains("Deny")).waitForExists(waitingTime)
|
||||||
|
Log.i(TAG, "denyPermission: Waited for $waitingTime ms for the \"Deny\" button to exist.")
|
||||||
|
Log.i(TAG, "denyPermission: Trying to click the \"Deny\" button.")
|
||||||
mDevice.findObject(UiSelector().textContains("Deny")).click()
|
mDevice.findObject(UiSelector().textContains("Deny")).click()
|
||||||
|
Log.i(TAG, "denyPermission: Clicked the \"Deny\" button.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isTestLab(): Boolean {
|
fun isTestLab(): Boolean {
|
||||||
|
@ -291,71 +431,76 @@ object AppAndSystemHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the default language of the entire device, not just the app.
|
* Changes the default language of the entire device, not just the app.
|
||||||
* Runs on Debug variant as we don't want to adjust Release permission manifests
|
|
||||||
* Runs the test in its testBlock.
|
* Runs the test in its testBlock.
|
||||||
* Cleans up and sets the default locale after it's done.
|
* Cleans up and sets the default locale after it's done.
|
||||||
* As a safety measure, always add the resetSystemLocaleToEnUS() method in the tearDown method of your Class.
|
|
||||||
*/
|
*/
|
||||||
fun runWithSystemLocaleChanged(locale: Locale, testRule: ActivityTestRule<HomeActivity>, testBlock: () -> Unit) {
|
fun runWithSystemLocaleChanged(locale: Locale, testRule: ActivityTestRule<HomeActivity>, testBlock: () -> Unit) {
|
||||||
|
val defaultLocale = Locale.getDefault()
|
||||||
|
|
||||||
|
try {
|
||||||
|
Log.i(TAG, "runWithSystemLocaleChanged: Trying to set the locale.")
|
||||||
|
setSystemLocale(locale)
|
||||||
|
Log.i(TAG, "runWithSystemLocaleChanged: Running the test block.")
|
||||||
|
testBlock()
|
||||||
|
ThreadUtils.runOnUiThread { testRule.activity.recreate() }
|
||||||
|
Log.i(TAG, "runWithSystemLocaleChanged: Test block finished.")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.i(TAG, "runWithSystemLocaleChanged: The test block has thrown an exception.${e.message}")
|
||||||
|
e.printStackTrace()
|
||||||
|
} finally {
|
||||||
|
Log.i(TAG, "runWithSystemLocaleChanged: Trying to reset the locale to default.")
|
||||||
|
setSystemLocale(defaultLocale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the default language of the entire device, not just the app.
|
||||||
|
* We can only use this if we're running on a debug build, otherwise it will change the permission manifests in release builds.
|
||||||
|
*/
|
||||||
|
fun setSystemLocale(locale: Locale) {
|
||||||
if (Config.channel.isDebug) {
|
if (Config.channel.isDebug) {
|
||||||
/* Sets permission to change device language */
|
/* Sets permission to change device language */
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"setSystemLocale: Requesting permission to change system locale to $locale.",
|
||||||
|
)
|
||||||
PermissionRequester().apply {
|
PermissionRequester().apply {
|
||||||
addPermissions(
|
addPermissions(
|
||||||
Manifest.permission.CHANGE_CONFIGURATION,
|
Manifest.permission.CHANGE_CONFIGURATION,
|
||||||
)
|
)
|
||||||
requestPermissions()
|
requestPermissions()
|
||||||
}
|
}
|
||||||
|
Log.i(
|
||||||
val defaultLocale = Locale.getDefault()
|
TAG,
|
||||||
|
"setSystemLocale: Received permission to change system locale to $locale.",
|
||||||
try {
|
)
|
||||||
setSystemLocale(locale)
|
val activityManagerNative = Class.forName("android.app.ActivityManagerNative")
|
||||||
testBlock()
|
val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0))
|
||||||
ThreadUtils.runOnUiThread { testRule.activity.recreate() }
|
.invoke(activityManagerNative, *arrayOfNulls(0))
|
||||||
} catch (e: Exception) {
|
val config =
|
||||||
e.printStackTrace()
|
InstrumentationRegistry.getInstrumentation().context.resources.configuration
|
||||||
} finally {
|
config.javaClass.getDeclaredField("locale")[config] = locale
|
||||||
setSystemLocale(defaultLocale)
|
config.javaClass.getDeclaredField("userSetLocale").setBoolean(config, true)
|
||||||
}
|
am.javaClass.getMethod(
|
||||||
|
"updateConfiguration",
|
||||||
|
Configuration::class.java,
|
||||||
|
).invoke(am, config)
|
||||||
}
|
}
|
||||||
}
|
Log.i(
|
||||||
|
TAG,
|
||||||
/**
|
"setSystemLocale: Changed system locale to $locale.",
|
||||||
* Resets the default language of the entire device back to EN-US.
|
)
|
||||||
* In case of a test instrumentation crash, the finally statement in the
|
|
||||||
* runWithSystemLocaleChanged(locale: Locale) method, will not be reached.
|
|
||||||
* Add this method inside the tearDown method of your test class, where the above method is used.
|
|
||||||
* Note: If set inside the ActivityTestRule's afterActivityFinished() method, this also won't work,
|
|
||||||
* as the methods inside it are not always executed: https://github.com/android/android-test/issues/498
|
|
||||||
*/
|
|
||||||
fun resetSystemLocaleToEnUS() {
|
|
||||||
if (Locale.getDefault() != Locale.US) {
|
|
||||||
Log.i(TAG, "Resetting system locale to EN US")
|
|
||||||
setSystemLocale(Locale.US)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the default language of the entire device, not just the app.
|
|
||||||
*/
|
|
||||||
fun setSystemLocale(locale: Locale) {
|
|
||||||
val activityManagerNative = Class.forName("android.app.ActivityManagerNative")
|
|
||||||
val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0))
|
|
||||||
.invoke(activityManagerNative, *arrayOfNulls(0))
|
|
||||||
val config = InstrumentationRegistry.getInstrumentation().context.resources.configuration
|
|
||||||
config.javaClass.getDeclaredField("locale")[config] = locale
|
|
||||||
config.javaClass.getDeclaredField("userSetLocale").setBoolean(config, true)
|
|
||||||
am.javaClass.getMethod(
|
|
||||||
"updateConfiguration",
|
|
||||||
Configuration::class.java,
|
|
||||||
).invoke(am, config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putAppToBackground() {
|
fun putAppToBackground() {
|
||||||
|
Log.i(TAG, "putAppToBackground: Trying to press the device Recent apps button.")
|
||||||
mDevice.pressRecentApps()
|
mDevice.pressRecentApps()
|
||||||
|
Log.i(TAG, "putAppToBackground: Pressed the device Recent apps button.")
|
||||||
|
Log.i(TAG, "putAppToBackground: Waiting for the app to be gone for $waitingTime ms.")
|
||||||
mDevice.findObject(UiSelector().resourceId("${TestHelper.packageName}:id/container")).waitUntilGone(
|
mDevice.findObject(UiSelector().resourceId("${TestHelper.packageName}:id/container")).waitUntilGone(
|
||||||
TestAssetHelper.waitingTime,
|
waitingTime,
|
||||||
)
|
)
|
||||||
|
Log.i(TAG, "putAppToBackground: Waited for the app to be gone for $waitingTime ms.")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -364,12 +509,19 @@ object AppAndSystemHelper {
|
||||||
* The recent apps tray on API 30 will always display only 2 apps, even if previously were opened more.
|
* The recent apps tray on API 30 will always display only 2 apps, even if previously were opened more.
|
||||||
* The index of the most recent opened app will always have index 2, meaning that the previously opened app will have index 1.
|
* The index of the most recent opened app will always have index 2, meaning that the previously opened app will have index 1.
|
||||||
*/
|
*/
|
||||||
fun bringAppToForeground() =
|
fun bringAppToForeground() {
|
||||||
mDevice.findObject(UiSelector().index(2).packageName(PIXEL_LAUNCHER)).clickAndWaitForNewWindow(waitingTimeShort)
|
Log.i(TAG, "bringAppToForeground: Trying to select the app from the recent apps tray and wait for $waitingTime ms for a new window")
|
||||||
|
mDevice.findObject(UiSelector().index(2).packageName(PIXEL_LAUNCHER))
|
||||||
|
.clickAndWaitForNewWindow(waitingTimeShort)
|
||||||
|
Log.i(TAG, "bringAppToForeground: Selected the app from the recent apps tray.")
|
||||||
|
}
|
||||||
|
|
||||||
fun verifyKeyboardVisibility(isExpectedToBeVisible: Boolean = true) {
|
fun verifyKeyboardVisibility(isExpectedToBeVisible: Boolean = true) {
|
||||||
|
Log.i(TAG, "verifyKeyboardVisibility: Waiting for the device to be idle.")
|
||||||
mDevice.waitForIdle()
|
mDevice.waitForIdle()
|
||||||
|
Log.i(TAG, "verifyKeyboardVisibility: Waited for the device to be idle.")
|
||||||
|
|
||||||
|
Log.i(TAG, "verifyKeyboardVisibility: Trying to verify the keyboard is visible.")
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"Keyboard not shown",
|
"Keyboard not shown",
|
||||||
isExpectedToBeVisible,
|
isExpectedToBeVisible,
|
||||||
|
@ -377,6 +529,7 @@ object AppAndSystemHelper {
|
||||||
.executeShellCommand("dumpsys input_method | grep mInputShown")
|
.executeShellCommand("dumpsys input_method | grep mInputShown")
|
||||||
.contains("mInputShown=true"),
|
.contains("mInputShown=true"),
|
||||||
)
|
)
|
||||||
|
Log.i(TAG, "verifyKeyboardVisibility: Verified the keyboard is visible.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openAppFromExternalLink(url: String) {
|
fun openAppFromExternalLink(url: String) {
|
||||||
|
@ -388,10 +541,14 @@ object AppAndSystemHelper {
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
Log.i(TAG, "openAppFromExternalLink: Trying to start the activity from an external intent.")
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
|
Log.i(TAG, "openAppFromExternalLink: Activity started from an external intent.")
|
||||||
} catch (ex: ActivityNotFoundException) {
|
} catch (ex: ActivityNotFoundException) {
|
||||||
|
Log.i(TAG, "openAppFromExternalLink: Exception caught. Trying to start the activity from a null intent.")
|
||||||
intent.setPackage(null)
|
intent.setPackage(null)
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
|
Log.i(TAG, "openAppFromExternalLink: Started the activity from a null intent.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,6 +557,7 @@ object AppAndSystemHelper {
|
||||||
* For example: this method will avoid accidentally running a test on GV versions where the feature is disabled.
|
* For example: this method will avoid accidentally running a test on GV versions where the feature is disabled.
|
||||||
*/
|
*/
|
||||||
fun runWithCondition(condition: Boolean, testBlock: () -> Unit) {
|
fun runWithCondition(condition: Boolean, testBlock: () -> Unit) {
|
||||||
|
Log.i(TAG, "runWithCondition: Trying to run the test based on condition. The condition is: $condition.")
|
||||||
if (condition) {
|
if (condition) {
|
||||||
testBlock()
|
testBlock()
|
||||||
}
|
}
|
||||||
|
@ -416,11 +574,15 @@ object AppAndSystemHelper {
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "runWithLauncherIntent: Trying to launch the activity from an intent: $launcherIntent.")
|
||||||
activityTestRule.activityRule.withIntent(launcherIntent).launchActivity(launcherIntent)
|
activityTestRule.activityRule.withIntent(launcherIntent).launchActivity(launcherIntent)
|
||||||
|
Log.i(TAG, "runWithLauncherIntent: Launched the activity from an intent: $launcherIntent.")
|
||||||
try {
|
try {
|
||||||
|
Log.i(TAG, "runWithLauncherIntent: Trying run the test block.")
|
||||||
testBlock()
|
testBlock()
|
||||||
|
Log.i(TAG, "runWithLauncherIntent: Finished running the test block.")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
Log.i(TAG, "runWithLauncherIntent: Exception caught while running the test block: ${e.message}")
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,9 @@ package org.mozilla.fenix.helpers
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.util.Log
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.mozilla.fenix.helpers.Constants.TAG
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts the two bitmaps are the same by ensuring their dimensions, config, and
|
* Asserts the two bitmaps are the same by ensuring their dimensions, config, and
|
||||||
|
@ -14,6 +16,7 @@ import org.junit.Assert.assertEquals
|
||||||
* [Bitmap.sameAs] uses.
|
* [Bitmap.sameAs] uses.
|
||||||
*/
|
*/
|
||||||
fun assertEqualsWithDelta(expectedB: Bitmap, actualB: Bitmap, delta: Float) {
|
fun assertEqualsWithDelta(expectedB: Bitmap, actualB: Bitmap, delta: Float) {
|
||||||
|
Log.i(TAG, "assertEqualsWithDelta: Trying to verify that the Bitmap of $expectedB is equal with the Bitmap of $actualB within delta: $delta")
|
||||||
assertEquals("widths should be equal", expectedB.width, actualB.width)
|
assertEquals("widths should be equal", expectedB.width, actualB.width)
|
||||||
assertEquals("heights should be equal", expectedB.height, actualB.height)
|
assertEquals("heights should be equal", expectedB.height, actualB.height)
|
||||||
assertEquals("config should be equal", expectedB.config, actualB.config)
|
assertEquals("config should be equal", expectedB.config, actualB.config)
|
||||||
|
@ -29,4 +32,5 @@ fun assertEqualsWithDelta(expectedB: Bitmap, actualB: Bitmap, delta: Float) {
|
||||||
assertEquals("$warn b", Color.blue(ePx).toFloat(), Color.blue(aPx).toFloat(), delta)
|
assertEquals("$warn b", Color.blue(ePx).toFloat(), Color.blue(aPx).toFloat(), delta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Log.i(TAG, "assertEqualsWithDelta: Verified that the Bitmap of $expectedB is equal with the Bitmap of $actualB within delta: $delta")
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,8 @@ object Constants {
|
||||||
const val RETRY_COUNT = 3
|
const val RETRY_COUNT = 3
|
||||||
|
|
||||||
val searchEngineCodes = mapOf(
|
val searchEngineCodes = mapOf(
|
||||||
"Google" to "client=firefox-b-m",
|
"LeOSearch" to "client=firefox-b-m",
|
||||||
"LeOSearch" to "firefox&pc=MOZB&form=MOZMBA",
|
"Bing" to "firefox&pc=MOZB&form=MOZMBA",
|
||||||
"DuckDuckGo" to "t=fpas",
|
"DuckDuckGo" to "t=fpas",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue