NCNetworking+Task.swift 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. //
  2. // NCNetworking+Task.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 24/08/24.
  6. // Copyright © 2024 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. import Foundation
  24. import UIKit
  25. import NextcloudKit
  26. import Alamofire
  27. import RealmSwift
  28. extension NCNetworking {
  29. func cancelAllTask() {
  30. cancelAllQueue()
  31. cancelAllDataTask()
  32. cancelAllWaitTask()
  33. cancelAllDownloadUploadTask()
  34. }
  35. func cancelAllDownloadTask() {
  36. cancelDownloadTasks()
  37. cancelDownloadBackgroundTask()
  38. }
  39. func cancelAllUploadTask() {
  40. cancelUploadTasks()
  41. cancelUploadBackgroundTask()
  42. }
  43. func cancelAllDownloadUploadTask() {
  44. cancelAllDownloadTask()
  45. cancelAllUploadTask()
  46. }
  47. // MARK: -
  48. func cancelTask(metadata: tableMetadata) {
  49. /// FAVORITE
  50. ///
  51. if metadata.status == global.metadataStatusWaitFavorite {
  52. let favorite = (metadata.storeFlag as? NSString)?.boolValue ?? false
  53. database.setMetadataFavorite(ocId: metadata.ocId, favorite: favorite, saveOldFavorite: nil, status: global.metadataStatusNormal)
  54. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterReloadDataSource)
  55. return
  56. }
  57. /// COPY
  58. ///
  59. if metadata.status == global.metadataStatusWaitCopy {
  60. database.setMetadataCopyMove(ocId: metadata.ocId, serverUrlTo: "", overwrite: nil, status: global.metadataStatusNormal)
  61. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterReloadDataSource)
  62. return
  63. }
  64. /// MOVE
  65. ///
  66. if metadata.status == global.metadataStatusWaitMove {
  67. database.setMetadataCopyMove(ocId: metadata.ocId, serverUrlTo: "", overwrite: nil, status: global.metadataStatusNormal)
  68. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterReloadDataSource)
  69. return
  70. }
  71. /// DELETE
  72. ///
  73. if metadata.status == global.metadataStatusWaitDelete {
  74. database.setMetadataStatus(ocId: metadata.ocId, status: global.metadataStatusNormal)
  75. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterReloadDataSource)
  76. return
  77. }
  78. /// RENAME
  79. ///
  80. if metadata.status == global.metadataStatusWaitRename {
  81. database.restoreMetadataFileName(ocId: metadata.ocId)
  82. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterReloadDataSource)
  83. return
  84. }
  85. /// CREATE FOLDER
  86. ///
  87. if metadata.status == global.metadataStatusWaitCreateFolder {
  88. let metadatas = database.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND status != 0", metadata.account, metadata.serverUrl))
  89. for metadata in metadatas {
  90. database.deleteMetadataOcId(metadata.ocId)
  91. utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  92. }
  93. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterReloadDataSource)
  94. return
  95. }
  96. /// NO SESSION
  97. ///
  98. if metadata.session.isEmpty {
  99. self.database.deleteMetadataOcId(metadata.ocId)
  100. utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  101. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterReloadDataSource)
  102. return
  103. }
  104. /// DOWNLOAD
  105. ///
  106. if metadata.session.contains("download") {
  107. if metadata.session == sessionDownload {
  108. cancelDownloadTasks(metadata: metadata)
  109. } else if metadata.session == sessionDownloadBackground {
  110. cancelDownloadBackgroundTask(metadata: metadata)
  111. }
  112. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterDownloadCancelFile,
  113. object: nil,
  114. userInfo: ["ocId": metadata.ocId,
  115. "ocIdTransfer": metadata.ocIdTransfer,
  116. "session": metadata.session,
  117. "serverUrl": metadata.serverUrl,
  118. "account": metadata.account],
  119. second: 0.5)
  120. }
  121. /// UPLOAD
  122. ///
  123. if metadata.session.contains("upload") {
  124. if metadata.session == NextcloudKit.shared.nkCommonInstance.identifierSessionUpload {
  125. cancelUploadTasks(metadata: metadata)
  126. } else {
  127. cancelUploadBackgroundTask(metadata: metadata)
  128. }
  129. utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  130. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterUploadCancelFile,
  131. object: nil,
  132. userInfo: ["ocId": metadata.ocId,
  133. "ocIdTransfer": metadata.ocIdTransfer,
  134. "session": metadata.session,
  135. "serverUrl": metadata.serverUrl,
  136. "account": metadata.account],
  137. second: 0.5)
  138. }
  139. }
  140. func cancelAllWaitTask() {
  141. let metadatas = database.getMetadatas(predicate: NSPredicate(format: "status IN %@", global.metadataStatusWaitWebDav))
  142. for metadata in metadatas {
  143. cancelTask(metadata: metadata)
  144. }
  145. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterReloadDataSource)
  146. }
  147. func cancelAllDataTask() {
  148. NextcloudKit.shared.nkCommonInstance.nksessions.forEach { session in
  149. session.sessionData.session.getTasksWithCompletionHandler { dataTasks, _, _ in
  150. dataTasks.forEach { task in
  151. task.cancel()
  152. }
  153. }
  154. }
  155. }
  156. // MARK: -
  157. func cancelDownloadTasks(metadata: tableMetadata? = nil) {
  158. NextcloudKit.shared.nkCommonInstance.nksessions.forEach { session in
  159. session.sessionData.session.getTasksWithCompletionHandler { _, _, downloadTasks in
  160. downloadTasks.forEach { task in
  161. if metadata == nil || (task.taskIdentifier == metadata?.sessionTaskIdentifier) {
  162. task.cancel()
  163. }
  164. }
  165. }
  166. }
  167. if let metadata {
  168. self.database.clearMetadataSession(metadata: metadata)
  169. } else if let results = self.database.getResultsMetadatas(predicate: NSPredicate(format: "(status == %d || status == %d || status == %d) AND session == %@",
  170. self.global.metadataStatusWaitDownload,
  171. self.global.metadataStatusDownloading,
  172. self.global.metadataStatusDownloadError,
  173. sessionDownload)) {
  174. self.database.clearMetadataSession(metadatas: Array(results))
  175. }
  176. }
  177. func cancelDownloadBackgroundTask(metadata: tableMetadata? = nil) {
  178. NextcloudKit.shared.nkCommonInstance.nksessions.forEach { session in
  179. Task {
  180. let tasksBackground = await session.sessionDownloadBackground.tasks
  181. for task in tasksBackground.2 { // ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask])
  182. if metadata == nil || (task.taskIdentifier == metadata?.sessionTaskIdentifier) {
  183. task.cancel()
  184. }
  185. }
  186. if let metadata {
  187. self.database.clearMetadataSession(metadata: metadata)
  188. } else if let results = self.database.getResultsMetadatas(predicate: NSPredicate(format: "(status == %d || status == %d || status == %d) AND session == %@",
  189. self.global.metadataStatusWaitDownload,
  190. self.global.metadataStatusDownloading,
  191. self.global.metadataStatusDownloadError,
  192. sessionDownloadBackground)) {
  193. self.database.clearMetadataSession(metadatas: Array(results))
  194. }
  195. }
  196. }
  197. }
  198. // MARK: -
  199. func cancelUploadTasks(metadata: tableMetadata? = nil) {
  200. NextcloudKit.shared.nkCommonInstance.nksessions.forEach { nkSession in
  201. nkSession.sessionData.session.getTasksWithCompletionHandler { _, uploadTasks, _ in
  202. uploadTasks.forEach { task in
  203. if metadata == nil || (metadata?.account == nkSession.account && metadata?.sessionTaskIdentifier == task.taskIdentifier) {
  204. task.cancel()
  205. }
  206. }
  207. }
  208. }
  209. if let metadata {
  210. self.database.deleteMetadataOcId(metadata.ocId)
  211. } else if let results = self.database.getResultsMetadatas(predicate: NSPredicate(format: "(status == %d || status == %d || status == %d) AND session == %@",
  212. self.global.metadataStatusWaitUpload,
  213. self.global.metadataStatusUploading,
  214. self.global.metadataStatusUploadError,
  215. sessionUpload)) {
  216. self.database.deleteMetadatas(Array(results))
  217. }
  218. }
  219. func cancelUploadBackgroundTask(metadata: tableMetadata? = nil) {
  220. NextcloudKit.shared.nkCommonInstance.nksessions.forEach { nkSession in
  221. Task {
  222. let tasksBackground = await nkSession.sessionUploadBackground.tasks
  223. for task in tasksBackground.1 { // ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask])
  224. if metadata == nil || (metadata?.account == nkSession.account &&
  225. metadata?.session == sessionUploadBackground &&
  226. metadata?.sessionTaskIdentifier == task.taskIdentifier) {
  227. task.cancel()
  228. }
  229. }
  230. let tasksBackgroundWWan = await nkSession.sessionUploadBackgroundWWan.tasks
  231. for task in tasksBackgroundWWan.1 { // ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask])
  232. if metadata == nil || (metadata?.account == nkSession.account &&
  233. metadata?.session == sessionUploadBackgroundWWan &&
  234. metadata?.sessionTaskIdentifier == task.taskIdentifier) {
  235. task.cancel()
  236. }
  237. }
  238. let tasksBackgroundExt = await nkSession.sessionUploadBackgroundExt.tasks
  239. for task in tasksBackgroundExt.1 { // ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask])
  240. if metadata == nil || (metadata?.account == nkSession.account &&
  241. metadata?.session == sessionUploadBackgroundExt &&
  242. metadata?.sessionTaskIdentifier == task.taskIdentifier) {
  243. task.cancel()
  244. }
  245. }
  246. if let metadata {
  247. self.database.deleteMetadataOcId(metadata.ocId)
  248. } else if let results = self.database.getResultsMetadatas(predicate: NSPredicate(format: "(status == %d || status == %d || status == %d) AND (session == %@ || session == %@ || session == %@)",
  249. self.global.metadataStatusWaitUpload,
  250. self.global.metadataStatusUploading,
  251. self.global.metadataStatusUploadError,
  252. sessionUploadBackground,
  253. sessionUploadBackgroundWWan,
  254. sessionUploadBackgroundExt
  255. )) {
  256. self.database.deleteMetadatas(Array(results))
  257. }
  258. }
  259. }
  260. }
  261. // MARK: -
  262. func getAllDataTask() async -> [URLSessionDataTask] {
  263. guard let nkSessions = NextcloudKit.shared.nkCommonInstance.nksessions.getArray() else { return [] }
  264. var taskArray: [URLSessionDataTask] = []
  265. for nkSession in nkSessions {
  266. let tasks = await nkSession.sessionData.session.tasks
  267. for task in tasks.0 {
  268. taskArray.append(task)
  269. }
  270. }
  271. return taskArray
  272. }
  273. // MARK: -
  274. func verifyZombie() async {
  275. var metadatas: [tableMetadata] = []
  276. /// UPLOADING-FOREGROUND
  277. ///
  278. metadatas = self.database.getMetadatas(predicate: NSPredicate(format: "session == %@ AND status == %d",
  279. sessionUpload,
  280. self.global.metadataStatusUploading))
  281. for metadata in metadatas {
  282. guard let nkSession = NextcloudKit.shared.getSession(account: metadata.account) else {
  283. self.database.deleteMetadataOcId(metadata.ocId)
  284. utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  285. continue
  286. }
  287. var foundTask = false
  288. let tasks = await nkSession.sessionData.session.tasks
  289. for task in tasks.1 { // ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask])
  290. if metadata.sessionTaskIdentifier == task.taskIdentifier {
  291. foundTask = true
  292. }
  293. }
  294. if !foundTask {
  295. if NCUtilityFileSystem().fileProviderStorageExists(metadata) {
  296. self.database.setMetadataSession(ocId: metadata.ocId,
  297. sessionError: "",
  298. status: self.global.metadataStatusWaitUpload)
  299. } else {
  300. self.database.deleteMetadataOcId(metadata.ocId)
  301. }
  302. }
  303. }
  304. /// UPLOADING-BACKGROUND
  305. ///
  306. metadatas = self.database.getMetadatas(predicate: NSPredicate(format: "(session == %@ OR session == %@ OR session == %@) AND status == %d",
  307. sessionUploadBackground,
  308. sessionUploadBackgroundWWan,
  309. sessionUploadBackgroundExt,
  310. self.global.metadataStatusUploading))
  311. for metadata in metadatas {
  312. guard let nkSession = NextcloudKit.shared.getSession(account: metadata.account) else {
  313. self.database.deleteMetadataOcId(metadata.ocId)
  314. utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  315. continue
  316. }
  317. var session: URLSession?
  318. if metadata.session == sessionUploadBackground {
  319. session = nkSession.sessionUploadBackground
  320. } else if metadata.session == sessionUploadBackgroundWWan {
  321. session = nkSession.sessionUploadBackgroundWWan
  322. } else if metadata.session == sessionUploadBackgroundExt {
  323. session = nkSession.sessionUploadBackgroundExt
  324. }
  325. var foundTask = false
  326. guard let tasks = await session?.allTasks else {
  327. self.database.deleteMetadataOcId(metadata.ocId)
  328. utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  329. continue
  330. }
  331. for task in tasks {
  332. if metadata.sessionTaskIdentifier == task.taskIdentifier {
  333. foundTask = true
  334. }
  335. }
  336. if !foundTask {
  337. if NCUtilityFileSystem().fileProviderStorageExists(metadata) {
  338. self.database.setMetadataSession(ocId: metadata.ocId,
  339. sessionError: "",
  340. status: self.global.metadataStatusWaitUpload)
  341. } else {
  342. self.database.deleteMetadataOcId(metadata.ocId)
  343. }
  344. }
  345. }
  346. /// DOWNLOADING-FOREGROUND
  347. ///
  348. metadatas = self.database.getMetadatas(predicate: NSPredicate(format: "session == %@ AND status == %d",
  349. sessionDownload,
  350. self.global.metadataStatusDownloading))
  351. for metadata in metadatas {
  352. guard let nkSession = NextcloudKit.shared.getSession(account: metadata.account) else {
  353. self.database.deleteMetadataOcId(metadata.ocId)
  354. utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  355. continue
  356. }
  357. var foundTask = false
  358. let tasks = await nkSession.sessionData.session.tasks
  359. for task in tasks.2 { // ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask])
  360. if metadata.sessionTaskIdentifier == task.taskIdentifier {
  361. foundTask = true
  362. }
  363. }
  364. if !foundTask {
  365. self.database.setMetadataSession(ocId: metadata.ocId,
  366. session: "",
  367. sessionError: "",
  368. selector: "",
  369. status: self.global.metadataStatusNormal)
  370. }
  371. }
  372. /// DOWNLOADING-BACKGROUND
  373. ///
  374. metadatas = self.database.getMetadatas(predicate: NSPredicate(format: "session == %@ AND status == %d",
  375. sessionDownloadBackground,
  376. self.global.metadataStatusDownloading))
  377. for metadata in metadatas {
  378. guard let nkSession = NextcloudKit.shared.getSession(account: metadata.account) else {
  379. self.database.deleteMetadataOcId(metadata.ocId)
  380. utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  381. continue
  382. }
  383. var foundTask = false
  384. let tasks = await nkSession.sessionDownloadBackground.allTasks
  385. for task in tasks {
  386. if metadata.sessionTaskIdentifier == task.taskIdentifier {
  387. foundTask = true
  388. }
  389. }
  390. if !foundTask {
  391. self.database.setMetadataSession(ocId: metadata.ocId,
  392. session: "",
  393. sessionError: "",
  394. selector: "",
  395. status: self.global.metadataStatusNormal)
  396. }
  397. }
  398. }
  399. }