Skip to content

Commit 0806ad7

Browse files
motiz88facebook-github-bot
authored andcommitted
Use a stable device+app ID to register with the inspector proxy (#41152)
Summary: Pull Request resolved: #41152 Building on byCedric's approach in facebook/metro#991, and on D49954920, this diff passes stable, unique *logical device IDs* to the debugger connection infrastructure from Android and iOS. See D49954920 for the precise stability and uniqueness requirements that these IDs meet. Changelog: [Changed][General] - Automatically reconnect to an existing debugger session on relaunching the app Reviewed By: huntie Differential Revision: D49954919 fbshipit-source-id: d4d918f0cbfd9df426e888845817e00410efb9d3
1 parent 7009634 commit 0806ad7

File tree

2 files changed

+130
-9
lines changed

2 files changed

+130
-9
lines changed

packages/react-native/React/DevSupport/RCTInspectorDevServerHelper.mm

+60-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#import <React/RCTDefines.h>
1616
#import <React/RCTInspectorPackagerConnection.h>
1717

18+
#import <CommonCrypto/CommonCrypto.h>
19+
1820
static NSString *const kDebuggerMsgDisable = @"{ \"id\":1,\"method\":\"Debugger.disable\" }";
1921

2022
static NSString *getServerHost(NSURL *bundleURL)
@@ -40,16 +42,65 @@
4042
return [NSString stringWithFormat:@"%@:%@", host, port];
4143
}
4244

45+
static NSString *getSHA256(NSString *string)
46+
{
47+
const char *str = string.UTF8String;
48+
unsigned char result[CC_SHA256_DIGEST_LENGTH];
49+
CC_SHA256(str, (CC_LONG)strlen(str), result);
50+
51+
return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
52+
result[0],
53+
result[1],
54+
result[2],
55+
result[3],
56+
result[4],
57+
result[5],
58+
result[6],
59+
result[7],
60+
result[8],
61+
result[9],
62+
result[10],
63+
result[11],
64+
result[12],
65+
result[13],
66+
result[14],
67+
result[15],
68+
result[16],
69+
result[17],
70+
result[18],
71+
result[19]];
72+
}
73+
74+
// Returns an opaque ID which is stable for the current combination of device and app, stable across installs,
75+
// and unique across devices.
76+
static NSString *getInspectorDeviceId()
77+
{
78+
// A bundle ID uniquely identifies a single app throughout the system. [Source: Apple docs]
79+
NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier];
80+
81+
// An alphanumeric string that uniquely identifies a device to the app's vendor. [Source: Apple docs]
82+
NSString *identifierForVendor = [[UIDevice currentDevice] identifierForVendor].UUIDString;
83+
84+
NSString *rawDeviceId = [NSString stringWithFormat:@"apple-%@-%@", identifierForVendor, bundleId];
85+
86+
return getSHA256(rawDeviceId);
87+
}
88+
4389
static NSURL *getInspectorDeviceUrl(NSURL *bundleURL)
4490
{
4591
NSString *escapedDeviceName = [[[UIDevice currentDevice] name]
4692
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
4793
NSString *escapedAppName = [[[NSBundle mainBundle] bundleIdentifier]
4894
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
49-
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/inspector/device?name=%@&app=%@",
95+
96+
NSString *escapedInspectorDeviceId = [getInspectorDeviceId()
97+
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
98+
99+
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/inspector/device?name=%@&app=%@&device=%@",
50100
getServerHost(bundleURL),
51101
escapedDeviceName,
52-
escapedAppName]];
102+
escapedAppName,
103+
escapedInspectorDeviceId]];
53104
}
54105

55106
@implementation RCTInspectorDevServerHelper
@@ -70,8 +121,13 @@ + (void)openDebugger:(NSURL *)bundleURL withErrorMessage:(NSString *)errorMessag
70121
NSString *appId = [[[NSBundle mainBundle] bundleIdentifier]
71122
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
72123

73-
NSURL *url = [NSURL
74-
URLWithString:[NSString stringWithFormat:@"http://%@/open-debugger?appId=%@", getServerHost(bundleURL), appId]];
124+
NSString *escapedInspectorDeviceId = [getInspectorDeviceId()
125+
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
126+
127+
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/open-debugger?appId=%@&device=%@",
128+
getServerHost(bundleURL),
129+
appId,
130+
escapedInspectorDeviceId]];
75131
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
76132
[request setHTTPMethod:@"POST"];
77133

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java

+70-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import android.net.Uri;
1111
import android.os.AsyncTask;
12+
import android.provider.Settings;
1213
import androidx.annotation.NonNull;
1314
import androidx.annotation.Nullable;
1415
import com.facebook.common.logging.FLog;
@@ -30,6 +31,9 @@
3031
import com.facebook.react.util.RNLog;
3132
import java.io.File;
3233
import java.io.IOException;
34+
import java.io.UnsupportedEncodingException;
35+
import java.security.MessageDigest;
36+
import java.security.NoSuchAlgorithmException;
3337
import java.util.HashMap;
3438
import java.util.Locale;
3539
import java.util.Map;
@@ -244,13 +248,73 @@ public String getWebsocketProxyURL() {
244248
mPackagerConnectionSettings.getDebugServerHost());
245249
}
246250

251+
private static String getSHA256(String string) {
252+
MessageDigest digest = null;
253+
try {
254+
digest = MessageDigest.getInstance("SHA-256");
255+
} catch (NoSuchAlgorithmException e) {
256+
throw new AssertionError("Could not get standard SHA-256 algorithm", e);
257+
}
258+
digest.reset();
259+
byte[] result;
260+
try {
261+
result = digest.digest(string.getBytes("UTF-8"));
262+
} catch (UnsupportedEncodingException e) {
263+
throw new AssertionError("This environment doesn't support UTF-8 encoding", e);
264+
}
265+
return String.format(
266+
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
267+
result[0],
268+
result[1],
269+
result[2],
270+
result[3],
271+
result[4],
272+
result[5],
273+
result[6],
274+
result[7],
275+
result[8],
276+
result[9],
277+
result[10],
278+
result[11],
279+
result[12],
280+
result[13],
281+
result[14],
282+
result[15],
283+
result[16],
284+
result[17],
285+
result[18],
286+
result[19]);
287+
}
288+
289+
// Returns an opaque ID which is stable for the current combination of device and app, stable
290+
// across installs, and unique across devices.
291+
private String getInspectorDeviceId() {
292+
// Every Android app has a unique application ID that looks like a Java or Kotlin package name,
293+
// such as com.example.myapp. This ID uniquely identifies your app on the device and in the
294+
// Google Play Store.
295+
// [Source: Android docs]
296+
String packageName = mPackageName;
297+
298+
// A 64-bit number expressed as a hexadecimal string, which is either:
299+
// * unique to each combination of app-signing key, user, and device (API level >= 26), or
300+
// * randomly generated when the user first sets up the device and should remain constant for
301+
// the lifetime of the user's device (API level < 26).
302+
// [Source: Android docs]
303+
String androidId = Settings.Secure.ANDROID_ID;
304+
305+
String rawDeviceId = String.format(Locale.US, "android-%s-%s", packageName, androidId);
306+
307+
return getSHA256(rawDeviceId);
308+
}
309+
247310
private String getInspectorDeviceUrl() {
248311
return String.format(
249312
Locale.US,
250-
"http://%s/inspector/device?name=%s&app=%s",
313+
"http://%s/inspector/device?name=%s&app=%s&device=%s",
251314
mPackagerConnectionSettings.getInspectorServerHost(),
252-
AndroidInfoHelpers.getFriendlyDeviceName(),
253-
mPackageName);
315+
Uri.encode(AndroidInfoHelpers.getFriendlyDeviceName()),
316+
Uri.encode(mPackageName),
317+
Uri.encode(getInspectorDeviceId()));
254318
}
255319

256320
public void downloadBundleFromURL(
@@ -425,9 +489,10 @@ public void openDebugger(final ReactContext context, final String errorMessage)
425489
String requestUrl =
426490
String.format(
427491
Locale.US,
428-
"http://%s/open-debugger?appId=%s",
492+
"http://%s/open-debugger?appId=%s&device=%s",
429493
mPackagerConnectionSettings.getInspectorServerHost(),
430-
Uri.encode(mPackageName));
494+
Uri.encode(mPackageName),
495+
Uri.encode(getInspectorDeviceId()));
431496
Request request =
432497
new Request.Builder().url(requestUrl).method("POST", RequestBody.create(null, "")).build();
433498

0 commit comments

Comments
 (0)