Skip to content

Commit b247622

Browse files
authored
Revamp format (readium#428)
1 parent bfadfa8 commit b247622

File tree

41 files changed

+2035
-1687
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2035
-1687
lines changed

readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtection.kt

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ import org.readium.r2.shared.util.data.decodeRwpm
2828
import org.readium.r2.shared.util.data.decodeXml
2929
import org.readium.r2.shared.util.data.readDecodeOrElse
3030
import org.readium.r2.shared.util.flatMap
31-
import org.readium.r2.shared.util.format.Format
32-
import org.readium.r2.shared.util.format.Trait
31+
import org.readium.r2.shared.util.format.EpubSpecification
32+
import org.readium.r2.shared.util.format.LcpLicenseSpecification
33+
import org.readium.r2.shared.util.format.LcpSpecification
3334
import org.readium.r2.shared.util.getOrElse
3435
import org.readium.r2.shared.util.resource.Resource
3536
import org.readium.r2.shared.util.resource.TransformingContainer
@@ -44,25 +45,23 @@ internal class LcpContentProtection(
4445
asset: Asset,
4546
credentials: String?,
4647
allowUserInteraction: Boolean
47-
): Try<ContentProtection.OpenResult, ContentProtection.OpenError> {
48-
if (
49-
!asset.format.conformsTo(Trait.LCP_PROTECTED) &&
50-
!asset.format.conformsTo(Format.LCP_LICENSE_DOCUMENT)
51-
) {
52-
return Try.failure(ContentProtection.OpenError.AssetNotSupported())
53-
}
54-
55-
return when (asset) {
48+
): Try<ContentProtection.OpenResult, ContentProtection.OpenError> =
49+
when (asset) {
5650
is ContainerAsset -> openPublication(asset, credentials, allowUserInteraction)
5751
is ResourceAsset -> openLicense(asset, credentials, allowUserInteraction)
5852
}
59-
}
6053

6154
private suspend fun openPublication(
6255
asset: ContainerAsset,
6356
credentials: String?,
6457
allowUserInteraction: Boolean
6558
): Try<ContentProtection.OpenResult, ContentProtection.OpenError> {
59+
if (
60+
!asset.format.conformsTo(LcpSpecification)
61+
) {
62+
return Try.failure(ContentProtection.OpenError.AssetNotSupported())
63+
}
64+
6665
val license = retrieveLicense(asset, credentials, allowUserInteraction)
6766
return createResultAsset(asset, license)
6867
}
@@ -88,7 +87,9 @@ internal class LcpContentProtection(
8887

8988
val encryptionData =
9089
when {
91-
asset.format.conformsTo(Trait.EPUB) -> parseEncryptionDataEpub(asset.container)
90+
asset.format.conformsTo(EpubSpecification) -> parseEncryptionDataEpub(
91+
asset.container
92+
)
9293
else -> parseEncryptionDataRpf(asset.container)
9394
}
9495
.getOrElse { return Try.failure(ContentProtection.OpenError.Reading(it)) }
@@ -146,6 +147,10 @@ internal class LcpContentProtection(
146147
credentials: String?,
147148
allowUserInteraction: Boolean
148149
): Try<ContentProtection.OpenResult, ContentProtection.OpenError> {
150+
if (!licenseAsset.format.conformsTo(LcpLicenseSpecification)) {
151+
return Try.failure(ContentProtection.OpenError.AssetNotSupported())
152+
}
153+
149154
val license = retrieveLicense(licenseAsset, credentials, allowUserInteraction)
150155

151156
val licenseDoc = license.getOrNull()?.license

readium/lcp/src/main/java/org/readium/r2/lcp/LcpPublicationRetriever.kt

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,17 @@ import org.readium.r2.lcp.license.model.LicenseDocument
1515
import org.readium.r2.shared.extensions.tryOrLog
1616
import org.readium.r2.shared.util.AbsoluteUrl
1717
import org.readium.r2.shared.util.ErrorException
18+
import org.readium.r2.shared.util.FileExtension
1819
import org.readium.r2.shared.util.asset.AssetSniffer
1920
import org.readium.r2.shared.util.downloads.DownloadManager
21+
import org.readium.r2.shared.util.format.EpubSpecification
2022
import org.readium.r2.shared.util.format.Format
2123
import org.readium.r2.shared.util.format.FormatHints
22-
import org.readium.r2.shared.util.format.FormatRegistry
23-
import org.readium.r2.shared.util.format.Trait
24+
import org.readium.r2.shared.util.format.FormatSpecification
25+
import org.readium.r2.shared.util.format.LcpSpecification
26+
import org.readium.r2.shared.util.format.ZipSpecification
2427
import org.readium.r2.shared.util.getOrElse
28+
import org.readium.r2.shared.util.mediatype.MediaType
2529

2630
/**
2731
* Utility to acquire a protected publication from an LCP License Document.
@@ -128,9 +132,6 @@ public class LcpPublicationRetriever(
128132
private val coroutineScope: CoroutineScope =
129133
MainScope()
130134

131-
private val formatRegistry: FormatRegistry =
132-
FormatRegistry()
133-
134135
private val downloadsRepository: LcpDownloadsRepository =
135136
LcpDownloadsRepository(context)
136137

@@ -195,7 +196,7 @@ public class LcpPublicationRetriever(
195196
}
196197
downloadsRepository.removeDownload(requestId.value)
197198

198-
val baseFormat =
199+
val format =
199200
assetSniffer.sniff(
200201
download.file,
201202
FormatHints(
@@ -204,13 +205,21 @@ public class LcpPublicationRetriever(
204205
download.mediaType
205206
)
206207
)
207-
).getOrElse { Format.EPUB }
208-
209-
val format = baseFormat + Trait.LCP_PROTECTED
208+
).getOrElse {
209+
Format(
210+
specification = FormatSpecification(
211+
ZipSpecification,
212+
EpubSpecification,
213+
LcpSpecification
214+
),
215+
mediaType = MediaType.EPUB,
216+
fileExtension = FileExtension("epub")
217+
)
218+
}
210219

211220
try {
212221
// Saves the License Document into the downloaded publication
213-
val container = createLicenseContainer(download.file, format)
222+
val container = createLicenseContainer(download.file, format.specification)
214223
container.write(license)
215224
} catch (e: Exception) {
216225
tryOrLog { download.file.delete() }
@@ -279,7 +288,4 @@ public class LcpPublicationRetriever(
279288
listeners.remove(lcpRequestId)
280289
}
281290
}
282-
283-
private val Format.fileExtension: String get() =
284-
formatRegistry[this]?.fileExtension?.value ?: "epub"
285291
}

readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import org.readium.r2.shared.publication.protection.ContentProtection
3030
import org.readium.r2.shared.util.Try
3131
import org.readium.r2.shared.util.asset.Asset
3232
import org.readium.r2.shared.util.asset.AssetOpener
33-
import org.readium.r2.shared.util.asset.AssetSniffer
3433
import org.readium.r2.shared.util.downloads.DownloadManager
3534
import org.readium.r2.shared.util.format.Format
3635

@@ -43,10 +42,12 @@ public interface LcpService {
4342
* Returns if the file is a LCP license document or a publication protected by LCP.
4443
*/
4544
@Deprecated(
46-
"Use an AssetSniffer and check the returned format for Trait.LCP_PROTECTED",
45+
"Use an AssetSniffer and check the conformance of the returned format to LcpSpecification",
4746
level = DeprecationLevel.ERROR
4847
)
49-
public suspend fun isLcpProtected(file: File): Boolean
48+
public suspend fun isLcpProtected(file: File): Boolean {
49+
throw NotImplementedError()
50+
}
5051

5152
/**
5253
* Acquires a protected publication from a standalone LCPL's bytes.
@@ -60,7 +61,9 @@ public interface LcpService {
6061
ReplaceWith("publicationRetriever()"),
6162
level = DeprecationLevel.ERROR
6263
)
63-
public suspend fun acquirePublication(lcpl: ByteArray, onProgress: (Double) -> Unit = {}): Try<AcquiredPublication, LcpError>
64+
public suspend fun acquirePublication(lcpl: ByteArray, onProgress: (Double) -> Unit = {}): Try<AcquiredPublication, LcpError> {
65+
throw NotImplementedError()
66+
}
6467

6568
/**
6669
* Acquires a protected publication from a standalone LCPL file.
@@ -88,13 +91,21 @@ public interface LcpService {
8891
* The request will be cancelled if no passphrase is found in the LCP passphrase storage
8992
* and the provided [authentication].
9093
* @param allowUserInteraction Indicates whether the user can be prompted for their passphrase.
94+
* @param sender Free object that can be used by reading apps to give some UX context when
95+
* presenting dialogs with [LcpAuthenticating].
9196
*/
97+
@Deprecated(
98+
"Use the overload taking an asset instead.",
99+
level = DeprecationLevel.ERROR
100+
)
92101
public suspend fun retrieveLicense(
93102
file: File,
94-
format: Format,
95-
authentication: LcpAuthenticating,
96-
allowUserInteraction: Boolean
97-
): Try<LcpLicense, LcpError>
103+
authentication: LcpAuthenticating = LcpDialogAuthentication(),
104+
allowUserInteraction: Boolean,
105+
sender: Any? = null
106+
): Try<LcpLicense, LcpError>? {
107+
throw NotImplementedError()
108+
}
98109

99110
/**
100111
* Opens the LCP license of a protected publication, to access its DRM metadata and decipher
@@ -164,7 +175,6 @@ public interface LcpService {
164175
public operator fun invoke(
165176
context: Context,
166177
assetOpener: AssetOpener,
167-
assetSniffer: AssetSniffer,
168178
downloadManager: DownloadManager
169179
): LcpService? {
170180
if (!LcpClient.isAvailable()) {
@@ -191,7 +201,6 @@ public interface LcpService {
191201
passphrases = passphrases,
192202
context = context,
193203
assetOpener = assetOpener,
194-
assetSniffer = assetSniffer,
195204
downloadManager = downloadManager
196205
)
197206
}

readium/lcp/src/main/java/org/readium/r2/lcp/license/container/LicenseContainer.kt

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import org.readium.r2.shared.util.asset.Asset
1919
import org.readium.r2.shared.util.asset.ContainerAsset
2020
import org.readium.r2.shared.util.asset.ResourceAsset
2121
import org.readium.r2.shared.util.data.Container
22-
import org.readium.r2.shared.util.format.Format
22+
import org.readium.r2.shared.util.format.EpubSpecification
23+
import org.readium.r2.shared.util.format.FormatSpecification
24+
import org.readium.r2.shared.util.format.LcpLicenseSpecification
2325
import org.readium.r2.shared.util.resource.Resource
2426

2527
private val LICENSE_IN_EPUB = Url("META-INF/license.lcpl")!!
@@ -39,11 +41,14 @@ internal interface WritableLicenseContainer : LicenseContainer {
3941

4042
internal fun createLicenseContainer(
4143
file: File,
42-
format: Format
44+
formatSpecification: FormatSpecification
4345
): WritableLicenseContainer =
4446
when {
45-
format.conformsTo(Format.EPUB) -> FileZipLicenseContainer(file.path, LICENSE_IN_EPUB)
46-
format.conformsTo(Format.LCP_LICENSE_DOCUMENT) -> LcplLicenseContainer(file)
47+
formatSpecification.conformsTo(EpubSpecification) -> FileZipLicenseContainer(
48+
file.path,
49+
LICENSE_IN_EPUB
50+
)
51+
formatSpecification.conformsTo(LcpLicenseSpecification) -> LcplLicenseContainer(file)
4752
// Assuming it's a Readium WebPub package (e.g. audiobook, LCPDF, etc.) as a fallback
4853
else -> FileZipLicenseContainer(file.path, LICENSE_IN_RPF)
4954
}
@@ -53,15 +58,19 @@ internal fun createLicenseContainer(
5358
asset: Asset
5459
): LicenseContainer =
5560
when (asset) {
56-
is ResourceAsset -> createLicenseContainer(asset.resource, asset.format)
57-
is ContainerAsset -> createLicenseContainer(context, asset.container, asset.format)
61+
is ResourceAsset -> createLicenseContainer(asset.resource, asset.format.specification)
62+
is ContainerAsset -> createLicenseContainer(
63+
context,
64+
asset.container,
65+
asset.format.specification
66+
)
5867
}
5968

6069
internal fun createLicenseContainer(
6170
resource: Resource,
62-
format: Format
71+
formatSpecification: FormatSpecification
6372
): LicenseContainer {
64-
if (!format.conformsTo(Format.LCP_LICENSE_DOCUMENT)) {
73+
if (!formatSpecification.conformsTo(LcpLicenseSpecification)) {
6574
throw LcpException(LcpError.Container.OpenFailed)
6675
}
6776

@@ -76,10 +85,10 @@ internal fun createLicenseContainer(
7685
internal fun createLicenseContainer(
7786
context: Context,
7887
container: Container<Resource>,
79-
format: Format
88+
formatSpecification: FormatSpecification
8089
): LicenseContainer {
8190
val licensePath = when {
82-
format.conformsTo(Format.EPUB) -> LICENSE_IN_EPUB
91+
formatSpecification.conformsTo(EpubSpecification) -> LICENSE_IN_EPUB
8392
// Assuming it's a Readium WebPub package (e.g. audiobook, LCPDF, etc.) as a fallback
8493
else -> LICENSE_IN_RPF
8594
}

0 commit comments

Comments
 (0)