Skip to content

Commit

Permalink
Merge branch 'develop' into feature-i18n
Browse files Browse the repository at this point in the history
  • Loading branch information
seanwu1105 committed Oct 24, 2020
2 parents 31b9bf0 + 173959d commit 3e3cf45
Show file tree
Hide file tree
Showing 13 changed files with 223 additions and 93 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/qa-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,13 @@ jobs:
Version: ${{ steps.extract_version.outputs.versionName }} (${{ steps.extract_version.outputs.versionCode }})
<https://github.com/numbersprotocol/starling-capture/releases/tag/${{ steps.extract_version.outputs.versionName }}|GitHub Release Note>
*APKs*
APKs
<https://drive.google.com/drive/folders/1Ed77Mkg1XGIRa6PZuyW6ua92MSmXSIfB?usp=sharing|Google Drive (Master-Debug, Master-QA, Internal-Debug and Internal-QA)>
<https://play.google.com/apps/testing/io.numbersprotocol.starlingcapture|Google Play Closed Alpha Testing (Internal-Release)>
*Notes*
Notes
- Publishing process usually requires some time to complete, and thus the link provided above might still display the old version of the app. Please check the app version before download and install the app.
- This message is automatically sent from GitHub Action.
Expand Down Expand Up @@ -220,4 +222,4 @@ jobs:
google-client-id: ${{ secrets.SKICKA_GOOGLE_CLIENT_ID }}
google-client-secret: ${{ secrets.SKICKA_GOOGLE_CLIENT_SECRET }}
upload-from: ./app/build/outputs/apk/internal/qa/
upload-to: /starling-capture/apk/internal/qa/
upload-to: /starling-capture/apk/internal/qa/
6 changes: 3 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ dependencies {
implementation "com.afollestad.material-dialogs:input:3.3.0"
implementation "com.afollestad.material-dialogs:bottomsheets:3.3.0"

implementation "io.coil-kt:coil:0.13.0"
implementation "io.coil-kt:coil-video:0.13.0"
implementation "io.coil-kt:coil:1.0.0"
implementation "io.coil-kt:coil-video:1.0.0"

implementation "com.github.lisawray.groupie:groupie:2.8.1"
implementation "com.github.lisawray.groupie:groupie-viewbinding:2.8.1"
Expand All @@ -169,7 +169,7 @@ dependencies {
internalImplementation "com.google.firebase:firebase-crashlytics:17.2.2"

testImplementation "junit:junit:4.13.1"
testImplementation "org.mockito:mockito-core:3.5.13"
testImplementation "org.mockito:mockito-core:3.5.15"

androidTestImplementation "androidx.test.ext:junit:1.1.2"
androidTestImplementation "androidx.test.espresso:espresso-core:3.3.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.numbersprotocol.starlingcapture.collector

import android.content.Context
import androidx.annotation.StringRes
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import io.numbersprotocol.starlingcapture.util.MimeType
import io.numbersprotocol.starlingcapture.util.NotificationUtil
import org.koin.core.KoinComponent
import org.koin.core.inject
import kotlin.properties.Delegates

abstract class CollectWorker(
val context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params), KoinComponent {

abstract val name: String

lateinit var hash: String
lateinit var mimeType: MimeType
private var notificationId by Delegates.notNull<Int>()
private val notificationUtil: NotificationUtil by inject()

private fun initialize() {
hash = inputData.getString(ProofCollector.KEY_HASH)!!
mimeType = MimeType.fromString(inputData.getString(ProofCollector.KEY_MIME_TYPE)!!)

val illegalNotificationId = NotificationUtil.NOTIFICATION_ID_MIN - 1
notificationId = inputData.getInt(ProofCollector.KEY_NOTIFICATION_ID, illegalNotificationId)
if (notificationId == illegalNotificationId) error("Cannot get notification ID from input data.")
}

override suspend fun doWork(): Result {
initialize()
return try {
onStarted()
collect()
onCleared()
Result.success()
} catch (e: Exception) {
notificationUtil.notifyException(e, notificationId)
Result.failure()
} finally {
onCleared()
}
}

open suspend fun onStarted() {}
abstract suspend fun collect()
open suspend fun onCleared() {}

protected fun notifyStartCollecting(@StringRes stringRes: Int) {
val builder = ProofCollector.getNotificationBuilder(context).apply {
setContentText(context.resources.getString(stringRes))
setProgress(0, 0, true)
setOngoing(true)
}
notificationUtil.notify(notificationId, builder)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.numbersprotocol.starlingcapture.collector

import android.content.Context
import androidx.work.WorkerParameters
import io.numbersprotocol.starlingcapture.R
import io.numbersprotocol.starlingcapture.data.information.Information
import io.numbersprotocol.starlingcapture.data.information.InformationRepository
import org.koin.core.inject

abstract class InformationProvider(
context: Context, params: WorkerParameters
) : CollectWorker(context, params) {

private val informationRepository: InformationRepository by inject()

override suspend fun collect() {
notifyStartCollecting(R.string.message_collecting_proof_information)
informationRepository.add(*provide().toTypedArray())
}

abstract suspend fun provide(): Collection<Information>
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class ProofCollector(
private val notificationUtil: NotificationUtil
) {

private val provideInformationAndSignatureRequestBuilders =
mutableSetOf<OneTimeWorkRequest.Builder>()
private val provideInformationRequestBuilders = mutableSetOf<OneTimeWorkRequest.Builder>()
private val provideSignatureRequestBuilders = mutableSetOf<OneTimeWorkRequest.Builder>()

suspend fun storeAndCollect(cachedMediaFile: File, mimeType: MimeType): String {
val notificationId = notificationUtil.createNotificationId()
Expand All @@ -40,24 +40,33 @@ class ProofCollector(
.setInputData(workData)
.build()

val provideInformationRequests = provideInformationAndSignatureRequestBuilders.map {
it.setInputData(workData).build()
}
val provideInformationRequests =
provideInformationRequestBuilders.map { it.setInputData(workData).build() }

val provideSignatureRequests =
provideSignatureRequestBuilders.map { it.setInputData(workData).build() }

notifyStartCollecting(notificationId)
WorkManager.getInstance(context)
.beginWith(provideInformationRequests)
.then(provideSignatureRequests)
.then(finishCollectionRequest)
.enqueue()

return proofHash
}

fun addProvideInformationAndSignatureRequestBuilder(builder: OneTimeWorkRequest.Builder) =
provideInformationAndSignatureRequestBuilders.add(builder)
fun addProvideInformationRequestBuilder(builder: OneTimeWorkRequest.Builder) =
provideInformationRequestBuilders.add(builder)

fun removeProvideInformationRequestBuilder(builder: OneTimeWorkRequest.Builder) =
provideInformationRequestBuilders.remove(builder)

fun removeProvideInformationAndSignatureRequestBuilder(builder: OneTimeWorkRequest.Builder) =
provideInformationAndSignatureRequestBuilders.remove(builder)
fun addProvideSignatureRequestBuilder(builder: OneTimeWorkRequest.Builder) =
provideSignatureRequestBuilders.add(builder)

fun removeProvideSignatureRequestBuilder(builder: OneTimeWorkRequest.Builder) =
provideSignatureRequestBuilders.remove(builder)

private fun notifyStartCollecting(notificationId: Int) {
val builder = getNotificationBuilder(context).apply {
Expand All @@ -68,6 +77,26 @@ class ProofCollector(
notificationUtil.notify(notificationId, builder)
}

class FinishCollectionWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params), KoinComponent {

private val notificationUtil: NotificationUtil by inject()

override suspend fun doWork(): Result {
val illegalNotificationId = NotificationUtil.NOTIFICATION_ID_MIN - 1
val notificationId =
inputData.getInt(KEY_NOTIFICATION_ID, illegalNotificationId)
if (notificationId == illegalNotificationId) {
Timber.e("Cannot get notification ID from input data.")
return Result.failure()
}
notificationUtil.cancel(notificationId)
return Result.success()
}
}

companion object {
const val KEY_HASH = "KEY_HASH"
const val KEY_MIME_TYPE = "KEY_MIME_TYPE"
Expand All @@ -78,24 +107,4 @@ class ProofCollector(
.setSmallIcon(R.drawable.ic_capture)
.setContentTitle(context.getString(R.string.collect_proof_information))
}
}

class FinishCollectionWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params), KoinComponent {

private val notificationUtil: NotificationUtil by inject()

override suspend fun doWork(): Result {
val illegalNotificationId = NotificationUtil.NOTIFICATION_ID_MIN - 1
val notificationId =
inputData.getInt(ProofCollector.KEY_NOTIFICATION_ID, illegalNotificationId)
if (notificationId == illegalNotificationId) {
Timber.e("Cannot get notification ID from input data.")
return Result.failure()
}
notificationUtil.cancel(notificationId)
return Result.success()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.numbersprotocol.starlingcapture.collector

import android.content.Context
import androidx.work.WorkerParameters
import io.numbersprotocol.starlingcapture.R
import io.numbersprotocol.starlingcapture.data.information.InformationRepository
import io.numbersprotocol.starlingcapture.data.proof.ProofRepository
import io.numbersprotocol.starlingcapture.data.serialization.SortedProofInformation
import io.numbersprotocol.starlingcapture.data.signature.Signature
import io.numbersprotocol.starlingcapture.data.signature.SignatureRepository
import org.koin.core.inject

abstract class SignatureProvider(
context: Context, params: WorkerParameters
) : CollectWorker(context, params) {

private val proofRepository: ProofRepository by inject()
private val informationRepository: InformationRepository by inject()
private val signatureRepository: SignatureRepository by inject()

override suspend fun collect() {
notifyStartCollecting(R.string.message_signing_proof_information)
val proof = proofRepository.getByHash(hash)!!
val sortedProofInformation = SortedProofInformation.create(proof, informationRepository)
val json = sortedProofInformation.toJson()
signatureRepository.add(*provide(json).toTypedArray())
}

abstract suspend fun provide(serialized: String): Collection<Signature>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package io.numbersprotocol.starlingcapture.collector.android_open_ssl

import android.content.Context
import androidx.work.WorkerParameters
import io.numbersprotocol.starlingcapture.collector.InformationAndSignatureProvider
import io.numbersprotocol.starlingcapture.collector.SignatureProvider
import io.numbersprotocol.starlingcapture.data.preference.PreferenceRepository
import io.numbersprotocol.starlingcapture.data.signature.Signature
import io.numbersprotocol.starlingcapture.util.androidOpenSslSignatureProvider
Expand All @@ -13,13 +13,13 @@ import org.koin.core.inject
class AndroidOpenSslSignatureProvider(
context: Context,
params: WorkerParameters
) : InformationAndSignatureProvider(context, params), KoinComponent {
) : SignatureProvider(context, params), KoinComponent {

override val name = androidOpenSslSignatureProvider

private val preferenceRepository: PreferenceRepository by inject()

override suspend fun provideSignature(serialized: String): Collection<Signature>? {
override suspend fun provide(serialized: String): Collection<Signature> {
val privateKey = preferenceRepository.defaultPrivateKey
val publicKey = preferenceRepository.defaultPublicKey
val signature = serialized.signWithSha256AndEcdsa(privateKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.content.Context
import androidx.work.WorkerParameters
import io.numbers.infosnapshot.InfoSnapshotBuilder
import io.numbersprotocol.starlingcapture.R
import io.numbersprotocol.starlingcapture.collector.InformationAndSignatureProvider
import io.numbersprotocol.starlingcapture.collector.InformationProvider
import io.numbersprotocol.starlingcapture.data.information.Information
import org.koin.core.KoinComponent
import java.text.DateFormat
Expand All @@ -13,13 +13,13 @@ import java.time.Instant
class InfoSnapshotProvider(
context: Context,
params: WorkerParameters
) : InformationAndSignatureProvider(context, params), KoinComponent {
) : InformationProvider(context, params), KoinComponent {

override val name = InfoSnapshotConfig.name

private val informationSet = mutableSetOf<Information>()

override suspend fun provideInformation(): Collection<Information>? {
override suspend fun provide(): Collection<Information> {
val snapshot = InfoSnapshotBuilder(context).apply {
duration = 10000
enableDeviceInfo = InfoSnapshotConfig.collectDeviceInfo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ object ProofModeConfig : KoinComponent {

fun enable() {
isEnabled = true
proofCollector.addProvideInformationAndSignatureRequestBuilder(proofModeProviderBuilder)
proofCollector.addProvideInformationRequestBuilder(proofModeProviderBuilder)
}

fun disable() {
proofCollector.removeProvideInformationAndSignatureRequestBuilder(proofModeProviderBuilder)
proofCollector.removeProvideInformationRequestBuilder(proofModeProviderBuilder)
isEnabled = false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package io.numbersprotocol.starlingcapture.collector.proofmode
import android.content.Context
import androidx.core.net.toUri
import androidx.work.WorkerParameters
import io.numbersprotocol.starlingcapture.collector.InformationAndSignatureProvider
import io.numbersprotocol.starlingcapture.collector.InformationProvider
import io.numbersprotocol.starlingcapture.data.information.Information
import io.numbersprotocol.starlingcapture.data.proof.ProofRepository
import io.numbersprotocol.starlingcapture.data.signature.Signature
import org.koin.core.KoinComponent
import org.koin.core.inject
import org.witness.proofmode.ProofMode
Expand All @@ -15,7 +14,7 @@ import java.io.File
class ProofModeProvider(
context: Context,
params: WorkerParameters
) : InformationAndSignatureProvider(context, params), KoinComponent {
) : InformationProvider(context, params), KoinComponent {

override val name = ProofModeConfig.name

Expand All @@ -31,23 +30,32 @@ class ProofModeProvider(
if (!generatedDir.exists()) throw IllegalStateException("Cannot locate information directory generated by ProofMode: $hashFromProofMode")
}

override suspend fun provideInformation(): Collection<Information>? {
override suspend fun provide(): Collection<Information> {
val infoText = generatedDir.listFiles { _, filename ->
filename.endsWith(INFORMATION_FILE_SUFFIX)
}!!.first().readText()
return setOf(Information(hash, name, name, infoText, Information.Importance.HIGH))
}

override suspend fun provideSignature(serialized: String): Collection<Signature>? {
val rawFileSignatureText = generatedDir.listFiles { _, filename ->
filename.endsWith(RAW_FILE_SIGNATURE_FILE_SUFFIX)
}!!.first().readText()
val informationSignatureText = generatedDir.listFiles { _, filename ->
filename.endsWith(INFORMATION_SIGNATURE_FILE_SUFFIX)
}!!.first().readText()
return setOf(
Signature(hash, "$name-Raw Media File", rawFileSignatureText, ""),
Signature(hash, "$name-Information", informationSignatureText, "")
Information(hash, name, name, infoText, Information.Importance.HIGH),
Information(
hash,
name,
"Raw File Signature",
rawFileSignatureText,
Information.Importance.LOW
),
Information(
hash,
name,
"Information Signature",
informationSignatureText,
Information.Importance.LOW
)
)
}

Expand Down
Loading

0 comments on commit 3e3cf45

Please sign in to comment.