clean-checkpoint-2-restore-missing

This commit is contained in:
Magesh K
2024-12-08 02:50:40 +05:30
parent 63a3203e50
commit a7b31ec7a2
22 changed files with 114 additions and 644 deletions

View File

@@ -77,9 +77,9 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
UserDefaults.standard.preferredServerID = Bundle.main.object(forInfoDictionaryKey: Bundle.Info.serverID) as? String
#if DEBUG || BETA
// #if DEBUG || BETA
UserDefaults.standard.isDebugModeEnabled = true
#endif
// #endif
self.prepareForBackgroundFetch()

View File

@@ -304,10 +304,13 @@ extension AppManager
func log(_ error: Error, operation: LoggedError.Operation, app: AppProtocol)
{
switch error {
case ~OperationError.Code.cancelled: return // Don't log cancelled events
default: break
switch error
{
case is CancellationError: return // Don't log CancellationErrors
case let nsError as NSError where nsError.domain == CancellationError()._domain: return
default: break
}
// Sanitize NSError on same thread before performing background task.
let sanitizedError = (error as NSError).sanitizedForSerialization()
@@ -903,6 +906,7 @@ extension AppManager
var installedApp: InstalledApp?
}
let appName = installedApp.name
let context = Context()
context.installedApp = installedApp
@@ -915,12 +919,11 @@ extension AppManager
let localizedTitle = String(format: NSLocalizedString("Failed to Enable JIT for %@", comment: ""), appName)
let error = nsError.withLocalizedTitle(localizedTitle)
self.log(error, operation: .enableJIT, app: installedApp)
// self.log(error, operation: .enableJIT, app: installedApp)
completionHandler(.failure(error))
}
}
enableJITOperation.addDependency(findServerOperation)
self.run([enableJITOperation], context: context, requiresSerialQueue: true)
}
@@ -1061,7 +1064,8 @@ private extension AppManager
}
var loggedErrorOperation: LoggedError.Operation {
switch self {
switch self
{
case .install: return .install
case .update: return .update
case .refresh: return .refresh
@@ -1351,7 +1355,14 @@ private extension AppManager
}
}
private func _install(_ app: AppProtocol, operation appOperation: AppOperation, group: RefreshGroup, context: InstallAppOperationContext? = nil, additionalEntitlements: [ALTEntitlement: Any] = [.increasedDebuggingMemoryLimit: ALTEntitlement.increasedDebuggingMemoryLimit, .increasedMemoryLimit: ALTEntitlement.increasedMemoryLimit, .extendedVirtualAddressing: ALTEntitlement.extendedVirtualAddressing], cacheApp: Bool = true, completionHandler: @escaping (Result<InstalledApp, Error>) -> Void) -> Progress
private func _install(_ app: AppProtocol,
operation appOperation: AppOperation,
group: RefreshGroup,
context: InstallAppOperationContext? = nil,
additionalEntitlements: [ALTEntitlement: Any]? = [.increasedDebuggingMemoryLimit: ALTEntitlement.increasedDebuggingMemoryLimit, .increasedMemoryLimit: ALTEntitlement.increasedMemoryLimit, .extendedVirtualAddressing: ALTEntitlement.extendedVirtualAddressing],
reviewPermissions permissionReviewMode: VerifyAppOperation.PermissionReviewMode = .none,
cacheApp: Bool = true,
completionHandler: @escaping (Result<InstalledApp, Error>) -> Void) -> Progress
{
let progress = Progress.discreteProgress(totalUnitCount: 100)
@@ -1490,8 +1501,8 @@ private extension AppManager
}
removeAppExtensionsOperation.addDependency(verifyOperation)
/* Refresh Anisette Data */
let refreshAnisetteDataOperation = FetchAnisetteDataOperation(context: group.context)
refreshAnisetteDataOperation.resultHandler = { (result) in
@@ -1511,7 +1522,7 @@ private extension AppManager
switch result
{
case .failure(let error): context.error = error
case .success(let provisioningProfiles):
case .success(let provisioningProfiles):
context.provisioningProfiles = provisioningProfiles
print("PROVISIONING PROFILES \(context.provisioningProfiles)")
}
@@ -1642,7 +1653,7 @@ private extension AppManager
}
patchAppOperation.addDependency(deactivateAppsOperation)
/* Resign */
let resignAppOperation = ResignAppOperation(context: context)
resignAppOperation.resultHandler = { (result) in
@@ -1752,8 +1763,7 @@ private extension AppManager
}
progress.addChild(fetchProvisioningProfilesOperation.progress, withPendingUnitCount: 60)
fetchProvisioningProfilesOperation.addDependency(validateAppExtensionsOperation)
/* Refresh */
let refreshAppOperation = RefreshAppOperation(context: context)
refreshAppOperation.resultHandler = { (result) in
@@ -2055,7 +2065,7 @@ private extension AppManager
let temporaryDirectoryURL = context.temporaryDirectory.appendingPathComponent("AltBackup-" + UUID().uuidString)
try FileManager.default.createDirectory(at: temporaryDirectoryURL, withIntermediateDirectories: true, attributes: nil)
guard let altbackupFileURL = Bundle.main.url(forResource: "AltBackup", withExtension: "ipa") else { throw OperationError.appNotFound(name: app.name) }
guard let altbackupFileURL = Bundle.main.url(forResource: "AltBackup", withExtension: "ipa") else { throw OperationError.appNotFound(name: "AltBackup") }
let unzippedAppBundleURL = try FileManager.default.unzipAppBundle(at: altbackupFileURL, toDirectory: temporaryDirectoryURL)
guard let unzippedAppBundle = Bundle(url: unzippedAppBundleURL) else { throw OperationError.invalidApp }
@@ -2201,20 +2211,27 @@ private extension AppManager
catch let nsError as NSError
{
var appName: String!
if let app = operation.app as? (NSManagedObject & AppProtocol) {
if let context = app.managedObjectContext {
if let app = operation.app as? (NSManagedObject & AppProtocol)
{
if let context = app.managedObjectContext
{
context.performAndWait {
appName = app.name
}
} else {
}
else
{
appName = NSLocalizedString("Unknown App", comment: "")
}
} else {
}
else
{
appName = operation.app.name
}
let localizedTitle: String
switch operation {
switch operation
{
case .install: localizedTitle = String(format: NSLocalizedString("Failed to Install %@", comment: ""), appName)
case .refresh: localizedTitle = String(format: NSLocalizedString("Failed to Refresh %@", comment: ""), appName)
case .update: localizedTitle = String(format: NSLocalizedString("Failed to Update %@", comment: ""), appName)
@@ -2250,51 +2267,7 @@ private extension AppManager
let request = UNNotificationRequest(identifier: AppManager.expirationWarningNotificationID, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
func log(_ error: Error, operation: LoggedError.Operation, app: AppProtocol)
{
switch error
{
case is CancellationError: return // Don't log CancellationErrors
case let nsError as NSError where nsError.domain == CancellationError()._domain: return
default: break
}
// Sanitize NSError on same thread before performing background task.
let sanitizedError = (error as NSError).sanitizedForSerialization()
let loggedErrorOperation: LoggedError.Operation = {
switch operation
{
case .install: return .install
case .update: return .update
case .refresh: return .refresh
case .activate: return .activate
case .deactivate: return .deactivate
case .backup: return .backup
case .restore: return .restore
}
}()
DatabaseManager.shared.persistentContainer.performBackgroundTask { context in
var app = app
if let managedApp = app as? NSManagedObject, let tempApp = context.object(with: managedApp.objectID) as? AppProtocol
{
app = tempApp
}
do
{
_ = LoggedError(error: sanitizedError, app: app, operation: operation, context: context)
try context.save()
}
catch let saveError
{
print("[ALTLog] Failed to log error \(sanitizedError.domain) code \(sanitizedError.code) for \(app.bundleIdentifier):", saveError)
}
}
}
func run(_ operations: [Foundation.Operation], context: OperationContext?, requiresSerialQueue: Bool = false)
{
// Find "Install AltStore" operation if it already exists in `context`

View File

@@ -19,7 +19,7 @@ extension OperationError
// General
case unknown = 1000
case unknownResult = 1001
case cancelled = 1002
// case cancelled = 1002
case timedOut = 1003
case notAuthenticated = 1004
case appNotFound = 1005
@@ -200,7 +200,6 @@ struct OperationError: ALTLocalizedError {
case .maximumAppIDLimitReached: return NSLocalizedString("Cannot register more than 10 App IDs within a 7 day period.", comment: "")
case .noSources: return NSLocalizedString("There are no SideStore sources.", comment: "")
case .missingAppGroup: return NSLocalizedString("SideStore's shared app group could not be accessed.", comment: "")
case .invalidParameters: return NSLocalizedString("Invalid parameters.", comment: "")
case .forbidden:
guard let failureReason = self._failureReason else { return NSLocalizedString("The operation is forbidden.", comment: "") }
return failureReason

View File

@@ -133,7 +133,7 @@ private extension VerifyAppOperation
func verifyPermissions(of app: ALTApplication, @AsyncManaged match appVersion: AppVersion) async throws
{
guard self.permissionsMode != .none else { return }
guard let storeApp = await $appVersion.app else { throw OperationError.invalidParameters }
guard let storeApp = await $appVersion.app else { throw OperationError.invalidParameters("verifyPermissions requires storeApp to be non-nil") }
// Verify source permissions match first.
let allPermissions = try await self.verifyPermissions(of: app, match: storeApp)

View File

@@ -348,26 +348,26 @@ private extension SourcesViewController
{
func handleAddSourceDeepLink()
{
let alertController = UIAlertController(title: NSLocalizedString("Add Source", comment: ""), message: nil, preferredStyle: .alert)
alertController.addTextField { (textField) in
textField.placeholder = "https://apps.sidestore.io"
textField.textContentType = .URL
}
alertController.addAction(.cancel)
alertController.addAction(UIAlertAction(title: NSLocalizedString("Add", comment: ""), style: .default) { (action) in
guard let text = alertController.textFields![0].text else { return }
guard var sourceURL = URL(string: text) else { return }
if sourceURL.scheme == nil {
guard let httpsSourceURL = URL(string: "https://" + text) else { return }
sourceURL = httpsSourceURL
}
self.navigationItem.leftBarButtonItem?.isIndicatingActivity = true
self.addSource(url: sourceURL) { _ in
self.navigationItem.leftBarButtonItem?.isIndicatingActivity = false
}
})
// let alertController = UIAlertController(title: NSLocalizedString("Add Source", comment: ""), message: nil, preferredStyle: .alert)
// alertController.addTextField { (textField) in
// textField.placeholder = "https://apps.sidestore.io"
// textField.textContentType = .URL
// }
// alertController.addAction(.cancel)
// alertController.addAction(UIAlertAction(title: NSLocalizedString("Add", comment: ""), style: .default) { (action) in
// guard let text = alertController.textFields![0].text else { return }
// guard var sourceURL = URL(string: text) else { return }
// if sourceURL.scheme == nil {
// guard let httpsSourceURL = URL(string: "https://" + text) else { return }
// sourceURL = httpsSourceURL
// }
//
// self.navigationItem.leftBarButtonItem?.isIndicatingActivity = true
//
// self.addSource(url: sourceURL) { _ in
// self.navigationItem.leftBarButtonItem?.isIndicatingActivity = false
// }
// })
guard let url = self.deepLinkSourceURL, self.view.window != nil else { return }
// Only handle deep link once.
@@ -453,39 +453,39 @@ private extension SourcesViewController
{
completionHandler?(false)
let dispatchGroup = DispatchGroup()
var sourcesByURL = [URL: Source]()
var fetchError: Error?
for sourceURL in featuredSourceURLs
{
dispatchGroup.enter()
AppManager.shared.fetchSource(sourceURL: sourceURL, managedObjectContext: context) { result in
// Serialize access to sourcesByURL.
context.performAndWait {
switch result
{
case .failure(let error): fetchError = error
case .success(let source): sourcesByURL[source.sourceURL] = source
}
dispatchGroup.leave()
}
}
}
dispatchGroup.notify(queue: .main) {
if let error = fetchError
{
print(error)
// 1 error doesn't mean all trusted sources failed to load! Riley, why did you do this???????
// finish(.failure(error))
}
let sources = featuredSourceURLs.compactMap { sourcesByURL[$0] }
finish(.success(sources))
}
// let dispatchGroup = DispatchGroup()
//
// var sourcesByURL = [URL: Source]()
// var fetchError: Error?
//
// for sourceURL in featuredSourceURLs
// {
// dispatchGroup.enter()
//
// AppManager.shared.fetchSource(sourceURL: sourceURL, managedObjectContext: context) { result in
// // Serialize access to sourcesByURL.
// context.performAndWait {
// switch result
// {
// case .failure(let error): fetchError = error
// case .success(let source): sourcesByURL[source.sourceURL] = source
// }
//
// dispatchGroup.leave()
// }
// }
// }
//
// dispatchGroup.notify(queue: .main) {
// if let error = fetchError
// {
// print(error)
// // 1 error doesn't mean all trusted sources failed to load! Riley, why did you do this???????
//// finish(.failure(error))
// }
// let sources = featuredSourceURLs.compactMap { sourcesByURL[$0] }
// finish(.success(sources))
// }
self.present(error)
}
}