Skip to content

Commit 98b2aac

Browse files
authored
Reuse existing Iid as Fid (#924)
* Add FisError to the persisted installation entry. (#931)
1 parent 42e442f commit 98b2aac

File tree

6 files changed

+282
-53
lines changed

6 files changed

+282
-53
lines changed

firebase-installations/api.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ package com.google.firebase.installations {
2525

2626
package com.google.firebase.installations.local {
2727

28+
public class IidStore {
29+
ctor public IidStore();
30+
method @Nullable public String readIid();
31+
}
32+
2833
public class PersistedInstallation {
2934
ctor public PersistedInstallation(@NonNull FirebaseApp);
3035
method @NonNull public boolean clear();

firebase-installations/src/androidTest/java/com/google/firebase/installations/FirebaseInstallationsInstrumentedTest.java

Lines changed: 96 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
import static com.google.firebase.installations.FisAndroidTestConstants.TEST_CREATION_TIMESTAMP_2;
2929
import static com.google.firebase.installations.FisAndroidTestConstants.TEST_FID_1;
3030
import static com.google.firebase.installations.FisAndroidTestConstants.TEST_INSTALLATION_RESPONSE;
31+
import static com.google.firebase.installations.FisAndroidTestConstants.TEST_INSTALLATION_RESPONSE_WITH_IID;
3132
import static com.google.firebase.installations.FisAndroidTestConstants.TEST_INSTALLATION_TOKEN_RESULT;
33+
import static com.google.firebase.installations.FisAndroidTestConstants.TEST_INSTANCE_ID_1;
3234
import static com.google.firebase.installations.FisAndroidTestConstants.TEST_PROJECT_ID;
3335
import static com.google.firebase.installations.FisAndroidTestConstants.TEST_REFRESH_TOKEN;
3436
import static com.google.firebase.installations.FisAndroidTestConstants.TEST_TOKEN_EXPIRATION_TIMESTAMP;
@@ -52,6 +54,7 @@
5254
import com.google.firebase.FirebaseApp;
5355
import com.google.firebase.FirebaseException;
5456
import com.google.firebase.FirebaseOptions;
57+
import com.google.firebase.installations.local.IidStore;
5558
import com.google.firebase.installations.local.PersistedInstallation;
5659
import com.google.firebase.installations.local.PersistedInstallation.RegistrationStatus;
5760
import com.google.firebase.installations.local.PersistedInstallationEntry;
@@ -88,6 +91,7 @@ public class FirebaseInstallationsInstrumentedTest {
8891
@Mock private Utils mockUtils;
8992
@Mock private PersistedInstallation mockPersistedInstallation;
9093
@Mock private FirebaseInstallationServiceClient mockClient;
94+
@Mock private IidStore mockIidStore;
9195

9296
private static final PersistedInstallationEntry REGISTERED_INSTALLATION_ENTRY =
9397
PersistedInstallationEntry.builder()
@@ -99,6 +103,16 @@ public class FirebaseInstallationsInstrumentedTest {
99103
.setRegistrationStatus(PersistedInstallation.RegistrationStatus.REGISTERED)
100104
.build();
101105

106+
private static final PersistedInstallationEntry REGISTERED_IID_ENTRY =
107+
PersistedInstallationEntry.builder()
108+
.setFirebaseInstallationId(TEST_INSTANCE_ID_1)
109+
.setAuthToken(TEST_AUTH_TOKEN)
110+
.setRefreshToken(TEST_REFRESH_TOKEN)
111+
.setTokenCreationEpochInSecs(TEST_CREATION_TIMESTAMP_2)
112+
.setExpiresInSecs(TEST_TOKEN_EXPIRATION_TIMESTAMP)
113+
.setRegistrationStatus(PersistedInstallation.RegistrationStatus.REGISTERED)
114+
.build();
115+
102116
private static final PersistedInstallationEntry EXPIRED_AUTH_TOKEN_ENTRY =
103117
PersistedInstallationEntry.builder()
104118
.setFirebaseInstallationId(TEST_FID_1)
@@ -189,12 +203,20 @@ public void cleanUp() throws Exception {
189203
persistedInstallation.clear();
190204
}
191205

206+
private FirebaseInstallations getFirebaseInstallations() {
207+
return new FirebaseInstallations(
208+
executor,
209+
firebaseApp,
210+
backendClientReturnsOk,
211+
persistedInstallation,
212+
mockUtils,
213+
mockIidStore);
214+
}
215+
192216
@Test
193217
public void testGetId_PersistedInstallationOk_BackendOk() throws Exception {
194-
when(mockUtils.isAuthTokenExpired(REGISTERED_INSTALLATION_ENTRY)).thenReturn(false);
195-
FirebaseInstallations firebaseInstallations =
196-
new FirebaseInstallations(
197-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
218+
when(mockUtils.isAuthTokenExpired(REGISTERED_IID_ENTRY)).thenReturn(false);
219+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
198220

199221
// No exception, means success.
200222
assertWithMessage("getId Task failed.")
@@ -204,7 +226,8 @@ public void testGetId_PersistedInstallationOk_BackendOk() throws Exception {
204226
persistedInstallation.readPersistedInstallationEntryValue();
205227
assertThat(entryValue).hasFid(TEST_FID_1);
206228

207-
// Waiting for Task that registers FID on the FIS Servers
229+
// getId() returns fid immediately but registers fid asynchronously. Waiting for half a second
230+
// while we mock fid registration. We dont send an actual request to FIS in tests.
208231
executor.awaitTermination(500, TimeUnit.MILLISECONDS);
209232

210233
PersistedInstallationEntry updatedInstallationEntry =
@@ -213,15 +236,39 @@ public void testGetId_PersistedInstallationOk_BackendOk() throws Exception {
213236
assertThat(updatedInstallationEntry).hasRegistrationStatus(RegistrationStatus.REGISTERED);
214237
}
215238

239+
@Test
240+
public void testGetId_migrateIid_successful() throws Exception {
241+
when(mockIidStore.readIid()).thenReturn(TEST_INSTANCE_ID_1);
242+
when(mockUtils.isAuthTokenExpired(REGISTERED_INSTALLATION_ENTRY)).thenReturn(false);
243+
when(backendClientReturnsOk.createFirebaseInstallation(
244+
anyString(), anyString(), anyString(), anyString()))
245+
.thenReturn(TEST_INSTALLATION_RESPONSE_WITH_IID);
246+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
247+
248+
// No exception, means success.
249+
assertWithMessage("getId Task failed.")
250+
.that(Tasks.await(firebaseInstallations.getId()))
251+
.isNotEmpty();
252+
PersistedInstallationEntry entryValue =
253+
persistedInstallation.readPersistedInstallationEntryValue();
254+
assertThat(entryValue).hasFid(TEST_INSTANCE_ID_1);
255+
256+
// Waiting for Task that registers FID on the FIS Servers
257+
executor.awaitTermination(500, TimeUnit.MILLISECONDS);
258+
259+
PersistedInstallationEntry updatedInstallationEntry =
260+
persistedInstallation.readPersistedInstallationEntryValue();
261+
assertThat(updatedInstallationEntry).hasFid(TEST_INSTANCE_ID_1);
262+
assertThat(updatedInstallationEntry).hasRegistrationStatus(RegistrationStatus.REGISTERED);
263+
}
264+
216265
@Test
217266
public void testGetId_multipleCalls_sameFIDReturned() throws Exception {
218267
when(mockUtils.isAuthTokenExpired(REGISTERED_INSTALLATION_ENTRY)).thenReturn(false);
219268
when(backendClientReturnsOk.createFirebaseInstallation(
220269
anyString(), anyString(), anyString(), anyString()))
221270
.thenReturn(TEST_INSTALLATION_RESPONSE);
222-
FirebaseInstallations firebaseInstallations =
223-
new FirebaseInstallations(
224-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
271+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
225272

226273
// Call getId multiple times
227274
Task<String> task1 = firebaseInstallations.getId();
@@ -249,9 +296,7 @@ public void testGetId_invalidFid_storesValidFidFromResponse() throws Exception {
249296
// Update local storage with installation entry that has invalid fid.
250297
persistedInstallation.insertOrUpdatePersistedInstallationEntry(INVALID_INSTALLATION_ENTRY);
251298
when(mockUtils.isAuthTokenExpired(REGISTERED_INSTALLATION_ENTRY)).thenReturn(false);
252-
FirebaseInstallations firebaseInstallations =
253-
new FirebaseInstallations(
254-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
299+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
255300

256301
// No exception, means success.
257302
assertWithMessage("getId Task failed.")
@@ -275,7 +320,12 @@ public void testGetId_invalidFid_storesValidFidFromResponse() throws Exception {
275320
public void testGetId_PersistedInstallationOk_BackendError() throws Exception {
276321
FirebaseInstallations firebaseInstallations =
277322
new FirebaseInstallations(
278-
executor, firebaseApp, backendClientReturnsError, persistedInstallation, mockUtils);
323+
executor,
324+
firebaseApp,
325+
backendClientReturnsError,
326+
persistedInstallation,
327+
mockUtils,
328+
mockIidStore);
279329

280330
Tasks.await(firebaseInstallations.getId());
281331

@@ -299,9 +349,7 @@ public void testGetId_ServerError_UnregisteredFID() throws Exception {
299349
anyString(), anyString(), anyString(), anyString()))
300350
.thenReturn(SERVER_ERROR_INSTALLATION_RESPONSE);
301351

302-
FirebaseInstallations firebaseInstallations =
303-
new FirebaseInstallations(
304-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
352+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
305353

306354
Tasks.await(firebaseInstallations.getId());
307355

@@ -326,7 +374,8 @@ public void testGetId_PersistedInstallationError_BackendOk() throws InterruptedE
326374
firebaseApp,
327375
backendClientReturnsOk,
328376
persistedInstallationReturnsError,
329-
mockUtils);
377+
mockUtils,
378+
mockIidStore);
330379

331380
// Expect exception
332381
try {
@@ -355,7 +404,7 @@ public void testGetId_fidRegistrationUncheckedException_statusUpdated() throws E
355404

356405
FirebaseInstallations firebaseInstallations =
357406
new FirebaseInstallations(
358-
executor, firebaseApp, mockClient, persistedInstallation, mockUtils);
407+
executor, firebaseApp, mockClient, persistedInstallation, mockUtils, mockIidStore);
359408

360409
Tasks.await(firebaseInstallations.getId());
361410

@@ -387,7 +436,7 @@ public void testGetId_expiredAuthTokenUncheckedException_statusUpdated() throws
387436

388437
FirebaseInstallations firebaseInstallations =
389438
new FirebaseInstallations(
390-
executor, firebaseApp, mockClient, persistedInstallation, mockUtils);
439+
executor, firebaseApp, mockClient, persistedInstallation, mockUtils, mockIidStore);
391440

392441
assertWithMessage("getId Task failed")
393442
.that(Tasks.await(firebaseInstallations.getId()))
@@ -412,9 +461,7 @@ public void testGetId_expiredAuthToken_refreshesAuthToken() throws Exception {
412461
persistedInstallation.insertOrUpdatePersistedInstallationEntry(EXPIRED_AUTH_TOKEN_ENTRY);
413462
when(mockUtils.isAuthTokenExpired(EXPIRED_AUTH_TOKEN_ENTRY)).thenReturn(true);
414463

415-
FirebaseInstallations firebaseInstallations =
416-
new FirebaseInstallations(
417-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
464+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
418465

419466
assertWithMessage("getId Task failed")
420467
.that(Tasks.await(firebaseInstallations.getId()))
@@ -439,9 +486,7 @@ public void testGetId_expiredAuthToken_refreshesAuthToken() throws Exception {
439486
@Test
440487
public void testGetAuthToken_fidDoesNotExist_successful() throws Exception {
441488
when(mockUtils.isAuthTokenExpired(REGISTERED_INSTALLATION_ENTRY)).thenReturn(false);
442-
FirebaseInstallations firebaseInstallations =
443-
new FirebaseInstallations(
444-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
489+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
445490

446491
Tasks.await(firebaseInstallations.getAuthToken(FirebaseInstallationsApi.DO_NOT_FORCE_REFRESH));
447492

@@ -459,7 +504,8 @@ public void testGetAuthToken_PersistedInstallationError_failure() throws Excepti
459504
firebaseApp,
460505
backendClientReturnsOk,
461506
persistedInstallationReturnsError,
462-
mockUtils);
507+
mockUtils,
508+
mockIidStore);
463509

464510
// Expect exception
465511
try {
@@ -485,7 +531,12 @@ public void testGetAuthToken_fidExists_successful() throws Exception {
485531

486532
FirebaseInstallations firebaseInstallations =
487533
new FirebaseInstallations(
488-
executor, firebaseApp, backendClientReturnsOk, mockPersistedInstallation, mockUtils);
534+
executor,
535+
firebaseApp,
536+
backendClientReturnsOk,
537+
mockPersistedInstallation,
538+
mockUtils,
539+
mockIidStore);
489540

490541
InstallationTokenResult installationTokenResult =
491542
Tasks.await(
@@ -504,9 +555,7 @@ public void testGetAuthToken_expiredAuthToken_fetchedNewTokenFromFIS() throws Ex
504555
when(mockUtils.isAuthTokenExpired(EXPIRED_AUTH_TOKEN_ENTRY)).thenReturn(true);
505556
when(mockUtils.isAuthTokenExpired(UPDATED_AUTH_TOKEN_ENTRY)).thenReturn(false);
506557

507-
FirebaseInstallations firebaseInstallations =
508-
new FirebaseInstallations(
509-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
558+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
510559

511560
InstallationTokenResult installationTokenResult =
512561
Tasks.await(
@@ -526,9 +575,7 @@ public void testGetAuthToken_unregisteredFid_fetchedNewTokenFromFIS() throws Exc
526575
persistedInstallation.insertOrUpdatePersistedInstallationEntry(UNREGISTERED_INSTALLATION_ENTRY);
527576
when(mockUtils.isAuthTokenExpired(REGISTERED_INSTALLATION_ENTRY)).thenReturn(false);
528577

529-
FirebaseInstallations firebaseInstallations =
530-
new FirebaseInstallations(
531-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
578+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
532579

533580
InstallationTokenResult installationTokenResult =
534581
Tasks.await(
@@ -552,7 +599,12 @@ public void testGetAuthToken_serverError_failure() throws Exception {
552599

553600
FirebaseInstallations firebaseInstallations =
554601
new FirebaseInstallations(
555-
executor, firebaseApp, backendClientReturnsError, mockPersistedInstallation, mockUtils);
602+
executor,
603+
firebaseApp,
604+
backendClientReturnsError,
605+
mockPersistedInstallation,
606+
mockUtils,
607+
mockIidStore);
556608

557609
// Expect exception
558610
try {
@@ -579,9 +631,7 @@ public void testGetAuthToken_multipleCallsDoNotForceRefresh_fetchedNewTokenOnce(
579631
when(mockUtils.isAuthTokenExpired(EXPIRED_AUTH_TOKEN_ENTRY)).thenReturn(true);
580632
when(mockUtils.isAuthTokenExpired(UPDATED_AUTH_TOKEN_ENTRY)).thenReturn(false);
581633

582-
FirebaseInstallations firebaseInstallations =
583-
new FirebaseInstallations(
584-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
634+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
585635

586636
// Call getAuthToken multiple times with DO_NOT_FORCE_REFRESH option
587637
Task<InstallationTokenResult> task1 =
@@ -630,9 +680,7 @@ public void testGetAuthToken_multipleCallsForceRefresh_fetchedNewTokenTwice() th
630680
.generateAuthToken(anyString(), anyString(), anyString(), anyString());
631681
when(mockUtils.isAuthTokenExpired(any())).thenReturn(false);
632682

633-
FirebaseInstallations firebaseInstallations =
634-
new FirebaseInstallations(
635-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
683+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
636684

637685
// Call getAuthToken multiple times with FORCE_REFRESH option.
638686
Task<InstallationTokenResult> task1 =
@@ -659,9 +707,7 @@ public void testGetAuthToken_multipleCallsForceRefresh_fetchedNewTokenTwice() th
659707
public void testDelete_registeredFID_successful() throws Exception {
660708
// Update local storage with a registered installation entry
661709
persistedInstallation.insertOrUpdatePersistedInstallationEntry(REGISTERED_INSTALLATION_ENTRY);
662-
FirebaseInstallations firebaseInstallations =
663-
new FirebaseInstallations(
664-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
710+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
665711

666712
Tasks.await(firebaseInstallations.delete());
667713

@@ -676,9 +722,7 @@ public void testDelete_registeredFID_successful() throws Exception {
676722
public void testDelete_unregisteredFID_successful() throws Exception {
677723
// Update local storage with a unregistered installation entry
678724
persistedInstallation.insertOrUpdatePersistedInstallationEntry(UNREGISTERED_INSTALLATION_ENTRY);
679-
FirebaseInstallations firebaseInstallations =
680-
new FirebaseInstallations(
681-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
725+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
682726

683727
Tasks.await(firebaseInstallations.delete());
684728

@@ -691,9 +735,7 @@ public void testDelete_unregisteredFID_successful() throws Exception {
691735

692736
@Test
693737
public void testDelete_emptyPersistedFidEntry_successful() throws Exception {
694-
FirebaseInstallations firebaseInstallations =
695-
new FirebaseInstallations(
696-
executor, firebaseApp, backendClientReturnsOk, persistedInstallation, mockUtils);
738+
FirebaseInstallations firebaseInstallations = getFirebaseInstallations();
697739

698740
Tasks.await(firebaseInstallations.delete());
699741

@@ -710,7 +752,12 @@ public void testDelete_serverError_failure() throws Exception {
710752
persistedInstallation.insertOrUpdatePersistedInstallationEntry(REGISTERED_INSTALLATION_ENTRY);
711753
FirebaseInstallations firebaseInstallations =
712754
new FirebaseInstallations(
713-
executor, firebaseApp, backendClientReturnsError, persistedInstallation, mockUtils);
755+
executor,
756+
firebaseApp,
757+
backendClientReturnsError,
758+
persistedInstallation,
759+
mockUtils,
760+
mockIidStore);
714761

715762
// Expect exception
716763
try {

firebase-installations/src/androidTest/java/com/google/firebase/installations/FisAndroidTestConstants.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public final class FisAndroidTestConstants {
4343
public static final long TEST_CREATION_TIMESTAMP_1 = 2000L;
4444
public static final long TEST_CREATION_TIMESTAMP_2 = 2L;
4545

46+
public static final String TEST_INSTANCE_ID_1 = "ccccccccccc";
47+
4648
public static final PersistedInstallationEntry DEFAULT_PERSISTED_INSTALLATION_ENTRY =
4749
PersistedInstallationEntry.builder().build();
4850
public static final InstallationResponse TEST_INSTALLATION_RESPONSE =
@@ -59,6 +61,20 @@ public final class FisAndroidTestConstants {
5961
.setResponseCode(ResponseCode.OK)
6062
.build();
6163

64+
public static final InstallationResponse TEST_INSTALLATION_RESPONSE_WITH_IID =
65+
InstallationResponse.builder()
66+
.setUri("/projects/" + TEST_PROJECT_ID + "/installations/" + TEST_INSTANCE_ID_1)
67+
.setFid(TEST_INSTANCE_ID_1)
68+
.setRefreshToken(TEST_REFRESH_TOKEN)
69+
.setAuthToken(
70+
InstallationTokenResult.builder()
71+
.setToken(TEST_AUTH_TOKEN)
72+
.setTokenExpirationTimestamp(TEST_TOKEN_EXPIRATION_TIMESTAMP)
73+
.setTokenCreationTimestamp(TEST_CREATION_TIMESTAMP_1)
74+
.build())
75+
.setResponseCode(ResponseCode.OK)
76+
.build();
77+
6278
public static final InstallationTokenResult TEST_INSTALLATION_TOKEN_RESULT =
6379
InstallationTokenResult.builder()
6480
.setToken(TEST_AUTH_TOKEN_2)

0 commit comments

Comments
 (0)