Commit c5a59bad authored by Sebastian Kaspari's avatar Sebastian Kaspari
Browse files

Update GeckoView release to 81.0.20200914232702.

parent eb4aebb9
......@@ -16,7 +16,7 @@ internal object GeckoVersions {
/**
* GeckoView Release Version.
*/
const val release_version = "80.0.20200831163820"
const val release_version = "81.0.20200914232702"
}
@Suppress("Unused", "MaxLineLength")
......
......@@ -546,6 +546,10 @@ class GeckoEngine(
if (cookieBehavior != value.cookiePolicy.id) {
cookieBehavior = value.cookiePolicy.id
}
if (cookiePurging != value.cookiePurging) {
setCookiePurging(value.cookiePurging)
}
}
defaultSettings?.trackingProtectionPolicy = value
......
......@@ -709,6 +709,10 @@ class GeckoEngineSession(
notifyObservers { onFirstContentfulPaint() }
}
override fun onPaintStatusReset(session: GeckoSession) {
notifyObservers { onPaintStatusReset() }
}
override fun onContextMenu(
session: GeckoSession,
screenX: Int,
......
......@@ -38,7 +38,7 @@ class GeckoEngineView @JvmOverloads constructor(
} catch (e: IllegalStateException) {
// This is to debug "display already acquired" crashes
val otherActivityClassName =
this.session?.accessibility?.view?.context?.javaClass?.simpleName
this.session?.accessibility?.view?.context?.javaClass?.simpleName
val otherActivityClassHashcode =
this.session?.accessibility?.view?.context?.hashCode()
val activityClassName = context.javaClass.simpleName
......@@ -156,7 +156,21 @@ class GeckoEngineView @JvmOverloads constructor(
* GeckoEngineSession) - since the previous one is no longer usable.
*/
private fun rebind() {
currentSession?.let { currentGeckoView.setSession(it.geckoSession) }
try {
currentSession?.let { currentGeckoView.setSession(it.geckoSession) }
} catch (e: IllegalArgumentException) {
// This is to debug "Display not attached" crashes
val otherActivityClassName =
currentSession?.geckoSession?.accessibility?.view?.context?.javaClass?.simpleName
val otherActivityClassHashcode =
currentSession?.geckoSession?.accessibility?.view?.context?.hashCode()
val activityClassName = context.javaClass.simpleName
val activityClassHashCode = context.hashCode()
val msg = "REBIND: Current activity: $activityClassName hashcode " +
"$activityClassHashCode Other activity: $otherActivityClassName " +
"hashcode $otherActivityClassHashcode"
throw IllegalArgumentException(msg, e)
}
}
@Synchronized
......
......@@ -19,6 +19,7 @@ fun TrackingProtectionPolicy.toContentBlockingSetting(
enhancedTrackingProtectionLevel(getEtpLevel())
antiTracking(getAntiTrackingPolicy())
cookieBehavior(cookiePolicy.id)
cookiePurging(cookiePurging)
safeBrowsing(safeBrowsingPolicy.sumBy { it.id })
strictSocialTrackingProtection(getStrictSocialTrackingProtection())
}.build()
......
......@@ -268,7 +268,7 @@ class GeckoWebExtension(
}
override fun onOpenOptionsPage(ext: GeckoNativeWebExtension) {
ext.metaData?.optionsPageUrl?.let { optionsPageUrl ->
ext.metaData.optionsPageUrl?.let { optionsPageUrl ->
tabHandler.onNewTab(
this@GeckoWebExtension,
GeckoEngineSession(runtime),
......@@ -340,7 +340,7 @@ class GeckoWebExtension(
* See [WebExtension.getMetadata].
*/
override fun getMetadata(): Metadata? {
return nativeExtension.metaData?.let {
return nativeExtension.metaData.let {
Metadata(
name = it.name,
description = it.description,
......@@ -364,11 +364,11 @@ class GeckoWebExtension(
}
override fun isEnabled(): Boolean {
return nativeExtension.metaData?.enabled ?: true
return nativeExtension.metaData.enabled
}
override fun isAllowedInPrivateBrowsing(): Boolean {
return isBuiltIn() || nativeExtension.metaData?.allowedInPrivateBrowsing ?: false
return isBuiltIn() || nativeExtension.metaData.allowedInPrivateBrowsing
}
}
......
......@@ -53,9 +53,10 @@ import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyList
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mockito
import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.spy
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
......@@ -1761,14 +1762,14 @@ class GeckoEngineSessionTest {
fun `toggleDesktopMode should reload a non-mobile url when set to desktop mode`() {
val mobileUrl = "https://m.example.com"
val nonMobileUrl = "https://example.com"
val engineSession = Mockito.spy(GeckoEngineSession(runtime, geckoSessionProvider = geckoSessionProvider))
val engineSession = spy(GeckoEngineSession(runtime, geckoSessionProvider = geckoSessionProvider))
engineSession.currentUrl = mobileUrl
engineSession.toggleDesktopMode(true, reload = true)
verify(engineSession, Mockito.atLeastOnce()).loadUrl(nonMobileUrl, null, LoadUrlFlags.select(LoadUrlFlags.LOAD_FLAGS_REPLACE_HISTORY), null)
verify(engineSession, atLeastOnce()).loadUrl(nonMobileUrl, null, LoadUrlFlags.select(LoadUrlFlags.LOAD_FLAGS_REPLACE_HISTORY), null)
engineSession.toggleDesktopMode(false, reload = true)
verify(engineSession, Mockito.atLeastOnce()).reload()
verify(engineSession, atLeastOnce()).reload()
}
@Test
......@@ -2194,6 +2195,25 @@ class GeckoEngineSessionTest {
assertTrue(observed)
}
@Test
fun `onPaintStatusReset notifies observers`() {
val engineSession = GeckoEngineSession(mock(),
geckoSessionProvider = geckoSessionProvider)
captureDelegates()
var observed = false
engineSession.register(object : EngineSession.Observer {
override fun onPaintStatusReset() {
observed = true
}
})
contentDelegate.value.onPaintStatusReset(mock())
assertTrue(observed)
}
@Test
fun `onCrash notifies observers about crash`() {
val engineSession = GeckoEngineSession(mock(),
......
......@@ -362,6 +362,27 @@ class GeckoEngineTest {
)
}
@Test
fun `cookiePurging is only invoked when the value is changed`() {
val mockRuntime = mock<GeckoRuntime>()
val settings = spy(ContentBlocking.Settings.Builder().build())
whenever(mockRuntime.settings).thenReturn(mock())
whenever(mockRuntime.settings.contentBlocking).thenReturn(settings)
val engine = GeckoEngine(testContext, runtime = mockRuntime)
val policy = TrackingProtectionPolicy.recommended()
engine.settings.trackingProtectionPolicy = policy
verify(mockRuntime.settings.contentBlocking).setCookiePurging(policy.cookiePurging)
reset(settings)
engine.settings.trackingProtectionPolicy = policy
verify(mockRuntime.settings.contentBlocking, never()).setCookiePurging(policy.cookiePurging)
}
@Test
fun `setCookieBehavior is only invoked when the value is changed`() {
val mockRuntime = mock<GeckoRuntime>()
......@@ -1192,6 +1213,11 @@ class GeckoEngineTest {
val bundle = GeckoBundle()
bundle.putString("webExtensionId", "id")
bundle.putString("locationURI", "uri")
val metaDataBundle = GeckoBundle()
metaDataBundle.putStringArray("disabledFlags", emptyArray())
metaDataBundle.putBoolean("privateBrowsingAllowed", false)
bundle.putBundle("metaData", metaDataBundle)
val installedExtension = MockWebExtension(bundle)
val installedExtensions = listOf<GeckoWebExtension>(installedExtension)
......
......@@ -27,7 +27,8 @@ class TrackingProtectionPolicyKtTest {
assertEquals(policy.getAntiTrackingPolicy(), setting.antiTrackingCategories)
assertEquals(policy.cookiePolicy.id, setting.cookieBehavior)
assertEquals(defaultSafeBrowsing.sumBy { it.id }, setting.safeBrowsingCategories)
assertEquals(setting.strictSocialTrackingProtection, setting.strictSocialTrackingProtection)
assertEquals(setting.strictSocialTrackingProtection, policy.strictSocialTrackingProtection)
assertEquals(setting.cookiePurging, policy.cookiePurging)
val policyWithSafeBrowsing = TrackingProtectionPolicy.recommended().toContentBlockingSetting(emptyArray())
assertEquals(0, policyWithSafeBrowsing.safeBrowsingCategories)
......
......@@ -12,6 +12,7 @@ import mozilla.components.concept.engine.prompt.Choice
import mozilla.components.concept.engine.prompt.PromptRequest
import mozilla.components.concept.engine.prompt.PromptRequest.MultipleChoice
import mozilla.components.concept.engine.prompt.PromptRequest.SingleChoice
import mozilla.components.concept.storage.Login
import mozilla.components.support.ktx.kotlin.toDate
import mozilla.components.support.test.any
import mozilla.components.support.test.mock
......@@ -26,10 +27,10 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.spy
import org.mockito.Mockito
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.verify
import org.mockito.Mockito.never
import org.mozilla.gecko.util.GeckoBundle
import org.mozilla.geckoview.Autocomplete
import org.mozilla.geckoview.GeckoResult
import org.mozilla.geckoview.GeckoRuntime
import org.mozilla.geckoview.GeckoSession
......@@ -46,6 +47,7 @@ import java.security.InvalidParameterException
import java.util.Calendar
import java.util.Calendar.YEAR
import java.util.Date
typealias GeckoChoice = GeckoSession.PromptDelegate.ChoicePrompt.Choice
typealias GECKO_AUTH_LEVEL = GeckoSession.PromptDelegate.AuthPrompt.AuthOptions.Level
typealias GECKO_PROMPT_CHOICE_TYPE = GeckoSession.PromptDelegate.ChoicePrompt.Type
......@@ -145,11 +147,11 @@ class GeckoPromptDelegateTest {
)
mockSession.register(
object : EngineSession.Observer {
override fun onPromptRequest(promptRequest: PromptRequest) {
promptRequestSingleChoice = promptRequest
}
})
object : EngineSession.Observer {
override fun onPromptRequest(promptRequest: PromptRequest) {
promptRequestSingleChoice = promptRequest
}
})
val geckoResult = gecko.onChoicePrompt(mock(), geckoPrompt)
geckoResult!!.accept {
......@@ -478,7 +480,8 @@ class GeckoPromptDelegateTest {
dateRequest = promptRequest
}
})
val geckoResult = promptDelegate.onDateTimePrompt(mock(), GeckoDateTimePrompt(type = DATETIME_LOCAL))
val geckoResult =
promptDelegate.onDateTimePrompt(mock(), GeckoDateTimePrompt(type = DATETIME_LOCAL))
geckoResult!!.accept {
confirmCalled = true
}
......@@ -563,7 +566,7 @@ class GeckoPromptDelegateTest {
val mockUri: Uri = mock()
doReturn(contentResolver).`when`(context).contentResolver
doReturn(mock<FileInputStream>()).`when`(contentResolver).openInputStream(mozilla.components.support.test.any())
doReturn(mock<FileInputStream>()).`when`(contentResolver).openInputStream(any())
var filePickerRequest: PromptRequest.File = mock()
......@@ -621,6 +624,125 @@ class GeckoPromptDelegateTest {
)
}
@Test
fun `Calling onLoginSave must provide an SaveLoginPrompt PromptRequest`() {
val mockSession = GeckoEngineSession(runtime)
var onLoginSaved = false
var onDismissWasCalled = false
var loginSaveRequest: PromptRequest.SaveLoginPrompt = mock()
val promptDelegate = spy(GeckoPromptDelegate(mockSession))
mockSession.register(object : EngineSession.Observer {
override fun onPromptRequest(promptRequest: PromptRequest) {
loginSaveRequest = promptRequest as PromptRequest.SaveLoginPrompt
}
})
val login = createLogin()
val saveOption = Autocomplete.LoginSaveOption(login.toLoginEntry())
var geckoResult =
promptDelegate.onLoginSave(mock(), GeckoLoginSavePrompt(arrayOf(saveOption)))
geckoResult!!.accept {
onDismissWasCalled = true
}
loginSaveRequest.onDismiss()
assertTrue(onDismissWasCalled)
geckoResult = promptDelegate.onLoginSave(mock(), GeckoLoginSavePrompt(arrayOf(saveOption)))
geckoResult!!.accept {
onLoginSaved = true
}
loginSaveRequest.onConfirm(login)
assertTrue(onLoginSaved)
}
@Test
fun `Calling onLoginSelect must provide an SelectLoginPrompt PromptRequest`() {
val mockSession = GeckoEngineSession(runtime)
var onLoginSelected = false
var onDismissWasCalled = false
var loginSelectRequest: PromptRequest.SelectLoginPrompt = mock()
val promptDelegate = spy(GeckoPromptDelegate(mockSession))
mockSession.register(object : EngineSession.Observer {
override fun onPromptRequest(promptRequest: PromptRequest) {
loginSelectRequest = promptRequest as PromptRequest.SelectLoginPrompt
}
})
val login = createLogin()
val loginSelectOption = Autocomplete.LoginSelectOption(login.toLoginEntry())
val secondLogin = createLogin(username = "username2")
val secondLoginSelectOption = Autocomplete.LoginSelectOption(secondLogin.toLoginEntry())
var geckoResult =
promptDelegate.onLoginSelect(
mock(),
GeckoLoginSelectPrompt(arrayOf(loginSelectOption, secondLoginSelectOption))
)
geckoResult!!.accept {
onDismissWasCalled = true
}
loginSelectRequest.onDismiss()
assertTrue(onDismissWasCalled)
geckoResult = promptDelegate.onLoginSelect(
mock(),
GeckoLoginSelectPrompt(arrayOf(loginSelectOption, secondLoginSelectOption))
)
geckoResult!!.accept {
onLoginSelected = true
}
loginSelectRequest.onConfirm(login)
assertTrue(onLoginSelected)
}
fun createLogin(
guid: String = "id",
password: String = "password",
username: String = "username",
origin: String = "https://www.origin.com",
httpRealm: String = "httpRealm",
formActionOrigin: String = "https://www.origin.com",
usernameField: String = "usernameField",
passwordField: String = "passwordField"
) = Login(
guid = guid,
origin = origin,
password = password,
username = username,
httpRealm = httpRealm,
formActionOrigin = formActionOrigin,
usernameField = usernameField,
passwordField = passwordField
)
/**
* Converts an Android Components [Login] to a GeckoView [LoginStorage.LoginEntry]
*/
private fun Login.toLoginEntry() = Autocomplete.LoginEntry.Builder()
.guid(guid)
.origin(origin)
.formActionOrigin(formActionOrigin)
.httpRealm(httpRealm)
.username(username)
.password(password)
.build()
@Test
fun `Calling onAuthPrompt must provide an Authentication PromptRequest`() {
val mockSession = GeckoEngineSession(runtime)
......@@ -969,7 +1091,7 @@ class GeckoPromptDelegateTest {
prompt.dismissSafely(geckoResult)
verify(geckoResult).complete(any())
Mockito.verify(geckoResult).complete(any())
}
@Test
......@@ -981,7 +1103,7 @@ class GeckoPromptDelegateTest {
prompt.dismissSafely(geckoResult)
verify(geckoResult, never()).complete(any())
Mockito.verify(geckoResult, Mockito.never()).complete(any())
}
class GeckoChoicePrompt(
......@@ -1006,7 +1128,7 @@ class GeckoPromptDelegateTest {
title: String = "title",
type: Int,
capture: Int = 0,
mimeTypes: Array<out String > = emptyArray()
mimeTypes: Array<out String> = emptyArray()
) : GeckoSession.PromptDelegate.FilePrompt(title, type, capture, mimeTypes)
class GeckoAuthPrompt(
......@@ -1043,6 +1165,14 @@ class GeckoPromptDelegateTest {
message: String = "message"
) : GeckoSession.PromptDelegate.ButtonPrompt(title, message)
class GeckoLoginSelectPrompt(
loginArray: Array<Autocomplete.LoginSelectOption>
) : GeckoSession.PromptDelegate.AutocompleteRequest<Autocomplete.LoginSelectOption>(loginArray)
class GeckoLoginSavePrompt(
login: Array<Autocomplete.LoginSaveOption>
) : GeckoSession.PromptDelegate.AutocompleteRequest<Autocomplete.LoginSaveOption>(login)
class GeckoAuthOptions : GeckoSession.PromptDelegate.AuthPrompt.AuthOptions()
private fun GeckoSession.PromptDelegate.BasePrompt.getGeckoResult(): GeckoBundle {
......
......@@ -302,10 +302,15 @@ class GeckoWebExtensionTest {
val tabHandler: TabHandler = mock()
val tabDelegateCaptor = argumentCaptor<WebExtension.TabDelegate>()
val engineSessionCaptor = argumentCaptor<GeckoEngineSession>()
var metaDataBundle = GeckoBundle()
metaDataBundle.putStringArray("disabledFlags", emptyArray())
metaDataBundle.putString("optionsPageUrl", "optionsPageUrl")
val bundle = GeckoBundle()
bundle.putString("webExtensionId", "id")
bundle.putString("locationURI", "uri")
bundle.putBundle("metaData", metaDataBundle)
val nativeGeckoWebExt: WebExtension = mockNativeExtension(bundle)
// Create extension and register global tab handler
......@@ -328,7 +333,7 @@ class GeckoWebExtensionTest {
tabDelegateCaptor.value.onOpenOptionsPage(nativeGeckoWebExt)
verify(tabHandler, never()).onNewTab(eq(extension), any(), eq(false), eq("http://options-page.moz"))
val metaDataBundle = GeckoBundle()
metaDataBundle = GeckoBundle()
metaDataBundle.putStringArray("disabledFlags", emptyArray())
bundle.putBundle("metaData", metaDataBundle)
val nativeGeckoWebExtWithMetadata = MockWebExtension(bundle)
......@@ -384,11 +389,6 @@ class GeckoWebExtensionTest {
val runtime: GeckoRuntime = mock()
val webExtensionController: WebExtensionController = mock()
whenever(runtime.webExtensionController).thenReturn(webExtensionController)
val extensionWithoutMetadata = GeckoWebExtension(
mockNativeExtension(),
runtime
)
assertNull(extensionWithoutMetadata.getMetadata())
val metaDataBundle = GeckoBundle()
metaDataBundle.putStringArray("promptPermissions", arrayOf("p1", "p2"))
......@@ -433,11 +433,6 @@ class GeckoWebExtensionTest {
val runtime: GeckoRuntime = mock()
val webExtensionController: WebExtensionController = mock()
whenever(runtime.webExtensionController).thenReturn(webExtensionController)
val extensionWithoutMetadata = GeckoWebExtension(
mockNativeExtension(),
runtime
)
assertNull(extensionWithoutMetadata.getMetadata())
val metaDataBundle = GeckoBundle()
metaDataBundle.putStringArray("promptPermissions", arrayOf("p1", "p2"))
......@@ -497,9 +492,6 @@ class GeckoWebExtensionTest {
val bundle = GeckoBundle()
bundle.putString("webExtensionId", "id")
bundle.putString("locationURI", "uri")
val nativeExtensionWithoutMetadata = MockWebExtension(bundle)
val webExtension = GeckoWebExtension(nativeExtensionWithoutMetadata, runtime)
assertTrue(webExtension.isEnabled())
val metaDataBundle = GeckoBundle()
metaDataBundle.putBoolean("enabled", true)
......@@ -526,6 +518,8 @@ class GeckoWebExtensionTest {
builtInBundle.putBoolean("isBuiltIn", true)
builtInBundle.putString("webExtensionId", "id")
builtInBundle.putString("locationURI", "uri")
builtInBundle.putBoolean("privateBrowsingAllowed", false)
val builtInExtension = GeckoWebExtension(
mockNativeExtension(builtInBundle),
runtime
......@@ -535,9 +529,6 @@ class GeckoWebExtensionTest {
val bundle = GeckoBundle()
bundle.putString("webExtensionId", "id")
bundle.putString("locationURI", "uri")
val nativeExtensionWithoutMetadata = MockWebExtension(bundle)
val webExtension = GeckoWebExtension(nativeExtensionWithoutMetadata, runtime)
assertFalse(webExtension.isAllowedInPrivateBrowsing())
val metaDataBundle = GeckoBundle()
metaDataBundle.putBoolean("privateBrowsingAllowed", true)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment