Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Clock interface #5907

Merged
merged 12 commits into from
May 4, 2022
1 change: 1 addition & 0 deletions changelog.d/5907.sdk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Replace usage of `System.currentTimeMillis()` by a `Clock` interface
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ import java.util.concurrent.TimeUnit
class CommonTestHelper(context: Context) {

internal val matrix: TestMatrix
val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
private var accountNumber = 0

fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor

Expand Down Expand Up @@ -167,7 +168,8 @@ class CommonTestHelper(context: Context) {
if (rootThreadEventId != null) {
room.relationService().replyInThread(
rootThreadEventId = rootThreadEventId,
replyInThreadText = formattedMessage)
replyInThreadText = formattedMessage
)
} else {
room.sendService().sendTextMessage(formattedMessage)
}
Expand Down Expand Up @@ -237,7 +239,7 @@ class CommonTestHelper(context: Context) {
password: String,
testParams: SessionTestParams): Session {
val session = createAccountAndSync(
userNamePrefix + "_" + System.currentTimeMillis() + UUID.randomUUID(),
userNamePrefix + "_" + accountNumber++ + "_" + UUID.randomUUID(),
password,
testParams
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt
import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo
import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileKey
import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
import org.matrix.android.sdk.internal.util.time.DefaultClock
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.util.UUID

/**
* Unit tests AttachmentEncryptionTest.
Expand All @@ -48,13 +50,18 @@ class AttachmentEncryptionTest {
inputStream = if (inputAsByteArray.isEmpty()) {
inputAsByteArray.inputStream()
} else {
val memoryFile = MemoryFile("file" + System.currentTimeMillis(), inputAsByteArray.size)
val memoryFile = MemoryFile("file_" + UUID.randomUUID(), inputAsByteArray.size)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

memoryFile.outputStream.write(inputAsByteArray)
memoryFile.inputStream
}

val decryptedStream = ByteArrayOutputStream()
val result = MXEncryptedAttachments.decryptAttachment(inputStream, encryptedFileInfo.toElementToDecrypt()!!, decryptedStream)
val result = MXEncryptedAttachments.decryptAttachment(
attachmentStream = inputStream,
elementToDecrypt = encryptedFileInfo.toElementToDecrypt()!!,
outputStream = decryptedStream,
clock = DefaultClock()
)

assert(result)

Expand Down Expand Up @@ -117,9 +124,13 @@ class AttachmentEncryptionTest {
url = "dummyUrl"
)

assertEquals("YWxwaGFudW1lcmljYWxseWFscGhhbnVtZXJpY2FsbHlhbHBoYW51bWVyaWNhbGx5YWxwaGFudW1lcmljYWxseQ",
checkDecryption("zhtFStAeFx0s+9L/sSQO+WQMtldqYEHqTxMduJrCIpnkyer09kxJJuA4K+adQE4w+7jZe/vR9kIcqj9rOhDR8Q",
encryptedFileInfo))
assertEquals(
"YWxwaGFudW1lcmljYWxseWFscGhhbnVtZXJpY2FsbHlhbHBoYW51bWVyaWNhbGx5YWxwaGFudW1lcmljYWxseQ",
checkDecryption(
"zhtFStAeFx0s+9L/sSQO+WQMtldqYEHqTxMduJrCIpnkyer09kxJJuA4K+adQE4w+7jZe/vR9kIcqj9rOhDR8Q",
encryptedFileInfo
)
)
}

@Test
Expand All @@ -138,8 +149,12 @@ class AttachmentEncryptionTest {
url = "dummyUrl"
)

assertNotEquals("YWxwaGFudW1lcmljYWxseWFscGhhbnVtZXJpY2FsbHlhbHBoYW51bWVyaWNhbGx5YWxwaGFudW1lcmljYWxseQ",
checkDecryption("tJVNBVJ/vl36UQt4Y5e5m84bRUrQHhcdLPvS/7EkDvlkDLZXamBB6k8THbiawiKZ5Mnq9PZMSSbgOCvmnUBOMA",
encryptedFileInfo))
assertNotEquals(
"YWxwaGFudW1lcmljYWxseWFscGhhbnVtZXJpY2FsbHlhbHBoYW51bWVyaWNhbGx5YWxwaGFudW1lcmljYWxseQ",
checkDecryption(
"tJVNBVJ/vl36UQt4Y5e5m84bRUrQHhcdLPvS/7EkDvlkDLZXamBB6k8THbiawiKZ5Mnq9PZMSSbgOCvmnUBOMA",
encryptedFileInfo
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreModule
import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper
import org.matrix.android.sdk.internal.di.MoshiProvider
import org.matrix.android.sdk.internal.util.time.DefaultClock
import kotlin.random.Random

internal class CryptoStoreHelper {
Expand All @@ -34,7 +35,8 @@ internal class CryptoStoreHelper {
.build(),
crossSigningKeysMapper = CrossSigningKeysMapper(MoshiProvider.providesMoshi()),
userId = "userId_" + Random.nextInt(),
deviceId = "deviceId_sample"
deviceId = "deviceId_sample",
clock = DefaultClock(),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.junit.runner.RunWith
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.util.time.DefaultClock
import org.matrix.olm.OlmAccount
import org.matrix.olm.OlmManager
import org.matrix.olm.OlmSession
Expand All @@ -37,6 +38,7 @@ private const val DUMMY_DEVICE_KEY = "DeviceKey"
class CryptoStoreTest : InstrumentedTest {

private val cryptoStoreHelper = CryptoStoreHelper()
private val clock = DefaultClock()

@Before
fun setup() {
Expand Down Expand Up @@ -106,15 +108,15 @@ class CryptoStoreTest : InstrumentedTest {

// Note: we cannot be sure what will be the result of getLastUsedSessionId() here

olmSessionWrapper2.onMessageReceived()
olmSessionWrapper2.onMessageReceived(clock.epochMillis())
cryptoStore.storeSession(olmSessionWrapper2, DUMMY_DEVICE_KEY)

// sessionId2 is returned now
assertEquals(sessionId2, cryptoStore.getLastUsedSessionId(DUMMY_DEVICE_KEY))

Thread.sleep(2)

olmSessionWrapper1.onMessageReceived()
olmSessionWrapper1.onMessageReceived(clock.epochMillis())
cryptoStore.storeSession(olmSessionWrapper1, DUMMY_DEVICE_KEY)

// sessionId1 is returned now
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ import org.matrix.android.sdk.internal.database.mapper.toEntity
import org.matrix.android.sdk.internal.database.model.ChunkEntity
import org.matrix.android.sdk.internal.database.model.SessionRealmModule
import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection
import org.matrix.android.sdk.internal.util.time.DefaultClock
import org.matrix.android.sdk.session.room.timeline.RoomDataHelper.createFakeListOfEvents
import org.matrix.android.sdk.session.room.timeline.RoomDataHelper.createFakeMessageEvent

@RunWith(AndroidJUnit4::class)
internal class ChunkEntityTest : InstrumentedTest {

private lateinit var monarchy: Monarchy
private val clock = DefaultClock()

@Before
fun setup() {
Expand All @@ -59,7 +61,7 @@ internal class ChunkEntityTest : InstrumentedTest {
monarchy.runTransactionSync { realm ->
val chunk: ChunkEntity = realm.createObject()

val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED, System.currentTimeMillis()).let {
val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED, clock.epochMillis()).let {
realm.copyToRealm(it)
}
chunk.addTimelineEvent(
Expand All @@ -75,7 +77,7 @@ internal class ChunkEntityTest : InstrumentedTest {
fun add_shouldNotAdd_whenAlreadyIncluded() {
monarchy.runTransactionSync { realm ->
val chunk: ChunkEntity = realm.createObject()
val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED, System.currentTimeMillis()).let {
val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED, clock.epochMillis()).let {
realm.copyToRealm(it)
}
chunk.addTimelineEvent(
Expand Down Expand Up @@ -153,7 +155,7 @@ internal class ChunkEntityTest : InstrumentedTest {
events: List<Event>,
direction: PaginationDirection) {
events.forEach { event ->
val fakeEvent = event.toEntity(roomId, SendState.SYNCED, System.currentTimeMillis()).let {
val fakeEvent = event.toEntity(roomId, SendState.SYNCED, clock.epochMillis()).let {
realm.copyToRealm(it)
}
addTimelineEvent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ internal class FakeGetContextOfEventTask constructor(private val tokenChunkEvent
override suspend fun execute(params: GetContextOfEventTask.Params): TokenChunkEventPersistor.Result {
val fakeEvents = RoomDataHelper.createFakeListOfEvents(30)
val tokenChunkEvent = FakeTokenChunkEvent(
Random.nextLong(System.currentTimeMillis()).toString(),
Random.nextLong(System.currentTimeMillis()).toString(),
Random.nextLong().toString(),
Random.nextLong().toString(),
fakeEvents
)
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, PaginationDirection.BACKWARDS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal class FakePaginationTask @Inject constructor(private val tokenChunkEven

override suspend fun execute(params: PaginationTask.Params): TokenChunkEventPersistor.Result {
val fakeEvents = RoomDataHelper.createFakeListOfEvents(30)
val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong(System.currentTimeMillis()).toString(), fakeEvents)
val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong().toString(), fakeEvents)
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, params.direction)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,17 @@ data class IncomingRequestCancellation(
* Factory
*
* @param event the event
* @param currentTimeMillis the current time in milliseconds
*/
fun fromEvent(event: Event): IncomingRequestCancellation? {
fun fromEvent(event: Event, currentTimeMillis: Long): IncomingRequestCancellation? {
return event.getClearContent()
.toModel<ShareRequestCancellation>()
?.let {
IncomingRequestCancellation(
userId = event.senderId,
deviceId = it.requestingDeviceId,
requestId = it.requestId,
localCreationTimestamp = event.ageLocalTs ?: System.currentTimeMillis()
localCreationTimestamp = event.ageLocalTs ?: currentTimeMillis
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ data class IncomingRoomKeyRequest(
* Factory
*
* @param event the event
* @param currentTimeMillis the current time in milliseconds
*/
fun fromEvent(event: Event): IncomingRoomKeyRequest? {
fun fromEvent(event: Event, currentTimeMillis: Long): IncomingRoomKeyRequest? {
return event.getClearContent()
.toModel<RoomKeyShareRequest>()
?.let {
Expand All @@ -74,7 +75,7 @@ data class IncomingRoomKeyRequest(
deviceId = it.requestingDeviceId,
requestId = it.requestId,
requestBody = it.body ?: RoomKeyRequestBody(),
localCreationTimestamp = event.ageLocalTs ?: System.currentTimeMillis()
localCreationTimestamp = event.ageLocalTs ?: currentTimeMillis
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ data class IncomingSecretShareRequest(
* Factory
*
* @param event the event
* @param currentTimeMillis the current time in milliseconds
*/
fun fromEvent(event: Event): IncomingSecretShareRequest? {
fun fromEvent(event: Event, currentTimeMillis: Long): IncomingSecretShareRequest? {
return event.getClearContent()
.toModel<SecretShareRequest>()
?.let {
Expand All @@ -74,7 +75,7 @@ data class IncomingSecretShareRequest(
deviceId = it.requestingDeviceId,
requestId = it.requestId,
secretName = it.secretName,
localCreationTimestamp = event.ageLocalTs ?: System.currentTimeMillis()
localCreationTimestamp = event.ageLocalTs ?: currentTimeMillis
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,10 @@ interface VerificationService {
private const val TEN_MINUTES_IN_MILLIS = 10 * 60 * 1000
private const val FIVE_MINUTES_IN_MILLIS = 5 * 60 * 1000

fun isValidRequest(age: Long?): Boolean {
fun isValidRequest(age: Long?, currentTimeMillis: Long): Boolean {
if (age == null) return false
val now = System.currentTimeMillis()
val tooInThePast = now - TEN_MINUTES_IN_MILLIS
val tooInTheFuture = now + FIVE_MINUTES_IN_MILLIS
val tooInThePast = currentTimeMillis - TEN_MINUTES_IN_MILLIS
val tooInTheFuture = currentTimeMillis + FIVE_MINUTES_IN_MILLIS
return age in tooInThePast..tooInTheFuture
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId
import org.matrix.android.sdk.internal.session.SessionComponent
import org.matrix.android.sdk.internal.util.time.Clock
import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker
import org.matrix.android.sdk.internal.worker.SessionWorkerParams
import javax.inject.Inject
Expand Down Expand Up @@ -65,6 +66,7 @@ internal class CancelGossipRequestWorker(context: Context, params: WorkerParamet
@Inject lateinit var sendToDeviceTask: SendToDeviceTask
@Inject lateinit var cryptoStore: IMXCryptoStore
@Inject lateinit var credentials: Credentials
@Inject lateinit var clock: Clock

override fun injectWith(injector: SessionComponent) {
injector.inject(this)
Expand All @@ -85,7 +87,7 @@ internal class CancelGossipRequestWorker(context: Context, params: WorkerParamet
content = toDeviceContent.toContent(),
senderId = credentials.userId
).also {
it.ageLocalTs = System.currentTimeMillis()
it.ageLocalTs = clock.epochMillis()
})

params.recipients.forEach { userToDeviceMap ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ import org.matrix.android.sdk.internal.task.TaskThread
import org.matrix.android.sdk.internal.task.configureWith
import org.matrix.android.sdk.internal.task.launchToCallback
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
import org.matrix.android.sdk.internal.util.time.Clock
import org.matrix.olm.OlmManager
import timber.log.Timber
import java.util.concurrent.atomic.AtomicBoolean
Expand Down Expand Up @@ -130,6 +131,7 @@ internal class DefaultCryptoService @Inject constructor(
private val userId: String,
@DeviceId
private val deviceId: String?,
private val clock: Clock,
private val myDeviceInfoHolder: Lazy<MyDeviceInfoHolder>,
// the crypto store
private val cryptoStore: IMXCryptoStore,
Expand Down Expand Up @@ -701,11 +703,11 @@ internal class DefaultCryptoService @Inject constructor(
}
val safeAlgorithm = alg
if (safeAlgorithm != null) {
val t0 = System.currentTimeMillis()
val t0 = clock.epochMillis()
Timber.tag(loggerTag.value).v("encryptEventContent() starts")
runCatching {
val content = safeAlgorithm.encryptEventContent(eventContent, eventType, userIds)
Timber.tag(loggerTag.value).v("## CRYPTO | encryptEventContent() : succeeds after ${System.currentTimeMillis() - t0} ms")
Timber.tag(loggerTag.value).v("## CRYPTO | encryptEventContent() : succeeds after ${clock.epochMillis() - t0} ms")
MXEncryptEventContentResult(content, EventType.ENCRYPTED)
}.foldToCallback(callback)
} else {
Expand Down Expand Up @@ -1022,17 +1024,17 @@ internal class DefaultCryptoService @Inject constructor(
return withContext(coroutineDispatchers.crypto) {
Timber.tag(loggerTag.value).v("importRoomKeys starts")

val t0 = System.currentTimeMillis()
val t0 = clock.epochMillis()
val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password)
val t1 = System.currentTimeMillis()
val t1 = clock.epochMillis()

Timber.tag(loggerTag.value).v("importRoomKeys : decryptMegolmKeyFile done in ${t1 - t0} ms")

val importedSessions = MoshiProvider.providesMoshi()
.adapter<List<MegolmSessionData>>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java))
.fromJson(roomKeys)

val t2 = System.currentTimeMillis()
val t2 = clock.epochMillis()

Timber.tag(loggerTag.value).v("importRoomKeys : JSON parsing ${t2 - t1} ms")

Expand Down Expand Up @@ -1224,7 +1226,7 @@ internal class DefaultCryptoService @Inject constructor(
// val deviceKey = deviceInfo.identityKey()
//
// val lastForcedDate = lastNewSessionForcedDates.getObject(senderId, deviceKey) ?: 0
// val now = System.currentTimeMillis()
// val now = clock.epochMillis()
// if (now - lastForcedDate < CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS) {
// Timber.d("## CRYPTO | markOlmSessionForUnwedging: New session already forced with device at $lastForcedDate. Not forcing another")
// return
Expand Down
Loading