Loading components/feature/pwa/src/main/java/mozilla/components/feature/pwa/ManifestStorage.kt +13 −2 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ package mozilla.components.feature.pwa import android.content.Context import androidx.annotation.VisibleForTesting import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.withContext import mozilla.components.concept.engine.manifest.WebAppManifest import mozilla.components.feature.pwa.db.ManifestDatabase Loading @@ -33,7 +34,7 @@ class ManifestStorage(context: Context) { /** * Save a Web App Manifest to disk. */ suspend fun saveManifest(manifest: WebAppManifest) = withContext(Dispatchers.IO) { suspend fun saveManifest(manifest: WebAppManifest) = withContext(IO) { val entity = ManifestEntity( manifest = manifest, updatedAt = System.currentTimeMillis(), Loading @@ -42,10 +43,20 @@ class ManifestStorage(context: Context) { manifestDao.value.insertManifest(entity) } /** * Update an existing Web App Manifest on disk. */ suspend fun updateManifest(manifest: WebAppManifest) = withContext(IO) { manifestDao.value.getManifest(manifest.startUrl)?.let { existing -> val update = existing.copy(manifest = manifest, updatedAt = System.currentTimeMillis()) manifestDao.value.updateManifest(update) } } /** * Delete all manifests associated with the list of URLs. */ suspend fun removeManifests(startUrls: List<String>) = withContext(Dispatchers.IO) { suspend fun removeManifests(startUrls: List<String>) = withContext(IO) { manifestDao.value.deleteManifests(startUrls) } } components/feature/pwa/src/main/java/mozilla/components/feature/pwa/WebAppShortcutManager.kt +1 −1 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ const val SHORTCUT_CATEGORY = "mozilla.components.pwa.category.SHORTCUT" class WebAppShortcutManager( context: Context, httpClient: Client, private val storage: ManifestStorage = ManifestStorage(context), private val storage: ManifestStorage, internal val supportWebApps: Boolean = true ) { Loading components/feature/pwa/src/main/java/mozilla/components/feature/pwa/WebAppUseCases.kt +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ class WebAppUseCases( WebAppShortcutManager( applicationContext, httpClient, storage = ManifestStorage(applicationContext), supportWebApps = supportWebApps ) ) Loading components/feature/pwa/src/main/java/mozilla/components/feature/pwa/db/ManifestDao.kt +5 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Update /** * Internal DAO for accessing [ManifestEntity] instances. Loading @@ -23,6 +24,10 @@ internal interface ManifestDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertManifest(manifest: ManifestEntity): Long @WorkerThread @Update fun updateManifest(manifest: ManifestEntity) @WorkerThread @Query("DELETE FROM manifests WHERE start_url IN (:startUrls)") fun deleteManifests(startUrls: List<String>) Loading components/feature/pwa/src/main/java/mozilla/components/feature/pwa/feature/ManifestUpdateFeature.kt 0 → 100644 +72 −0 Original line number Diff line number Diff line /* 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 mozilla.components.feature.pwa.feature import android.content.Context import androidx.annotation.VisibleForTesting import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.MainScope import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.concept.engine.manifest.WebAppManifest import mozilla.components.feature.pwa.ManifestStorage import mozilla.components.feature.pwa.WebAppShortcutManager import mozilla.components.support.base.feature.LifecycleAwareFeature /** * Feature used to update the existing web app manifest and web app shortcut. * * @param shortcutManager Shortcut manager used to update pinned shortcuts. * @param storage Manifest storage used to have updated manifests. * @param sessionId ID of the web app session to observe. * @param initialManifest Loaded manifest for the current web app. */ class ManifestUpdateFeature( private val applicationContext: Context, private val sessionManager: SessionManager, private val shortcutManager: WebAppShortcutManager, private val storage: ManifestStorage, private val sessionId: String, private var initialManifest: WebAppManifest ) : Session.Observer, LifecycleAwareFeature { private var scope: CoroutineScope? = null private var updateJob: Job? = null /** * When the manifest is changed, compare it to the existing manifest. * If it is different, update the disk and shortcut. Ignore if called with a null * manifest or a manifest with a different start URL. */ override fun onWebAppManifestChanged(session: Session, manifest: WebAppManifest?) { if (manifest?.startUrl == initialManifest.startUrl && manifest != initialManifest) { updateJob?.cancel() updateJob = scope?.launch { updateStoredManifest(manifest) } } } /** * Updates the manifest on disk then updates the pinned shortcut to reflect changes. */ @VisibleForTesting internal suspend fun updateStoredManifest(manifest: WebAppManifest) { storage.updateManifest(manifest) shortcutManager.updateShortcuts(applicationContext, listOf(manifest)) initialManifest = manifest } override fun start() { scope = MainScope() sessionManager.findSessionById(sessionId)?.register(this) } override fun stop() { scope?.cancel() sessionManager.findSessionById(sessionId)?.unregister(this) } } Loading
components/feature/pwa/src/main/java/mozilla/components/feature/pwa/ManifestStorage.kt +13 −2 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ package mozilla.components.feature.pwa import android.content.Context import androidx.annotation.VisibleForTesting import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.withContext import mozilla.components.concept.engine.manifest.WebAppManifest import mozilla.components.feature.pwa.db.ManifestDatabase Loading @@ -33,7 +34,7 @@ class ManifestStorage(context: Context) { /** * Save a Web App Manifest to disk. */ suspend fun saveManifest(manifest: WebAppManifest) = withContext(Dispatchers.IO) { suspend fun saveManifest(manifest: WebAppManifest) = withContext(IO) { val entity = ManifestEntity( manifest = manifest, updatedAt = System.currentTimeMillis(), Loading @@ -42,10 +43,20 @@ class ManifestStorage(context: Context) { manifestDao.value.insertManifest(entity) } /** * Update an existing Web App Manifest on disk. */ suspend fun updateManifest(manifest: WebAppManifest) = withContext(IO) { manifestDao.value.getManifest(manifest.startUrl)?.let { existing -> val update = existing.copy(manifest = manifest, updatedAt = System.currentTimeMillis()) manifestDao.value.updateManifest(update) } } /** * Delete all manifests associated with the list of URLs. */ suspend fun removeManifests(startUrls: List<String>) = withContext(Dispatchers.IO) { suspend fun removeManifests(startUrls: List<String>) = withContext(IO) { manifestDao.value.deleteManifests(startUrls) } }
components/feature/pwa/src/main/java/mozilla/components/feature/pwa/WebAppShortcutManager.kt +1 −1 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ const val SHORTCUT_CATEGORY = "mozilla.components.pwa.category.SHORTCUT" class WebAppShortcutManager( context: Context, httpClient: Client, private val storage: ManifestStorage = ManifestStorage(context), private val storage: ManifestStorage, internal val supportWebApps: Boolean = true ) { Loading
components/feature/pwa/src/main/java/mozilla/components/feature/pwa/WebAppUseCases.kt +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ class WebAppUseCases( WebAppShortcutManager( applicationContext, httpClient, storage = ManifestStorage(applicationContext), supportWebApps = supportWebApps ) ) Loading
components/feature/pwa/src/main/java/mozilla/components/feature/pwa/db/ManifestDao.kt +5 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Update /** * Internal DAO for accessing [ManifestEntity] instances. Loading @@ -23,6 +24,10 @@ internal interface ManifestDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertManifest(manifest: ManifestEntity): Long @WorkerThread @Update fun updateManifest(manifest: ManifestEntity) @WorkerThread @Query("DELETE FROM manifests WHERE start_url IN (:startUrls)") fun deleteManifests(startUrls: List<String>) Loading
components/feature/pwa/src/main/java/mozilla/components/feature/pwa/feature/ManifestUpdateFeature.kt 0 → 100644 +72 −0 Original line number Diff line number Diff line /* 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 mozilla.components.feature.pwa.feature import android.content.Context import androidx.annotation.VisibleForTesting import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.MainScope import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.concept.engine.manifest.WebAppManifest import mozilla.components.feature.pwa.ManifestStorage import mozilla.components.feature.pwa.WebAppShortcutManager import mozilla.components.support.base.feature.LifecycleAwareFeature /** * Feature used to update the existing web app manifest and web app shortcut. * * @param shortcutManager Shortcut manager used to update pinned shortcuts. * @param storage Manifest storage used to have updated manifests. * @param sessionId ID of the web app session to observe. * @param initialManifest Loaded manifest for the current web app. */ class ManifestUpdateFeature( private val applicationContext: Context, private val sessionManager: SessionManager, private val shortcutManager: WebAppShortcutManager, private val storage: ManifestStorage, private val sessionId: String, private var initialManifest: WebAppManifest ) : Session.Observer, LifecycleAwareFeature { private var scope: CoroutineScope? = null private var updateJob: Job? = null /** * When the manifest is changed, compare it to the existing manifest. * If it is different, update the disk and shortcut. Ignore if called with a null * manifest or a manifest with a different start URL. */ override fun onWebAppManifestChanged(session: Session, manifest: WebAppManifest?) { if (manifest?.startUrl == initialManifest.startUrl && manifest != initialManifest) { updateJob?.cancel() updateJob = scope?.launch { updateStoredManifest(manifest) } } } /** * Updates the manifest on disk then updates the pinned shortcut to reflect changes. */ @VisibleForTesting internal suspend fun updateStoredManifest(manifest: WebAppManifest) { storage.updateManifest(manifest) shortcutManager.updateShortcuts(applicationContext, listOf(manifest)) initialManifest = manifest } override fun start() { scope = MainScope() sessionManager.findSessionById(sessionId)?.register(this) } override fun stop() { scope?.cancel() sessionManager.findSessionById(sessionId)?.unregister(this) } }