aboutsummaryrefslogtreecommitdiffstats
path: root/WireGuard/WireGuard
diff options
context:
space:
mode:
authorRoopesh Chander <roop@roopc.net>2019-04-17 13:35:43 +0530
committerRoopesh Chander <roop@roopc.net>2019-04-21 15:43:10 +0530
commit178fe86d367d3a936c1270c2fb8285bd9df8f9b6 (patch)
tree18372b35898c442c2a61accb43c974a0fdd6759c /WireGuard/WireGuard
parentVersion bump (diff)
downloadwireguard-apple-178fe86d367d3a936c1270c2fb8285bd9df8f9b6.tar.xz
wireguard-apple-178fe86d367d3a936c1270c2fb8285bd9df8f9b6.zip
macOS: Detect when updating from the App Store
And show an alert when tunnels are active during updation -- that might cause the update to not work correctly. Signed-off-by: Roopesh Chander <roop@roopc.net>
Diffstat (limited to 'WireGuard/WireGuard')
-rw-r--r--WireGuard/WireGuard/Base.lproj/Localizable.strings6
-rw-r--r--WireGuard/WireGuard/UI/macOS/AppDelegate.swift30
-rw-r--r--WireGuard/WireGuard/UI/macOS/MacAppStoreUpdateDetector.swift39
-rw-r--r--WireGuard/WireGuard/WireGuard-Bridging-Header.h5
4 files changed, 80 insertions, 0 deletions
diff --git a/WireGuard/WireGuard/Base.lproj/Localizable.strings b/WireGuard/WireGuard/Base.lproj/Localizable.strings
index 8600a63..9cfaef1 100644
--- a/WireGuard/WireGuard/Base.lproj/Localizable.strings
+++ b/WireGuard/WireGuard/Base.lproj/Localizable.strings
@@ -405,3 +405,9 @@
"macUnusableTunnelMessage" = "The configuration for this tunnel cannot be found in the keychain.";
"macUnusableTunnelInfo" = "In case this tunnel was created by another user, only that user can view, edit, or activate this tunnel.";
"macUnusableTunnelButtonTitleDeleteTunnel" = "Delete tunnel";
+
+// Mac App Store updating alert
+
+"macAppStoreUpdatingAlertMessage" = "App Store would like to update WireGuard";
+"macAppStoreUpdatingAlertInfoWithOnDemand (%@)" = "Please disable on-demand for tunnel ‘%@’, deactivate it, and then continue updating in App Store.";
+"macAppStoreUpdatingAlertInfoWithoutOnDemand (%@)" = "Please deactivate tunnel ‘%@’ and then continue updating in App Store.";
diff --git a/WireGuard/WireGuard/UI/macOS/AppDelegate.swift b/WireGuard/WireGuard/UI/macOS/AppDelegate.swift
index e80d971..3e98c20 100644
--- a/WireGuard/WireGuard/UI/macOS/AppDelegate.swift
+++ b/WireGuard/WireGuard/UI/macOS/AppDelegate.swift
@@ -68,6 +68,36 @@ class AppDelegate: NSObject, NSApplicationDelegate {
NSApp.terminate(nil)
}
}
+
+ func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
+ if UserDefaults.standard.bool(forKey: "shouldSuppressAppStoreUpdateDetection") {
+ wg_log(.debug, staticMessage: "App Store update detection is suppressed")
+ return .terminateNow
+ }
+ guard let currentTunnel = tunnelsTracker?.currentTunnel, currentTunnel.status == .active || currentTunnel.status == .activating else {
+ return .terminateNow
+ }
+ guard let appleEvent = NSAppleEventManager.shared().currentAppleEvent else {
+ return .terminateNow
+ }
+ guard MacAppStoreUpdateDetector.isUpdatingFromMacAppStore(quitAppleEvent: appleEvent) else {
+ return .terminateNow
+ }
+ let alert = NSAlert()
+ alert.messageText = tr("macAppStoreUpdatingAlertMessage")
+ if currentTunnel.isActivateOnDemandEnabled {
+ alert.informativeText = tr(format: "macAppStoreUpdatingAlertInfoWithOnDemand (%@)", currentTunnel.name)
+ } else {
+ alert.informativeText = tr(format: "macAppStoreUpdatingAlertInfoWithoutOnDemand (%@)", currentTunnel.name)
+ }
+ NSApp.activate(ignoringOtherApps: true)
+ if let manageWindow = manageTunnelsWindowObject {
+ alert.beginSheetModal(for: manageWindow) { _ in }
+ } else {
+ alert.runModal()
+ }
+ return .terminateCancel
+ }
}
extension AppDelegate: StatusMenuWindowDelegate {
diff --git a/WireGuard/WireGuard/UI/macOS/MacAppStoreUpdateDetector.swift b/WireGuard/WireGuard/UI/macOS/MacAppStoreUpdateDetector.swift
new file mode 100644
index 0000000..7fbb011
--- /dev/null
+++ b/WireGuard/WireGuard/UI/macOS/MacAppStoreUpdateDetector.swift
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: MIT
+// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
+
+import Cocoa
+
+class MacAppStoreUpdateDetector {
+ static func isUpdatingFromMacAppStore(quitAppleEvent: NSAppleEventDescriptor) -> Bool {
+ guard isQuitEvent(quitAppleEvent) else { return false }
+ guard let senderPIDDescriptor = quitAppleEvent.attributeDescriptor(forKeyword: keySenderPIDAttr) else { return false }
+ let pid = senderPIDDescriptor.int32Value
+ guard let executablePath = getExecutablePath(from: pid) else { return false }
+ wg_log(.debug, message: "aevt/quit Apple event received from: \(executablePath)")
+ if executablePath.hasPrefix("/System/Library/") {
+ let executableName = URL(fileURLWithPath: executablePath, isDirectory: false).lastPathComponent
+ return executableName == "com.apple.CommerceKit.StoreAEService"
+ }
+ return false
+ }
+}
+
+private func isQuitEvent(_ event: NSAppleEventDescriptor) -> Bool {
+ if let eventClassDescriptor = event.attributeDescriptor(forKeyword: keyEventClassAttr),
+ let eventIdDescriptor = event.attributeDescriptor(forKeyword: keyEventIDAttr) {
+ return eventClassDescriptor.typeCodeValue == kCoreEventClass && eventIdDescriptor.typeCodeValue == kAEQuitApplication
+ }
+ return false
+}
+
+private func getExecutablePath(from pid: pid_t) -> String? {
+ let bufferSize = Int(PATH_MAX)
+ var buffer = Data(capacity: bufferSize)
+ return buffer.withUnsafeMutableBytes { (ptr: UnsafeMutableRawBufferPointer) -> String? in
+ if let basePtr = ptr.baseAddress {
+ let byteCount = proc_pidpath(pid, basePtr, UInt32(bufferSize))
+ return byteCount > 0 ? String(cString: basePtr.bindMemory(to: CChar.self, capacity: bufferSize)) : nil
+ }
+ return nil
+ }
+}
diff --git a/WireGuard/WireGuard/WireGuard-Bridging-Header.h b/WireGuard/WireGuard/WireGuard-Bridging-Header.h
index 210b3df..81766ab 100644
--- a/WireGuard/WireGuard/WireGuard-Bridging-Header.h
+++ b/WireGuard/WireGuard/WireGuard-Bridging-Header.h
@@ -5,3 +5,8 @@
#include "ringlogger.h"
#include "highlighter.h"
#include "key.h"
+
+#import "TargetConditionals.h"
+#if TARGET_OS_OSX
+#include <libproc.h>
+#endif