Skip to content

Commit

Permalink
Merge branch 'darwin' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
inetic committed Nov 19, 2024
2 parents 473a5c5 + 5143c25 commit 984a27b
Show file tree
Hide file tree
Showing 27 changed files with 630 additions and 371 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,17 @@ extension Extension {

let proxyId = generateProxyId()

connection.interruptionHandler = { [weak self] in
connection.interruptionHandler = { [weak self] in guard let self else { return }
NSLog("😡 Connection to Ouisync XPC service has been interrupted")
if let s = self {
synchronized(s) {
s.proxies.removeValue(forKey: proxyId)
return
}
synchronized(self) {
_ = self.proxies.removeValue(forKey: proxyId)
}
}

connection.invalidationHandler = { [weak self] in
connection.invalidationHandler = { [weak self] in guard let self else { return }
NSLog("😡 Connection to Ouisync XPC service has been invalidated")
if let s = self {
synchronized(s) {
s.proxies.removeValue(forKey: proxyId)
return
}
synchronized(self) {
_ = self.proxies.removeValue(forKey: proxyId)
}
}

Expand All @@ -109,12 +103,34 @@ extension Extension {
return false
}

// this is a bit awkward because to avoid a reference leak, we have to atomically add
// our invalidation closure iff the base extension has not been shut down yet, but we
// also don't want to lift the rest of this function into the synchronized block,
// thus resulting in two checks against the same value
let active = synchronized(ext) {
if ext.active {
ext.invalidators.append {
connection.invalidate() // this should notify peer; invalidationHandler cleans up proxies
await ouisyncClient.close()
}
}
return ext.active
}
guard active else {
// presumably the OS is smart enough to not keep using this service provider bound
// to an instance it has already invalidate()d but stranger things have happened
NSLog("👋 The File Provider extension has received a connection from the app but is in the process of shutting down")
return false
}

let proxy = AppToBackendProxy(connection, sendToApp, ouisyncClient)

connection.exportedObject = proxy
connection.exportedInterface = NSXPCInterface(with: FromAppToFileProviderProtocol.self)

proxies[proxyId] = proxy
synchronized(self) {
proxies[proxyId] = proxy
}

connection.resume()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import OSLog
import Common
import Network

class Extension: NSObject, NSFileProviderReplicatedExtension {
open class Extension: NSObject, NSFileProviderReplicatedExtension {
static let WRITE_CHUNK_SIZE: UInt64 = 32768 // TODO: Decide on optimal value
static let READ_CHUNK_SIZE: Int = 32768 // TODO: Decide on optimal value

Expand All @@ -25,7 +25,7 @@ class Extension: NSObject, NSFileProviderReplicatedExtension {
let pastEnumerations: PastEnumerations?
let manager: NSFileProviderManager

required init(domain: NSFileProviderDomain) {
public required init(domain: NSFileProviderDomain) {
// TODO: The containing application must create a domain using
// `NSFileProviderManager.add(_:, completionHandler:)`. The system will
// then launch the application extension process, call
Expand Down Expand Up @@ -151,11 +151,28 @@ class Extension: NSObject, NSFileProviderReplicatedExtension {
}
}

func invalidate() {
// TODO: cleanup any resources
// WARN: only mutate these while holding a lock on self
var active = true // this is set to false when shutting down
var invalidators: [@Sendable () async -> Void] = [] // list of things called on invalidate(); only append if active = true!
public func invalidate() {
let active = synchronized(self) {
defer { self.active = false }
return self.active
}
guard active else { return }
Task {
NSLog("👋 The File Provider extension is shutting down")
async let _ = ouisyncSession.client.close()
await withTaskGroup(of: Void.self) {
for invalidator in invalidators {
$0.addTask(operation: invalidator)
}
invalidators.removeAll() // just in case they were holding strong refs
}
}
}

func item(for identifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) -> Progress {
public func item(for identifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) -> Progress {
let log = self.log.child("item").trace("invoked(\(identifier))")

let handler = { (item: NSFileProviderItem?, error: Error?) in
Expand Down Expand Up @@ -187,7 +204,7 @@ class Extension: NSObject, NSFileProviderReplicatedExtension {
return Progress()
}

func fetchContents(for itemIdentifier: NSFileProviderItemIdentifier, version requestedVersion: NSFileProviderItemVersion?, request: NSFileProviderRequest, completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void) -> Progress {
public func fetchContents(for itemIdentifier: NSFileProviderItemIdentifier, version requestedVersion: NSFileProviderItemVersion?, request: NSFileProviderRequest, completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void) -> Progress {
let log = self.log.child("fetchContents").info("invoked(\(itemIdentifier), \(requestedVersion.flatMap{Version($0)} as Optional)")
// TODO: implement fetching of the contents for the itemIdentifier at the specified version

Expand Down Expand Up @@ -281,7 +298,7 @@ class Extension: NSObject, NSFileProviderReplicatedExtension {
return progress
}

func createItem(basedOn itemTemplate: NSFileProviderItem, fields: NSFileProviderItemFields, contents url: URL?, options: NSFileProviderCreateItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress {
public func createItem(basedOn itemTemplate: NSFileProviderItem, fields: NSFileProviderItemFields, contents url: URL?, options: NSFileProviderCreateItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress {
// TODO: a new item was created on disk, process the item's creation
let log = log.child("createItem").trace("invoked(itemTemplate:\(itemTemplate), fields:\(fields), url:\(url as Optional), options:\(options))")

Expand Down Expand Up @@ -348,7 +365,7 @@ class Extension: NSObject, NSFileProviderReplicatedExtension {
return Progress()
}

func modifyItem(_ item: NSFileProviderItem, baseVersion version: NSFileProviderItemVersion, changedFields: NSFileProviderItemFields, contents newContents: URL?, options: NSFileProviderModifyItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress {
public func modifyItem(_ item: NSFileProviderItem, baseVersion version: NSFileProviderItemVersion, changedFields: NSFileProviderItemFields, contents newContents: URL?, options: NSFileProviderModifyItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress {
// TODO: an item was modified on disk, process the item's modification
let log = self.log.child("modifyItem").trace("invoked(\(item), changedFields: \(changedFields))")

Expand Down Expand Up @@ -461,7 +478,7 @@ class Extension: NSObject, NSFileProviderReplicatedExtension {
return Progress()
}

func deleteItem(identifier: NSFileProviderItemIdentifier, baseVersion version: NSFileProviderItemVersion, options: NSFileProviderDeleteItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (Error?) -> Void) -> Progress {
public func deleteItem(identifier: NSFileProviderItemIdentifier, baseVersion version: NSFileProviderItemVersion, options: NSFileProviderDeleteItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (Error?) -> Void) -> Progress {
// TODO: an item was deleted on disk, process the item's deletion
let log = log.child("deleteItem").trace("invoked(\(identifier))")

Expand Down Expand Up @@ -498,7 +515,7 @@ class Extension: NSObject, NSFileProviderReplicatedExtension {
return Progress()
}

func enumerator(for rawIdentifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest) throws -> NSFileProviderEnumerator {
public func enumerator(for rawIdentifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest) throws -> NSFileProviderEnumerator {
let identifier = ItemIdentifier(rawIdentifier)

let log = self.log.child("enumerator").level(.trace).trace("invoked(\(identifier))")
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
13 changes: 0 additions & 13 deletions macos/Common/Common.docc/Common.md

This file was deleted.

18 changes: 0 additions & 18 deletions macos/Common/Common.h

This file was deleted.

36 changes: 0 additions & 36 deletions macos/CommonTests/CommonTests.swift

This file was deleted.

File renamed without changes.
4 changes: 4 additions & 0 deletions macos/Extension/EntryPoint.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Backend // bit of a hack until we sort out the visibility


final class FileProvider: Extension {}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<key>NSExtensionPointIdentifier</key>
<string>com.apple.fileprovider-nonui</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).Extension</string>
<string>$(PRODUCT_MODULE_NAME).FileProvider</string>
</dict>
</dict>
</plist>
Loading

0 comments on commit 984a27b

Please sign in to comment.