Skip to content

Reuse existing Iid as Fid #924

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

Merged
merged 10 commits into from
Oct 25, 2019
Merged

Reuse existing Iid as Fid #924

merged 10 commits into from
Oct 25, 2019

Conversation

ankitaj224
Copy link
Contributor

Reading iid from "com.google.android.gms.appid" shared pref

@googlebot googlebot added the cla: yes Override cla label Oct 16, 2019
@ankitaj224 ankitaj224 changed the title Reusing existing Iid as Fid Reuse existing Iid as Fid Oct 16, 2019

public IidStore(@NonNull FirebaseApp firebaseApp) {
// Different FirebaseApp in the same Android application should have the same application
// context and same dir path
Copy link
Contributor

Choose a reason for hiding this comment

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

this comment is true, but it's not obvious why it's here? are we doing something differently because of this fact?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated. PTAL.

public class IidStore {
private static final String IID_SHARED_PREFS_NAME = "com.google.android.gms.appid";
private static final String STORE_KEY_PUB = "|S||P|";
private static final String STORE_KEY_ID = "|S|id";
Copy link
Contributor

Choose a reason for hiding this comment

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

both of these are missing the subtype part of the key format so they'll lose any subtype'd IDs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you please provide some context on subtype.

I saw that SUBTYPE_DEFAULT = ""; in
FirebaseInstanceId.java and this value is used for getting id from store.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't honestly know much about this topic. Rayo will have more info on subtypes and whether they're important, I just want to know that we're explicitly ok with dropping non-default subtypes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@andirayo Can you please take a look at this.

Thanks for pointing it out @ciarand

Copy link
Contributor

Choose a reason for hiding this comment

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

Background
The Instance-ID Service revolves around Registrations (identified by IID-Tokens). Registrations are authorizations, mainly authorizations to Cloud/Firebase projects (identified by project-number, called "Sender-ID") to send (FCM) notifications to an App-Instance (identified by Android-ID, Package-Name, and if necessary other parameters).
For some applications, particularly browsers (e.g. Chrome), the application needs additional information how to route incoming notifications. For this purpose, the field "subtype" was introduced. In the case of browsers, the field "subtype" holds the URL of the browser-tab or web-app that a notification is intended for. Every web-app (i.e. every different value of "subtype") will create a separate registration.
Nevertheless, the Instance-ID for all these registrations is always the same. That means, 1 App-Instance of a browser-app can have hundreds of registrations (and IID-Tokens), but only 1 Instance-ID.

IID Storage on Android
Unfortunately, I'm not familiar with the details of how the FirebaseInstanceId SDK stores data on an Android device, but the value of the field "subtype" should be irrelevant for getting the Instance-ID of an App-Instance.
However, maybe it is necessary to know one value for "subtype" to get the Instance-ID - I don't know.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I looked at the IID Android code: this was the subtype default SUBTYPE_DEFAULT = ""; Hence, I skipped adding subtype.

@ankitaj224 ankitaj224 requested a review from ciarand October 16, 2019 22:56
@ankitaj224
Copy link
Contributor Author

/test new-smoke-tests

Copy link
Contributor

@andirayo andirayo left a comment

Choose a reason for hiding this comment

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

pretty cool stuff!

assertThat(entryValue).hasFid(TEST_INSTANCE_ID_1);

// Waiting for Task that registers FID on the FIS Servers
executor.awaitTermination(500, TimeUnit.MILLISECONDS);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does this have to wait half a second?
Are we actually sending a request to FIS here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test is for getId(). As you know, getId() return fid immediately but registers fid asynchronously. Tests have to wait for half a second while we mock registration. We dont send an actual request to FIS in tests.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would recommend to add this explanation to the comment in the code.
Also, 500ms sounds excessive, but can't hurt maybe... :)

public class IidStore {
private static final String IID_SHARED_PREFS_NAME = "com.google.android.gms.appid";
private static final String STORE_KEY_PUB = "|S||P|";
private static final String STORE_KEY_ID = "|S|id";
Copy link
Contributor

Choose a reason for hiding this comment

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

Background
The Instance-ID Service revolves around Registrations (identified by IID-Tokens). Registrations are authorizations, mainly authorizations to Cloud/Firebase projects (identified by project-number, called "Sender-ID") to send (FCM) notifications to an App-Instance (identified by Android-ID, Package-Name, and if necessary other parameters).
For some applications, particularly browsers (e.g. Chrome), the application needs additional information how to route incoming notifications. For this purpose, the field "subtype" was introduced. In the case of browsers, the field "subtype" holds the URL of the browser-tab or web-app that a notification is intended for. Every web-app (i.e. every different value of "subtype") will create a separate registration.
Nevertheless, the Instance-ID for all these registrations is always the same. That means, 1 App-Instance of a browser-app can have hundreds of registrations (and IID-Tokens), but only 1 Instance-ID.

IID Storage on Android
Unfortunately, I'm not familiar with the details of how the FirebaseInstanceId SDK stores data on an Android device, but the value of the field "subtype" should be irrelevant for getting the Instance-ID of an App-Instance.
However, maybe it is necessary to know one value for "subtype" to get the Instance-ID - I don't know.

Comment on lines 55 to 59
String id = iidPrefs.getString(STORE_KEY_ID, /* defaultValue= */ null);

if (id != null) {
return id;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

(Feel free to ignore this)
How about outsourcing this into its own method, even though its only one line:

private Optional<String> readInstanceIdFromLocalStorage() {
return Optional.ofNullable(iidPrefs.getString(STORE_KEY_ID, /* defaultValue= */ null));
}

(after reading my comments below)
You can then rewrite this method like this:

return readInstanceIdFromLocalStorage().orElse(this:: readPublicKeyFromLocalStorageAndCalculateInstanceIdFromIt);

Comment on lines 230 to 233
String fid = iidStore.readIid();
if (fid == null) {
fid = utils.createRandomFid();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

(please see my comments at the bottom)
Assuming you switch the IidStore class to avoid NULL values, you can rewrite this as
String fid = iidStroe.readIid().orElse(utils::createRandomFid);

assertThat(entryValue).hasFid(TEST_INSTANCE_ID_1);

// Waiting for Task that registers FID on the FIS Servers
executor.awaitTermination(500, TimeUnit.MILLISECONDS);
Copy link
Contributor

Choose a reason for hiding this comment

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

I would recommend to add this explanation to the comment in the code.
Also, 500ms sounds excessive, but can't hurt maybe... :)

@@ -59,6 +61,20 @@
.setResponseCode(ResponseCode.OK)
.build();

public static final InstallationResponse TEST_INSTALLATION_RESPONSE_WITH_IID =
InstallationResponse.builder()
.setUri("/projects/" + TEST_PROJECT_ID + "/installations/" + TEST_INSTANCE_ID_1)
Copy link
Contributor

Choose a reason for hiding this comment

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

you could use a constant for this as well:
FIS_URI = "/projects/%s/installations/%s";

but not important.

@ankitaj224
Copy link
Contributor Author

/test smoke-tests

1 similar comment
@ankitaj224
Copy link
Contributor Author

/test smoke-tests

@ankitaj224 ankitaj224 merged commit 98b2aac into fis_sdk Oct 25, 2019
@ankitaj224 ankitaj224 deleted the iid-migration branch October 25, 2019 18:43
@firebase firebase locked and limited conversation to collaborators Nov 25, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla: yes Override cla size/L
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants