Merge pull request #42 from wynwxst/main

In-LiveContainer Support + Extended Error Handling
This commit is contained in:
Stephen 2025-03-30 23:34:21 -04:00 • committed by GitHub
commit 15907e9870
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 80 additions and 24 deletions

View file

@ -16,6 +16,8 @@ struct HeartbeatApp: App {
@State private var isPairing = false
@State private var heartBeat = false
@State private var error: Int32? = nil
@State private var show_error = false
@State private var error_string = ""
@StateObject private var mount = MountingProgress.shared
let urls: [String] = [
@ -23,7 +25,7 @@ struct HeartbeatApp: App {
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg",
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg.trustcache"
]
let outputDir: String = "DDI"
let outputFiles: [String] = [
@ -126,11 +128,23 @@ struct HeartbeatApp: App {
for (index, urlString) in urls.enumerated() {
let destinationURL = URL.documentsDirectory.appendingPathComponent(outputFiles[index])
if !fileManager.fileExists(atPath: destinationURL.path) {
downloadFile(from: urlString, to: destinationURL)
downloadFile(from: urlString, to: destinationURL){ result in
if (result != ""){
error_string = "[Download DDI Error]: " + result
show_error = true
}
}
}
}
}
.alert("An Error Occurred", isPresented: $show_error) {
Button("OK", role: .cancel) { }
} message: {
Text(error_string)
}
}
}
}
@ -439,19 +453,21 @@ public func showAlert(title: String, message: String, showOk: Bool, showTryAgain
}
}
func downloadFile(from urlString: String, to destinationURL: URL) {
func downloadFile(from urlString: String, to destinationURL: URL,completion: @escaping (String) -> Void){
let fileManager = FileManager.default
let documentsDirectory = URL.documentsDirectory
guard let url = URL(string: urlString) else {
print("Invalid URL: \(urlString)")
completion("[Internal Invalid URL error]")
return
}
let task = URLSession.shared.downloadTask(with: url) { (tempLocalUrl, response, error) in
guard let tempLocalUrl = tempLocalUrl, error == nil else {
print("Error downloading file from \(urlString): \(String(describing: error))")
completion("Are you connected to the internet? [Download Failed]")
return
}
@ -460,10 +476,13 @@ func downloadFile(from urlString: String, to destinationURL: URL) {
try fileManager.createDirectory(at: destinationURL.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil)
try fileManager.moveItem(at: tempLocalUrl, to: destinationURL)
print("Downloaded \(urlString) to \(destinationURL.path)")
} catch {
print("Error saving file: \(error)")
}
}
task.resume()
completion("")
}

View file

@ -15,6 +15,7 @@ extension UIDocumentPickerViewController {
}
struct HomeView: View {
@Binding var is_lc: Bool
@AppStorage("username") private var username = "User"
@AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = Color.primaryBackground.toHex() ?? "#000000"
@AppStorage("autoQuitAfterEnablingJIT") private var doAutoQuitAfterEnablingJIT = false
@ -32,6 +33,10 @@ struct HomeView: View {
@State private var viewDidAppeared = false
@State private var pendingBundleIdToEnableJIT : String? = nil
init(is_lc: Binding<Bool>? = nil) {
self._is_lc = is_lc ?? .constant(false)
}
var body: some View {
ZStack {
@ -265,7 +270,9 @@ struct HomeView: View {
LogManager.shared.addInfoLog("Starting JIT for \(bundleID)")
DispatchQueue.global(qos: .background).async {
let success = JITEnableContext.shared.debugApp(withBundleID: bundleID, logger: { message in
let success = JITEnableContext.shared.debugApp(withBundleID: bundleID,isLC: is_lc, logger: { message in
if let message = message {
// Log messages from the JIT process
LogManager.shared.addInfoLog(message)

View file

@ -19,6 +19,7 @@ struct SettingsView: View {
@State private var pairingFileIsValid = false
@State private var isImportingFile = false
@State private var importProgress: Float = 0.0
@State private var is_lc = false
@StateObject private var mountProg = MountingProgress.shared
@ -33,7 +34,8 @@ struct SettingsView: View {
"Stossy11": "https://github.com/Stossy11.png",
"Neo": "https://github.com/neoarz.png",
"Se2crid": "https://github.com/Se2crid.png",
"Huge_Black": "https://github.com/HugeBlack.png"
"Huge_Black": "https://github.com/HugeBlack.png",
"Wynwxst": "https://github.com/Wynwxst.png"
]
var body: some View {
@ -258,6 +260,21 @@ struct SettingsView: View {
self.mounted = isMounted()
}
}
SettingsCard {
VStack(alignment: .leading, spacing: 20) {
Text("Misclaneous Settings")
.font(.headline)
.foregroundColor(.primary)
.padding(.bottom, 4)
Toggle("Enable In-LiveContainer JIT", isOn: $is_lc)
.padding()
HomeView(is_lc: $is_lc)
}
.padding(.vertical, 20)
.padding(.horizontal, 16)
}
// About section
@ -342,6 +359,8 @@ struct SettingsView: View {
CollaboratorRow(name: "Se2crid", url: "https://github.com/Se2crid", imageUrl: developerProfiles["Se2crid"] ?? "")
CollaboratorRow(name: "HugeBlack", url: "https://github.com/HugeBlack", imageUrl: developerProfiles["HugeBlack"] ?? "")
CollaboratorRow(name: "Wynwxst", url: "https://github.com/Wynwxst", imageUrl: developerProfiles["Wynwxst"] ?? "")
}
}

View file

@ -16,7 +16,7 @@ typedef void (^LogFunc)(NSString *message);
@property (class, readonly)JITEnableContext* shared;
- (IdevicePairingFile*)getPairingFileWithError:(NSError**)error;
- (void)startHeartbeatWithCompletionHandler:(HeartbeatCompletionHandler)completionHandler logger:(LogFunc)logger;
- (BOOL)debugAppWithBundleID:(NSString*)bundleID logger:(LogFunc)logger;
- (BOOL)debugAppWithBundleID:(NSString*)bundleID isLC:(BOOL)isLC logger:(LogFunc)logger;
- (NSDictionary<NSString*, NSString*>*)getAppListWithError:(NSError**)error;
- (UIImage*)getAppIconWithBundleId:(NSString*)bundleId error:(NSError**)error;
@end

View file

@ -104,7 +104,9 @@ JITEnableContext* sharedJITContext = nil;
completionHandler(result,[NSString stringWithCString:message encoding:NSASCIIStringEncoding]);
}, [self createCLogger:logger]);
}
- (BOOL)debugAppWithBundleID:(NSString*)bundleID logger:(LogFunc)logger {
- (BOOL)debugAppWithBundleID:(NSString*)bundleID isLC:(BOOL)isLC logger:(LogFunc)logger {
if(!provider) {
if(logger) {
logger(@"Provider not initialized!");
@ -113,7 +115,10 @@ JITEnableContext* sharedJITContext = nil;
return NO;
}
return debug_app(provider, [bundleID UTF8String], [self createCLogger:logger]) == 0;
return debug_app(provider, [bundleID UTF8String], [self createCLogger:logger], (bool)(isLC)) == 0;
}

View file

@ -18,7 +18,7 @@
#include "jit.h"
int debug_app(TcpProviderHandle* tcp_provider, const char *bundle_id, LogFuncC logger) {
int debug_app(TcpProviderHandle* tcp_provider, const char *bundle_id, LogFuncC logger,bool isLC) {
// Initialize logger
idevice_init_logger(Debug, Disabled, NULL);
IdeviceErrorCode err = IdeviceSuccess;
@ -98,8 +98,10 @@ int debug_app(TcpProviderHandle* tcp_provider, const char *bundle_id, LogFuncC l
* Process Control - Launch App
*****************************************************************/
logger("=== Launching App ===");
uint64_t pid;
// Get the adapter back from the XPC device
AdapterHandle *pc_adapter = NULL;
err = xpc_device_adapter_into_inner(xpc_device, &pc_adapter);
if (err != IdeviceSuccess) {
@ -140,21 +142,25 @@ int debug_app(TcpProviderHandle* tcp_provider, const char *bundle_id, LogFuncC l
xpc_service_free(debug_service);
return 1;
}
// Launch application
uint64_t pid;
err = process_control_launch_app(process_control, bundle_id, NULL, 0, NULL, 0,
true, false, &pid);
if (err != IdeviceSuccess) {
logger("Failed to launch app: %d", err);
process_control_free(process_control);
remote_server_free(remote_server);
xpc_service_free(pc_service);
xpc_service_free(debug_service);
return 1;
if(!isLC){
// Launch application
err = process_control_launch_app(process_control, bundle_id, NULL, 0, NULL, 0,
true, false, &pid);
if (err != IdeviceSuccess) {
logger("Failed to launch app: %d", err);
process_control_free(process_control);
remote_server_free(remote_server);
xpc_service_free(pc_service);
xpc_service_free(debug_service);
return 1;
}
logger("Successfully launched app with PID: %" PRIu64 "", pid);
} else {
pid = getpid();
}
logger("Successfully launched app with PID: %" PRIu64 "", pid);
// Disable memory limit for PID
err = process_control_disable_memory_limit(process_control, pid);
if (err != IdeviceSuccess) {

View file

@ -11,6 +11,6 @@
#include "idevice.h"
typedef void (^LogFuncC)(const char* message, ...);
int debug_app(TcpProviderHandle* provider, const char *bundle_id, LogFuncC logger);
int debug_app(TcpProviderHandle* provider, const char *bundle_id, LogFuncC logger, bool isLC);
#endif /* JIT_H */