windows: fixed in app browser dealloc, fixed on load stop event, implemented onReceivedError and onReceivedHttpError events

This commit is contained in:
unknown 2024-01-07 23:28:46 +01:00
parent 43aa01d944
commit dcfeeb7497
35 changed files with 681 additions and 200 deletions

View File

@ -30,6 +30,7 @@ class MyInAppBrowser extends InAppBrowser {
@override
Future onLoadStop(url) async {
pullToRefreshController?.endRefreshing();
print(await webViewController?.getUrl());
}
@override

View File

@ -64,6 +64,7 @@ class PlatformInAppBrowserCreationParams {
///- Android native WebView
///- iOS
///- MacOS
///- Windows
///{@endtemplate}
abstract class PlatformInAppBrowser extends PlatformInterface
implements Disposable {
@ -172,6 +173,7 @@ abstract class PlatformInAppBrowser extends PlatformInterface
///- Android native WebView
///- iOS
///- MacOS
///- Windows
///{@endtemplate}
Future<void> openUrlRequest(
{required URLRequest urlRequest,
@ -464,6 +466,7 @@ abstract class PlatformInAppBrowser extends PlatformInterface
///- Android native WebView
///- iOS
///- MacOS
///- Windows
///{@endtemplate}
bool isOpened() {
throw UnimplementedError(
@ -487,6 +490,7 @@ abstract class PlatformInAppBrowserEvents {
///- Android native WebView
///- iOS
///- MacOS
///- Windows
void onBrowserCreated() {}
///Event fired when the [PlatformInAppBrowser] window is closed.
@ -495,6 +499,7 @@ abstract class PlatformInAppBrowserEvents {
///- Android native WebView
///- iOS
///- MacOS
///- Windows
void onExit() {}
///Event fired when the main window is about to close.
@ -509,6 +514,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))
void onLoadStart(WebUri? url) {}
///Event fired when the [PlatformInAppBrowser] finishes loading an [url].
@ -517,6 +523,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))
void onLoadStop(WebUri? url) {}
///Use [onReceivedError] instead.
@ -529,6 +536,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))
void onReceivedError(WebResourceRequest request, WebResourceError error) {}
///Use [onReceivedHttpError] instead.
@ -547,6 +555,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))
void onReceivedHttpError(
WebResourceRequest request, WebResourceResponse errorResponse) {}

View File

@ -134,6 +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/iwebview2webview?view=webview2-0.8.355#get_source))
///{@endtemplate}
Future<WebUri?> getUrl() {
throw UnimplementedError(
@ -224,6 +225,7 @@ abstract class PlatformInAppWebViewController extends PlatformInterface
///- iOS ([Official API - WKWebView.load](https://developer.apple.com/documentation/webkit/wkwebview/1414954-load). If [allowingReadAccessTo] is used, [Official API - WKWebView.loadFileURL](https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl))
///- MacOS ([Official API - WKWebView.load](https://developer.apple.com/documentation/webkit/wkwebview/1414954-load). If [allowingReadAccessTo] is used, [Official API - WKWebView.loadFileURL](https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl))
///- Web
///- Windows ([Official API - ICoreWebView2_2.NavigateWithWebResourceRequest](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2_2?view=webview2-1.0.2210.55#navigatewithwebresourcerequest))
///{@endtemplate}
Future<void> loadUrl(
{required URLRequest urlRequest,

View File

@ -60,7 +60,12 @@ class WebResourceErrorType_ {
apiName: 'URLError.cannotConnectToHost',
apiUrl:
'https://developer.apple.com/documentation/foundation/urlerror/code/2883001-cannotconnecttohost',
value: -1004)
value: -1004),
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_CANNOT_CONNECT',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 12)
])
static const CANNOT_CONNECT_TO_HOST =
WebResourceErrorType_._internal("CANNOT_CONNECT_TO_HOST");
@ -124,7 +129,12 @@ class WebResourceErrorType_ {
apiName: 'URLError.cannotFindHost',
apiUrl:
'https://developer.apple.com/documentation/foundation/urlerror/code/2883157-cannotfindhost',
value: -1003)
value: -1003),
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_HOST_NAME_NOT_RESOLVED',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 13)
])
static const HOST_LOOKUP = WebResourceErrorType_._internal("HOST_LOOKUP");
@ -186,7 +196,12 @@ class WebResourceErrorType_ {
apiName: 'URLError.timedOut',
apiUrl:
'https://developer.apple.com/documentation/foundation/urlerror/code/2883027-timedout',
value: -1001)
value: -1001),
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_TIMEOUT',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 7)
])
static const TIMEOUT = WebResourceErrorType_._internal("TIMEOUT");
@ -217,7 +232,12 @@ class WebResourceErrorType_ {
apiName: 'URLError.unknown',
apiUrl:
'https://developer.apple.com/documentation/foundation/urlerror/2293357-unknown',
value: -1)
value: -1),
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_UNKNOWN',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 0)
])
static const UNKNOWN = WebResourceErrorType_._internal("UNKNOWN");
@ -276,7 +296,12 @@ class WebResourceErrorType_ {
apiName: 'URLError.cancelled',
apiUrl:
'https://developer.apple.com/documentation/foundation/urlerror/code/2883178-cancelled',
value: -999)
value: -999),
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_OPERATION_CANCELED',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 14)
])
static const CANCELLED = WebResourceErrorType_._internal("CANCELLED");
@ -291,7 +316,12 @@ class WebResourceErrorType_ {
apiName: 'URLError.networkConnectionLost',
apiUrl:
'https://developer.apple.com/documentation/foundation/urlerror/2293759-networkconnectionlost',
value: -1005)
value: -1005),
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_DISCONNECTED',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 11)
])
static const NETWORK_CONNECTION_LOST =
WebResourceErrorType_._internal("NETWORK_CONNECTION_LOST");
@ -356,7 +386,12 @@ class WebResourceErrorType_ {
apiName: 'URLError.badServerResponse',
apiUrl:
'https://developer.apple.com/documentation/foundation/urlerror/2293606-badserverresponse',
value: -1011)
value: -1011),
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_ERROR_HTTP_INVALID_SERVER_RESPONSE',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 8)
])
static const BAD_SERVER_RESPONSE =
WebResourceErrorType_._internal("BAD_SERVER_RESPONSE");
@ -389,7 +424,12 @@ class WebResourceErrorType_ {
apiName: 'URLError.userAuthenticationRequired',
apiUrl:
'https://developer.apple.com/documentation/foundation/urlerror/2293560-userauthenticationrequired',
value: -1013)
value: -1013),
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_VALID_AUTHENTICATION_CREDENTIALS_REQUIRED',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 17),
])
static const USER_AUTHENTICATION_REQUIRED =
WebResourceErrorType_._internal("USER_AUTHENTICATION_REQUIRED");
@ -892,4 +932,64 @@ class WebResourceErrorType_ {
])
static const BACKGROUND_SESSION_WAS_DISCONNECTED =
WebResourceErrorType_._internal("BACKGROUND_SESSION_WAS_DISCONNECTED");
///Indicates that the host is unreachable.
@EnumSupportedPlatforms(platforms: [
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_SERVER_UNREACHABLE',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 6),
])
static const SERVER_UNREACHABLE = WebResourceErrorType_._internal("SERVER_UNREACHABLE");
///Indicates that the connection was stopped.
@EnumSupportedPlatforms(platforms: [
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_CONNECTION_ABORTED',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 9)
])
static const CONNECTION_ABORTED = WebResourceErrorType_._internal("CONNECTION_ABORTED");
///Indicates that the connection was reset.
@EnumSupportedPlatforms(platforms: [
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_CONNECTION_RESET',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 10),
])
static const RESET = WebResourceErrorType_._internal("RESET");
///Indicates that the request redirect failed.
@EnumSupportedPlatforms(platforms: [
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_REDIRECT_FAILED',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 15),
])
static const REDIRECT_FAILED = WebResourceErrorType_._internal("REDIRECT_FAILED");
///Indicates that an unexpected error occurred.
@EnumSupportedPlatforms(platforms: [
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_UNEXPECTED_ERROR',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 16),
])
static const UNEXPECTED_ERROR = WebResourceErrorType_._internal("UNEXPECTED_ERROR");
///Indicates that user lacks proper authentication credentials for a proxy server.
@EnumSupportedPlatforms(platforms: [
EnumWindowsPlatform(
apiName: 'COREWEBVIEW2_WEB_ERROR_STATUS_VALID_PROXY_AUTHENTICATION_REQUIRED',
apiUrl:
'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status',
value: 18),
])
static const VALID_PROXY_AUTHENTICATION_REQUIRED = WebResourceErrorType_._internal("VALID_PROXY_AUTHENTICATION_REQUIRED");
}

View File

@ -97,6 +97,7 @@ class WebResourceErrorType {
///**Officially Supported Platforms/Implementations**:
///- iOS ([Official API - URLError.badServerResponse](https://developer.apple.com/documentation/foundation/urlerror/2293606-badserverresponse))
///- MacOS ([Official API - URLError.badServerResponse](https://developer.apple.com/documentation/foundation/urlerror/2293606-badserverresponse))
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_ERROR_HTTP_INVALID_SERVER_RESPONSE](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final BAD_SERVER_RESPONSE =
WebResourceErrorType._internalMultiPlatform('BAD_SERVER_RESPONSE', () {
switch (defaultTargetPlatform) {
@ -104,6 +105,8 @@ class WebResourceErrorType {
return -1011;
case TargetPlatform.macOS:
return -1011;
case TargetPlatform.windows:
return 8;
default:
break;
}
@ -154,6 +157,7 @@ class WebResourceErrorType {
///**Officially Supported Platforms/Implementations**:
///- iOS ([Official API - URLError.cancelled](https://developer.apple.com/documentation/foundation/urlerror/code/2883178-cancelled))
///- MacOS ([Official API - URLError.cancelled](https://developer.apple.com/documentation/foundation/urlerror/code/2883178-cancelled))
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_OPERATION_CANCELED](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final CANCELLED =
WebResourceErrorType._internalMultiPlatform('CANCELLED', () {
switch (defaultTargetPlatform) {
@ -161,6 +165,8 @@ class WebResourceErrorType {
return -999;
case TargetPlatform.macOS:
return -999;
case TargetPlatform.windows:
return 14;
default:
break;
}
@ -191,6 +197,7 @@ class WebResourceErrorType {
///- Android native WebView ([Official API - WebViewClient.ERROR_CONNECT](https://developer.android.com/reference/android/webkit/WebViewClient#ERROR_CONNECT))
///- iOS ([Official API - URLError.cannotConnectToHost](https://developer.apple.com/documentation/foundation/urlerror/code/2883001-cannotconnecttohost))
///- MacOS ([Official API - URLError.cannotConnectToHost](https://developer.apple.com/documentation/foundation/urlerror/code/2883001-cannotconnecttohost))
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_CANNOT_CONNECT](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final CANNOT_CONNECT_TO_HOST =
WebResourceErrorType._internalMultiPlatform('CANNOT_CONNECT_TO_HOST', () {
switch (defaultTargetPlatform) {
@ -200,6 +207,8 @@ class WebResourceErrorType {
return -1004;
case TargetPlatform.macOS:
return -1004;
case TargetPlatform.windows:
return 12;
default:
break;
}
@ -408,6 +417,21 @@ class WebResourceErrorType {
return null;
});
///Indicates that the connection was stopped.
///
///**Officially Supported Platforms/Implementations**:
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_CONNECTION_ABORTED](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final CONNECTION_ABORTED =
WebResourceErrorType._internalMultiPlatform('CONNECTION_ABORTED', () {
switch (defaultTargetPlatform) {
case TargetPlatform.windows:
return 9;
default:
break;
}
return null;
});
///The length of the resource data exceeds the maximum allowed.
///
///**Officially Supported Platforms/Implementations**:
@ -558,6 +582,7 @@ class WebResourceErrorType {
///- Android native WebView ([Official API - WebViewClient.ERROR_HOST_LOOKUP](https://developer.android.com/reference/android/webkit/WebViewClient#ERROR_HOST_LOOKUP))
///- iOS ([Official API - URLError.cannotFindHost](https://developer.apple.com/documentation/foundation/urlerror/code/2883157-cannotfindhost))
///- MacOS ([Official API - URLError.cannotFindHost](https://developer.apple.com/documentation/foundation/urlerror/code/2883157-cannotfindhost))
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_HOST_NAME_NOT_RESOLVED](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final HOST_LOOKUP =
WebResourceErrorType._internalMultiPlatform('HOST_LOOKUP', () {
switch (defaultTargetPlatform) {
@ -567,6 +592,8 @@ class WebResourceErrorType {
return -1003;
case TargetPlatform.macOS:
return -1003;
case TargetPlatform.windows:
return 13;
default:
break;
}
@ -611,6 +638,7 @@ class WebResourceErrorType {
///**Officially Supported Platforms/Implementations**:
///- iOS ([Official API - URLError.networkConnectionLost](https://developer.apple.com/documentation/foundation/urlerror/2293759-networkconnectionlost))
///- MacOS ([Official API - URLError.networkConnectionLost](https://developer.apple.com/documentation/foundation/urlerror/2293759-networkconnectionlost))
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_DISCONNECTED](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final NETWORK_CONNECTION_LOST =
WebResourceErrorType._internalMultiPlatform('NETWORK_CONNECTION_LOST',
() {
@ -619,6 +647,8 @@ class WebResourceErrorType {
return -1005;
case TargetPlatform.macOS:
return -1005;
case TargetPlatform.windows:
return 11;
default:
break;
}
@ -678,6 +708,21 @@ class WebResourceErrorType {
return null;
});
///Indicates that the request redirect failed.
///
///**Officially Supported Platforms/Implementations**:
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_REDIRECT_FAILED](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final REDIRECT_FAILED =
WebResourceErrorType._internalMultiPlatform('REDIRECT_FAILED', () {
switch (defaultTargetPlatform) {
case TargetPlatform.windows:
return 15;
default:
break;
}
return null;
});
///A redirect was specified by way of server response code, but the server didnt accompany this code with a redirect URL.
///
///**Officially Supported Platforms/Implementations**:
@ -716,6 +761,20 @@ class WebResourceErrorType {
return null;
});
///Indicates that the connection was reset.
///
///**Officially Supported Platforms/Implementations**:
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_CONNECTION_RESET](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final RESET = WebResourceErrorType._internalMultiPlatform('RESET', () {
switch (defaultTargetPlatform) {
case TargetPlatform.windows:
return 10;
default:
break;
}
return null;
});
///A requested resource couldn't be retrieved.
///This error can indicate a file-not-found situation, or decoding problems that prevent data from being processed correctly.
///
@ -830,12 +889,28 @@ class WebResourceErrorType {
return null;
});
///Indicates that the host is unreachable.
///
///**Officially Supported Platforms/Implementations**:
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_SERVER_UNREACHABLE](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final SERVER_UNREACHABLE =
WebResourceErrorType._internalMultiPlatform('SERVER_UNREACHABLE', () {
switch (defaultTargetPlatform) {
case TargetPlatform.windows:
return 6;
default:
break;
}
return null;
});
///Connection timed out.
///
///**Officially Supported Platforms/Implementations**:
///- Android native WebView ([Official API - WebViewClient.ERROR_TIMEOUT](https://developer.android.com/reference/android/webkit/WebViewClient#ERROR_TIMEOUT))
///- iOS ([Official API - URLError.timedOut](https://developer.apple.com/documentation/foundation/urlerror/code/2883027-timedout))
///- MacOS ([Official API - URLError.timedOut](https://developer.apple.com/documentation/foundation/urlerror/code/2883027-timedout))
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_TIMEOUT](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final TIMEOUT =
WebResourceErrorType._internalMultiPlatform('TIMEOUT', () {
switch (defaultTargetPlatform) {
@ -845,6 +920,8 @@ class WebResourceErrorType {
return -1001;
case TargetPlatform.macOS:
return -1001;
case TargetPlatform.windows:
return 7;
default:
break;
}
@ -887,12 +964,28 @@ class WebResourceErrorType {
return null;
});
///Indicates that an unexpected error occurred.
///
///**Officially Supported Platforms/Implementations**:
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_UNEXPECTED_ERROR](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final UNEXPECTED_ERROR =
WebResourceErrorType._internalMultiPlatform('UNEXPECTED_ERROR', () {
switch (defaultTargetPlatform) {
case TargetPlatform.windows:
return 16;
default:
break;
}
return null;
});
///The URL Loading System encountered an error that it cant interpret.
///
///**Officially Supported Platforms/Implementations**:
///- Android native WebView ([Official API - WebViewClient.ERROR_UNKNOWN](https://developer.android.com/reference/android/webkit/WebViewClient#ERROR_UNKNOWN))
///- iOS ([Official API - URLError.unknown](https://developer.apple.com/documentation/foundation/urlerror/2293357-unknown))
///- MacOS ([Official API - URLError.unknown](https://developer.apple.com/documentation/foundation/urlerror/2293357-unknown))
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_UNKNOWN](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final UNKNOWN =
WebResourceErrorType._internalMultiPlatform('UNKNOWN', () {
switch (defaultTargetPlatform) {
@ -902,6 +995,8 @@ class WebResourceErrorType {
return -1;
case TargetPlatform.macOS:
return -1;
case TargetPlatform.windows:
return 0;
default:
break;
}
@ -982,6 +1077,7 @@ class WebResourceErrorType {
///**Officially Supported Platforms/Implementations**:
///- iOS ([Official API - URLError.userAuthenticationRequired](https://developer.apple.com/documentation/foundation/urlerror/2293560-userauthenticationrequired))
///- MacOS ([Official API - URLError.userAuthenticationRequired](https://developer.apple.com/documentation/foundation/urlerror/2293560-userauthenticationrequired))
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_VALID_AUTHENTICATION_CREDENTIALS_REQUIRED](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final USER_AUTHENTICATION_REQUIRED =
WebResourceErrorType._internalMultiPlatform(
'USER_AUTHENTICATION_REQUIRED', () {
@ -990,6 +1086,8 @@ class WebResourceErrorType {
return -1013;
case TargetPlatform.macOS:
return -1013;
case TargetPlatform.windows:
return 17;
default:
break;
}
@ -1016,6 +1114,22 @@ class WebResourceErrorType {
return null;
});
///Indicates that user lacks proper authentication credentials for a proxy server.
///
///**Officially Supported Platforms/Implementations**:
///- Windows ([Official API - COREWEBVIEW2_WEB_ERROR_STATUS_VALID_PROXY_AUTHENTICATION_REQUIRED](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2210.55#corewebview2_web_error_status))
static final VALID_PROXY_AUTHENTICATION_REQUIRED =
WebResourceErrorType._internalMultiPlatform(
'VALID_PROXY_AUTHENTICATION_REQUIRED', () {
switch (defaultTargetPlatform) {
case TargetPlatform.windows:
return 18;
default:
break;
}
return null;
});
///A server reported that a URL has a non-zero content length, but terminated the network connection gracefully without sending any data.
///
///**Officially Supported Platforms/Implementations**:
@ -1057,6 +1171,7 @@ class WebResourceErrorType {
WebResourceErrorType.CANNOT_WRITE_TO_FILE,
WebResourceErrorType.CLIENT_CERTIFICATE_REJECTED,
WebResourceErrorType.CLIENT_CERTIFICATE_REQUIRED,
WebResourceErrorType.CONNECTION_ABORTED,
WebResourceErrorType.DATA_LENGTH_EXCEEDS_MAXIMUM,
WebResourceErrorType.DATA_NOT_ALLOWED,
WebResourceErrorType.DOWNLOAD_DECODING_FAILED_MID_STREAM,
@ -1072,17 +1187,21 @@ class WebResourceErrorType {
WebResourceErrorType.NOT_CONNECTED_TO_INTERNET,
WebResourceErrorType.NO_PERMISSIONS_TO_READ_FILE,
WebResourceErrorType.PROXY_AUTHENTICATION,
WebResourceErrorType.REDIRECT_FAILED,
WebResourceErrorType.REDIRECT_TO_NON_EXISTENT_LOCATION,
WebResourceErrorType.REQUEST_BODY_STREAM_EXHAUSTED,
WebResourceErrorType.RESET,
WebResourceErrorType.RESOURCE_UNAVAILABLE,
WebResourceErrorType.SECURE_CONNECTION_FAILED,
WebResourceErrorType.SERVER_CERTIFICATE_HAS_BAD_DATE,
WebResourceErrorType.SERVER_CERTIFICATE_HAS_UNKNOWN_ROOT,
WebResourceErrorType.SERVER_CERTIFICATE_NOT_YET_VALID,
WebResourceErrorType.SERVER_CERTIFICATE_UNTRUSTED,
WebResourceErrorType.SERVER_UNREACHABLE,
WebResourceErrorType.TIMEOUT,
WebResourceErrorType.TOO_MANY_REDIRECTS,
WebResourceErrorType.TOO_MANY_REQUESTS,
WebResourceErrorType.UNEXPECTED_ERROR,
WebResourceErrorType.UNKNOWN,
WebResourceErrorType.UNSAFE_RESOURCE,
WebResourceErrorType.UNSUPPORTED_AUTH_SCHEME,
@ -1090,6 +1209,7 @@ class WebResourceErrorType {
WebResourceErrorType.USER_AUTHENTICATION_FAILED,
WebResourceErrorType.USER_AUTHENTICATION_REQUIRED,
WebResourceErrorType.USER_CANCELLED_AUTHENTICATION,
WebResourceErrorType.VALID_PROXY_AUTHENTICATION_REQUIRED,
WebResourceErrorType.ZERO_BYTE_RESOURCE,
].toSet();

View File

@ -65,7 +65,7 @@ class WindowsInAppBrowser extends PlatformInAppBrowser with ChannelController {
return _staticValue;
}
WindowsInAppBrowserCreationParams get _macosParams =>
WindowsInAppBrowserCreationParams get _windowsParams =>
params as WindowsInAppBrowserCreationParams;
static const MethodChannel _staticChannel =
@ -95,7 +95,7 @@ class WindowsInAppBrowser extends PlatformInAppBrowser with ChannelController {
channel!,
this,
this.initialUserScripts);
_macosParams.findInteractionController?.init(id);
_windowsParams.findInteractionController?.init(id);
}
_debugLog(String method, dynamic args) {

View File

@ -49,12 +49,11 @@ add_custom_command(
# Any new source files that you add to the plugin should be added here.
list(APPEND PLUGIN_SOURCES
"flutter_inappwebview_windows_base_plugin.h"
"flutter_inappwebview_windows_base_plugin.cpp"
"flutter_inappwebview_windows_plugin.cpp"
"flutter_inappwebview_windows_plugin.h"
"utils/strconv.h"
"utils/util.h"
"utils/flutter.h"
"types/channel_delegate.cpp"
"types/channel_delegate.h"
"types/base_callback_result.h"
@ -62,6 +61,12 @@ list(APPEND PLUGIN_SOURCES
"types/url_request.h"
"types/navigation_action.cpp"
"types/navigation_action.h"
"types/web_resource_error.cpp"
"types/web_resource_error.h"
"types/web_resource_request.cpp"
"types/web_resource_request.h"
"types/web_resource_response.cpp"
"types/web_resource_response.h"
"in_app_webview/in_app_webview.cpp"
"in_app_webview/in_app_webview.h"
"in_app_webview/webview_channel_delegate.cpp"

View File

@ -1,14 +0,0 @@
#include "flutter_inappwebview_windows_base_plugin.h"
namespace flutter_inappwebview_plugin
{
FlutterInappwebviewWindowsBasePlugin::FlutterInappwebviewWindowsBasePlugin(flutter::PluginRegistrarWindows* registrar) : registrar(registrar)
{
}
FlutterInappwebviewWindowsBasePlugin::~FlutterInappwebviewWindowsBasePlugin()
{
}
}

View File

@ -1,18 +0,0 @@
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_BASE_PLUGIN_H_
#define FLUTTER_INAPPWEBVIEW_PLUGIN_BASE_PLUGIN_H_
#include <flutter/plugin_registrar_windows.h>
namespace flutter_inappwebview_plugin
{
class FlutterInappwebviewWindowsBasePlugin : public flutter::Plugin, public std::enable_shared_from_this<FlutterInappwebviewWindowsBasePlugin> {
public:
flutter::PluginRegistrarWindows* registrar;
FlutterInappwebviewWindowsBasePlugin(flutter::PluginRegistrarWindows* registrar);
virtual ~FlutterInappwebviewWindowsBasePlugin();
};
}
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_BASE_PLUGIN_H_

View File

@ -3,6 +3,8 @@
#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include "in_app_browser/in_app_browser_manager.h"
namespace flutter_inappwebview_plugin
{
// static
@ -13,7 +15,7 @@ namespace flutter_inappwebview_plugin
}
FlutterInappwebviewWindowsPlugin::FlutterInappwebviewWindowsPlugin(flutter::PluginRegistrarWindows* registrar)
: FlutterInappwebviewWindowsBasePlugin(registrar)
: registrar(registrar)
{
inAppBrowserManager = std::make_unique<InAppBrowserManager>(this);
}

View File

@ -4,16 +4,13 @@
#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include <memory>
#include "flutter_inappwebview_windows_base_plugin.h"
#include "in_app_browser/in_app_browser_manager.h"
namespace flutter_inappwebview_plugin
{
class FlutterInappwebviewWindowsPlugin : public FlutterInappwebviewWindowsBasePlugin {
class InAppBrowserManager;
class FlutterInappwebviewWindowsPlugin : public flutter::Plugin {
public:
flutter::PluginRegistrarWindows* registrar;
std::unique_ptr<InAppBrowserManager> inAppBrowserManager;
static void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar);

View File

@ -1,33 +1,11 @@
#include <Windows.h>
#include "in_app_browser.h"
#include <cstdint>
#include <memory>
#include "flutter/event_channel.h"
#include "flutter/plugin_registrar.h"
#include "flutter/plugin_registrar_windows.h"
#include "flutter/method_channel.h"
#include "flutter/encodable_value.h"
#include <stdlib.h>
#include <string>
#include <tchar.h>
#include <wil/wrl.h>
#include <wil/com.h>
#include "../utils/strconv.h"
#include "../utils/util.h"
#include <WebView2.h>
#include <WebView2EnvironmentOptions.h>
#include "in_app_browser_manager.h"
namespace flutter_inappwebview_plugin
{
using namespace Microsoft::WRL;
const wchar_t* CLASS_NAME = L"InAppBrowser";
InAppBrowser::InAppBrowser(FlutterInappwebviewWindowsBasePlugin* plugin, const InAppBrowserCreationParams& params)
InAppBrowser::InAppBrowser(FlutterInappwebviewWindowsPlugin* plugin, const InAppBrowserCreationParams& params)
: plugin(plugin),
m_hInstance(GetModuleHandle(nullptr)),
id(params.id),
@ -35,7 +13,7 @@ namespace flutter_inappwebview_plugin
channelDelegate(std::make_unique<InAppBrowserChannelDelegate>(id, plugin->registrar->messenger()))
{
WNDCLASS wndClass = {};
wndClass.lpszClassName = CLASS_NAME;
wndClass.lpszClassName = InAppBrowser::CLASS_NAME;
wndClass.hInstance = m_hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
@ -45,8 +23,8 @@ namespace flutter_inappwebview_plugin
m_hWnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
InAppBrowser::CLASS_NAME, // Window class
L"", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
@ -186,15 +164,19 @@ namespace flutter_inappwebview_plugin
) noexcept {
switch (message) {
case WM_DESTROY: {
webView.reset();
// might receive multiple WM_DESTROY messages.
if (!destroyed_) {
destroyed_ = true;
webView.reset();
if (channelDelegate) {
channelDelegate->onExit();
}
if (plugin && plugin->inAppBrowserManager) {
plugin->inAppBrowserManager->browsers.erase(id);
}
}
return 0;
}

View File

@ -6,7 +6,7 @@
#include <optional>
#include <wil/com.h>
#include "../flutter_inappwebview_windows_base_plugin.h"
#include "../flutter_inappwebview_windows_plugin.h"
#include "../in_app_webview/in_app_webview.h"
#include "../types/url_request.h"
#include "in_app_browser_channel_delegate.h"
@ -22,19 +22,20 @@ namespace flutter_inappwebview_plugin
class InAppBrowser {
public:
static inline const std::string METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappbrowser_";
static inline const wchar_t* CLASS_NAME = L"InAppBrowser";
static LRESULT CALLBACK WndProc(HWND window,
UINT message,
WPARAM wparam,
LPARAM lparam) noexcept;
FlutterInappwebviewWindowsBasePlugin* plugin;
FlutterInappwebviewWindowsPlugin* plugin;
std::string id;
std::optional<URLRequest> initialUrlRequest;
std::unique_ptr<InAppWebView> webView;
std::unique_ptr<InAppBrowserChannelDelegate> channelDelegate;
InAppBrowser(FlutterInappwebviewWindowsBasePlugin* plugin, const InAppBrowserCreationParams& params);
InAppBrowser(FlutterInappwebviewWindowsPlugin* plugin, const InAppBrowserCreationParams& params);
~InAppBrowser();
private:

View File

@ -5,7 +5,7 @@
namespace flutter_inappwebview_plugin
{
InAppBrowserChannelDelegate::InAppBrowserChannelDelegate(const std::string id, flutter::BinaryMessenger* messenger)
InAppBrowserChannelDelegate::InAppBrowserChannelDelegate(const std::string& id, flutter::BinaryMessenger* messenger)
: ChannelDelegate(messenger, InAppBrowser::METHOD_CHANNEL_NAME_PREFIX + id)
{

View File

@ -11,7 +11,7 @@ namespace flutter_inappwebview_plugin
class InAppBrowserChannelDelegate : public ChannelDelegate
{
public:
InAppBrowserChannelDelegate(const std::string id, flutter::BinaryMessenger* messenger);
InAppBrowserChannelDelegate(const std::string& id, flutter::BinaryMessenger* messenger);
~InAppBrowserChannelDelegate();
void HandleMethodCall(

View File

@ -1,16 +1,17 @@
#include <memory>
#include <flutter/method_channel.h>
#include <flutter/standard_method_codec.h>
#include <optional>
#include "in_app_browser_manager.h"
#include "../types/url_request.h"
#include "../utils/util.h"
#include "../utils/flutter.h"
namespace flutter_inappwebview_plugin
{
InAppBrowserManager::InAppBrowserManager(FlutterInappwebviewWindowsBasePlugin* plugin)
InAppBrowserManager::InAppBrowserManager(FlutterInappwebviewWindowsPlugin* plugin)
: plugin(plugin), ChannelDelegate(plugin->registrar->messenger(), InAppBrowserManager::METHOD_CHANNEL_NAME)
{
@ -31,16 +32,16 @@ namespace flutter_inappwebview_plugin
void InAppBrowserManager::open(const flutter::EncodableMap* arguments)
{
auto id = std::get<std::string>(arguments->at(flutter::EncodableValue("id")));
auto urlRequestMap = std::get_if<flutter::EncodableMap>(&arguments->at(flutter::EncodableValue("urlRequest")));
auto urlRequest = make_pointer_optional<URLRequest>(new URLRequest(*urlRequestMap));
auto id = get_fl_map_value<std::string>(*arguments, "id");
auto urlRequestMap = get_optional_fl_map_value<flutter::EncodableMap>(*arguments, "urlRequest");
std::optional<URLRequest> urlRequest = urlRequestMap.has_value() ? std::make_optional<URLRequest>(urlRequestMap.value()) : std::optional<URLRequest>{};
InAppBrowserCreationParams params = {
id,
urlRequest
};
auto inAppBrowser = std::make_unique<InAppBrowser>(plugin, params);
browsers[id] = std::move(inAppBrowser);
browsers.insert({ id, std::move(inAppBrowser) });
}
InAppBrowserManager::~InAppBrowserManager()

View File

@ -6,7 +6,7 @@
#include <flutter/method_channel.h>
#include <flutter/standard_message_codec.h>
#include "../flutter_inappwebview_windows_base_plugin.h"
#include "../flutter_inappwebview_windows_plugin.h"
#include "in_app_browser.h"
@ -19,10 +19,10 @@ namespace flutter_inappwebview_plugin
public:
static inline const std::string METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappbrowser";
FlutterInappwebviewWindowsBasePlugin* plugin;
FlutterInappwebviewWindowsPlugin* plugin;
std::map<std::string, std::unique_ptr<InAppBrowser>> browsers;
InAppBrowserManager(FlutterInappwebviewWindowsBasePlugin* plugin);
InAppBrowserManager(FlutterInappwebviewWindowsPlugin* plugin);
~InAppBrowserManager();
void HandleMethodCall(

View File

@ -6,18 +6,20 @@
#include <Shlwapi.h>
#include "../utils/strconv.h"
#include "../utils/util.h"
#include "../types/web_resource_request.h"
#include "../types/web_resource_error.h"
namespace flutter_inappwebview_plugin
{
using namespace Microsoft::WRL;
InAppWebView::InAppWebView(FlutterInappwebviewWindowsBasePlugin* plugin, std::variant<std::string, int> id, const HWND parentWindow, const std::function<void()> completionHandler)
InAppWebView::InAppWebView(FlutterInappwebviewWindowsPlugin* plugin, const std::variant<std::string, int>& id, const HWND parentWindow, const std::function<void()> completionHandler)
: plugin(plugin), id(id), channelDelegate(std::make_unique<WebViewChannelDelegate>(this, plugin->registrar->messenger()))
{
createWebView(parentWindow, completionHandler);
}
InAppWebView::InAppWebView(FlutterInappwebviewWindowsBasePlugin* plugin, std::variant<std::string, int> id, const HWND parentWindow, const std::string& channelName, const std::function<void()> completionHandler)
InAppWebView::InAppWebView(FlutterInappwebviewWindowsPlugin* plugin, const std::variant<std::string, int>& id, const HWND parentWindow, const std::string& channelName, const std::function<void()> completionHandler)
: plugin(plugin), id(id), channelDelegate(std::make_unique<WebViewChannelDelegate>(this, plugin->registrar->messenger(), channelName))
{
createWebView(parentWindow, completionHandler);
@ -29,7 +31,7 @@ namespace flutter_inappwebview_plugin
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[parentWindow, completionHandler, this](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
webViewEnv = env;
// Create a CoreWebView2Controller and get the associated CoreWebView2 whose parent is the main window hWnd
// Create a CoreWebView2Controller and get the associated CoreWebView2 whose parent is the main window HWND
env->CreateCoreWebView2Controller(parentWindow, Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
[parentWindow, completionHandler, this](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT {
if (controller != nullptr) {
@ -67,9 +69,9 @@ namespace flutter_inappwebview_plugin
}
wil::unique_cotaskmem_string uri = nullptr;
std::optional<std::string> url = SUCCEEDED(args->get_Uri(&uri)) ? wide_to_utf8(std::wstring(uri.get())) : std::optional<std::string>{};
std::optional<std::string> url = SUCCEEDED(args->get_Uri(&uri)) ? wide_to_utf8(uri.get()) : std::optional<std::string>{};
wil::unique_cotaskmem_string method = nullptr;
wil::unique_cotaskmem_string requestMethod = nullptr;
wil::com_ptr<ICoreWebView2HttpRequestHeaders> requestHeaders = nullptr;
std::optional<std::map<std::string, std::string>> headers = std::optional<std::map<std::string, std::string>>{};
if (SUCCEEDED(args->get_RequestHeaders(&requestHeaders))) {
@ -83,27 +85,34 @@ namespace flutter_inappwebview_plugin
wil::unique_cotaskmem_string value;
if (SUCCEEDED(iterator->GetCurrentHeader(&name, &value))) {
headers->insert({ wide_to_utf8(std::wstring(name.get())), wide_to_utf8(std::wstring(value.get())) });
headers->insert({ wide_to_utf8(name.get()), wide_to_utf8(value.get()) });
}
BOOL hasNext = FALSE;
iterator->MoveNext(&hasNext);
}
requestHeaders->GetHeader(L"Flutter-InAppWebView-Request-Method", &method);
requestHeaders->GetHeader(L"Flutter-InAppWebView-Request-Method", &requestMethod);
requestHeaders->RemoveHeader(L"Flutter-InAppWebView-Request-Method");
}
if (callShouldOverrideUrlLoading && method == nullptr) {
// for some reason, we can't cancel and load an URL with other HTTP methods other than GET,
// so ignore the shouldOverrideUrlLoading event.
std::optional<std::string> method = requestMethod ? wide_to_utf8(requestMethod.get()) : std::optional<std::string>{};
auto urlRequest = std::make_shared<URLRequest>(url, std::nullopt, headers, std::nullopt);
auto navigationAction = std::make_unique<NavigationAction>(
auto urlRequest = std::make_shared<URLRequest>(url, method, headers, std::nullopt);
auto navigationAction = std::make_shared<NavigationAction>(
urlRequest,
true
);
UINT64 navigationId;
if (SUCCEEDED(args->get_NavigationId(&navigationId))) {
navigationActions.insert({navigationId, navigationAction});
}
if (callShouldOverrideUrlLoading && requestMethod == nullptr) {
// for some reason, we can't cancel and load an URL with other HTTP methods than GET,
// so ignore the shouldOverrideUrlLoading event.
auto callback = std::make_unique<WebViewChannelDelegate::ShouldOverrideUrlLoadingCallback>();
callback->nonNullSuccess = [this, urlRequest](const NavigationActionPolicy actionPolicy) {
callShouldOverrideUrlLoading = false;
@ -137,9 +146,17 @@ namespace flutter_inappwebview_plugin
webView->add_NavigationCompleted(
Callback<ICoreWebView2NavigationCompletedEventHandler>(
[this](ICoreWebView2* sender, ICoreWebView2NavigationCompletedEventArgs* args) {
COREWEBVIEW2_WEB_ERROR_STATUS web_error_status;
args->get_WebErrorStatus(&web_error_status);
debugLog("WebErrorStatus " + std::to_string(web_error_status) + "\n");
std::shared_ptr<NavigationAction> navigationAction;
UINT64 navigationId;
if (SUCCEEDED(args->get_NavigationId(&navigationId))) {
navigationAction = map_at_or_null(navigationActions, navigationId);
if (navigationAction) {
navigationActions.erase(navigationId);
}
}
COREWEBVIEW2_WEB_ERROR_STATUS webErrorType = COREWEBVIEW2_WEB_ERROR_STATUS_UNKNOWN;
args->get_WebErrorStatus(&webErrorType);
BOOL isSuccess;
args->get_IsSuccess(&isSuccess);
@ -150,7 +167,21 @@ namespace flutter_inappwebview_plugin
if (isSuccess) {
channelDelegate->onLoadStop(url);
}
else if (!InAppWebView::isSslError(webErrorType) && navigationAction) {
auto webResourceRequest = std::make_unique<WebResourceRequest>(url, navigationAction->request->method, navigationAction->request->headers, navigationAction->isForMainFrame);
int httpStatusCode = 0;
wil::com_ptr<ICoreWebView2NavigationCompletedEventArgs2> args2;
if (SUCCEEDED(args->QueryInterface(IID_PPV_ARGS(&args2))) && SUCCEEDED(args2->get_HttpStatusCode(&httpStatusCode)) && httpStatusCode >= 400) {
auto webResourceResponse = std::make_unique<WebResourceResponse>(httpStatusCode);
channelDelegate->onReceivedHttpError(std::move(webResourceRequest), std::move(webResourceResponse));
}
else if (httpStatusCode < 400) {
auto webResourceError = std::make_unique<WebResourceError>(WebErrorStatusDescription[webErrorType], webErrorType);
channelDelegate->onReceivedError(std::move(webResourceRequest), std::move(webResourceError));
}
}
}
return S_OK;
}
).Get(), nullptr);
@ -159,10 +190,10 @@ namespace flutter_inappwebview_plugin
std::optional<std::string> InAppWebView::getUrl() const
{
LPWSTR uri = nullptr;
return SUCCEEDED(webView->get_Source(&uri)) ? wide_to_utf8(std::wstring(uri)) : std::optional<std::string>{};
return SUCCEEDED(webView->get_Source(&uri)) ? wide_to_utf8(uri) : std::optional<std::string>{};
}
void InAppWebView::loadUrl(const URLRequest urlRequest) const
void InAppWebView::loadUrl(const URLRequest& urlRequest) const
{
if (!webView || !urlRequest.url.has_value()) {
return;
@ -191,7 +222,7 @@ namespace flutter_inappwebview_plugin
);
wil::com_ptr<ICoreWebView2HttpRequestHeaders> requestHeaders;
if (SUCCEEDED(webResourceRequest->get_Headers(&requestHeaders))) {
if (urlRequest.method.has_value() && urlRequest.method.value().compare("GET") != 0) {
if (method.compare(L"GET") != 0) {
requestHeaders->SetHeader(L"Flutter-InAppWebView-Request-Method", method.c_str());
}
if (urlRequest.headers.has_value()) {
@ -208,6 +239,10 @@ namespace flutter_inappwebview_plugin
}
}
bool InAppWebView::isSslError(const COREWEBVIEW2_WEB_ERROR_STATUS& webErrorStatus) {
return webErrorStatus >= COREWEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_COMMON_NAME_IS_INCORRECT && webErrorStatus <= COREWEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_IS_INVALID;
}
InAppWebView::~InAppWebView()
{
debugLog("dealloc InAppWebView");
@ -217,6 +252,7 @@ namespace flutter_inappwebview_plugin
if (webViewController) {
webViewController->Close();
}
navigationActions.clear();
plugin = nullptr;
}
}

View File

@ -6,8 +6,9 @@
#include <WebView2.h>
#include <wil/com.h>
#include "../types/url_request.h"
#include "../types/navigation_action.h"
#include "webview_channel_delegate.h"
#include "../flutter_inappwebview_windows_base_plugin.h"
#include "../flutter_inappwebview_windows_plugin.h"
namespace flutter_inappwebview_plugin
{
@ -18,20 +19,22 @@ namespace flutter_inappwebview_plugin
public:
static inline const std::string METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_";
FlutterInappwebviewWindowsBasePlugin* plugin;
std::variant<std::string, int> id;
const FlutterInappwebviewWindowsPlugin* plugin;
const std::variant<std::string, int> id;
wil::com_ptr<ICoreWebView2Environment> webViewEnv;
wil::com_ptr<ICoreWebView2Controller> webViewController;
wil::com_ptr<ICoreWebView2> webView;
std::unique_ptr<WebViewChannelDelegate> channelDelegate;
const std::unique_ptr<WebViewChannelDelegate> channelDelegate;
std::map<UINT64, std::shared_ptr<NavigationAction>> navigationActions = {};
InAppWebView(FlutterInappwebviewWindowsBasePlugin* plugin, std::variant<std::string, int> id, const HWND parentWindow, const std::function<void()> completionHandler);
InAppWebView(FlutterInappwebviewWindowsBasePlugin* plugin, std::variant<std::string, int> id, const HWND parentWindow, const std::string& channelName, const std::function<void()> completionHandler);
InAppWebView(FlutterInappwebviewWindowsPlugin* plugin, const std::variant<std::string, int>& id, const HWND parentWindow, const std::function<void()> completionHandler);
InAppWebView(FlutterInappwebviewWindowsPlugin* plugin, const std::variant<std::string, int>& id, const HWND parentWindow, const std::string& channelName, const std::function<void()> completionHandler);
~InAppWebView();
std::optional<std::string> getUrl() const;
void loadUrl(const URLRequest urlRequest) const;
void loadUrl(const URLRequest& urlRequest) const;
static bool isSslError(const COREWEBVIEW2_WEB_ERROR_STATUS& webErrorStatus);
private:
bool callShouldOverrideUrlLoading = true;
void createWebView(const HWND parentWindow, const std::function<void()> completionHandler);

View File

@ -1,7 +1,7 @@
#include "in_app_webview.h"
#include "webview_channel_delegate.h"
#include "../utils/util.h"
#include "../utils/flutter.h"
#include "../utils/strconv.h"
#include "../types/base_callback_result.h"
@ -38,43 +38,44 @@ namespace flutter_inappwebview_plugin
}
if (method_call.method_name().compare("getUrl") == 0) {
result->Success(optional_to_fl_value(webView->getUrl()));
} else if (method_call.method_name().compare("loadUrl") == 0) {
result->Success(make_fl_value(webView->getUrl()));
}
else if (method_call.method_name().compare("loadUrl") == 0) {
auto& arguments = std::get<flutter::EncodableMap>(*method_call.arguments());
auto urlRequest = std::make_unique<URLRequest>(get_fl_map_value<flutter::EncodableMap>(arguments, "urlRequest"));
webView->loadUrl(*urlRequest);
result->Success(flutter::EncodableValue(true));
result->Success(make_fl_value(true));
}
else {
result->NotImplemented();
}
}
void WebViewChannelDelegate::onLoadStart(const std::optional<std::string> url) const
void WebViewChannelDelegate::onLoadStart(const std::optional<std::string>& url) const
{
if (!channel) {
return;
}
auto arguments = std::make_unique<flutter::EncodableValue>(flutter::EncodableMap {
{flutter::EncodableValue("url"), optional_to_fl_value(url)},
{flutter::EncodableValue("url"), make_fl_value(url)},
});
channel->InvokeMethod("onLoadStart", std::move(arguments));
}
void WebViewChannelDelegate::onLoadStop(const std::optional<std::string> url) const
void WebViewChannelDelegate::onLoadStop(const std::optional<std::string>& url) const
{
if (!channel) {
return;
}
auto arguments = std::make_unique<flutter::EncodableValue>(flutter::EncodableMap{
{flutter::EncodableValue("url"), optional_to_fl_value(url)},
{flutter::EncodableValue("url"), make_fl_value(url)},
});
channel->InvokeMethod("onLoadStop", std::move(arguments));
}
void WebViewChannelDelegate::shouldOverrideUrlLoading(std::shared_ptr<NavigationAction> navigationAction, std::unique_ptr<ShouldOverrideUrlLoadingCallback> callback)
void WebViewChannelDelegate::shouldOverrideUrlLoading(std::shared_ptr<NavigationAction> navigationAction, std::unique_ptr<ShouldOverrideUrlLoadingCallback> callback) const
{
if (!channel) {
return;
@ -84,6 +85,32 @@ namespace flutter_inappwebview_plugin
channel->InvokeMethod("shouldOverrideUrlLoading", std::move(arguments), std::move(callback));
}
void WebViewChannelDelegate::onReceivedError(std::shared_ptr<WebResourceRequest> request, std::shared_ptr<WebResourceError> error) const
{
if (!channel) {
return;
}
auto arguments = std::make_unique<flutter::EncodableValue>(flutter::EncodableMap{
{flutter::EncodableValue("request"), request->toEncodableMap()},
{flutter::EncodableValue("error"), error->toEncodableMap()},
});
channel->InvokeMethod("onReceivedError", std::move(arguments));
}
void WebViewChannelDelegate::onReceivedHttpError(std::shared_ptr<WebResourceRequest> request, std::shared_ptr<WebResourceResponse> errorResponse) const
{
if (!channel) {
return;
}
auto arguments = std::make_unique<flutter::EncodableValue>(flutter::EncodableMap{
{flutter::EncodableValue("request"), request->toEncodableMap()},
{flutter::EncodableValue("errorResponse"), errorResponse->toEncodableMap()},
});
channel->InvokeMethod("onReceivedHttpError", std::move(arguments));
}
WebViewChannelDelegate::~WebViewChannelDelegate()
{
debugLog("dealloc WebViewChannelDelegate");

View File

@ -7,6 +7,9 @@
#include "../types/channel_delegate.h"
#include "../types/base_callback_result.h"
#include "../types/navigation_action.h"
#include "../types/web_resource_request.h"
#include "../types/web_resource_error.h"
#include "../types/web_resource_response.h"
namespace flutter_inappwebview_plugin
{
@ -33,9 +36,11 @@ namespace flutter_inappwebview_plugin
const flutter::MethodCall<flutter::EncodableValue>& method_call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
void onLoadStart(const std::optional<std::string> url) const;
void onLoadStop(const std::optional<std::string> url) const;
void shouldOverrideUrlLoading(std::shared_ptr<NavigationAction> navigationAction, std::unique_ptr<ShouldOverrideUrlLoadingCallback> callback);
void onLoadStart(const std::optional<std::string>& url) const;
void onLoadStop(const std::optional<std::string>& url) const;
void shouldOverrideUrlLoading(std::shared_ptr<NavigationAction> navigationAction, std::unique_ptr<ShouldOverrideUrlLoadingCallback> callback) const;
void WebViewChannelDelegate::onReceivedError(std::shared_ptr<WebResourceRequest> request, std::shared_ptr<WebResourceError> error) const;
void WebViewChannelDelegate::onReceivedHttpError(std::shared_ptr<WebResourceRequest> request, std::shared_ptr<WebResourceResponse> error) const;
};
}

View File

@ -3,6 +3,8 @@
#include "channel_delegate.h"
#include "../utils/util.h"
namespace flutter_inappwebview_plugin
{
ChannelDelegate::ChannelDelegate(flutter::BinaryMessenger* messenger, const std::string& name) : messenger(messenger)

View File

@ -3,11 +3,6 @@
#include <flutter/method_channel.h>
#include <memory>
#include <set>
#include "../flutter_inappwebview_windows_base_plugin.h"
namespace flutter_inappwebview_plugin
{
class ChannelDelegate

View File

@ -4,7 +4,7 @@
namespace flutter_inappwebview_plugin
{
NavigationAction::NavigationAction(std::shared_ptr<URLRequest> request, bool isForMainFrame)
NavigationAction::NavigationAction(std::shared_ptr<URLRequest> request, const bool& isForMainFrame)
: request(std::move(request)), isForMainFrame(isForMainFrame)
{

View File

@ -13,7 +13,7 @@ namespace flutter_inappwebview_plugin
const std::shared_ptr<URLRequest> request;
const bool isForMainFrame;
NavigationAction(std::shared_ptr<URLRequest> request, bool isForMainFrame);
NavigationAction(std::shared_ptr<URLRequest> request, const bool& isForMainFrame);
~NavigationAction() = default;
flutter::EncodableMap toEncodableMap();
};

View File

@ -1,19 +1,20 @@
#include "url_request.h"
#include "../utils/util.h"
#include "../utils/flutter.h"
namespace flutter_inappwebview_plugin
{
URLRequest::URLRequest(std::optional<std::string> url, std::optional<std::string> method, std::optional<std::map<std::string, std::string>> headers, std::optional<std::vector<uint8_t>> body)
URLRequest::URLRequest(const std::optional<std::string>& url, const std::optional<std::string>& method,
const std::optional<std::map<std::string, std::string>>& headers, const std::optional<std::vector<uint8_t>>& body)
: url(url), method(method), headers(headers), body(body)
{
}
URLRequest::URLRequest(const flutter::EncodableMap map)
URLRequest::URLRequest(const flutter::EncodableMap& map)
: url(get_optional_fl_map_value<std::string>(map, "url")),
method(get_optional_fl_map_value<std::string>(map, "method")),
headers(get_optional_fl_map_value(map, "headers")),
headers(get_optional_fl_map_value<std::string, std::string>(map, "headers")),
body(get_optional_fl_map_value<std::vector<uint8_t>>(map, "body"))
{
@ -22,10 +23,10 @@ namespace flutter_inappwebview_plugin
flutter::EncodableMap URLRequest::toEncodableMap()
{
return flutter::EncodableMap{
{flutter::EncodableValue("url"), optional_to_fl_value(url)},
{flutter::EncodableValue("method"), optional_to_fl_value(method)},
{flutter::EncodableValue("headers"), optional_to_fl_value(headers)},
{flutter::EncodableValue("body"), optional_to_fl_value(body)}
{make_fl_value("url"), make_fl_value(url)},
{make_fl_value("method"), make_fl_value(method)},
{make_fl_value("headers"), make_fl_value(headers)},
{make_fl_value("body"), make_fl_value(body)}
};
}
}

View File

@ -15,8 +15,9 @@ namespace flutter_inappwebview_plugin
const std::optional<std::map<std::string, std::string>> headers;
const std::optional<std::vector<uint8_t>> body;
URLRequest(std::optional<std::string> url, std::optional<std::string> method, std::optional<std::map<std::string, std::string>> headers, std::optional<std::vector<uint8_t>> body);
URLRequest(const flutter::EncodableMap map);
URLRequest(const std::optional<std::string>& url, const std::optional<std::string>& method,
const std::optional<std::map<std::string, std::string>>& headers, const std::optional<std::vector<uint8_t>>& body);
URLRequest(const flutter::EncodableMap& map);
~URLRequest() = default;
flutter::EncodableMap toEncodableMap();
};

View File

@ -0,0 +1,27 @@
#include "web_resource_error.h"
#include "../utils/flutter.h"
namespace flutter_inappwebview_plugin
{
WebResourceError::WebResourceError(const std::string& description, const int type)
: description(description), type(type)
{
}
WebResourceError::WebResourceError(const flutter::EncodableMap& map)
: description(get_fl_map_value<std::string>(map, "description")),
type(get_fl_map_value<int>(map, "type"))
{
}
flutter::EncodableMap WebResourceError::toEncodableMap()
{
return flutter::EncodableMap{
{make_fl_value("description"), make_fl_value(description)},
{make_fl_value("type"), make_fl_value(type)}
};
}
}

View File

@ -0,0 +1,46 @@
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_WEB_RESOURCE_ERROR_H_
#define FLUTTER_INAPPWEBVIEW_PLUGIN_WEB_RESOURCE_ERROR_H_
#include <flutter/standard_method_codec.h>
#include <optional>
namespace flutter_inappwebview_plugin
{
static const std::string WebErrorStatusDescription[] =
{
"Indicates that an unknown error occurred.",
"Indicates that the SSL certificate common name does not match the web address.",
"Indicates that the SSL certificate has expired.",
"Indicates that the SSL client certificate contains errors.",
"Indicates that the SSL certificate has been revoked.",
"Indicates that the SSL certificate is not valid.",
"Indicates that the host is unreachable.",
"Indicates that the connection has timed out.",
"Indicates that the server returned an invalid or unrecognized response.",
"Indicates that the connection was stopped.",
"Indicates that the connection was reset.",
"Indicates that the Internet connection has been lost.",
"Indicates that a connection to the destination was not established.",
"Indicates that the provided host name was not able to be resolved.",
"Indicates that the operation was canceled.",
"Indicates that the request redirect failed.",
"Indicates that an unexpected error occurred.",
"Indicates that user is prompted with a login, waiting on user action.",
"Indicates that user lacks proper authentication credentials for a proxy server.",
};
class WebResourceError
{
public:
const std::string description;
const int type;
WebResourceError(const std::string& description, const int type);
WebResourceError(const flutter::EncodableMap& map);
~WebResourceError() = default;
flutter::EncodableMap toEncodableMap();
};
}
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_WEB_RESOURCE_ERROR_H_

View File

@ -0,0 +1,32 @@
#include "web_resource_request.h"
#include "../utils/flutter.h"
namespace flutter_inappwebview_plugin
{
WebResourceRequest::WebResourceRequest(const std::optional<std::string>& url, const std::optional<std::string>& method,
const std::optional<std::map<std::string, std::string>>& headers, const std::optional<bool>& isForMainFrame)
: url(url), method(method), headers(headers), isForMainFrame(isForMainFrame)
{
}
WebResourceRequest::WebResourceRequest(const flutter::EncodableMap& map)
: url(get_optional_fl_map_value<std::string>(map, "url")),
method(get_optional_fl_map_value<std::string>(map, "method")),
headers(get_optional_fl_map_value<std::string, std::string>(map, "headers")),
isForMainFrame(get_optional_fl_map_value<bool>(map, "isForMainFrame"))
{
}
flutter::EncodableMap WebResourceRequest::toEncodableMap()
{
return flutter::EncodableMap{
{make_fl_value("url"), make_fl_value(url)},
{make_fl_value("method"), make_fl_value(method)},
{make_fl_value("headers"), make_fl_value(headers)},
{make_fl_value("isForMainFrame"), make_fl_value(isForMainFrame)}
};
}
}

View File

@ -0,0 +1,26 @@
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_WEB_RESOURCE_REQUEST_H_
#define FLUTTER_INAPPWEBVIEW_PLUGIN_WEB_RESOURCE_REQUEST_H_
#include <flutter/standard_method_codec.h>
#include <optional>
namespace flutter_inappwebview_plugin
{
class WebResourceRequest
{
public:
const std::optional<std::string> url;
const std::optional<std::string> method;
const std::optional<std::map<std::string, std::string>> headers;
const std::optional<bool> isForMainFrame;
WebResourceRequest(const std::optional<std::string>& url, const std::optional<std::string>& method,
const std::optional<std::map<std::string, std::string>>& headers, const std::optional<bool>& isForMainFrame);
WebResourceRequest(const flutter::EncodableMap& map);
~WebResourceRequest() = default;
flutter::EncodableMap toEncodableMap();
};
}
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_WEB_RESOURCE_REQUEST_H_

View File

@ -0,0 +1,25 @@
#include "web_resource_response.h"
#include "../utils/flutter.h"
namespace flutter_inappwebview_plugin
{
WebResourceResponse::WebResourceResponse(const std::optional<int>& statusCode)
: statusCode(statusCode)
{
}
WebResourceResponse::WebResourceResponse(const flutter::EncodableMap& map)
: statusCode(get_optional_fl_map_value<int>(map, "statusCode"))
{
}
flutter::EncodableMap WebResourceResponse::toEncodableMap()
{
return flutter::EncodableMap{
{make_fl_value("statusCode"), make_fl_value(statusCode)}
};
}
}

View File

@ -0,0 +1,22 @@
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_WEB_RESOURCE_RESPONSE_H_
#define FLUTTER_INAPPWEBVIEW_PLUGIN_WEB_RESOURCE_RESPONSE_H_
#include <flutter/standard_method_codec.h>
#include <optional>
namespace flutter_inappwebview_plugin
{
class WebResourceResponse
{
public:
const std::optional<int> statusCode;
WebResourceResponse(const std::optional<int>& statusCode);
WebResourceResponse(const flutter::EncodableMap& map);
~WebResourceResponse() = default;
flutter::EncodableMap toEncodableMap();
};
}
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_WEB_RESOURCE_RESPONSE_H_

View File

@ -0,0 +1,77 @@
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_FLUTTER_UTIL_H_
#define FLUTTER_INAPPWEBVIEW_PLUGIN_FLUTTER_UTIL_H_
#include <string>
#include <optional>
#include <flutter/encodable_value.h>
#include "util.h"
namespace flutter_inappwebview_plugin
{
static inline flutter::EncodableValue make_fl_value()
{
return flutter::EncodableValue();
}
template<typename T>
static inline flutter::EncodableValue make_fl_value(const T& val)
{
return flutter::EncodableValue(val);
}
template<typename T>
static inline flutter::EncodableValue make_fl_value(const T* val)
{
return val == nullptr ? make_fl_value() : flutter::EncodableValue(val);
}
template<typename T>
static inline flutter::EncodableValue make_fl_value(const std::optional<T>& optional)
{
return optional.has_value() ? make_fl_value(optional.value()) : make_fl_value();
}
static inline flutter::EncodableValue make_fl_value(const std::optional<std::map<std::string, std::string>>& optional)
{
if (!optional.has_value()) {
return make_fl_value();
}
auto& mapValue = optional.value();
auto encodableMap = flutter::EncodableMap{};
for (auto const& [key, val] : mapValue)
{
encodableMap.insert({ make_fl_value(key), make_fl_value(val) });
}
return encodableMap;
}
template<typename T>
static inline T get_fl_map_value(const flutter::EncodableMap& map, const char* string)
{
return std::get<T>(map.at(make_fl_value(string)));
}
template<typename T>
static inline std::optional<T> get_optional_fl_map_value(const flutter::EncodableMap& map, const char* string)
{
return make_pointer_optional<T>(std::get_if<T>(&map.at(make_fl_value(string))));
}
template<typename K, typename T>
static inline std::optional<std::map<K, T>> get_optional_fl_map_value(const flutter::EncodableMap& map, const char* string)
{
auto flMap = std::get_if<flutter::EncodableMap>(&map.at(make_fl_value(string)));
if (flMap) {
auto mapValue = std::map<K, T>{};
for (auto itr = flMap->begin(); itr != flMap->end(); itr++)
{
mapValue.insert({ std::get<K>(itr->first), std::get<T>(itr->second) });
}
return make_pointer_optional<std::map<K, T>>(&mapValue);
}
return std::nullopt;
}
}
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_FLUTTER_UTIL_H_

View File

@ -22,52 +22,7 @@ namespace flutter_inappwebview_plugin
return value == nullptr ? std::nullopt : std::make_optional<T>(*value);
}
template<typename T>
static inline T get_fl_map_value(const flutter::EncodableMap map, const char* string)
{
return std::get<T>(map.at(flutter::EncodableValue(string)));
}
template<typename T>
static inline std::optional<T> get_optional_fl_map_value(const flutter::EncodableMap map, const char* string)
{
return make_pointer_optional<T>(std::get_if<T>(&map.at(flutter::EncodableValue(string))));
}
static inline std::optional<std::map<std::string, std::string>> get_optional_fl_map_value(const flutter::EncodableMap map, const char* string)
{
auto mapValue = std::map<std::string, std::string>{};
auto flMap = std::get_if<flutter::EncodableMap>(&map.at(flutter::EncodableValue(string)));
if (flMap) {
for (auto itr = flMap->begin(); itr != flMap->end(); itr++)
{
mapValue.insert({ std::get<std::string>(itr->first), std::get<std::string>(itr->second) });
}
}
return make_pointer_optional<std::map<std::string, std::string>>(&mapValue);
}
template<typename T>
static inline flutter::EncodableValue optional_to_fl_value(const std::optional<T> optional)
{
return optional.has_value() ? flutter::EncodableValue(optional.value()) : flutter::EncodableValue();
}
static inline flutter::EncodableValue optional_to_fl_value(const std::optional<std::map<std::string, std::string>> optional)
{
if (!optional.has_value()) {
return flutter::EncodableValue();
}
auto& mapValue = optional.value();
auto encodableMap = flutter::EncodableMap{};
for (auto const& [key, val] : mapValue)
{
encodableMap.insert({ flutter::EncodableValue(key), flutter::EncodableValue(val) });
}
return encodableMap;
}
static inline std::string variant_to_string(std::variant<std::string, int> var)
static inline std::string variant_to_string(const std::variant<std::string, int>& var)
{
return std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
@ -79,6 +34,19 @@ namespace flutter_inappwebview_plugin
static_assert(always_false_v<T>, "non-exhaustive visitor!");
}, var);
}
template<typename K, typename T>
static inline bool map_contains(const std::map<K, T>& map, const K& key)
{
return map.find(key) != map.end();
}
template<typename K, typename T>
static inline T map_at_or_null(const std::map<K, T>& map, const K& key)
{
auto itr = map.find(key);
return itr != map.end() ? itr->second : nullptr;
}
}
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_H_