windows: added openDevTools, callDevToolsProtocolMethod, addDevToolsProtocolEventListener and removeDevToolsProtocolEventListener methods, added some more inappwebview and inappbrowser basic settings

This commit is contained in:
unknown 2024-01-31 04:04:26 +01:00
parent ade2edfb7d
commit 599e2fd94f
23 changed files with 710 additions and 136 deletions

View File

@ -484,6 +484,21 @@ class InAppWebViewController {
URLResponse? urlResponse}) => URLResponse? urlResponse}) =>
platform.loadSimulatedRequest(urlRequest: urlRequest, data: data); platform.loadSimulatedRequest(urlRequest: urlRequest, data: data);
///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.openDevTools}
Future<void> openDevTools() => platform.openDevTools();
///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.callDevToolsProtocolMethod}
Future<dynamic> callDevToolsProtocolMethod({required String methodName, Map<String, dynamic>? parameters}) =>
platform.callDevToolsProtocolMethod(methodName: methodName, parameters: parameters);
///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.addDevToolsProtocolEventListener}
Future<void> addDevToolsProtocolEventListener({required String eventName, required Function(dynamic data) callback}) =>
platform.addDevToolsProtocolEventListener(eventName: eventName, callback: callback);
///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.removeDevToolsProtocolEventListener}
Future<void> removeDevToolsProtocolEventListener({required String eventName}) =>
platform.removeDevToolsProtocolEventListener(eventName: eventName);
///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.getIFrameId} ///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.getIFrameId}
Future<String?> getIFrameId() => platform.getIFrameId(); Future<String?> getIFrameId() => platform.getIFrameId();

View File

@ -1,3 +1,7 @@
## 1.0.11
- Added `PlatformWebViewEnvironment` class
## 1.0.10 ## 1.0.10
- Merged "Added == operator and hashCode to WebUri" [#1941](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1941) (thanks to [daisukeueta](https://github.com/daisukeueta)) - Merged "Added == operator and hashCode to WebUri" [#1941](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1941) (thanks to [daisukeueta](https://github.com/daisukeueta))

View File

@ -98,194 +98,198 @@ class InAppBrowserSettings_
implements BrowserOptions, AndroidOptions, IosOptions { implements BrowserOptions, AndroidOptions, IosOptions {
///Set to `true` to create the browser and load the page, but not show it. Omit or set to `false` to have the browser open and load normally. ///Set to `true` to create the browser and load the page, but not show it. Omit or set to `false` to have the browser open and load normally.
///The default value is `false`. ///The default value is `false`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform(),
///- Android native WebView IOSPlatform(),
///- iOS MacOSPlatform(),
///- MacOS WindowsPlatform()
])
bool? hidden; bool? hidden;
///Set to `true` to hide the toolbar at the top of the WebView. The default value is `false`. ///Set to `true` to hide the toolbar at the top of the WebView. The default value is `false`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform(),
///- Android native WebView IOSPlatform(),
///- iOS MacOSPlatform()
///- MacOS ])
bool? hideToolbarTop; bool? hideToolbarTop;
///Set the custom background color of the toolbar at the top. ///Set the custom background color of the toolbar at the top.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform(),
///- Android native WebView IOSPlatform(),
///- iOS MacOSPlatform()
///- MacOS ])
Color_? toolbarTopBackgroundColor; Color_? toolbarTopBackgroundColor;
///Set to `true` to hide the url bar on the toolbar at the top. The default value is `false`. ///Set to `true` to hide the url bar on the toolbar at the top. The default value is `false`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform(),
///- Android native WebView IOSPlatform(),
///- iOS MacOSPlatform()
///- MacOS ])
bool? hideUrlBar; bool? hideUrlBar;
///Set to `true` to hide the progress bar when the WebView is loading a page. The default value is `false`. ///Set to `true` to hide the progress bar when the WebView is loading a page. The default value is `false`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform(),
///- Android native WebView IOSPlatform(),
///- iOS MacOSPlatform()
///- MacOS ])
bool? hideProgressBar; bool? hideProgressBar;
///Set to `true` to hide the default menu items. The default value is `false`. ///Set to `true` to hide the default menu items. The default value is `false`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform(),
///- Android native WebView IOSPlatform(),
///- iOS MacOSPlatform()
])
bool? hideDefaultMenuItems; bool? hideDefaultMenuItems;
///Set to `true` if you want the title should be displayed. The default value is `false`. ///Set to `true` if you want the title should be displayed. The default value is `false`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform()
///- Android native WebView ])
bool? hideTitleBar; bool? hideTitleBar;
///Set the action bar's title. ///Set the action bar's title.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform(),
///- Android native WebView MacOSPlatform(),
///- MacOS WindowsPlatform()
])
String? toolbarTopFixedTitle; String? toolbarTopFixedTitle;
///Set to `false` to not close the InAppBrowser when the user click on the Android back button and the WebView cannot go back to the history. The default value is `true`. ///Set to `false` to not close the InAppBrowser when the user click on the Android back button and the WebView cannot go back to the history. The default value is `true`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform()
///- Android native WebView ])
bool? closeOnCannotGoBack; bool? closeOnCannotGoBack;
///Set to `false` to block the InAppBrowser WebView going back when the user click on the Android back button. The default value is `true`. ///Set to `false` to block the InAppBrowser WebView going back when the user click on the Android back button. The default value is `true`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform()
///- Android native WebView ])
bool? allowGoBackWithBackButton; bool? allowGoBackWithBackButton;
///Set to `true` to close the InAppBrowser when the user click on the Android back button. The default value is `false`. ///Set to `true` to close the InAppBrowser when the user click on the Android back button. The default value is `false`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: AndroidPlatform()
///- Android native WebView ])
bool? shouldCloseOnBackButtonPressed; bool? shouldCloseOnBackButtonPressed;
///Set to `true` to set the toolbar at the top translucent. The default value is `true`. ///Set to `true` to set the toolbar at the top translucent. The default value is `true`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
bool? toolbarTopTranslucent; bool? toolbarTopTranslucent;
///Set the tint color to apply to the navigation bar background. ///Set the tint color to apply to the navigation bar background.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
Color_? toolbarTopBarTintColor; Color_? toolbarTopBarTintColor;
///Set the tint color to apply to the navigation items and bar button items. ///Set the tint color to apply to the navigation items and bar button items.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
Color_? toolbarTopTintColor; Color_? toolbarTopTintColor;
///Set to `true` to hide the toolbar at the bottom of the WebView. The default value is `false`. ///Set to `true` to hide the toolbar at the bottom of the WebView. The default value is `false`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
bool? hideToolbarBottom; bool? hideToolbarBottom;
///Set the custom background color of the toolbar at the bottom. ///Set the custom background color of the toolbar at the bottom.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
Color_? toolbarBottomBackgroundColor; Color_? toolbarBottomBackgroundColor;
///Set the tint color to apply to the bar button items. ///Set the tint color to apply to the bar button items.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
Color_? toolbarBottomTintColor; Color_? toolbarBottomTintColor;
///Set to `true` to set the toolbar at the bottom translucent. The default value is `true`. ///Set to `true` to set the toolbar at the bottom translucent. The default value is `true`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
bool? toolbarBottomTranslucent; bool? toolbarBottomTranslucent;
///Set the custom text for the close button. ///Set the custom text for the close button.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
String? closeButtonCaption; String? closeButtonCaption;
///Set the custom color for the close button. ///Set the custom color for the close button.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
Color_? closeButtonColor; Color_? closeButtonColor;
///Set to `true` to hide the close button. The default value is `false`. ///Set to `true` to hide the close button. The default value is `false`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
bool? hideCloseButton; bool? hideCloseButton;
///Set the custom color for the menu button. ///Set the custom color for the menu button.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
Color_? menuButtonColor; Color_? menuButtonColor;
///Set the custom modal presentation style when presenting the WebView. The default value is [ModalPresentationStyle.FULL_SCREEN]. ///Set the custom modal presentation style when presenting the WebView. The default value is [ModalPresentationStyle.FULL_SCREEN].
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
ModalPresentationStyle_? presentationStyle; ModalPresentationStyle_? presentationStyle;
///Set to the custom transition style when presenting the WebView. The default value is [ModalTransitionStyle.COVER_VERTICAL]. ///Set to the custom transition style when presenting the WebView. The default value is [ModalTransitionStyle.COVER_VERTICAL].
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: IOSPlatform()
///- iOS ])
ModalTransitionStyle_? transitionStyle; ModalTransitionStyle_? transitionStyle;
///How the browser window should be added to the main window. ///How the browser window should be added to the main window.
///The default value is [WindowType.WINDOW]. ///The default value is [WindowType.WINDOW].
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: MacOSPlatform(),
///- MacOS WindowsPlatform()
])
WindowType_? windowType; WindowType_? windowType;
///The windows alpha value. ///The windows alpha value.
///The default value is `1.0`. ///The default value is `1.0`.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: MacOSPlatform(),
///- MacOS WindowsPlatform()
])
double? windowAlphaValue; double? windowAlphaValue;
///Flags that describe the windows current style, such as if its resizable or in full-screen mode. ///Flags that describe the windows current style, such as if its resizable or in full-screen mode.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: MacOSPlatform()
///- MacOS ])
WindowStyleMask_? windowStyleMask; WindowStyleMask_? windowStyleMask;
///The type of separator that the app displays between the title bar and content of a window. ///The type of separator that the app displays between the title bar and content of a window.
/// @SupportedPlatforms(platforms: [
///**NOTE for MacOS**: available on MacOS 11.0+. MacOSPlatform(available: '11.0')
/// ])
///**Officially Supported Platforms/Implementations**:
///- MacOS
WindowTitlebarSeparatorStyle_? windowTitlebarSeparatorStyle; WindowTitlebarSeparatorStyle_? windowTitlebarSeparatorStyle;
///Sets the origin and size of the windows frame rectangle according to a given frame rectangle, ///Sets the origin and size of the windows frame rectangle according to a given frame rectangle,
///thereby setting its position and size onscreen. ///thereby setting its position and size onscreen.
/// @SupportedPlatforms(platforms: [
///**Officially Supported Platforms/Implementations**: MacOSPlatform(),
///- MacOS WindowsPlatform()
])
InAppWebViewRect_? windowFrame; InAppWebViewRect_? windowFrame;
InAppBrowserSettings_( InAppBrowserSettings_(

View File

@ -28,6 +28,7 @@ class InAppWebViewControllerKeepAliveProps {
Map<String, ScriptHtmlTagAttributes> injectedScriptsFromURL; Map<String, ScriptHtmlTagAttributes> injectedScriptsFromURL;
Set<PlatformWebMessageChannel> webMessageChannels = Set(); Set<PlatformWebMessageChannel> webMessageChannels = Set();
Set<PlatformWebMessageListener> webMessageListeners = Set(); Set<PlatformWebMessageListener> webMessageListeners = Set();
Map<String, Function(dynamic data)> devToolsProtocolEventListenerMap;
InAppWebViewControllerKeepAliveProps( InAppWebViewControllerKeepAliveProps(
{required this.javaScriptHandlersMap, {required this.javaScriptHandlersMap,
@ -35,5 +36,7 @@ class InAppWebViewControllerKeepAliveProps {
required this.webMessageListenerObjNames, required this.webMessageListenerObjNames,
required this.injectedScriptsFromURL, required this.injectedScriptsFromURL,
required this.webMessageChannels, required this.webMessageChannels,
required this.webMessageListeners}); required this.webMessageListeners,
required this.devToolsProtocolEventListenerMap
});
} }

View File

@ -58,7 +58,7 @@ class InAppWebViewSettings_ {
///it will be automatically inferred as `true`, otherwise, the default value is `false`. ///it will be automatically inferred as `true`, otherwise, the default value is `false`.
///This logic will not be applied for [PlatformInAppBrowser], where you must set the value manually. ///This logic will not be applied for [PlatformInAppBrowser], where you must set the value manually.
@SupportedPlatforms( @SupportedPlatforms(
platforms: [AndroidPlatform(), IOSPlatform(), MacOSPlatform()]) platforms: [AndroidPlatform(), IOSPlatform(), MacOSPlatform(), WindowsPlatform()])
bool? useShouldOverrideUrlLoading; bool? useShouldOverrideUrlLoading;
///Set to `true` to be able to listen at the [PlatformWebViewCreationParams.onLoadResource] event. ///Set to `true` to be able to listen at the [PlatformWebViewCreationParams.onLoadResource] event.
@ -98,7 +98,11 @@ class InAppWebViewSettings_ {
MacOSPlatform( MacOSPlatform(
apiName: "WKWebView.customUserAgent", apiName: "WKWebView.customUserAgent",
apiUrl: apiUrl:
"https://developer.apple.com/documentation/webkit/wkwebview/1414950-customuseragent") "https://developer.apple.com/documentation/webkit/wkwebview/1414950-customuseragent"),
WindowsPlatform(
apiName: 'ICoreWebView2Settings2.put_UserAgent',
apiUrl: 'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2settings2?view=webview2-1.0.2210.55#put_useragent'
)
]) ])
String? userAgent; String? userAgent;
@ -130,7 +134,12 @@ class InAppWebViewSettings_ {
apiName: "WKWebpagePreferences.allowsContentJavaScript", apiName: "WKWebpagePreferences.allowsContentJavaScript",
apiUrl: apiUrl:
"https://developer.apple.com/documentation/webkit/wkwebpagepreferences/3552422-allowscontentjavascript/"), "https://developer.apple.com/documentation/webkit/wkwebpagepreferences/3552422-allowscontentjavascript/"),
WebPlatform(requiresSameOrigin: false) WebPlatform(requiresSameOrigin: false),
WindowsPlatform(
apiName: "ICoreWebView2Settings.put_IsScriptEnabled",
apiUrl:
"https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2settings?view=webview2-1.0.2210.55#put_isscriptenabled"
)
]) ])
bool? javaScriptEnabled; bool? javaScriptEnabled;
@ -307,7 +316,12 @@ because there isn't any way to make the website data store non-persistent for th
@SupportedPlatforms(platforms: [ @SupportedPlatforms(platforms: [
AndroidPlatform(), AndroidPlatform(),
IOSPlatform(), IOSPlatform(),
MacOSPlatform(available: "12.0") MacOSPlatform(available: "12.0"),
WindowsPlatform(
available: '1.0.774.44',
apiName: 'ICoreWebView2Controller2.put_DefaultBackgroundColor',
apiUrl: 'https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2controller2?view=webview2-1.0.2210.55#put_defaultbackgroundcolor'
)
]) ])
bool? transparentBackground; bool? transparentBackground;
@ -323,7 +337,13 @@ because there isn't any way to make the website data store non-persistent for th
///Set to `true` to disable context menu. The default value is `false`. ///Set to `true` to disable context menu. The default value is `false`.
@SupportedPlatforms( @SupportedPlatforms(
platforms: [AndroidPlatform(), IOSPlatform(), WebPlatform()]) platforms: [AndroidPlatform(), IOSPlatform(), WebPlatform(),
WindowsPlatform(
apiName: "ICoreWebView2Settings.put_AreDefaultContextMenusEnabled",
apiUrl:
"https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2settings?view=webview2-1.0.2210.55#put_aredefaultcontextmenusenabled"
)
])
bool? disableContextMenu; bool? disableContextMenu;
///Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`. ///Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`.
@ -333,7 +353,12 @@ because there isn't any way to make the website data store non-persistent for th
apiUrl: apiUrl:
"https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setSupportZoom(boolean)"), "https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setSupportZoom(boolean)"),
IOSPlatform(), IOSPlatform(),
MacOSPlatform() MacOSPlatform(),
WindowsPlatform(
apiName: "ICoreWebView2Settings.put_IsZoomControlEnabled",
apiUrl:
"https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2settings?view=webview2-1.0.2210.55#put_iszoomcontrolenabled"
)
]) ])
bool? supportZoom; bool? supportZoom;
@ -1537,7 +1562,12 @@ as it can cause framerate drops on animations in Android 9 and lower (see [Hybri
available: "13.3", available: "13.3",
apiName: "WKWebView.isInspectable", apiName: "WKWebView.isInspectable",
apiUrl: apiUrl:
"https://developer.apple.com/documentation/webkit/wkwebview/4111163-isinspectable") "https://developer.apple.com/documentation/webkit/wkwebview/4111163-isinspectable"),
WindowsPlatform(
apiName: "ICoreWebView2Settings.put_AreDevToolsEnabled",
apiUrl:
"https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2settings?view=webview2-1.0.2210.55#put_aredevtoolsenabled"
)
]) ])
bool? isInspectable; bool? isInspectable;

View File

@ -371,6 +371,7 @@ class InAppWebViewSettings {
///- Android native WebView ///- Android native WebView
///- iOS ///- iOS
///- Web but iframe requires same origin ///- Web but iframe requires same origin
///- Windows ([Official API - ICoreWebView2Settings.put_AreDefaultContextMenusEnabled](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2settings?view=webview2-1.0.2210.55#put_aredefaultcontextmenusenabled))
bool? disableContextMenu; bool? disableContextMenu;
///Sets whether the default Android WebViews internal error page should be suppressed or displayed for bad navigations. ///Sets whether the default Android WebViews internal error page should be suppressed or displayed for bad navigations.
@ -648,6 +649,7 @@ class InAppWebViewSettings {
///**Officially Supported Platforms/Implementations**: ///**Officially Supported Platforms/Implementations**:
///- iOS 16.4+ ([Official API - WKWebView.isInspectable](https://developer.apple.com/documentation/webkit/wkwebview/4111163-isinspectable)) ///- iOS 16.4+ ([Official API - WKWebView.isInspectable](https://developer.apple.com/documentation/webkit/wkwebview/4111163-isinspectable))
///- MacOS 13.3+ ([Official API - WKWebView.isInspectable](https://developer.apple.com/documentation/webkit/wkwebview/4111163-isinspectable)) ///- MacOS 13.3+ ([Official API - WKWebView.isInspectable](https://developer.apple.com/documentation/webkit/wkwebview/4111163-isinspectable))
///- Windows ([Official API - ICoreWebView2Settings.put_AreDevToolsEnabled](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2settings?view=webview2-1.0.2210.55#put_aredevtoolsenabled))
bool? isInspectable; bool? isInspectable;
///A Boolean value that determines whether paging is enabled for the scroll view. ///A Boolean value that determines whether paging is enabled for the scroll view.
@ -691,6 +693,7 @@ class InAppWebViewSettings {
///- iOS ([Official API - WKWebpagePreferences.allowsContentJavaScript](https://developer.apple.com/documentation/webkit/wkwebpagepreferences/3552422-allowscontentjavascript/)) ///- iOS ([Official API - WKWebpagePreferences.allowsContentJavaScript](https://developer.apple.com/documentation/webkit/wkwebpagepreferences/3552422-allowscontentjavascript/))
///- MacOS ([Official API - WKWebpagePreferences.allowsContentJavaScript](https://developer.apple.com/documentation/webkit/wkwebpagepreferences/3552422-allowscontentjavascript/)) ///- MacOS ([Official API - WKWebpagePreferences.allowsContentJavaScript](https://developer.apple.com/documentation/webkit/wkwebpagepreferences/3552422-allowscontentjavascript/))
///- Web ///- Web
///- Windows ([Official API - ICoreWebView2Settings.put_IsScriptEnabled](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2settings?view=webview2-1.0.2210.55#put_isscriptenabled))
bool? javaScriptEnabled; bool? javaScriptEnabled;
///Sets the underlying layout algorithm. This will cause a re-layout of the WebView. ///Sets the underlying layout algorithm. This will cause a re-layout of the WebView.
@ -983,6 +986,7 @@ class InAppWebViewSettings {
///- Android native WebView ([Official API - WebSettings.setSupportZoom](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setSupportZoom(boolean))) ///- Android native WebView ([Official API - WebSettings.setSupportZoom](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setSupportZoom(boolean)))
///- iOS ///- iOS
///- MacOS ///- MacOS
///- Windows ([Official API - ICoreWebView2Settings.put_IsZoomControlEnabled](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2settings?view=webview2-1.0.2210.55#put_iszoomcontrolenabled))
bool? supportZoom; bool? supportZoom;
///Set to `true` if you want the WebView suppresses content rendering until it is fully loaded into memory. The default value is `false`. ///Set to `true` if you want the WebView suppresses content rendering until it is fully loaded into memory. The default value is `false`.
@ -1012,6 +1016,7 @@ class InAppWebViewSettings {
///- Android native WebView ///- Android native WebView
///- iOS ///- iOS
///- MacOS 12.0+ ///- MacOS 12.0+
///- Windows 1.0.774.44+ ([Official API - ICoreWebView2Controller2.put_DefaultBackgroundColor](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2controller2?view=webview2-1.0.2210.55#put_defaultbackgroundcolor))
bool? transparentBackground; bool? transparentBackground;
///The color the web view displays behind the active page, visible when the user scrolls beyond the bounds of the page. ///The color the web view displays behind the active page, visible when the user scrolls beyond the bounds of the page.
@ -1137,6 +1142,7 @@ class InAppWebViewSettings {
///- Android native WebView ///- Android native WebView
///- iOS ///- iOS
///- MacOS ///- MacOS
///- Windows
bool? useShouldOverrideUrlLoading; bool? useShouldOverrideUrlLoading;
///Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. ///Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport.
@ -1154,6 +1160,7 @@ class InAppWebViewSettings {
///- Android native WebView ([Official API - WebSettings.setUserAgentString](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setUserAgentString(java.lang.String))) ///- Android native WebView ([Official API - WebSettings.setUserAgentString](https://developer.android.com/reference/android/webkit/WebSettings?hl=en#setUserAgentString(java.lang.String)))
///- iOS ([Official API - WKWebView.customUserAgent](https://developer.apple.com/documentation/webkit/wkwebview/1414950-customuseragent)) ///- iOS ([Official API - WKWebView.customUserAgent](https://developer.apple.com/documentation/webkit/wkwebview/1414950-customuseragent))
///- MacOS ([Official API - WKWebView.customUserAgent](https://developer.apple.com/documentation/webkit/wkwebview/1414950-customuseragent)) ///- MacOS ([Official API - WKWebView.customUserAgent](https://developer.apple.com/documentation/webkit/wkwebview/1414950-customuseragent))
///- Windows ([Official API - ICoreWebView2Settings2.put_UserAgent](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2settings2?view=webview2-1.0.2210.55#put_useragent))
String? userAgent; String? userAgent;
///Define whether the vertical scrollbar should be drawn or not. The default value is `true`. ///Define whether the vertical scrollbar should be drawn or not. The default value is `true`.

View File

@ -2040,6 +2040,62 @@ abstract class PlatformInAppWebViewController extends PlatformInterface
'loadSimulatedRequest is not implemented on the current platform'); 'loadSimulatedRequest is not implemented on the current platform');
} }
///{@template flutter_inappwebview_platform_interface.PlatformInAppWebViewController.openDevTools}
///Opens the DevTools window for the current document in the WebView.
///Does nothing if run when the DevTools window is already open.
///
///**Officially Supported Platforms/Implementations**:
///- Windows ([Official API - ICoreWebView2.OpenDevToolsWindow](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#opendevtoolswindow))
///{@endtemplate}
Future<void> openDevTools() {
throw UnimplementedError(
'openDevTools is not implemented on the current platform');
}
///{@template flutter_inappwebview_platform_interface.PlatformInAppWebViewController.callDevToolsProtocolMethod}
///Runs an asynchronous `DevToolsProtocol` method.
///
///For more information about available methods, navigate to [DevTools Protocol Viewer](https://chromedevtools.github.io/devtools-protocol/tot).
///The [methodName] parameter is the full name of the method in the `{domain}.{method}` format.
///The [parameters] will be a JSON formatted string containing the parameters for the corresponding method.
///This function throws an error if the [methodName] is unknown or the [parameters] has an error.
///In the case of such an error, the [parameters] parameter of the
///handler will include information about the error.
///Note even though WebView dispatches the CDP messages in the order called,
///CDP method calls may be processed out of order.
///If you require CDP methods to run in a particular order, you should wait for
///the previous method's completed handler to run before calling the next method.
///
///**Officially Supported Platforms/Implementations**:
///- Windows ([Official API - ICoreWebView2.CallDevToolsProtocolMethod](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.2210.55#calldevtoolsprotocolmethod))
///{@endtemplate}
Future<dynamic> callDevToolsProtocolMethod({required String methodName, Map<String, dynamic>? parameters}) {
throw UnimplementedError(
'callDevToolsProtocolMethod is not implemented on the current platform');
}
///{@template flutter_inappwebview_platform_interface.PlatformInAppWebViewController.addDevToolsProtocolEventListener}
///Subscribe to a `DevToolsProtocol` event.
///
///**Officially Supported Platforms/Implementations**:
///- Windows ([Official API - ICoreWebView2DevToolsProtocolEventReceiver.add_DevToolsProtocolEventReceived](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2devtoolsprotocoleventreceiver?view=webview2-1.0.2210.55#add_devtoolsprotocoleventreceived))
///{@endtemplate}
Future<void> addDevToolsProtocolEventListener({required String eventName, required Function(dynamic data) callback}) {
throw UnimplementedError(
'addDevToolsProtocolEventListener is not implemented on the current platform');
}
///{@template flutter_inappwebview_platform_interface.PlatformInAppWebViewController.removeDevToolsProtocolEventListener}
///Remove an event handler previously added with [addDevToolsProtocolEventListener].
///
///**Officially Supported Platforms/Implementations**:
///- Windows ([Official API - ICoreWebView2DevToolsProtocolEventReceiver.remove_DevToolsProtocolEventReceived](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2devtoolsprotocoleventreceiver?view=webview2-1.0.2210.55#remove_devtoolsprotocoleventreceived))
///{@endtemplate}
Future<void> removeDevToolsProtocolEventListener({required String eventName}) {
throw UnimplementedError(
'removeDevToolsProtocolEventListener is not implemented on the current platform');
}
///{@template flutter_inappwebview_platform_interface.PlatformInAppWebViewController.getIFrameId} ///{@template flutter_inappwebview_platform_interface.PlatformInAppWebViewController.getIFrameId}
///Returns the iframe `id` attribute used on the Web platform. ///Returns the iframe `id` attribute used on the Web platform.
/// ///

View File

@ -12,11 +12,11 @@ class WindowType_ {
const WindowType_._internal(this._value); const WindowType_._internal(this._value);
///Adds the new browser window as a separate new window from the main window. ///Adds the new browser window as a separate new window from the main window.
@EnumSupportedPlatforms(platforms: [EnumMacOSPlatform(value: 'WINDOW')]) @EnumSupportedPlatforms(platforms: [EnumMacOSPlatform(value: 'WINDOW'), EnumWindowsPlatform(value: 'WINDOW')])
static const WINDOW = const WindowType_._internal('WINDOW'); static const WINDOW = const WindowType_._internal('WINDOW');
///Adds the new browser window as a child window of the main window. ///Adds the new browser window as a child window of the main window.
@EnumSupportedPlatforms(platforms: [EnumMacOSPlatform(value: 'CHILD')]) @EnumSupportedPlatforms(platforms: [EnumMacOSPlatform(value: 'CHILD'), EnumWindowsPlatform(value: 'CHILD')])
static const CHILD = const WindowType_._internal('CHILD'); static const CHILD = const WindowType_._internal('CHILD');
///Adds the new browser window as a new tab in a tabbed window of the main window. ///Adds the new browser window as a new tab in a tabbed window of the main window.

View File

@ -20,10 +20,13 @@ class WindowType {
/// ///
///**Officially Supported Platforms/Implementations**: ///**Officially Supported Platforms/Implementations**:
///- MacOS ///- MacOS
///- Windows
static final CHILD = WindowType._internalMultiPlatform('CHILD', () { static final CHILD = WindowType._internalMultiPlatform('CHILD', () {
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.macOS: case TargetPlatform.macOS:
return 'CHILD'; return 'CHILD';
case TargetPlatform.windows:
return 'CHILD';
default: default:
break; break;
} }
@ -48,10 +51,13 @@ class WindowType {
/// ///
///**Officially Supported Platforms/Implementations**: ///**Officially Supported Platforms/Implementations**:
///- MacOS ///- MacOS
///- Windows
static final WINDOW = WindowType._internalMultiPlatform('WINDOW', () { static final WINDOW = WindowType._internalMultiPlatform('WINDOW', () {
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.macOS: case TargetPlatform.macOS:
return 'WINDOW'; return 'WINDOW';
case TargetPlatform.windows:
return 'WINDOW';
default: default:
break; break;
} }

View File

@ -76,6 +76,7 @@ class WindowsInAppWebViewController extends PlatformInAppWebViewController
Map<String, ScriptHtmlTagAttributes> _injectedScriptsFromURL = {}; Map<String, ScriptHtmlTagAttributes> _injectedScriptsFromURL = {};
Set<WindowsWebMessageChannel> _webMessageChannels = Set(); Set<WindowsWebMessageChannel> _webMessageChannels = Set();
Set<WindowsWebMessageListener> _webMessageListeners = Set(); Set<WindowsWebMessageListener> _webMessageListeners = Set();
Map<String, Function(dynamic data)> _devToolsProtocolEventListenerMap = HashMap();
// static map that contains the properties to be saved and restored for keep alive feature // static map that contains the properties to be saved and restored for keep alive feature
static final Map<InAppWebViewKeepAlive, InAppWebViewControllerKeepAliveProps?> static final Map<InAppWebViewKeepAlive, InAppWebViewControllerKeepAliveProps?>
@ -179,7 +180,9 @@ class WindowsInAppWebViewController extends PlatformInAppWebViewController
userScripts: _userScripts, userScripts: _userScripts,
webMessageListenerObjNames: _webMessageListenerObjNames, webMessageListenerObjNames: _webMessageListenerObjNames,
webMessageChannels: _webMessageChannels, webMessageChannels: _webMessageChannels,
webMessageListeners: _webMessageListeners); webMessageListeners: _webMessageListeners,
devToolsProtocolEventListenerMap: _devToolsProtocolEventListenerMap
);
} else { } else {
// restore controller properties // restore controller properties
_injectedScriptsFromURL = props.injectedScriptsFromURL; _injectedScriptsFromURL = props.injectedScriptsFromURL;
@ -190,6 +193,7 @@ class WindowsInAppWebViewController extends PlatformInAppWebViewController
props.webMessageChannels as Set<WindowsWebMessageChannel>; props.webMessageChannels as Set<WindowsWebMessageChannel>;
_webMessageListeners = _webMessageListeners =
props.webMessageListeners as Set<WindowsWebMessageListener>; props.webMessageListeners as Set<WindowsWebMessageListener>;
_devToolsProtocolEventListenerMap = props.devToolsProtocolEventListenerMap;
} }
} }
} }
@ -1403,6 +1407,14 @@ class WindowsInAppWebViewController extends PlatformInAppWebViewController
.onContentSizeChanged(oldContentSize, newContentSize); .onContentSizeChanged(oldContentSize, newContentSize);
} }
break; break;
case "onDevToolsProtocolEventReceived":
String eventName = call.arguments["eventName"];
dynamic data = call.arguments["data"] != null ? jsonDecode(call.arguments["data"]) : null;
if (this._devToolsProtocolEventListenerMap.containsKey(eventName)) {
this._devToolsProtocolEventListenerMap[eventName]!.call(data);
}
break;
case "onCallJsHandler": case "onCallJsHandler":
String handlerName = call.arguments["handlerName"]; String handlerName = call.arguments["handlerName"];
// decode args to json // decode args to json
@ -2627,6 +2639,40 @@ class WindowsInAppWebViewController extends PlatformInAppWebViewController
await channel?.invokeMethod('loadSimulatedRequest', args); await channel?.invokeMethod('loadSimulatedRequest', args);
} }
@override
Future<void> openDevTools() async {
Map<String, dynamic> args = <String, dynamic>{};
await channel?.invokeMethod('openDevTools', args);
}
@override
Future<dynamic> callDevToolsProtocolMethod({required String methodName, Map<String, dynamic>? parameters}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('methodName', () => methodName);
args.putIfAbsent('parametersAsJson', () => parameters != null ? jsonEncode(parameters) : null);
final result = await channel?.invokeMethod<String>('callDevToolsProtocolMethod', args);
if (result != null) {
return jsonDecode(result);
}
return null;
}
@override
Future<void> addDevToolsProtocolEventListener({required String eventName, required Function(dynamic data) callback}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('eventName', () => eventName);
await channel?.invokeMethod('addDevToolsProtocolEventListener', args);
this._devToolsProtocolEventListenerMap[eventName] = callback;
}
@override
Future<void> removeDevToolsProtocolEventListener({required String eventName}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('eventName', () => eventName);
await channel?.invokeMethod('removeDevToolsProtocolEventListener', args);
this._devToolsProtocolEventListenerMap.remove(eventName);
}
@override @override
Future<String> getDefaultUserAgent() async { Future<String> getDefaultUserAgent() async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
@ -2689,6 +2735,7 @@ class WindowsInAppWebViewController extends PlatformInAppWebViewController
webMessageListener.dispose(); webMessageListener.dispose();
} }
_webMessageListeners.clear(); _webMessageListeners.clear();
_devToolsProtocolEventListenerMap.clear();
} }
} }
} }

View File

@ -21,25 +21,48 @@ namespace flutter_inappwebview_plugin
wndClass.hInstance = m_hInstance; wndClass.hInstance = m_hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO); wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpfnWndProc = InAppBrowser::WndProc; wndClass.lpfnWndProc = InAppBrowser::WndProc;
RegisterClass(&wndClass); RegisterClass(&wndClass);
auto parentWindow = plugin->registrar->GetView()->GetNativeWindow();
RECT bounds;
GetWindowRect(parentWindow, &bounds);
auto x = CW_USEDEFAULT;
auto y = CW_USEDEFAULT;
auto width = bounds.right - bounds.left;
auto height = bounds.bottom - bounds.top;
if (settings->windowFrame) {
x = (int)settings->windowFrame->x;
y = (int)settings->windowFrame->y;
width = (int)settings->windowFrame->width;
height = (int)settings->windowFrame->height;
}
m_hWnd = CreateWindowEx( m_hWnd = CreateWindowEx(
0, // Optional window styles. WS_EX_LAYERED, // Optional window styles.
wndClass.lpszClassName, // Window class wndClass.lpszClassName, // Window class
L"", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position settings->toolbarTopFixedTitle.empty() ? L"" : utf8_to_wide(settings->toolbarTopFixedTitle).c_str(), // Window text
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window settings->windowType == InAppBrowserWindowType::window ? WS_OVERLAPPEDWINDOW : (WS_CHILDWINDOW | WS_OVERLAPPEDWINDOW), // Window style
NULL, // Menu
// Position
x, y,
// Size
width, height,
settings->windowType == InAppBrowserWindowType::window ? nullptr : parentWindow, // Parent window
nullptr, // Menu
wndClass.hInstance, // Instance handle wndClass.hInstance, // Instance handle
this // Additional application data this // Additional application data
); );
SetLayeredWindowAttributes(m_hWnd, 0, (BYTE)(255 * settings->windowAlphaValue), LWA_ALPHA);
ShowWindow(m_hWnd, settings->hidden ? SW_HIDE : SW_SHOW); ShowWindow(m_hWnd, settings->hidden ? SW_HIDE : SW_SHOW);
InAppWebViewCreationParams webViewParams = { InAppWebViewCreationParams webViewParams = {
@ -99,9 +122,49 @@ namespace flutter_inappwebview_plugin
return !IsWindowVisible(m_hWnd); return !IsWindowVisible(m_hWnd);
} }
void InAppBrowser::setSettings(const std::shared_ptr<InAppBrowserSettings> newSettings, const flutter::EncodableMap& newSettingsMap)
{
if (webView) {
webView->setSettings(std::make_shared<InAppWebViewSettings>(newSettingsMap), newSettingsMap);
}
if (fl_map_contains_not_null(newSettingsMap, "hidden") && settings->hidden != newSettings->hidden) {
newSettings->hidden ? hide() : show();
}
if (fl_map_contains_not_null(newSettingsMap, "toolbarTopFixedTitle") && !string_equals(settings->toolbarTopFixedTitle, newSettings->toolbarTopFixedTitle) && !newSettings->toolbarTopFixedTitle.empty()) {
SetWindowText(m_hWnd, utf8_to_wide(newSettings->toolbarTopFixedTitle).c_str());
}
if (fl_map_contains_not_null(newSettingsMap, "windowAlphaValue") && settings->windowAlphaValue != newSettings->windowAlphaValue) {
SetLayeredWindowAttributes(m_hWnd, 0, (BYTE)(255 * newSettings->windowAlphaValue), LWA_ALPHA);
}
if (fl_map_contains_not_null(newSettingsMap, "windowFrame")) {
auto x = (int)newSettings->windowFrame->x;
auto y = (int)newSettings->windowFrame->y;
auto width = (int)newSettings->windowFrame->width;
auto height = (int)newSettings->windowFrame->height;
MoveWindow(m_hWnd, x, y, width, height, true);
}
settings = newSettings;
}
flutter::EncodableValue InAppBrowser::getSettings() const
{
if (!settings || !webView) {
return make_fl_value();
}
auto encodableMap = settings->getRealSettings(this);
encodableMap.merge(std::get<flutter::EncodableMap>(webView->getSettings()));
return encodableMap;
}
void InAppBrowser::didChangeTitle(const std::optional<std::string>& title) const void InAppBrowser::didChangeTitle(const std::optional<std::string>& title) const
{ {
if (title.has_value()) { if (title.has_value() && settings->toolbarTopFixedTitle.empty()) {
SetWindowText(m_hWnd, utf8_to_wide(title.value()).c_str()); SetWindowText(m_hWnd, utf8_to_wide(title.value()).c_str());
} }
} }

View File

@ -3,7 +3,6 @@
#include <optional> #include <optional>
#include <string> #include <string>
#include <wil/com.h>
#include <Windows.h> #include <Windows.h>
#include "../flutter_inappwebview_windows_plugin.h" #include "../flutter_inappwebview_windows_plugin.h"
@ -41,7 +40,7 @@ namespace flutter_inappwebview_plugin
const std::string id; const std::string id;
std::unique_ptr<InAppWebView> webView; std::unique_ptr<InAppWebView> webView;
std::unique_ptr<InAppBrowserChannelDelegate> channelDelegate; std::unique_ptr<InAppBrowserChannelDelegate> channelDelegate;
const std::shared_ptr<InAppBrowserSettings> settings; std::shared_ptr<InAppBrowserSettings> settings;
InAppBrowser(const FlutterInappwebviewWindowsPlugin* plugin, const InAppBrowserCreationParams& params); InAppBrowser(const FlutterInappwebviewWindowsPlugin* plugin, const InAppBrowserCreationParams& params);
~InAppBrowser(); ~InAppBrowser();
@ -50,9 +49,14 @@ namespace flutter_inappwebview_plugin
void show() const; void show() const;
void hide() const; void hide() const;
bool isHidden() const; bool isHidden() const;
void setSettings(const std::shared_ptr<InAppBrowserSettings> newSettings, const flutter::EncodableMap& newSettingsMap);
flutter::EncodableValue getSettings() const;
void didChangeTitle(const std::optional<std::string>& title) const; void didChangeTitle(const std::optional<std::string>& title) const;
HWND getHWND() const
{
return m_hWnd;
}
private: private:
const HINSTANCE m_hInstance; const HINSTANCE m_hInstance;
HWND m_hWnd; HWND m_hWnd;

View File

@ -1,29 +1,27 @@
#include "../utils/flutter.h" #include "../utils/flutter.h"
#include "../utils/log.h" #include "../utils/log.h"
#include "../utils/string.h"
#include "in_app_browser_settings.h" #include "in_app_browser_settings.h"
#include "in_app_browser.h"
namespace flutter_inappwebview_plugin namespace flutter_inappwebview_plugin
{ {
namespace namespace
{ {
InAppBrowserWindowType inAppBrowserWindowTypeFromString(const std::string& s) InAppBrowserWindowType inAppBrowserWindowTypeFromString(const std::string& s)
{ {
if (s.compare("CHILD") == 0) { if (string_equals(s, "CHILD")) {
return child; return InAppBrowserWindowType::child;
} }
else if (s.compare("TABBED") == 0) { return InAppBrowserWindowType::window;
return tabbed;
}
return window;
} }
std::string inAppBrowserWindowTypeToString(const InAppBrowserWindowType& t) std::string inAppBrowserWindowTypeToString(const InAppBrowserWindowType& t)
{ {
switch (t) { switch (t) {
case child: case InAppBrowserWindowType::child:
return "CHILD"; return "CHILD";
case tabbed:
return "TABBED";
default: default:
return "WINDOW"; return "WINDOW";
} }
@ -35,8 +33,40 @@ namespace flutter_inappwebview_plugin
InAppBrowserSettings::InAppBrowserSettings(const flutter::EncodableMap& encodableMap) InAppBrowserSettings::InAppBrowserSettings(const flutter::EncodableMap& encodableMap)
{ {
hidden = get_fl_map_value(encodableMap, "hidden", hidden); hidden = get_fl_map_value(encodableMap, "hidden", hidden);
windowType = inAppBrowserWindowTypeFromString(get_fl_map_value<std::string>(encodableMap, "windowType", inAppBrowserWindowTypeToString(window))); windowType = inAppBrowserWindowTypeFromString(get_fl_map_value<std::string>(encodableMap, "windowType", inAppBrowserWindowTypeToString(InAppBrowserWindowType::window)));
toolbarTopFixedTitle = get_fl_map_value(encodableMap, "toolbarTopFixedTitle", toolbarTopFixedTitle);
windowAlphaValue = get_fl_map_value(encodableMap, "windowAlphaValue", windowAlphaValue); windowAlphaValue = get_fl_map_value(encodableMap, "windowAlphaValue", windowAlphaValue);
auto windowFrameMap = get_optional_fl_map_value<flutter::EncodableMap>(encodableMap, "windowFrame");
if (windowFrameMap.has_value()) {
windowFrame = std::make_shared<Rect>(windowFrameMap.value());
}
}
flutter::EncodableMap InAppBrowserSettings::toEncodableMap() const
{
return flutter::EncodableMap{
{"hidden", hidden},
{"windowType", inAppBrowserWindowTypeToString(windowType)},
{"toolbarTopFixedTitle", toolbarTopFixedTitle},
{"windowAlphaValue", windowAlphaValue},
{"windowFrame", windowFrame ? windowFrame->toEncodableMap() : make_fl_value()},
};
}
flutter::EncodableMap InAppBrowserSettings::getRealSettings(const InAppBrowser* inAppBrowser) const
{
auto settingsMap = toEncodableMap();
settingsMap["hidden"] = inAppBrowser->isHidden();
BYTE alphaValue = 0;
GetLayeredWindowAttributes(inAppBrowser->getHWND(), nullptr, &alphaValue, nullptr);
settingsMap["windowAlphaValue"] = (double)alphaValue;
RECT position;
GetWindowRect(inAppBrowser->getHWND(), &position);
settingsMap["windowFrame"] = std::make_unique<Rect>(position.left, position.top, position.right - position.left, position.bottom - position.top)->toEncodableMap();
return settingsMap;
} }
InAppBrowserSettings::~InAppBrowserSettings() InAppBrowserSettings::~InAppBrowserSettings()

View File

@ -2,14 +2,18 @@
#define FLUTTER_INAPPWEBVIEW_PLUGIN_IN_APP_BROWSER_SETTINGS_H_ #define FLUTTER_INAPPWEBVIEW_PLUGIN_IN_APP_BROWSER_SETTINGS_H_
#include <flutter/standard_message_codec.h> #include <flutter/standard_message_codec.h>
#include <optional>
#include <string> #include <string>
#include "../types/rect.h"
namespace flutter_inappwebview_plugin namespace flutter_inappwebview_plugin
{ {
class InAppBrowser;
enum InAppBrowserWindowType { enum InAppBrowserWindowType {
window, window,
child, child
tabbed
}; };
class InAppBrowserSettings class InAppBrowserSettings
@ -17,11 +21,16 @@ namespace flutter_inappwebview_plugin
public: public:
bool hidden = false; bool hidden = false;
InAppBrowserWindowType windowType = window; InAppBrowserWindowType windowType = window;
std::string toolbarTopFixedTitle;
double windowAlphaValue = 1.0; double windowAlphaValue = 1.0;
std::shared_ptr<Rect> windowFrame;
InAppBrowserSettings(); InAppBrowserSettings();
InAppBrowserSettings(const flutter::EncodableMap& encodableMap); InAppBrowserSettings(const flutter::EncodableMap& encodableMap);
~InAppBrowserSettings(); ~InAppBrowserSettings();
flutter::EncodableMap toEncodableMap() const;
flutter::EncodableMap getRealSettings(const InAppBrowser* inAppBrowser) const;
}; };
} }
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_IN_APP_BROWSER_SETTINGS_H_ #endif //FLUTTER_INAPPWEBVIEW_PLUGIN_IN_APP_BROWSER_SETTINGS_H_

View File

@ -143,6 +143,8 @@ namespace flutter_inappwebview_plugin
if (succeededOrLog(hrWebView2Settings)) { if (succeededOrLog(hrWebView2Settings)) {
webView2Settings->put_IsScriptEnabled(settings->javaScriptEnabled); webView2Settings->put_IsScriptEnabled(settings->javaScriptEnabled);
webView2Settings->put_IsZoomControlEnabled(settings->supportZoom); webView2Settings->put_IsZoomControlEnabled(settings->supportZoom);
webView2Settings->put_AreDevToolsEnabled(settings->isInspectable);
webView2Settings->put_AreDefaultContextMenusEnabled(!settings->disableContextMenu);
wil::com_ptr<ICoreWebView2Settings2> webView2Settings2; wil::com_ptr<ICoreWebView2Settings2> webView2Settings2;
if (succeededOrLog(webView2Settings->QueryInterface(IID_PPV_ARGS(&webView2Settings2)))) { if (succeededOrLog(webView2Settings->QueryInterface(IID_PPV_ARGS(&webView2Settings2)))) {
@ -152,6 +154,13 @@ namespace flutter_inappwebview_plugin
} }
} }
wil::com_ptr<ICoreWebView2Controller2> webViewController2;
if (succeededOrLog(webViewController->QueryInterface(IID_PPV_ARGS(&webViewController2)))) {
if (!settings->transparentBackground) {
webViewController2->put_DefaultBackgroundColor({ 0, 255, 255, 255 });
}
}
// required to make Runtime events work // required to make Runtime events work
failedLog(webView->CallDevToolsProtocolMethod(L"Runtime.enable", L"{}", Callback<ICoreWebView2CallDevToolsProtocolMethodCompletedHandler>( failedLog(webView->CallDevToolsProtocolMethod(L"Runtime.enable", L"{}", Callback<ICoreWebView2CallDevToolsProtocolMethodCompletedHandler>(
[this](HRESULT errorCode, LPCWSTR returnObjectAsJson) [this](HRESULT errorCode, LPCWSTR returnObjectAsJson)
@ -971,6 +980,137 @@ namespace flutter_inappwebview_plugin
} }
} }
void InAppWebView::setSettings(const std::shared_ptr<InAppWebViewSettings> newSettings, const flutter::EncodableMap& newSettingsMap)
{
wil::com_ptr<ICoreWebView2Settings> webView2Settings;
if (succeededOrLog(webView->get_Settings(&webView2Settings))) {
if (fl_map_contains_not_null(newSettingsMap, "javaScriptEnabled") && settings->javaScriptEnabled != newSettings->javaScriptEnabled) {
webView2Settings->put_IsScriptEnabled(newSettings->javaScriptEnabled);
}
if (fl_map_contains_not_null(newSettingsMap, "supportZoom") && settings->supportZoom != newSettings->supportZoom) {
webView2Settings->put_IsZoomControlEnabled(newSettings->supportZoom);
}
if (fl_map_contains_not_null(newSettingsMap, "isInspectable") && settings->isInspectable != newSettings->isInspectable) {
webView2Settings->put_AreDevToolsEnabled(newSettings->isInspectable);
}
if (fl_map_contains_not_null(newSettingsMap, "disableContextMenu") && settings->disableContextMenu != newSettings->disableContextMenu) {
webView2Settings->put_AreDefaultContextMenusEnabled(!newSettings->disableContextMenu);
}
wil::com_ptr<ICoreWebView2Settings2> webView2Settings2;
if (succeededOrLog(webView2Settings->QueryInterface(IID_PPV_ARGS(&webView2Settings2)))) {
if (fl_map_contains_not_null(newSettingsMap, "userAgent") && !string_equals(settings->userAgent, newSettings->userAgent)) {
webView2Settings2->put_UserAgent(utf8_to_wide(newSettings->userAgent).c_str());
}
}
}
wil::com_ptr<ICoreWebView2Controller2> webViewController2;
if (succeededOrLog(webViewController->QueryInterface(IID_PPV_ARGS(&webViewController2)))) {
if (fl_map_contains_not_null(newSettingsMap, "transparentBackground") && settings->transparentBackground != newSettings->transparentBackground) {
BYTE alpha = newSettings->transparentBackground ? 0 : 255;
webViewController2->put_DefaultBackgroundColor({ alpha, 255, 255, 255 });
}
}
settings = newSettings;
}
flutter::EncodableValue InAppWebView::getSettings() const
{
if (!settings || !webView) {
return make_fl_value();
}
wil::com_ptr<ICoreWebView2Settings> webView2Settings;
if (succeededOrLog(webView->get_Settings(&webView2Settings))) {
return settings->getRealSettings(webView2Settings.get());
}
return settings->toEncodableMap();
}
void InAppWebView::openDevTools() const
{
if (!webView) {
return;
}
failedLog(webView->OpenDevToolsWindow());
}
void InAppWebView::callDevToolsProtocolMethod(const std::string& methodName, const std::optional<std::string>& parametersAsJson, const std::function<void(const HRESULT& errorCode, const std::optional<std::string>&)> completionHandler) const
{
if (!webView) {
if (completionHandler) {
completionHandler(S_OK, std::nullopt);
}
return;
}
auto hr = webView->CallDevToolsProtocolMethod(
utf8_to_wide(methodName).c_str(),
!parametersAsJson.has_value() || parametersAsJson.value().empty() ? L"{}" : utf8_to_wide(parametersAsJson.value()).c_str(),
Callback<ICoreWebView2CallDevToolsProtocolMethodCompletedHandler>(
[completionHandler](HRESULT errorCode, LPCWSTR returnObjectAsJson)
{
failedLog(errorCode);
if (completionHandler) {
completionHandler(errorCode, wide_to_utf8(returnObjectAsJson));
}
return S_OK;
}
).Get());
if (failedAndLog(hr) && completionHandler) {
completionHandler(hr, std::nullopt);
}
}
void InAppWebView::addDevToolsProtocolEventListener(const std::string& eventName)
{
if (map_contains(devToolsProtocolEventListener_, eventName)) {
return;
}
wil::com_ptr<ICoreWebView2DevToolsProtocolEventReceiver> eventReceiver;
if (succeededOrLog(webView->GetDevToolsProtocolEventReceiver(utf8_to_wide(eventName).c_str(), &eventReceiver))) {
EventRegistrationToken token = {};
auto hr = eventReceiver->add_DevToolsProtocolEventReceived(
Callback<ICoreWebView2DevToolsProtocolEventReceivedEventHandler>(
[this, eventName](
ICoreWebView2* sender,
ICoreWebView2DevToolsProtocolEventReceivedEventArgs* args) -> HRESULT
{
if (!channelDelegate) {
return S_OK;
}
wil::unique_cotaskmem_string json;
failedLog(args->get_ParameterObjectAsJson(&json));
channelDelegate->onDevToolsProtocolEventReceived(eventName, wide_to_utf8(json.get()));
return S_OK;
})
.Get(), &token);
if (succeededOrLog(hr)) {
devToolsProtocolEventListener_.insert({ eventName, std::make_pair(std::move(eventReceiver), token) });
}
}
}
void InAppWebView::removeDevToolsProtocolEventListener(const std::string& eventName)
{
if (map_contains(devToolsProtocolEventListener_, eventName)) {
auto eventReceiver = devToolsProtocolEventListener_.at(eventName).first;
auto token = devToolsProtocolEventListener_.at(eventName).second;
eventReceiver->remove_DevToolsProtocolEventReceived(token);
devToolsProtocolEventListener_.erase(eventName);
}
}
// flutter_view // flutter_view
void InAppWebView::setSurfaceSize(size_t width, size_t height, float scale_factor) void InAppWebView::setSurfaceSize(size_t width, size_t height, float scale_factor)
{ {

View File

@ -95,7 +95,7 @@ namespace flutter_inappwebview_plugin
wil::com_ptr<ICoreWebView2CompositionController> webViewCompositionController; wil::com_ptr<ICoreWebView2CompositionController> webViewCompositionController;
wil::com_ptr<ICoreWebView2> webView; wil::com_ptr<ICoreWebView2> webView;
std::unique_ptr<WebViewChannelDelegate> channelDelegate; std::unique_ptr<WebViewChannelDelegate> channelDelegate;
const std::shared_ptr<InAppWebViewSettings> settings; std::shared_ptr<InAppWebViewSettings> settings;
InAppBrowser* inAppBrowser = nullptr; InAppBrowser* inAppBrowser = nullptr;
std::unique_ptr<UserContentController> userContentController; std::unique_ptr<UserContentController> userContentController;
@ -164,6 +164,12 @@ namespace flutter_inappwebview_plugin
void removeUserScriptsByGroupName(const std::string& groupName) const; void removeUserScriptsByGroupName(const std::string& groupName) const;
void removeAllUserScripts() const; void removeAllUserScripts() const;
void takeScreenshot(const std::optional<std::shared_ptr<ScreenshotConfiguration>> screenshotConfiguration, const std::function<void(const std::optional<std::string>)> completionHandler) const; void takeScreenshot(const std::optional<std::shared_ptr<ScreenshotConfiguration>> screenshotConfiguration, const std::function<void(const std::optional<std::string>)> completionHandler) const;
void setSettings(const std::shared_ptr<InAppWebViewSettings> newSettings, const flutter::EncodableMap& newSettingsMap);
flutter::EncodableValue getSettings() const;
void openDevTools() const;
void callDevToolsProtocolMethod(const std::string& methodName, const std::optional<std::string>& parametersAsJson, const std::function<void(const HRESULT& errorCode, const std::optional<std::string>&)> completionHandler) const;
void addDevToolsProtocolEventListener(const std::string& eventName);
void removeDevToolsProtocolEventListener(const std::string& eventName);
std::string pageFrameId() const std::string pageFrameId() const
{ {
@ -185,6 +191,7 @@ namespace flutter_inappwebview_plugin
std::shared_ptr<NavigationAction> lastNavigationAction_; std::shared_ptr<NavigationAction> lastNavigationAction_;
bool isLoading_ = false; bool isLoading_ = false;
std::string pageFrameId_; std::string pageFrameId_;
std::map<std::string, std::pair<wil::com_ptr<ICoreWebView2DevToolsProtocolEventReceiver>, EventRegistrationToken>> devToolsProtocolEventListener_ = {};
void registerEventHandlers(); void registerEventHandlers();
void registerSurfaceEventHandlers(); void registerSurfaceEventHandlers();

View File

@ -2,8 +2,12 @@
#include "../utils/log.h" #include "../utils/log.h"
#include "in_app_webview_settings.h" #include "in_app_webview_settings.h"
#include <wil/com.h>
namespace flutter_inappwebview_plugin namespace flutter_inappwebview_plugin
{ {
using namespace Microsoft::WRL;
InAppWebViewSettings::InAppWebViewSettings() {}; InAppWebViewSettings::InAppWebViewSettings() {};
InAppWebViewSettings::InAppWebViewSettings(const flutter::EncodableMap& encodableMap) InAppWebViewSettings::InAppWebViewSettings(const flutter::EncodableMap& encodableMap)
@ -16,6 +20,56 @@ namespace flutter_inappwebview_plugin
resourceCustomSchemes = get_fl_map_value(encodableMap, "resourceCustomSchemes", resourceCustomSchemes); resourceCustomSchemes = get_fl_map_value(encodableMap, "resourceCustomSchemes", resourceCustomSchemes);
transparentBackground = get_fl_map_value(encodableMap, "transparentBackground", transparentBackground); transparentBackground = get_fl_map_value(encodableMap, "transparentBackground", transparentBackground);
supportZoom = get_fl_map_value(encodableMap, "supportZoom", supportZoom); supportZoom = get_fl_map_value(encodableMap, "supportZoom", supportZoom);
isInspectable = get_fl_map_value(encodableMap, "isInspectable", isInspectable);
disableContextMenu = get_fl_map_value(encodableMap, "disableContextMenu", disableContextMenu);
}
flutter::EncodableMap InAppWebViewSettings::toEncodableMap() const
{
return flutter::EncodableMap{
{"useShouldOverrideUrlLoading", useShouldOverrideUrlLoading},
{"useOnLoadResource", useOnLoadResource},
{"useOnDownloadStart", useOnDownloadStart},
{"userAgent", userAgent},
{"javaScriptEnabled", javaScriptEnabled},
{"resourceCustomSchemes", make_fl_value(resourceCustomSchemes)},
{"transparentBackground", transparentBackground},
{"supportZoom", supportZoom},
{"isInspectable", isInspectable},
{"disableContextMenu", disableContextMenu},
};
}
flutter::EncodableMap InAppWebViewSettings::getRealSettings(ICoreWebView2Settings* settings) const
{
auto settingsMap = toEncodableMap();
if (settings) {
BOOL realJavaScriptEnabled;
if (SUCCEEDED(settings->get_IsScriptEnabled(&realJavaScriptEnabled))) {
settingsMap["javaScriptEnabled"] = (bool)realJavaScriptEnabled;
}
BOOL realSupportZoom;
if (SUCCEEDED(settings->get_IsZoomControlEnabled(&realSupportZoom))) {
settingsMap["supportZoom"] = (bool)realSupportZoom;
}
BOOL realIsInspectable;
if (SUCCEEDED(settings->get_AreDevToolsEnabled(&realIsInspectable))) {
settingsMap["isInspectable"] = (bool)realIsInspectable;
}
BOOL areDefaultContextMenusEnabled;
if (SUCCEEDED(settings->get_AreDefaultContextMenusEnabled(&areDefaultContextMenusEnabled))) {
settingsMap["disableContextMenu"] = !(bool)areDefaultContextMenusEnabled;
}
wil::com_ptr<ICoreWebView2Settings2> settings2;
if (SUCCEEDED(settings->QueryInterface(IID_PPV_ARGS(&settings2)))) {
wil::unique_cotaskmem_string realUserAgent;
if (SUCCEEDED(settings2->get_UserAgent(&realUserAgent))) {
settingsMap["userAgent"] = wide_to_utf8(realUserAgent.get());
}
}
}
return settingsMap;
} }
InAppWebViewSettings::~InAppWebViewSettings() InAppWebViewSettings::~InAppWebViewSettings()

View File

@ -3,6 +3,7 @@
#include <flutter/standard_message_codec.h> #include <flutter/standard_message_codec.h>
#include <string> #include <string>
#include <WebView2.h>
namespace flutter_inappwebview_plugin namespace flutter_inappwebview_plugin
{ {
@ -17,10 +18,15 @@ namespace flutter_inappwebview_plugin
std::vector<std::string> resourceCustomSchemes; std::vector<std::string> resourceCustomSchemes;
bool transparentBackground = false; bool transparentBackground = false;
bool supportZoom = true; bool supportZoom = true;
bool isInspectable = true;
bool disableContextMenu = false;
InAppWebViewSettings(); InAppWebViewSettings();
InAppWebViewSettings(const flutter::EncodableMap& encodableMap); InAppWebViewSettings(const flutter::EncodableMap& encodableMap);
~InAppWebViewSettings(); ~InAppWebViewSettings();
flutter::EncodableMap toEncodableMap() const;
flutter::EncodableMap getRealSettings(ICoreWebView2Settings* settings) const;
}; };
} }
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_IN_APP_WEBVIEW_SETTINGS_H_ #endif //FLUTTER_INAPPWEBVIEW_PLUGIN_IN_APP_WEBVIEW_SETTINGS_H_

View File

@ -169,6 +169,55 @@ namespace flutter_inappwebview_plugin
result_->Success(make_fl_value(data)); result_->Success(make_fl_value(data));
}); });
} }
else if (string_equals(methodName, "setSettings")) {
if (webView->inAppBrowser) {
auto settingsMap = get_fl_map_value<flutter::EncodableMap>(arguments, "settings");
auto settings = std::make_unique<InAppBrowserSettings>(settingsMap);
webView->inAppBrowser->setSettings(std::move(settings), settingsMap);
}
else {
auto settingsMap = get_fl_map_value<flutter::EncodableMap>(arguments, "settings");
auto settings = std::make_unique<InAppWebViewSettings>(settingsMap);
webView->setSettings(std::move(settings), settingsMap);
}
result->Success(true);
}
else if (string_equals(methodName, "getSettings")) {
if (webView->inAppBrowser) {
result->Success(webView->inAppBrowser->getSettings());
}
else {
result->Success(webView->getSettings());
}
}
else if (string_equals(methodName, "openDevTools")) {
webView->openDevTools();
result->Success(true);
}
else if (string_equals(methodName, "callDevToolsProtocolMethod")) {
auto result_ = std::shared_ptr<flutter::MethodResult<flutter::EncodableValue>>(std::move(result));
auto cdpMethodName = get_fl_map_value<std::string>(arguments, "methodName");
auto parametersAsJson = get_optional_fl_map_value<std::string>(arguments, "parametersAsJson");
webView->callDevToolsProtocolMethod(cdpMethodName, parametersAsJson, [result_ = std::move(result_)](const HRESULT& errorCode, const std::optional<std::string>& data)
{
if (SUCCEEDED(errorCode)) {
result_->Success(make_fl_value(data));
}
else {
result_->Error(std::to_string(errorCode), getHRMessage(errorCode));
}
});
}
else if (string_equals(methodName, "addDevToolsProtocolEventListener")) {
auto eventName = get_fl_map_value<std::string>(arguments, "eventName");
webView->addDevToolsProtocolEventListener(eventName);
result->Success(true);
}
else if (string_equals(methodName, "removeDevToolsProtocolEventListener")) {
auto eventName = get_fl_map_value<std::string>(arguments, "eventName");
webView->removeDevToolsProtocolEventListener(eventName);
result->Success(true);
}
// for inAppBrowser // for inAppBrowser
else if (webView->inAppBrowser && string_equals(methodName, "show")) { else if (webView->inAppBrowser && string_equals(methodName, "show")) {
webView->inAppBrowser->show(); webView->inAppBrowser->show();
@ -302,6 +351,20 @@ namespace flutter_inappwebview_plugin
channel->InvokeMethod("onConsoleMessage", std::move(arguments)); channel->InvokeMethod("onConsoleMessage", std::move(arguments));
} }
void WebViewChannelDelegate::onDevToolsProtocolEventReceived(const std::string& eventName, const std::string& data) const
{
if (!channel) {
return;
}
auto arguments = std::make_unique<flutter::EncodableValue>(flutter::EncodableMap{
{"eventName", eventName},
{"data", data}
});
channel->InvokeMethod("onDevToolsProtocolEventReceived", std::move(arguments));
}
WebViewChannelDelegate::~WebViewChannelDelegate() WebViewChannelDelegate::~WebViewChannelDelegate()
{ {
debugLog("dealloc WebViewChannelDelegate"); debugLog("dealloc WebViewChannelDelegate");

View File

@ -51,6 +51,7 @@ namespace flutter_inappwebview_plugin
void onUpdateVisitedHistory(const std::optional<std::string>& url, const std::optional<bool>& isReload) const; void onUpdateVisitedHistory(const std::optional<std::string>& url, const std::optional<bool>& isReload) const;
void onCallJsHandler(const std::string& handlerName, const std::string& args, std::unique_ptr<CallJsHandlerCallback> callback) const; void onCallJsHandler(const std::string& handlerName, const std::string& args, std::unique_ptr<CallJsHandlerCallback> callback) const;
void onConsoleMessage(const std::string& message, const int64_t& messageLevel) const; void onConsoleMessage(const std::string& message, const int64_t& messageLevel) const;
void onDevToolsProtocolEventReceived(const std::string& eventName, const std::string& data) const;
}; };
} }

View File

@ -20,6 +20,15 @@ namespace flutter_inappwebview_plugin
Rect(const flutter::EncodableMap& map); Rect(const flutter::EncodableMap& map);
~Rect() = default; ~Rect() = default;
bool Rect::operator==(const Rect& other)
{
return x == other.x && y == other.y && width == other.width && height == other.height;
}
bool Rect::operator!=(const Rect& other)
{
return !(*this == other);
}
flutter::EncodableMap toEncodableMap() const; flutter::EncodableMap toEncodableMap() const;
}; };
} }

View File

@ -18,6 +18,15 @@ namespace flutter_inappwebview_plugin
Size2D(const flutter::EncodableMap& map); Size2D(const flutter::EncodableMap& map);
~Size2D() = default; ~Size2D() = default;
bool Size2D::operator==(const Size2D& other)
{
return width == other.width && height == other.height;
}
bool Size2D::operator!=(const Size2D& other)
{
return !(*this == other);
}
flutter::EncodableMap toEncodableMap() const; flutter::EncodableMap toEncodableMap() const;
}; };
} }

View File

@ -4,6 +4,7 @@
#include <optional> #include <optional>
#include <string> #include <string>
#include <variant> #include <variant>
#include <Windows.h>
namespace flutter_inappwebview_plugin namespace flutter_inappwebview_plugin
{ {
@ -26,6 +27,12 @@ namespace flutter_inappwebview_plugin
static_assert(always_false_v<T>, "non-exhaustive visitor!"); static_assert(always_false_v<T>, "non-exhaustive visitor!");
}, var); }, var);
} }
static inline float get_current_scale_factor(HWND hwnd)
{
auto dpi = GetDpiForWindow(hwnd);
return dpi > 0 ? dpi / 96.0f : 1.0f;
}
} }
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_H_ #endif //FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_H_