From 43aa01d9444e9e3ae6c75f52317923b98e6027b2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 7 Jan 2024 03:26:14 +0100 Subject: [PATCH] added implementation for callback result, impl for shouldOverrideUrlLoading --- .../windows/CMakeLists.txt | 3 + .../flutter_inappwebview_windows_plugin.cpp | 12 +- .../windows/in_app_browser/in_app_browser.cpp | 3 +- .../in_app_browser_channel_delegate.cpp | 2 +- .../in_app_browser/in_app_browser_manager.cpp | 6 +- .../windows/in_app_webview/in_app_webview.cpp | 132 ++++++++++++++++-- .../windows/in_app_webview/in_app_webview.h | 2 + .../webview_channel_delegate.cpp | 35 ++++- .../in_app_webview/webview_channel_delegate.h | 11 ++ .../windows/types/base_callback_result.h | 53 +++++++ .../windows/types/channel_delegate.h | 9 +- .../windows/types/navigation_action.cpp | 20 +++ .../windows/types/navigation_action.h | 22 +++ .../windows/types/url_request.cpp | 24 +++- .../windows/types/url_request.h | 5 + .../windows/utils/util.h | 47 ++++++- 16 files changed, 343 insertions(+), 43 deletions(-) create mode 100644 flutter_inappwebview_windows/windows/types/base_callback_result.h create mode 100644 flutter_inappwebview_windows/windows/types/navigation_action.cpp create mode 100644 flutter_inappwebview_windows/windows/types/navigation_action.h diff --git a/flutter_inappwebview_windows/windows/CMakeLists.txt b/flutter_inappwebview_windows/windows/CMakeLists.txt index 532e96c5..a2088f2f 100644 --- a/flutter_inappwebview_windows/windows/CMakeLists.txt +++ b/flutter_inappwebview_windows/windows/CMakeLists.txt @@ -57,8 +57,11 @@ list(APPEND PLUGIN_SOURCES "utils/util.h" "types/channel_delegate.cpp" "types/channel_delegate.h" + "types/base_callback_result.h" "types/url_request.cpp" "types/url_request.h" + "types/navigation_action.cpp" + "types/navigation_action.h" "in_app_webview/in_app_webview.cpp" "in_app_webview/in_app_webview.h" "in_app_webview/webview_channel_delegate.cpp" diff --git a/flutter_inappwebview_windows/windows/flutter_inappwebview_windows_plugin.cpp b/flutter_inappwebview_windows/windows/flutter_inappwebview_windows_plugin.cpp index 4574c7e9..b849e10b 100644 --- a/flutter_inappwebview_windows/windows/flutter_inappwebview_windows_plugin.cpp +++ b/flutter_inappwebview_windows/windows/flutter_inappwebview_windows_plugin.cpp @@ -1,17 +1,7 @@ #include "flutter_inappwebview_windows_plugin.h" -// This must be included before many other Windows headers. -#include - -// For getPlatformVersion; remove unless needed for your plugin implementation. -#include - #include #include -#include - -#include -#include namespace flutter_inappwebview_plugin { @@ -30,6 +20,6 @@ namespace flutter_inappwebview_plugin FlutterInappwebviewWindowsPlugin::~FlutterInappwebviewWindowsPlugin() { - inAppBrowserManager.release(); + } } \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser.cpp b/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser.cpp index b822373b..50bc8e6f 100644 --- a/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser.cpp +++ b/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser.cpp @@ -16,6 +16,7 @@ #include #include #include "../utils/strconv.h" +#include "../utils/util.h" #include #include @@ -229,7 +230,7 @@ namespace flutter_inappwebview_plugin InAppBrowser::~InAppBrowser() { - std::cout << "dealloc InAppBrowser\n"; + debugLog("dealloc InAppBrowser"); webView.reset(); SetWindowLongPtr(m_hWnd, GWLP_USERDATA, 0); plugin = nullptr; diff --git a/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_channel_delegate.cpp b/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_channel_delegate.cpp index 3fab5fab..ebfee72c 100644 --- a/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_channel_delegate.cpp +++ b/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_channel_delegate.cpp @@ -35,6 +35,6 @@ namespace flutter_inappwebview_plugin InAppBrowserChannelDelegate::~InAppBrowserChannelDelegate() { - std::cout << "dealloc InAppBrowserChannelDelegate\n"; + debugLog("dealloc InAppBrowserChannelDelegate"); } } \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_manager.cpp b/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_manager.cpp index 88870d79..b7dad155 100644 --- a/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_manager.cpp +++ b/flutter_inappwebview_windows/windows/in_app_browser/in_app_browser_manager.cpp @@ -45,11 +45,7 @@ namespace flutter_inappwebview_plugin InAppBrowserManager::~InAppBrowserManager() { - std::cout << "dealloc InAppBrowserManager\n"; - for (std::map>::iterator itr = browsers.begin(); itr != browsers.end(); itr++) - { - browsers.erase(itr->first); - } + debugLog("dealloc InAppBrowserManager"); browsers.clear(); plugin = nullptr; } diff --git a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp index bfaf0394..4ec9f748 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp +++ b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp @@ -1,7 +1,11 @@ +#pragma comment(lib, "Shlwapi.lib") + #include "in_app_webview.h" #include #include +#include #include "../utils/strconv.h" +#include "../utils/util.h" namespace flutter_inappwebview_plugin { @@ -24,6 +28,7 @@ namespace flutter_inappwebview_plugin CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, nullptr, Callback( [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 env->CreateCoreWebView2Controller(parentWindow, Callback( [parentWindow, completionHandler, this](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT { @@ -56,13 +61,74 @@ namespace flutter_inappwebview_plugin webView->add_NavigationStarting( Callback( [this](ICoreWebView2* sender, ICoreWebView2NavigationStartingEventArgs* args) { - if (channelDelegate) { - LPWSTR uri = nullptr; - std::optional url = SUCCEEDED(args->get_Uri(&uri)) ? wide_to_utf8(std::wstring(uri)) : std::optional{}; - channelDelegate->onLoadStart(url); + if (!channelDelegate) { + args->put_Cancel(false); + return S_OK; + } + + wil::unique_cotaskmem_string uri = nullptr; + std::optional url = SUCCEEDED(args->get_Uri(&uri)) ? wide_to_utf8(std::wstring(uri.get())) : std::optional{}; + + wil::unique_cotaskmem_string method = nullptr; + wil::com_ptr requestHeaders = nullptr; + std::optional> headers = std::optional>{}; + if (SUCCEEDED(args->get_RequestHeaders(&requestHeaders))) { + headers = std::make_optional>({}); + wil::com_ptr iterator; + requestHeaders->GetIterator(&iterator); + BOOL hasCurrent = FALSE; + while (SUCCEEDED(iterator->get_HasCurrentHeader(&hasCurrent)) && hasCurrent) + { + wil::unique_cotaskmem_string name; + 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())) }); + } + + BOOL hasNext = FALSE; + iterator->MoveNext(&hasNext); + } + + requestHeaders->GetHeader(L"Flutter-InAppWebView-Request-Method", &method); + requestHeaders->RemoveHeader(L"Flutter-InAppWebView-Request-Method"); } - args->put_Cancel(false); + 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. + + auto urlRequest = std::make_shared(url, std::nullopt, headers, std::nullopt); + auto navigationAction = std::make_unique( + urlRequest, + true + ); + + auto callback = std::make_unique(); + callback->nonNullSuccess = [this, urlRequest](const NavigationActionPolicy actionPolicy) { + callShouldOverrideUrlLoading = false; + if (actionPolicy == allow) { + loadUrl(*urlRequest); + } + return false; + }; + auto defaultBehaviour = [this, urlRequest](const std::optional actionPolicy) { + callShouldOverrideUrlLoading = false; + loadUrl(*urlRequest); + }; + callback->defaultBehaviour = defaultBehaviour; + callback->error = [defaultBehaviour](const std::string& error_code, const std::string& error_message, const flutter::EncodableValue* error_details) { + debugLog(error_code + ", " + error_message); + defaultBehaviour(std::nullopt); + }; + channelDelegate->shouldOverrideUrlLoading(std::move(navigationAction), std::move(callback)); + args->put_Cancel(true); + } + else { + callShouldOverrideUrlLoading = true; + channelDelegate->onLoadStart(url); + args->put_Cancel(false); + } return S_OK; } @@ -71,10 +137,19 @@ namespace flutter_inappwebview_plugin webView->add_NavigationCompleted( Callback( [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"); + + BOOL isSuccess; + args->get_IsSuccess(&isSuccess); + if (channelDelegate) { LPWSTR uri = nullptr; std::optional url = SUCCEEDED(webView->get_Source(&uri)) ? wide_to_utf8(std::wstring(uri)) : std::optional{}; - channelDelegate->onLoadStop(url); + if (isSuccess) { + channelDelegate->onLoadStop(url); + } } return S_OK; } @@ -89,20 +164,53 @@ namespace flutter_inappwebview_plugin void InAppWebView::loadUrl(const URLRequest urlRequest) const { - if (!webView) { + if (!webView || !urlRequest.url.has_value()) { return; } - auto url = urlRequest.url.value(); - std::wstring stemp = ansi_to_wide(url); + std::wstring url = ansi_to_wide(urlRequest.url.value()); - // Schedule an async task to navigate to Bing - webView->Navigate(stemp.c_str()); + wil::com_ptr webViewEnv2; + wil::com_ptr webView2; + if (SUCCEEDED(webViewEnv->QueryInterface(IID_PPV_ARGS(&webViewEnv2))) && SUCCEEDED(webView->QueryInterface(IID_PPV_ARGS(&webView2)))) { + wil::com_ptr webResourceRequest; + std::wstring method = urlRequest.method.has_value() ? ansi_to_wide(urlRequest.method.value()) : L"GET"; + + wil::com_ptr postDataStream = nullptr; + if (urlRequest.body.has_value()) { + auto postData = std::string(urlRequest.body->begin(), urlRequest.body->end()); + postDataStream = SHCreateMemStream( + reinterpret_cast(postData.data()), static_cast(postData.length())); + } + webViewEnv2->CreateWebResourceRequest( + url.c_str(), + method.c_str(), + postDataStream.get(), + L"", + &webResourceRequest + ); + wil::com_ptr requestHeaders; + if (SUCCEEDED(webResourceRequest->get_Headers(&requestHeaders))) { + if (urlRequest.method.has_value() && urlRequest.method.value().compare("GET") != 0) { + requestHeaders->SetHeader(L"Flutter-InAppWebView-Request-Method", method.c_str()); + } + if (urlRequest.headers.has_value()) { + auto& headers = urlRequest.headers.value(); + for (auto const& [key, val] : headers) { + requestHeaders->SetHeader(ansi_to_wide(key).c_str(), ansi_to_wide(val).c_str()); + } + } + } + webView2->NavigateWithWebResourceRequest(webResourceRequest.get()); + } + else { + webView->Navigate(url.c_str()); + } } InAppWebView::~InAppWebView() { - std::cout << "dealloc InAppWebView\n"; + debugLog("dealloc InAppWebView"); if (webView) { webView->Stop(); } diff --git a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.h b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.h index 814f0a74..833fc641 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.h +++ b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.h @@ -20,6 +20,7 @@ namespace flutter_inappwebview_plugin FlutterInappwebviewWindowsBasePlugin* plugin; std::variant id; + wil::com_ptr webViewEnv; wil::com_ptr webViewController; wil::com_ptr webView; std::unique_ptr channelDelegate; @@ -32,6 +33,7 @@ namespace flutter_inappwebview_plugin void loadUrl(const URLRequest urlRequest) const; private: + bool callShouldOverrideUrlLoading = true; void createWebView(const HWND parentWindow, const std::function completionHandler); void InAppWebView::registerEventHandlers(); }; diff --git a/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.cpp b/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.cpp index a863b466..d68dc2c1 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.cpp +++ b/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.cpp @@ -3,6 +3,7 @@ #include "../utils/util.h" #include "../utils/strconv.h" +#include "../types/base_callback_result.h" namespace flutter_inappwebview_plugin { @@ -18,6 +19,16 @@ namespace flutter_inappwebview_plugin } + WebViewChannelDelegate::ShouldOverrideUrlLoadingCallback::ShouldOverrideUrlLoadingCallback() { + decodeResult = [](const flutter::EncodableValue* value) { + if (value->IsNull()) { + return cancel; + } + auto navigationPolicy = std::get(*value); + return static_cast(navigationPolicy); + }; + } + void WebViewChannelDelegate::HandleMethodCall(const flutter::MethodCall& method_call, std::unique_ptr> result) { @@ -27,8 +38,12 @@ namespace flutter_inappwebview_plugin } if (method_call.method_name().compare("getUrl") == 0) { - std::optional url = webView->getUrl(); - result->Success(url.has_value() ? flutter::EncodableValue(url.value()) : flutter::EncodableValue()); + result->Success(optional_to_fl_value(webView->getUrl())); + } else if (method_call.method_name().compare("loadUrl") == 0) { + auto& arguments = std::get(*method_call.arguments()); + auto urlRequest = std::make_unique(get_fl_map_value(arguments, "urlRequest")); + webView->loadUrl(*urlRequest); + result->Success(flutter::EncodableValue(true)); } else { result->NotImplemented(); @@ -42,7 +57,7 @@ namespace flutter_inappwebview_plugin } auto arguments = std::make_unique(flutter::EncodableMap { - {flutter::EncodableValue("url"), url.has_value() ? flutter::EncodableValue(url.value()) : flutter::EncodableValue()}, + {flutter::EncodableValue("url"), optional_to_fl_value(url)}, }); channel->InvokeMethod("onLoadStart", std::move(arguments)); } @@ -54,14 +69,24 @@ namespace flutter_inappwebview_plugin } auto arguments = std::make_unique(flutter::EncodableMap{ - {flutter::EncodableValue("url"), url.has_value() ? flutter::EncodableValue(url.value()) : flutter::EncodableValue()}, + {flutter::EncodableValue("url"), optional_to_fl_value(url)}, }); channel->InvokeMethod("onLoadStop", std::move(arguments)); } + void WebViewChannelDelegate::shouldOverrideUrlLoading(std::shared_ptr navigationAction, std::unique_ptr callback) + { + if (!channel) { + return; + } + + auto arguments = std::make_unique(navigationAction->toEncodableMap()); + channel->InvokeMethod("shouldOverrideUrlLoading", std::move(arguments), std::move(callback)); + } + WebViewChannelDelegate::~WebViewChannelDelegate() { - std::cout << "dealloc WebViewChannelDelegate\n"; + debugLog("dealloc WebViewChannelDelegate"); webView = nullptr; } } \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.h b/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.h index 3736ba5d..a5bfe0a4 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.h +++ b/flutter_inappwebview_windows/windows/in_app_webview/webview_channel_delegate.h @@ -5,16 +5,26 @@ #include #include "../types/channel_delegate.h" +#include "../types/base_callback_result.h" +#include "../types/navigation_action.h" namespace flutter_inappwebview_plugin { class InAppWebView; + enum NavigationActionPolicy {cancel = 0, allow = 1}; + class WebViewChannelDelegate : public ChannelDelegate { public: InAppWebView* webView; + class ShouldOverrideUrlLoadingCallback : public BaseCallbackResult { + public: + ShouldOverrideUrlLoadingCallback(); + ~ShouldOverrideUrlLoadingCallback() = default; + }; + WebViewChannelDelegate(InAppWebView* webView, flutter::BinaryMessenger* messenger); WebViewChannelDelegate(InAppWebView* webView, flutter::BinaryMessenger* messenger, const std::string& name); ~WebViewChannelDelegate(); @@ -25,6 +35,7 @@ namespace flutter_inappwebview_plugin void onLoadStart(const std::optional url) const; void onLoadStop(const std::optional url) const; + void shouldOverrideUrlLoading(std::shared_ptr navigationAction, std::unique_ptr callback); }; } diff --git a/flutter_inappwebview_windows/windows/types/base_callback_result.h b/flutter_inappwebview_windows/windows/types/base_callback_result.h new file mode 100644 index 00000000..66958b5a --- /dev/null +++ b/flutter_inappwebview_windows/windows/types/base_callback_result.h @@ -0,0 +1,53 @@ +#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_BASE_CALLBACK_RESULT_H_ +#define FLUTTER_INAPPWEBVIEW_PLUGIN_BASE_CALLBACK_RESULT_H_ + +#include +#include +#include + +namespace flutter_inappwebview_plugin +{ + template + class BaseCallbackResult : public flutter::MethodResultFunctions + { + public: + flutter::ResultHandlerError error; + flutter::ResultHandlerNotImplemented notImplemented; + std::function nonNullSuccess = [](const T result) { return true; }; + std::function nullSuccess = []() { return true; }; + std::function result)> defaultBehaviour = [](const std::optional result) {}; + std::function(const flutter::EncodableValue* result)> decodeResult = [](const flutter::EncodableValue* result) { return std::nullopt; }; + + BaseCallbackResult() : + MethodResultFunctions( + [this](const flutter::EncodableValue* val) { + std::optional result = decodeResult ? decodeResult(val) : std::nullopt; + auto shouldRunDefaultBehaviour = false; + if (result.has_value()) { + shouldRunDefaultBehaviour = nonNullSuccess ? nonNullSuccess(result.value()) : shouldRunDefaultBehaviour; + } + else { + shouldRunDefaultBehaviour = nullSuccess ? nullSuccess() : shouldRunDefaultBehaviour; + } + if (shouldRunDefaultBehaviour && defaultBehaviour) { + defaultBehaviour(result); + } + }, + [this](const std::string& error_code, const std::string& error_message, const flutter::EncodableValue* error_details) { + if (error) { + error(error_code, error_message, error_details); + } + }, + [this]() { + if (defaultBehaviour) { + defaultBehaviour(std::nullopt); + } + if (notImplemented) { + notImplemented(); + } + }) {}; + virtual ~BaseCallbackResult() {}; + }; +} + +#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_BASE_CALLBACK_RESULT_H_ \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/types/channel_delegate.h b/flutter_inappwebview_windows/windows/types/channel_delegate.h index b494d5c9..79c1b5d9 100644 --- a/flutter_inappwebview_windows/windows/types/channel_delegate.h +++ b/flutter_inappwebview_windows/windows/types/channel_delegate.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_CHANNEL_DELEGATE_H_ +#define FLUTTER_INAPPWEBVIEW_PLUGIN_CHANNEL_DELEGATE_H_ #include @@ -18,10 +19,12 @@ namespace flutter_inappwebview_plugin flutter::BinaryMessenger* messenger; ChannelDelegate(flutter::BinaryMessenger* messenger, const std::string& name); - ~ChannelDelegate(); + virtual ~ChannelDelegate(); virtual void HandleMethodCall( const flutter::MethodCall& method_call, std::unique_ptr> result); }; -} \ No newline at end of file +} + +#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_CHANNEL_DELEGATE_H_ \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/types/navigation_action.cpp b/flutter_inappwebview_windows/windows/types/navigation_action.cpp new file mode 100644 index 00000000..9cb94398 --- /dev/null +++ b/flutter_inappwebview_windows/windows/types/navigation_action.cpp @@ -0,0 +1,20 @@ +#include "navigation_action.h" + +#include "../utils/util.h" + +namespace flutter_inappwebview_plugin +{ + NavigationAction::NavigationAction(std::shared_ptr request, bool isForMainFrame) + : request(std::move(request)), isForMainFrame(isForMainFrame) + { + + } + + flutter::EncodableMap NavigationAction::toEncodableMap() + { + return flutter::EncodableMap{ + {flutter::EncodableValue("request"), request->toEncodableMap()}, + {flutter::EncodableValue("isForMainFrame"), flutter::EncodableValue(isForMainFrame)} + }; + } +} \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/types/navigation_action.h b/flutter_inappwebview_windows/windows/types/navigation_action.h new file mode 100644 index 00000000..1b48753b --- /dev/null +++ b/flutter_inappwebview_windows/windows/types/navigation_action.h @@ -0,0 +1,22 @@ +#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_NAVIGATION_ACTION_H_ +#define FLUTTER_INAPPWEBVIEW_PLUGIN_NAVIGATION_ACTION_H_ + +#include +#include +#include "url_request.h" + +namespace flutter_inappwebview_plugin +{ + class NavigationAction + { + public: + const std::shared_ptr request; + const bool isForMainFrame; + + NavigationAction(std::shared_ptr request, bool isForMainFrame); + ~NavigationAction() = default; + flutter::EncodableMap toEncodableMap(); + }; +} + +#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_NAVIGATION_ACTION_H_ \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/types/url_request.cpp b/flutter_inappwebview_windows/windows/types/url_request.cpp index 2c74e213..ddd7317c 100644 --- a/flutter_inappwebview_windows/windows/types/url_request.cpp +++ b/flutter_inappwebview_windows/windows/types/url_request.cpp @@ -4,10 +4,28 @@ namespace flutter_inappwebview_plugin { - URLRequest::URLRequest(const flutter::EncodableMap map) - : url(get_optional_flutter_value(map, "url")), - method(get_optional_flutter_value(map, "method")) + URLRequest::URLRequest(std::optional url, std::optional method, std::optional> headers, std::optional> body) + : url(url), method(method), headers(headers), body(body) { } + + URLRequest::URLRequest(const flutter::EncodableMap map) + : url(get_optional_fl_map_value(map, "url")), + method(get_optional_fl_map_value(map, "method")), + headers(get_optional_fl_map_value(map, "headers")), + body(get_optional_fl_map_value>(map, "body")) + { + + } + + 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)} + }; + } } \ No newline at end of file diff --git a/flutter_inappwebview_windows/windows/types/url_request.h b/flutter_inappwebview_windows/windows/types/url_request.h index 5e5f9569..d05dac7a 100644 --- a/flutter_inappwebview_windows/windows/types/url_request.h +++ b/flutter_inappwebview_windows/windows/types/url_request.h @@ -12,8 +12,13 @@ namespace flutter_inappwebview_plugin public: const std::optional url; const std::optional method; + const std::optional> headers; + const std::optional> body; + URLRequest(std::optional url, std::optional method, std::optional> headers, std::optional> body); URLRequest(const flutter::EncodableMap map); + ~URLRequest() = default; + flutter::EncodableMap toEncodableMap(); }; } diff --git a/flutter_inappwebview_windows/windows/utils/util.h b/flutter_inappwebview_windows/windows/utils/util.h index 9ff79419..843401f3 100644 --- a/flutter_inappwebview_windows/windows/utils/util.h +++ b/flutter_inappwebview_windows/windows/utils/util.h @@ -1,11 +1,21 @@ #ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_H_ #define FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_H_ +#include #include #include +#include +#include "strconv.h" namespace flutter_inappwebview_plugin { + static inline void debugLog(const std::string& msg) { +#ifndef NDEBUG + std::cout << msg << std::endl; + OutputDebugString(ansi_to_wide(msg + "\n").c_str()); +#endif + } + template static inline std::optional make_pointer_optional(const T* value) { @@ -13,17 +23,50 @@ namespace flutter_inappwebview_plugin } template - static inline T get_flutter_value(const flutter::EncodableMap map, const char* string) + static inline T get_fl_map_value(const flutter::EncodableMap map, const char* string) { return std::get(map.at(flutter::EncodableValue(string))); } template - static inline std::optional get_optional_flutter_value(const flutter::EncodableMap map, const char* string) + static inline std::optional get_optional_fl_map_value(const flutter::EncodableMap map, const char* string) { return make_pointer_optional(std::get_if(&map.at(flutter::EncodableValue(string)))); } + static inline std::optional> get_optional_fl_map_value(const flutter::EncodableMap map, const char* string) + { + auto mapValue = std::map{}; + auto flMap = std::get_if(&map.at(flutter::EncodableValue(string))); + if (flMap) { + for (auto itr = flMap->begin(); itr != flMap->end(); itr++) + { + mapValue.insert({ std::get(itr->first), std::get(itr->second) }); + } + } + return make_pointer_optional>(&mapValue); + } + + template + static inline flutter::EncodableValue optional_to_fl_value(const std::optional optional) + { + return optional.has_value() ? flutter::EncodableValue(optional.value()) : flutter::EncodableValue(); + } + + static inline flutter::EncodableValue optional_to_fl_value(const std::optional> 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 var) { return std::visit([](auto&& arg) {