diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
commit | 8dd16259287f58f9273002717ec4d27e97127719 (patch) | |
tree | 3863e62a53829a84037444beab3abd4ed9dfc7d0 /mobile/android/android-components/components/browser/engine-gecko | |
parent | Releasing progress-linux version 126.0.1-1~progress7.99u1. (diff) | |
download | firefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz firefox-8dd16259287f58f9273002717ec4d27e97127719.zip |
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/android-components/components/browser/engine-gecko')
10 files changed, 75 insertions, 66 deletions
diff --git a/mobile/android/android-components/components/browser/engine-gecko/build.gradle b/mobile/android/android-components/components/browser/engine-gecko/build.gradle index 4e5c2fda65..776c083ee9 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/build.gradle +++ b/mobile/android/android-components/components/browser/engine-gecko/build.gradle @@ -76,8 +76,9 @@ dependencies { api getGeckoViewDependency() } + implementation ComponentsDependencies.androidx_core_ktx implementation ComponentsDependencies.androidx_paging - implementation ComponentsDependencies.androidx_data_store_preferences + implementation ComponentsDependencies.androidx_datastore_preferences implementation ComponentsDependencies.androidx_lifecycle_livedata testImplementation ComponentsDependencies.androidx_test_core diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt index 92e6074a61..f5f1012448 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt @@ -426,6 +426,10 @@ class GeckoEngine( exception as WebExtensionInstallException, ) } + + override fun onOptionalPermissionsChanged(extension: org.mozilla.geckoview.WebExtension) { + webExtensionDelegate.onOptionalPermissionsChanged(GeckoWebExtension(extension, runtime)) + } } val extensionProcessDelegate = object : WebExtensionController.ExtensionProcessDelegate { diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt index e6907c6dde..dbf7b2d54f 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt @@ -4,7 +4,6 @@ package mozilla.components.browser.engine.gecko -import android.annotation.SuppressLint import android.net.Uri import android.os.Build import android.view.WindowManager @@ -58,6 +57,7 @@ import mozilla.components.support.base.facts.Action import mozilla.components.support.base.facts.Fact import mozilla.components.support.base.facts.collect import mozilla.components.support.base.log.logger.Logger +import mozilla.components.support.ktx.kotlin.decode import mozilla.components.support.ktx.kotlin.isEmail import mozilla.components.support.ktx.kotlin.isExtensionUrl import mozilla.components.support.ktx.kotlin.isGeoLocation @@ -557,9 +557,8 @@ class GeckoEngineSession( /** * See [EngineSession.findNext] */ - @SuppressLint("WrongConstant") // FinderFindFlags annotation doesn't include a 0 value. override fun findNext(forward: Boolean) { - val findFlags = if (forward) 0 else GeckoSession.FINDER_FIND_BACKWARDS + val findFlags = if (forward) GeckoSession.FINDER_FIND_FORWARD else GeckoSession.FINDER_FIND_BACKWARDS geckoSession.finder.find(null, findFlags).then { result: GeckoSession.FinderResult? -> result?.let { val activeMatchOrdinal = if (it.current > 0) it.current - 1 else it.current @@ -1159,9 +1158,9 @@ class GeckoEngineSession( return when { maybeInterceptRequest(request, false) != null -> - GeckoResult.fromValue(AllowOrDeny.DENY) + GeckoResult.deny() request.target == NavigationDelegate.TARGET_WINDOW_NEW -> - GeckoResult.fromValue(AllowOrDeny.ALLOW) + GeckoResult.allow() else -> { notifyObservers { onLoadRequest( @@ -1171,7 +1170,7 @@ class GeckoEngineSession( ) } - GeckoResult.fromValue(AllowOrDeny.ALLOW) + GeckoResult.allow() } } } @@ -1181,15 +1180,15 @@ class GeckoEngineSession( request: NavigationDelegate.LoadRequest, ): GeckoResult<AllowOrDeny> { if (request.target == NavigationDelegate.TARGET_WINDOW_NEW) { - return GeckoResult.fromValue(AllowOrDeny.ALLOW) + return GeckoResult.allow() } return if (maybeInterceptRequest(request, true) != null) { - GeckoResult.fromValue(AllowOrDeny.DENY) + GeckoResult.deny() } else { // Not notifying session observer because of performance concern and currently there // is no use case. - GeckoResult.fromValue(AllowOrDeny.ALLOW) + GeckoResult.allow() } } @@ -1526,7 +1525,7 @@ class GeckoEngineSession( url = url, contentLength = contentLength, contentType = DownloadUtils.sanitizeMimeType(contentType), - fileName = fileName.sanitizeFileName(), + fileName = fileName.sanitizeFileName().decode(), response = response, isPrivate = privateMode, openInApp = webResponse.requestExternalApp, diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineView.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineView.kt index d5d77b3073..39a4c2d6cc 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineView.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineView.kt @@ -9,6 +9,7 @@ import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.Color import android.util.AttributeSet +import android.view.View import android.widget.FrameLayout import androidx.annotation.VisibleForTesting import androidx.core.view.ViewCompat @@ -63,7 +64,7 @@ class GeckoEngineView @JvmOverloads constructor( // Explicitly mark this view as important for autofill. The default "auto" doesn't seem to trigger any // autofill behavior for us here. @Suppress("WrongConstant") - ViewCompat.setImportantForAutofill(this, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES) + ViewCompat.setImportantForAutofill(this, View.IMPORTANT_FOR_ACCESSIBILITY_YES) } internal fun setColorScheme(preferredColorScheme: PreferredColorScheme) { @@ -205,29 +206,18 @@ class GeckoEngineView @JvmOverloads constructor( geckoView.activityContextDelegate = GeckoViewActivityContextDelegate(WeakReference(context)) } - @Suppress("TooGenericExceptionCaught") override fun captureThumbnail(onFinish: (Bitmap?) -> Unit) { - try { - val geckoResult = geckoView.capturePixels() - geckoResult.then( - { bitmap -> - onFinish(bitmap) - GeckoResult<Void>() - }, - { - onFinish(null) - GeckoResult<Void>() - }, - ) - } catch (e: Exception) { - // There's currently no reliable way for consumers of GeckoView to - // know whether or not the compositor is ready. So we have to add - // a catch-all here. In the future, GeckoView will invoke our error - // callback instead and this block can be removed: - // https://bugzilla.mozilla.org/show_bug.cgi?id=1645114 - // https://github.com/mozilla-mobile/android-components/issues/6680 - onFinish(null) - } + val geckoResult = geckoView.capturePixels() + geckoResult.then( + { bitmap -> + onFinish(bitmap) + GeckoResult() + }, + { + onFinish(null) + GeckoResult<Void>() + }, + ) } override fun clearSelection() { diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt index d4276e675a..8fb2e1e0fb 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt @@ -282,17 +282,16 @@ internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSe return geckoResult } + @Suppress("MaxLineLength") override fun onLoginSelect( session: GeckoSession, prompt: AutocompleteRequest<Autocomplete.LoginSelectOption>, ): GeckoResult<PromptResponse>? { val promptOptions = prompt.options + val generatedPassword = - if (promptOptions.isNotEmpty() && promptOptions.first().hint == Autocomplete.SelectOption.Hint.GENERATED) { - promptOptions.first().value.password - } else { - null - } + promptOptions.firstOrNull { option -> option.hint == Autocomplete.SelectOption.Hint.GENERATED }?.value?.password + val geckoResult = GeckoResult<PromptResponse>() val onConfirmSelect: (Login) -> Unit = { login -> if (!prompt.isComplete) { diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegate.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegate.kt index 3266ba8538..884db33824 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegate.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegate.kt @@ -66,10 +66,11 @@ internal class GeckoTranslateSessionDelegate( state?.requestedTranslationPair?.toLanguage, ) val translationsState = TranslationEngineState( - detectedLanguages, - state?.error, - state?.isEngineReady, - pair, + detectedLanguages = detectedLanguages, + error = state?.error, + isEngineReady = state?.isEngineReady, + hasVisibleChange = state?.hasVisibleChange, + requestedTranslationPair = pair, ) engineSession.notifyObservers { diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt index 87849440b6..871c46a33d 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt @@ -349,7 +349,7 @@ class GeckoEngineSessionTest { val observer: EngineSession.Observer = mock() engineSession.register(observer) - val response = WebResponse.Builder("https://download.mozilla.org/image.png") + val response = WebResponse.Builder("https://download.mozilla.org/image%20name.png") .addHeader(Headers.Names.CONTENT_TYPE, "image/png") .addHeader(Headers.Names.CONTENT_LENGTH, "42") .skipConfirmation(true) @@ -362,8 +362,8 @@ class GeckoEngineSessionTest { contentDelegate.value.onExternalResponse(mock(), response) verify(observer).onExternalResource( - url = eq("https://download.mozilla.org/image.png"), - fileName = eq("image.png"), + url = eq("https://download.mozilla.org/image%20name.png"), + fileName = eq("image name.png"), contentLength = eq(42), contentType = eq("image/png"), cookie = eq(null), @@ -4361,7 +4361,7 @@ class GeckoEngineSessionTest { mockLoadRequest("sample:about", triggeredByRedirect = true), ) - assertEquals(geckoResult!!, GeckoResult.fromValue(AllowOrDeny.ALLOW)) + assertEquals(geckoResult!!, GeckoResult.allow()) } @Test diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt index 6a8ed3c330..a7b6c59954 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt @@ -2740,6 +2740,28 @@ class GeckoEngineTest { } @Test + fun `web extension delegate handles add-on onOptionalPermissionsChanged event`() { + val runtime: GeckoRuntime = mock() + val webExtensionController: WebExtensionController = mock() + whenever(runtime.webExtensionController).thenReturn(webExtensionController) + + val extension = mockNativeWebExtension("test", "uri") + val webExtensionsDelegate: WebExtensionDelegate = mock() + val engine = GeckoEngine(context, runtime = runtime) + engine.registerWebExtensionDelegate(webExtensionsDelegate) + + val geckoDelegateCaptor = argumentCaptor<WebExtensionController.AddonManagerDelegate>() + verify(webExtensionController).setAddonManagerDelegate(geckoDelegateCaptor.capture()) + + assertEquals(Unit, geckoDelegateCaptor.value.onOptionalPermissionsChanged(extension)) + val extensionCaptor = argumentCaptor<WebExtension>() + verify(webExtensionsDelegate).onOptionalPermissionsChanged(extensionCaptor.capture()) + val capturedExtension = + extensionCaptor.value as mozilla.components.browser.engine.gecko.webextension.GeckoWebExtension + assertEquals(extension, capturedExtension.nativeExtension) + } + + @Test fun `web extension delegate handles add-on onInstallationFailed event`() { val runtime: GeckoRuntime = mock() val webExtensionController: WebExtensionController = mock() diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineViewTest.kt b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineViewTest.kt index 7056187e09..13fd983483 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineViewTest.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineViewTest.kt @@ -90,15 +90,6 @@ class GeckoEngineViewTest { shadowOf(getMainLooper()).idle() assertNull(thumbnail) - - // Test GeckoView throwing an exception - whenever(mockGeckoView.capturePixels()).thenThrow(IllegalStateException("Compositor not ready")) - - thumbnail = mock() - engineView.captureThumbnail { - thumbnail = it - } - assertNull(thumbnail) } @Test diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegateTest.kt b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegateTest.kt index 65a1c7d8f9..f0c9762fa8 100644 --- a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegateTest.kt +++ b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegateTest.kt @@ -69,13 +69,14 @@ class GeckoTranslateSessionDelegateTest { val gecko = GeckoTranslateSessionDelegate(mockSession) // Mock state parameters to check Gecko to AC mapping is correctly occurring - var userLangTag = "en" - var isDocLangTagSupported = true - var docLangTag = "es" - var fromLanguage = "de" - var toLanguage = "bg" - var error = "Error!" - var isEngineReady = false + val userLangTag = "en" + val isDocLangTagSupported = true + val docLangTag = "es" + val fromLanguage = "de" + val toLanguage = "bg" + val error = "Error!" + val isEngineReady = false + val hasVisibleChange = true mockSession.register( object : EngineSession.Observer { @@ -88,14 +89,15 @@ class GeckoTranslateSessionDelegateTest { assertTrue(state.requestedTranslationPair?.toLanguage == toLanguage) assertTrue(state.error == error) assertTrue(state.isEngineReady == isEngineReady) + assertTrue(state.hasVisibleChange == hasVisibleChange) } }, ) // Mock states - var mockDetectedLanguages = TranslationsController.SessionTranslation.DetectedLanguages(userLangTag, isDocLangTagSupported, docLangTag) - var mockTranslationsPair = TranslationsController.SessionTranslation.TranslationPair(fromLanguage, toLanguage) - var mockGeckoState = TranslationsController.SessionTranslation.TranslationState(mockTranslationsPair, error, mockDetectedLanguages, isEngineReady) + val mockDetectedLanguages = TranslationsController.SessionTranslation.DetectedLanguages(userLangTag, isDocLangTagSupported, docLangTag) + val mockTranslationsPair = TranslationsController.SessionTranslation.TranslationPair(fromLanguage, toLanguage) + val mockGeckoState = TranslationsController.SessionTranslation.TranslationState(mockTranslationsPair, error, mockDetectedLanguages, isEngineReady, hasVisibleChange) gecko.onTranslationStateChange(mock(), mockGeckoState) assertTrue(onTranslateStateChangeWasCalled) |