@@ -26,6 +26,99 @@ extern "C" size_t LWE_EXPORT createWebViewInstance(
26
26
const std::function<void(::LWE::WebContainer*, bool isRendered)>&
27
27
renderedCb);
28
28
29
+ template <typename T = flutter::EncodableValue>
30
+ class NavigationRequestResult : public flutter ::MethodResult<T> {
31
+ public:
32
+ NavigationRequestResult (std::string url, WebView* webView)
33
+ : url_(url), webView_(webView) {}
34
+
35
+ void SuccessInternal (const T* shouldLoad) override {
36
+ if (std::holds_alternative<bool >(*shouldLoad)) {
37
+ if (std::get<bool >(*shouldLoad)) {
38
+ LoadUrl ();
39
+ }
40
+ }
41
+ }
42
+
43
+ void ErrorInternal (const std::string& error_code,
44
+ const std::string& error_message,
45
+ const T* error_details) override {
46
+ throw std::invalid_argument (" navigationRequest calls must succeed [code:" +
47
+ error_code + " ][msg:" + error_message + " ]" );
48
+ }
49
+
50
+ void NotImplementedInternal () override {
51
+ throw std::invalid_argument (
52
+ " navigationRequest must be implemented by the webview method channel" );
53
+ }
54
+
55
+ private:
56
+ void LoadUrl () {
57
+ if (webView_ && webView_->GetWebViewInstance ()) {
58
+ webView_->GetWebViewInstance ()->LoadURL (url_);
59
+ }
60
+ }
61
+
62
+ std::string url_;
63
+ WebView* webView_;
64
+ };
65
+
66
+ enum RequestErrorType {
67
+ NoError,
68
+ UnknownError,
69
+ HostLookupError,
70
+ UnsupportedAuthSchemeError,
71
+ AuthenticationError,
72
+ ProxyAuthenticationError,
73
+ ConnectError,
74
+ IOError,
75
+ TimeoutError,
76
+ RedirectLoopError,
77
+ UnsupportedSchemeError,
78
+ FailedSSLHandshakeError,
79
+ BadURLError,
80
+ FileError,
81
+ FileNotFoundError,
82
+ TooManyRequestError,
83
+ };
84
+
85
+ static std::string ErrorCodeToString (int errorCode) {
86
+ switch (errorCode) {
87
+ case RequestErrorType::AuthenticationError:
88
+ return " authentication" ;
89
+ case RequestErrorType::BadURLError:
90
+ return " badUrl" ;
91
+ case RequestErrorType::ConnectError:
92
+ return " connect" ;
93
+ case RequestErrorType::FailedSSLHandshakeError:
94
+ return " failedSslHandshake" ;
95
+ case RequestErrorType::FileError:
96
+ return " file" ;
97
+ case RequestErrorType::FileNotFoundError:
98
+ return " fileNotFound" ;
99
+ case RequestErrorType::HostLookupError:
100
+ return " hostLookup" ;
101
+ case RequestErrorType::IOError:
102
+ return " io" ;
103
+ case RequestErrorType::ProxyAuthenticationError:
104
+ return " proxyAuthentication" ;
105
+ case RequestErrorType::RedirectLoopError:
106
+ return " redirectLoop" ;
107
+ case RequestErrorType::TimeoutError:
108
+ return " timeout" ;
109
+ case RequestErrorType::TooManyRequestError:
110
+ return " tooManyRequests" ;
111
+ case RequestErrorType::UnknownError:
112
+ return " unknown" ;
113
+ case RequestErrorType::UnsupportedAuthSchemeError:
114
+ return " unsupportedAuthScheme" ;
115
+ case RequestErrorType::UnsupportedSchemeError:
116
+ return " unsupportedScheme" ;
117
+ }
118
+ std::string message = " Could not find a string for errorCode: " + errorCode;
119
+ throw std::invalid_argument (message);
120
+ }
121
+
29
122
std::string ExtractStringFromMap (const flutter::EncodableValue& arguments,
30
123
const char * key) {
31
124
if (std::holds_alternative<flutter::EncodableMap>(arguments)) {
@@ -63,7 +156,9 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int viewId,
63
156
webViewInstance_(nullptr ),
64
157
width_(width),
65
158
height_(height),
66
- tbmSurface_(nullptr ) {
159
+ tbmSurface_(nullptr ),
160
+ isMouseLButtonDown_(false ),
161
+ hasNavigationDelegate_(false ) {
67
162
SetTextureId (FlutterRegisterExternalTexture (textureRegistrar_));
68
163
InitWebView ();
69
164
@@ -82,6 +177,14 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int viewId,
82
177
currentUrl_ = " about:blank" ;
83
178
}
84
179
180
+ auto settings = params[flutter::EncodableValue (" settings" )];
181
+ if (std::holds_alternative<flutter::EncodableMap>(settings)) {
182
+ auto settingList = std::get<flutter::EncodableMap>(settings);
183
+ if (settingList.size () > 0 ) {
184
+ ApplySettings (settingList);
185
+ }
186
+ }
187
+
85
188
auto names = params[flutter::EncodableValue (" javascriptChannelNames" )];
86
189
if (std::holds_alternative<flutter::EncodableList>(names)) {
87
190
auto nameList = std::get<flutter::EncodableList>(names);
@@ -99,8 +202,7 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int viewId,
99
202
map.insert (
100
203
std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
101
204
flutter::EncodableValue (" url" ), flutter::EncodableValue (url)));
102
- std::unique_ptr<flutter::EncodableValue> args =
103
- std::make_unique<flutter::EncodableValue>(map);
205
+ auto args = std::make_unique<flutter::EncodableValue>(map);
104
206
channel_->InvokeMethod (" onPageStarted" , std::move (args));
105
207
});
106
208
webViewInstance_->RegisterOnPageLoadedHandler (
@@ -110,14 +212,81 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int viewId,
110
212
map.insert (
111
213
std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
112
214
flutter::EncodableValue (" url" ), flutter::EncodableValue (url)));
113
- std::unique_ptr<flutter::EncodableValue> args =
114
- std::make_unique<flutter::EncodableValue>(map);
215
+ auto args = std::make_unique<flutter::EncodableValue>(map);
216
+ channel_->InvokeMethod (" onPageFinished" , std::move (args));
217
+ });
218
+ webViewInstance_->RegisterOnReceivedErrorHandler (
219
+ [this ](LWE::WebContainer* container, LWE::ResourceError e) {
220
+ flutter::EncodableMap map;
221
+ map.insert (
222
+ std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
223
+ flutter::EncodableValue (" errorCode" ),
224
+ flutter::EncodableValue (e.GetErrorCode ())));
225
+ map.insert (
226
+ std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
227
+ flutter::EncodableValue (" description" ),
228
+ flutter::EncodableValue (e.GetDescription ())));
229
+ map.insert (
230
+ std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
231
+ flutter::EncodableValue (" errorType" ),
232
+ flutter::EncodableValue (ErrorCodeToString (e.GetErrorCode ()))));
233
+ map.insert (
234
+ std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
235
+ flutter::EncodableValue (" failingUrl" ),
236
+ flutter::EncodableValue (e.GetUrl ())));
237
+ auto args = std::make_unique<flutter::EncodableValue>(map);
115
238
channel_->InvokeMethod (" onPageFinished" , std::move (args));
116
239
});
117
240
241
+ webViewInstance_->RegisterShouldOverrideUrlLoadingHandler (
242
+ [this ](LWE::WebContainer* view, const std::string& url) -> bool {
243
+ if (!hasNavigationDelegate_) {
244
+ return false ;
245
+ }
246
+ flutter::EncodableMap map;
247
+ map.insert (
248
+ std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
249
+ flutter::EncodableValue (" url" ), flutter::EncodableValue (url)));
250
+ map.insert (
251
+ std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
252
+ flutter::EncodableValue (" isForMainFrame" ),
253
+ flutter::EncodableValue (true )));
254
+ auto args = std::make_unique<flutter::EncodableValue>(map);
255
+ auto onResult =
256
+ std::make_unique<NavigationRequestResult<flutter::EncodableValue>>(
257
+ url, this );
258
+ channel_->InvokeMethod (" navigationRequest" , std::move (args),
259
+ std::move (onResult));
260
+
261
+ return true ;
262
+ });
263
+
118
264
webViewInstance_->LoadURL (currentUrl_);
119
265
}
120
266
267
+ void WebView::ApplySettings (flutter::EncodableMap settings) {
268
+ for (auto const & [key, val] : settings) {
269
+ if (std::holds_alternative<std::string>(key)) {
270
+ std::string k = std::get<std::string>(key);
271
+ if (" jsMode" == k) {
272
+ // TODO: Not implemented
273
+ } else if (" hasNavigationDelegate" == k) {
274
+ if (std::holds_alternative<bool >(val)) {
275
+ hasNavigationDelegate_ = std::get<bool >(val);
276
+ }
277
+ } else if (" debuggingEnabled" == k) {
278
+ // TODO: Not implemented
279
+ } else if (" gestureNavigationEnabled" == k) {
280
+ // TODO: Not implemented
281
+ } else if (" userAgent" == k) {
282
+ // TODO: Not implemented
283
+ } else {
284
+ throw std::invalid_argument (" Unknown WebView setting: " + k);
285
+ }
286
+ }
287
+ }
288
+ }
289
+
121
290
/* *
122
291
* Added as a JavaScript interface to the WebView for any JavaScript channel
123
292
* that the Dart code sets up.
@@ -155,8 +324,10 @@ std::string WebView::GetChannelName() {
155
324
void WebView::Dispose () {
156
325
FlutterUnregisterExternalTexture (textureRegistrar_, GetTextureId ());
157
326
158
- webViewInstance_->Destroy ();
159
- webViewInstance_ = nullptr ;
327
+ if (webViewInstance_) {
328
+ webViewInstance_->Destroy ();
329
+ webViewInstance_ = nullptr ;
330
+ }
160
331
}
161
332
162
333
void WebView::Resize (double width, double height) {
0 commit comments