-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathIssue16032.cs
More file actions
174 lines (143 loc) · 4.82 KB
/
Copy pathIssue16032.cs
File metadata and controls
174 lines (143 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#if ANDROID
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using AWebView = Android.Webkit.WebView;
using IWebResourceRequest = Android.Webkit.IWebResourceRequest;
using Microsoft.Maui.Platform;
using WebResourceResponse = Android.Webkit.WebResourceResponse;
namespace Maui.Controls.Sample.Issues
{
[Issue(IssueTracker.Github, 16032, "Improve the customization of WebView on Android", PlatformAffected.Android, isInternetRequired: true)]
public class Issue16032 : ContentPage
{
public Issue16032()
{
Content = new VerticalStackLayout()
{
new Issue16032WebView
{
Background = new SolidPaint(Colors.Red),
WidthRequest = 300,
HeightRequest = 300
}
};
}
class Issue16032WebView : WebView, IPropertyMapperView
{
PropertyMapper<Issue16032WebView, WebViewHandler> TestMapper =
new PropertyMapper<Issue16032WebView, WebViewHandler>(WebViewHandler.Mapper);
public Issue16032WebView()
{
TestMapper.ModifyMapping(
"WebViewClient",
(handler, view, setter) =>
{
WebClient ??= new CustomWebClient((WebViewHandler)handler);
handler.PlatformView.SetWebViewClient(WebClient);
});
}
protected async override void OnHandlerChanged()
{
if (Handler is not WebViewHandler webViewHandler)
{
return;
}
var platformWebView = webViewHandler.PlatformView;
platformWebView.Settings.AllowFileAccess = true;
Source = new UrlWebViewSource { Url = "extracontent.html" };
var tcsLoaded = new TaskCompletionSource<bool>();
var tcsNavigating = new TaskCompletionSource();
var tcsRequested = new TaskCompletionSource();
// if the timeout happens, cancel everything
var pageLoadTimeout = TimeSpan.FromSeconds(30);
var ctsTimeout = new CancellationTokenSource(pageLoadTimeout);
ctsTimeout.Token.Register(() =>
{
tcsRequested.TrySetException(new TimeoutException($"Failed to request the image"));
tcsNavigating.TrySetException(new TimeoutException($"Failed to navigate to the loaded page"));
tcsLoaded.TrySetException(new TimeoutException($"Failed to load HTML"));
});
// attach some event handlers to track things
var navigatingCount = 0;
Navigating += ((sender, args) =>
{
navigatingCount++;
if (args.Url == "file:///android_asset/extracontent.html")
tcsNavigating.TrySetResult();
});
var shouldRequestCount = 0;
ShouldInterceptRequestDelegate = new((view, request) =>
{
shouldRequestCount++;
if (request.Url.ToString().StartsWith("https://raw.githubusercontent.com/dotnet/maui/4c096c1f17e9a23bf3961ba5778d3936039ad881/Assets/icon.png"))
tcsRequested.TrySetResult();
});
// set up a task to wait for the page to load
Navigated += (sender, args) =>
{
// Set success when we have a successful nav result
if (args.Result == WebNavigationResult.Success && args.Url == "file:///android_asset/extracontent.html")
tcsLoaded.TrySetResult(args.Result == WebNavigationResult.Success);
};
string failureMessage = String.Empty;
try
{
if (WebClient is not CustomWebClient)
{
throw new Exception("CustomWebClient was not set");
}
// wait for the navigation to complete
await tcsNavigating.Task;
if (navigatingCount < 1)
{
throw new Exception("Navigating event did not fire");
}
if ((!await tcsLoaded.Task))
{
throw new Exception("HTML Source Failed to Load");
}
// wait for the image to be requested
await tcsRequested.Task;
if (shouldRequestCount != 1)
{
throw new Exception("only 1 request for the image to load");
}
}
catch(Exception ex)
{
failureMessage = ex.Message;
}
if (String.IsNullOrEmpty(failureMessage))
{
((VerticalStackLayout)Parent).Insert(0, new Label { Text = "All Expectations Have Been Met", AutomationId = "Success" });
}
else
{
((VerticalStackLayout)Parent).Insert(0, new Label { Text = failureMessage });
}
}
PropertyMapper IPropertyMapperView.GetPropertyMapperOverrides() => TestMapper;
CustomWebClient WebClient { get; set; }
public Action<AWebView, IWebResourceRequest> ShouldInterceptRequestDelegate { get; set; }
class CustomWebClient : MauiWebViewClient
{
WebViewHandler _handler;
public CustomWebClient(WebViewHandler handler)
: base(handler)
{
_handler = handler;
}
public override WebResourceResponse ShouldInterceptRequest(AWebView view, IWebResourceRequest request)
{
if (_handler.VirtualView is Issue16032WebView customWebView)
customWebView.ShouldInterceptRequestDelegate(view, request);
return base.ShouldInterceptRequest(view, request);
}
}
}
}
}
#endif