try mitigate initialization race condition
This commit is contained in:
+106
-31
@@ -21,12 +21,18 @@ import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.fragment.app.Fragment
|
||||
import eu.weblibre.flutter_mozilla_components.addons.WebExtensionActionPopupActivity
|
||||
import eu.weblibre.flutter_mozilla_components.addons.WebExtensionPromptFeature
|
||||
import eu.weblibre.flutter_mozilla_components.databinding.FragmentBrowserBinding
|
||||
import eu.weblibre.flutter_mozilla_components.ext.getPreferenceKey
|
||||
import eu.weblibre.flutter_mozilla_components.feature.ReadabilityExtractFeature
|
||||
import eu.weblibre.flutter_mozilla_components.feature.WebExtensionToolbarFeature
|
||||
import eu.weblibre.flutter_mozilla_components.integration.ReaderViewIntegration
|
||||
import eu.weblibre.flutter_mozilla_components.services.DownloadService
|
||||
import io.flutter.Log
|
||||
import mozilla.components.browser.state.selector.selectedTab
|
||||
import mozilla.components.browser.state.state.WebExtensionState
|
||||
import mozilla.components.browser.thumbnails.BrowserThumbnails
|
||||
import mozilla.components.concept.engine.EngineView
|
||||
import mozilla.components.feature.app.links.AppLinksFeature
|
||||
import mozilla.components.feature.downloads.DownloadsFeature
|
||||
@@ -43,6 +49,7 @@ import mozilla.components.feature.session.SwipeRefreshFeature
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsFeature
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules.AutoplayAction
|
||||
import mozilla.components.feature.tabs.WindowFeature
|
||||
import mozilla.components.feature.webauthn.WebAuthnFeature
|
||||
import mozilla.components.support.base.feature.ActivityResultHandler
|
||||
import mozilla.components.support.base.feature.PermissionsFeature
|
||||
@@ -52,6 +59,7 @@ import mozilla.components.support.base.log.logger.Logger
|
||||
import mozilla.components.support.ktx.android.view.enterImmersiveMode
|
||||
import mozilla.components.support.ktx.android.view.exitImmersiveMode
|
||||
import mozilla.components.support.locale.ActivityContextWrapper
|
||||
import mozilla.components.support.webextensions.WebExtensionPopupObserver
|
||||
|
||||
/**
|
||||
* Base fragment extended by [BrowserFragment] and [ExternalAppBrowserFragment].
|
||||
@@ -77,6 +85,13 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
|
||||
|
||||
private var pictureInPictureFeature: PictureInPictureFeature? = null
|
||||
|
||||
private val windowFeature = ViewBoundFeatureWrapper<WindowFeature>()
|
||||
private val thumbnailsFeature = ViewBoundFeatureWrapper<BrowserThumbnails>()
|
||||
val readerViewFeature = ViewBoundFeatureWrapper<ReaderViewIntegration>()
|
||||
private val readabilityExtractFeature = ViewBoundFeatureWrapper<ReadabilityExtractFeature>()
|
||||
private val webExtensionPopupObserver = ViewBoundFeatureWrapper<WebExtensionPopupObserver>()
|
||||
private val webExtToolbarFeature = ViewBoundFeatureWrapper<WebExtensionToolbarFeature>()
|
||||
|
||||
// Registers a photo picker activity launcher in single-select mode.
|
||||
private val singleMediaPicker =
|
||||
AndroidPhotoPicker.singleMediaPicker(
|
||||
@@ -160,6 +175,49 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
|
||||
@CallSuper
|
||||
@Suppress("LongMethod")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
view.post {
|
||||
if (GlobalComponents.components != null) {
|
||||
createAndSetupEngine(view)
|
||||
} else {
|
||||
// Retry or handle error
|
||||
view.postDelayed({ createAndSetupEngine(view) }, 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun restartApp(context: Context) {
|
||||
val packageManager = context.packageManager
|
||||
val intent = packageManager.getLaunchIntentForPackage(context.packageName)
|
||||
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
intent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
context.startActivity(intent)
|
||||
|
||||
if (context is Activity) {
|
||||
context.finish()
|
||||
}
|
||||
|
||||
Runtime.getRuntime().exit(0)
|
||||
}
|
||||
|
||||
private fun createAndSetupEngine(view: View) {
|
||||
try {
|
||||
// Set layout parameters
|
||||
val layoutParams = FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
FrameLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
|
||||
val engineView = createEngine(components)
|
||||
val originalContext = ActivityContextWrapper.getOriginalContext(requireActivity())
|
||||
val engineNativeView = engineView.asView()
|
||||
engineNativeView.layoutParams = layoutParams
|
||||
|
||||
engineView.setActivityContext(originalContext)
|
||||
|
||||
binding.swipeToRefresh.addView(engineNativeView)
|
||||
|
||||
components.engineView = engineView
|
||||
|
||||
sessionFeature.set(
|
||||
feature = SessionFeature(
|
||||
components.core.store,
|
||||
@@ -338,53 +396,70 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
}
|
||||
|
||||
private fun restartApp(context: Context) {
|
||||
val packageManager = context.packageManager
|
||||
val intent = packageManager.getLaunchIntentForPackage(context.packageName)
|
||||
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
intent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
context.startActivity(intent)
|
||||
|
||||
if (context is Activity) {
|
||||
context.finish()
|
||||
}
|
||||
|
||||
Runtime.getRuntime().exit(0)
|
||||
}
|
||||
|
||||
private fun createAndSetupEngine() {
|
||||
try {
|
||||
// Set layout parameters
|
||||
val layoutParams = FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
FrameLayout.LayoutParams.MATCH_PARENT
|
||||
readerViewFeature.set(
|
||||
feature = ReaderViewIntegration(
|
||||
requireContext(),
|
||||
components.core.engine,
|
||||
components.core.store,
|
||||
binding.readerViewBar,
|
||||
components.events.readerViewEvents,
|
||||
components.readerViewController,
|
||||
),
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
val engineView = createEngine(components)
|
||||
val originalContext = ActivityContextWrapper.getOriginalContext(requireActivity())
|
||||
val engineNativeView = engineView.asView()
|
||||
engineNativeView.layoutParams = layoutParams
|
||||
readabilityExtractFeature.set(
|
||||
feature = components.features.readabilityExtractFeature,
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
engineView.setActivityContext(originalContext)
|
||||
windowFeature.set(
|
||||
feature = WindowFeature(components.core.store, components.useCases.tabsUseCases),
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
binding.swipeToRefresh.addView(engineNativeView)
|
||||
thumbnailsFeature.set(
|
||||
feature = BrowserThumbnails(requireContext(), components.engineView!!, components.core.store),
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
webExtensionPopupObserver.set(
|
||||
feature = WebExtensionPopupObserver(components.core.store, ::openPopup),
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
webExtToolbarFeature.set(
|
||||
feature = components.features.webExtensionToolbarFeature,
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
components.core.historyStorage.registerStorageMaintenanceWorker()
|
||||
|
||||
components.engineView = engineView
|
||||
} catch (e: Exception) {
|
||||
Log.e("EngineCreation", "Failed to create engine: ${e.message}", e)
|
||||
context?.let { restartApp(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun openPopup(webExtensionState: WebExtensionState) {
|
||||
val intent = Intent(requireContext().applicationContext, WebExtensionActionPopupActivity::class.java)
|
||||
intent.putExtra("web_extension_id", webExtensionState.id)
|
||||
intent.putExtra("web_extension_name", webExtensionState.name)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Suppress("LongMethod")
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
_binding = FragmentBrowserBinding.inflate(inflater, container, false)
|
||||
|
||||
createAndSetupEngine()
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
|
||||
+1
-61
@@ -27,13 +27,6 @@ import mozilla.components.support.webextensions.WebExtensionPopupObserver
|
||||
* Fragment used for browsing the web within the main app.
|
||||
*/
|
||||
class BrowserFragment() : BaseBrowserFragment(), UserInteractionHandler {
|
||||
private val windowFeature = ViewBoundFeatureWrapper<WindowFeature>()
|
||||
private val thumbnailsFeature = ViewBoundFeatureWrapper<BrowserThumbnails>()
|
||||
private val readerViewFeature = ViewBoundFeatureWrapper<ReaderViewIntegration>()
|
||||
private val readabilityExtractFeature = ViewBoundFeatureWrapper<ReadabilityExtractFeature>()
|
||||
private val webExtensionPopupObserver = ViewBoundFeatureWrapper<WebExtensionPopupObserver>()
|
||||
private val webExtToolbarFeature = ViewBoundFeatureWrapper<WebExtensionToolbarFeature>()
|
||||
|
||||
override fun createEngine(components: Components): EngineView {
|
||||
return components.core.engine.createView(requireContext()).apply {
|
||||
selectionActionDelegate = components.selectionAction
|
||||
@@ -49,63 +42,10 @@ class BrowserFragment() : BaseBrowserFragment(), UserInteractionHandler {
|
||||
@Suppress("LongMethod")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
readerViewFeature.set(
|
||||
feature = ReaderViewIntegration(
|
||||
requireContext(),
|
||||
components.core.engine,
|
||||
components.core.store,
|
||||
binding.readerViewBar,
|
||||
components.events.readerViewEvents,
|
||||
components.readerViewController,
|
||||
),
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
readabilityExtractFeature.set(
|
||||
feature = components.features.readabilityExtractFeature,
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
windowFeature.set(
|
||||
feature = WindowFeature(components.core.store, components.useCases.tabsUseCases),
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
thumbnailsFeature.set(
|
||||
feature = BrowserThumbnails(requireContext(), components.engineView!!, components.core.store),
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
webExtensionPopupObserver.set(
|
||||
feature = WebExtensionPopupObserver(components.core.store, ::openPopup),
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
webExtToolbarFeature.set(
|
||||
feature = components.features.webExtensionToolbarFeature,
|
||||
owner = this,
|
||||
view = view,
|
||||
)
|
||||
|
||||
components.core.historyStorage.registerStorageMaintenanceWorker()
|
||||
}
|
||||
|
||||
private fun openPopup(webExtensionState: WebExtensionState) {
|
||||
val intent = Intent(requireContext().applicationContext, WebExtensionActionPopupActivity::class.java)
|
||||
intent.putExtra("web_extension_id", webExtensionState.id)
|
||||
intent.putExtra("web_extension_name", webExtensionState.name)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean =
|
||||
readerViewFeature.onBackPressed() || super.onBackPressed()
|
||||
super.readerViewFeature.onBackPressed() || super.onBackPressed()
|
||||
|
||||
companion object {
|
||||
fun create(sessionId: String? = null) = BrowserFragment().apply {
|
||||
|
||||
Reference in New Issue
Block a user