Uses UTIs to determine whether apps are installed or not

AltStore now inserts an app-specific UTI when resigning apps, and it periodically checks whether that app has been deleted by checking whether UTTypeCopyDeclaration returns nil for the same app-specific UTI.
This commit is contained in:
Riley Testut
2019-12-17 19:17:45 -08:00
parent 748ad8588d
commit e3ea200ad5
4 changed files with 28 additions and 2 deletions

View File

@@ -18,6 +18,7 @@ public extension Bundle
public static let appGroups = "ALTAppGroups"
public static let urlTypes = "CFBundleURLTypes"
public static let exportedUTIs = "UTExportedTypeDeclarations"
}
}

View File

@@ -9,6 +9,7 @@
import Foundation
import UIKit
import UserNotifications
import MobileCoreServices
import AltSign
import AltKit
@@ -55,16 +56,19 @@ extension AppManager
do
{
let installedApps = try context.fetch(fetchRequest)
for app in installedApps where app.storeApp != nil
for app in installedApps
{
let uti = UTTypeCopyDeclaration(app.installedAppUTI as CFString)?.takeRetainedValue() as NSDictionary?
if app.bundleIdentifier == StoreApp.altstoreAppID
{
self.scheduleExpirationWarningLocalNotification(for: app)
}
else
{
if !UIApplication.shared.canOpenURL(app.openAppURL)
if uti == nil
{
// This UTI is not declared by any apps, which means this app has been deleted by the user.
context.delete(app)
}
}

View File

@@ -187,6 +187,12 @@ extension InstalledApp
return directoryURL
}
class func installedAppUTI(forBundleIdentifier bundleIdentifier: String) -> String
{
let installedAppUTI = "io.altstore.Installed." + bundleIdentifier
return installedAppUTI
}
var directoryURL: URL {
return InstalledApp.directoryURL(for: self)
}
@@ -198,4 +204,8 @@ extension InstalledApp
var refreshedIPAURL: URL {
return InstalledApp.refreshedIPAURL(for: self)
}
var installedAppUTI: String {
return InstalledApp.installedAppUTI(forBundleIdentifier: self.resignedBundleIdentifier)
}
}

View File

@@ -372,6 +372,17 @@ private extension ResignAppOperation
infoDictionary[Bundle.Info.appGroups] = appGroups
}
// Add app-specific exported UTI so we can check later if this app (extension) is installed or not.
let installedAppUTI = ["UTTypeConformsTo": [],
"UTTypeDescription": "AltStore Installed App",
"UTTypeIconFiles": [],
"UTTypeIdentifier": InstalledApp.installedAppUTI(forBundleIdentifier: profile.bundleIdentifier),
"UTTypeTagSpecification": [:]] as [String : Any]
var exportedUTIs = infoDictionary[Bundle.Info.exportedUTIs] as? [[String: Any]] ?? []
exportedUTIs.append(installedAppUTI)
infoDictionary[Bundle.Info.exportedUTIs] = exportedUTIs
try (infoDictionary as NSDictionary).write(to: bundle.infoPlistURL)
}