Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit

Permalink
Extracted WebViewRenderer.WebClient to FormsWebViewClient, moved Send…
Browse files Browse the repository at this point in the history
…Navigating call from ShouldOverrideUrlLoading to OnPageStarted
  • Loading branch information
jcmanke committed Sep 13, 2018
1 parent 8a91dd9 commit d688969
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 83 deletions.
96 changes: 96 additions & 0 deletions Xamarin.Forms.Platform.Android/Renderers/FormsWebViewClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Webkit;
using Android.Widget;

namespace Xamarin.Forms.Platform.Android
{
public class FormsWebViewClient : WebViewClient
{
WebNavigationResult _navigationResult = WebNavigationResult.Success;
WebViewRenderer _renderer;

public FormsWebViewClient(WebViewRenderer renderer)
{
if (renderer == null)
throw new ArgumentNullException("renderer");
_renderer = renderer;
}

public override void OnPageStarted(global::Android.Webkit.WebView view, string url, Bitmap favicon)
{
if (_renderer.Element == null || url == WebViewRenderer.AssetBaseUrl)
return;

var args = new WebNavigatingEventArgs(WebNavigationEvent.NewPage, new UrlWebViewSource { Url = url }, url);

_renderer.ElementController.SendNavigating(args);
_navigationResult = WebNavigationResult.Success;

_renderer.UpdateCanGoBackForward();

if (args.Cancel)
{
_renderer.Control.StopLoading();
}
else
{
base.OnPageStarted(view, url, favicon);
}
}

public override void OnPageFinished(global::Android.Webkit.WebView view, string url)
{
if (_renderer.Element == null || url == WebViewRenderer.AssetBaseUrl)
return;

var source = new UrlWebViewSource { Url = url };
_renderer.IgnoreSourceChanges = true;
_renderer.ElementController.SetValueFromRenderer(WebView.SourceProperty, source);
_renderer.IgnoreSourceChanges = false;

var args = new WebNavigatedEventArgs(WebNavigationEvent.NewPage, source, url, _navigationResult);

_renderer.ElementController.SendNavigated(args);

_renderer.UpdateCanGoBackForward();

base.OnPageFinished(view, url);
}

[Obsolete("OnReceivedError is obsolete as of version 2.3.0. This method was deprecated in API level 23.")]
public override void OnReceivedError(global::Android.Webkit.WebView view, ClientError errorCode, string description, string failingUrl)
{
_navigationResult = WebNavigationResult.Failure;
if (errorCode == ClientError.Timeout)
_navigationResult = WebNavigationResult.Timeout;
#pragma warning disable 618
base.OnReceivedError(view, errorCode, description, failingUrl);
#pragma warning restore 618
}

public override void OnReceivedError(global::Android.Webkit.WebView view, IWebResourceRequest request, WebResourceError error)
{
_navigationResult = WebNavigationResult.Failure;
if (error.ErrorCode == ClientError.Timeout)
_navigationResult = WebNavigationResult.Timeout;
base.OnReceivedError(view, request, error);
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
_renderer = null;
}
}
}
103 changes: 20 additions & 83 deletions Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ namespace Xamarin.Forms.Platform.Android
{
public class WebViewRenderer : ViewRenderer<WebView, AWebView>, IWebViewDelegate
{
bool _ignoreSourceChanges;
public const string AssetBaseUrl = "file:///android_asset/";

FormsWebViewClient _webViewClient;
FormsWebChromeClient _webChromeClient;

IWebViewController ElementController => Element;
public IWebViewController ElementController => Element;
public bool IgnoreSourceChanges { get; set; }

public WebViewRenderer(Context context) : base(context)
{
Expand All @@ -33,7 +36,7 @@ public WebViewRenderer()

public void LoadHtml(string html, string baseUrl)
{
Control.LoadDataWithBaseURL(baseUrl == null ? "file:///android_asset/" : baseUrl, html, "text/html", "UTF-8", null);
Control.LoadDataWithBaseURL(baseUrl ?? AssetBaseUrl, html, "text/html", "UTF-8", null);
}

public void LoadUrl(string url)
Expand All @@ -47,19 +50,25 @@ protected override void Dispose(bool disposing)
{
if (Element != null)
{
if (Control != null)
Control.StopLoading();
Control?.StopLoading();

ElementController.EvalRequested -= OnEvalRequested;
ElementController.GoBackRequested -= OnGoBackRequested;
ElementController.GoForwardRequested -= OnGoForwardRequested;

_webViewClient?.Dispose();
_webChromeClient?.Dispose();
}
}

base.Dispose(disposing);
}

protected virtual FormsWebViewClient GetFormsWebViewClient()
{
return new FormsWebViewClient(this);
}

protected virtual FormsWebChromeClient GetFormsWebChromeClient()
{
return new FormsWebChromeClient();
Expand All @@ -85,7 +94,9 @@ protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
#pragma warning disable 618 // This can probably be replaced with LinearLayout(LayoutParams.MatchParent, LayoutParams.MatchParent); just need to test that theory
webView.LayoutParameters = new global::Android.Widget.AbsoluteLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent, 0, 0);
#pragma warning restore 618
webView.SetWebViewClient(new WebClient(this));

_webViewClient = GetFormsWebViewClient();
webView.SetWebViewClient(_webViewClient);

_webChromeClient = GetFormsWebChromeClient();
_webChromeClient.SetContext(Context as Activity);
Expand Down Expand Up @@ -136,11 +147,10 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE

void Load()
{
if (_ignoreSourceChanges)
if (IgnoreSourceChanges)
return;

if (Element.Source != null)
Element.Source.Load(this);
Element.Source?.Load(this);

UpdateCanGoBackForward();
}
Expand Down Expand Up @@ -175,7 +185,7 @@ void OnGoForwardRequested(object sender, EventArgs eventArgs)
UpdateCanGoBackForward();
}

void UpdateCanGoBackForward()
public void UpdateCanGoBackForward()
{
if (Element == null || Control == null)
return;
Expand All @@ -191,79 +201,6 @@ void UpdateMixedContentMode()
}
}

class WebClient : WebViewClient
{
WebNavigationResult _navigationResult = WebNavigationResult.Success;
WebViewRenderer _renderer;

public WebClient(WebViewRenderer renderer)
{
if (renderer == null)
throw new ArgumentNullException("renderer");
_renderer = renderer;
}

public override void OnPageFinished(AWebView view, string url)
{
if (_renderer.Element == null || url == "file:///android_asset/")
return;

var source = new UrlWebViewSource { Url = url };
_renderer._ignoreSourceChanges = true;
_renderer.ElementController.SetValueFromRenderer(WebView.SourceProperty, source);
_renderer._ignoreSourceChanges = false;

var args = new WebNavigatedEventArgs(WebNavigationEvent.NewPage, source, url, _navigationResult);

_renderer.ElementController.SendNavigated(args);

_renderer.UpdateCanGoBackForward();

base.OnPageFinished(view, url);
}

[Obsolete("OnReceivedError is obsolete as of version 2.3.0. This method was deprecated in API level 23.")]
public override void OnReceivedError(AWebView view, ClientError errorCode, string description, string failingUrl)
{
_navigationResult = WebNavigationResult.Failure;
if (errorCode == ClientError.Timeout)
_navigationResult = WebNavigationResult.Timeout;
#pragma warning disable 618
base.OnReceivedError(view, errorCode, description, failingUrl);
#pragma warning restore 618
}

public override void OnReceivedError(AWebView view, IWebResourceRequest request, WebResourceError error)
{
_navigationResult = WebNavigationResult.Failure;
if (error.ErrorCode == ClientError.Timeout)
_navigationResult = WebNavigationResult.Timeout;
base.OnReceivedError(view, request, error);
}

[Obsolete]
public override bool ShouldOverrideUrlLoading(AWebView view, string url)
{
if (_renderer.Element == null)
return true;

var args = new WebNavigatingEventArgs(WebNavigationEvent.NewPage, new UrlWebViewSource { Url = url }, url);

_renderer.ElementController.SendNavigating(args);
_navigationResult = WebNavigationResult.Success;

_renderer.UpdateCanGoBackForward();
return args.Cancel;
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
_renderer = null;
}
}

class JavascriptResult : Java.Lang.Object, IValueCallback
{
TaskCompletionSource<string> source;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
<Compile Include="GetDesiredSizeDelegate.cs" />
<Compile Include="IDeviceInfoProvider.cs" />
<Compile Include="ITabStop.cs" />
<Compile Include="Renderers\FormsWebViewClient.cs" />
<Compile Include="Renderers\IImageViewHandler.cs" />
<Compile Include="InnerGestureListener.cs" />
<Compile Include="InnerScaleListener.cs" />
Expand Down

0 comments on commit d688969

Please sign in to comment.