Commit 2ee0dafa authored by MozLando's avatar MozLando
Browse files

Merge #6165

6165: Closes #6162: Provide API to speculatively create engine session r=pocmo a=csadilek

See https://github.com/mozilla-mobile/android-components/issues/6162#issuecomment-594093161

.

Another advantage of decoupling this from `speculativeConnect` is that we can also handle private sessions. Applied to all 3 engine variants.  

Co-authored-by: default avatarChristian Sadilek <christian.sadilek@gmail.com>
parents 56cc26f2 62ad8097
Loading
Loading
Loading
Loading
+27 −2
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ package mozilla.components.browser.engine.gecko

import android.content.Context
import android.util.AttributeSet
import androidx.annotation.VisibleForTesting
import mozilla.components.browser.engine.gecko.integration.LocaleSettingUpdater
import mozilla.components.browser.engine.gecko.mediaquery.from
import mozilla.components.browser.engine.gecko.mediaquery.toGeckoValue
@@ -35,6 +36,7 @@ import mozilla.components.concept.engine.webextension.WebExtensionRuntime
import mozilla.components.concept.engine.webnotifications.WebNotificationDelegate
import mozilla.components.concept.engine.webpush.WebPushDelegate
import mozilla.components.concept.engine.webpush.WebPushHandler
import mozilla.components.support.utils.ThreadUtils
import org.json.JSONObject
import org.mozilla.geckoview.AllowOrDeny
import org.mozilla.geckoview.ContentBlocking
@@ -63,6 +65,7 @@ class GeckoEngine(
) : Engine, WebExtensionRuntime {
    private val executor by lazy { executorProvider.invoke() }
    private val localeUpdater = LocaleSettingUpdater(context, runtime)
    @VisibleForTesting internal var speculativeSession: GeckoEngineSession? = null

    private var webExtensionDelegate: WebExtensionDelegate? = null
    private val webExtensionActionHandler = object : ActionHandler {
@@ -133,10 +136,21 @@ class GeckoEngine(
    }

    /**
     * Creates a new Gecko-based EngineSession.
     * See [Engine.createSession].
     */
    override fun createSession(private: Boolean): EngineSession {
        return GeckoEngineSession(runtime, private, defaultSettings)
        ThreadUtils.assertOnUiThread()
        val speculativeSession = this.speculativeSession?.let { speculativeSession ->
            if (speculativeSession.geckoSession.settings.usePrivateMode == private) {
                speculativeSession
            } else {
                speculativeSession.close()
                null
            }.also {
                this.speculativeSession = null
            }
        }
        return speculativeSession ?: GeckoEngineSession(runtime, private, defaultSettings)
    }

    /**
@@ -146,6 +160,17 @@ class GeckoEngine(
        return GeckoEngineSessionState.fromJSON(json)
    }

    /**
     * See [Engine.speculativeCreateSession].
     */
    override fun speculativeCreateSession(private: Boolean) {
        ThreadUtils.assertOnUiThread()
        if (this.speculativeSession?.geckoSession?.settings?.usePrivateMode != private) {
            this.speculativeSession?.geckoSession?.close()
            this.speculativeSession = GeckoEngineSession(runtime, private, defaultSettings)
        }
    }

    /**
     * Opens a speculative connection to the host of [url].
     *
+46 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import mozilla.components.test.ReflectionUtils
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNotSame
import org.junit.Assert.assertNull
import org.junit.Assert.assertSame
import org.junit.Assert.assertTrue
@@ -80,7 +81,51 @@ class GeckoEngineTest {

    @Test
    fun createSession() {
        assertTrue(GeckoEngine(context, runtime = runtime).createSession() is GeckoEngineSession)
        val engine = GeckoEngine(context, runtime = runtime)
        assertTrue(engine.createSession() is GeckoEngineSession)

        // Create a private speculative session and consume it
        engine.speculativeCreateSession(private = true)
        assertNotNull(engine.speculativeSession)
        var privateSpeculativeSession = engine.speculativeSession!!
        assertSame(privateSpeculativeSession, engine.createSession(private = true))
        assertNull(engine.speculativeSession)

        // Create a regular speculative session and make sure it is not returned
        // if a private session is requested instead.
        engine.speculativeCreateSession(private = false)
        assertNotNull(engine.speculativeSession)
        privateSpeculativeSession = engine.speculativeSession!!
        assertNotSame(privateSpeculativeSession, engine.createSession(private = true))
        // Make sure previous (never used) speculative session is now closed
        assertFalse(privateSpeculativeSession.geckoSession.isOpen)
        assertNull(engine.speculativeSession)
    }

    @Test
    fun speculativeCreateSession() {
        val engine = GeckoEngine(context, runtime = runtime)
        assertNull(engine.speculativeSession)

        // Create a private speculative session
        engine.speculativeCreateSession(private = true)
        assertNotNull(engine.speculativeSession)
        val privateSpeculativeSession = engine.speculativeSession!!
        assertTrue(privateSpeculativeSession.geckoSession.settings.usePrivateMode)

        // Creating another private speculative session should have no effect as
        // session hasn't been "consumed".
        engine.speculativeCreateSession(private = true)
        assertSame(privateSpeculativeSession, engine.speculativeSession)
        assertTrue(privateSpeculativeSession.geckoSession.settings.usePrivateMode)

        // Creating a non-private speculative session should affect prepared session
        engine.speculativeCreateSession(private = false)
        assertNotSame(privateSpeculativeSession, engine.speculativeSession)
        // Make sure previous (never used) speculative session is now closed
        assertFalse(privateSpeculativeSession.geckoSession.isOpen)
        val regularSpeculativeSession = engine.speculativeSession!!
        assertFalse(regularSpeculativeSession.geckoSession.settings.usePrivateMode)
    }

    @Test
+27 −2
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ package mozilla.components.browser.engine.gecko

import android.content.Context
import android.util.AttributeSet
import androidx.annotation.VisibleForTesting
import mozilla.components.browser.engine.gecko.integration.LocaleSettingUpdater
import mozilla.components.browser.engine.gecko.mediaquery.from
import mozilla.components.browser.engine.gecko.mediaquery.toGeckoValue
@@ -35,6 +36,7 @@ import mozilla.components.concept.engine.webextension.WebExtensionRuntime
import mozilla.components.concept.engine.webnotifications.WebNotificationDelegate
import mozilla.components.concept.engine.webpush.WebPushDelegate
import mozilla.components.concept.engine.webpush.WebPushHandler
import mozilla.components.support.utils.ThreadUtils
import org.json.JSONObject
import org.mozilla.geckoview.AllowOrDeny
import org.mozilla.geckoview.ContentBlocking
@@ -61,6 +63,7 @@ class GeckoEngine(
) : Engine, WebExtensionRuntime {
    private val executor by lazy { executorProvider.invoke() }
    private val localeUpdater = LocaleSettingUpdater(context, runtime)
    @VisibleForTesting internal var speculativeSession: GeckoEngineSession? = null

    private var webExtensionDelegate: WebExtensionDelegate? = null
    private val webExtensionActionHandler = object : ActionHandler {
@@ -131,10 +134,21 @@ class GeckoEngine(
    }

    /**
     * Creates a new Gecko-based EngineSession.
     * See [Engine.createSession].
     */
    override fun createSession(private: Boolean): EngineSession {
        return GeckoEngineSession(runtime, private, defaultSettings)
        ThreadUtils.assertOnUiThread()
        val speculativeSession = this.speculativeSession?.let { speculativeSession ->
            if (speculativeSession.geckoSession.settings.usePrivateMode == private) {
                speculativeSession
            } else {
                speculativeSession.close()
                null
            }.also {
                this.speculativeSession = null
            }
        }
        return speculativeSession ?: GeckoEngineSession(runtime, private, defaultSettings)
    }

    /**
@@ -144,6 +158,17 @@ class GeckoEngine(
        return GeckoEngineSessionState.fromJSON(json)
    }

    /**
     * See [Engine.speculativeCreateSession].
     */
    override fun speculativeCreateSession(private: Boolean) {
        ThreadUtils.assertOnUiThread()
        if (this.speculativeSession?.geckoSession?.settings?.usePrivateMode != private) {
            this.speculativeSession?.geckoSession?.close()
            this.speculativeSession = GeckoEngineSession(runtime, private, defaultSettings)
        }
    }

    /**
     * Opens a speculative connection to the host of [url].
     *
+46 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import mozilla.components.test.ReflectionUtils
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNotSame
import org.junit.Assert.assertNull
import org.junit.Assert.assertSame
import org.junit.Assert.assertTrue
@@ -86,7 +87,51 @@ class GeckoEngineTest {

    @Test
    fun createSession() {
        assertTrue(GeckoEngine(context, runtime = runtime).createSession() is GeckoEngineSession)
        val engine = GeckoEngine(context, runtime = runtime)
        assertTrue(engine.createSession() is GeckoEngineSession)

        // Create a private speculative session and consume it
        engine.speculativeCreateSession(private = true)
        assertNotNull(engine.speculativeSession)
        var privateSpeculativeSession = engine.speculativeSession!!
        assertSame(privateSpeculativeSession, engine.createSession(private = true))
        assertNull(engine.speculativeSession)

        // Create a regular speculative session and make sure it is not returned
        // if a private session is requested instead.
        engine.speculativeCreateSession(private = false)
        assertNotNull(engine.speculativeSession)
        privateSpeculativeSession = engine.speculativeSession!!
        assertNotSame(privateSpeculativeSession, engine.createSession(private = true))
        // Make sure previous (never used) speculative session is now closed
        assertFalse(privateSpeculativeSession.geckoSession.isOpen)
        assertNull(engine.speculativeSession)
    }

    @Test
    fun speculativeCreateSession() {
        val engine = GeckoEngine(context, runtime = runtime)
        assertNull(engine.speculativeSession)

        // Create a private speculative session
        engine.speculativeCreateSession(private = true)
        assertNotNull(engine.speculativeSession)
        val privateSpeculativeSession = engine.speculativeSession!!
        assertTrue(privateSpeculativeSession.geckoSession.settings.usePrivateMode)

        // Creating another private speculative session should have no effect as
        // session hasn't been "consumed".
        engine.speculativeCreateSession(private = true)
        assertSame(privateSpeculativeSession, engine.speculativeSession)
        assertTrue(privateSpeculativeSession.geckoSession.settings.usePrivateMode)

        // Creating a non-private speculative session should affect prepared session
        engine.speculativeCreateSession(private = false)
        assertNotSame(privateSpeculativeSession, engine.speculativeSession)
        // Make sure previous (never used) speculative session is now closed
        assertFalse(privateSpeculativeSession.geckoSession.isOpen)
        val regularSpeculativeSession = engine.speculativeSession!!
        assertFalse(regularSpeculativeSession.geckoSession.settings.usePrivateMode)
    }

    @Test
+27 −2
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ package mozilla.components.browser.engine.gecko

import android.content.Context
import android.util.AttributeSet
import androidx.annotation.VisibleForTesting
import mozilla.components.browser.engine.gecko.integration.LocaleSettingUpdater
import mozilla.components.browser.engine.gecko.mediaquery.from
import mozilla.components.browser.engine.gecko.mediaquery.toGeckoValue
@@ -35,6 +36,7 @@ import mozilla.components.concept.engine.webextension.WebExtensionRuntime
import mozilla.components.concept.engine.webnotifications.WebNotificationDelegate
import mozilla.components.concept.engine.webpush.WebPushDelegate
import mozilla.components.concept.engine.webpush.WebPushHandler
import mozilla.components.support.utils.ThreadUtils
import org.json.JSONObject
import org.mozilla.geckoview.AllowOrDeny
import org.mozilla.geckoview.ContentBlocking
@@ -63,6 +65,7 @@ class GeckoEngine(
) : Engine, WebExtensionRuntime {
    private val executor by lazy { executorProvider.invoke() }
    private val localeUpdater = LocaleSettingUpdater(context, runtime)
    @VisibleForTesting internal var speculativeSession: GeckoEngineSession? = null

    private var webExtensionDelegate: WebExtensionDelegate? = null
    private val webExtensionActionHandler = object : ActionHandler {
@@ -133,10 +136,21 @@ class GeckoEngine(
    }

    /**
     * Creates a new Gecko-based EngineSession.
     * See [Engine.createSession].
     */
    override fun createSession(private: Boolean): EngineSession {
        return GeckoEngineSession(runtime, private, defaultSettings)
        ThreadUtils.assertOnUiThread()
        val speculativeSession = this.speculativeSession?.let { speculativeSession ->
            if (speculativeSession.geckoSession.settings.usePrivateMode == private) {
                speculativeSession
            } else {
                speculativeSession.close()
                null
            }.also {
                this.speculativeSession = null
            }
        }
        return speculativeSession ?: GeckoEngineSession(runtime, private, defaultSettings)
    }

    /**
@@ -146,6 +160,17 @@ class GeckoEngine(
        return GeckoEngineSessionState.fromJSON(json)
    }

    /**
     * See [Engine.speculativeCreateSession].
     */
    override fun speculativeCreateSession(private: Boolean) {
        ThreadUtils.assertOnUiThread()
        if (this.speculativeSession?.geckoSession?.settings?.usePrivateMode != private) {
            this.speculativeSession?.geckoSession?.close()
            this.speculativeSession = GeckoEngineSession(runtime, private, defaultSettings)
        }
    }

    /**
     * Opens a speculative connection to the host of [url].
     *
Loading