1
+ #include < DispatcherQueue.h>
2
+ #include < flutter/method_channel.h>
3
+ #include < flutter/standard_method_codec.h>
4
+ #include < shlobj.h>
5
+ #include < windows.graphics.capture.h>
6
+
7
+ #include " ../in_app_webview/in_app_webview_settings.h"
8
+ #include " ../types/size_2d.h"
9
+ #include " ../types/url_request.h"
10
+ #include " ../types/user_script.h"
11
+ #include " ../utils/flutter.h"
12
+ #include " ../utils/log.h"
13
+ #include " ../utils/string.h"
14
+ #include " ../utils/vector.h"
15
+ #include " headless_in_app_webview_manager.h"
16
+
17
+ namespace flutter_inappwebview_plugin
18
+ {
19
+ HeadlessInAppWebViewManager::HeadlessInAppWebViewManager (const FlutterInappwebviewWindowsPlugin* plugin)
20
+ : plugin(plugin),
21
+ ChannelDelegate (plugin->registrar->messenger (), HeadlessInAppWebViewManager::METHOD_CHANNEL_NAME)
22
+ {
23
+ windowClass_.lpszClassName = HeadlessInAppWebView::CLASS_NAME;
24
+ windowClass_.lpfnWndProc = &DefWindowProc;
25
+
26
+ RegisterClass (&windowClass_);
27
+ }
28
+
29
+ void HeadlessInAppWebViewManager::HandleMethodCall (const flutter::MethodCall<flutter::EncodableValue>& method_call,
30
+ std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result)
31
+ {
32
+ auto * arguments = std::get_if<flutter::EncodableMap>(method_call.arguments ());
33
+ auto & methodName = method_call.method_name ();
34
+
35
+ if (string_equals (methodName, " run" )) {
36
+ run (arguments, std::move (result));
37
+ }
38
+ else {
39
+ result->NotImplemented ();
40
+ }
41
+ }
42
+
43
+ void HeadlessInAppWebViewManager::run (const flutter::EncodableMap* arguments, std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result)
44
+ {
45
+ auto result_ = std::shared_ptr<flutter::MethodResult<flutter::EncodableValue>>(std::move (result));
46
+
47
+ auto id = get_fl_map_value<std::string>(*arguments, " id" );
48
+ auto params = get_fl_map_value<flutter::EncodableMap>(*arguments, " params" );
49
+
50
+ auto initialSize = std::make_shared<Size2D>(get_fl_map_value<flutter::EncodableMap>(params, " initialSize" ));
51
+
52
+ auto settingsMap = get_fl_map_value<flutter::EncodableMap>(params, " initialSettings" );
53
+ auto urlRequestMap = get_optional_fl_map_value<flutter::EncodableMap>(params, " initialUrlRequest" );
54
+ auto initialFile = get_optional_fl_map_value<std::string>(params, " initialFile" );
55
+ auto initialDataMap = get_optional_fl_map_value<flutter::EncodableMap>(params, " initialData" );
56
+ auto initialUserScriptList = get_optional_fl_map_value<flutter::EncodableList>(params, " initialUserScripts" );
57
+
58
+ RECT bounds;
59
+ GetClientRect (plugin->registrar ->GetView ()->GetNativeWindow (), &bounds);
60
+
61
+ auto initialWidth = initialSize->width >= 0 ? initialSize->width : bounds.right - bounds.left ;
62
+ auto initialHeight = initialSize->height >= 0 ? initialSize->height : bounds.bottom - bounds.top ;
63
+
64
+ auto hwnd = CreateWindowEx (0 , windowClass_.lpszClassName , L" " , 0 , 0 ,
65
+ 0 , (int )initialWidth, (int )initialHeight,
66
+ plugin->registrar ->GetView ()->GetNativeWindow (),
67
+ nullptr ,
68
+ windowClass_.hInstance , nullptr );
69
+
70
+ InAppWebView::createInAppWebViewEnv (hwnd, false ,
71
+ [=](wil::com_ptr<ICoreWebView2Environment> webViewEnv,
72
+ wil::com_ptr<ICoreWebView2Controller> webViewController,
73
+ wil::com_ptr<ICoreWebView2CompositionController> webViewCompositionController)
74
+ {
75
+ if (webViewEnv && webViewController) {
76
+ auto initialSettings = std::make_unique<InAppWebViewSettings>(settingsMap);
77
+ std::optional<std::vector<std::shared_ptr<UserScript>>> initialUserScripts = initialUserScriptList.has_value () ?
78
+ functional_map (initialUserScriptList.value (), [](const flutter::EncodableValue& map) { return std::make_shared<UserScript>(std::get<flutter::EncodableMap>(map)); }) :
79
+ std::optional<std::vector<std::shared_ptr<UserScript>>>{};
80
+
81
+ InAppWebViewCreationParams params = {
82
+ id,
83
+ std::move (initialSettings),
84
+ initialUserScripts
85
+ };
86
+
87
+ auto inAppWebView = std::make_unique<InAppWebView>(plugin, params, hwnd,
88
+ std::move (webViewEnv), std::move (webViewController), nullptr
89
+ );
90
+
91
+ HeadlessInAppWebViewCreationParams headlessParams = {
92
+ id,
93
+ std::move (initialSize)
94
+ };
95
+
96
+ auto headlessInAppWebView = std::make_unique<HeadlessInAppWebView>(plugin,
97
+ headlessParams,
98
+ hwnd,
99
+ std::move (inAppWebView));
100
+
101
+ headlessInAppWebView->webView ->initChannel (std::nullopt, std::nullopt);
102
+
103
+ if (headlessInAppWebView->channelDelegate ) {
104
+ headlessInAppWebView->channelDelegate ->onWebViewCreated ();
105
+ }
106
+
107
+ std::optional<std::shared_ptr<URLRequest>> urlRequest = urlRequestMap.has_value () ? std::make_shared<URLRequest>(urlRequestMap.value ()) : std::optional<std::shared_ptr<URLRequest>>{};
108
+ if (urlRequest.has_value ()) {
109
+ headlessInAppWebView->webView ->loadUrl (urlRequest.value ());
110
+ }
111
+ else if (initialFile.has_value ()) {
112
+ headlessInAppWebView->webView ->loadFile (initialFile.value ());
113
+ }
114
+ else if (initialDataMap.has_value ()) {
115
+ headlessInAppWebView->webView ->loadData (get_fl_map_value<std::string>(initialDataMap.value (), " data" ));
116
+ }
117
+
118
+ webViews.insert ({ id, std::move (headlessInAppWebView) });
119
+
120
+ result_->Success (true );
121
+ }
122
+ else {
123
+ result_->Error (" 0" , " Cannot create the HeadlessInAppWebView instance!" );
124
+ }
125
+ }
126
+ );
127
+ }
128
+
129
+ HeadlessInAppWebViewManager::~HeadlessInAppWebViewManager ()
130
+ {
131
+ debugLog (" dealloc HeadlessInAppWebViewManager" );
132
+ webViews.clear ();
133
+ UnregisterClass (windowClass_.lpszClassName , nullptr );
134
+ plugin = nullptr ;
135
+ }
136
+ }
0 commit comments