Skip to content

Commit

Permalink
Prevent system from deleting caches while app is running
Browse files Browse the repository at this point in the history
  • Loading branch information
wuyuehyang committed Jun 14, 2023
1 parent 9f1173a commit 216a7eb
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 36 deletions.
29 changes: 15 additions & 14 deletions Mixin/Service/DeviceTransfer/DeviceTransferClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ final class DeviceTransferClient {
private let key: DeviceTransferKey
private let remotePlatform: DeviceTransferPlatform
private let connection: NWConnection
private let cacheContainerURL: URL
private let messageProcessor: DeviceTransferMessageProcessor
private let queue = Queue(label: "one.mixin.messenger.DeviceTransferClient")
private let cacheContainerURL = FileManager.default.temporaryDirectory.appendingPathComponent("DeviceTransfer", isDirectory: true)
private let speedInspector = NetworkSpeedInspector()
private let messageProcessor: DeviceTransferMessageProcessor

private weak var statisticsTimer: Timer?

Expand All @@ -40,7 +40,18 @@ final class DeviceTransferClient {
Unmanaged<DeviceTransferClient>.passUnretained(self).toOpaque()
}

init(hostname: String, port: UInt16, code: UInt16, key: DeviceTransferKey, remotePlatform: DeviceTransferPlatform) {
init(hostname: String, port: UInt16, code: UInt16, key: DeviceTransferKey, remotePlatform: DeviceTransferPlatform) throws {
// https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW2
// In iOS 5.0 and later, the system may delete the Caches directory on rare occasions when the system is very low on disk space.
// This will never occur while an app is running.
let manager = FileManager.default
let cacheContainerURL = try manager.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("DeviceTransfer")
if manager.fileExists(atPath: cacheContainerURL.path) {
try? manager.removeItem(at: cacheContainerURL)
}
try manager.createDirectory(at: cacheContainerURL, withIntermediateDirectories: true)

self.hostname = hostname
self.port = port
self.code = code
Expand All @@ -52,6 +63,7 @@ final class DeviceTransferClient {
let endpoint = NWEndpoint.hostPort(host: host, port: port)
return NWConnection(to: endpoint, using: .deviceTransfer)
}()
self.cacheContainerURL = cacheContainerURL
self.messageProcessor = .init(key: key.aes,
remotePlatform: remotePlatform,
cacheContainerURL: cacheContainerURL,
Expand All @@ -65,17 +77,6 @@ final class DeviceTransferClient {

func start() {
Logger.general.info(category: "DeviceTransferClient", message: "Will start connecting to [\(hostname)]:\(port)")
do {
let manager = FileManager.default
if manager.fileExists(atPath: cacheContainerURL.path) {
try? manager.removeItem(at: cacheContainerURL)
}
try manager.createDirectory(at: cacheContainerURL, withIntermediateDirectories: true)
} catch {
Logger.general.error(category: "DeviceTransferClient", message: "Failed to create cache container: \(error)")
fail(error: .createCacheContainer(error))
return
}
messageProcessor.$processingError
.receive(on: queue.dispatchQueue)
.sink { error in
Expand Down
1 change: 0 additions & 1 deletion Mixin/Service/DeviceTransfer/DeviceTransferError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@ enum DeviceTransferError: Error {
case mismatchedHMAC(local: Data, remote: Data)
case connectionFailed(Error)
case receiveFile(Error)
case createCacheContainer(Error)
case importing(DeviceTransferMessageProcessor.ProcessingError)
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,24 @@ extension RestoreFromDesktopViewController {
dataSource.replaceSection(at: 0, with: section, animation: .automatic)
tableView.isUserInteractionEnabled = true
case let .push(context):
let client = DeviceTransferClient(hostname: context.hostname,
port: context.port,
code: context.code,
key: context.key,
remotePlatform: command.platform)
stateObserver = client.$state
.receive(on: DispatchQueue.main)
.sink { [weak self] state in
self?.stateDidChange(client: client, state: state)
do {
let client = try DeviceTransferClient(hostname: context.hostname,
port: context.port,
code: context.code,
key: context.key,
remotePlatform: command.platform)
stateObserver = client.$state
.receive(on: DispatchQueue.main)
.sink { [weak self] state in
self?.stateDidChange(client: client, state: state)
}
client.start()
} catch {
Logger.general.error(category: "RestoreFromDesktop", message: "Unable to init client: \(error)")
alert(R.string.localizable.connection_establishment_failed(), message: nil) { _ in
self.navigationController?.popViewController(animated: true)
}
client.start()
}
default:
Logger.general.info(category: "RestoreFromDesktop", message: "Invalid command")
alert(R.string.localizable.connection_establishment_failed(), message: nil) { _ in
Expand Down
27 changes: 16 additions & 11 deletions Mixin/UserInterface/Windows/UrlWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -888,17 +888,22 @@ class UrlWindow {
UIApplication.currentActivity()?.alert(R.string.localizable.unable_synced_between_different_account())
return true
}
let client = DeviceTransferClient(hostname: context.hostname,
port: context.port,
code: context.code,
key: context.key,
remotePlatform: command.platform)
client.start()
let progress = DeviceTransferProgressViewController(connection: .client(client, .phone))
if let navigationController = AppDelegate.current.mainWindow.rootViewController as? UINavigationController {
navigationController.pushViewController(progress, animated: true)
} else {
AppDelegate.current.mainWindow.rootViewController?.present(progress, animated: true)
do {
let client = try DeviceTransferClient(hostname: context.hostname,
port: context.port,
code: context.code,
key: context.key,
remotePlatform: command.platform)
client.start()
let progress = DeviceTransferProgressViewController(connection: .client(client, .phone))
if let navigationController = AppDelegate.current.mainWindow.rootViewController as? UINavigationController {
navigationController.pushViewController(progress, animated: true)
} else {
AppDelegate.current.mainWindow.rootViewController?.present(progress, animated: true)
}
} catch {
Logger.general.error(category: "UrlWindow", message: "Unable to init client: \(error)")
UIApplication.currentActivity()?.alert(R.string.localizable.connection_establishment_failed())
}
return true
}
Expand Down

0 comments on commit 216a7eb

Please sign in to comment.