@@ -26,6 +26,99 @@ extern "C" size_t LWE_EXPORT createWebViewInstance(
2626 const std::function<void(::LWE::WebContainer*, bool isRendered)>&
2727 renderedCb);
2828
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+
29122std::string ExtractStringFromMap (const flutter::EncodableValue& arguments,
30123 const char * key) {
31124 if (std::holds_alternative<flutter::EncodableMap>(arguments)) {
@@ -63,7 +156,9 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int viewId,
63156 webViewInstance_(nullptr ),
64157 width_(width),
65158 height_(height),
66- tbmSurface_(nullptr ) {
159+ tbmSurface_(nullptr ),
160+ isMouseLButtonDown_(false ),
161+ hasNavigationDelegate_(false ) {
67162 SetTextureId (FlutterRegisterExternalTexture (textureRegistrar_));
68163 InitWebView ();
69164
@@ -82,6 +177,14 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int viewId,
82177 currentUrl_ = " about:blank" ;
83178 }
84179
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+
85188 auto names = params[flutter::EncodableValue (" javascriptChannelNames" )];
86189 if (std::holds_alternative<flutter::EncodableList>(names)) {
87190 auto nameList = std::get<flutter::EncodableList>(names);
@@ -99,8 +202,7 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int viewId,
99202 map.insert (
100203 std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
101204 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);
104206 channel_->InvokeMethod (" onPageStarted" , std::move (args));
105207 });
106208 webViewInstance_->RegisterOnPageLoadedHandler (
@@ -110,14 +212,81 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int viewId,
110212 map.insert (
111213 std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
112214 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);
115238 channel_->InvokeMethod (" onPageFinished" , std::move (args));
116239 });
117240
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+
118264 webViewInstance_->LoadURL (currentUrl_);
119265}
120266
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+
121290/* *
122291 * Added as a JavaScript interface to the WebView for any JavaScript channel
123292 * that the Dart code sets up.
@@ -155,8 +324,10 @@ std::string WebView::GetChannelName() {
155324void WebView::Dispose () {
156325 FlutterUnregisterExternalTexture (textureRegistrar_, GetTextureId ());
157326
158- webViewInstance_->Destroy ();
159- webViewInstance_ = nullptr ;
327+ if (webViewInstance_) {
328+ webViewInstance_->Destroy ();
329+ webViewInstance_ = nullptr ;
330+ }
160331}
161332
162333void WebView::Resize (double width, double height) {
0 commit comments