Skip to content

Commit

Permalink
Refactor download manager
Browse files Browse the repository at this point in the history
  • Loading branch information
qnga committed Sep 4, 2023
1 parent fd9af69 commit 70f6dd1
Show file tree
Hide file tree
Showing 23 changed files with 697 additions and 721 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ internal class LcpDownloadsRepository(
private val snapshot: MutableMap<String, JSONObject> =
storageFile.readText(Charsets.UTF_8).toData().toMutableMap()

fun getIds(): List<String> {
return snapshot.keys.toList()
}

fun addDownload(id: String, license: JSONObject) {
snapshot[id] = license
storageFile.writeText(snapshot.toJson(), Charsets.UTF_8)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@ import org.readium.r2.shared.extensions.tryOrLog
import org.readium.r2.shared.util.Try
import org.readium.r2.shared.util.Url
import org.readium.r2.shared.util.downloads.DownloadManager
import org.readium.r2.shared.util.downloads.DownloadManagerProvider
import org.readium.r2.shared.util.mediatype.FormatRegistry
import org.readium.r2.shared.util.mediatype.MediaType
import org.readium.r2.shared.util.mediatype.MediaTypeRetriever

public class LcpPublicationRetriever(
context: Context,
private val listener: Listener,
downloadManagerProvider: DownloadManagerProvider,
private val downloadManager: DownloadManager,
private val mediaTypeRetriever: MediaTypeRetriever
) {

Expand Down Expand Up @@ -55,8 +53,21 @@ public class LcpPublicationRetriever(
file: File
) {
val lcpRequestId = RequestId(requestId.value)

val license = LicenseDocument(downloadsRepository.retrieveLicense(requestId.value)!!)
val listenersForId = listeners[lcpRequestId].orEmpty()

val license = downloadsRepository.retrieveLicense(requestId.value)
?.let { LicenseDocument(it) }
?: run {
listenersForId.forEach {
it.onAcquisitionFailed(
lcpRequestId,
LcpException.wrap(
Exception("Couldn't retrieve license from local storage.")
)
)
}
return
}
downloadsRepository.removeDownload(requestId.value)

val link = license.link(LicenseDocument.Rel.Publication)!!
Expand All @@ -70,7 +81,9 @@ public class LcpPublicationRetriever(
container.write(license)
} catch (e: Exception) {
tryOrLog { file.delete() }
listener.onAcquisitionFailed(lcpRequestId, LcpException.wrap(e))
listenersForId.forEach {
it.onAcquisitionFailed(lcpRequestId, LcpException.wrap(e))
}
return
}

Expand All @@ -81,48 +94,72 @@ public class LcpPublicationRetriever(
licenseDocument = license
)

listener.onAcquisitionCompleted(lcpRequestId, acquiredPublication)
listenersForId.forEach {
it.onAcquisitionCompleted(lcpRequestId, acquiredPublication)
}
listeners.remove(lcpRequestId)
}

override fun onDownloadProgressed(
requestId: DownloadManager.RequestId,
downloaded: Long,
expected: Long?
) {
listener.onAcquisitionProgressed(
RequestId(requestId.value),
downloaded,
expected
)
val lcpRequestId = RequestId(requestId.value)
val listenersForId = listeners[lcpRequestId].orEmpty()

listenersForId.forEach {
it.onAcquisitionProgressed(
lcpRequestId,
downloaded,
expected
)
}
}

override fun onDownloadFailed(
requestId: DownloadManager.RequestId,
error: DownloadManager.Error
) {
listener.onAcquisitionFailed(
RequestId(requestId.value),
LcpException.Network(Exception(error.message))
)
val lcpRequestId = RequestId(requestId.value)
val listenersForId = listeners[lcpRequestId].orEmpty()

listenersForId.forEach {
it.onAcquisitionFailed(
lcpRequestId,
LcpException.Network(Exception(error.message))
)
}

listeners.remove(lcpRequestId)
}
}

private val downloadManager: DownloadManager =
downloadManagerProvider.createDownloadManager(
DownloadListener(),
LcpPublicationRetriever::class.qualifiedName!!
)

private val formatRegistry: FormatRegistry =
FormatRegistry()

private val downloadsRepository: LcpDownloadsRepository =
LcpDownloadsRepository(context)

public suspend fun retrieve(
private val downloadListener: DownloadManager.Listener =
DownloadListener()

private val listeners: MutableMap<RequestId, MutableList<Listener>> =
mutableMapOf()

public fun register(
requestId: RequestId,
listener: Listener
) {
listeners.getOrPut(requestId) { mutableListOf() }.add(listener)
downloadManager.register(DownloadManager.RequestId(requestId.value), downloadListener)
}

public fun retrieve(
license: ByteArray,
downloadTitle: String,
downloadDescription: String? = null
downloadDescription: String? = null,
listener: Listener
): Try<RequestId, LcpException> {
return try {
val licenseDocument = LicenseDocument(license)
Expand All @@ -131,34 +168,32 @@ public class LcpPublicationRetriever(
downloadTitle,
downloadDescription
)
register(requestId, listener)
Try.success(requestId)
} catch (e: Exception) {
Try.failure(LcpException.wrap(e))
}
}

public suspend fun retrieve(
public fun retrieve(
license: File,
downloadTitle: String,
downloadDescription: String
downloadDescription: String,
listener: Listener
): Try<RequestId, LcpException> {
return try {
retrieve(license.readBytes(), downloadTitle, downloadDescription)
retrieve(license.readBytes(), downloadTitle, downloadDescription, listener)
} catch (e: Exception) {
Try.failure(LcpException.wrap(e))
}
}

public suspend fun close() {
downloadManager.close()
}

public suspend fun cancel(requestId: RequestId) {
public fun cancel(requestId: RequestId) {
downloadManager.cancel(DownloadManager.RequestId(requestId.value))
downloadsRepository.removeDownload(requestId.value)
}

private suspend fun fetchPublication(
private fun fetchPublication(
license: LicenseDocument,
downloadTitle: String,
downloadDescription: String?
Expand All @@ -168,12 +203,13 @@ public class LcpPublicationRetriever(
?: throw LcpException.Parsing.Url(rel = LicenseDocument.Rel.Publication.value)

val requestId = downloadManager.submit(
DownloadManager.Request(
request = DownloadManager.Request(
url = Url(url),
title = downloadTitle,
description = downloadDescription,
headers = emptyMap()
)
),
listener = downloadListener
)

downloadsRepository.addDownload(requestId.value, license.json)
Expand Down
14 changes: 4 additions & 10 deletions readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import org.readium.r2.shared.asset.Asset
import org.readium.r2.shared.asset.AssetRetriever
import org.readium.r2.shared.publication.protection.ContentProtection
import org.readium.r2.shared.util.Try
import org.readium.r2.shared.util.downloads.DownloadManagerProvider
import org.readium.r2.shared.util.downloads.DownloadManager
import org.readium.r2.shared.util.mediatype.MediaType
import org.readium.r2.shared.util.mediatype.MediaTypeRetriever

Expand Down Expand Up @@ -128,14 +128,8 @@ public interface LcpService {
* Creates a [LcpPublicationRetriever] instance which can be used to acquire a protected
* publication from standalone LCPL's bytes.
*
* You should use only one instance of [LcpPublicationRetriever] in your app. If you don't,
* behaviour is undefined.
*
* @param listener listener to implement to be notified about the status of the downloads.
*/
public fun publicationRetriever(
listener: LcpPublicationRetriever.Listener
): LcpPublicationRetriever
public fun publicationRetriever(): LcpPublicationRetriever

/**
* Creates a [ContentProtection] instance which can be used with a Streamer to unlock
Expand Down Expand Up @@ -180,7 +174,7 @@ public interface LcpService {
context: Context,
assetRetriever: AssetRetriever,
mediaTypeRetriever: MediaTypeRetriever,
downloadManagerProvider: DownloadManagerProvider
downloadManager: DownloadManager
): LcpService? {
if (!LcpClient.isAvailable()) {
return null
Expand All @@ -207,7 +201,7 @@ public interface LcpService {
context = context,
assetRetriever = assetRetriever,
mediaTypeRetriever = mediaTypeRetriever,
downloadManagerProvider = downloadManagerProvider
downloadManager = downloadManager
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import org.readium.r2.shared.asset.AssetRetriever
import org.readium.r2.shared.extensions.tryOr
import org.readium.r2.shared.publication.protection.ContentProtection
import org.readium.r2.shared.util.Try
import org.readium.r2.shared.util.downloads.DownloadManagerProvider
import org.readium.r2.shared.util.downloads.DownloadManager
import org.readium.r2.shared.util.mediatype.FormatRegistry
import org.readium.r2.shared.util.mediatype.MediaType
import org.readium.r2.shared.util.mediatype.MediaTypeRetriever
Expand All @@ -50,7 +50,7 @@ internal class LicensesService(
private val context: Context,
private val assetRetriever: AssetRetriever,
private val mediaTypeRetriever: MediaTypeRetriever,
private val downloadManagerProvider: DownloadManagerProvider
private val downloadManager: DownloadManager
) : LcpService, CoroutineScope by MainScope() {

override suspend fun isLcpProtected(file: File): Boolean {
Expand All @@ -75,13 +75,10 @@ internal class LicensesService(
): ContentProtection =
LcpContentProtection(this, authentication, assetRetriever)

override fun publicationRetriever(
listener: LcpPublicationRetriever.Listener
): LcpPublicationRetriever {
override fun publicationRetriever(): LcpPublicationRetriever {
return LcpPublicationRetriever(
context,
listener,
downloadManagerProvider,
downloadManager,
mediaTypeRetriever
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,11 @@ public interface DownloadManager {
public fun onDownloadFailed(requestId: RequestId, error: Error)
}

public suspend fun submit(request: Request): RequestId
public fun submit(request: Request, listener: Listener): RequestId

public suspend fun cancel(requestId: RequestId)
public fun register(requestId: RequestId, listener: Listener)

public suspend fun close()
public fun cancel(requestId: RequestId)

public fun close()
}

This file was deleted.

Loading

0 comments on commit 70f6dd1

Please sign in to comment.