mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
[AltServer] Adds “Enable JIT” menu option
Allows user to enable JIT execution for any sideloaded app by starting (and immediately stopping) a debug session on device.
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
#import "ALTDeviceManager.h"
|
#import "ALTDeviceManager.h"
|
||||||
#import "ALTWiredConnection.h"
|
#import "ALTWiredConnection.h"
|
||||||
#import "ALTNotificationConnection.h"
|
#import "ALTNotificationConnection.h"
|
||||||
|
#import "ALTDebugConnection.h"
|
||||||
|
|
||||||
// Shared
|
// Shared
|
||||||
#import "ALTConstants.h"
|
#import "ALTConstants.h"
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
@IBOutlet private var appMenu: NSMenu!
|
@IBOutlet private var appMenu: NSMenu!
|
||||||
@IBOutlet private var connectedDevicesMenu: NSMenu!
|
@IBOutlet private var connectedDevicesMenu: NSMenu!
|
||||||
@IBOutlet private var sideloadIPAConnectedDevicesMenu: NSMenu!
|
@IBOutlet private var sideloadIPAConnectedDevicesMenu: NSMenu!
|
||||||
|
@IBOutlet private var enableJITMenu: NSMenu!
|
||||||
|
|
||||||
@IBOutlet private var launchAtLoginMenuItem: NSMenuItem!
|
@IBOutlet private var launchAtLoginMenuItem: NSMenuItem!
|
||||||
@IBOutlet private var installMailPluginMenuItem: NSMenuItem!
|
@IBOutlet private var installMailPluginMenuItem: NSMenuItem!
|
||||||
|
|
||||||
@@ -45,6 +47,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
|
|
||||||
private var connectedDevicesMenuController: MenuController<ALTDevice>!
|
private var connectedDevicesMenuController: MenuController<ALTDevice>!
|
||||||
private var sideloadIPAConnectedDevicesMenuController: MenuController<ALTDevice>!
|
private var sideloadIPAConnectedDevicesMenuController: MenuController<ALTDevice>!
|
||||||
|
private var enableJITMenuController: MenuController<ALTDevice>!
|
||||||
|
|
||||||
|
private var _jitAppListMenuControllers = [AnyObject]()
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ aNotification: Notification)
|
func applicationDidFinishLaunching(_ aNotification: Notification)
|
||||||
{
|
{
|
||||||
@@ -76,6 +81,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
self?.sideloadIPA(to: device)
|
self?.sideloadIPA(to: device)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.enableJITMenuController = MenuController<ALTDevice>(menu: self.enableJITMenu, items: [])
|
||||||
|
self.enableJITMenuController.placeholder = placeholder
|
||||||
|
|
||||||
UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) { (success, error) in
|
UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) { (success, error) in
|
||||||
guard success else { return }
|
guard success else { return }
|
||||||
|
|
||||||
@@ -123,6 +131,47 @@ private extension AppDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func enableJIT(for app: InstalledApp, on device: ALTDevice)
|
||||||
|
{
|
||||||
|
func finish(_ result: Result<Void, Error>)
|
||||||
|
{
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
switch result
|
||||||
|
{
|
||||||
|
case .failure(let error):
|
||||||
|
self.showErrorAlert(title: String(format: NSLocalizedString("JIT compilation could not be enabled for %@.", comment: ""), app.name), error: error)
|
||||||
|
|
||||||
|
case .success:
|
||||||
|
let alert = NSAlert()
|
||||||
|
alert.messageText = String(format: NSLocalizedString("Successfully enabled JIT for %@.", comment: ""), app.name)
|
||||||
|
alert.informativeText = String(format: NSLocalizedString("JIT will remain enabled until you quit the app. You can now disconnect %@ from your computer.", comment: ""), device.name)
|
||||||
|
alert.runModal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ALTDeviceManager.shared.prepare(device) { (result) in
|
||||||
|
switch result
|
||||||
|
{
|
||||||
|
case .failure(let error as NSError): return finish(.failure(error))
|
||||||
|
case .success:
|
||||||
|
ALTDeviceManager.shared.startDebugConnection(to: device) { (connection, error) in
|
||||||
|
guard let connection = connection else {
|
||||||
|
return finish(.failure(error! as NSError))
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.enableUnsignedCodeExecutionForProcess(withName: app.executableName) { (success, error) in
|
||||||
|
guard success else {
|
||||||
|
return finish(.failure(error!))
|
||||||
|
}
|
||||||
|
|
||||||
|
finish(.success(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func installApplication(at url: URL, to device: ALTDevice)
|
func installApplication(at url: URL, to device: ALTDevice)
|
||||||
{
|
{
|
||||||
let alert = NSAlert()
|
let alert = NSAlert()
|
||||||
@@ -311,11 +360,15 @@ extension AppDelegate: NSMenuDelegate
|
|||||||
func menuWillOpen(_ menu: NSMenu)
|
func menuWillOpen(_ menu: NSMenu)
|
||||||
{
|
{
|
||||||
guard menu == self.appMenu else { return }
|
guard menu == self.appMenu else { return }
|
||||||
|
|
||||||
|
// Clear any cached _jitAppListMenuControllers.
|
||||||
|
self._jitAppListMenuControllers.removeAll()
|
||||||
|
|
||||||
self.connectedDevices = ALTDeviceManager.shared.availableDevices
|
self.connectedDevices = ALTDeviceManager.shared.availableDevices
|
||||||
|
|
||||||
self.connectedDevicesMenuController.items = self.connectedDevices
|
self.connectedDevicesMenuController.items = self.connectedDevices
|
||||||
self.sideloadIPAConnectedDevicesMenuController.items = self.connectedDevices
|
self.sideloadIPAConnectedDevicesMenuController.items = self.connectedDevices
|
||||||
|
self.enableJITMenuController.items = self.connectedDevices
|
||||||
|
|
||||||
self.launchAtLoginMenuItem.target = self
|
self.launchAtLoginMenuItem.target = self
|
||||||
self.launchAtLoginMenuItem.action = #selector(AppDelegate.toggleLaunchAtLogin(_:))
|
self.launchAtLoginMenuItem.action = #selector(AppDelegate.toggleLaunchAtLogin(_:))
|
||||||
@@ -335,6 +388,60 @@ extension AppDelegate: NSMenuDelegate
|
|||||||
}
|
}
|
||||||
self.installMailPluginMenuItem.target = self
|
self.installMailPluginMenuItem.target = self
|
||||||
self.installMailPluginMenuItem.action = #selector(AppDelegate.handleInstallMailPluginMenuItem(_:))
|
self.installMailPluginMenuItem.action = #selector(AppDelegate.handleInstallMailPluginMenuItem(_:))
|
||||||
|
|
||||||
|
// Need to re-set this every time menu appears so we can refresh device app list.
|
||||||
|
self.enableJITMenuController.submenuHandler = { [weak self] device in
|
||||||
|
let submenu = NSMenu(title: NSLocalizedString("Sideloaded Apps", comment: ""))
|
||||||
|
|
||||||
|
guard let `self` = self else { return submenu }
|
||||||
|
|
||||||
|
let submenuController = MenuController<InstalledApp>(menu: submenu, items: [])
|
||||||
|
submenuController.placeholder = NSLocalizedString("Loading...", comment: "")
|
||||||
|
submenuController.action = { [weak self] (appInfo) in
|
||||||
|
self?.enableJIT(for: appInfo, on: device)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep strong reference
|
||||||
|
self._jitAppListMenuControllers.append(submenuController)
|
||||||
|
|
||||||
|
ALTDeviceManager.shared.fetchInstalledApps(on: device) { (installedApps, error) in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
guard let installedApps = installedApps else {
|
||||||
|
print("Failed to fetch installed apps from \(device).", error!)
|
||||||
|
submenuController.placeholder = error?.localizedDescription
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Fetched \(installedApps.count) apps for \(device).")
|
||||||
|
|
||||||
|
let sortedApps = installedApps.sorted { (app1, app2) in
|
||||||
|
if app1.name == app2.name
|
||||||
|
{
|
||||||
|
return app1.bundleIdentifier < app2.bundleIdentifier
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return app1.name < app2.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submenuController.items = sortedApps
|
||||||
|
|
||||||
|
if submenuController.items.isEmpty
|
||||||
|
{
|
||||||
|
submenuController.placeholder = NSLocalizedString("No Sideloaded Apps", comment: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return submenu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func menuDidClose(_ menu: NSMenu)
|
||||||
|
{
|
||||||
|
// Clearing _jitAppListMenuControllers now prevents action handler from being called.
|
||||||
|
// self._jitAppListMenuControllers = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="17503.1" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17503.1"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
@@ -62,6 +62,7 @@
|
|||||||
<outlet property="authenticationAppleIDTextField" destination="zLd-d8-ghZ" id="wW5-0J-zdq"/>
|
<outlet property="authenticationAppleIDTextField" destination="zLd-d8-ghZ" id="wW5-0J-zdq"/>
|
||||||
<outlet property="authenticationPasswordTextField" destination="9rp-Vx-rvB" id="ZoC-DI-jzQ"/>
|
<outlet property="authenticationPasswordTextField" destination="9rp-Vx-rvB" id="ZoC-DI-jzQ"/>
|
||||||
<outlet property="connectedDevicesMenu" destination="KJ9-WY-pW1" id="Mcv-64-iFU"/>
|
<outlet property="connectedDevicesMenu" destination="KJ9-WY-pW1" id="Mcv-64-iFU"/>
|
||||||
|
<outlet property="enableJITMenu" destination="la4-Sa-L3C" id="YrW-hR-uA7"/>
|
||||||
<outlet property="installMailPluginMenuItem" destination="3CM-gV-X2G" id="lio-ha-z0S"/>
|
<outlet property="installMailPluginMenuItem" destination="3CM-gV-X2G" id="lio-ha-z0S"/>
|
||||||
<outlet property="launchAtLoginMenuItem" destination="IyR-FQ-upe" id="Fxn-EP-hwH"/>
|
<outlet property="launchAtLoginMenuItem" destination="IyR-FQ-upe" id="Fxn-EP-hwH"/>
|
||||||
<outlet property="sideloadIPAConnectedDevicesMenu" destination="IuI-bV-fTY" id="QQw-St-HfG"/>
|
<outlet property="sideloadIPAConnectedDevicesMenu" destination="IuI-bV-fTY" id="QQw-St-HfG"/>
|
||||||
@@ -108,6 +109,16 @@
|
|||||||
</items>
|
</items>
|
||||||
</menu>
|
</menu>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
|
<menuItem title="Enable JIT" id="TvL-8M-oPZ">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<menu key="submenu" title="Enable JIT" systemMenu="recentDocuments" id="la4-Sa-L3C">
|
||||||
|
<items>
|
||||||
|
<menuItem title="No Connected Devices" id="Aya-FP-EzE">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
</menuItem>
|
||||||
|
</items>
|
||||||
|
</menu>
|
||||||
|
</menuItem>
|
||||||
<menuItem isSeparatorItem="YES" id="1ZZ-BB-xHy"/>
|
<menuItem isSeparatorItem="YES" id="1ZZ-BB-xHy"/>
|
||||||
<menuItem title="Launch at Login" id="IyR-FQ-upe" userLabel="Launch At Login">
|
<menuItem title="Launch at Login" id="IyR-FQ-upe" userLabel="Launch At Login">
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user