Skip to content

Commit 23db8ef

Browse files
committed
Adds device parameter to InspectorPackagerConnection URL
In preparation for unblocking Fusebox in react-native-windows, this change adds a stable device ID, which is a hash of the publisher device ID from Windows APIs and the bundle ID.
1 parent 2731008 commit 23db8ef

File tree

6 files changed

+80
-33
lines changed

6 files changed

+80
-33
lines changed

vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ void ReactInstanceWin::InitializeBridgeless() noexcept {
611611

612612
if (devSettings->useDirectDebugger) {
613613
::Microsoft::ReactNative::GetSharedDevManager()->EnsureHermesInspector(
614-
devSettings->sourceBundleHost, devSettings->sourceBundlePort);
614+
devSettings->sourceBundleHost, devSettings->sourceBundlePort, devSettings->bundleAppId);
615615
}
616616

617617
m_jsiRuntimeHolder = std::make_shared<Microsoft::ReactNative::HermesRuntimeHolder>(

vnext/Shared/DevServerHelper.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,14 @@ class DevServerHelper {
7676
const std::string &packagerHost,
7777
const uint16_t packagerPort,
7878
const std::string &deviceName,
79-
const std::string &packageName) {
79+
const std::string &packageName,
80+
const std::string &deviceId) {
8081
return string_format(
8182
InspectorDeviceUrlFormat,
8283
GetDeviceLocalHost(packagerHost, packagerPort).c_str(),
8384
deviceName.c_str(),
84-
packageName.c_str());
85+
packageName.c_str(),
86+
deviceId.c_str());
8587
}
8688

8789
static constexpr const char DefaultPackagerHost[] = "localhost";
@@ -105,7 +107,7 @@ class DevServerHelper {
105107
static constexpr const char PackagerConnectionUrlFormat[] = "ws://%s/message";
106108
static constexpr const char PackagerStatusUrlFormat[] = "http://%s/status";
107109
static constexpr const char PackagerOpenStackFrameUrlFormat[] = "https://%s/open-stack-frame";
108-
static constexpr const char InspectorDeviceUrlFormat[] = "ws://%s/inspector/device?name=%s&app=%s";
110+
static constexpr const char InspectorDeviceUrlFormat[] = "ws://%s/inspector/device?name=%s&app=%s&device=%s";
109111

110112
static constexpr const char PackagerOkStatus[] = "packager-status:running";
111113
const int LongPollFailureDelayMs = 5000;

vnext/Shared/DevSupportManager.cpp

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616

1717
#include <Utils/CppWinrtLessExceptions.h>
1818
#include <winrt/Windows.Foundation.h>
19+
#include <winrt/Windows.Security.Cryptography.Core.h>
20+
#include <winrt/Windows.Security.Cryptography.h>
1921
#include <winrt/Windows.Storage.Streams.h>
22+
#include <winrt/Windows.System.Profile.h>
2023
#include <winrt/Windows.Web.Http.Filters.h>
2124
#include <winrt/Windows.Web.Http.Headers.h>
2225
#include <winrt/Windows.Web.Http.h>
@@ -171,6 +174,33 @@ bool IsIgnorablePollHResult(HRESULT hr) {
171174
return hr == WININET_E_INVALID_SERVER_RESPONSE;
172175
}
173176

177+
std::string GetDeviceId(const std::string &bundleAppId) {
178+
const auto hash = winrt::Windows::Security::Cryptography::Core::HashAlgorithmProvider::OpenAlgorithm(
179+
winrt::Windows::Security::Cryptography::Core::HashAlgorithmNames::Sha256())
180+
.CreateHash();
181+
hash.Append(winrt::Windows::System::Profile::SystemIdentification::GetSystemIdForPublisher().Id());
182+
winrt::Windows::Storage::Streams::InMemoryRandomAccessStream stream;
183+
winrt::Windows::Storage::Streams::DataWriter writer;
184+
// If an app ID is provided, we will allow reconnection to DevTools.
185+
// Apps must supply a unique app ID to each ReactNativeHost instance settings for this to behave correctly.
186+
if (!bundleAppId.empty()) {
187+
const auto bundleAppIdBuffer = winrt::Windows::Security::Cryptography::CryptographicBuffer::ConvertStringToBinary(
188+
winrt::to_hstring(bundleAppId), winrt::Windows::Security::Cryptography::BinaryStringEncoding::Utf16BE);
189+
hash.Append(bundleAppIdBuffer);
190+
} else {
191+
const auto processId = GetCurrentProcessId();
192+
std::vector<uint8_t> processIdBytes(
193+
reinterpret_cast<const uint8_t *>(&processId), reinterpret_cast<const uint8_t *>(&processId + 1));
194+
winrt::array_view<uint8_t> processIdByteArray(processIdBytes);
195+
const auto processIdBuffer =
196+
winrt::Windows::Security::Cryptography::CryptographicBuffer::CreateFromByteArray(processIdByteArray);
197+
hash.Append(processIdBuffer);
198+
}
199+
const auto hashBuffer = hash.GetValueAndReset();
200+
const auto hashString = winrt::Windows::Security::Cryptography::CryptographicBuffer::EncodeToHexString(hashBuffer);
201+
return winrt::to_string(hashString);
202+
}
203+
174204
std::future<winrt::Windows::Web::Http::HttpStatusCode> PollForLiveReload(const std::string &url) {
175205
winrt::Windows::Web::Http::HttpClient httpClient;
176206
winrt::Windows::Foundation::Uri uri(Microsoft::Common::Unicode::Utf8ToUtf16(url));
@@ -240,16 +270,21 @@ void DevSupportManager::StopPollingLiveReload() {
240270

241271
void DevSupportManager::EnsureHermesInspector(
242272
[[maybe_unused]] const std::string &packagerHost,
243-
[[maybe_unused]] const uint16_t packagerPort) noexcept {
273+
[[maybe_unused]] const uint16_t packagerPort,
274+
[[maybe_unused]] const std::string &bundleAppId) noexcept {
244275
static std::once_flag once;
245-
std::call_once(once, [this, &packagerHost, packagerPort]() {
276+
std::call_once(once, [this, &packagerHost, packagerPort, &jsBundleName]() {
246277
// TODO: should we use the bundleAppId as the app param if available?
247-
std::string packageName("RNW");
248-
wchar_t fullName[PACKAGE_FULL_NAME_MAX_LENGTH]{};
249-
UINT32 size = ARRAYSIZE(fullName);
250-
if (SUCCEEDED(GetCurrentPackageFullName(&size, fullName))) {
251-
// we are in an unpackaged app
252-
packageName = winrt::to_string(fullName);
278+
279+
std::string packageName{bundleAppId};
280+
if (packageName == "") {
281+
std::string packageName("RNW");
282+
wchar_t fullName[PACKAGE_FULL_NAME_MAX_LENGTH]{};
283+
UINT32 size = ARRAYSIZE(fullName);
284+
if (SUCCEEDED(GetCurrentPackageFullName(&size, fullName))) {
285+
// we are in an unpackaged app
286+
packageName = winrt::to_string(fullName);
287+
}
253288
}
254289

255290
std::string deviceName("RNWHost");
@@ -258,8 +293,10 @@ void DevSupportManager::EnsureHermesInspector(
258293
deviceName = winrt::to_string(hostNames.First().Current().DisplayName());
259294
}
260295

296+
const auto deviceId = GetDeviceId(packageName);
261297
m_inspectorPackagerConnection = std::make_shared<InspectorPackagerConnection>(
262-
facebook::react::DevServerHelper::get_InspectorDeviceUrl(packagerHost, packagerPort, deviceName, packageName),
298+
facebook::react::DevServerHelper::get_InspectorDeviceUrl(
299+
packagerHost, packagerPort, deviceName, packageName, deviceId),
263300
m_BundleStatusProvider);
264301
m_inspectorPackagerConnection->connectAsync();
265302
});

vnext/Shared/DevSupportManager.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ class DevSupportManager final : public facebook::react::IDevSupportManager {
4949
std::function<void()> onChangeCallback) override;
5050
virtual void StopPollingLiveReload() override;
5151

52-
virtual void EnsureHermesInspector(const std::string &packagerHost, const uint16_t packagerPort) noexcept override;
52+
virtual void EnsureHermesInspector(
53+
const std::string &packagerHost,
54+
const uint16_t packagerPort,
55+
const std::string &bundleAppId) noexcept override;
5356
virtual void UpdateBundleStatus(bool isLastDownloadSuccess, int64_t updateTimestamp) noexcept override;
5457

5558
private:

vnext/Shared/IDevSupportManager.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ struct IDevSupportManager {
2424
std::function<void()> onChangeCallback) = 0;
2525
virtual void StopPollingLiveReload() = 0;
2626

27-
virtual void EnsureHermesInspector(const std::string &packagerHost, const uint16_t packagerPort) noexcept = 0;
27+
virtual void EnsureHermesInspector(
28+
const std::string &packagerHost,
29+
const uint16_t packagerPort,
30+
const std::string &bundleAppId) noexcept = 0;
2831
virtual void UpdateBundleStatus(bool isLastDownloadSuccess, int64_t updateTimestamp) noexcept = 0;
2932
};
3033

vnext/Shared/OInstance.cpp

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,20 @@ using namespace Microsoft::JSI;
7373
using std::make_shared;
7474
using winrt::Microsoft::ReactNative::ReactPropertyBagHelper;
7575

76+
namespace facebook::react {
77+
bool shouldStartHermesInspector(DevSettings &devSettings) {
78+
bool isHermes =
79+
((devSettings.jsiEngineOverride == JSIEngineOverride::Hermes) ||
80+
(devSettings.jsiEngineOverride == JSIEngineOverride::Default && devSettings.jsiRuntimeHolder &&
81+
devSettings.jsiRuntimeHolder->getRuntimeType() == facebook::react::JSIEngineOverride::Hermes));
82+
83+
if (isHermes && devSettings.useDirectDebugger && !devSettings.useWebDebugger)
84+
return true;
85+
else
86+
return false;
87+
}
88+
} // namespace facebook::react
89+
7690
namespace Microsoft::ReactNative {
7791

7892
// Note: Based on
@@ -105,6 +119,12 @@ void LoadRemoteUrlScript(
105119
hermesBytecodeVersion = ::hermes::hbc::BYTECODE_VERSION;
106120
#endif
107121

122+
const auto bundlePath = ;
123+
if (facebook::react::shouldStartHermesInspector(*devSettings)) {
124+
devManager->EnsureHermesInspector(
125+
devSettings->sourceBundleHost, devSettings->sourceBundlePort, devSettings->bundleAppId);
126+
}
127+
108128
auto [jsBundleString, success] = GetJavaScriptFromServer(
109129
devSettings->sourceBundleHost,
110130
devSettings->sourceBundlePort,
@@ -329,20 +349,6 @@ void InstanceImpl::SetInError() noexcept {
329349
m_isInError = true;
330350
}
331351

332-
namespace {
333-
bool shouldStartHermesInspector(DevSettings &devSettings) {
334-
bool isHermes =
335-
((devSettings.jsiEngineOverride == JSIEngineOverride::Hermes) ||
336-
(devSettings.jsiEngineOverride == JSIEngineOverride::Default && devSettings.jsiRuntimeHolder &&
337-
devSettings.jsiRuntimeHolder->getRuntimeType() == facebook::react::JSIEngineOverride::Hermes));
338-
339-
if (isHermes && devSettings.useDirectDebugger && !devSettings.useWebDebugger)
340-
return true;
341-
else
342-
return false;
343-
}
344-
} // namespace
345-
346352
InstanceImpl::InstanceImpl(
347353
std::shared_ptr<Instance> &&instance,
348354
std::string &&jsBundleBasePath,
@@ -373,10 +379,6 @@ InstanceImpl::InstanceImpl(
373379
facebook::react::tracing::initializeETW();
374380
#endif
375381

376-
if (shouldStartHermesInspector(*m_devSettings)) {
377-
m_devManager->EnsureHermesInspector(m_devSettings->sourceBundleHost, m_devSettings->sourceBundlePort);
378-
}
379-
380382
// Default (common) NativeModules
381383
auto modules = GetDefaultNativeModules(nativeQueue);
382384

0 commit comments

Comments
 (0)