Browse Source

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
Sergio Padrino 3 years ago
parent
commit
abf6f5c8ba

+ 16 - 1
docs/api/app.md

@@ -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
 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
 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
 your application when they are running the x64 version under Rosetta
 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.

+ 25 - 0
shell/browser/api/electron_api_app.cc

@@ -1440,6 +1440,27 @@ void App::SetUserAgentFallback(const std::string& 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() {
   return ElectronBrowserClient::Get()->GetUserAgent();
 }
@@ -1642,6 +1663,10 @@ gin::ObjectTemplateBuilder App::GetObjectTemplateBuilder(v8::Isolate* isolate) {
       .SetProperty("dock", &App::GetDockAPI)
       .SetProperty("runningUnderRosettaTranslation",
                    &App::IsRunningUnderRosettaTranslation)
+#endif
+#if defined(OS_MAC) || defined(OS_WIN)
+      .SetProperty("runningUnderARM64Translation",
+                   &App::IsRunningUnderARM64Translation)
 #endif
       .SetProperty("userAgentFallback", &App::GetUserAgentFallback,
                    &App::SetUserAgentFallback)

+ 4 - 0
shell/browser/api/electron_api_app.h

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

+ 11 - 0
shell/browser/api/electron_api_app_mac.mm

@@ -60,6 +60,17 @@ void App::SetActivationPolicy(gin_helper::ErrorThrower thrower,
 }
 
 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;
   size_t size = sizeof(proc_translated);
   if (sysctlbyname("sysctl.proc_translated", &proc_translated, &size, NULL,

+ 13 - 0
spec-main/api-app-spec.ts

@@ -1700,6 +1700,19 @@ describe('default behavior', () => {
       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[]) {