Commit dd82ca27 authored by Simon Chae's avatar Simon Chae
Browse files

Closes #4438: Add support for browser.tabs.create()

parent ad99377a
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import mozilla.components.concept.engine.history.HistoryTrackingDelegate
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
import mozilla.components.concept.engine.utils.EngineVersion
import mozilla.components.concept.engine.webextension.WebExtension
import mozilla.components.concept.engine.webextension.WebExtensionTabDelegate
import org.json.JSONObject
import org.mozilla.geckoview.ContentBlocking
import org.mozilla.geckoview.ContentBlockingController
@@ -33,6 +34,7 @@ import org.mozilla.geckoview.GeckoRuntime
import org.mozilla.geckoview.GeckoRuntimeSettings
import org.mozilla.geckoview.GeckoSession
import org.mozilla.geckoview.GeckoWebExecutor
import org.mozilla.geckoview.WebExtensionController
import java.lang.IllegalStateException

/**
@@ -146,6 +148,28 @@ class GeckoEngine(
        }
    }

    /**
     * See [Engine.registerWebExtensionTabDelegate].
     */
    override fun registerWebExtensionTabDelegate(
        webExtensionTabDelegate: WebExtensionTabDelegate
    ) {
        val tabsDelegate = object : WebExtensionController.TabDelegate {
            override fun onNewTab(
                webExtension: org.mozilla.geckoview.WebExtension?,
                url: String?
            ): GeckoResult<GeckoSession>? {
                val geckoEngineSession = GeckoEngineSession(runtime, openGeckoSession = false)
                val geckoWebExtension = webExtension?.let { GeckoWebExtension(it.id, it.location) }
                webExtensionTabDelegate.onNewTab(geckoWebExtension, url ?: "", geckoEngineSession)

                return GeckoResult.fromValue(geckoEngineSession.geckoSession)
            }
        }

        runtime.webExtensionController.tabDelegate = tabsDelegate
    }

    /**
     * See [Engine.clearData].
     */
+37 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ import mozilla.components.concept.engine.UnsupportedSettingException
import mozilla.components.concept.engine.content.blocking.TrackerLog
import mozilla.components.concept.engine.content.blocking.TrackingProtectionExceptionStorage
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
import mozilla.components.concept.engine.webextension.WebExtensionTabDelegate
import mozilla.components.support.test.any
import mozilla.components.support.test.argumentCaptor
import mozilla.components.support.test.eq
@@ -44,6 +45,7 @@ import org.mozilla.geckoview.GeckoRuntimeSettings
import org.mozilla.geckoview.GeckoSession
import org.mozilla.geckoview.GeckoWebExecutor
import org.mozilla.geckoview.StorageController
import org.mozilla.geckoview.WebExtensionController
import org.robolectric.Robolectric
import java.io.IOException
import java.lang.Exception
@@ -523,6 +525,41 @@ class GeckoEngineTest {
        assertEquals(expected, throwable)
    }

    @Test
    fun `register web extension tab delegate`() {
        val runtime: GeckoRuntime = mock()
        val webExtensionController: WebExtensionController = mock()
        whenever(runtime.webExtensionController).thenReturn(webExtensionController)

        val webExtensionsTabDelegate: WebExtensionTabDelegate = mock()
        val engine = GeckoEngine(context, runtime = runtime)
        engine.registerWebExtensionTabDelegate(webExtensionsTabDelegate)
        val captor = argumentCaptor<WebExtensionController.TabDelegate>()
        verify(webExtensionController).tabDelegate = captor.capture()

        val engineSessionCaptor = argumentCaptor<GeckoEngineSession>()
        captor.value.onNewTab(null, null)
        verify(webExtensionsTabDelegate).onNewTab(eq(null), eq(""), engineSessionCaptor.capture())
        assertNotNull(engineSessionCaptor.value)
        assertFalse(engineSessionCaptor.value.geckoSession.isOpen)

        captor.value.onNewTab(null, "https://www.mozilla.org")
        verify(webExtensionsTabDelegate).onNewTab(eq(null), eq("https://www.mozilla.org"),
            engineSessionCaptor.capture())
        assertNotNull(engineSessionCaptor.value)
        assertFalse(engineSessionCaptor.value.geckoSession.isOpen)

        val webExt = org.mozilla.geckoview.WebExtension("test")
        val geckoExtCap = argumentCaptor<mozilla.components.browser.engine.gecko.webextension.GeckoWebExtension>()
        captor.value.onNewTab(webExt, "https://test-moz.org")
        verify(webExtensionsTabDelegate).onNewTab(geckoExtCap.capture(), eq("https://test-moz.org"),
            engineSessionCaptor.capture())
        assertNotNull(geckoExtCap.value)
        assertEquals(geckoExtCap.value.id, webExt.id)
        assertNotNull(engineSessionCaptor.value)
        assertFalse(engineSessionCaptor.value.geckoSession.isOpen)
    }

    @Test(expected = RuntimeException::class)
    fun `WHEN GeckoRuntime is shutting down THEN GeckoEngine throws runtime exception`() {
        val runtime: GeckoRuntime = mock()
+24 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import mozilla.components.concept.engine.history.HistoryTrackingDelegate
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
import mozilla.components.concept.engine.utils.EngineVersion
import mozilla.components.concept.engine.webextension.WebExtension
import mozilla.components.concept.engine.webextension.WebExtensionTabDelegate
import org.json.JSONObject
import org.mozilla.geckoview.ContentBlocking
import org.mozilla.geckoview.ContentBlockingController
@@ -33,6 +34,7 @@ import org.mozilla.geckoview.GeckoRuntime
import org.mozilla.geckoview.GeckoRuntimeSettings
import org.mozilla.geckoview.GeckoSession
import org.mozilla.geckoview.GeckoWebExecutor
import org.mozilla.geckoview.WebExtensionController
import java.lang.IllegalStateException

/**
@@ -145,6 +147,28 @@ class GeckoEngine(
        }
    }

    /**
     * See [Engine.registerWebExtensionTabDelegate].
     */
    override fun registerWebExtensionTabDelegate(
        webExtensionTabDelegate: WebExtensionTabDelegate
    ) {
        val tabsDelegate = object : WebExtensionController.TabDelegate {
            override fun onNewTab(
                webExtension: org.mozilla.geckoview.WebExtension?,
                url: String?
            ): GeckoResult<GeckoSession>? {
                val geckoEngineSession = GeckoEngineSession(runtime, openGeckoSession = false)
                val geckoWebExtension = webExtension?.let { GeckoWebExtension(it.id, it.location) }
                webExtensionTabDelegate.onNewTab(geckoWebExtension, url ?: "", geckoEngineSession)

                return GeckoResult.fromValue(geckoEngineSession.geckoSession)
            }
        }

        runtime.webExtensionController.tabDelegate = tabsDelegate
    }

    /**
     * See [Engine.clearData].
     */
+37 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ import mozilla.components.concept.engine.UnsupportedSettingException
import mozilla.components.concept.engine.content.blocking.TrackerLog
import mozilla.components.concept.engine.content.blocking.TrackingProtectionExceptionStorage
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
import mozilla.components.concept.engine.webextension.WebExtensionTabDelegate
import mozilla.components.support.test.any
import mozilla.components.support.test.argumentCaptor
import mozilla.components.support.test.eq
@@ -46,6 +47,7 @@ import org.mozilla.geckoview.GeckoRuntimeSettings
import org.mozilla.geckoview.GeckoSession
import org.mozilla.geckoview.GeckoWebExecutor
import org.mozilla.geckoview.StorageController
import org.mozilla.geckoview.WebExtensionController
import org.robolectric.Robolectric
import java.io.IOException
import java.lang.Exception
@@ -522,6 +524,41 @@ class GeckoEngineTest {
        assertEquals(expected, throwable)
    }

    @Test
    fun `register web extension tab delegate`() {
        val runtime: GeckoRuntime = mock()
        val webExtensionController: WebExtensionController = mock()
        whenever(runtime.webExtensionController).thenReturn(webExtensionController)

        val webExtensionsTabDelegate: WebExtensionTabDelegate = mock()
        val engine = GeckoEngine(context, runtime = runtime)
        engine.registerWebExtensionTabDelegate(webExtensionsTabDelegate)
        val captor = argumentCaptor<WebExtensionController.TabDelegate>()
        verify(webExtensionController).tabDelegate = captor.capture()

        val engineSessionCaptor = argumentCaptor<GeckoEngineSession>()
        captor.value.onNewTab(null, null)
        verify(webExtensionsTabDelegate).onNewTab(eq(null), eq(""), engineSessionCaptor.capture())
        assertNotNull(engineSessionCaptor.value)
        assertFalse(engineSessionCaptor.value.geckoSession.isOpen)

        captor.value.onNewTab(null, "https://www.mozilla.org")
        verify(webExtensionsTabDelegate).onNewTab(eq(null), eq("https://www.mozilla.org"),
            engineSessionCaptor.capture())
        assertNotNull(engineSessionCaptor.value)
        assertFalse(engineSessionCaptor.value.geckoSession.isOpen)

        val webExt = org.mozilla.geckoview.WebExtension("test")
        val geckoExtCap = argumentCaptor<mozilla.components.browser.engine.gecko.webextension.GeckoWebExtension>()
        captor.value.onNewTab(webExt, "https://test-moz.org")
        verify(webExtensionsTabDelegate).onNewTab(geckoExtCap.capture(), eq("https://test-moz.org"),
            engineSessionCaptor.capture())
        assertNotNull(geckoExtCap.value)
        assertEquals(geckoExtCap.value.id, webExt.id)
        assertNotNull(engineSessionCaptor.value)
        assertFalse(engineSessionCaptor.value.geckoSession.isOpen)
    }

    @Test(expected = RuntimeException::class)
    fun `WHEN GeckoRuntime is shutting down THEN GeckoEngine throws runtime exception`() {
        val runtime: GeckoRuntime = mock()
+10 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ import mozilla.components.concept.engine.content.blocking.TrackingProtectionExce
import mozilla.components.concept.engine.content.blocking.TrackerLog
import mozilla.components.concept.engine.utils.EngineVersion
import mozilla.components.concept.engine.webextension.WebExtension
import mozilla.components.concept.engine.webextension.WebExtensionTabDelegate
import org.json.JSONObject
import java.lang.UnsupportedOperationException

@@ -129,6 +130,15 @@ interface Engine {
        onError: ((String, Throwable) -> Unit) = { _, _ -> }
    ): Unit = onError(id, UnsupportedOperationException("Web extension support is not available in this engine"))

    /**
     * Registers a [WebExtensionTabDelegate] to be notified when web extensions attempt to open/close tabs.
     *
     * @param webExtensionTabDelegate callback is invoked when a web extension opens a new tab.
     */
    fun registerWebExtensionTabDelegate(
        webExtensionTabDelegate: WebExtensionTabDelegate
    ): Unit = throw UnsupportedOperationException("Web extension support is not available in this engine")

    /**
     * Clears browsing data stored by the engine.
     *
Loading