v125
harvey186 2024-06-01 16:29:02 +02:00
parent d46b64ddc0
commit 331c06960a
2587 changed files with 156562 additions and 62903 deletions

2
.buildconfig.yml Normal file → Executable file
View File

@ -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

0
.editorconfig Normal file → Executable file
View File

0
.gitattributes vendored Normal file → Executable file
View File

8
.github/workflows/ci.yml vendored Normal file → Executable file
View File

@ -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
View File

0
.github/workflows/disabled_workflows/fenix-sync-strings.yml vendored Normal file → Executable file
View File

0
.github/workflows/disabled_workflows/fenix-update-ac.yml vendored Normal file → Executable file
View File

View File

0
.github/workflows/disabled_workflows/glean-probe-scraper.yml vendored Normal file → Executable file
View File

0
.github/workflows/disabled_workflows/issue-linker.yml vendored Normal file → Executable file
View File

0
.github/workflows/disabled_workflows/milestone.yml vendored Normal file → Executable file
View File

0
.github/workflows/disabled_workflows/qa-needed.yml vendored Normal file → Executable file
View File

0
.github/workflows/disabled_workflows/reopen-for-qa-needed.yml vendored Normal file → Executable file
View File

8
.github/workflows/release.yml vendored Normal file → Executable file
View 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')"

0
.gitignore vendored Normal file → Executable file
View File

0
.gitmodules vendored Normal file → Executable file
View File

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

0
CODE_OF_CONDUCT.md Normal file → Executable file
View File

0
Gemfile Normal file → Executable file
View File

0
Jenkinsfile vendored Normal file → Executable file
View File

22
README.md Normal file → Executable file
View File

@ -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)"

0
SECURITY.md Normal file → Executable file
View File

@ -1 +1 @@
Subproject commit 96c21391b62d8b02ddddb0b86fa1e4702efa24f9 Subproject commit f03a5f2688acc3faffe488c75cea6658d079fea3

0
app/.experimenter.yaml Normal file → Executable file
View File

0
app/.gitignore vendored Normal file → Executable file
View File

0
app/benchmark.gradle Normal file → Executable file
View File

16
app/build.gradle Normal file → Executable file
View File

@ -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 {

0
app/lint-baseline.xml Normal file → Executable file
View File

0
app/lint.xml Normal file → Executable file
View File

10
app/messaging-evergreen-messages.fml.yaml Normal file → Executable file
View File

@ -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

0
app/messaging-fenix.fml.yaml Normal file → Executable file
View File

42
app/metrics.yaml Normal file → Executable file
View File

@ -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:

44
app/nimbus.fml.yaml Normal file → Executable file
View File

@ -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: {}

1
app/onboarding.fml.yaml Normal file → Executable file
View File

@ -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

0
app/pbm.fml.yaml Normal file → Executable file
View File

0
app/pings.yaml Normal file → Executable file
View File

0
app/proguard-rules.pro vendored Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/addressForm.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/audioMediaPage.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/creditCardForm.html Normal file → Executable file
View File

View File

0
app/src/androidTest/assets/pages/externalLinks.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/generic1.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/generic2.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/generic3.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/generic4.html Normal file → Executable file
View File

View File

0
app/src/androidTest/assets/pages/htmlControls.html Normal file → Executable file
View File

File diff suppressed because one or more lines are too long

0
app/src/androidTest/assets/pages/lorem-ipsum.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/mutedVideoPage.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/password.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/passwordsubmit.html Normal file → Executable file
View File

1
app/src/androidTest/assets/pages/refresh.html Normal file → Executable file
View File

@ -1,6 +1,5 @@
<html> <html>
<script src="jquery-3.4.1.slim.min.js"></script>
<script> <script>
function setCookie(newVal){ function setCookie(newVal){

0
app/src/androidTest/assets/pages/storage_check.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/storage_write.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/trackingPage.html Normal file → Executable file
View File

0
app/src/androidTest/assets/pages/videoMediaPage.html Normal file → Executable file
View File

0
app/src/androidTest/assets/resources/TestTTC.ttc Normal file → Executable file
View File

0
app/src/androidTest/assets/resources/TestTTF.ttf Normal file → Executable file
View File

0
app/src/androidTest/assets/resources/TestTT_-LICENSE Normal file → Executable file
View File

0
app/src/androidTest/assets/resources/audioSample.mp3 Normal file → Executable file
View File

0
app/src/androidTest/assets/resources/clip.mp4 Normal file → Executable file
View File

0
app/src/androidTest/assets/resources/pdfForm.pdf Normal file → Executable file
View File

0
app/src/androidTest/assets/resources/rabbit.jpg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

0
app/src/androidTest/assets/resources/trackingAPI.js Normal file → Executable file
View File

View File

View File

View File

View File

View 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,58 +431,54 @@ 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)
testBlock()
ThreadUtils.runOnUiThread { testRule.activity.recreate() }
} catch (e: Exception) {
e.printStackTrace()
} finally {
setSystemLocale(defaultLocale)
}
}
}
/**
* 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 activityManagerNative = Class.forName("android.app.ActivityManagerNative")
val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0)) val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0))
.invoke(activityManagerNative, *arrayOfNulls(0)) .invoke(activityManagerNative, *arrayOfNulls(0))
val config = InstrumentationRegistry.getInstrumentation().context.resources.configuration val config =
InstrumentationRegistry.getInstrumentation().context.resources.configuration
config.javaClass.getDeclaredField("locale")[config] = locale config.javaClass.getDeclaredField("locale")[config] = locale
config.javaClass.getDeclaredField("userSetLocale").setBoolean(config, true) config.javaClass.getDeclaredField("userSetLocale").setBoolean(config, true)
am.javaClass.getMethod( am.javaClass.getMethod(
@ -350,12 +486,21 @@ object AppAndSystemHelper {
Configuration::class.java, Configuration::class.java,
).invoke(am, config) ).invoke(am, config)
} }
Log.i(
TAG,
"setSystemLocale: Changed system locale to $locale.",
)
}
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()
} }
} }

View File

@ -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")
} }

View File

@ -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