From e9769cff1b09cc4dc79c5db761e4ed35ba2ed263 Mon Sep 17 00:00:00 2001 From: Sean Wu Date: Fri, 15 Jan 2021 17:09:53 +0800 Subject: [PATCH] Use capture timestamp instead of the timestamp on getCurrentPosition. #456 --- .../services/capture/capture.service.ts | 5 +++- .../collector/collector.service.spec.ts | 10 +++---- .../services/collector/collector.service.ts | 11 +++++--- .../capacitor-facts-provider.service.ts | 10 +++++-- .../collector/facts/facts-provider.ts | 2 +- .../geolocation/geolocation.service.ts | 28 ++++++++++++++----- 6 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/app/shared/services/capture/capture.service.ts b/src/app/shared/services/capture/capture.service.ts index 1a8fa480f..e0cd11c4d 100644 --- a/src/app/shared/services/capture/capture.service.ts +++ b/src/app/shared/services/capture/capture.service.ts @@ -40,7 +40,10 @@ export class CaptureService { this._collectingOldProofHashes$.next( this._collectingOldProofHashes$.value.add(getOldProof(proof).hash) ); - const collected = await this.collectorService.run(await proof.getAssets()); + const collected = await this.collectorService.run( + await proof.getAssets(), + proof.timestamp + ); const newCollectingOldProofHashes = this._collectingOldProofHashes$.value; newCollectingOldProofHashes.delete(getOldProof(proof).hash); this._collectingOldProofHashes$.next(newCollectingOldProofHashes); diff --git a/src/app/shared/services/collector/collector.service.spec.ts b/src/app/shared/services/collector/collector.service.spec.ts index 848cbb501..54fc24e3d 100644 --- a/src/app/shared/services/collector/collector.service.spec.ts +++ b/src/app/shared/services/collector/collector.service.spec.ts @@ -27,7 +27,7 @@ describe('CollectorService', () => { it('should be created', () => expect(service).toBeTruthy()); it('should get the stored proof after run', async () => { - const proof = await service.run(ASSETS); + const proof = await service.run(ASSETS, Date.now()); expect(await proof.getAssets()).toEqual(ASSETS); }); @@ -35,7 +35,7 @@ describe('CollectorService', () => { service.addFactsProvider(mockFactsProvider); service.removeFactsProvider(mockFactsProvider); - const proof = await service.run(ASSETS); + const proof = await service.run(ASSETS, Date.now()); expect(proof.truth.providers).toEqual({}); }); @@ -44,20 +44,20 @@ describe('CollectorService', () => { service.addSignatureProvider(mockSignatureProvider); service.removeSignatureProvider(mockSignatureProvider); - const proof = await service.run(ASSETS); + const proof = await service.run(ASSETS, Date.now()); expect(proof.signatures).toEqual({}); }); it('should get the stored proof with provided facts', async () => { service.addFactsProvider(mockFactsProvider); - const proof = await service.run(ASSETS); + const proof = await service.run(ASSETS, Date.now()); expect(proof.truth.providers).toEqual({ [mockFactsProvider.id]: FACTS }); }); it('should get the stored proof with provided signature', async () => { service.addSignatureProvider(mockSignatureProvider); - const proof = await service.run(ASSETS); + const proof = await service.run(ASSETS, Date.now()); expect(proof.signatures).toEqual({ [mockSignatureProvider.id]: SIGNATURE }); }); }); diff --git a/src/app/shared/services/collector/collector.service.ts b/src/app/shared/services/collector/collector.service.ts index 8c9843687..c65474362 100644 --- a/src/app/shared/services/collector/collector.service.ts +++ b/src/app/shared/services/collector/collector.service.ts @@ -20,22 +20,25 @@ export class CollectorService { constructor(private readonly imageStore: ImageStore) {} - async run(assets: Assets) { - const truth = await this.collectTruth(assets); + async run(assets: Assets, capturedTimestamp: number) { + const truth = await this.collectTruth(assets, capturedTimestamp); const signatures = await this.signTargets({ assets, truth }); const proof = await Proof.from(this.imageStore, assets, truth, signatures); proof.isCollected = true; return proof; } - private async collectTruth(assets: Assets): Promise { + private async collectTruth( + assets: Assets, + capturedTimestamp: number + ): Promise { return { timestamp: Date.now(), providers: Object.fromEntries( await Promise.all( [...this.factsProviders].map(async provider => [ provider.id, - await provider.provide(assets), + await provider.provide(assets, capturedTimestamp), ]) ) ), diff --git a/src/app/shared/services/collector/facts/capacitor-facts-provider/capacitor-facts-provider.service.ts b/src/app/shared/services/collector/facts/capacitor-facts-provider/capacitor-facts-provider.service.ts index 0c7a7bf5e..07395a9c9 100644 --- a/src/app/shared/services/collector/facts/capacitor-facts-provider/capacitor-facts-provider.service.ts +++ b/src/app/shared/services/collector/facts/capacitor-facts-provider/capacitor-facts-provider.service.ts @@ -31,9 +31,12 @@ export class CapacitorFactsProvider implements FactsProvider { private readonly translocoService: TranslocoService ) {} - async provide(_: Assets): Promise { + async provide( + _: Assets, + capturedTimestamp: number = Date.now() + ): Promise { const deviceInfo = await this.collectDeviceInfo(); - const locationInfo = await this.collectLocationInfo(); + const locationInfo = await this.collectLocationInfo(capturedTimestamp); return { [DefaultFactId.DEVICE_NAME]: deviceInfo?.model, [DefaultFactId.GEOLOCATION_LATITUDE]: locationInfo?.coords.latitude, @@ -65,7 +68,7 @@ export class CapacitorFactsProvider implements FactsProvider { return { ...(await Device.getInfo()), ...(await Device.getBatteryInfo()) }; } - private async collectLocationInfo() { + private async collectLocationInfo(capturedTimestamp: number) { const defaultGeolocationAge = 30000; const defaultGeolocationTimeout = 20000; const isLocationInfoCollectionEnabled = await this.isGeolocationInfoCollectionEnabled(); @@ -75,6 +78,7 @@ export class CapacitorFactsProvider implements FactsProvider { return this.geolocationService .getCurrentPosition({ + capturedTimestamp, enableHighAccuracy: true, maximumAge: defaultGeolocationAge, timeout: defaultGeolocationTimeout, diff --git a/src/app/shared/services/collector/facts/facts-provider.ts b/src/app/shared/services/collector/facts/facts-provider.ts index e4910ec16..a258c078a 100644 --- a/src/app/shared/services/collector/facts/facts-provider.ts +++ b/src/app/shared/services/collector/facts/facts-provider.ts @@ -2,5 +2,5 @@ import { Assets, Facts } from '../../repositories/proof/proof'; export interface FactsProvider { readonly id: string; - provide(assets: Assets): Promise; + provide(assets: Assets, capturedTimestamp?: number): Promise; } diff --git a/src/app/shared/services/geolocation/geolocation.service.ts b/src/app/shared/services/geolocation/geolocation.service.ts index 66fefe4d4..7659c55c3 100644 --- a/src/app/shared/services/geolocation/geolocation.service.ts +++ b/src/app/shared/services/geolocation/geolocation.service.ts @@ -11,7 +11,7 @@ export class GeolocationService { // Cache the current position manually due to the issue of Capacitor // geolocation plugin: https://github.com/ionic-team/capacitor/issues/3304 private currentPositionCache?: Position; - private lastRequestTimestamp?: number; + private lastCaptureTimestamp?: number; constructor( @Inject(GEOLOCATION_PLUGIN) @@ -19,33 +19,45 @@ export class GeolocationService { ) {} async getCurrentPosition( - { enableHighAccuracy, timeout, maximumAge }: GetCurrentPositionOptions = { + { + capturedTimestamp, + enableHighAccuracy, + timeout, + maximumAge, + }: GetCurrentPositionOptions = { enableHighAccuracy: true, timeout: undefined, maximumAge: undefined, } ): Promise { const result = await this._getCurrentPosition({ + capturedTimestamp, enableHighAccuracy, timeout, maximumAge, }); - this.lastRequestTimestamp = Date.now(); + this.lastCaptureTimestamp = capturedTimestamp; return result; } private async _getCurrentPosition( - { enableHighAccuracy, timeout, maximumAge }: GetCurrentPositionOptions = { + { + capturedTimestamp, + enableHighAccuracy, + timeout, + maximumAge, + }: GetCurrentPositionOptions = { enableHighAccuracy: true, timeout: undefined, maximumAge: undefined, } ): Promise { if ( + capturedTimestamp && maximumAge && maximumAge > 0 && this.currentPositionCache && - Date.now() - this.currentPositionCache.timestamp < maximumAge + capturedTimestamp - this.currentPositionCache.timestamp < maximumAge ) { return this.currentPositionCache; } @@ -74,9 +86,10 @@ export class GeolocationService { } if ( - this.lastRequestTimestamp && + capturedTimestamp && + this.lastCaptureTimestamp && maximumAge && - Date.now() - this.lastRequestTimestamp < maximumAge + capturedTimestamp - this.lastCaptureTimestamp < maximumAge ) { return this.currentPositionCache; } @@ -94,6 +107,7 @@ async function getTimer(timeout: number) { } export interface GetCurrentPositionOptions { + readonly capturedTimestamp?: number; readonly enableHighAccuracy?: boolean; readonly timeout?: number; readonly maximumAge?: number;