From 743c959354fa0afdbe27070378788966b95ec7a0 Mon Sep 17 00:00:00 2001 From: Alex Soto Date: Thu, 12 Mar 2020 14:47:07 -0400 Subject: [PATCH] [WebAuthenticator] Break iOS 13 dependency on WebAuthenticator WebAuthenticator's `ContextProvider` object implements `IASWebAuthenticationPresentationContextProviding` interface which is iOS 13 and up, since this is more of a native runtime requirement we can use the AdoptsAttribute to tell the Objective-C runtime via the `conformsToProtocol:` check that our object does conform to the `ASWebAuthenticationPresentationContextProviding` protocol. There is no problem with iOS versions < 13.0 because this Objective-C runtime check (runtime asking for conformance via `conformsToProtocol:`) will only happen on iOS 13 and up. --- .../WebAuthenticator.ios.tvos.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Xamarin.Essentials/WebAuthenticator/WebAuthenticator.ios.tvos.cs b/Xamarin.Essentials/WebAuthenticator/WebAuthenticator.ios.tvos.cs index 2ff8e66dc..eae90b326 100644 --- a/Xamarin.Essentials/WebAuthenticator/WebAuthenticator.ios.tvos.cs +++ b/Xamarin.Essentials/WebAuthenticator/WebAuthenticator.ios.tvos.cs @@ -14,6 +14,13 @@ namespace Xamarin.Essentials { public static partial class WebAuthenticator { +#if __IOS__ + [System.Runtime.InteropServices.DllImport(ObjCRuntime.Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSend")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Required for iOS Export")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Required for iOS Export")] + static extern void void_objc_msgSend_IntPtr(IntPtr receiver, IntPtr selector, IntPtr arg1); +#endif + static TaskCompletionSource tcsResponse; static UIViewController currentViewController; static Uri redirectUri; @@ -49,7 +56,13 @@ void AuthSessionCallback(NSUrl cbUrl, NSError error) if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0)) { var was = new ASWebAuthenticationSession(new NSUrl(url.OriginalString), scheme, AuthSessionCallback); - was.PresentationContextProvider = new ContextProvider(Platform.GetCurrentWindow()); + + if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0)) + { + var ctx = new ContextProvider(Platform.GetCurrentWindow()); + void_objc_msgSend_IntPtr(was.Handle, ObjCRuntime.Selector.GetHandle("setPresentationContextProvider:"), ctx.Handle); + } + was.Start(); return await tcsResponse.Task; } @@ -175,13 +188,15 @@ public override void DidFinish(SFSafariViewController controller) => DidFinishHandler?.Invoke(controller); } - class ContextProvider : NSObject, IASWebAuthenticationPresentationContextProviding + [ObjCRuntime.Adopts("ASWebAuthenticationPresentationContextProviding")] + class ContextProvider : NSObject { public ContextProvider(UIWindow window) => Window = window; public UIWindow Window { get; private set; } + [Export("presentationAnchorForWebAuthenticationSession:")] public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session) => Window; }