diff --git a/src/Constants.iOS.cs.in b/src/Constants.iOS.cs.in index 27e6a28f6794..7d9412c2d961 100644 --- a/src/Constants.iOS.cs.in +++ b/src/Constants.iOS.cs.in @@ -113,5 +113,6 @@ namespace MonoTouch { public const string IdentityLookupLibrary = "/System/Library/Frameworks/IdentityLookup.framework/IdentityLookup"; public const string CoreMLLibrary = "/System/Library/Frameworks/CoreML.framework/CoreML"; public const string VisionLibrary = "/System/Library/Frameworks/Vision.framework/Vision"; + public const string FileProviderLibrary = "/System/Library/Frameworks/FileProvider.framework/FileProvider"; } } diff --git a/src/FileProvider/NSFileProviderItemIdentifierExtensions.cs b/src/FileProvider/NSFileProviderItemIdentifierExtensions.cs new file mode 100644 index 000000000000..de20d883368a --- /dev/null +++ b/src/FileProvider/NSFileProviderItemIdentifierExtensions.cs @@ -0,0 +1,29 @@ +// +// NSFileProviderItemIdentifierExtensions.cs +// +// Authors: +// Alex Soto +// +// Copyright 2017 Xamarin Inc. All rights reserved. +// + +#if XAMCORE_2_0 +using System; +using XamCore.Foundation; + +namespace XamCore.FileProvider { + public partial class NSFileProviderItemIdentifierExtensions { + + public static NSString[] GetConstants (this NSFileProviderItemIdentifier[] self) + { + if (self == null) + throw new ArgumentNullException (nameof (self)); + + var array = new NSString [self.Length]; + for (int n = 0; n < self.Length; n++) + array [n] = self [n].GetConstant (); + return array; + } + } +} +#endif diff --git a/src/fileprovider.cs b/src/fileprovider.cs new file mode 100644 index 000000000000..26a44d964e9a --- /dev/null +++ b/src/fileprovider.cs @@ -0,0 +1,307 @@ +// +// FileProvider C# bindings +// +// Authors: +// Alex Soto +// +// Copyright 2017 Xamarin Inc. All rights reserved. +// + +#if XAMCORE_2_0 + +using System; +using XamCore.ObjCRuntime; +using XamCore.CoreGraphics; +using XamCore.Foundation; + +namespace XamCore.FileProvider { + + [iOS (11,0)] + [ErrorDomain ("NSFileProviderErrorDomain")] + [Native] + public enum NSFileProviderError : nint { + NotAuthenticated = -1000, + FilenameCollision = -1001, + SyncAnchorExpired = -1002, + PageExpired = SyncAnchorExpired, + InsufficientQuota = -1003, + ServerUnreachable = -1004, + NoSuchItem = -1005, + } + + [iOS (11,0)] + enum NSFileProviderItemIdentifier { + + [Field ("NSFileProviderRootContainerItemIdentifier")] + RootContainer, + + [Field ("NSFileProviderWorkingSetContainerItemIdentifier")] + WorkingSetContainer, + } + + [iOS (11,0)] + [Native] + [Flags] + public enum NSFileProviderItemCapabilities : nuint { + Reading = 1 << 0, + Writing = 1 << 1, + Reparenting = 1 << 2, + Renaming = 1 << 3, + Trashing = 1 << 4, + Deleting = 1 << 5, + AddingSubItems = Writing, + ContentEnumerating = Reading, + All = Reading | Writing | Reparenting | Renaming | Trashing | Deleting, + } + + [iOS (11,0)] + [DisableDefaultCtor] + [BaseType (typeof (NSObject))] + interface NSFileProviderDomain { + + [Export ("initWithIdentifier:displayName:pathRelativeToDocumentStorage:")] + IntPtr Constructor (string identifier, string displayName, string pathRelativeToDocumentStorage); + + [Export ("identifier")] + string Identifier { get; } + + [Export ("displayName")] + string DisplayName { get; } + + [Export ("pathRelativeToDocumentStorage")] + string PathRelativeToDocumentStorage { get; } + } + + interface INSFileProviderEnumerationObserver { } + + [iOS (11,0)] + [Protocol] + interface NSFileProviderEnumerationObserver { + + [Abstract] + [Export ("didEnumerateItems:")] + void DidEnumerateItems (INSFileProviderItem [] updatedItems); + + [Abstract] + [Export ("finishEnumeratingUpToPage:")] + void FinishEnumerating ([NullAllowed] NSData upToPage); + + [Abstract] + [Export ("finishEnumeratingWithError:")] + void FinishEnumerating (NSError error); + } + + interface INSFileProviderChangeObserver { } + + [iOS (11,0)] + [Protocol] + interface NSFileProviderChangeObserver { + + [Abstract] + [Export ("didUpdateItems:")] + void DidUpdateItems (INSFileProviderItem [] updatedItems); + + [Abstract] + [Export ("didDeleteItemsWithIdentifiers:")] + void DidDeleteItems (string [] deletedItemIdentifiers); + + [Abstract] + [Export ("finishEnumeratingChangesUpToSyncAnchor:moreComing:")] + void FinishEnumeratingChanges (NSData anchor, bool moreComing); + + [Abstract] + [Export ("finishEnumeratingWithError:")] + void FinishEnumerating (NSError error); + } + + interface INSFileProviderEnumerator { } + + [iOS (11,0)] + [Protocol] + interface NSFileProviderEnumerator { + + [Abstract] + [Export ("invalidate")] + void Invalidate (); + + [Abstract] + [Export ("enumerateItemsForObserver:startingAtPage:")] + void EnumerateItems (INSFileProviderEnumerationObserver observer, NSData startPage); + + [Export ("enumerateChangesForObserver:fromSyncAnchor:")] + void EnumerateChanges (INSFileProviderChangeObserver observer, NSData syncAnchor); + + [Export ("currentSyncAnchorWithCompletionHandler:")] + void CurrentSyncAnchor (Action completionHandler); + } + + interface INSFileProviderItem { } + + [iOS (11,0)] + [Protocol] + interface NSFileProviderItem { + + [Advice ("Use 'NSFileProviderItemIdentifierExtensions.GetValue (ItemIdentifier)' to get a 'NSFileProviderItemIdentifier' enum.")] + [Abstract] + [Export ("itemIdentifier")] + NSString Identifier { get; } + + [Advice ("Use 'NSFileProviderItemIdentifierExtensions.GetValue (ParentItemIdentifier)' to get a 'NSFileProviderItemIdentifier' enum.")] + [Abstract] + [Export ("parentItemIdentifier")] + NSString ParentIdentifier { get; } + + [Abstract] + [Export ("filename")] + string Filename { get; } + + [Abstract] + [Export ("typeIdentifier")] + string TypeIdentifier { get; } + + [Export ("capabilities")] + NSFileProviderItemCapabilities GetCapabilities (); + + [return: NullAllowed] + [Export ("documentSize", ArgumentSemantic.Copy)] + NSNumber GetDocumentSize (); + + [return: NullAllowed] + [Export ("childItemCount", ArgumentSemantic.Copy)] + NSNumber GetChildItemCount (); + + [return: NullAllowed] + [Export ("creationDate", ArgumentSemantic.Copy)] + NSDate GetCreationDate (); + + [return: NullAllowed] + [Export ("contentModificationDate", ArgumentSemantic.Copy)] + NSDate GetContentModificationDate (); + + [return: NullAllowed] + [Export ("lastUsedDate", ArgumentSemantic.Copy)] + NSDate GetLastUsedDate (); + + [return: NullAllowed] + [Export ("tagData", ArgumentSemantic.Copy)] + NSData GetTagData (); + + [return: NullAllowed] + [Export ("favoriteRank", ArgumentSemantic.Copy)] + NSNumber GetFavoriteRank (); + + [Export ("isTrashed")] + bool IsTrashed (); + + [Export ("isUploaded")] + bool IsUploaded (); + + [Export ("isUploading")] + bool IsUploading (); + + [return: NullAllowed] + [Export ("uploadingError", ArgumentSemantic.Copy)] + NSError GetUploadingError (); + + [Export ("isDownloaded")] + bool IsDownloaded (); + + [Export ("isDownloading")] + bool IsDownloading (); + + [return: NullAllowed] + [Export ("downloadingError", ArgumentSemantic.Copy)] + NSError GetDownloadingError (); + + [Export ("isMostRecentVersionDownloaded")] + bool IsMostRecentVersionDownloaded (); + + [Export ("isShared")] + bool IsShared (); + + [Export ("isSharedByCurrentUser")] + bool IsSharedByCurrentUser (); + + [return: NullAllowed] + [Export ("ownerNameComponents")] + NSPersonNameComponents GetOwnerNameComponents (); + + [return: NullAllowed] + [Export ("mostRecentEditorNameComponents")] + NSPersonNameComponents GetMostRecentEditorNameComponents (); + + [return: NullAllowed] + [Export ("versionIdentifier")] + NSData GetVersionIdentifier (); + + [return: NullAllowed] + [Export ("userInfo")] + NSDictionary GetUserInfo (); + } + + [iOS (11,0)] + [BaseType (typeof (NSObject))] + [DisableDefaultCtor] + interface NSFileProviderManager { + + [Static] + [Export ("defaultManager", ArgumentSemantic.Strong)] + NSFileProviderManager DefaultManager { get; } + + [Protected] + [Export ("signalEnumeratorForContainerItemIdentifier:completionHandler:")] + // Not Async'ified on purpose, because this can switch from app to extension. + void SignalEnumerator (NSString containerItemIdentifier, Action completion); + + [Wrap ("SignalEnumerator (containerItemIdentifier.GetConstant (), completion)")] + void SignalEnumerator (NSFileProviderItemIdentifier containerItemIdentifier, Action completion); + + // Not Async'ified on purpose, because the task must be accesed while the completion action is performing... + [Protected] + [Export ("registerURLSessionTask:forItemWithIdentifier:completionHandler:")] + void Register (NSUrlSessionTask task, NSString identifier, Action completion); + + [Wrap ("Register (task, identifier.GetConstant (), completion)")] + void Register (NSUrlSessionTask task, NSFileProviderItemIdentifier identifier, Action completion); + + [Export ("providerIdentifier")] + string ProviderIdentifier { get; } + + [Export ("documentStorageURL")] + NSUrl DocumentStorageUrl { get; } + + [Static] + [Export ("writePlaceholderAtURL:withMetadata:error:")] + bool WritePlaceholder (NSUrl placeholderUrl, INSFileProviderItem metadata, out NSError error); + + [Static] + [Export ("placeholderURLForURL:")] + NSUrl GetPlaceholderUrl (NSUrl url); + + [Static] + [Async] + [Export ("addDomain:completionHandler:")] + void AddDomain (NSFileProviderDomain domain, Action completionHandler); + + [Static] + [Async] + [Export ("removeDomain:completionHandler:")] + void RemoveDomain (NSFileProviderDomain domain, Action completionHandler); + + [Static] + [Async] + [Export ("getDomainsWithCompletionHandler:")] + void GetDomains (Action completionHandler); + + [Static] + [Async] + [Export ("removeAllDomainsWithCompletionHandler:")] + void RemoveAllDomains (Action completionHandler); + + [Static] + [Export ("managerForDomain:")] + [return: NullAllowed] + NSFileProviderManager FromDomain (NSFileProviderDomain domain); + } +} +#endif diff --git a/src/foundation.cs b/src/foundation.cs index bb01d9299210..8c328808d0b9 100644 --- a/src/foundation.cs +++ b/src/foundation.cs @@ -43,6 +43,9 @@ using XamCore.Security; #if IOS using XamCore.CoreSpotlight; +#if XAMCORE_2_0 +using XamCore.FileProvider; +#endif #endif #if MONOMAC @@ -3180,6 +3183,21 @@ interface NSError : NSSecureCoding, NSCopying { [Export ("userInfoValueProviderForDomain:")] [return: NullAllowed] NSErrorUserInfoValueProvider GetUserInfoValueProvider (string errorDomain); + +#if XAMCORE_2_0 && IOS + + // From NSError (NSFileProviderError) Category to avoid static category uglyness + + [iOS (11,0)] + [Static] + [Export ("fileProviderErrorForCollisionWithItem:")] + NSError GetFileProviderError (INSFileProviderItem existingItem); + + [iOS (11,0)] + [Static] + [Export ("fileProviderErrorForNonExistentItemWithIdentifier:")] + NSError GetFileProviderError (string nonExistentItemIdentifier); +#endif #if false // FIXME that value is present in the header (7.0 DP 6) files but returns NULL (i.e. unusable) diff --git a/src/frameworks.sources b/src/frameworks.sources index e6fcf529be16..705d47aa281c 100644 --- a/src/frameworks.sources +++ b/src/frameworks.sources @@ -599,6 +599,11 @@ EVENTKITUI_SOURCES = \ EXTERNALACCESSORY_API_SOURCES = \ ExternalAccessory/EAEnums.cs \ +# FileProvider + +FILEPROVIDER_SOURCES = \ + FileProvider/NSFileProviderItemIdentifierExtensions.cs \ + # FinderSync FINDERSYNC_CORE_SOURCES = \ @@ -1652,6 +1657,7 @@ IOS_FRAMEWORKS = \ EventKit \ EventKitUI \ ExternalAccessory \ + FileProvider \ GLKit \ GameController \ GameplayKit \ diff --git a/src/generator.cs b/src/generator.cs index 69d920a0fe83..59f01fb2da82 100644 --- a/src/generator.cs +++ b/src/generator.cs @@ -729,6 +729,8 @@ public NamespaceManager (string prefix, string customObjCRuntimeNS, bool skipSys ImplicitNamespaces.Add (Get ("GameplayKit")); if (Frameworks.HaveSpriteKit) ImplicitNamespaces.Add (Get ("SpriteKit")); + if (Frameworks.HaveFileProvider && Generator.UnifiedAPI) + ImplicitNamespaces.Add (Get ("FileProvider")); // These are both types and namespaces NamespacesThatConflictWithTypes = new HashSet { diff --git a/src/uikit.cs b/src/uikit.cs index b3a2bfd95deb..94299b34ce95 100644 --- a/src/uikit.cs +++ b/src/uikit.cs @@ -24,6 +24,10 @@ #endif using XamCore.CoreData; +#if XAMCORE_2_0 && IOS +using XamCore.FileProvider; +#endif + using System; using System.ComponentModel; @@ -277,21 +281,27 @@ interface NSDataAsset : NSCopying NSString TypeIdentifier { get; } } + delegate void NSFileProviderExtensionFetchThumbnailsHandler (NSString identifier, [NullAllowed] NSData imageData, [NullAllowed] NSError error); + [NoWatch] [NoTV] [iOS (8,0)] [ThreadSafe] [BaseType (typeof (NSObject))] partial interface NSFileProviderExtension { + [Deprecated (PlatformName.iOS, 11, 0, message: "Use 'NSFileProviderManager' instead.")] [Static, Export ("writePlaceholderAtURL:withMetadata:error:")] bool WritePlaceholder (NSUrl placeholderUrl, NSDictionary metadata, ref NSError error); + [Deprecated (PlatformName.iOS, 11, 0, message: "Use 'FileProvider::NSFileProviderManager.GetPlaceholderUrl (NSUrl)' instead.")] [Static, Export ("placeholderURLForURL:")] NSUrl GetPlaceholderUrl (NSUrl url); + [Deprecated (PlatformName.iOS, 11, 0, message: "Use 'FileProvider::NSFileProviderManager.ProviderIdentifier' instead.")] [Export ("providerIdentifier")] string ProviderIdentifier { get; } + [Deprecated (PlatformName.iOS, 11, 0, message: "Use 'FileProvider::NSFileProviderManager.DocumentStorageUrl' instead.")] [Export ("documentStorageURL")] NSUrl DocumentStorageUrl { get; } @@ -314,6 +324,117 @@ partial interface NSFileProviderExtension { [Export ("stopProvidingItemAtURL:")] void StopProvidingItemAtUrl (NSUrl url); + +#if XAMCORE_2_0 && IOS + + [Protected] + [iOS (11,0)] + [Export ("itemForIdentifier:error:")] + [return: NullAllowed] + INSFileProviderItem GetItem (NSString identifier, out NSError error); + + [iOS (11,0)] + [Wrap ("GetItem (identifier.GetConstant (), out error)")] + INSFileProviderItem GetItem (NSFileProviderItemIdentifier identifier, out NSError error); + + // Inlining NSFileProviderExtension (NSFileProviderActions) so we get asyncs + + [iOS (11,0)] + [Async] + [Export ("importDocumentAtURL:toParentItemIdentifier:completionHandler:")] + void ImportDocument (NSUrl fileUrl, string parentItemIdentifier, Action completionHandler); + + [iOS (11,0)] + [Async] + [Export ("createDirectoryWithName:inParentItemIdentifier:completionHandler:")] + void CreateDirectory (string directoryName, string parentItemIdentifier, Action completionHandler); + + [iOS (11,0)] + [Async] + [Export ("renameItemWithIdentifier:toName:completionHandler:")] + void RenameItem (string itemIdentifier, string itemName, Action completionHandler); + + [iOS (11,0)] + [Async] + [Export ("reparentItemWithIdentifier:toParentItemWithIdentifier:completionHandler:")] + void ReparentItem (string itemIdentifier, string parentItemIdentifier, Action completionHandler); + + [iOS (11,0)] + [Async] + [Export ("trashItemWithIdentifier:completionHandler:")] + void TrashItem (string itemIdentifier, Action completionHandler); + + [iOS (11,0)] + [Async] + [Export ("untrashItemWithIdentifier:toParentItemIdentifier:completionHandler:")] + void UntrashItem (string itemIdentifier, [NullAllowed] string parentItemIdentifier, Action completionHandler); + + [iOS (11,0)] + [Async] + [Export ("deleteItemWithIdentifier:completionHandler:")] + void DeleteItem (string itemIdentifier, Action completionHandler); + + [iOS (11,0)] + [Async] + [Export ("setLastUsedDate:forItemIdentifier:completionHandler:")] + void SetLastUsedDate ([NullAllowed] NSDate lastUsedDate, string itemIdentifier, Action completionHandler); + + [iOS (11,0)] + [Async] + [Export ("setTagData:forItemIdentifier:completionHandler:")] + void SetTagData ([NullAllowed] NSData tagData, string itemIdentifier, Action completionHandler); + + [iOS (11,0)] + [Async] + [Export ("setFavoriteRank:forItemIdentifier:completionHandler:")] + void SetFavoriteRank ([NullAllowed] NSNumber favoriteRank, string itemIdentifier, Action completionHandler); + + [iOS (11,0)] + [Export ("enumeratorForContainerItemIdentifier:error:")] + [return: NullAllowed] + XamCore.FileProvider.INSFileProviderEnumerator GetEnumerator (string containerItemIdentifier, out NSError error); + + // From NSFileProviderExtension (NSFileProviderThumbnailing) + + [iOS (11,0)] + [Export ("fetchThumbnailsForItemIdentifiers:requestedSize:perThumbnailCompletionHandler:completionHandler:")] + [Async] + NSProgress FetchThumbnails (NSString [] itemIdentifiers, CGSize size, NSFileProviderExtensionFetchThumbnailsHandler perThumbnailCompletionHandler, Action completionHandler); + + [Async] + [iOS (11,0)] + [Wrap ("FetchThumbnails (itemIdentifiers.GetConstants (), size, perThumbnailCompletionHandler, completionHandler)")] + NSProgress FetchThumbnails (NSFileProviderItemIdentifier [] itemIdentifiers, CGSize size, NSFileProviderExtensionFetchThumbnailsHandler perThumbnailCompletionHandler, Action completionHandler); + + // From NSFileProviderExtension (NSFileProviderMessaging) + + // Missing members -> https://bugzilla.xamarin.com/show_bug.cgi?id=58222 + // TODO: NSFileProviderMessageInterfaceName is not bound yet, comes from Foundation + //[iOS (11,0)] + //[Internal] + //[Export ("supportedMessageInterfaceNamesForItemWithIdentifier:")] + //NSFileProviderMessageInterfaceName[] GetSupportedMessageInterfaceNames (NSString identifier); + + //[iOS (11,0)] + //[Wrap ("GetSupportedMessageInterfaceNames (identifier.GetConstant ())")] + //NSFileProviderMessageInterfaceName[] GetSupportedMessageInterfaceNames (NSFileProviderItemIdentifier identifier); + + // TODO: NSFileProviderMessageInterface is not bound yet, comes from Foundation + //[iOS (11,0)] + //[Export ("protocolForMessageInterface:")] + //Protocol GetProtocol (NSFileProviderMessageInterface messageInterface); + + // TODO: NSFileProviderMessageInterface is not bound yet, comes from Foundation + //[iOS (11,0)] + //[Internal] + //[return: NullAllowed] + //[Export ("exportedObjectForMessageInterface:itemIdentifier:error:")] + //NSObject GetExportedObject (NSFileProviderMessageInterface messageInterface, NSString identifier, out NSError error); + + //[iOS (11,0)] + //[Wrap ("GetExportedObject (messageInterface, identifier.GetConstant (), out error)")] + //NSObject GetExportedObject (NSFileProviderMessageInterface messageInterface, NSFileProviderItemIdentifier identifier, out NSError error); +#endif } #endif // !WATCH diff --git a/tests/introspection/ApiSignatureTest.cs b/tests/introspection/ApiSignatureTest.cs index 82881018905a..bfd50cc1e95a 100644 --- a/tests/introspection/ApiSignatureTest.cs +++ b/tests/introspection/ApiSignatureTest.cs @@ -983,6 +983,10 @@ protected virtual bool IgnoreAsync (MethodInfo m) // It does not make sense for this API case "RequestData": return m.DeclaringType.Name == "PHAssetResourceManager"; + // It does not make sense for this API + case "Register": + case "SignalEnumerator": + return m.DeclaringType.Name == "NSFileProviderManager"; } return false; } diff --git a/tests/introspection/ApiTypoTest.cs b/tests/introspection/ApiTypoTest.cs index 86033723dfc6..ab059ac2a5f2 100644 --- a/tests/introspection/ApiTypoTest.cs +++ b/tests/introspection/ApiTypoTest.cs @@ -405,6 +405,7 @@ public virtual bool Skip (MemberInfo methodName, string typo) { "Unproject", "Uterance", "Unentitled", + "Untrash", "Utf", "Upce", "Uti", diff --git a/tests/introspection/iOS/iOSApiProtocolTest.cs b/tests/introspection/iOS/iOSApiProtocolTest.cs index 66cd77bf040d..37bee14364be 100644 --- a/tests/introspection/iOS/iOSApiProtocolTest.cs +++ b/tests/introspection/iOS/iOSApiProtocolTest.cs @@ -205,6 +205,7 @@ protected override bool Skip (Type type, string protocolName) case "HMTimeEvent": case "ILMessageFilterExtensionContext": // Conformance not in headers case "MSMessageLiveLayout": + case "NSFileProviderDomain": // Conformance not in headers return true; #if __WATCHOS__ case "CLKComplicationTemplate": @@ -338,6 +339,7 @@ protected override bool Skip (Type type, string protocolName) case "NSPropertyDescription": case "NSRelationshipDescription": case "MSMessageLiveLayout": + case "NSFileProviderDomain": // Conformance not in headers return true; #if __WATCHOS__ case "CLKComplicationTemplate": @@ -422,6 +424,7 @@ protected override bool Skip (Type type, string protocolName) case "ACAccountCredential": // b2: Conformance not in headers case "ILMessageFilterExtensionContext": // b2: Conformance not in headers case "HMCharacteristicEvent": // Selectors not available on 32 bit + case "NSFileProviderDomain": // Conformance not in headers return true; #if __WATCHOS__ diff --git a/tools/common/Frameworks.cs b/tools/common/Frameworks.cs index c61b3bfc0342..fda7d7b96812 100644 --- a/tools/common/Frameworks.cs +++ b/tools/common/Frameworks.cs @@ -251,6 +251,7 @@ public static Frameworks GetiOSFrameworks (Application app) { "IdentityLookup", "IdentityLookup", 11 }, { "CoreML", "CoreML", 11 }, { "Vision", "Vision", 11 }, + { "FileProvider", "FileProvider", 11 }, }; } return ios_frameworks;