added implementation for callback result, impl for shouldOverrideUrlLoading
This commit is contained in:
parent
81b72b3213
commit
43aa01d944
|
@ -57,8 +57,11 @@ list(APPEND PLUGIN_SOURCES
|
||||||
"utils/util.h"
|
"utils/util.h"
|
||||||
"types/channel_delegate.cpp"
|
"types/channel_delegate.cpp"
|
||||||
"types/channel_delegate.h"
|
"types/channel_delegate.h"
|
||||||
|
"types/base_callback_result.h"
|
||||||
"types/url_request.cpp"
|
"types/url_request.cpp"
|
||||||
"types/url_request.h"
|
"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.cpp"
|
||||||
"in_app_webview/in_app_webview.h"
|
"in_app_webview/in_app_webview.h"
|
||||||
"in_app_webview/webview_channel_delegate.cpp"
|
"in_app_webview/webview_channel_delegate.cpp"
|
||||||
|
|
|
@ -1,17 +1,7 @@
|
||||||
#include "flutter_inappwebview_windows_plugin.h"
|
#include "flutter_inappwebview_windows_plugin.h"
|
||||||
|
|
||||||
// This must be included before many other Windows headers.
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
// For getPlatformVersion; remove unless needed for your plugin implementation.
|
|
||||||
#include <VersionHelpers.h>
|
|
||||||
|
|
||||||
#include <flutter/method_channel.h>
|
#include <flutter/method_channel.h>
|
||||||
#include <flutter/plugin_registrar_windows.h>
|
#include <flutter/plugin_registrar_windows.h>
|
||||||
#include <flutter/standard_method_codec.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace flutter_inappwebview_plugin
|
namespace flutter_inappwebview_plugin
|
||||||
{
|
{
|
||||||
|
@ -30,6 +20,6 @@ namespace flutter_inappwebview_plugin
|
||||||
|
|
||||||
FlutterInappwebviewWindowsPlugin::~FlutterInappwebviewWindowsPlugin()
|
FlutterInappwebviewWindowsPlugin::~FlutterInappwebviewWindowsPlugin()
|
||||||
{
|
{
|
||||||
inAppBrowserManager.release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
#include <wil/wrl.h>
|
#include <wil/wrl.h>
|
||||||
#include <wil/com.h>
|
#include <wil/com.h>
|
||||||
#include "../utils/strconv.h"
|
#include "../utils/strconv.h"
|
||||||
|
#include "../utils/util.h"
|
||||||
|
|
||||||
#include <WebView2.h>
|
#include <WebView2.h>
|
||||||
#include <WebView2EnvironmentOptions.h>
|
#include <WebView2EnvironmentOptions.h>
|
||||||
|
@ -229,7 +230,7 @@ namespace flutter_inappwebview_plugin
|
||||||
|
|
||||||
InAppBrowser::~InAppBrowser()
|
InAppBrowser::~InAppBrowser()
|
||||||
{
|
{
|
||||||
std::cout << "dealloc InAppBrowser\n";
|
debugLog("dealloc InAppBrowser");
|
||||||
webView.reset();
|
webView.reset();
|
||||||
SetWindowLongPtr(m_hWnd, GWLP_USERDATA, 0);
|
SetWindowLongPtr(m_hWnd, GWLP_USERDATA, 0);
|
||||||
plugin = nullptr;
|
plugin = nullptr;
|
||||||
|
|
|
@ -35,6 +35,6 @@ namespace flutter_inappwebview_plugin
|
||||||
|
|
||||||
InAppBrowserChannelDelegate::~InAppBrowserChannelDelegate()
|
InAppBrowserChannelDelegate::~InAppBrowserChannelDelegate()
|
||||||
{
|
{
|
||||||
std::cout << "dealloc InAppBrowserChannelDelegate\n";
|
debugLog("dealloc InAppBrowserChannelDelegate");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -45,11 +45,7 @@ namespace flutter_inappwebview_plugin
|
||||||
|
|
||||||
InAppBrowserManager::~InAppBrowserManager()
|
InAppBrowserManager::~InAppBrowserManager()
|
||||||
{
|
{
|
||||||
std::cout << "dealloc InAppBrowserManager\n";
|
debugLog("dealloc InAppBrowserManager");
|
||||||
for (std::map<std::string, std::unique_ptr<InAppBrowser>>::iterator itr = browsers.begin(); itr != browsers.end(); itr++)
|
|
||||||
{
|
|
||||||
browsers.erase(itr->first);
|
|
||||||
}
|
|
||||||
browsers.clear();
|
browsers.clear();
|
||||||
plugin = nullptr;
|
plugin = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
|
#pragma comment(lib, "Shlwapi.lib")
|
||||||
|
|
||||||
#include "in_app_webview.h"
|
#include "in_app_webview.h"
|
||||||
#include <WebView2EnvironmentOptions.h>
|
#include <WebView2EnvironmentOptions.h>
|
||||||
#include <wil/wrl.h>
|
#include <wil/wrl.h>
|
||||||
|
#include <Shlwapi.h>
|
||||||
#include "../utils/strconv.h"
|
#include "../utils/strconv.h"
|
||||||
|
#include "../utils/util.h"
|
||||||
|
|
||||||
namespace flutter_inappwebview_plugin
|
namespace flutter_inappwebview_plugin
|
||||||
{
|
{
|
||||||
|
@ -24,6 +28,7 @@ namespace flutter_inappwebview_plugin
|
||||||
CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, nullptr,
|
CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, nullptr,
|
||||||
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
|
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
|
||||||
[parentWindow, completionHandler, this](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
|
[parentWindow, completionHandler, this](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
|
||||||
|
webViewEnv = env;
|
||||||
// Create a CoreWebView2Controller and get the associated CoreWebView2 whose parent is the main window hWnd
|
// Create a CoreWebView2Controller and get the associated CoreWebView2 whose parent is the main window hWnd
|
||||||
env->CreateCoreWebView2Controller(parentWindow, Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
|
env->CreateCoreWebView2Controller(parentWindow, Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
|
||||||
[parentWindow, completionHandler, this](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT {
|
[parentWindow, completionHandler, this](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT {
|
||||||
|
@ -56,13 +61,74 @@ namespace flutter_inappwebview_plugin
|
||||||
webView->add_NavigationStarting(
|
webView->add_NavigationStarting(
|
||||||
Callback<ICoreWebView2NavigationStartingEventHandler>(
|
Callback<ICoreWebView2NavigationStartingEventHandler>(
|
||||||
[this](ICoreWebView2* sender, ICoreWebView2NavigationStartingEventArgs* args) {
|
[this](ICoreWebView2* sender, ICoreWebView2NavigationStartingEventArgs* args) {
|
||||||
if (channelDelegate) {
|
if (!channelDelegate) {
|
||||||
LPWSTR uri = nullptr;
|
args->put_Cancel(false);
|
||||||
std::optional<std::string> url = SUCCEEDED(args->get_Uri(&uri)) ? wide_to_utf8(std::wstring(uri)) : std::optional<std::string>{};
|
return S_OK;
|
||||||
channelDelegate->onLoadStart(url);
|
}
|
||||||
|
|
||||||
|
wil::unique_cotaskmem_string uri = nullptr;
|
||||||
|
std::optional<std::string> url = SUCCEEDED(args->get_Uri(&uri)) ? wide_to_utf8(std::wstring(uri.get())) : std::optional<std::string>{};
|
||||||
|
|
||||||
|
wil::unique_cotaskmem_string method = nullptr;
|
||||||
|
wil::com_ptr<ICoreWebView2HttpRequestHeaders> requestHeaders = nullptr;
|
||||||
|
std::optional<std::map<std::string, std::string>> headers = std::optional<std::map<std::string, std::string>>{};
|
||||||
|
if (SUCCEEDED(args->get_RequestHeaders(&requestHeaders))) {
|
||||||
|
headers = std::make_optional<std::map<std::string, std::string>>({});
|
||||||
|
wil::com_ptr<ICoreWebView2HttpHeadersCollectionIterator> 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<URLRequest>(url, std::nullopt, headers, std::nullopt);
|
||||||
|
auto navigationAction = std::make_unique<NavigationAction>(
|
||||||
|
urlRequest,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
auto callback = std::make_unique<WebViewChannelDelegate::ShouldOverrideUrlLoadingCallback>();
|
||||||
|
callback->nonNullSuccess = [this, urlRequest](const NavigationActionPolicy actionPolicy) {
|
||||||
|
callShouldOverrideUrlLoading = false;
|
||||||
|
if (actionPolicy == allow) {
|
||||||
|
loadUrl(*urlRequest);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
auto defaultBehaviour = [this, urlRequest](const std::optional<NavigationActionPolicy> 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;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -71,10 +137,19 @@ namespace flutter_inappwebview_plugin
|
||||||
webView->add_NavigationCompleted(
|
webView->add_NavigationCompleted(
|
||||||
Callback<ICoreWebView2NavigationCompletedEventHandler>(
|
Callback<ICoreWebView2NavigationCompletedEventHandler>(
|
||||||
[this](ICoreWebView2* sender, ICoreWebView2NavigationCompletedEventArgs* args) {
|
[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) {
|
if (channelDelegate) {
|
||||||
LPWSTR uri = nullptr;
|
LPWSTR uri = nullptr;
|
||||||
std::optional<std::string> url = SUCCEEDED(webView->get_Source(&uri)) ? wide_to_utf8(std::wstring(uri)) : std::optional<std::string>{};
|
std::optional<std::string> url = SUCCEEDED(webView->get_Source(&uri)) ? wide_to_utf8(std::wstring(uri)) : std::optional<std::string>{};
|
||||||
channelDelegate->onLoadStop(url);
|
if (isSuccess) {
|
||||||
|
channelDelegate->onLoadStop(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -89,20 +164,53 @@ namespace flutter_inappwebview_plugin
|
||||||
|
|
||||||
void InAppWebView::loadUrl(const URLRequest urlRequest) const
|
void InAppWebView::loadUrl(const URLRequest urlRequest) const
|
||||||
{
|
{
|
||||||
if (!webView) {
|
if (!webView || !urlRequest.url.has_value()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto url = urlRequest.url.value();
|
std::wstring url = ansi_to_wide(urlRequest.url.value());
|
||||||
std::wstring stemp = ansi_to_wide(url);
|
|
||||||
|
|
||||||
// Schedule an async task to navigate to Bing
|
wil::com_ptr<ICoreWebView2Environment2> webViewEnv2;
|
||||||
webView->Navigate(stemp.c_str());
|
wil::com_ptr<ICoreWebView2_2> webView2;
|
||||||
|
if (SUCCEEDED(webViewEnv->QueryInterface(IID_PPV_ARGS(&webViewEnv2))) && SUCCEEDED(webView->QueryInterface(IID_PPV_ARGS(&webView2)))) {
|
||||||
|
wil::com_ptr<ICoreWebView2WebResourceRequest> webResourceRequest;
|
||||||
|
std::wstring method = urlRequest.method.has_value() ? ansi_to_wide(urlRequest.method.value()) : L"GET";
|
||||||
|
|
||||||
|
wil::com_ptr<IStream> postDataStream = nullptr;
|
||||||
|
if (urlRequest.body.has_value()) {
|
||||||
|
auto postData = std::string(urlRequest.body->begin(), urlRequest.body->end());
|
||||||
|
postDataStream = SHCreateMemStream(
|
||||||
|
reinterpret_cast<const BYTE*>(postData.data()), static_cast<UINT>(postData.length()));
|
||||||
|
}
|
||||||
|
webViewEnv2->CreateWebResourceRequest(
|
||||||
|
url.c_str(),
|
||||||
|
method.c_str(),
|
||||||
|
postDataStream.get(),
|
||||||
|
L"",
|
||||||
|
&webResourceRequest
|
||||||
|
);
|
||||||
|
wil::com_ptr<ICoreWebView2HttpRequestHeaders> 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()
|
InAppWebView::~InAppWebView()
|
||||||
{
|
{
|
||||||
std::cout << "dealloc InAppWebView\n";
|
debugLog("dealloc InAppWebView");
|
||||||
if (webView) {
|
if (webView) {
|
||||||
webView->Stop();
|
webView->Stop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace flutter_inappwebview_plugin
|
||||||
|
|
||||||
FlutterInappwebviewWindowsBasePlugin* plugin;
|
FlutterInappwebviewWindowsBasePlugin* plugin;
|
||||||
std::variant<std::string, int> id;
|
std::variant<std::string, int> id;
|
||||||
|
wil::com_ptr<ICoreWebView2Environment> webViewEnv;
|
||||||
wil::com_ptr<ICoreWebView2Controller> webViewController;
|
wil::com_ptr<ICoreWebView2Controller> webViewController;
|
||||||
wil::com_ptr<ICoreWebView2> webView;
|
wil::com_ptr<ICoreWebView2> webView;
|
||||||
std::unique_ptr<WebViewChannelDelegate> channelDelegate;
|
std::unique_ptr<WebViewChannelDelegate> channelDelegate;
|
||||||
|
@ -32,6 +33,7 @@ namespace flutter_inappwebview_plugin
|
||||||
void loadUrl(const URLRequest urlRequest) const;
|
void loadUrl(const URLRequest urlRequest) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool callShouldOverrideUrlLoading = true;
|
||||||
void createWebView(const HWND parentWindow, const std::function<void()> completionHandler);
|
void createWebView(const HWND parentWindow, const std::function<void()> completionHandler);
|
||||||
void InAppWebView::registerEventHandlers();
|
void InAppWebView::registerEventHandlers();
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "../utils/util.h"
|
#include "../utils/util.h"
|
||||||
#include "../utils/strconv.h"
|
#include "../utils/strconv.h"
|
||||||
|
#include "../types/base_callback_result.h"
|
||||||
|
|
||||||
namespace flutter_inappwebview_plugin
|
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<int>(*value);
|
||||||
|
return static_cast<NavigationActionPolicy>(navigationPolicy);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void WebViewChannelDelegate::HandleMethodCall(const flutter::MethodCall<flutter::EncodableValue>& method_call,
|
void WebViewChannelDelegate::HandleMethodCall(const flutter::MethodCall<flutter::EncodableValue>& method_call,
|
||||||
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result)
|
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result)
|
||||||
{
|
{
|
||||||
|
@ -27,8 +38,12 @@ namespace flutter_inappwebview_plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method_call.method_name().compare("getUrl") == 0) {
|
if (method_call.method_name().compare("getUrl") == 0) {
|
||||||
std::optional<std::string> url = webView->getUrl();
|
result->Success(optional_to_fl_value(webView->getUrl()));
|
||||||
result->Success(url.has_value() ? flutter::EncodableValue(url.value()) : flutter::EncodableValue());
|
} else if (method_call.method_name().compare("loadUrl") == 0) {
|
||||||
|
auto& arguments = std::get<flutter::EncodableMap>(*method_call.arguments());
|
||||||
|
auto urlRequest = std::make_unique<URLRequest>(get_fl_map_value<flutter::EncodableMap>(arguments, "urlRequest"));
|
||||||
|
webView->loadUrl(*urlRequest);
|
||||||
|
result->Success(flutter::EncodableValue(true));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result->NotImplemented();
|
result->NotImplemented();
|
||||||
|
@ -42,7 +57,7 @@ namespace flutter_inappwebview_plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
auto arguments = std::make_unique<flutter::EncodableValue>(flutter::EncodableMap {
|
auto arguments = std::make_unique<flutter::EncodableValue>(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));
|
channel->InvokeMethod("onLoadStart", std::move(arguments));
|
||||||
}
|
}
|
||||||
|
@ -54,14 +69,24 @@ namespace flutter_inappwebview_plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
auto arguments = std::make_unique<flutter::EncodableValue>(flutter::EncodableMap{
|
auto arguments = std::make_unique<flutter::EncodableValue>(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));
|
channel->InvokeMethod("onLoadStop", std::move(arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebViewChannelDelegate::shouldOverrideUrlLoading(std::shared_ptr<NavigationAction> navigationAction, std::unique_ptr<ShouldOverrideUrlLoadingCallback> callback)
|
||||||
|
{
|
||||||
|
if (!channel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto arguments = std::make_unique<flutter::EncodableValue>(navigationAction->toEncodableMap());
|
||||||
|
channel->InvokeMethod("shouldOverrideUrlLoading", std::move(arguments), std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
WebViewChannelDelegate::~WebViewChannelDelegate()
|
WebViewChannelDelegate::~WebViewChannelDelegate()
|
||||||
{
|
{
|
||||||
std::cout << "dealloc WebViewChannelDelegate\n";
|
debugLog("dealloc WebViewChannelDelegate");
|
||||||
webView = nullptr;
|
webView = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,16 +5,26 @@
|
||||||
#include <flutter/standard_message_codec.h>
|
#include <flutter/standard_message_codec.h>
|
||||||
|
|
||||||
#include "../types/channel_delegate.h"
|
#include "../types/channel_delegate.h"
|
||||||
|
#include "../types/base_callback_result.h"
|
||||||
|
#include "../types/navigation_action.h"
|
||||||
|
|
||||||
namespace flutter_inappwebview_plugin
|
namespace flutter_inappwebview_plugin
|
||||||
{
|
{
|
||||||
class InAppWebView;
|
class InAppWebView;
|
||||||
|
|
||||||
|
enum NavigationActionPolicy {cancel = 0, allow = 1};
|
||||||
|
|
||||||
class WebViewChannelDelegate : public ChannelDelegate
|
class WebViewChannelDelegate : public ChannelDelegate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InAppWebView* webView;
|
InAppWebView* webView;
|
||||||
|
|
||||||
|
class ShouldOverrideUrlLoadingCallback : public BaseCallbackResult<NavigationActionPolicy> {
|
||||||
|
public:
|
||||||
|
ShouldOverrideUrlLoadingCallback();
|
||||||
|
~ShouldOverrideUrlLoadingCallback() = default;
|
||||||
|
};
|
||||||
|
|
||||||
WebViewChannelDelegate(InAppWebView* webView, flutter::BinaryMessenger* messenger);
|
WebViewChannelDelegate(InAppWebView* webView, flutter::BinaryMessenger* messenger);
|
||||||
WebViewChannelDelegate(InAppWebView* webView, flutter::BinaryMessenger* messenger, const std::string& name);
|
WebViewChannelDelegate(InAppWebView* webView, flutter::BinaryMessenger* messenger, const std::string& name);
|
||||||
~WebViewChannelDelegate();
|
~WebViewChannelDelegate();
|
||||||
|
@ -25,6 +35,7 @@ namespace flutter_inappwebview_plugin
|
||||||
|
|
||||||
void onLoadStart(const std::optional<std::string> url) const;
|
void onLoadStart(const std::optional<std::string> url) const;
|
||||||
void onLoadStop(const std::optional<std::string> url) const;
|
void onLoadStop(const std::optional<std::string> url) const;
|
||||||
|
void shouldOverrideUrlLoading(std::shared_ptr<NavigationAction> navigationAction, std::unique_ptr<ShouldOverrideUrlLoadingCallback> callback);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_BASE_CALLBACK_RESULT_H_
|
||||||
|
#define FLUTTER_INAPPWEBVIEW_PLUGIN_BASE_CALLBACK_RESULT_H_
|
||||||
|
|
||||||
|
#include <flutter/standard_method_codec.h>
|
||||||
|
#include <flutter/method_result_functions.h>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
class BaseCallbackResult : public flutter::MethodResultFunctions<flutter::EncodableValue>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
flutter::ResultHandlerError<flutter::EncodableValue> error;
|
||||||
|
flutter::ResultHandlerNotImplemented<flutter::EncodableValue> notImplemented;
|
||||||
|
std::function<bool(const T result)> nonNullSuccess = [](const T result) { return true; };
|
||||||
|
std::function<bool()> nullSuccess = []() { return true; };
|
||||||
|
std::function<void(const std::optional<T> result)> defaultBehaviour = [](const std::optional<T> result) {};
|
||||||
|
std::function<std::optional<T>(const flutter::EncodableValue* result)> decodeResult = [](const flutter::EncodableValue* result) { return std::nullopt; };
|
||||||
|
|
||||||
|
BaseCallbackResult<T>() :
|
||||||
|
MethodResultFunctions(
|
||||||
|
[this](const flutter::EncodableValue* val) {
|
||||||
|
std::optional<T> 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<T>() {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_BASE_CALLBACK_RESULT_H_
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_CHANNEL_DELEGATE_H_
|
||||||
|
#define FLUTTER_INAPPWEBVIEW_PLUGIN_CHANNEL_DELEGATE_H_
|
||||||
|
|
||||||
#include <flutter/method_channel.h>
|
#include <flutter/method_channel.h>
|
||||||
|
|
||||||
|
@ -18,10 +19,12 @@ namespace flutter_inappwebview_plugin
|
||||||
flutter::BinaryMessenger* messenger;
|
flutter::BinaryMessenger* messenger;
|
||||||
|
|
||||||
ChannelDelegate(flutter::BinaryMessenger* messenger, const std::string& name);
|
ChannelDelegate(flutter::BinaryMessenger* messenger, const std::string& name);
|
||||||
~ChannelDelegate();
|
virtual ~ChannelDelegate();
|
||||||
|
|
||||||
virtual void HandleMethodCall(
|
virtual void HandleMethodCall(
|
||||||
const flutter::MethodCall<flutter::EncodableValue>& method_call,
|
const flutter::MethodCall<flutter::EncodableValue>& method_call,
|
||||||
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
|
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_CHANNEL_DELEGATE_H_
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include "navigation_action.h"
|
||||||
|
|
||||||
|
#include "../utils/util.h"
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
NavigationAction::NavigationAction(std::shared_ptr<URLRequest> 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)}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_NAVIGATION_ACTION_H_
|
||||||
|
#define FLUTTER_INAPPWEBVIEW_PLUGIN_NAVIGATION_ACTION_H_
|
||||||
|
|
||||||
|
#include <flutter/standard_method_codec.h>
|
||||||
|
#include <optional>
|
||||||
|
#include "url_request.h"
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
class NavigationAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const std::shared_ptr<URLRequest> request;
|
||||||
|
const bool isForMainFrame;
|
||||||
|
|
||||||
|
NavigationAction(std::shared_ptr<URLRequest> request, bool isForMainFrame);
|
||||||
|
~NavigationAction() = default;
|
||||||
|
flutter::EncodableMap toEncodableMap();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_NAVIGATION_ACTION_H_
|
|
@ -4,10 +4,28 @@
|
||||||
|
|
||||||
namespace flutter_inappwebview_plugin
|
namespace flutter_inappwebview_plugin
|
||||||
{
|
{
|
||||||
URLRequest::URLRequest(const flutter::EncodableMap map)
|
URLRequest::URLRequest(std::optional<std::string> url, std::optional<std::string> method, std::optional<std::map<std::string, std::string>> headers, std::optional<std::vector<uint8_t>> body)
|
||||||
: url(get_optional_flutter_value<std::string>(map, "url")),
|
: url(url), method(method), headers(headers), body(body)
|
||||||
method(get_optional_flutter_value<std::string>(map, "method"))
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
URLRequest::URLRequest(const flutter::EncodableMap map)
|
||||||
|
: url(get_optional_fl_map_value<std::string>(map, "url")),
|
||||||
|
method(get_optional_fl_map_value<std::string>(map, "method")),
|
||||||
|
headers(get_optional_fl_map_value(map, "headers")),
|
||||||
|
body(get_optional_fl_map_value<std::vector<uint8_t>>(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)}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -12,8 +12,13 @@ namespace flutter_inappwebview_plugin
|
||||||
public:
|
public:
|
||||||
const std::optional<std::string> url;
|
const std::optional<std::string> url;
|
||||||
const std::optional<std::string> method;
|
const std::optional<std::string> method;
|
||||||
|
const std::optional<std::map<std::string, std::string>> headers;
|
||||||
|
const std::optional<std::vector<uint8_t>> body;
|
||||||
|
|
||||||
|
URLRequest(std::optional<std::string> url, std::optional<std::string> method, std::optional<std::map<std::string, std::string>> headers, std::optional<std::vector<uint8_t>> body);
|
||||||
URLRequest(const flutter::EncodableMap map);
|
URLRequest(const flutter::EncodableMap map);
|
||||||
|
~URLRequest() = default;
|
||||||
|
flutter::EncodableMap toEncodableMap();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_H_
|
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_H_
|
||||||
#define FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_H_
|
#define FLUTTER_INAPPWEBVIEW_PLUGIN_UTIL_H_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "strconv.h"
|
||||||
|
|
||||||
namespace flutter_inappwebview_plugin
|
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<typename T>
|
template<typename T>
|
||||||
static inline std::optional<T> make_pointer_optional(const T* value)
|
static inline std::optional<T> make_pointer_optional(const T* value)
|
||||||
{
|
{
|
||||||
|
@ -13,17 +23,50 @@ namespace flutter_inappwebview_plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
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<T>(map.at(flutter::EncodableValue(string)));
|
return std::get<T>(map.at(flutter::EncodableValue(string)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline std::optional<T> get_optional_flutter_value(const flutter::EncodableMap map, const char* string)
|
static inline std::optional<T> get_optional_fl_map_value(const flutter::EncodableMap map, const char* string)
|
||||||
{
|
{
|
||||||
return make_pointer_optional<T>(std::get_if<T>(&map.at(flutter::EncodableValue(string))));
|
return make_pointer_optional<T>(std::get_if<T>(&map.at(flutter::EncodableValue(string))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline std::optional<std::map<std::string, std::string>> get_optional_fl_map_value(const flutter::EncodableMap map, const char* string)
|
||||||
|
{
|
||||||
|
auto mapValue = std::map<std::string, std::string>{};
|
||||||
|
auto flMap = std::get_if<flutter::EncodableMap>(&map.at(flutter::EncodableValue(string)));
|
||||||
|
if (flMap) {
|
||||||
|
for (auto itr = flMap->begin(); itr != flMap->end(); itr++)
|
||||||
|
{
|
||||||
|
mapValue.insert({ std::get<std::string>(itr->first), std::get<std::string>(itr->second) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return make_pointer_optional<std::map<std::string, std::string>>(&mapValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static inline flutter::EncodableValue optional_to_fl_value(const std::optional<T> optional)
|
||||||
|
{
|
||||||
|
return optional.has_value() ? flutter::EncodableValue(optional.value()) : flutter::EncodableValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline flutter::EncodableValue optional_to_fl_value(const std::optional<std::map<std::string, std::string>> optional)
|
||||||
|
{
|
||||||
|
if (!optional.has_value()) {
|
||||||
|
return flutter::EncodableValue();
|
||||||
|
}
|
||||||
|
auto& mapValue = optional.value();
|
||||||
|
auto encodableMap = flutter::EncodableMap{};
|
||||||
|
for (auto const& [key, val] : mapValue)
|
||||||
|
{
|
||||||
|
encodableMap.insert({ flutter::EncodableValue(key), flutter::EncodableValue(val) });
|
||||||
|
}
|
||||||
|
return encodableMap;
|
||||||
|
}
|
||||||
|
|
||||||
static inline std::string variant_to_string(std::variant<std::string, int> var)
|
static inline std::string variant_to_string(std::variant<std::string, int> var)
|
||||||
{
|
{
|
||||||
return std::visit([](auto&& arg) {
|
return std::visit([](auto&& arg) {
|
||||||
|
|
Loading…
Reference in New Issue