Advertisement
architekt909

PlatformWKWebView.cs

Mar 10th, 2018
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.65 KB | None | 0 0
  1. using System;
  2. using System.Threading.Tasks;
  3. using CoreGraphics;
  4. using Foundation;
  5. using IdentityModel.OidcClient.Browser;
  6. using UIKit;
  7. using WebKit;
  8.  
  9. namespace Auth0.OidcClient
  10. {
  11.     // Replaces PlatformWebView
  12.     class PlatformWKWebView : WKNavigationDelegate, IWKUIDelegate, IBrowser, IWKScriptMessageHandler
  13.     {
  14.         private WKWebView _webView;
  15.         private readonly UIViewController _controller;
  16.         private readonly string _redirectUri;
  17.  
  18.         private class DisableZoomDelegate : UIScrollViewDelegate
  19.         {
  20.             public override UIView ViewForZoomingInScrollView(UIScrollView scrollView)
  21.             {
  22.                 return null;
  23.             }
  24.         }
  25.  
  26.         // See Auth0Client for a detailed explanation of these two parameters
  27.         public string JavascriptCallbackHandlerName { get; set; }
  28.         public string JavascriptOnLockHideEventName { get; set; }
  29.  
  30.         // If not specified, uses the controller's entire view frame
  31.         public CGRect WKWebViewFrame { get; set; } = CGRect.Null;
  32.  
  33.         // If true, prevents the web view from bouncing if you scroll and release
  34.         public bool DisableBouncing { get; set; }
  35.  
  36.         // If true, prevents the web view from being able to be zoomed in. This will also prevent zooming when the user types in a text field
  37.         public bool DisableZooming { get; set; }
  38.  
  39.         // If true, prevents the web view from being able to scroll at all
  40.         public bool DisableScrolling { get; set; }
  41.  
  42.         // If true, will automatically close the login window upon successfully logging in.
  43.         public bool AutoClose { get; set; }
  44.  
  45.         // A handler to be called (optionally) if the user cancels the login. Passes in the web view.
  46.         public Action<WKWebView> OnCancel { get; set; }
  47.  
  48.         // A handler to be called (optionally) upon successfully logging in. This is called right before auto closing of the view.
  49.         // If auto close is false, this is still called and could be used to customize the closing of the view. Passes in the web view.
  50.         public Action<WKWebView> OnSuccess { get; set; }
  51.  
  52.         public PlatformWKWebView(UIViewController controller, string redirectUri)
  53.         {
  54.             _controller = controller;
  55.             _redirectUri = redirectUri.ToLower();
  56.         }
  57.  
  58.         // Lets us respond to javascript postMessage calls. We'll use this to listen for the close button being pressed.
  59.         public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
  60.         {
  61.             var content = message.Body.ToString();
  62.             if (content.Equals(JavascriptOnLockHideEventName, StringComparison.OrdinalIgnoreCase))
  63.                 ActivityMediator.Instance.Send("UserCancel");
  64.         }
  65.  
  66.  
  67.         // Takes the place of overriding AppDelegate.OpenUrl
  68.         public override void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, Action<WKNavigationActionPolicy> decisionHandler)
  69.         {          
  70.             var url = navigationAction.Request.Url.ToString().ToLower();
  71.             if (url.StartsWith(_redirectUri, StringComparison.Ordinal))
  72.                 ActivityMediator.Instance.Send(navigationAction.Request.Url.AbsoluteString);
  73.             else
  74.                 decisionHandler(WKNavigationActionPolicy.Allow);
  75.         }      
  76.  
  77.         public Task<BrowserResult> InvokeAsync(BrowserOptions options)
  78.         {
  79.             if (string.IsNullOrWhiteSpace(options.StartUrl))
  80.             {
  81.                 throw new ArgumentException("Missing StartUrl", nameof(options));
  82.             }
  83.  
  84.             if (string.IsNullOrWhiteSpace(options.EndUrl))
  85.             {
  86.                 throw new ArgumentException("Missing EndUrl", nameof(options));
  87.             }
  88.  
  89.             // must be able to wait for the intent to be finished to continue
  90.             // with setting the task result
  91.             var tcs = new TaskCompletionSource<BrowserResult>();           
  92.  
  93.             var config = new WKWebViewConfiguration
  94.             {
  95.                 Preferences = new WKPreferences { JavaScriptEnabled = true }
  96.             };
  97.  
  98.             // Listen for the user clicking the close button
  99.             if (!string.IsNullOrEmpty(JavascriptOnLockHideEventName) && !string.IsNullOrEmpty(JavascriptCallbackHandlerName))
  100.             {
  101.                 var cc = new WKUserContentController();
  102.                 cc.AddScriptMessageHandler(this, JavascriptCallbackHandlerName);
  103.                 config.UserContentController = cc;
  104.             }
  105.  
  106.             // Make our browser view
  107.             _webView = new WKWebView(WKWebViewFrame == CGRect.Null ? _controller.View.Frame : WKWebViewFrame, config);
  108.             _webView.UIDelegate = this;
  109.             _webView.NavigationDelegate = this;
  110.  
  111.             if (DisableBouncing)
  112.                 _webView.ScrollView.Bounces = false;
  113.  
  114.             if (DisableScrolling)
  115.                 _webView.ScrollView.ScrollEnabled = false;
  116.  
  117.             if (DisableZooming)
  118.                 _webView.ScrollView.Delegate = new DisableZoomDelegate();
  119.  
  120.  
  121.             void Callback(string response)
  122.             {
  123.                 // remove handler
  124.                 ActivityMediator.Instance.ActivityMessageReceived -= Callback;
  125.  
  126.                 if (DisableZooming)
  127.                     _webView.ScrollView.Delegate = null;
  128.  
  129.                 if (response == "UserCancel")
  130.                 {                  
  131.                     tcs.SetResult(new BrowserResult {ResultType = BrowserResultType.UserCancel});
  132.  
  133.                     OnCancel?.Invoke(_webView);
  134.  
  135.                     if (AutoClose)
  136.                     {
  137.                         _webView.RemoveFromSuperview();
  138.                         UIApplication.SharedApplication.KeyWindow.SetNeedsLayout();
  139.                     }
  140.                 }
  141.                 else
  142.                 {
  143.                     // set result
  144.                     tcs.SetResult(new BrowserResult
  145.                     {
  146.                         Response = response,
  147.                         ResultType = BrowserResultType.Success
  148.                     });
  149.  
  150.                     // Close web view
  151.                     OnSuccess?.Invoke(_webView);
  152.  
  153.                     if (AutoClose)
  154.                     {
  155.                         _webView.RemoveFromSuperview();
  156.                         UIApplication.SharedApplication.KeyWindow.SetNeedsLayout();
  157.                     }                  
  158.                 }
  159.             }
  160.  
  161.             // attach handler
  162.             ActivityMediator.Instance.ActivityMessageReceived += Callback;
  163.  
  164.             // launch browser
  165.             _controller.Add(_webView);
  166.             _webView.LoadRequest(new NSUrlRequest(new NSUrl(options.StartUrl)));
  167.  
  168.             // need an intent to be triggered when browsing to the "io.identitymodel.native://callback"
  169.             // scheme/URI => CallbackInterceptorActivity
  170.             return tcs.Task;
  171.         }
  172.  
  173.     }
  174. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement