feat: add new runningUnderARM64Translation property to detect x64 translated apps running on Windows ARM (#29168)

* feat: add new runningUnderARM64Translation property to detect x64 translated apps running on Windows ARM

* docs: add documentation for the new runningUnderARM64Translation property

* refactor: clean up `IsRunningUnderARM64Translation` Windows implementation

* Return false if IsWow64Process2 doesn't exist

* Emit deprecation warning in runningUnderRosettaTranslation
This commit is contained in:
Sergio Padrino 2021-06-02 09:16:33 +02:00 committed by GitHub
parent 3b75549511
commit abf6f5c8ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 1 deletions

View file

@ -1427,7 +1427,7 @@ This is the user agent that will be used when no user agent is set at the
app has the same user agent. Set to a custom value as early as possible app has the same user agent. Set to a custom value as early as possible
in your app's initialization to ensure that your overridden value is used. in your app's initialization to ensure that your overridden value is used.
### `app.runningUnderRosettaTranslation` _macOS_ _Readonly_ ### `app.runningUnderRosettaTranslation` _macOS_ _Readonly_ _Deprecated_
A `Boolean` which when `true` indicates that the app is currently running A `Boolean` which when `true` indicates that the app is currently running
under the [Rosetta Translator Environment](https://en.wikipedia.org/wiki/Rosetta_(software)). under the [Rosetta Translator Environment](https://en.wikipedia.org/wiki/Rosetta_(software)).
@ -1435,3 +1435,18 @@ under the [Rosetta Translator Environment](https://en.wikipedia.org/wiki/Rosetta
You can use this property to prompt users to download the arm64 version of You can use this property to prompt users to download the arm64 version of
your application when they are running the x64 version under Rosetta your application when they are running the x64 version under Rosetta
incorrectly. incorrectly.
**Deprecated:** This property is superceded by the `runningUnderARM64Translation`
property which detects when the app is being translated to ARM64 in both macOS
and Windows.
### `app.runningUnderARM64Translation` _Readonly_ _macOS_ _Windows_
A `Boolean` which when `true` indicates that the app is currently running under
an ARM64 translator (like the macOS
[Rosetta Translator Environment](https://en.wikipedia.org/wiki/Rosetta_(software))
or Windows [WOW](https://en.wikipedia.org/wiki/Windows_on_Windows)).
You can use this property to prompt users to download the arm64 version of
your application when they are running the x64 version under Rosetta
incorrectly.

View file

@ -1440,6 +1440,27 @@ void App::SetUserAgentFallback(const std::string& user_agent) {
ElectronBrowserClient::Get()->SetUserAgent(user_agent); ElectronBrowserClient::Get()->SetUserAgent(user_agent);
} }
#if defined(OS_WIN)
bool App::IsRunningUnderARM64Translation() const {
USHORT processMachine = 0;
USHORT nativeMachine = 0;
auto IsWow64Process2 = reinterpret_cast<decltype(&::IsWow64Process2)>(
GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process2"));
if (IsWow64Process2 == nullptr) {
return false;
}
if (!IsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine)) {
return false;
}
return nativeMachine == IMAGE_FILE_MACHINE_ARM64;
}
#endif
std::string App::GetUserAgentFallback() { std::string App::GetUserAgentFallback() {
return ElectronBrowserClient::Get()->GetUserAgent(); return ElectronBrowserClient::Get()->GetUserAgent();
} }
@ -1642,6 +1663,10 @@ gin::ObjectTemplateBuilder App::GetObjectTemplateBuilder(v8::Isolate* isolate) {
.SetProperty("dock", &App::GetDockAPI) .SetProperty("dock", &App::GetDockAPI)
.SetProperty("runningUnderRosettaTranslation", .SetProperty("runningUnderRosettaTranslation",
&App::IsRunningUnderRosettaTranslation) &App::IsRunningUnderRosettaTranslation)
#endif
#if defined(OS_MAC) || defined(OS_WIN)
.SetProperty("runningUnderARM64Translation",
&App::IsRunningUnderARM64Translation)
#endif #endif
.SetProperty("userAgentFallback", &App::GetUserAgentFallback, .SetProperty("userAgentFallback", &App::GetUserAgentFallback,
&App::SetUserAgentFallback) &App::SetUserAgentFallback)

View file

@ -223,6 +223,10 @@ class App : public ElectronBrowserClient::Delegate,
v8::Global<v8::Value> dock_; v8::Global<v8::Value> dock_;
#endif #endif
#if defined(OS_MAC) || defined(OS_WIN)
bool IsRunningUnderARM64Translation() const;
#endif
#if defined(MAS_BUILD) #if defined(MAS_BUILD)
base::RepeatingCallback<void()> StartAccessingSecurityScopedResource( base::RepeatingCallback<void()> StartAccessingSecurityScopedResource(
gin::Arguments* args); gin::Arguments* args);

View file

@ -60,6 +60,17 @@ void App::SetActivationPolicy(gin_helper::ErrorThrower thrower,
} }
bool App::IsRunningUnderRosettaTranslation() const { bool App::IsRunningUnderRosettaTranslation() const {
node::Environment* env =
node::Environment::GetCurrent(JavascriptEnvironment::GetIsolate());
EmitWarning(env,
"The app.runningUnderRosettaTranslation API is deprecated, use "
"app.runningUnderARM64Translation instead.",
"electron");
return IsRunningUnderARM64Translation();
}
bool App::IsRunningUnderARM64Translation() const {
int proc_translated = 0; int proc_translated = 0;
size_t size = sizeof(proc_translated); size_t size = sizeof(proc_translated);
if (sysctlbyname("sysctl.proc_translated", &proc_translated, &size, NULL, if (sysctlbyname("sysctl.proc_translated", &proc_translated, &size, NULL,

View file

@ -1700,6 +1700,19 @@ describe('default behavior', () => {
expect(webContents).to.equal(w.webContents); expect(webContents).to.equal(w.webContents);
}); });
}); });
describe('running under ARM64 translation', () => {
it('does not throw an error', () => {
if (process.platform === 'darwin' || process.platform === 'win32') {
expect(app.runningUnderARM64Translation).not.to.be.undefined();
expect(() => {
return app.runningUnderARM64Translation;
}).not.to.throw();
} else {
expect(app.runningUnderARM64Translation).to.be.undefined();
}
});
});
}); });
async function runTestApp (name: string, ...args: any[]) { async function runTestApp (name: string, ...args: any[]) {