diff --git a/app/src/main/java/org/mozilla/fenix/addons/AddonInternalSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/AddonInternalSettingsFragment.kt index a19c65aa5..1b0926208 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/AddonInternalSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/AddonInternalSettingsFragment.kt @@ -8,30 +8,25 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.fragment.app.Fragment import androidx.navigation.fragment.navArgs import kotlinx.android.synthetic.main.fragment_add_on_internal_settings.* -import mozilla.components.concept.engine.EngineSession import mozilla.components.feature.addons.ui.translate import org.mozilla.fenix.R -import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.showToolbar /** * A fragment to show the internal settings of an add-on. */ -class AddonInternalSettingsFragment : Fragment() { +class AddonInternalSettingsFragment : AddonPopupBaseFragment() { private val args by navArgs() - private lateinit var engineSession: EngineSession override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - engineSession = requireComponents.core.engine.createSession() - + initializeSession() return inflater.inflate(R.layout.fragment_add_on_internal_settings, container, false) } @@ -43,12 +38,9 @@ class AddonInternalSettingsFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - addonSettingsEngineView.render(engineSession) - engineSession.loadUrl(args.addon.installedState!!.optionsPageUrl) - } - - override fun onDestroyView() { - engineSession.close() - super.onDestroyView() + engineSession?.let { engineSession -> + addonSettingsEngineView.render(engineSession) + engineSession.loadUrl(args.addon.installedState!!.optionsPageUrl) + } } } diff --git a/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt new file mode 100644 index 000000000..fbd94090c --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt @@ -0,0 +1,106 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.addons + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.Fragment +import androidx.navigation.fragment.NavHostFragment.findNavController +import androidx.navigation.fragment.findNavController +import mozilla.components.browser.state.action.ContentAction +import mozilla.components.browser.state.action.CustomTabListAction +import mozilla.components.browser.state.state.CustomTabSessionState +import mozilla.components.browser.state.state.EngineState +import mozilla.components.browser.state.state.SessionState +import mozilla.components.browser.state.state.createCustomTab +import mozilla.components.concept.engine.EngineSession +import mozilla.components.concept.engine.prompt.PromptRequest +import mozilla.components.concept.engine.window.WindowRequest +import mozilla.components.feature.prompts.PromptFeature +import mozilla.components.support.base.feature.ViewBoundFeatureWrapper +import org.mozilla.fenix.ext.requireComponents + +/** + * Provides shared functionality to our fragments for add-on settings and + * browser/page action popups. + */ +abstract class AddonPopupBaseFragment : Fragment(), EngineSession.Observer { + private val promptsFeature = ViewBoundFeatureWrapper() + + protected var session: SessionState? = null + protected var engineSession: EngineSession? = null + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + session?.let { + promptsFeature.set( + feature = PromptFeature( + fragment = this, + store = requireComponents.core.store, + customTabId = it.id, + fragmentManager = parentFragmentManager, + onNeedToRequestPermissions = { permissions -> + requestPermissions(permissions, REQUEST_CODE_PROMPT_PERMISSIONS) + }), + owner = this, + view = view + ) + } + } + + override fun onDestroyView() { + engineSession?.close() + session?.let { + requireComponents.core.store.dispatch(CustomTabListAction.RemoveCustomTabAction(it.id)) + } + super.onDestroyView() + } + + override fun onStart() { + super.onStart() + engineSession?.register(this) + } + + override fun onStop() { + super.onStop() + engineSession?.unregister(this) + } + + override fun onPromptRequest(promptRequest: PromptRequest) { + session?.let { session -> + requireComponents.core.store.dispatch( + ContentAction.UpdatePromptRequestAction( + session.id, + promptRequest + ) + ) + } + } + + override fun onWindowRequest(windowRequest: WindowRequest) { + if (windowRequest.type == WindowRequest.Type.CLOSE) { + findNavController().popBackStack() + } + } + + protected fun initializeSession(fromEngineSession: EngineSession? = null) { + engineSession = fromEngineSession ?: requireComponents.core.engine.createSession() + session = createCustomTab("").copy(engineState = EngineState(engineSession)) + requireComponents.core.store.dispatch(CustomTabListAction.AddCustomTabAction(session as CustomTabSessionState)) + } + + final override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + when (requestCode) { + REQUEST_CODE_PROMPT_PERMISSIONS -> promptsFeature.get()?.onPermissionsResult(permissions, grantResults) + } + } + + companion object { + private const val REQUEST_CODE_PROMPT_PERMISSIONS = 1 + } +} diff --git a/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt index ea34f112f..2a4d572a1 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt @@ -8,7 +8,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import kotlinx.android.synthetic.main.fragment_add_on_internal_settings.* @@ -16,7 +15,6 @@ 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.fenix.R import org.mozilla.fenix.ext.requireComponents @@ -25,10 +23,9 @@ import org.mozilla.fenix.ext.showToolbar /** * A fragment to show the web extension action popup with [EngineView]. */ -class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer { +class WebExtensionActionPopupFragment : AddonPopupBaseFragment(), EngineSession.Observer { private val args by navArgs() - private var engineSession: EngineSession? = null private val coreComponents by lazy { requireComponents.core } private val safeArguments get() = requireNotNull(arguments) private var sessionConsumed @@ -43,8 +40,8 @@ class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer { savedInstanceState: Bundle? ): View? { // Grab the [EngineSession] from the store when the view is created if it is available. - if (engineSession == null) { - engineSession = coreComponents.store.state.extensions[args.webExtensionId]?.popupSession + coreComponents.store.state.extensions[args.webExtensionId]?.popupSession?.let { + initializeSession(it) } return inflater.inflate(R.layout.fragment_add_on_internal_settings, container, false) @@ -56,22 +53,6 @@ class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer { showToolbar(title) } - override fun onStart() { - super.onStart() - engineSession?.register(this) - } - - override fun onStop() { - super.onStop() - engineSession?.unregister(this) - } - - override fun onWindowRequest(windowRequest: WindowRequest) { - if (windowRequest.type == WindowRequest.Type.CLOSE) { - activity?.onBackPressed() - } - } - @ExperimentalCoroutinesApi override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -86,6 +67,7 @@ class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer { state.extensions[args.webExtensionId]?.let { extState -> val popupSession = extState.popupSession if (popupSession != null) { + initializeSession(popupSession) addonSettingsEngineView.render(popupSession) popupSession.register(this) consumePopupSession()