diff --git a/flutter_inappwebview_platform_interface/lib/src/in_app_browser/platform_in_app_browser.dart b/flutter_inappwebview_platform_interface/lib/src/in_app_browser/platform_in_app_browser.dart index 6574d899..1af48a02 100755 --- a/flutter_inappwebview_platform_interface/lib/src/in_app_browser/platform_in_app_browser.dart +++ b/flutter_inappwebview_platform_interface/lib/src/in_app_browser/platform_in_app_browser.dart @@ -518,7 +518,7 @@ abstract class PlatformInAppBrowserEvents { ///- Android native WebView ([Official API - WebViewClient.onPageStarted](https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap))) ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview)) ///- MacOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview)) - ///- Windows ([Official API - IWebView2WebView.add_NavigationStarting](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationstarting)) + ///- Windows ([Official API - ICoreWebView2.add_NavigationStarting](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationstarting)) void onLoadStart(WebUri? url) {} ///Event fired when the [PlatformInAppBrowser] finishes loading an [url]. @@ -527,7 +527,7 @@ abstract class PlatformInAppBrowserEvents { ///- Android native WebView ([Official API - WebViewClient.onPageFinished](https://developer.android.com/reference/android/webkit/WebViewClient#onPageFinished(android.webkit.WebView,%20java.lang.String))) ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview)) ///- MacOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview)) - ///- Windows ([Official API - IWebView2WebView.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) + ///- Windows ([Official API - ICoreWebView2.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) void onLoadStop(WebUri? url) {} ///Use [onReceivedError] instead. @@ -540,7 +540,7 @@ abstract class PlatformInAppBrowserEvents { ///- Android native WebView ([Official API - WebViewClient.onReceivedError](https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedError(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceError))) ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455623-webview)) ///- MacOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455623-webview)) - ///- Windows ([Official API - IWebView2WebView.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) + ///- Windows ([Official API - ICoreWebView2.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) void onReceivedError(WebResourceRequest request, WebResourceError error) {} ///Use [onReceivedHttpError] instead. @@ -559,7 +559,7 @@ abstract class PlatformInAppBrowserEvents { ///- Android native WebView ([Official API - WebViewClient.onReceivedHttpError](https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpError(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceResponse))) ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview)) ///- MacOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview)) - ///- Windows ([Official API - IWebView2WebView.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) + ///- Windows ([Official API - ICoreWebView2.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) void onReceivedHttpError( WebResourceRequest request, WebResourceResponse errorResponse) {} @@ -899,7 +899,7 @@ abstract class PlatformInAppBrowserEvents { ///- Android native WebView ([Official API - WebViewClient.doUpdateVisitedHistory](https://developer.android.com/reference/android/webkit/WebViewClient#doUpdateVisitedHistory(android.webkit.WebView,%20java.lang.String,%20boolean))) ///- iOS ///- MacOS - ///- Windows ([Official API - IWebView2WebView.add_HistoryChanged](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#add_historychanged)) + ///- Windows ([Official API - ICoreWebView2.add_HistoryChanged](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#add_historychanged)) void onUpdateVisitedHistory(WebUri? url, bool? isReload) {} ///Use [onPrintRequest] instead @@ -969,7 +969,7 @@ abstract class PlatformInAppBrowserEvents { ///- Android native WebView ([Official API - WebChromeClient.onReceivedTitle](https://developer.android.com/reference/android/webkit/WebChromeClient#onReceivedTitle(android.webkit.WebView,%20java.lang.String))) ///- iOS ///- MacOS - ///- Windows ([Official API - IWebView2WebView.add_DocumentTitleChanged](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#add_documenttitlechanged)) + ///- Windows ([Official API - ICoreWebView2.add_DocumentTitleChanged](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#add_documenttitlechanged)) void onTitleChanged(String? title) {} ///Event fired to respond to the results of an over-scroll operation. diff --git a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_inappwebview_controller.dart b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_inappwebview_controller.dart index 1276f2b6..c38542ec 100644 --- a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_inappwebview_controller.dart +++ b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_inappwebview_controller.dart @@ -134,7 +134,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- iOS ([Official API - WKWebView.url](https://developer.apple.com/documentation/webkit/wkwebview/1415005-url)) ///- MacOS ([Official API - WKWebView.url](https://developer.apple.com/documentation/webkit/wkwebview/1415005-url)) ///- Web - ///- Windows ([Official API - IWebView2WebView.get_Source](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#get_source)) + ///- Windows ([Official API - ICoreWebView2.get_Source](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#get_source)) ///{@endtemplate} Future getUrl() { throw UnimplementedError( @@ -151,7 +151,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- iOS ([Official API - WKWebView.title](https://developer.apple.com/documentation/webkit/wkwebview/1415015-title)) ///- MacOS ([Official API - WKWebView.title](https://developer.apple.com/documentation/webkit/wkwebview/1415015-title)) ///- Web - ///- Windows ([Official API - IWebView2WebView.get_DocumentTitle](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#get_documenttitle)) + ///- Windows ([Official API - ICoreWebView2.get_DocumentTitle](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#get_documenttitle)) ///{@endtemplate} Future getTitle() { throw UnimplementedError( @@ -274,11 +274,14 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///Specify a directory to give WebView permission to read additional files in the specified directory. ///**NOTE**: available only on iOS and MacOS. /// + ///**NOTE for Windows**: only the [data] parameter is used. + /// ///**Officially Supported Platforms/Implementations**: ///- Android native WebView ([Official API - WebView.loadDataWithBaseURL](https://developer.android.com/reference/android/webkit/WebView#loadDataWithBaseURL(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String))) ///- iOS ([Official API - WKWebView.loadHTMLString](https://developer.apple.com/documentation/webkit/wkwebview/1415004-loadhtmlstring) or [Official API - WKWebView.load](https://developer.apple.com/documentation/webkit/wkwebview/1415011-load)) ///- MacOS ([Official API - WKWebView.loadHTMLString](https://developer.apple.com/documentation/webkit/wkwebview/1415004-loadhtmlstring) or [Official API - WKWebView.load](https://developer.apple.com/documentation/webkit/wkwebview/1415011-load)) ///- Web + ///- Windows ([Official API - ICoreWebView2.NavigateToString](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#navigatetostring)) ///{@endtemplate} Future loadData( {required String data, @@ -330,6 +333,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- iOS ([Official API - WKWebView.load](https://developer.apple.com/documentation/webkit/wkwebview/1414954-load)) ///- MacOS ([Official API - WKWebView.load](https://developer.apple.com/documentation/webkit/wkwebview/1414954-load)) ///- Web + ///- Windows ([Official API - ICoreWebView2.Navigate](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#navigate)) ///{@endtemplate} Future loadFile({required String assetFilePath}) { throw UnimplementedError( @@ -346,7 +350,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- iOS ([Official API - WKWebView.reload](https://developer.apple.com/documentation/webkit/wkwebview/1414969-reload)) ///- MacOS ([Official API - WKWebView.reload](https://developer.apple.com/documentation/webkit/wkwebview/1414969-reload)) ///- Web ([Official API - Location.reload](https://developer.mozilla.org/en-US/docs/Web/API/Location/reload)) - ///- Windows ([Official API - IWebView2WebView.Reload](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#reload)) + ///- Windows ([Official API - ICoreWebView2.Reload](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#reload)) ///{@endtemplate} Future reload() { throw UnimplementedError( @@ -363,7 +367,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- iOS ([Official API - WKWebView.goBack](https://developer.apple.com/documentation/webkit/wkwebview/1414952-goback)) ///- MacOS ([Official API - WKWebView.goBack](https://developer.apple.com/documentation/webkit/wkwebview/1414952-goback)) ///- Web ([Official API - History.back](https://developer.mozilla.org/en-US/docs/Web/API/History/back)) - ///- Windows ([Official API - IWebView2WebView.GoBack](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#goback)) + ///- Windows ([Official API - ICoreWebView2.GoBack](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#goback)) ///{@endtemplate} Future goBack() { throw UnimplementedError( @@ -377,7 +381,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- Android native WebView ([Official API - WebView.canGoBack](https://developer.android.com/reference/android/webkit/WebView#canGoBack())) ///- iOS ([Official API - WKWebView.canGoBack](https://developer.apple.com/documentation/webkit/wkwebview/1414966-cangoback)) ///- MacOS ([Official API - WKWebView.canGoBack](https://developer.apple.com/documentation/webkit/wkwebview/1414966-cangoback)) - ///- Windows ([Official API - IWebView2WebView.get_CanGoBack](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#get_cangoback)) + ///- Windows ([Official API - ICoreWebView2.get_CanGoBack](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#get_cangoback)) ///{@endtemplate} Future canGoBack() { throw UnimplementedError( @@ -394,7 +398,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- iOS ([Official API - WKWebView.goForward](https://developer.apple.com/documentation/webkit/wkwebview/1414993-goforward)) ///- MacOS ([Official API - WKWebView.goForward](https://developer.apple.com/documentation/webkit/wkwebview/1414993-goforward)) ///- Web ([Official API - History.forward](https://developer.mozilla.org/en-US/docs/Web/API/History/forward)) - ///- Windows ([Official API - IWebView2WebView.GoForward](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#goforward)) + ///- Windows ([Official API - ICoreWebView2.GoForward](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#goforward)) ///{@endtemplate} Future goForward() { throw UnimplementedError( @@ -408,7 +412,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- Android native WebView ([Official API - WebView.canGoForward](https://developer.android.com/reference/android/webkit/WebView#canGoForward())) ///- iOS ([Official API - WKWebView.canGoForward](https://developer.apple.com/documentation/webkit/wkwebview/1414962-cangoforward)) ///- MacOS ([Official API - WKWebView.canGoForward](https://developer.apple.com/documentation/webkit/wkwebview/1414962-cangoforward)) - ///- Windows ([Official API - IWebView2WebView.get_CanGoForward](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#get_cangoforward)) + ///- Windows ([Official API - ICoreWebView2.get_CanGoForward](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#get_cangoforward)) ///{@endtemplate} Future canGoForward() { throw UnimplementedError( @@ -487,7 +491,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- iOS ([Official API - WKWebView.stopLoading](https://developer.apple.com/documentation/webkit/wkwebview/1414981-stoploading)) ///- MacOS ([Official API - WKWebView.stopLoading](https://developer.apple.com/documentation/webkit/wkwebview/1414981-stoploading)) ///- Web ([Official API - Window.stop](https://developer.mozilla.org/en-US/docs/Web/API/Window/stop)) - ///- Windows ([Official API - IWebView2WebView.Stop](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#stop)) + ///- Windows ([Official API - ICoreWebView2.Stop](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#stop)) ///{@endtemplate} Future stopLoading() { throw UnimplementedError( @@ -517,7 +521,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- iOS ([Official API - WKWebView.evaluateJavascript](https://developer.apple.com/documentation/webkit/wkwebview/3656442-evaluatejavascript)) ///- MacOS ([Official API - WKWebView.evaluateJavascript](https://developer.apple.com/documentation/webkit/wkwebview/3656442-evaluatejavascript)) ///- Web ([Official API - Window.eval](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval?retiredLocale=it)) - ///- Windows ([Official API - IWebView2WebView.ExecuteScript](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#executescript)) + ///- Windows ([Official API - ICoreWebView2.ExecuteScript](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#executescript)) ///{@endtemplate} Future evaluateJavascript( {required String source, ContentWorld? contentWorld}) { @@ -1189,6 +1193,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- Android native WebView ///- iOS ([Official API - WKUserContentController.addUserScript](https://developer.apple.com/documentation/webkit/wkusercontentcontroller/1537448-adduserscript)) ///- MacOS ([Official API - WKUserContentController.addUserScript](https://developer.apple.com/documentation/webkit/wkusercontentcontroller/1537448-adduserscript)) + ///- Windows ///{@endtemplate} Future addUserScript({required UserScript userScript}) { throw UnimplementedError( @@ -1206,6 +1211,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- Android native WebView ///- iOS ///- MacOS + ///- Windows ///{@endtemplate} Future addUserScripts({required List userScripts}) { throw UnimplementedError( @@ -1225,6 +1231,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- Android native WebView ///- iOS ///- MacOS + ///- Windows ///{@endtemplate} Future removeUserScript({required UserScript userScript}) { throw UnimplementedError( @@ -1243,6 +1250,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- Android native WebView ///- iOS ///- MacOS + ///- Windows ///{@endtemplate} Future removeUserScriptsByGroupName({required String groupName}) { throw UnimplementedError( @@ -1261,6 +1269,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- Android native WebView ///- iOS ///- MacOS + ///- Windows ///{@endtemplate} Future removeUserScripts({required List userScripts}) { throw UnimplementedError( @@ -1278,6 +1287,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- Android native WebView ///- iOS ([Official API - WKUserContentController.removeAllUserScripts](https://developer.apple.com/documentation/webkit/wkusercontentcontroller/1536540-removealluserscripts)) ///- MacOS ([Official API - WKUserContentController.removeAllUserScripts](https://developer.apple.com/documentation/webkit/wkusercontentcontroller/1536540-removealluserscripts)) + ///- Windows ///{@endtemplate} Future removeAllUserScripts() { throw UnimplementedError( @@ -1291,6 +1301,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface ///- Android native WebView ///- iOS ///- MacOS + ///- Windows ///{@endtemplate} bool hasUserScript({required UserScript userScript}) { throw UnimplementedError( diff --git a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_webview.dart b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_webview.dart index 4949d48b..ff250815 100644 --- a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_webview.dart +++ b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_webview.dart @@ -55,7 +55,7 @@ class PlatformWebViewCreationParams { ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview)) ///- MacOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview)) ///- Web - ///- Windows ([Official API - IWebView2WebView.add_NavigationStarting](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationstarting)) + ///- Windows ([Official API - ICoreWebView2.add_NavigationStarting](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationstarting)) ///{@endtemplate} final void Function(T controller, WebUri? url)? onLoadStart; @@ -70,7 +70,7 @@ class PlatformWebViewCreationParams { ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview)) ///- MacOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview)) ///- Web ([Official API - Window.onload](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event)) - ///- Windows ([Official API - IWebView2WebView.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) + ///- Windows ([Official API - ICoreWebView2.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) ///{@endtemplate} final void Function(T controller, WebUri? url)? onLoadStop; @@ -86,7 +86,7 @@ class PlatformWebViewCreationParams { ///- Android native WebView ([Official API - WebViewClient.onReceivedError](https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedError(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceError))) ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455623-webview)) ///- MacOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455623-webview)) - ///- Windows ([Official API - IWebView2WebView.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) + ///- Windows ([Official API - ICoreWebView2.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) ///{@endtemplate} final void Function( T controller, WebResourceRequest request, WebResourceError error)? @@ -111,7 +111,7 @@ class PlatformWebViewCreationParams { ///- Android native WebView ([Official API - WebViewClient.onReceivedHttpError](https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpError(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceResponse))) ///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview)) ///- MacOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview)) - ///- Windows ([Official API - IWebView2WebView.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) + ///- Windows ([Official API - ICoreWebView2.add_NavigationCompleted](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/iwebview2webview?view=webview2-0.8.355#add_navigationcompleted)) ///{@endtemplate} final void Function(T controller, WebResourceRequest request, WebResourceResponse errorResponse)? onReceivedHttpError; @@ -504,7 +504,7 @@ class PlatformWebViewCreationParams { ///- iOS ///- MacOS ///- Web - ///- Windows ([Official API - IWebView2WebView.add_HistoryChanged](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#add_historychanged)) + ///- Windows ([Official API - ICoreWebView2.add_HistoryChanged](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#add_historychanged)) ///{@endtemplate} final void Function(T controller, WebUri? url, bool? isReload)? onUpdateVisitedHistory; @@ -599,7 +599,7 @@ class PlatformWebViewCreationParams { ///- iOS ///- MacOS ///- Web - ///- Windows ([Official API - IWebView2WebView.add_DocumentTitleChanged](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#add_documenttitlechanged)) + ///- Windows ([Official API - ICoreWebView2.add_DocumentTitleChanged](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#add_documenttitlechanged)) ///{@endtemplate} final void Function(T controller, String? title)? onTitleChanged; @@ -1059,6 +1059,7 @@ class PlatformWebViewCreationParams { ///- iOS ///- MacOS ///- Web + ///- Windows ///{@endtemplate} final URLRequest? initialUrlRequest; @@ -1070,6 +1071,7 @@ class PlatformWebViewCreationParams { ///- iOS ///- MacOS ///- Web + ///- Windows ///{@endtemplate} final String? initialFile; @@ -1081,6 +1083,7 @@ class PlatformWebViewCreationParams { ///- iOS ///- MacOS ///- Web + ///- Windows ///{@endtemplate} final InAppWebViewInitialData? initialData; diff --git a/flutter_inappwebview_windows/windows/CMakeLists.txt b/flutter_inappwebview_windows/windows/CMakeLists.txt index 998a399b..7df66194 100644 --- a/flutter_inappwebview_windows/windows/CMakeLists.txt +++ b/flutter_inappwebview_windows/windows/CMakeLists.txt @@ -44,6 +44,7 @@ list(APPEND PLUGIN_SOURCES "utils/strconv.h" "utils/map.h" "utils/vector.h" + "utils/string.h" "utils/util.h" "utils/flutter.h" "types/channel_delegate.cpp" @@ -80,6 +81,7 @@ list(APPEND PLUGIN_SOURCES "custom_platform_view/util/string_converter.cc" "custom_platform_view/util/string_converter.h" "custom_platform_view/util/swizzle.h" + "plugin_scripts_js/plugin_scripts_util.h" "plugin_scripts_js/javascript_bridge_js.cpp" "plugin_scripts_js/javascript_bridge_js.h" "in_app_webview/user_content_controller.cpp" diff --git a/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser.h b/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser.h index 7c6899a3..fe2e6988 100644 --- a/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser.h +++ b/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser.h @@ -18,7 +18,7 @@ namespace flutter_inappwebview_plugin struct InAppBrowserCreationParams { const std::string id; - const std::optional urlRequest; + const std::optional> urlRequest; const std::shared_ptr initialSettings; const std::shared_ptr initialWebViewSettings; }; @@ -35,7 +35,7 @@ namespace flutter_inappwebview_plugin const FlutterInappwebviewWindowsPlugin* plugin; const std::string id; - const std::optional initialUrlRequest; + const std::optional> initialUrlRequest; std::unique_ptr webView; std::unique_ptr channelDelegate; const std::shared_ptr settings; diff --git a/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_manager.cpp b/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_manager.cpp index efdd422a..0459326d 100644 --- a/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_manager.cpp +++ b/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_manager.cpp @@ -31,7 +31,7 @@ namespace flutter_inappwebview_plugin { auto id = get_fl_map_value(*arguments, "id"); auto urlRequestMap = get_optional_fl_map_value(*arguments, "urlRequest"); - std::optional urlRequest = urlRequestMap.has_value() ? std::make_optional(urlRequestMap.value()) : std::optional{}; + std::optional> urlRequest = urlRequestMap.has_value() ? std::make_shared(urlRequestMap.value()) : std::optional>{}; auto settingsMap = get_fl_map_value(*arguments, "settings"); auto initialSettings = std::make_unique(settingsMap); diff --git a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp index 2d601f4d..118eadd2 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp +++ b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -9,7 +10,9 @@ #include "../types/web_resource_error.h" #include "../types/web_resource_request.h" #include "../utils/log.h" +#include "../utils/map.h" #include "../utils/strconv.h" +#include "../utils/string.h" #include "in_app_webview.h" #include "in_app_webview_manager.h" @@ -246,14 +249,14 @@ namespace flutter_inappwebview_plugin { callShouldOverrideUrlLoading_ = false; if (actionPolicy == NavigationActionPolicy::allow) { - loadUrl(*urlRequest); + loadUrl(urlRequest); } return false; }; - auto defaultBehaviour = [this, urlRequest](const std::optional actionPolicy) + auto defaultBehaviour = [this, urlRequest](const std::optional actionPolicy) { callShouldOverrideUrlLoading_ = false; - loadUrl(*urlRequest); + loadUrl(urlRequest); }; callback->defaultBehaviour = defaultBehaviour; callback->error = [defaultBehaviour](const std::string& error_code, const std::string& error_message, const flutter::EncodableValue* error_details) @@ -280,6 +283,11 @@ namespace flutter_inappwebview_plugin { isLoading_ = false; + if (userContentController) { + evaluateJavascript(userContentController->generateWrappedCodeForDocumentEnd(), nullptr); + } + evaluateJavascript(PLATFORM_READY_JS_SOURCE, nullptr); + std::shared_ptr navigationAction; UINT64 navigationId; if (SUCCEEDED(args->get_NavigationId(&navigationId))) { @@ -349,12 +357,61 @@ namespace flutter_inappwebview_plugin failedLog(webView->add_WebMessageReceived(Callback( [this](ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args) { - wil::unique_cotaskmem_string uri; - args->get_Source(&uri); + if (!channelDelegate) { + return S_OK; + } + + /* + wil::unique_cotaskmem_string url; + args->get_Source(&url); + + wil::com_ptr uri; + failedLog(CreateUri( + url.get(), // NULL terminated URI + Uri_CREATE_ALLOW_RELATIVE, // Flags to control behavior + 0, // Reserved must be 0 + &uri)); + */ wil::unique_cotaskmem_string json; if (succeededOrLog(args->get_WebMessageAsJson(&json))) { - debugLog(json.get()); + auto message = nlohmann::json::parse(wide_to_ansi(json.get())); + + if (message.is_object() && message.contains("name") && message.at("name").is_string() && message.contains("body") && message.at("body").is_object()) { + auto name = message.at("name").get(); + auto body = message.at("body").get(); + + if (name.compare("callHandler") == 0 && body.contains("handlerName") && body.at("handlerName").is_string()) { + auto handlerName = body.at("handlerName").get(); + auto callHandlerID = body.at("_callHandlerID").is_number_integer() ? body.at("_callHandlerID").get() : 0; + std::string handlerArgs = body.at("args").is_string() ? body.at("args").get() : ""; + + auto callback = std::make_unique(); + callback->defaultBehaviour = [this, callHandlerID](const std::optional response) + { + std::string json = "null"; + if (response.has_value() && !response.value()->IsNull()) { + json = std::get(*(response.value())); + } + + evaluateJavascript("if (window." + JAVASCRIPT_BRIDGE_NAME + "[" + std::to_string(callHandlerID) + "] != null) { \ + window." + JAVASCRIPT_BRIDGE_NAME + "[" + std::to_string(callHandlerID) + "].resolve(" + json + "); \ + delete window." + JAVASCRIPT_BRIDGE_NAME + "[" + std::to_string(callHandlerID) + "]; \ + }", nullptr); + }; + callback->error = [this, callHandlerID](const std::string& error_code, const std::string& error_message, const flutter::EncodableValue* error_details) + { + auto errorMessage = error_code + ", " + error_message; + debugLog(errorMessage); + + evaluateJavascript("if (window." + JAVASCRIPT_BRIDGE_NAME + "[" + std::to_string(callHandlerID) + "] != null) { \ + window." + JAVASCRIPT_BRIDGE_NAME + "[" + std::to_string(callHandlerID) + "].reject(new Error('" + replace_all_copy(errorMessage, "\'", "\\'") + "')); \ + delete window." + JAVASCRIPT_BRIDGE_NAME + "[" + std::to_string(callHandlerID) + "]; \ + }", nullptr); + }; + channelDelegate->onCallJsHandler(handlerName, handlerArgs, std::move(callback)); + } + } } return S_OK; @@ -395,23 +452,23 @@ namespace flutter_inappwebview_plugin return webView && succeededOrLog(webView->get_DocumentTitle(&title)) ? wide_to_utf8(title.get()) : std::optional{}; } - void InAppWebView::loadUrl(const URLRequest& urlRequest) const + void InAppWebView::loadUrl(const std::shared_ptr urlRequest) const { - if (!webView || !urlRequest.url.has_value()) { + if (!webView || !urlRequest->url.has_value()) { return; } - std::wstring url = ansi_to_wide(urlRequest.url.value()); + std::wstring url = ansi_to_wide(urlRequest->url.value()); wil::com_ptr webViewEnv2; wil::com_ptr webView2; if (SUCCEEDED(webViewEnv->QueryInterface(IID_PPV_ARGS(&webViewEnv2))) && SUCCEEDED(webView->QueryInterface(IID_PPV_ARGS(&webView2)))) { wil::com_ptr webResourceRequest; - std::wstring method = urlRequest.method.has_value() ? ansi_to_wide(urlRequest.method.value()) : L"GET"; + std::wstring method = urlRequest->method.has_value() ? ansi_to_wide(urlRequest->method.value()) : L"GET"; wil::com_ptr postDataStream = nullptr; - if (urlRequest.body.has_value()) { - auto postData = std::string(urlRequest.body->begin(), urlRequest.body->end()); + if (urlRequest->body.has_value()) { + auto postData = std::string(urlRequest->body->begin(), urlRequest->body->end()); postDataStream = SHCreateMemStream( reinterpret_cast(postData.data()), static_cast(postData.length())); } @@ -427,8 +484,8 @@ namespace flutter_inappwebview_plugin if (method.compare(L"GET") != 0) { requestHeaders->SetHeader(L"Flutter-InAppWebView-Request-Method", method.c_str()); } - if (urlRequest.headers.has_value()) { - auto& headers = urlRequest.headers.value(); + if (urlRequest->headers.has_value()) { + auto& headers = urlRequest->headers.value(); for (auto const& [key, val] : headers) { requestHeaders->SetHeader(ansi_to_wide(key).c_str(), ansi_to_wide(val).c_str()); } @@ -441,6 +498,37 @@ namespace flutter_inappwebview_plugin failedLog(webView->Navigate(url.c_str())); } + + void InAppWebView::loadFile(const std::string& assetFilePath) const + { + if (!webView) { + return; + } + + WCHAR* buf = new WCHAR[32768]; + GetModuleFileName(NULL, buf, 32768); + std::filesystem::path exeAbsPath = std::wstring(buf); + delete[] buf; + + std::filesystem::path flutterAssetPath("data/flutter_assets/" + assetFilePath); + auto absAssetFilePath = exeAbsPath.parent_path() / flutterAssetPath; + + if (!std::filesystem::exists(absAssetFilePath)) { + debugLog(absAssetFilePath.native() + L" asset file cannot be found!"); + return; + } + failedLog(webView->Navigate(absAssetFilePath.c_str())); + } + + void InAppWebView::loadData(const std::string& data) const + { + if (!webView) { + return; + } + + failedLog(webView->NavigateToString(ansi_to_wide(data).c_str())); + } + void InAppWebView::reload() const { if (!webView) { @@ -527,7 +615,10 @@ namespace flutter_inappwebview_plugin int64_t size = items->size(); canGoBackOrForward_ = nextIndex >= 0 && nextIndex < size; } - completionHandler(canGoBackOrForward_); + + if (completionHandler) { + completionHandler(canGoBackOrForward_); + } } ); } @@ -544,13 +635,19 @@ namespace flutter_inappwebview_plugin void InAppWebView::getCopyBackForwardList(const std::function)> completionHandler) const { if (!webView) { - completionHandler(std::make_unique(std::nullopt, std::nullopt)); + if (completionHandler) { + completionHandler(std::make_unique(std::nullopt, std::nullopt)); + } return; } failedLog(webView->CallDevToolsProtocolMethod(L"Page.getNavigationHistory", L"{}", Callback( [completionHandler](HRESULT errorCode, LPCWSTR returnObjectAsJson) { + if (!completionHandler) { + return S_OK; + } + if (errorCode == S_OK) { auto historyJson = nlohmann::json::parse(wide_to_ansi(returnObjectAsJson)); @@ -585,7 +682,7 @@ namespace flutter_inappwebview_plugin ).Get())); } - void InAppWebView::evaluateJavascript(const std::string& source, std::function completionHanlder) const + void InAppWebView::evaluateJavascript(const std::string& source, const std::function completionHanlder) const { failedLog(webView->ExecuteScript(ansi_to_wide(source).c_str(), Callback( @@ -594,11 +691,51 @@ namespace flutter_inappwebview_plugin if (error != S_OK) { debugLog(error); } - completionHanlder(wide_to_ansi(result)); + + if (completionHanlder) { + completionHanlder(wide_to_ansi(result)); + } + return S_OK; }).Get())); } + void InAppWebView::addUserScript(const std::shared_ptr userScript) const + { + if (!userContentController) { + return; + } + + userContentController->addUserOnlyScript(userScript); + } + + void InAppWebView::removeUserScript(const int64_t index, const std::shared_ptr userScript) const + { + if (!userContentController) { + return; + } + + userContentController->removeUserOnlyScriptAt(index, userScript->injectionTime); + } + + void InAppWebView::removeUserScriptsByGroupName(const std::string& groupName) const + { + if (!userContentController) { + return; + } + + userContentController->removeUserOnlyScriptsByGroupName(groupName); + } + + void InAppWebView::removeAllUserScripts() const + { + if (!userContentController) { + return; + } + + userContentController->removeAllUserOnlyScripts(); + } + // flutter_view void InAppWebView::setSurfaceSize(size_t width, size_t height, float scale_factor) { diff --git a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.h b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.h index fb981452..6816590a 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.h +++ b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.h @@ -132,7 +132,9 @@ namespace flutter_inappwebview_plugin void prepare(); std::optional getUrl() const; std::optional getTitle() const; - void loadUrl(const URLRequest& urlRequest) const; + void loadUrl(const std::shared_ptr urlRequest) const; + void loadFile(const std::string& assetFilePath) const; + void loadData(const std::string& data) const; void reload() const; void goBack(); bool canGoBack() const; @@ -145,8 +147,12 @@ namespace flutter_inappwebview_plugin return isLoading_; } void stopLoading() const; - void evaluateJavascript(const std::string& source, std::function completionHanlder) const; + void evaluateJavascript(const std::string& source, const std::function completionHanlder) const; void getCopyBackForwardList(const std::function)> completionHandler) const; + void addUserScript(const std::shared_ptr userScript) const; + void removeUserScript(const int64_t index, const std::shared_ptr userScript) const; + void removeUserScriptsByGroupName(const std::string& groupName) const; + void removeAllUserScripts() const; static bool isSslError(const COREWEBVIEW2_WEB_ERROR_STATUS& webErrorStatus); private: diff --git a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview_manager.cpp b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview_manager.cpp index 10f2a0cd..761e1ff7 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview_manager.cpp +++ b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview_manager.cpp @@ -76,6 +76,8 @@ namespace flutter_inappwebview_plugin auto settingsMap = get_fl_map_value(*arguments, "initialSettings"); auto urlRequestMap = get_optional_fl_map_value(*arguments, "initialUrlRequest"); + auto initialFile = get_optional_fl_map_value(*arguments, "initialFile"); + auto initialDataMap = get_optional_fl_map_value(*arguments, "initialData"); auto hwnd = CreateWindowEx(0, windowClass_.lpszClassName, L"", 0, CW_DEFAULT, CW_DEFAULT, 0, 0, HWND_MESSAGE, nullptr, @@ -98,10 +100,16 @@ namespace flutter_inappwebview_plugin std::move(webViewEnv), std::move(webViewController), std::move(webViewCompositionController) ); - std::optional urlRequest = urlRequestMap.has_value() ? std::make_optional(urlRequestMap.value()) : std::optional{}; + std::optional> urlRequest = urlRequestMap.has_value() ? std::make_shared(urlRequestMap.value()) : std::optional>{}; if (urlRequest.has_value()) { inAppWebView->loadUrl(urlRequest.value()); } + else if (initialFile.has_value()) { + inAppWebView->loadFile(initialFile.value()); + } + else if (initialDataMap.has_value()) { + inAppWebView->loadData(get_fl_map_value(initialDataMap.value(), "data")); + } auto customPlatformView = std::make_unique(plugin->registrar->messenger(), plugin->registrar->texture_registrar(), diff --git a/flutter_inappwebview_windows/windows/in_app_webview/user_content_controller.cpp b/flutter_inappwebview_windows/windows/in_app_webview/user_content_controller.cpp index eed27040..9f51ed82 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/user_content_controller.cpp +++ b/flutter_inappwebview_windows/windows/in_app_webview/user_content_controller.cpp @@ -1,7 +1,7 @@ #include #include "../utils/log.h" -#include "../utils/strconv.h" +#include "../utils/string.h" #include "../utils/vector.h" #include "in_app_webview.h" #include "user_content_controller.h" @@ -25,6 +25,18 @@ namespace flutter_inappwebview_plugin return; } + if (userScript->injectionTime == UserScriptInjectionTime::atDocumentStart && webView_) { + failedLog(webView_->webView->AddScriptToExecuteOnDocumentCreated(ansi_to_wide(userScript->source).c_str(), + Callback( + [userScript](HRESULT error, PCWSTR id) -> HRESULT + { + if (succeededOrLog(error)) { + userScript->id = id; + } + return S_OK; + }).Get())); + } + userOnlyScripts_.at(userScript->injectionTime).push_back(std::move(userScript)); } @@ -41,7 +53,11 @@ namespace flutter_inappwebview_plugin return; } - vector_remove_erase_el(userOnlyScripts_.at(userScript->injectionTime), std::move(userScript)); + if (webView_) { + failedLog(webView_->webView->RemoveScriptToExecuteOnDocumentCreated(userScript->id.c_str())); + } + + vector_remove_erase(userOnlyScripts_.at(userScript->injectionTime), std::move(userScript)); } void UserContentController::removeUserOnlyScriptAt(const int64_t& index, const UserScriptInjectionTime& injectionTime) @@ -52,13 +68,49 @@ namespace flutter_inappwebview_plugin return; } - vec.erase(vec.begin() + index); + auto& userScript = vec.at(index); + if (userScript) { + if (webView_) { + failedLog(webView_->webView->RemoveScriptToExecuteOnDocumentCreated(userScript->id.c_str())); + } + vec.erase(vec.begin() + index); + } } void UserContentController::removeAllUserOnlyScripts() { - userOnlyScripts_.at(UserScriptInjectionTime::atDocumentStart).clear(); - userOnlyScripts_.at(UserScriptInjectionTime::atDocumentEnd).clear(); + auto& userScriptsAtStart = userOnlyScripts_.at(UserScriptInjectionTime::atDocumentStart); + auto& userScriptsAtEnd = userOnlyScripts_.at(UserScriptInjectionTime::atDocumentEnd); + + if (webView_) { + for (auto& userScript : userScriptsAtStart) { + failedLog(webView_->webView->RemoveScriptToExecuteOnDocumentCreated(userScript->id.c_str())); + } + for (auto& userScript : userScriptsAtEnd) { + failedLog(webView_->webView->RemoveScriptToExecuteOnDocumentCreated(userScript->id.c_str())); + } + } + + userScriptsAtStart.clear(); + userScriptsAtEnd.clear(); + } + + void UserContentController::removeUserOnlyScriptsByGroupName(const std::string& groupName) + { + std::vector> userScriptsAtStart = userOnlyScripts_.at(UserScriptInjectionTime::atDocumentStart); + std::vector> userScriptsAtEnd = userOnlyScripts_.at(UserScriptInjectionTime::atDocumentEnd); + + for (auto& userScript : userScriptsAtStart) { + if (string_equals(groupName, userScript->groupName)) { + removeUserOnlyScript(userScript); + } + } + + for (auto& userScript : userScriptsAtEnd) { + if (string_equals(groupName, userScript->groupName)) { + removeUserOnlyScript(userScript); + } + } } std::vector> UserContentController::getPluginScriptsAt(const UserScriptInjectionTime& injectionTime) const @@ -66,13 +118,28 @@ namespace flutter_inappwebview_plugin return pluginScripts_.at(injectionTime); } + bool UserContentController::containsUserOnlyScript(std::shared_ptr userScript) const + { + if (!userScript) { + return false; + } + + return vector_contains(userOnlyScripts_.at(userScript->injectionTime), std::move(userScript)); + } + + bool UserContentController::containsUserOnlyScriptByGroupName(const std::string& groupName) const + { + return vector_contains_if(userOnlyScripts_.at(UserScriptInjectionTime::atDocumentStart), [groupName](const std::shared_ptr userScript) { return string_equals(groupName, userScript->groupName); }) || + vector_contains_if(userOnlyScripts_.at(UserScriptInjectionTime::atDocumentEnd), [groupName](const std::shared_ptr userScript) { return string_equals(groupName, userScript->groupName); }); + } + void UserContentController::addPluginScript(std::shared_ptr pluginScript) { - if (!pluginScript || !webView_) { + if (!pluginScript) { return; } - if (pluginScript->injectionTime == UserScriptInjectionTime::atDocumentStart) { + if (pluginScript->injectionTime == UserScriptInjectionTime::atDocumentStart && webView_) { failedLog(webView_->webView->AddScriptToExecuteOnDocumentCreated(ansi_to_wide(pluginScript->source).c_str(), Callback( [pluginScript](HRESULT error, PCWSTR id) -> HRESULT @@ -96,19 +163,93 @@ namespace flutter_inappwebview_plugin void UserContentController::removePluginScript(std::shared_ptr pluginScript) { - if (!pluginScript || !webView_) { + if (!pluginScript) { return; } - failedLog(webView_->webView->RemoveScriptToExecuteOnDocumentCreated(pluginScript->id.c_str())); + if (webView_) { + failedLog(webView_->webView->RemoveScriptToExecuteOnDocumentCreated(pluginScript->id.c_str())); + } - vector_remove_erase_el(pluginScripts_.at(pluginScript->injectionTime), std::move(pluginScript)); + vector_remove_erase(pluginScripts_.at(pluginScript->injectionTime), std::move(pluginScript)); } void UserContentController::removeAllPluginScripts() { - pluginScripts_.at(UserScriptInjectionTime::atDocumentStart).clear(); - pluginScripts_.at(UserScriptInjectionTime::atDocumentEnd).clear(); + auto& pluginScriptsAtStart = pluginScripts_.at(UserScriptInjectionTime::atDocumentStart); + auto& pluginScriptsAtEnd = pluginScripts_.at(UserScriptInjectionTime::atDocumentEnd); + + if (webView_) { + for (auto& pluginScript : pluginScriptsAtStart) { + failedLog(webView_->webView->RemoveScriptToExecuteOnDocumentCreated(pluginScript->id.c_str())); + } + for (auto& pluginScript : pluginScriptsAtEnd) { + failedLog(webView_->webView->RemoveScriptToExecuteOnDocumentCreated(pluginScript->id.c_str())); + } + } + + pluginScriptsAtStart.clear(); + pluginScriptsAtEnd.clear(); + } + + bool UserContentController::containsPluginScript(std::shared_ptr pluginScript) const + { + if (!pluginScript) { + return false; + } + + return vector_contains(pluginScripts_.at(pluginScript->injectionTime), std::move(pluginScript)); + } + + bool UserContentController::containsPluginScriptByGroupName(const std::string& groupName) const + { + return vector_contains_if(pluginScripts_.at(UserScriptInjectionTime::atDocumentStart), [groupName](const std::shared_ptr pluginScript) { return string_equals(groupName, pluginScript->groupName); }) || + vector_contains_if(pluginScripts_.at(UserScriptInjectionTime::atDocumentEnd), [groupName](const std::shared_ptr pluginScript) { return string_equals(groupName, pluginScript->groupName); }); + } + + void UserContentController::removePluginScriptsByGroupName(const std::string& groupName) + { + std::vector> pluginScriptsAtStart = pluginScripts_.at(UserScriptInjectionTime::atDocumentStart); + std::vector> pluginScriptsAtEnd = pluginScripts_.at(UserScriptInjectionTime::atDocumentEnd); + + for (auto& pluginScript : pluginScriptsAtStart) { + if (string_equals(groupName, pluginScript->groupName)) { + removePluginScript(pluginScript); + } + } + + for (auto& pluginScript : pluginScriptsAtEnd) { + if (string_equals(groupName, pluginScript->groupName)) { + removePluginScript(pluginScript); + } + } + } + + std::string UserContentController::generatePluginScriptsCodeAt(const UserScriptInjectionTime& injectionTime) const + { + std::string code; + std::vector> pluginScripts = pluginScripts_.at(injectionTime); + for (auto& pluginScript : pluginScripts) { + code += ";" + pluginScript->source; + } + return code; + } + + std::string UserContentController::generateUserOnlyScriptsCodeAt(const UserScriptInjectionTime& injectionTime) const + { + std::string code; + std::vector> userScripts = userOnlyScripts_.at(injectionTime); + for (auto& userScript : userScripts) { + code += ";" + userScript->source; + } + return code; + } + + std::string UserContentController::generateWrappedCodeForDocumentEnd() const + { + std::string code = generatePluginScriptsCodeAt(UserScriptInjectionTime::atDocumentEnd); + code += generateUserOnlyScriptsCodeAt(UserScriptInjectionTime::atDocumentEnd); + return replace_all_copy(USER_SCRIPTS_AT_DOCUMENT_END_WRAPPER_JS_SOURCE, VAR_PLACEHOLDER_VALUE, code); } UserContentController::~UserContentController() diff --git a/flutter_inappwebview_windows/windows/in_app_webview/user_content_controller.h b/flutter_inappwebview_windows/windows/in_app_webview/user_content_controller.h index 1fee5cfa..c051544a 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/user_content_controller.h +++ b/flutter_inappwebview_windows/windows/in_app_webview/user_content_controller.h @@ -4,6 +4,8 @@ #include #include +#include "../plugin_scripts_js/javascript_bridge_js.h" +#include "../plugin_scripts_js/plugin_scripts_util.h" #include "../types/plugin_script.h" #include "../types/user_script.h" @@ -11,6 +13,12 @@ namespace flutter_inappwebview_plugin { class InAppWebView; + const std::string USER_SCRIPTS_AT_DOCUMENT_END_WRAPPER_JS_SOURCE = + "if (window." + JAVASCRIPT_BRIDGE_NAME + " != null && (window." + JAVASCRIPT_BRIDGE_NAME + "._userScriptsAtDocumentEndLoaded == null || !window." + JAVASCRIPT_BRIDGE_NAME + "._userScriptsAtDocumentEndLoaded)) { \ + window." + JAVASCRIPT_BRIDGE_NAME + "._userScriptsAtDocumentEndLoaded = true; \ + " + VAR_PLACEHOLDER_VALUE + " \ + }"; + class UserContentController { public: @@ -23,11 +31,20 @@ namespace flutter_inappwebview_plugin void removeUserOnlyScript(std::shared_ptr userScript); void removeUserOnlyScriptAt(const int64_t& index, const UserScriptInjectionTime& injectionTime); void removeAllUserOnlyScripts(); + bool containsUserOnlyScript(std::shared_ptr userScript) const; + bool containsUserOnlyScriptByGroupName(const std::string& groupName) const; + void removeUserOnlyScriptsByGroupName(const std::string& groupName); std::vector> getPluginScriptsAt(const UserScriptInjectionTime& injectionTime) const; void addPluginScript(std::shared_ptr pluginScript); void addPluginScripts(std::vector> pluginScripts); void removePluginScript(std::shared_ptr pluginScript); void removeAllPluginScripts(); + bool containsPluginScript(std::shared_ptr pluginScript) const; + bool containsPluginScriptByGroupName(const std::string& groupName) const; + void removePluginScriptsByGroupName(const std::string& groupName); + std::string generatePluginScriptsCodeAt(const UserScriptInjectionTime& injectionTime) const; + std::string generateUserOnlyScriptsCodeAt(const UserScriptInjectionTime& injectionTime) const; + std::string generateWrappedCodeForDocumentEnd() const; private: InAppWebView* webView_; diff --git a/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.cpp b/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.cpp index 1b634773..e1884e1f 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.cpp +++ b/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.cpp @@ -3,6 +3,7 @@ #include "../utils/flutter.h" #include "../utils/log.h" #include "../utils/strconv.h" +#include "../utils/string.h" #include "in_app_webview.h" #include "webview_channel_delegate.h" @@ -28,6 +29,14 @@ namespace flutter_inappwebview_plugin }; } + WebViewChannelDelegate::CallJsHandlerCallback::CallJsHandlerCallback() + { + decodeResult = [](const flutter::EncodableValue* value) + { + return value; + }; + } + void WebViewChannelDelegate::HandleMethodCall(const flutter::MethodCall& method_call, std::unique_ptr> result) { @@ -37,42 +46,53 @@ namespace flutter_inappwebview_plugin } auto& arguments = std::get(*method_call.arguments()); + auto& methodName = method_call.method_name(); - if (method_call.method_name().compare("getUrl") == 0) { + if (string_equals(methodName, "getUrl")) { result->Success(make_fl_value(webView->getUrl())); } - else if (method_call.method_name().compare("getTitle") == 0) { + else if (string_equals(methodName, "getTitle")) { result->Success(make_fl_value(webView->getUrl())); } - else if (method_call.method_name().compare("loadUrl") == 0) { + else if (string_equals(methodName, "loadUrl")) { auto urlRequest = std::make_unique(get_fl_map_value(arguments, "urlRequest")); - webView->loadUrl(*urlRequest); + webView->loadUrl(std::move(urlRequest)); result->Success(true); } - else if (method_call.method_name().compare("reload") == 0) { + else if (string_equals(methodName, "loadFile")) { + auto assetFilePath = get_fl_map_value(arguments, "assetFilePath"); + webView->loadFile(assetFilePath); + result->Success(true); + } + else if (string_equals(methodName, "loadData")) { + auto data = get_fl_map_value(arguments, "data"); + webView->loadData(data); + result->Success(true); + } + else if (string_equals(methodName, "reload")) { webView->reload(); result->Success(true); } - else if (method_call.method_name().compare("goBack") == 0) { + else if (string_equals(methodName, "goBack")) { webView->goBack(); result->Success(true); } - else if (method_call.method_name().compare("canGoBack") == 0) { + else if (string_equals(methodName, "canGoBack")) { result->Success(webView->canGoBack()); } - else if (method_call.method_name().compare("goForward") == 0) { + else if (string_equals(methodName, "goForward")) { webView->goForward(); result->Success(true); } - else if (method_call.method_name().compare("canGoForward") == 0) { + else if (string_equals(methodName, "canGoForward")) { result->Success(webView->canGoForward()); } - else if (method_call.method_name().compare("goBackOrForward") == 0) { + else if (string_equals(methodName, "goBackOrForward")) { auto steps = get_fl_map_value(arguments, "steps"); webView->goBackOrForward(steps); result->Success(true); } - else if (method_call.method_name().compare("canGoBackOrForward") == 0) { + else if (string_equals(methodName, "canGoBackOrForward")) { auto result_ = std::shared_ptr>(std::move(result)); auto steps = get_fl_map_value(arguments, "steps"); @@ -81,14 +101,14 @@ namespace flutter_inappwebview_plugin result_->Success(value); }); } - else if (method_call.method_name().compare("isLoading") == 0) { + else if (string_equals(methodName, "isLoading")) { result->Success(webView->isLoading()); } - else if (method_call.method_name().compare("stopLoading") == 0) { + else if (string_equals(methodName, "stopLoading")) { webView->stopLoading(); result->Success(true); } - else if (method_call.method_name().compare("evaluateJavascript") == 0) { + else if (string_equals(methodName, "evaluateJavascript")) { auto result_ = std::shared_ptr>(std::move(result)); auto source = get_fl_map_value(arguments, "source"); @@ -97,23 +117,43 @@ namespace flutter_inappwebview_plugin result_->Success(value); }); } - else if (method_call.method_name().compare("getCopyBackForwardList") == 0) { + else if (string_equals(methodName, "getCopyBackForwardList")) { auto result_ = std::shared_ptr>(std::move(result)); webView->getCopyBackForwardList([result_ = std::move(result_)](const std::unique_ptr value) { result_->Success(value->toEncodableMap()); }); } + else if (string_equals(methodName, "addUserScript")) { + auto userScript = std::make_unique(get_fl_map_value(arguments, "userScript")); + webView->addUserScript(std::move(userScript)); + result->Success(true); + } + else if (string_equals(methodName, "removeUserScript")) { + auto index = get_fl_map_value(arguments, "index"); + auto userScript = std::make_unique(get_fl_map_value(arguments, "userScript")); + webView->removeUserScript(index, std::move(userScript)); + result->Success(true); + } + else if (string_equals(methodName, "removeUserScriptsByGroupName")) { + auto groupName = get_fl_map_value(arguments, "groupName"); + webView->removeUserScriptsByGroupName(groupName); + result->Success(true); + } + else if (string_equals(methodName, "removeAllUserScripts")) { + webView->removeAllUserScripts(); + result->Success(true); + } // for inAppBrowser - else if (webView->inAppBrowser && method_call.method_name().compare("show") == 0) { + else if (webView->inAppBrowser && string_equals(methodName, "show")) { webView->inAppBrowser->show(); result->Success(true); } - else if (webView->inAppBrowser && method_call.method_name().compare("hide") == 0) { + else if (webView->inAppBrowser && string_equals(methodName, "hide")) { webView->inAppBrowser->hide(); result->Success(true); } - else if (webView->inAppBrowser && method_call.method_name().compare("close") == 0) { + else if (webView->inAppBrowser && string_equals(methodName, "close")) { webView->inAppBrowser->close(); result->Success(true); } @@ -211,6 +251,19 @@ namespace flutter_inappwebview_plugin channel->InvokeMethod("onUpdateVisitedHistory", std::move(arguments)); } + void WebViewChannelDelegate::onCallJsHandler(const std::string& handlerName, const std::string& args, std::unique_ptr callback) const + { + if (!channel) { + return; + } + + auto arguments = std::make_unique(flutter::EncodableMap{ + {"handlerName", handlerName}, + {"args", args} + }); + channel->InvokeMethod("onCallJsHandler", std::move(arguments), std::move(callback)); + } + WebViewChannelDelegate::~WebViewChannelDelegate() { debugLog("dealloc WebViewChannelDelegate"); diff --git a/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.h b/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.h index a3d8905d..f3141b4e 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.h +++ b/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.h @@ -22,12 +22,18 @@ namespace flutter_inappwebview_plugin public: InAppWebView* webView; - class ShouldOverrideUrlLoadingCallback : public BaseCallbackResult { + class ShouldOverrideUrlLoadingCallback : public BaseCallbackResult { public: ShouldOverrideUrlLoadingCallback(); ~ShouldOverrideUrlLoadingCallback() = default; }; + class CallJsHandlerCallback : public BaseCallbackResult { + public: + CallJsHandlerCallback(); + ~CallJsHandlerCallback() = default; + }; + WebViewChannelDelegate(InAppWebView* webView, flutter::BinaryMessenger* messenger); WebViewChannelDelegate(InAppWebView* webView, flutter::BinaryMessenger* messenger, const std::string& name); ~WebViewChannelDelegate(); @@ -43,6 +49,7 @@ namespace flutter_inappwebview_plugin void onReceivedHttpError(std::shared_ptr request, std::shared_ptr error) const; void onTitleChanged(const std::optional& title) const; void onUpdateVisitedHistory(const std::optional& url, const std::optional& isReload) const; + void onCallJsHandler(const std::string& handlerName, const std::string& args, std::unique_ptr callback) const; }; } diff --git a/flutter_inappwebview_windows/windows/plugin_scripts_js/javascript_bridge_js.cpp b/flutter_inappwebview_windows/windows/plugin_scripts_js/javascript_bridge_js.cpp index ba2c3066..a87baaf9 100644 --- a/flutter_inappwebview_windows/windows/plugin_scripts_js/javascript_bridge_js.cpp +++ b/flutter_inappwebview_windows/windows/plugin_scripts_js/javascript_bridge_js.cpp @@ -1,21 +1,12 @@ -#include +#include #include "javascript_bridge_js.h" namespace flutter_inappwebview_plugin { - const std::string JAVASCRIPT_BRIDGE_JS_SOURCE = "window." + JAVASCRIPT_BRIDGE_NAME + " = {}; \ - window." + JAVASCRIPT_BRIDGE_NAME + ".callHandler = function() { \ - var _callHandlerID = setTimeout(function() {}); \ - window.chrome.webview.postMessage({ 'internalHandlerName': 'callHandler', 'handlerName': arguments[0], '_callHandlerID' : _callHandlerID, 'args' : JSON.stringify(Array.prototype.slice.call(arguments, 1)) }); \ - return new Promise(function(resolve, reject) { \ - window." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = { resolve: resolve, reject : reject };\ - });\ - };"; - std::unique_ptr createJavaScriptBridgePluginScript() { - const std::set allowedOriginRules = { "*" }; + const std::vector allowedOriginRules = { "*" }; return std::make_unique( JAVASCRIPT_BRIDGE_JS_PLUGIN_SCRIPT_GROUP_NAME, JAVASCRIPT_BRIDGE_JS_SOURCE, diff --git a/flutter_inappwebview_windows/windows/plugin_scripts_js/javascript_bridge_js.h b/flutter_inappwebview_windows/windows/plugin_scripts_js/javascript_bridge_js.h index 5366bc6e..a10c832c 100644 --- a/flutter_inappwebview_windows/windows/plugin_scripts_js/javascript_bridge_js.h +++ b/flutter_inappwebview_windows/windows/plugin_scripts_js/javascript_bridge_js.h @@ -9,7 +9,21 @@ namespace flutter_inappwebview_plugin { const std::string JAVASCRIPT_BRIDGE_NAME = "flutter_inappwebview"; + const std::string JAVASCRIPT_BRIDGE_JS_SOURCE = "window." + JAVASCRIPT_BRIDGE_NAME + " = {}; \ + window." + JAVASCRIPT_BRIDGE_NAME + ".callHandler = function() { \ + var _callHandlerID = setTimeout(function() {}); \ + window.chrome.webview.postMessage({ 'name': 'callHandler', 'body': {'handlerName': arguments[0], '_callHandlerID' : _callHandlerID, 'args' : JSON.stringify(Array.prototype.slice.call(arguments, 1))} }); \ + return new Promise(function(resolve, reject) { \ + window." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = { resolve: resolve, reject : reject };\ + });\ + };"; const std::string JAVASCRIPT_BRIDGE_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_JAVASCRIPT_BRIDGE_JS_PLUGIN_SCRIPT"; + const std::string PLATFORM_READY_JS_SOURCE = "(function() { \ + if ((window.top == null || window.top === window) && window." + JAVASCRIPT_BRIDGE_NAME + " != null && window." + JAVASCRIPT_BRIDGE_NAME + "._platformReady == null) { \ + window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady')); \ + window." + JAVASCRIPT_BRIDGE_NAME + "._platformReady = true; \ + } \ + })();"; std::unique_ptr createJavaScriptBridgePluginScript(); } diff --git a/flutter_inappwebview_windows/windows/plugin_scripts_js/plugin_scripts_util.h b/flutter_inappwebview_windows/windows/plugin_scripts_js/plugin_scripts_util.h new file mode 100644 index 00000000..0c29cde5 --- /dev/null +++ b/flutter_inappwebview_windows/windows/plugin_scripts_js/plugin_scripts_util.h @@ -0,0 +1,11 @@ +#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_PLUGIN_SCRIPTS_UTIL_H_ +#define FLUTTER_INAPPWEBVIEW_PLUGIN_PLUGIN_SCRIPTS_UTIL_H_ + +#include + +namespace flutter_inappwebview_plugin +{ + const std::string VAR_PLACEHOLDER_VALUE = "$IN_APP_WEBVIEW_PLACEHOLDER_VALUE"; +} + +#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_PLUGIN_SCRIPTS_UTIL_H_ \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/types/plugin_script.cpp b/flutter_inappwebview_windows/windows/types/plugin_script.cpp index adc7d3f8..d9f9c73a 100644 --- a/flutter_inappwebview_windows/windows/types/plugin_script.cpp +++ b/flutter_inappwebview_windows/windows/types/plugin_script.cpp @@ -6,7 +6,7 @@ namespace flutter_inappwebview_plugin const std::optional& groupName, const std::string& source, const UserScriptInjectionTime& injectionTime, - const std::set& allowedOriginRules + const std::vector& allowedOriginRules ) : UserScript(groupName, source, injectionTime, allowedOriginRules) {} diff --git a/flutter_inappwebview_windows/windows/types/plugin_script.h b/flutter_inappwebview_windows/windows/types/plugin_script.h index b2fde408..1e633c88 100644 --- a/flutter_inappwebview_windows/windows/types/plugin_script.h +++ b/flutter_inappwebview_windows/windows/types/plugin_script.h @@ -13,7 +13,7 @@ namespace flutter_inappwebview_plugin const std::optional& groupName, const std::string& source, const UserScriptInjectionTime& injectionTime, - const std::set& allowedOriginRules + const std::vector& allowedOriginRules ); ~PluginScript(); }; diff --git a/flutter_inappwebview_windows/windows/types/user_script.cpp b/flutter_inappwebview_windows/windows/types/user_script.cpp index 3e5f39db..4befa0f4 100644 --- a/flutter_inappwebview_windows/windows/types/user_script.cpp +++ b/flutter_inappwebview_windows/windows/types/user_script.cpp @@ -1,3 +1,4 @@ +#include "../utils/map.h" #include "user_script.h" namespace flutter_inappwebview_plugin @@ -6,10 +7,17 @@ namespace flutter_inappwebview_plugin const std::optional& groupName, const std::string& source, const UserScriptInjectionTime& injectionTime, - const std::set& allowedOriginRules + const std::vector& allowedOriginRules ) : groupName(groupName), source(source), injectionTime(injectionTime), allowedOriginRules(allowedOriginRules) {} + UserScript::UserScript(const flutter::EncodableMap& map) + : groupName(get_optional_fl_map_value(map, "groupName")), + source(get_fl_map_value(map, "source")), + injectionTime(static_cast(get_fl_map_value(map, "injectionTime"))), + allowedOriginRules(functional_map(get_fl_map_value(map, "allowedOriginRules"), [](const flutter::EncodableValue& m) { return std::get(m); })) + {} + UserScript::~UserScript() {} } \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/types/user_script.h b/flutter_inappwebview_windows/windows/types/user_script.h index e6c79166..4c742cb8 100644 --- a/flutter_inappwebview_windows/windows/types/user_script.h +++ b/flutter_inappwebview_windows/windows/types/user_script.h @@ -1,14 +1,17 @@ #ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_USER_SCRIPT_H_ #define FLUTTER_INAPPWEBVIEW_PLUGIN_USER_SCRIPT_H_ +#include #include -#include #include +#include + +#include "../utils/flutter.h" namespace flutter_inappwebview_plugin { enum UserScriptInjectionTime { - atDocumentStart, + atDocumentStart = 0, atDocumentEnd }; @@ -19,14 +22,15 @@ namespace flutter_inappwebview_plugin const std::optional groupName; const std::string source; const UserScriptInjectionTime injectionTime; - const std::set allowedOriginRules; + const std::vector allowedOriginRules; UserScript( const std::optional& groupName, const std::string& source, const UserScriptInjectionTime& injectionTime, - const std::set& allowedOriginRules + const std::vector& allowedOriginRules ); + UserScript(const flutter::EncodableMap& map); ~UserScript(); }; } diff --git a/flutter_inappwebview_windows/windows/types/web_history.cpp b/flutter_inappwebview_windows/windows/types/web_history.cpp index b7cb9dee..aa89d9a2 100644 --- a/flutter_inappwebview_windows/windows/types/web_history.cpp +++ b/flutter_inappwebview_windows/windows/types/web_history.cpp @@ -1,4 +1,4 @@ -#include "../utils/util.h" +#include "../utils/vector.h" #include "web_history.h" namespace flutter_inappwebview_plugin diff --git a/flutter_inappwebview_windows/windows/utils/flutter.h b/flutter_inappwebview_windows/windows/utils/flutter.h index 6447b866..e8ed6444 100644 --- a/flutter_inappwebview_windows/windows/utils/flutter.h +++ b/flutter_inappwebview_windows/windows/utils/flutter.h @@ -1,5 +1,5 @@ -#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_FLUTTER_UTIL_H_ -#define FLUTTER_INAPPWEBVIEW_PLUGIN_FLUTTER_UTIL_H_ +#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_FLUTTER_H_ +#define FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_FLUTTER_H_ #include @@ -148,4 +148,4 @@ namespace flutter_inappwebview_plugin } } -#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_FLUTTER_UTIL_H_ \ No newline at end of file +#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_FLUTTER_H_ \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/utils/log.h b/flutter_inappwebview_windows/windows/utils/log.h index c410164a..e87cdd0c 100644 --- a/flutter_inappwebview_windows/windows/utils/log.h +++ b/flutter_inappwebview_windows/windows/utils/log.h @@ -4,12 +4,14 @@ #include #include #include +#include #include "strconv.h" namespace flutter_inappwebview_plugin { - static inline void debugLog(const std::string& msg, const bool& isError = false) + template + static inline void debugLog(const std::basic_string& msg, const bool& isError = false) { #ifndef NDEBUG if (isError) { @@ -22,11 +24,30 @@ namespace flutter_inappwebview_plugin #endif } + static inline void debugLog(const char* msg, const bool& isError = false) + { + debugLog(std::string(msg), isError); + } + static inline void debugLog(const std::wstring& msg, const bool& isError = false) { debugLog(wide_to_ansi(msg), isError); } + static inline void debugLog(const bool& value, const bool& isError = false) + { + debugLog(value ? "true" : "false", isError); + } + + template< + typename T, + typename = typename std::enable_if::value, T>::type + > + static inline void debugLog(const T& value, const bool& isError = false) + { + debugLog(std::to_string(value), isError); + } + static inline std::string getHRMessage(const HRESULT& error) { return wide_to_ansi(_com_error(error).ErrorMessage()); diff --git a/flutter_inappwebview_windows/windows/utils/map.h b/flutter_inappwebview_windows/windows/utils/map.h index 3a432d9f..c46d4a17 100644 --- a/flutter_inappwebview_windows/windows/utils/map.h +++ b/flutter_inappwebview_windows/windows/utils/map.h @@ -1,11 +1,10 @@ -#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_LOG_MAP_H_ -#define FLUTTER_INAPPWEBVIEW_PLUGIN_LOG_MAP_H_ +#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_MAP_H_ +#define FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_MAP_H_ #include #include #include #include -#include namespace flutter_inappwebview_plugin { @@ -33,39 +32,6 @@ namespace flutter_inappwebview_plugin auto itr = map.find(key); return itr != map.end() ? itr->second : nullptr; } - - template - static inline auto functional_map(Iterator begin, Iterator end, Func&& func) -> - std::vector()))> - { - using value_type = decltype(func(std::declval())); - - std::vector out_vector; - out_vector.reserve(std::distance(begin, end)); - - std::transform(begin, end, std::back_inserter(out_vector), - std::forward(func)); - - return out_vector; - } - - template - static inline auto functional_map(const T& iterable, Func&& func) -> - std::vector()))> - { - return functional_map(std::begin(iterable), std::end(iterable), - std::forward(func)); - } - - template - static inline auto functional_map(const std::optional& iterable, Func&& func) -> - std::vector()))> - { - if (!iterable.has_value()) { - return {}; - } - return functional_map(iterable.value(), std::forward(func)); - } } -#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_LOG_MAP_H_ \ No newline at end of file +#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_MAP_H_ \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/utils/string.h b/flutter_inappwebview_windows/windows/utils/string.h new file mode 100644 index 00000000..9fcf7e7d --- /dev/null +++ b/flutter_inappwebview_windows/windows/utils/string.h @@ -0,0 +1,112 @@ +#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_STRING_H_ +#define FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_STRING_H_ + +#include +#include + +#include "strconv.h" + +namespace flutter_inappwebview_plugin +{ + template + struct is_string + : std::false_type + {}; + + // Partial specialization - parameters used to qualify the specialization + template + struct is_string> + : std::true_type + {}; + + template + using is_basic_string = is_string>; + + template + static inline bool string_equals(const std::basic_string& s1, const std::basic_string& s2) + { + return s1.compare(s2) == 0; + } + + template + static inline bool string_equals(const std::basic_string& s1, const char* s2) + { + return s1.compare(s2) == 0; + } + + template + static inline bool string_equals(const char* s1, const std::basic_string& s2) + { + return s2.compare(s1) == 0; + } + + static inline bool string_equals(const std::string& s1, const std::wstring& s2) + { + return string_equals(s1, wide_to_ansi(s2)); + } + + static inline bool string_equals(const std::wstring& s1, const std::string& s2) + { + return string_equals(wide_to_ansi(s1), s2); + } + + template + static inline bool string_equals(const std::optional>& s1, const std::basic_string& s2) + { + return s1.has_value() ? string_equals(s1.value(), s2) : false; + } + + template + static inline bool string_equals(const std::basic_string& s1, const std::optional>& s2) + { + return s2.has_value() ? string_equals(s1, s2.value()) : false; + } + + template + static inline bool string_equals(const std::optional>& s1, const std::optional>& s2) + { + return s1.has_value() && s2.has_value() ? string_equals(s1.value(), s2.value()) : true; + } + + static inline void replace_all(std::string& source, const std::string& from, const std::string& to) + { + std::string newString; + newString.reserve(source.length()); // avoids a few memory allocations + + std::string::size_type lastPos = 0; + std::string::size_type findPos; + + while (std::string::npos != (findPos = source.find(from, lastPos))) { + newString.append(source, lastPos, findPos - lastPos); + newString += to; + lastPos = findPos + from.length(); + } + + // Care for the rest after last occurrence + newString += source.substr(lastPos); + + source.swap(newString); + } + + static inline std::string replace_all_copy(const std::string& source, const std::string& from, const std::string& to) + { + std::string newString; + newString.reserve(source.length()); // avoids a few memory allocations + + std::string::size_type lastPos = 0; + std::string::size_type findPos; + + while (std::string::npos != (findPos = source.find(from, lastPos))) { + newString.append(source, lastPos, findPos - lastPos); + newString += to; + lastPos = findPos + from.length(); + } + + // Care for the rest after last occurrence + newString += source.substr(lastPos); + + return newString; + } +} + +#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_STRING_H_ \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/utils/vector.h b/flutter_inappwebview_windows/windows/utils/vector.h index 5ba8558b..4a70e8a4 100644 --- a/flutter_inappwebview_windows/windows/utils/vector.h +++ b/flutter_inappwebview_windows/windows/utils/vector.h @@ -1,7 +1,8 @@ -#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_LOG_VECTOR_H_ -#define FLUTTER_INAPPWEBVIEW_PLUGIN_LOG_VECTOR_H_ +#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_VECTOR_H_ +#define FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_VECTOR_H_ #include +#include #include #include #include @@ -26,16 +27,73 @@ namespace flutter_inappwebview_plugin struct is_vector : is_vector_impl::type { }; template - static inline void vector_remove_el(std::vector& vec, const T& el) + static inline void vector_remove(std::vector& vec, const T& el) { std::remove(vec.begin(), vec.end(), el); } + template + static inline void vector_remove_if(std::vector& vec, UnaryPredicate&& predicate) + { + std::remove_if(vec.begin(), vec.end(), std::forward(predicate)); + } + template - static inline void vector_remove_erase_el(std::vector& vec, const T& el) + static inline void vector_remove_erase(std::vector& vec, const T& el) { vec.erase(std::remove(vec.begin(), vec.end(), el), vec.end()); } + + template + static inline void vector_remove_erase_if(std::vector& vec, UnaryPredicate&& predicate) + { + vec.erase(std::remove_if(vec.begin(), vec.end(), std::forward(predicate)), vec.end()); + } + + template + static inline bool vector_contains(const std::vector& vec, const T& value) + { + return std::find(vec.begin(), vec.end(), value) != vec.end(); + } + + template + static inline bool vector_contains_if(const std::vector& vec, UnaryPredicate&& predicate) + { + return std::find_if(vec.begin(), vec.end(), std::forward(predicate)) != vec.end(); + } + + template + static inline auto functional_map(Iterator begin, Iterator end, Func&& func) -> + std::vector()))> + { + using value_type = decltype(func(std::declval())); + + std::vector out_vector; + out_vector.reserve(std::distance(begin, end)); + + std::transform(begin, end, std::back_inserter(out_vector), + std::forward(func)); + + return out_vector; + } + + template + static inline auto functional_map(const T& iterable, Func&& func) -> + std::vector()))> + { + return functional_map(std::begin(iterable), std::end(iterable), + std::forward(func)); + } + + template + static inline auto functional_map(const std::optional& iterable, Func&& func) -> + std::vector()))> + { + if (!iterable.has_value()) { + return {}; + } + return functional_map(iterable.value(), std::forward(func)); + } } -#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_LOG_VECTOR_H_ \ No newline at end of file +#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_VECTOR_H_ \ No newline at end of file