Commit 0e690abd authored by MozLando's avatar MozLando
Browse files

Merge #7427



7427: Closes #7397: Integrate GV API for runtime.openOptionsPage r=Amejia481 a=csadilek

Decided to go with the simplest solution that works, similar to Fennec/Desktop, and open a new tab when the options page is triggered via JavaScript.

We may want to make this customizable in the future and support deep linking into our AddosManager/Addon/Settings UI, but this doesn't seem needed right now. It's also tricky for us as we don't use `about:addons`, but have a native UI instead. The user experience definitely feels better this way too.

Other changes:
- Use M3 add-ons so we can test decentraleyes etc.
- Make sure our action popup (in Sample Browser) responds to `window.close`

Co-authored-by: default avatarChristian Sadilek <christian.sadilek@gmail.com>
parents 9fe469d3 eed463d9
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -279,6 +279,17 @@ class GeckoWebExtension(
                )
                return GeckoResult.fromValue(geckoEngineSession.geckoSession)
            }

            override fun onOpenOptionsPage(ext: GeckoNativeWebExtension) {
                ext.metaData?.optionsPageUrl?.let { optionsPageUrl ->
                    tabHandler.onNewTab(
                        this@GeckoWebExtension,
                        GeckoEngineSession(runtime),
                        false,
                        optionsPageUrl
                    )
                }
            }
        }

        nativeExtension.tabDelegate = tabDelegate
+22 −6
Original line number Diff line number Diff line
@@ -334,17 +334,19 @@ class GeckoWebExtensionTest {
    @Test
    fun `register global tab handler`() {
        val runtime: GeckoRuntime = mock()
        whenever(runtime.settings).thenReturn(mock())
        whenever(runtime.webExtensionController).thenReturn(mock())
        val tabHandler: TabHandler = mock()
        val tabDelegateCaptor = argumentCaptor<WebExtension.TabDelegate>()
        val engineSessionCaptor = argumentCaptor<GeckoEngineSession>()

        val nativeGeckoWebExt = spy(WebExtension(
            "https://addons.mozilla.org/firefox/downloads/file/123/some_web_ext.xpi",
            "test-webext",
            WebExtension.Flags.NONE,
            runtime.webExtensionController
        ))
        val metaDataBundle = GeckoBundle()
        metaDataBundle.putStringArray("disabledFlags", emptyArray())
        val bundle = GeckoBundle()
        bundle.putString("webExtensionId", "test-webext")
        bundle.putString("locationURI", "https://addons.mozilla.org/firefox/downloads/file/123/some_web_ext.xpi")

        val nativeGeckoWebExt = spy(MockWebExtension(bundle))
        // Create extension and register global tab handler
        val extension = GeckoWebExtension(
            id = "mozacTest",
@@ -365,6 +367,20 @@ class GeckoWebExtensionTest {
        tabDelegateCaptor.value.onNewTab(nativeGeckoWebExt, tabDetails)
        verify(tabHandler).onNewTab(eq(extension), engineSessionCaptor.capture(), eq(true), eq("url"))
        assertNotNull(engineSessionCaptor.value)

        tabDelegateCaptor.value.onOpenOptionsPage(nativeGeckoWebExt)
        verify(tabHandler, never()).onNewTab(eq(extension), any(), eq(false), eq("http://options-page.moz"))

        bundle.putBundle("metaData", metaDataBundle)
        val nativeGeckoWebExtWithMetadata = MockWebExtension(bundle)
        tabDelegateCaptor.value.onOpenOptionsPage(nativeGeckoWebExtWithMetadata)
        verify(tabHandler, never()).onNewTab(eq(extension), any(), eq(false), eq("http://options-page.moz"))

        metaDataBundle.putString("optionsPageURL", "http://options-page.moz")
        bundle.putBundle("metaData", metaDataBundle)
        val nativeGeckoWebExtWithOptionsPageUrl = MockWebExtension(bundle)
        tabDelegateCaptor.value.onOpenOptionsPage(nativeGeckoWebExtWithOptionsPageUrl)
        verify(tabHandler).onNewTab(eq(extension), any(), eq(false), eq("http://options-page.moz"))
    }

    @Test
+1 −1
Original line number Diff line number Diff line
@@ -161,7 +161,7 @@ open class DefaultComponents(private val applicationContext: Context) {
        AddonCollectionProvider(
            applicationContext,
            client,
            collectionName = "16f6e5d9a40448b8955db57ced6d75",
            collectionName = "3204bb44a6ef44d39ee34917f28055",
            maxCacheAgeInMinutes = DAY_IN_MINUTES
        )
    }
+11 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.browser.state.action.WebExtensionAction
import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.EngineView
import mozilla.components.concept.engine.window.WindowRequest
import mozilla.components.lib.state.ext.consumeFrom
import org.mozilla.samples.browser.R
import org.mozilla.samples.browser.ext.components
@@ -51,7 +52,7 @@ class WebExtensionActionPopupActivity : AppCompatActivity() {
    /**
     * A fragment to show the web extension action popup with [EngineView].
     */
    class WebExtensionActionPopupFragment : Fragment() {
    class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer {
        private var engineSession: EngineSession? = null
        private lateinit var webExtensionId: String

@@ -69,6 +70,7 @@ class WebExtensionActionPopupActivity : AppCompatActivity() {
            val session = engineSession
            if (session != null) {
                addonSettingsEngineView.render(session)
                session.register(this, view)
                consumePopupSession()
            } else {
                consumeFrom(context!!.components.store) { state ->
@@ -76,6 +78,7 @@ class WebExtensionActionPopupActivity : AppCompatActivity() {
                        extState.popupSession?.let {
                            if (engineSession == null) {
                                addonSettingsEngineView.render(it)
                                it.register(this, view)
                                consumePopupSession()
                                engineSession = it
                            }
@@ -85,6 +88,13 @@ class WebExtensionActionPopupActivity : AppCompatActivity() {
            }
        }

        override fun onWindowRequest(windowRequest: WindowRequest) {
            if (windowRequest.type == WindowRequest.Type.CLOSE) {
                activity?.finish()
            } else {
                engineSession?.loadUrl(windowRequest.url)
            }
        }
        private fun consumePopupSession() {
            components.store.dispatch(
                WebExtensionAction.UpdatePopupSessionAction(webExtensionId, popupSession = null)