Skip to content

Commit

Permalink
Fully implement LCP streaming
Browse files Browse the repository at this point in the history
This implements the mountain of changes required to implement LCP
audiobook streaming in a somewhat backwards-compatible manner.

* Switch to the 14.0.0-SNAPSHOT branch of the audiobooks components.

* The app is no longer responsible for downloading the contents of
  LCP audiobooks: This is handled by the audiobooks components, and
  old book files are copied into the audiobooks components storage
  as a compatibility measure (otherwise users would have to download
  books all over again).

* Numerous adjustments were made to the taskrecorder API to better
  capture error information.

Affects: https://ebce-lyrasis.atlassian.net/browse/PP-256
Affects: https://ebce-lyrasis.atlassian.net/browse/PP-405
Affects: https://ebce-lyrasis.atlassian.net/browse/PP-902
  • Loading branch information
io7m committed Jul 31, 2024
1 parent 284990e commit a21ee42
Show file tree
Hide file tree
Showing 98 changed files with 2,406 additions and 2,606 deletions.
2 changes: 1 addition & 1 deletion org.thepalaceproject.android.platform
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class AccountProviderRegistry private constructor(
@Volatile
private var statusRef: AccountProviderRegistryStatus = Idle

private val descriptions = Collections.synchronizedMap(LinkedHashMap<URI, AccountProviderDescription>())
private val descriptions =
Collections.synchronizedMap(LinkedHashMap<URI, AccountProviderDescription>())
private val descriptionsReadOnly = Collections.unmodifiableMap(this.descriptions)
private val resolved = ConcurrentHashMap<URI, AccountProviderType>()
private val resolvedReadOnly = Collections.unmodifiableMap(this.resolved)
Expand Down Expand Up @@ -87,6 +88,7 @@ class AccountProviderRegistry private constructor(
this.updateDescription(newDescriptions[key]!!)
}
}

is AccountProviderSourceType.SourceResult.SourceFailed -> {
this.eventsActual.onNext(SourceFailed(source.javaClass, result.exception))
}
Expand Down Expand Up @@ -118,6 +120,7 @@ class AccountProviderRegistry private constructor(
this.updateDescription(newDescriptions[key]!!)
}
}

is AccountProviderSourceType.SourceResult.SourceFailed -> {
this.eventsActual.onNext(SourceFailed(source.javaClass, result.exception))
}
Expand Down Expand Up @@ -202,20 +205,27 @@ class AccountProviderRegistry private constructor(
this.updateDescription(result.result.toDescription())
taskRecorder.finishSuccess(result.result)
}

is TaskResult.Failure -> taskRecorder.finishFailure()
}
}
}

taskRecorder.currentStepFailed(
"No sources can resolve the given description.",
"noApplicableSource ${description.id} ${description.title}"
message = "No sources can resolve the given description.",
errorCode = "noApplicableSource ${description.id} ${description.title}",
extraMessages = listOf()
)
return taskRecorder.finishFailure()
} catch (e: Exception) {
this.logger.error("resolution exception: ", e)
val message = e.message ?: e.javaClass.canonicalName ?: "unknown"
taskRecorder.currentStepFailedAppending(message, "unexpectedException", e)
taskRecorder.currentStepFailedAppending(
message = message,
errorCode = "unexpectedException",
exception = e,
extraMessages = listOf()
)
return taskRecorder.finishFailure()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ class AccountProviderResolution(
taskRecorder.currentStepFailedAppending(
message = this.stringResources.resolvingUnexpectedException,
errorCode = unexpectedException(this.description),
exception = e
exception = e,
extraMessages = listOf()
)
taskRecorder.finishFailure()
}
Expand Down Expand Up @@ -201,7 +202,11 @@ class AccountProviderResolution(
}

val message = this.stringResources.resolvingAuthDocumentNoStartURI
taskRecorder.currentStepFailed(message, authDocumentUnusable(this.description))
taskRecorder.currentStepFailed(
message = message,
errorCode = authDocumentUnusable(this.description),
extraMessages = listOf()
)
onProgress.invoke(this.description.id, message)
throw IOException()
}
Expand Down Expand Up @@ -252,6 +257,7 @@ class AccountProviderResolution(
this.extractAuthenticationDescriptionSAML20(taskRecorder, authObject)
)
}

BASIC_TOKEN_TYPE -> {
authObjects.add(
extractAuthenticationDescriptionBasicToken(taskRecorder, authObject)
Expand Down Expand Up @@ -279,7 +285,11 @@ class AccountProviderResolution(
}

val message = this.stringResources.resolvingAuthDocumentNoUsableAuthenticationTypes
taskRecorder.currentStepFailed(message, authDocumentUnusable(this.description))
taskRecorder.currentStepFailed(
message = message,
errorCode = authDocumentUnusable(this.description),
extraMessages = listOf()
)
throw IOException(message)
}

Expand All @@ -295,7 +305,11 @@ class AccountProviderResolution(
val authenticateURI = authenticate?.hrefURI
if (authenticateURI == null) {
val message = this.stringResources.resolvingAuthDocumentSAML20Malformed
taskRecorder.currentStepFailed(message, authDocumentUnusable(this.description))
taskRecorder.currentStepFailed(
message = message,
errorCode = authDocumentUnusable(this.description),
extraMessages = listOf()
)
throw IOException(message)
}

Expand All @@ -318,7 +332,11 @@ class AccountProviderResolution(
val authenticateURI = authenticate?.hrefURI
if (authenticateURI == null) {
val message = this.stringResources.resolvingAuthDocumentOAuthMalformed
taskRecorder.currentStepFailed(message, authDocumentUnusable(this.description))
taskRecorder.currentStepFailed(
message = message,
errorCode = authDocumentUnusable(this.description),
extraMessages = listOf()
)
throw IOException(message)
}

Expand Down Expand Up @@ -361,7 +379,11 @@ class AccountProviderResolution(
val authenticateURI = authenticate?.hrefURI
if (authenticateURI == null) {
val message = this.stringResources.resolvingAuthDocumentBasicTokenMalformed
taskRecorder.currentStepFailed(message, authDocumentUnusable(this.description))
taskRecorder.currentStepFailed(
message = message,
errorCode = authDocumentUnusable(this.description),
extraMessages = listOf()
)
throw IOException(message)
}

Expand Down Expand Up @@ -420,7 +442,11 @@ class AccountProviderResolution(
)
} else {
val message = this.stringResources.resolvingAuthDocumentCOPPAAgeGateMalformed
taskRecorder.currentStepFailed(message, authDocumentUnusable(this.description))
taskRecorder.currentStepFailed(
message = message,
errorCode = authDocumentUnusable(this.description),
extraMessages = listOf()
)
throw IOException(message)
}
}
Expand Down Expand Up @@ -472,12 +498,13 @@ class AccountProviderResolution(
} else {
val message = this.stringResources.resolvingAuthDocumentRetrievalFailed
taskRecorder.currentStepFailed(
message,
httpRequestFailed(
message = message,
errorCode = httpRequestFailed(
targetLink.hrefURI,
status.properties.originalStatus,
status.properties.message
)
),
extraMessages = listOf()
)
throw IOException(message)
}
Expand All @@ -491,7 +518,11 @@ class AccountProviderResolution(

is Link.LinkTemplated -> {
val message = this.stringResources.resolvingAuthDocumentUnusableLink
taskRecorder.currentStepFailed(message, authDocumentUnusableLink(this.description))
taskRecorder.currentStepFailed(
message = message,
errorCode = authDocumentUnusableLink(this.description),
extraMessages = listOf()
)
throw IOException(message)
}
}
Expand All @@ -516,7 +547,11 @@ class AccountProviderResolution(
parseResult.warnings.forEach { warning -> this.logger.warn("{}", warning.message) }
parseResult.errors.forEach { error -> this.logger.error("{}", error.message) }
val message = this.stringResources.resolvingAuthDocumentParseFailed
taskRecorder.currentStepFailed(message, authDocumentParseFailed(this.description))
taskRecorder.currentStepFailed(
message = message,
errorCode = authDocumentParseFailed(this.description),
extraMessages = listOf()
)
throw IOException(message)
}
}
Expand Down
18 changes: 1 addition & 17 deletions simplified-app-palace/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,6 @@ dependencies {
implementation(libs.androidx.webkit)

implementation(libs.azam.ulidj)
implementation(libs.commons.compress)
implementation(libs.firebase.analytics)
implementation(libs.firebase.annotations)
implementation(libs.firebase.common)
Expand Down Expand Up @@ -562,6 +561,7 @@ dependencies {
implementation(libs.palace.audiobook.http)
implementation(libs.palace.audiobook.json.canon)
implementation(libs.palace.audiobook.json.web.token)
implementation(libs.palace.audiobook.lcp.downloads)
implementation(libs.palace.audiobook.lcp.license.status)
implementation(libs.palace.audiobook.license.check.api)
implementation(libs.palace.audiobook.license.check.spi)
Expand Down Expand Up @@ -613,25 +613,9 @@ dependencies {
implementation(libs.rxjava)
implementation(libs.rxjava2)
implementation(libs.rxjava2.extensions)
implementation(libs.service.wight.annotation)
implementation(libs.service.wight.core)
implementation(libs.slf4j)
implementation(libs.timber)
implementation(libs.transport.api)
implementation(libs.transport.backend.cct)
implementation(libs.transport.runtime)
implementation(libs.truecommons.cio)
implementation(libs.truecommons.io)
implementation(libs.truecommons.key.disable)
implementation(libs.truecommons.key.spec)
implementation(libs.truecommons.logging)
implementation(libs.truecommons.services)
implementation(libs.truecommons.shed)
implementation(libs.truevfs.access)
implementation(libs.truevfs.comp.zip)
implementation(libs.truevfs.comp.zipdriver)
implementation(libs.truevfs.driver.file)
implementation(libs.truevfs.driver.zip)
implementation(libs.truevfs.kernel.impl)
implementation(libs.truevfs.kernel.spec)
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,15 @@ sealed class BookDRMInformation : Serializable {
* The hashed LCP passphrase for the book.
*/

val hashedPassphrase: String?
val hashedPassphrase: String?,

/**
* The bytes of the LCP license.
*/

val licenseBytes: ByteArray?
) : BookDRMInformation() {

override fun playerCredentials(): PlayerBookCredentialsType {
return if (this.hashedPassphrase != null) {
PlayerBookCredentialsLCP(this.hashedPassphrase)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ sealed class BookFormat {
* The URI that can be used to fetch a more recent copy of the manifest.
*/

val manifestURI: URI,
val manifestURI: URI?,

/**
* The most recent copy of the audio book manifest, if any has been fetched.
Expand Down Expand Up @@ -112,6 +112,7 @@ sealed class BookFormat {
* only the manifest is downloaded, this will always be null.
*/

@Deprecated("Packaged audiobooks are no longer handled by the application directly.")
val file: File?,

/**
Expand Down
6 changes: 6 additions & 0 deletions simplified-books-audio/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
dependencies {
implementation(project(":simplified-accounts-api"))
implementation(project(":simplified-books-database-api"))
implementation(project(":simplified-presentableerror-api"))
implementation(project(":simplified-services-api"))
implementation(project(":simplified-taskrecorder-api"))

implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.constraintlayout.core)
implementation(libs.google.guava)
implementation(libs.io7m.junreachable)
implementation(libs.irradia.mime.api)
Expand All @@ -13,6 +16,7 @@ dependencies {
implementation(libs.palace.audiobook.api)
implementation(libs.palace.audiobook.downloads)
implementation(libs.palace.audiobook.feedbooks)
implementation(libs.palace.audiobook.lcp.downloads)
implementation(libs.palace.audiobook.license.check.api)
implementation(libs.palace.audiobook.license.check.spi)
implementation(libs.palace.audiobook.manifest.api)
Expand All @@ -25,6 +29,8 @@ dependencies {
implementation(libs.palace.audiobook.manifest.parser.webpub)
implementation(libs.palace.audiobook.parser.api)
implementation(libs.palace.http.api)
implementation(libs.palace.http.downloads)
implementation(libs.r2.lcp)
implementation(libs.r2.shared)
implementation(libs.rxjava2)
implementation(libs.slf4j)
Expand Down
Loading

0 comments on commit a21ee42

Please sign in to comment.