30
30
import java .security .PublicKey ;
31
31
import java .security .spec .InvalidKeySpecException ;
32
32
import java .security .spec .X509EncodedKeySpec ;
33
+ import org .json .JSONException ;
34
+ import org .json .JSONObject ;
33
35
34
36
/**
35
37
* Read existing iid only for default (first initialized) instance of this firebase application.*
@@ -38,17 +40,79 @@ public class IidStore {
38
40
private static final String IID_SHARED_PREFS_NAME = "com.google.android.gms.appid" ;
39
41
private static final String STORE_KEY_PUB = "|S||P|" ;
40
42
private static final String STORE_KEY_ID = "|S|id" ;
43
+ private static final String STORE_KEY_TOKEN = "|T|" ;
44
+ private static final String DEFAULT_SCOPE = "|*" ;
45
+ private static final String JSON_TOKEN_KEY = "token" ;
46
+ private static final String JSON_ENCODED_PREFIX = "{" ;
41
47
42
48
@ GuardedBy ("iidPrefs" )
43
49
private final SharedPreferences iidPrefs ;
44
50
51
+ private final String defaultSenderId ;
52
+
45
53
public IidStore () {
46
54
// Different FirebaseApp in the same Android application should have the same application
47
55
// context and same dir path. We only read existing Iids for the default firebase application.
48
56
iidPrefs =
49
57
FirebaseApp .getInstance ()
50
58
.getApplicationContext ()
51
59
.getSharedPreferences (IID_SHARED_PREFS_NAME , Context .MODE_PRIVATE );
60
+
61
+ defaultSenderId = getDefaultSenderId (FirebaseApp .getInstance ());
62
+ }
63
+
64
+ private static String getDefaultSenderId (FirebaseApp app ) {
65
+ // Check for an explicit sender id
66
+ String senderId = app .getOptions ().getGcmSenderId ();
67
+ if (senderId != null ) {
68
+ return senderId ;
69
+ }
70
+ String appId = app .getOptions ().getApplicationId ();
71
+ if (!appId .startsWith ("1:" )) {
72
+ // Not v1, server should be updated to accept the full app ID now
73
+ return appId ;
74
+ }
75
+ // For v1 app IDs, fall back to parsing the project number out
76
+ @ SuppressWarnings ("StringSplitter" )
77
+ String [] parts = appId .split (":" );
78
+ if (parts .length < 2 ) {
79
+ return null ; // Invalid format
80
+ }
81
+ String projectNumber = parts [1 ];
82
+ if (projectNumber .isEmpty ()) {
83
+ return null ; // No project number
84
+ }
85
+ return projectNumber ;
86
+ }
87
+
88
+ private String createTokenKey (@ NonNull String senderId ) {
89
+ return STORE_KEY_TOKEN + senderId + DEFAULT_SCOPE ;
90
+ }
91
+
92
+ @ Nullable
93
+ public String readToken () {
94
+ synchronized (iidPrefs ) {
95
+ String token = iidPrefs .getString (createTokenKey (defaultSenderId ), null );
96
+ if (token .isEmpty ()) {
97
+ return null ;
98
+ }
99
+
100
+ if (token .startsWith (JSON_ENCODED_PREFIX )) {
101
+ return parseIidTokenFromJson (token );
102
+ }
103
+ // Legacy value, token is whole string
104
+ return token ;
105
+ }
106
+ }
107
+
108
+ private String parseIidTokenFromJson (String token ) {
109
+ // Encoded as JSON
110
+ try {
111
+ JSONObject json = new JSONObject (token );
112
+ return json .getString (JSON_TOKEN_KEY );
113
+ } catch (JSONException e ) {
114
+ return null ;
115
+ }
52
116
}
53
117
54
118
@ Nullable
0 commit comments