summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:35:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:35:29 +0000
commit59203c63bb777a3bacec32fb8830fba33540e809 (patch)
tree58298e711c0ff0575818c30485b44a2f21bf28a0 /mobile/android/geckoview
parentAdding upstream version 126.0.1. (diff)
downloadfirefox-59203c63bb777a3bacec32fb8830fba33540e809.tar.xz
firefox-59203c63bb777a3bacec32fb8830fba33540e809.zip
Adding upstream version 127.0.upstream/127.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/geckoview')
-rw-r--r--mobile/android/geckoview/api.txt31
-rw-r--r--mobile/android/geckoview/build.gradle16
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-all-urls/manifest.json13
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt3
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoViewTest.kt3
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt26
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TelemetryTest.kt131
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TranslationsTest.kt115
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExtensionTest.kt102
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java6
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/RuntimeCreator.java50
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoDisplay.java6
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoEditable.java6
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java26
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java4
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java18
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java10
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java171
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java4
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionFinder.java4
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TranslationsController.java38
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java2
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java26
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md13
24 files changed, 355 insertions, 469 deletions
diff --git a/mobile/android/geckoview/api.txt b/mobile/android/geckoview/api.txt
index 658677a509..57c4d18d56 100644
--- a/mobile/android/geckoview/api.txt
+++ b/mobile/android/geckoview/api.txt
@@ -102,7 +102,6 @@ import org.mozilla.geckoview.OverscrollEdgeEffect;
import org.mozilla.geckoview.PanZoomController;
import org.mozilla.geckoview.ProfilerController;
import org.mozilla.geckoview.RuntimeSettings;
-import org.mozilla.geckoview.RuntimeTelemetry;
import org.mozilla.geckoview.ScreenLength;
import org.mozilla.geckoview.SessionAccessibility;
import org.mozilla.geckoview.SessionFinder;
@@ -886,7 +885,6 @@ package org.mozilla.geckoview {
method public boolean getRemoteDebuggingEnabled();
method @Nullable public GeckoRuntime getRuntime();
method @Nullable public Rect getScreenSizeOverride();
- method @Nullable public RuntimeTelemetry.Delegate getTelemetryDelegate();
method public boolean getTranslationsOfferPopup();
method @NonNull public String getTrustedRecursiveResolverUri();
method public int getTrustedRecusiveResolverMode();
@@ -969,7 +967,6 @@ package org.mozilla.geckoview {
method @NonNull public GeckoRuntimeSettings.Builder preferredColorScheme(int);
method @NonNull public GeckoRuntimeSettings.Builder remoteDebuggingEnabled(boolean);
method @NonNull public GeckoRuntimeSettings.Builder screenSizeOverride(int, int);
- method @Deprecated @DeprecationSchedule(id="geckoview-gvst",version=127) @NonNull public GeckoRuntimeSettings.Builder telemetryDelegate(@NonNull RuntimeTelemetry.Delegate);
method @NonNull public GeckoRuntimeSettings.Builder translationsOfferPopup(boolean);
method @NonNull public GeckoRuntimeSettings.Builder trustedRecursiveResolverMode(int);
method @NonNull public GeckoRuntimeSettings.Builder trustedRecursiveResolverUri(@NonNull String);
@@ -1081,6 +1078,7 @@ package org.mozilla.geckoview {
field public static final int FINDER_DISPLAY_DRAW_LINK_OUTLINE = 4;
field public static final int FINDER_DISPLAY_HIGHLIGHT_ALL = 1;
field public static final int FINDER_FIND_BACKWARDS = 1;
+ field public static final int FINDER_FIND_FORWARD = 0;
field public static final int FINDER_FIND_LINKS_ONLY = 8;
field public static final int FINDER_FIND_MATCH_CASE = 2;
field public static final int FINDER_FIND_WHOLE_WORD = 4;
@@ -2168,28 +2166,6 @@ package org.mozilla.geckoview {
method @AnyThread @NonNull protected abstract Settings newSettings(@Nullable Settings);
}
- public final class RuntimeTelemetry {
- ctor protected RuntimeTelemetry();
- }
-
- public static interface RuntimeTelemetry.Delegate {
- method @AnyThread default public void onBooleanScalar(@NonNull RuntimeTelemetry.Metric<Boolean>);
- method @AnyThread default public void onHistogram(@NonNull RuntimeTelemetry.Histogram);
- method @AnyThread default public void onLongScalar(@NonNull RuntimeTelemetry.Metric<Long>);
- method @AnyThread default public void onStringScalar(@NonNull RuntimeTelemetry.Metric<String>);
- }
-
- public static class RuntimeTelemetry.Histogram extends RuntimeTelemetry.Metric<long[]> {
- ctor protected Histogram();
- field public final boolean isCategorical;
- }
-
- public static class RuntimeTelemetry.Metric<T> {
- ctor protected Metric();
- field @NonNull public final String name;
- field @NonNull public final T value;
- }
-
public class ScreenLength {
method @AnyThread @NonNull public static ScreenLength bottom();
method @AnyThread @NonNull public static ScreenLength fromPixels(double);
@@ -2396,9 +2372,11 @@ package org.mozilla.geckoview {
}
public static class TranslationsController.SessionTranslation.TranslationState {
- ctor public TranslationState(@Nullable TranslationsController.SessionTranslation.TranslationPair, @Nullable String, @Nullable TranslationsController.SessionTranslation.DetectedLanguages, @NonNull Boolean);
+ ctor @Deprecated @DeprecationSchedule(version=130,id="translation-state-deprecated-constructor") public TranslationState(@Nullable TranslationsController.SessionTranslation.TranslationPair, @Nullable String, @Nullable TranslationsController.SessionTranslation.DetectedLanguages, @NonNull Boolean);
+ ctor public TranslationState(@Nullable TranslationsController.SessionTranslation.TranslationPair, @Nullable String, @Nullable TranslationsController.SessionTranslation.DetectedLanguages, @NonNull Boolean, @NonNull Boolean);
field @Nullable public final TranslationsController.SessionTranslation.DetectedLanguages detectedLanguages;
field @Nullable public final String error;
+ field @NonNull public final Boolean hasVisibleChange;
field @NonNull public final Boolean isEngineReady;
field @Nullable public final TranslationsController.SessionTranslation.TranslationPair requestedTranslationPair;
}
@@ -2792,6 +2770,7 @@ package org.mozilla.geckoview {
method @UiThread default public void onInstallationFailed(@Nullable WebExtension, @NonNull WebExtension.InstallException);
method @UiThread default public void onInstalled(@NonNull WebExtension);
method @UiThread default public void onInstalling(@NonNull WebExtension);
+ method @UiThread default public void onOptionalPermissionsChanged(@NonNull WebExtension);
method @UiThread default public void onReady(@NonNull WebExtension);
method @UiThread default public void onUninstalled(@NonNull WebExtension);
method @UiThread default public void onUninstalling(@NonNull WebExtension);
diff --git a/mobile/android/geckoview/build.gradle b/mobile/android/geckoview/build.gradle
index 040cd2fea8..8a8ba698ec 100644
--- a/mobile/android/geckoview/build.gradle
+++ b/mobile/android/geckoview/build.gradle
@@ -229,6 +229,8 @@ configurations {
dependencies {
implementation ComponentsDependencies.androidx_annotation
+ implementation ComponentsDependencies.androidx_collection
+ implementation ComponentsDependencies.androidx_core
implementation "com.google.android.gms:play-services-fido:20.0.1"
implementation "org.yaml:snakeyaml:2.2"
@@ -384,20 +386,6 @@ android.libraryVariants.all { variant ->
}
}
-android.libraryVariants.all { variant ->
- // At this point, the Android-Gradle plugin has created all the Android
- // tasks and configurations. This is the time for us to declare additional
- // Glean files to package into AAR files. This packs `metrics.yaml` in the
- // root of the AAR, sibling to `AndroidManifest.xml` and `classes.jar`. By
- // default, consumers of the AAR will ignore this file, but consumers that
- // look for it can find it (provided GeckoView is a `module()` dependency
- // and not a `project()` dependency.) Under the hood this uses that the
- // task provided by `packageLibraryProvider` task is a Maven `Zip` task,
- // and we can simply extend its inputs. See
- // https://android.googlesource.com/platform/tools/base/+/0cbe8846f7d02c0bb6f07156b9f4fde16d96d329/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/BundleAar.kt#94.
- variant.packageLibraryProvider.get().from("${topsrcdir}/toolkit/components/telemetry/geckoview/streaming/metrics.yaml")
-}
-
apply plugin: 'maven-publish'
version = getVersionNumber()
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-all-urls/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-all-urls/manifest.json
new file mode 100644
index 0000000000..c1c8fd9caa
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-all-urls/manifest.json
@@ -0,0 +1,13 @@
+{
+ "manifest_version": 3,
+ "name": "optional-permission-all-urls",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "optional-permission-all-urls@example.com"
+ }
+ },
+ "version": "1.0",
+ "description": "Request optional extension origins for all urls.",
+ "optional_permissions": ["geolocation", "activeTab"],
+ "host_permissions": ["http://*/", "https://*/", "file://*/*"]
+}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
index 2ec305f913..06b946ba3d 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
@@ -2029,9 +2029,6 @@ class GeckoSessionTestRuleTest : BaseSessionTest(noErrorCollector = true) {
@IgnoreCrash
@Test
fun contentCrashIgnored() {
- // TODO: Bug 1673953
- assumeThat(sessionRule.env.isFission, equalTo(false))
-
// TODO: bug 1710940
assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false))
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoViewTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoViewTest.kt
index 82af2c6475..c2ecb652a2 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoViewTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoViewTest.kt
@@ -11,7 +11,6 @@ import android.view.View
import android.view.ViewStructure
import android.view.autofill.AutofillId
import android.view.autofill.AutofillValue
-import androidx.core.view.ViewCompat
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
@@ -79,7 +78,7 @@ class GeckoViewTest : BaseSessionTest() {
activityRule.scenario.onActivity {
assertThat(
"View should be attached",
- ViewCompat.isAttachedToWindow(it.view),
+ it.view.isAttachedToWindow(),
equalTo(true),
)
it.view.session!!.acquireDisplay()
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt
index f3141c661c..301995c95c 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt
@@ -12,7 +12,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import androidx.test.platform.app.InstrumentationRegistry
import org.hamcrest.Matchers.* // ktlint-disable no-wildcard-imports
-import org.junit.Assert
+import org.junit.Assert.*
import org.junit.Assume.assumeThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -25,6 +25,7 @@ import org.mozilla.geckoview.GeckoSession.ContentDelegate
import org.mozilla.geckoview.GeckoSession.ProgressDelegate
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay
+import org.mozilla.geckoview.test.util.UiThreadUtils
import java.lang.IllegalStateException
import kotlin.math.absoluteValue
import kotlin.math.max
@@ -142,6 +143,27 @@ class ScreenshotTest : BaseSessionTest() {
}
}
+ @WithDisplay(height = SCREEN_HEIGHT, width = SCREEN_WIDTH)
+ @Test
+ fun capturePixelsFailsWhenCompositorNotReady() {
+ sessionRule.display?.let { display ->
+ mainSession.close()
+ var exceptionListenerCalled = false
+ val result = display.capturePixels()
+ result.exceptionally { error: Throwable ->
+ assertTrue(error is IllegalStateException)
+ exceptionListenerCalled = true
+ result
+ }.accept {
+ fail("screenshot shouldn't complete successfully after session is closed")
+ }
+ UiThreadUtils.waitForCondition(
+ { exceptionListenerCalled },
+ sessionRule.env.defaultTimeoutMillis,
+ )
+ } ?: run { fail("no display found") }
+ }
+
// This tests tries to catch problems like Bug 1644561.
@WithDisplay(height = SCREEN_HEIGHT, width = SCREEN_WIDTH)
@Test
@@ -430,7 +452,7 @@ class ScreenshotTest : BaseSessionTest() {
.capture()
.exceptionally(
OnExceptionListener<Throwable> { error: Throwable ->
- Assert.assertTrue(error is OutOfMemoryError)
+ assertTrue(error is OutOfMemoryError)
fromException(error)
},
)
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TelemetryTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TelemetryTest.kt
deleted file mode 100644
index 42286c47a7..0000000000
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TelemetryTest.kt
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-package org.mozilla.geckoview.test
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.MediumTest
-import org.hamcrest.CoreMatchers.equalTo
-import org.hamcrest.Matchers.* // ktlint-disable no-wildcard-imports
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mozilla.geckoview.GeckoResult
-import org.mozilla.geckoview.RuntimeTelemetry
-import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
-
-@RunWith(AndroidJUnit4::class)
-@MediumTest
-class TelemetryTest : BaseSessionTest() {
- @Test
- fun testOnTelemetryReceived() {
- // Let's make sure we batch the telemetry calls.
- sessionRule.setPrefsUntilTestEnd(
- mapOf("toolkit.telemetry.geckoview.batchDurationMS" to 100000),
- )
-
- val expectedHistograms = listOf<Long>(401, 12, 1, 109, 2000)
- val receivedHistograms = mutableListOf<Long>()
- val histogram = GeckoResult<Void>()
- val stringScalar = GeckoResult<Void>()
- val booleanScalar = GeckoResult<Void>()
- val longScalar = GeckoResult<Void>()
-
- sessionRule.addExternalDelegateUntilTestEnd(
- RuntimeTelemetry.Delegate::class,
- sessionRule::setTelemetryDelegate,
- { sessionRule.setTelemetryDelegate(null) },
- object : RuntimeTelemetry.Delegate {
- @AssertCalled
- override fun onHistogram(metric: RuntimeTelemetry.Histogram) {
- if (metric.name != "TELEMETRY_TEST_STREAMING") {
- return
- }
-
- assertThat(
- "The histogram should not be categorical",
- metric.isCategorical,
- equalTo(false),
- )
-
- receivedHistograms.addAll(metric.value.toList())
-
- if (receivedHistograms.size == expectedHistograms.size) {
- histogram.complete(null)
- }
- }
-
- @AssertCalled
- override fun onStringScalar(metric: RuntimeTelemetry.Metric<String>) {
- if (metric.name != "telemetry.test.string_kind") {
- return
- }
-
- assertThat(
- "Metric value should match",
- metric.value,
- equalTo("test scalar"),
- )
-
- stringScalar.complete(null)
- }
-
- @AssertCalled
- override fun onBooleanScalar(metric: RuntimeTelemetry.Metric<Boolean>) {
- if (metric.name != "telemetry.test.boolean_kind") {
- return
- }
-
- assertThat(
- "Metric value should match",
- metric.value,
- equalTo(true),
- )
-
- booleanScalar.complete(null)
- }
-
- @AssertCalled
- override fun onLongScalar(metric: RuntimeTelemetry.Metric<Long>) {
- if (metric.name != "telemetry.test.unsigned_int_kind") {
- return
- }
-
- assertThat(
- "Metric value should match",
- metric.value,
- equalTo(1234L),
- )
-
- longScalar.complete(null)
- }
- },
- )
-
- sessionRule.addHistogram("TELEMETRY_TEST_STREAMING", expectedHistograms[0])
- sessionRule.addHistogram("TELEMETRY_TEST_STREAMING", expectedHistograms[1])
- sessionRule.addHistogram("TELEMETRY_TEST_STREAMING", expectedHistograms[2])
- sessionRule.addHistogram("TELEMETRY_TEST_STREAMING", expectedHistograms[3])
-
- sessionRule.setScalar("telemetry.test.boolean_kind", true)
- sessionRule.setScalar("telemetry.test.unsigned_int_kind", 1234)
- sessionRule.setScalar("telemetry.test.string_kind", "test scalar")
-
- // Forces flushing telemetry data at next histogram.
- sessionRule.setPrefsUntilTestEnd(
- mapOf("toolkit.telemetry.geckoview.batchDurationMS" to 0),
- )
- sessionRule.addHistogram("TELEMETRY_TEST_STREAMING", expectedHistograms[4])
-
- sessionRule.waitForResult(histogram)
- sessionRule.waitForResult(stringScalar)
- sessionRule.waitForResult(booleanScalar)
- sessionRule.waitForResult(longScalar)
-
- assertThat(
- "Metric values should match",
- receivedHistograms,
- equalTo(expectedHistograms),
- )
- }
-}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TranslationsTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TranslationsTest.kt
index a2c4eede62..966eba73b6 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TranslationsTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TranslationsTest.kt
@@ -6,6 +6,7 @@ package org.mozilla.geckoview.test
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
+import junit.framework.TestCase.assertFalse
import junit.framework.TestCase.assertTrue
import org.json.JSONObject
import org.junit.After
@@ -78,7 +79,7 @@ class TranslationsTest : BaseSessionTest() {
handled.complete(null)
}
})
- var expectedTranslateEvent = JSONObject(
+ val expectedTranslateEvent = JSONObject(
"""
{
"actor":{
@@ -89,6 +90,7 @@ class TranslationsTest : BaseSessionTest() {
"docLangTag": "es"
},
"requestedTranslationPair": null,
+ "hasVisibleChange": false,
"error": null,
"isEngineReady": false
}
@@ -153,28 +155,43 @@ class TranslationsTest : BaseSessionTest() {
val translate = sessionRule.session.sessionTranslation!!.translate("en", "es", null)
try {
sessionRule.waitForResult(translate)
- assertTrue("Translate should complete.", true)
+ // When testing from AS, this path is possible.
+ if (!sessionRule.env.isAutomation) {
+ assertTrue("Translate should complete.", true)
+ }
} catch (e: Exception) {
- assertTrue("Should not have an exception while translating.", false)
+ if (sessionRule.env.isAutomation) {
+ assertTrue("Expect an exception while translating in automation.", true)
+ }
}
// Options should work as expected
- var options = TranslationOptions.Builder().downloadModel(true).build()
+ val options = TranslationOptions.Builder().downloadModel(true).build()
val translateOptions = sessionRule.session.sessionTranslation!!.translate("en", "es", options)
try {
sessionRule.waitForResult(translateOptions)
- assertTrue("Translate should complete with options.", true)
+ // When testing from AS, this path is possible.
+ if (!sessionRule.env.isAutomation) {
+ assertTrue("Translate should complete with options.", true)
+ }
} catch (e: Exception) {
- assertTrue("Should not have an exception while translating with options.", false)
+ if (sessionRule.env.isAutomation) {
+ assertTrue("Expect an exception while translating in automation.", true)
+ }
}
// Language tags should be fault tolerant of minor variations
val longLanguageTag = sessionRule.session.sessionTranslation!!.translate("EN", "ES", null)
try {
sessionRule.waitForResult(longLanguageTag)
- assertTrue("Translate should complete with longer language tag.", true)
+ // When testing from AS, this path is possible.
+ if (!sessionRule.env.isAutomation) {
+ assertTrue("Translate should complete with longer language tag.", true)
+ }
} catch (e: Exception) {
- assertTrue("Should not have an exception while translating with a longer language tag.", false)
+ if (sessionRule.env.isAutomation) {
+ assertTrue("Expect an exception while translating in automation.", true)
+ }
}
}
@@ -244,9 +261,14 @@ class TranslationsTest : BaseSessionTest() {
val translate = sessionRule.session.sessionTranslation!!.translate("es", "en", null)
try {
sessionRule.waitForResult(translate)
- assertTrue("Should be able to translate.", true)
+ // When testing from AS, this path is possible.
+ if (!sessionRule.env.isAutomation) {
+ assertTrue("Should be able to translate.", true)
+ }
} catch (e: Exception) {
- assertTrue("Should not have an exception.", false)
+ if (sessionRule.env.isAutomation) {
+ assertTrue("Expect an exception while translating in automation.", true)
+ }
}
}
@@ -443,10 +465,10 @@ class TranslationsTest : BaseSessionTest() {
@Test
fun testGetLanguageSettings() {
// Note: Test endpoint is using a mocked response and doesn't reflect actual prefs
- var languageSettings: Map<String, String> =
+ val languageSettings: Map<String, String> =
sessionRule.waitForResult(TranslationsController.RuntimeTranslation.getLanguageSettings())
- var frLanguageSetting = sessionRule.waitForResult(TranslationsController.RuntimeTranslation.getLanguageSetting("fr"))
+ val frLanguageSetting = sessionRule.waitForResult(TranslationsController.RuntimeTranslation.getLanguageSetting("fr"))
if (sessionRule.env.isAutomation) {
assertTrue("FR was correctly set to ALWAYS via full query.", languageSettings["fr"] == ALWAYS)
@@ -621,4 +643,73 @@ class TranslationsTest : BaseSessionTest() {
}
}
}
+
+ @Test
+ fun hasVisibleChangeTest() {
+ mainSession.loadTestPath(TRANSLATIONS_ES)
+ mainSession.waitForPageStop()
+
+ val handled = GeckoResult<Void>()
+ var delegateCalled = 0
+ sessionRule.delegateUntilTestEnd(object : Delegate {
+ @AssertCalled(count = 2)
+ override fun onTranslationStateChange(
+ session: GeckoSession,
+ translationState: TranslationState?,
+ ) {
+ delegateCalled++
+
+ if (delegateCalled == 1) {
+ assertFalse("Initially not visibly changed.", translationState!!.hasVisibleChange)
+ }
+
+ if (delegateCalled == 2) {
+ assertTrue("After a translation, the DOM should be visibly changed.", translationState!!.hasVisibleChange)
+ handled.complete(null)
+ }
+ }
+ })
+ val notTranslated = JSONObject(
+ """
+ {
+ "actor":{
+ "languageState":{
+ "detectedLanguages": {
+ "userLangTag": "en",
+ "isDocLangTagSupported": true,
+ "docLangTag": "es"
+ },
+ "requestedTranslationPair": null,
+ "hasVisibleChange": false,
+ "error": null,
+ "isEngineReady": false
+ }
+ }
+ }
+ """.trimIndent(),
+ )
+ mainSession.triggerLanguageStateChange(notTranslated)
+
+ val translated = JSONObject(
+ """
+ {
+ "actor":{
+ "languageState":{
+ "detectedLanguages": {
+ "userLangTag": "en",
+ "isDocLangTagSupported": true,
+ "docLangTag": "es"
+ },
+ "requestedTranslationPair": {"fromLanguage" : "es" , "toLanguage" : "en"},
+ "hasVisibleChange": true,
+ "error": null,
+ "isEngineReady": true
+ }
+ }
+ }
+ """.trimIndent(),
+ )
+ mainSession.triggerLanguageStateChange(translated)
+ sessionRule.waitForResult(handled)
+ }
}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExtensionTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExtensionTest.kt
index fa5caa8693..413ca7e2f6 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExtensionTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExtensionTest.kt
@@ -482,6 +482,101 @@ class WebExtensionTest : BaseSessionTest() {
sessionRule.waitForResult(controller.uninstall(extension))
}
+ @Test
+ fun optionalOriginsNormalized() {
+ // For mv3 extensions the host_permissions are being granted automatically at install time
+ // but this test needs them to not be granted yet and so we explicitly opt-out in this test.
+ sessionRule.setPrefsUntilTestEnd(
+ mapOf(
+ "extensions.originControls.grantByDefault" to false,
+ ),
+ )
+
+ var extension = sessionRule.waitForResult(
+ controller.ensureBuiltIn(
+ "resource://android/assets/web_extensions/optional-permission-all-urls/",
+ "optional-permission-all-urls@example.com",
+ ),
+ )
+
+ assertEquals("optional-permission-all-urls@example.com", extension.id)
+
+ var grantedOptionalOrigins = extension.metaData.grantedOptionalOrigins
+ assertArrayEquals(
+ "grantedOptionalPermissions must be initially empty",
+ arrayOf(),
+ grantedOptionalOrigins,
+ )
+
+ extension = sessionRule.waitForResult(
+ controller.addOptionalPermissions(
+ extension.id,
+ arrayOf(),
+ arrayOf("http://*/", "https://*/", "file://*/*"),
+ ),
+ )
+
+ grantedOptionalOrigins = extension.metaData.grantedOptionalOrigins
+
+ assertArrayEquals(
+ "grantedOptionalPermissions must be [http://*/*, https://*/*, file://*/*]",
+ arrayOf("http://*/*", "https://*/*", "file://*/*"),
+ grantedOptionalOrigins,
+ )
+
+ sessionRule.waitForResult(controller.uninstall(extension))
+ }
+
+ @Test
+ fun onOptionalPermissionsChanged() {
+ var extension = sessionRule.waitForResult(
+ controller.ensureBuiltIn(
+ "resource://android/assets/web_extensions/optional-permission-request/",
+ "optional-permission-request@example.com",
+ ),
+ )
+
+ assertEquals("optional-permission-request@example.com", extension.id)
+
+ var grantedOptionalPermissions = extension.metaData.grantedOptionalPermissions
+ var grantedOptionalOrigins = extension.metaData.grantedOptionalOrigins
+
+ assertThat(
+ "grantedOptionalPermissions must be 0.",
+ grantedOptionalPermissions.size,
+ equalTo(0),
+ )
+ assertThat("grantedOptionalOrigins must be 0.", grantedOptionalOrigins.size, equalTo(0))
+
+ sessionRule.delegateDuringNextWait(object : WebExtensionController.AddonManagerDelegate {
+ @AssertCalled(count = 1)
+ override fun onOptionalPermissionsChanged(updatedExtension: WebExtension) {
+ grantedOptionalPermissions = updatedExtension.metaData.grantedOptionalPermissions
+ grantedOptionalOrigins = updatedExtension.metaData.grantedOptionalOrigins
+ assertNull(updatedExtension)
+ assertArrayEquals(
+ "grantedOptionalPermissions must be [activeTab, geolocation].",
+ arrayOf("activeTab", "geolocation"),
+ grantedOptionalPermissions,
+ )
+ assertArrayEquals(
+ "grantedOptionalPermissions must be [*://example.com/*].",
+ arrayOf("*://example.com/*"),
+ grantedOptionalOrigins,
+ )
+ }
+ })
+
+ extension = sessionRule.waitForResult(
+ controller.addOptionalPermissions(
+ extension.id,
+ arrayOf("activeTab", "geolocation"),
+ arrayOf("*://example.com/*"),
+ ),
+ )
+ sessionRule.waitForResult(controller.uninstall(extension))
+ }
+
private fun assertBodyBorderEqualTo(expected: String) {
val color = mainSession.evaluateJS("document.body.style.borderColor")
assertThat(
@@ -2763,7 +2858,7 @@ class WebExtensionTest : BaseSessionTest() {
"extensions.install.requireBuiltInCerts" to false,
"extensions.update.requireBuiltInCerts" to false,
"extensions.getAddons.cache.enabled" to true,
- "extensions.getAddons.cache.lastUpdate" to 0,
+ "extensions.getAddons.cache.lastUpdate" to 1,
),
)
mainSession.loadUri("https://example.com")
@@ -3721,11 +3816,6 @@ class WebExtensionTest : BaseSessionTest() {
mainSession.evaluateJS("typeof navigator.mozAddonManager") as String,
equalTo("object"),
)
- assertThat(
- "mozAddonManager.abuseReportPanelEnabled should be false",
- mainSession.evaluateJS("navigator.mozAddonManager.abuseReportPanelEnabled") as Boolean,
- equalTo(false),
- )
// Install an add-on, then assert results got from `mozAddonManager.getAddonByID()`.
var addonId = ""
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
index 727f403931..7c95233552 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
@@ -89,7 +89,6 @@ import org.mozilla.geckoview.GeckoSession.TextInputDelegate;
import org.mozilla.geckoview.GeckoSessionSettings;
import org.mozilla.geckoview.MediaSession;
import org.mozilla.geckoview.OrientationController;
-import org.mozilla.geckoview.RuntimeTelemetry;
import org.mozilla.geckoview.SessionTextInput;
import org.mozilla.geckoview.TranslationsController;
import org.mozilla.geckoview.WebExtension;
@@ -988,10 +987,6 @@ public class GeckoSessionTestRule implements TestRule {
return RuntimeCreator.getRuntime();
}
- public void setTelemetryDelegate(final RuntimeTelemetry.Delegate delegate) {
- RuntimeCreator.setTelemetryDelegate(delegate);
- }
-
/** Sets an experiment delegate on the runtime creator. */
public void setExperimentDelegate(final ExperimentDelegate delegate) {
RuntimeCreator.setExperimentDelegate(delegate);
@@ -1463,7 +1458,6 @@ public class GeckoSessionTestRule implements TestRule {
mLastWaitStart = 0;
mLastWaitEnd = 0;
mTimeoutMillis = 0;
- RuntimeCreator.setTelemetryDelegate(null);
RuntimeCreator.setExperimentDelegate(null);
}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/RuntimeCreator.java b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/RuntimeCreator.java
index 7eda360459..db18c06a9d 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/RuntimeCreator.java
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/RuntimeCreator.java
@@ -18,7 +18,6 @@ import org.mozilla.geckoview.ExperimentDelegate;
import org.mozilla.geckoview.GeckoResult;
import org.mozilla.geckoview.GeckoRuntime;
import org.mozilla.geckoview.GeckoRuntimeSettings;
-import org.mozilla.geckoview.RuntimeTelemetry;
import org.mozilla.geckoview.WebExtension;
import org.mozilla.geckoview.test.TestCrashHandler;
@@ -34,40 +33,6 @@ public class RuntimeCreator {
public static AtomicInteger sTestSupport = new AtomicInteger(0);
public static WebExtension sTestSupportExtension;
- // The RuntimeTelemetry.Delegate can only be set when creating the RuntimeCreator, to
- // let tests set their own Delegate we need to create a proxy here.
- public static class RuntimeTelemetryDelegate implements RuntimeTelemetry.Delegate {
- public RuntimeTelemetry.Delegate delegate = null;
-
- @Override
- public void onHistogram(@NonNull final RuntimeTelemetry.Histogram metric) {
- if (delegate != null) {
- delegate.onHistogram(metric);
- }
- }
-
- @Override
- public void onBooleanScalar(@NonNull final RuntimeTelemetry.Metric<Boolean> metric) {
- if (delegate != null) {
- delegate.onBooleanScalar(metric);
- }
- }
-
- @Override
- public void onStringScalar(@NonNull final RuntimeTelemetry.Metric<String> metric) {
- if (delegate != null) {
- delegate.onStringScalar(metric);
- }
- }
-
- @Override
- public void onLongScalar(@NonNull final RuntimeTelemetry.Metric<Long> metric) {
- if (delegate != null) {
- delegate.onLongScalar(metric);
- }
- }
- }
-
/**
* The ExperimentDelegate can only be set when starting the RuntimeCreator, so for testing we are
* setting up a proxy here
@@ -110,9 +75,6 @@ public class RuntimeCreator {
}
}
- public static final RuntimeTelemetryDelegate sRuntimeTelemetryProxy =
- new RuntimeTelemetryDelegate();
-
public static RuntimeExperimentDelegate sRuntimeExperimentDelegateProxy =
new RuntimeExperimentDelegate();
private static WebExtension.Port sBackgroundPort;
@@ -163,17 +125,6 @@ public class RuntimeCreator {
}
/**
- * Set the {@link RuntimeTelemetry.Delegate} instance for this test. Application code can only
- * register this delegate when the {@link GeckoRuntime} is created, so we need to proxy it for
- * test code.
- *
- * @param delegate the {@link RuntimeTelemetry.Delegate} for this test run.
- */
- public static void setTelemetryDelegate(final RuntimeTelemetry.Delegate delegate) {
- sRuntimeTelemetryProxy.delegate = delegate;
- }
-
- /**
* Set the {@link ExperimentDelegate} instance for this test. Application code can only register
* this delegate when the {@link GeckoRuntime} is created, so we need to proxy it for test code.
*
@@ -216,7 +167,6 @@ public class RuntimeCreator {
.remoteDebuggingEnabled(true)
.consoleOutput(true)
.crashHandler(TestCrashHandler.class)
- .telemetryDelegate(sRuntimeTelemetryProxy)
.experimentDelegate(sRuntimeExperimentDelegateProxy)
.build();
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoDisplay.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoDisplay.java
index 1fc34cb8bb..e0c16d66cc 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoDisplay.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoDisplay.java
@@ -453,13 +453,15 @@ public class GeckoDisplay {
* <p>This function must be called on the UI thread.
*
* @return A {@link GeckoResult} that completes with a {@link Bitmap} containing the pixels and
- * size information of the requested portion of the visible web page.
+ * size information of the requested portion of the visible web page, or returns a failure
+ * {@link GeckoResult} including the reason why in an {@link Exception}
*/
@UiThread
public @NonNull GeckoResult<Bitmap> capture() {
ThreadUtils.assertOnUiThread();
if (!mSession.isCompositorReady()) {
- throw new IllegalStateException("Compositor must be ready before pixels can be captured");
+ return GeckoResult.fromException(
+ new IllegalStateException("Compositor must be ready before pixels can be captured"));
}
final GeckoResult<Bitmap> result = new GeckoResult<>();
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoEditable.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoEditable.java
index 8750f344a8..ccd513f6bd 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoEditable.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoEditable.java
@@ -1893,7 +1893,7 @@ import org.mozilla.geckoview.SessionTextInput.EditableListener.IMEState;
outAttrs.imeOptions = EditorInfo.IME_ACTION_GO;
} else if (actionHint.equals("done")) {
outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
- } else if (actionHint.equals("next") || actionHint.equals("maybenext")) {
+ } else if (actionHint.equals("next")) {
outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT;
} else if (actionHint.equals("previous")) {
outAttrs.imeOptions = EditorInfo.IME_ACTION_PREVIOUS;
@@ -1901,6 +1901,9 @@ import org.mozilla.geckoview.SessionTextInput.EditableListener.IMEState;
outAttrs.imeOptions = EditorInfo.IME_ACTION_SEARCH;
} else if (actionHint.equals("send")) {
outAttrs.imeOptions = EditorInfo.IME_ACTION_SEND;
+ } else if (actionHint.equals("maybenext")) {
+ // this should be low priority as "maybenext" is internal type
+ outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT;
} else if (actionHint.length() > 0) {
if (DEBUG) Log.w(LOGTAG, "Unexpected actionHint=\"" + actionHint + "\"");
outAttrs.actionLabel = actionHint;
@@ -2568,6 +2571,7 @@ import org.mozilla.geckoview.SessionTextInput.EditableListener.IMEState;
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
case KeyEvent.KEYCODE_BACK:
+ case KeyEvent.KEYCODE_FORWARD:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_SEARCH:
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
index 0a80b02b04..482fa32f39 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
@@ -457,21 +457,6 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
}
/**
- * Add a {@link RuntimeTelemetry.Delegate} instance to this GeckoRuntime. This delegate can be
- * used by the app to receive streaming telemetry data from GeckoView.
- *
- * @param delegate the delegate that will handle telemetry
- * @return The builder instance.
- */
- @Deprecated
- @DeprecationSchedule(id = "geckoview-gvst", version = 127)
- public @NonNull Builder telemetryDelegate(final @NonNull RuntimeTelemetry.Delegate delegate) {
- getSettings().mTelemetryProxy = new RuntimeTelemetry.Proxy(delegate);
- getSettings().mTelemetryEnabled.set(true);
- return this;
- }
-
- /**
* Set the {@link ExperimentDelegate} instance on this runtime, if any. This delegate is used to
* send and receive experiment information from Nimbus.
*
@@ -663,7 +648,6 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
/* package */ int mScreenHeightOverride;
/* package */ Class<? extends Service> mCrashHandler;
/* package */ String[] mRequestedLocales;
- /* package */ RuntimeTelemetry.Proxy mTelemetryProxy;
/* package */ ExperimentDelegate mExperimentDelegate;
/**
@@ -674,10 +658,6 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
/* package */ void attachTo(final @NonNull GeckoRuntime runtime) {
mRuntime = runtime;
commit();
-
- if (mTelemetryProxy != null) {
- mTelemetryProxy.attach();
- }
}
@Override // RuntimeSettings
@@ -719,7 +699,6 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
mCrashHandler = settings.mCrashHandler;
mRequestedLocales = settings.mRequestedLocales;
mConfigFilePath = settings.mConfigFilePath;
- mTelemetryProxy = settings.mTelemetryProxy;
mExperimentDelegate = settings.mExperimentDelegate;
}
@@ -1368,11 +1347,6 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
return this;
}
- @SuppressWarnings("checkstyle:javadocmethod")
- public @Nullable RuntimeTelemetry.Delegate getTelemetryDelegate() {
- return mTelemetryProxy.getDelegate();
- }
-
/**
* Get the {@link ExperimentDelegate} instance set on this runtime, if any,
*
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
index 85b3abf9a9..ccf1e8520e 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
@@ -2448,6 +2448,7 @@ public class GeckoSession {
@IntDef(
flag = true,
value = {
+ FINDER_FIND_FORWARD,
FINDER_FIND_BACKWARDS,
FINDER_FIND_LINKS_ONLY,
FINDER_FIND_MATCH_CASE,
@@ -2455,6 +2456,9 @@ public class GeckoSession {
})
public @interface FinderFindFlags {}
+ /** Go forward when finding the next match. */
+ public static final int FINDER_FIND_FORWARD = 0;
+
/** Go backwards when finding the next match. */
public static final int FINDER_FIND_BACKWARDS = 1;
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
index 14f6b14c47..4dc23bc519 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
@@ -331,11 +331,11 @@ public final class GeckoSessionSettings implements Parcelable {
new Key<Boolean>("fullAccessibilityTree", /* initOnly */ false, /* values */ null);
/**
- * Key to specify if this GeckoSession is a Popup or not. Popup sessions can paint over other
- * sessions and are not exposed to the tabs WebExtension API.
+ * Key to specify if this GeckoSession is a Extension Popup or not. Popup sessions can paint over
+ * other sessions and are not exposed to the tabs WebExtension API.
*/
- private static final Key<Boolean> IS_POPUP =
- new Key<Boolean>("isPopup", /* initOnly */ false, /* values */ null);
+ private static final Key<Boolean> IS_EXTENSION_POPUP =
+ new Key<Boolean>("isExtensionPopup", /* initOnly */ false, /* values */ null);
/** Internal Gecko key to specify the session context ID. Derived from `UNSAFE_CONTEXT_ID`. */
private static final Key<String> CONTEXT_ID =
@@ -375,7 +375,7 @@ public final class GeckoSessionSettings implements Parcelable {
mBundle.putBoolean(SUSPEND_MEDIA_WHEN_INACTIVE.name, false);
mBundle.putBoolean(ALLOW_JAVASCRIPT.name, true);
mBundle.putBoolean(FULL_ACCESSIBILITY_TREE.name, false);
- mBundle.putBoolean(IS_POPUP.name, false);
+ mBundle.putBoolean(IS_EXTENSION_POPUP.name, false);
mBundle.putInt(USER_AGENT_MODE.name, USER_AGENT_MODE_MOBILE);
mBundle.putString(USER_AGENT_OVERRIDE.name, null);
mBundle.putInt(VIEWPORT_MODE.name, VIEWPORT_MODE_MOBILE);
@@ -430,8 +430,8 @@ public final class GeckoSessionSettings implements Parcelable {
setBoolean(FULL_ACCESSIBILITY_TREE, value);
}
- /* package */ void setIsPopup(final boolean value) {
- setBoolean(IS_POPUP, value);
+ /* package */ void setIsExtensionPopup(final boolean value) {
+ setBoolean(IS_EXTENSION_POPUP, value);
}
private void setBoolean(final Key<Boolean> key, final boolean value) {
@@ -498,8 +498,8 @@ public final class GeckoSessionSettings implements Parcelable {
return getBoolean(FULL_ACCESSIBILITY_TREE);
}
- /* package */ boolean getIsPopup() {
- return getBoolean(IS_POPUP);
+ /* package */ boolean getIsExtensionPopup() {
+ return getBoolean(IS_EXTENSION_POPUP);
}
private boolean getBoolean(final Key<Boolean> key) {
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
index 2271ff71f7..8b31862524 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
@@ -22,6 +22,8 @@ import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.os.Handler;
import android.print.PrintDocumentAdapter;
@@ -269,6 +271,14 @@ public class GeckoView extends FrameLayout implements GeckoDisplay.NewSurfacePro
// descendants to affect the way LayerView retains its focus.
setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
+ // When GeckoView.requestFocus() is called with hardware keyboard, the focused state color
+ // might be applied on this view. But we don't want to apply it as default.
+ final StateListDrawable drawable = new StateListDrawable();
+ drawable.addState(
+ new int[] {android.R.attr.state_focused, -android.R.attr.state_focused},
+ new ColorDrawable(Color.WHITE));
+ setBackground(drawable);
+
// This will stop PropertyAnimator from creating a drawing cache (i.e. a
// bitmap) from a SurfaceView, which is just not possible (the bitmap will be
// transparent).
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java
deleted file mode 100644
index 1fad0cb17e..0000000000
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * vim: ts=4 sw=4 expandtab:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.geckoview;
-
-import androidx.annotation.AnyThread;
-import androidx.annotation.NonNull;
-import org.mozilla.gecko.GeckoThread;
-import org.mozilla.gecko.annotation.WrapForJNI;
-import org.mozilla.gecko.mozglue.JNIObject;
-
-/** The telemetry API gives access to telemetry data of the Gecko runtime. */
-public final class RuntimeTelemetry {
- protected RuntimeTelemetry() {}
-
- /**
- * The runtime telemetry metric object.
- *
- * @param <T> type of the underlying metric sample
- */
- public static class Metric<T> {
- /** The runtime metric name. */
- public final @NonNull String name;
-
- /** The metric values. */
- public final @NonNull T value;
-
- /* package */ Metric(final String name, final T value) {
- this.name = name;
- this.value = value;
- }
-
- @Override
- public String toString() {
- return "name: " + name + ", value: " + value;
- }
-
- // For testing
- protected Metric() {
- name = null;
- value = null;
- }
- }
-
- /** The Histogram telemetry metric object. */
- public static class Histogram extends Metric<long[]> {
- /** Whether or not this is a Categorical Histogram. */
- public final boolean isCategorical;
-
- /* package */ Histogram(final boolean isCategorical, final String name, final long[] value) {
- super(name, value);
- this.isCategorical = isCategorical;
- }
-
- // For testing
- protected Histogram() {
- super(null, null);
- isCategorical = false;
- }
- }
-
- /**
- * The runtime telemetry delegate. Implement this if you want to receive runtime (Gecko) telemetry
- * and attach it via {@link GeckoRuntimeSettings.Builder#telemetryDelegate}.
- */
- public interface Delegate {
- /**
- * A runtime telemetry histogram metric has been received.
- *
- * @param metric The runtime metric details.
- */
- @AnyThread
- default void onHistogram(final @NonNull Histogram metric) {}
-
- /**
- * A runtime telemetry boolean scalar has been received.
- *
- * @param metric The runtime metric details.
- */
- @AnyThread
- default void onBooleanScalar(final @NonNull Metric<Boolean> metric) {}
-
- /**
- * A runtime telemetry long scalar has been received.
- *
- * @param metric The runtime metric details.
- */
- @AnyThread
- default void onLongScalar(final @NonNull Metric<Long> metric) {}
-
- /**
- * A runtime telemetry string scalar has been received.
- *
- * @param metric The runtime metric details.
- */
- @AnyThread
- default void onStringScalar(final @NonNull Metric<String> metric) {}
- }
-
- // The proxy connects to telemetry core and forwards telemetry events
- // to the attached delegate.
- /* package */ static final class Proxy extends JNIObject {
- private final Delegate mDelegate;
-
- public Proxy(final @NonNull Delegate delegate) {
- mDelegate = delegate;
- }
-
- // Attach to current runtime.
- // We might have different mechanics of attaching to specific runtimes
- // in future, for which case we should split the delegate assignment in
- // the setup phase from the attaching.
- public void attach() {
- if (GeckoThread.isRunning()) {
- registerDelegateProxy(this);
- } else {
- GeckoThread.queueNativeCall(Proxy.class, "registerDelegateProxy", Proxy.class, this);
- }
- }
-
- public @NonNull Delegate getDelegate() {
- return mDelegate;
- }
-
- @WrapForJNI(dispatchTo = "gecko")
- private static native void registerDelegateProxy(Proxy proxy);
-
- @WrapForJNI(calledFrom = "gecko")
- /* package */ void dispatchHistogram(
- final boolean isCategorical, final String name, final long[] values) {
- if (mDelegate == null) {
- // TODO throw?
- return;
- }
- mDelegate.onHistogram(new Histogram(isCategorical, name, values));
- }
-
- @WrapForJNI(calledFrom = "gecko")
- /* package */ void dispatchStringScalar(final String name, final String value) {
- if (mDelegate == null) {
- return;
- }
- mDelegate.onStringScalar(new Metric<>(name, value));
- }
-
- @WrapForJNI(calledFrom = "gecko")
- /* package */ void dispatchBooleanScalar(final String name, final boolean value) {
- if (mDelegate == null) {
- return;
- }
- mDelegate.onBooleanScalar(new Metric<>(name, value));
- }
-
- @WrapForJNI(calledFrom = "gecko")
- /* package */ void dispatchLongScalar(final String name, final long value) {
- if (mDelegate == null) {
- return;
- }
- mDelegate.onLongScalar(new Metric<>(name, value));
- }
-
- @Override // JNIObject
- protected void disposeNative() {
- // We don't hold native references.
- throw new UnsupportedOperationException();
- }
- }
-}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java
index 1ce4b41659..e88976a447 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java
@@ -1,4 +1,6 @@
-/* License, v. 2.0. If a copy of the MPL was not distributed with this
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.geckoview;
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionFinder.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionFinder.java
index 2ed0b1a6c3..b245a39f1e 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionFinder.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionFinder.java
@@ -27,6 +27,7 @@ public final class SessionFinder {
private static final List<Pair<Integer, String>> sFlagNames =
Arrays.asList(
+ new Pair<>(GeckoSession.FINDER_FIND_FORWARD, "forward"),
new Pair<>(GeckoSession.FINDER_FIND_BACKWARDS, "backwards"),
new Pair<>(GeckoSession.FINDER_FIND_LINKS_ONLY, "linksOnly"),
new Pair<>(GeckoSession.FINDER_FIND_MATCH_CASE, "matchCase"),
@@ -70,7 +71,8 @@ public final class SessionFinder {
* previous search string.
*
* @param searchString String to search, or null to find again using the previous string.
- * @param flags Flags for performing the search; either 0 or a combination of {@link
+ * @param flags Flags for performing the search; either FINDER_FIND_FORWARD {@link
+ * GeckoSession#FINDER_FIND_FORWARD} or a combination of {@link
* GeckoSession#FINDER_FIND_BACKWARDS FINDER_FIND_*} constants.
* @return Result of the search operation as a {@link GeckoResult} object.
* @see #clear
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TranslationsController.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TranslationsController.java
index 37e5e7139a..256877532b 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TranslationsController.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TranslationsController.java
@@ -1081,14 +1081,20 @@ public class TranslationsController {
/** If the translation engine is ready for use or will need to be loaded. */
public final @NonNull Boolean isEngineReady;
+ /** If the DOM has began visibly changing to the translated text. */
+ public final @NonNull Boolean hasVisibleChange;
+
/**
- * Translation State constructor.
+ * This constructor is deprecated, please use the [TranslationState] with [hasVisibleChange]
+ * parameter. This constructor will be removed in bug 1895275. Translation State constructor.
*
* @param requestedTranslationPair the language pair to translate
* @param error if an error occurred
* @param detectedLanguages detected language
* @param isEngineReady if the engine is ready for translations
*/
+ @Deprecated
+ @DeprecationSchedule(version = 130, id = "translation-state-deprecated-constructor")
public TranslationState(
final @Nullable TranslationPair requestedTranslationPair,
final @Nullable String error,
@@ -1098,6 +1104,29 @@ public class TranslationsController {
this.error = error;
this.detectedLanguages = detectedLanguages;
this.isEngineReady = isEngineReady;
+ this.hasVisibleChange = false;
+ }
+
+ /**
+ * Translation State constructor.
+ *
+ * @param requestedTranslationPair the language pair to translate
+ * @param error if an error occurred
+ * @param detectedLanguages detected language
+ * @param isEngineReady if the engine is ready for translations
+ * @param hasVisibleChange if the DOM has began to visibly change to translated text
+ */
+ public TranslationState(
+ final @Nullable TranslationPair requestedTranslationPair,
+ final @Nullable String error,
+ final @Nullable DetectedLanguages detectedLanguages,
+ final @NonNull Boolean isEngineReady,
+ final @NonNull Boolean hasVisibleChange) {
+ this.requestedTranslationPair = requestedTranslationPair;
+ this.error = error;
+ this.detectedLanguages = detectedLanguages;
+ this.isEngineReady = isEngineReady;
+ this.hasVisibleChange = hasVisibleChange;
}
@Override
@@ -1112,6 +1141,8 @@ public class TranslationsController {
+ detectedLanguages
+ ", isEngineReady="
+ isEngineReady
+ + ", hasVisibleChange="
+ + hasVisibleChange
+ '}';
}
@@ -1130,7 +1161,8 @@ public class TranslationsController {
TranslationPair.fromBundle(bundle.getBundle("requestedTranslationPair")),
bundle.getString("error"),
DetectedLanguages.fromBundle(bundle.getBundle("detectedLanguages")),
- bundle.getBoolean("isEngineReady", false));
+ bundle.getBoolean("isEngineReady", false),
+ bundle.getBoolean("hasVisibleChange", false));
}
}
@@ -1168,7 +1200,7 @@ public class TranslationsController {
final GeckoBundle data = message.getBundle("data");
final TranslationState translationState = TranslationState.fromBundle(data);
if (DEBUG) {
- Log.d(LOGTAG, "received translation state: " + translationState);
+ Log.d(LOGTAG, "Received translation state: " + translationState);
}
delegate.onTranslationStateChange(mSession, translationState);
if (translationState != null
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java
index bf5d431cf1..53d57b126a 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java
@@ -1442,7 +1442,7 @@ public class WebExtension {
return;
}
- session.getSettings().setIsPopup(true);
+ session.getSettings().setIsExtensionPopup(true);
session.loadUri(popupUri);
});
}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java
index 07e848b079..889cd91895 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java
@@ -336,6 +336,14 @@ public class WebExtensionController {
default void onDisabling(@NonNull WebExtension extension) {}
/**
+ * Called whenever optional permissions of an extension have changed.
+ *
+ * @param extension The {@link WebExtension} that has optional permissions changed.
+ */
+ @UiThread
+ default void onOptionalPermissionsChanged(@NonNull WebExtension extension) {}
+
+ /**
* Called whenever an extension has been disabled.
*
* @param extension The {@link WebExtension} that is being disabled.
@@ -489,6 +497,7 @@ public class WebExtensionController {
EventDispatcher.getInstance()
.unregisterUiThreadListener(
mInternals,
+ "GeckoView:WebExtension:OnOptionalPermissionsChanged",
"GeckoView:WebExtension:OnDisabling",
"GeckoView:WebExtension:OnDisabled",
"GeckoView:WebExtension:OnEnabling",
@@ -503,6 +512,7 @@ public class WebExtensionController {
EventDispatcher.getInstance()
.registerUiThreadListener(
mInternals,
+ "GeckoView:WebExtension:OnOptionalPermissionsChanged",
"GeckoView:WebExtension:OnDisabling",
"GeckoView:WebExtension:OnDisabled",
"GeckoView:WebExtension:OnEnabling",
@@ -1021,6 +1031,9 @@ public class WebExtensionController {
} else if ("GeckoView:WebExtension:OnDisabling".equals(event)) {
onDisabling(bundle);
return;
+ } else if ("GeckoView:WebExtension:OnOptionalPermissionsChanged".equals(event)) {
+ onOptionalPermissionsChanged(bundle);
+ return;
} else if ("GeckoView:WebExtension:OnDisabled".equals(event)) {
onDisabled(bundle);
return;
@@ -1265,6 +1278,17 @@ public class WebExtensionController {
mAddonManagerDelegate.onDisabling(extension);
}
+ private void onOptionalPermissionsChanged(final GeckoBundle bundle) {
+ if (mAddonManagerDelegate == null) {
+ Log.e(LOGTAG, "no AddonManager delegate registered");
+ return;
+ }
+
+ final GeckoBundle extensionBundle = bundle.getBundle("extension");
+ final WebExtension extension = new WebExtension(mDelegateControllerProvider, extensionBundle);
+ mAddonManagerDelegate.onOptionalPermissionsChanged(extension);
+ }
+
private void onDisabled(final GeckoBundle bundle) {
if (mAddonManagerDelegate == null) {
Log.e(LOGTAG, "no AddonManager delegate registered");
@@ -1525,7 +1549,7 @@ public class WebExtensionController {
if (delegate != null) {
result = delegate.onCloseTab(extension, message.session);
} else {
- result = GeckoResult.fromValue(AllowOrDeny.DENY);
+ result = GeckoResult.deny();
}
message.callback.resolveTo(
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
index e2df6df21b..a2d30d25ef 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
@@ -13,6 +13,17 @@ exclude: true
⚠️ breaking change and deprecation notices
+## v127
+- ⚠️ Removed deprecated [`RuntimeTelemetry`][125.5], [`GeckoRuntimeSettings.getTelemetryDelegate`][125.6] and [`GeckoRuntimeSettings.telemetryDelegate`][125.7].
+- Added [FINDER_FIND_FORWARD][127.1]
+- Added [`WebExtensionController.AddonManagerDelegate.onOptionalPermissionsChanged`][127.2] ([bug 1892302]({{bugzilla}}1892302).
+- Added a new [`TranslationState`][127.3] constructor to add `hasVisibleChange` and deprecated the prior [`TranslationsState`][127.4] constructor to be removed in v130.
+
+[127.1]: {{javadoc_uri}}/GeckoSession.html#FINDER_FIND_FORWARD
+[127.2]: {{javadoc_uri}}/WebExtensionController.AddonManagerDelegate.html#onOptionalPermissionsChanged
+[127.3]: {{javadoc_uri}}/TranslationsController.SessionTranslation.TranslationState.html#%3Cinit%3E(org.mozilla.geckoview.TranslationsController.SessionTranslation.TranslationPair,java.lang.String,org.mozilla.geckoview.TranslationsController.SessionTranslation.DetectedLanguages,java.lang.Boolean,java.lang.Boolean)
+[127.4]: {{javadoc_uri}}/TranslationsController.SessionTranslation.TranslationState.html#<init>(org.mozilla.geckoview.TranslationsController.SessionTranslation.TranslationPair,java.lang.String,org.mozilla.geckoview.TranslationsController.SessionTranslation.DetectedLanguages,java.lang.Boolean)
+
## v125
- ⚠️ Deprecated [`GeckoSession.NavigationDelegate.onLocationChange`][125.1], to be removed in v127.
([bug 1837601]({{bugzilla}}1837601))
@@ -1547,4 +1558,4 @@ to allow adding gecko profiler markers.
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport(android.content.Context,android.os.Bundle,java.lang.String)
[65.25]: {{javadoc_uri}}/GeckoResult.html
-[api-version]: 2c319e9f18adb4178ce09d71088a173b56d1a694
+[api-version]: 0b9d0f241805fab7e71d3d745170a237f6ac113d