1
0
Fork 0

For #8143: Allow add-on popups to display prompts

master
Christian Sadilek 2020-02-13 12:35:59 -05:00
parent 9adc617765
commit 40031e6130
3 changed files with 116 additions and 36 deletions

View File

@ -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<AddonInternalSettingsFragmentArgs>()
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)
engineSession?.let { engineSession ->
addonSettingsEngineView.render(engineSession)
engineSession.loadUrl(args.addon.installedState!!.optionsPageUrl)
}
override fun onDestroyView() {
engineSession.close()
super.onDestroyView()
}
}

View File

@ -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<PromptFeature>()
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<String>,
grantResults: IntArray
) {
when (requestCode) {
REQUEST_CODE_PROMPT_PERMISSIONS -> promptsFeature.get()?.onPermissionsResult(permissions, grantResults)
}
}
companion object {
private const val REQUEST_CODE_PROMPT_PERMISSIONS = 1
}
}

View File

@ -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<WebExtensionActionPopupFragmentArgs>()
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()