mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Use a stable device+app ID to register with the inspector proxy (#41152)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41152 Building on byCedric's approach in https://github.com/facebook/metro/pull/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
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTInspectorPackagerConnection.h>
|
||||
|
||||
#import <CommonCrypto/CommonCrypto.h>
|
||||
|
||||
static NSString *const kDebuggerMsgDisable = @"{ \"id\":1,\"method\":\"Debugger.disable\" }";
|
||||
|
||||
static NSString *getServerHost(NSURL *bundleURL)
|
||||
@@ -40,16 +42,65 @@ static NSString *getServerHost(NSURL *bundleURL)
|
||||
return [NSString stringWithFormat:@"%@:%@", host, port];
|
||||
}
|
||||
|
||||
static NSString *getSHA256(NSString *string)
|
||||
{
|
||||
const char *str = string.UTF8String;
|
||||
unsigned char result[CC_SHA256_DIGEST_LENGTH];
|
||||
CC_SHA256(str, (CC_LONG)strlen(str), result);
|
||||
|
||||
return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
result[0],
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
result[6],
|
||||
result[7],
|
||||
result[8],
|
||||
result[9],
|
||||
result[10],
|
||||
result[11],
|
||||
result[12],
|
||||
result[13],
|
||||
result[14],
|
||||
result[15],
|
||||
result[16],
|
||||
result[17],
|
||||
result[18],
|
||||
result[19]];
|
||||
}
|
||||
|
||||
// Returns an opaque ID which is stable for the current combination of device and app, stable across installs,
|
||||
// and unique across devices.
|
||||
static NSString *getInspectorDeviceId()
|
||||
{
|
||||
// A bundle ID uniquely identifies a single app throughout the system. [Source: Apple docs]
|
||||
NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier];
|
||||
|
||||
// An alphanumeric string that uniquely identifies a device to the app's vendor. [Source: Apple docs]
|
||||
NSString *identifierForVendor = [[UIDevice currentDevice] identifierForVendor].UUIDString;
|
||||
|
||||
NSString *rawDeviceId = [NSString stringWithFormat:@"apple-%@-%@", identifierForVendor, bundleId];
|
||||
|
||||
return getSHA256(rawDeviceId);
|
||||
}
|
||||
|
||||
static NSURL *getInspectorDeviceUrl(NSURL *bundleURL)
|
||||
{
|
||||
NSString *escapedDeviceName = [[[UIDevice currentDevice] name]
|
||||
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
|
||||
NSString *escapedAppName = [[[NSBundle mainBundle] bundleIdentifier]
|
||||
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
|
||||
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/inspector/device?name=%@&app=%@",
|
||||
|
||||
NSString *escapedInspectorDeviceId = [getInspectorDeviceId()
|
||||
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
|
||||
|
||||
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/inspector/device?name=%@&app=%@&device=%@",
|
||||
getServerHost(bundleURL),
|
||||
escapedDeviceName,
|
||||
escapedAppName]];
|
||||
escapedAppName,
|
||||
escapedInspectorDeviceId]];
|
||||
}
|
||||
|
||||
@implementation RCTInspectorDevServerHelper
|
||||
@@ -70,8 +121,13 @@ static void sendEventToAllConnections(NSString *event)
|
||||
NSString *appId = [[[NSBundle mainBundle] bundleIdentifier]
|
||||
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
|
||||
|
||||
NSURL *url = [NSURL
|
||||
URLWithString:[NSString stringWithFormat:@"http://%@/open-debugger?appId=%@", getServerHost(bundleURL), appId]];
|
||||
NSString *escapedInspectorDeviceId = [getInspectorDeviceId()
|
||||
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
|
||||
|
||||
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/open-debugger?appId=%@&device=%@",
|
||||
getServerHost(bundleURL),
|
||||
appId,
|
||||
escapedInspectorDeviceId]];
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
||||
[request setHTTPMethod:@"POST"];
|
||||
|
||||
|
||||
+70
-5
@@ -9,6 +9,7 @@ package com.facebook.react.devsupport;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.provider.Settings;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.common.logging.FLog;
|
||||
@@ -30,6 +31,9 @@ import com.facebook.react.packagerconnection.Responder;
|
||||
import com.facebook.react.util.RNLog;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -244,13 +248,73 @@ public class DevServerHelper {
|
||||
mPackagerConnectionSettings.getDebugServerHost());
|
||||
}
|
||||
|
||||
private static String getSHA256(String string) {
|
||||
MessageDigest digest = null;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError("Could not get standard SHA-256 algorithm", e);
|
||||
}
|
||||
digest.reset();
|
||||
byte[] result;
|
||||
try {
|
||||
result = digest.digest(string.getBytes("UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError("This environment doesn't support UTF-8 encoding", e);
|
||||
}
|
||||
return String.format(
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
result[0],
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
result[6],
|
||||
result[7],
|
||||
result[8],
|
||||
result[9],
|
||||
result[10],
|
||||
result[11],
|
||||
result[12],
|
||||
result[13],
|
||||
result[14],
|
||||
result[15],
|
||||
result[16],
|
||||
result[17],
|
||||
result[18],
|
||||
result[19]);
|
||||
}
|
||||
|
||||
// Returns an opaque ID which is stable for the current combination of device and app, stable
|
||||
// across installs, and unique across devices.
|
||||
private String getInspectorDeviceId() {
|
||||
// Every Android app has a unique application ID that looks like a Java or Kotlin package name,
|
||||
// such as com.example.myapp. This ID uniquely identifies your app on the device and in the
|
||||
// Google Play Store.
|
||||
// [Source: Android docs]
|
||||
String packageName = mPackageName;
|
||||
|
||||
// A 64-bit number expressed as a hexadecimal string, which is either:
|
||||
// * unique to each combination of app-signing key, user, and device (API level >= 26), or
|
||||
// * randomly generated when the user first sets up the device and should remain constant for
|
||||
// the lifetime of the user's device (API level < 26).
|
||||
// [Source: Android docs]
|
||||
String androidId = Settings.Secure.ANDROID_ID;
|
||||
|
||||
String rawDeviceId = String.format(Locale.US, "android-%s-%s", packageName, androidId);
|
||||
|
||||
return getSHA256(rawDeviceId);
|
||||
}
|
||||
|
||||
private String getInspectorDeviceUrl() {
|
||||
return String.format(
|
||||
Locale.US,
|
||||
"http://%s/inspector/device?name=%s&app=%s",
|
||||
"http://%s/inspector/device?name=%s&app=%s&device=%s",
|
||||
mPackagerConnectionSettings.getInspectorServerHost(),
|
||||
AndroidInfoHelpers.getFriendlyDeviceName(),
|
||||
mPackageName);
|
||||
Uri.encode(AndroidInfoHelpers.getFriendlyDeviceName()),
|
||||
Uri.encode(mPackageName),
|
||||
Uri.encode(getInspectorDeviceId()));
|
||||
}
|
||||
|
||||
public void downloadBundleFromURL(
|
||||
@@ -425,9 +489,10 @@ public class DevServerHelper {
|
||||
String requestUrl =
|
||||
String.format(
|
||||
Locale.US,
|
||||
"http://%s/open-debugger?appId=%s",
|
||||
"http://%s/open-debugger?appId=%s&device=%s",
|
||||
mPackagerConnectionSettings.getInspectorServerHost(),
|
||||
Uri.encode(mPackageName));
|
||||
Uri.encode(mPackageName),
|
||||
Uri.encode(getInspectorDeviceId()));
|
||||
Request request =
|
||||
new Request.Builder().url(requestUrl).method("POST", RequestBody.create(null, "")).build();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user