windows: added headless inappwebview initial implementation
This commit is contained in:
parent
ab869e9703
commit
7721deb062
|
@ -274,7 +274,7 @@ class WindowsHeadlessInAppWebView extends PlatformHeadlessInAppWebView
|
||||||
|
|
||||||
dynamic _controllerFromPlatform;
|
dynamic _controllerFromPlatform;
|
||||||
|
|
||||||
WindowsHeadlessInAppWebViewCreationParams get _macosParams =>
|
WindowsHeadlessInAppWebViewCreationParams get _windowsParams =>
|
||||||
params as WindowsHeadlessInAppWebViewCreationParams;
|
params as WindowsHeadlessInAppWebViewCreationParams;
|
||||||
|
|
||||||
_init() {
|
_init() {
|
||||||
|
@ -284,7 +284,7 @@ class WindowsHeadlessInAppWebView extends PlatformHeadlessInAppWebView
|
||||||
_controllerFromPlatform =
|
_controllerFromPlatform =
|
||||||
params.controllerFromPlatform?.call(_webViewController!) ??
|
params.controllerFromPlatform?.call(_webViewController!) ??
|
||||||
_webViewController!;
|
_webViewController!;
|
||||||
_macosParams.findInteractionController?.init(id);
|
_windowsParams.findInteractionController?.init(id);
|
||||||
channel =
|
channel =
|
||||||
MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview_$id');
|
MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview_$id');
|
||||||
handler = _handleMethod;
|
handler = _handleMethod;
|
||||||
|
@ -320,8 +320,8 @@ class WindowsHeadlessInAppWebView extends PlatformHeadlessInAppWebView
|
||||||
initialSettings.toMap();
|
initialSettings.toMap();
|
||||||
|
|
||||||
Map<String, dynamic> pullToRefreshSettings =
|
Map<String, dynamic> pullToRefreshSettings =
|
||||||
_macosParams.pullToRefreshController?.params.settings.toMap() ??
|
_windowsParams.pullToRefreshController?.params.settings.toMap() ??
|
||||||
_macosParams.pullToRefreshController?.params.options.toMap() ??
|
_windowsParams.pullToRefreshController?.params.options.toMap() ??
|
||||||
PullToRefreshSettings(enabled: false).toMap();
|
PullToRefreshSettings(enabled: false).toMap();
|
||||||
|
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
@ -341,8 +341,14 @@ class WindowsHeadlessInAppWebView extends PlatformHeadlessInAppWebView
|
||||||
'pullToRefreshSettings': pullToRefreshSettings,
|
'pullToRefreshSettings': pullToRefreshSettings,
|
||||||
'initialSize': params.initialSize.toMap()
|
'initialSize': params.initialSize.toMap()
|
||||||
});
|
});
|
||||||
await _sharedChannel.invokeMethod('run', args);
|
try {
|
||||||
_running = true;
|
await _sharedChannel.invokeMethod('run', args);
|
||||||
|
_running = true;
|
||||||
|
} catch (e) {
|
||||||
|
_running = false;
|
||||||
|
_started = false;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _inferInitialSettings(InAppWebViewSettings settings) {
|
void _inferInitialSettings(InAppWebViewSettings settings) {
|
||||||
|
@ -420,8 +426,8 @@ class WindowsHeadlessInAppWebView extends PlatformHeadlessInAppWebView
|
||||||
_webViewController?.dispose();
|
_webViewController?.dispose();
|
||||||
_webViewController = null;
|
_webViewController = null;
|
||||||
_controllerFromPlatform = null;
|
_controllerFromPlatform = null;
|
||||||
_macosParams.pullToRefreshController?.dispose();
|
_windowsParams.pullToRefreshController?.dispose();
|
||||||
_macosParams.findInteractionController?.dispose();
|
_windowsParams.findInteractionController?.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_pla
|
||||||
import 'in_app_browser/in_app_browser.dart';
|
import 'in_app_browser/in_app_browser.dart';
|
||||||
import 'in_app_webview/in_app_webview.dart';
|
import 'in_app_webview/in_app_webview.dart';
|
||||||
import 'in_app_webview/in_app_webview_controller.dart';
|
import 'in_app_webview/in_app_webview_controller.dart';
|
||||||
|
import 'in_app_webview/headless_in_app_webview.dart';
|
||||||
|
|
||||||
/// Implementation of [InAppWebViewPlatform] using the WebKit API.
|
/// Implementation of [InAppWebViewPlatform] using the WebKit API.
|
||||||
class WindowsInAppWebViewPlatform extends InAppWebViewPlatform {
|
class WindowsInAppWebViewPlatform extends InAppWebViewPlatform {
|
||||||
|
@ -61,4 +62,15 @@ class WindowsInAppWebViewPlatform extends InAppWebViewPlatform {
|
||||||
WindowsInAppBrowser createPlatformInAppBrowserStatic() {
|
WindowsInAppBrowser createPlatformInAppBrowserStatic() {
|
||||||
return WindowsInAppBrowser.static();
|
return WindowsInAppBrowser.static();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new [WindowsHeadlessInAppWebView].
|
||||||
|
///
|
||||||
|
/// This function should only be called by the app-facing package.
|
||||||
|
/// Look at using [HeadlessInAppWebView] in `flutter_inappwebview` instead.
|
||||||
|
@override
|
||||||
|
WindowsHeadlessInAppWebView createPlatformHeadlessInAppWebView(
|
||||||
|
PlatformHeadlessInAppWebViewCreationParams params,
|
||||||
|
) {
|
||||||
|
return WindowsHeadlessInAppWebView(params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,8 @@ list(APPEND PLUGIN_SOURCES
|
||||||
"types/user_script.h"
|
"types/user_script.h"
|
||||||
"types/plugin_script.cpp"
|
"types/plugin_script.cpp"
|
||||||
"types/plugin_script.h"
|
"types/plugin_script.h"
|
||||||
|
"types/size_2d.cpp"
|
||||||
|
"types/size_2d.h"
|
||||||
"custom_platform_view/custom_platform_view.cc"
|
"custom_platform_view/custom_platform_view.cc"
|
||||||
"custom_platform_view/custom_platform_view.h"
|
"custom_platform_view/custom_platform_view.h"
|
||||||
"custom_platform_view/texture_bridge.cc"
|
"custom_platform_view/texture_bridge.cc"
|
||||||
|
@ -96,6 +98,12 @@ list(APPEND PLUGIN_SOURCES
|
||||||
"in_app_webview/in_app_webview_manager.h"
|
"in_app_webview/in_app_webview_manager.h"
|
||||||
"in_app_webview/webview_channel_delegate.cpp"
|
"in_app_webview/webview_channel_delegate.cpp"
|
||||||
"in_app_webview/webview_channel_delegate.h"
|
"in_app_webview/webview_channel_delegate.h"
|
||||||
|
"headless_in_app_webview/headless_in_app_webview.cpp"
|
||||||
|
"headless_in_app_webview/headless_in_app_webview.h"
|
||||||
|
"headless_in_app_webview/headless_in_app_webview_manager.cpp"
|
||||||
|
"headless_in_app_webview/headless_in_app_webview_manager.h"
|
||||||
|
"headless_in_app_webview/headless_webview_channel_delegate.cpp"
|
||||||
|
"headless_in_app_webview/headless_webview_channel_delegate.h"
|
||||||
"in_app_browser/in_app_browser_settings.cpp"
|
"in_app_browser/in_app_browser_settings.cpp"
|
||||||
"in_app_browser/in_app_browser_settings.h"
|
"in_app_browser/in_app_browser_settings.h"
|
||||||
"in_app_browser/in_app_browser_manager.cpp"
|
"in_app_browser/in_app_browser_manager.cpp"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "flutter_inappwebview_windows_plugin.h"
|
#include "flutter_inappwebview_windows_plugin.h"
|
||||||
|
|
||||||
#include <flutter/method_channel.h>
|
|
||||||
#include <flutter/plugin_registrar_windows.h>
|
#include <flutter/plugin_registrar_windows.h>
|
||||||
|
|
||||||
|
#include "headless_in_app_webview/headless_in_app_webview_manager.h"
|
||||||
#include "in_app_browser/in_app_browser_manager.h"
|
#include "in_app_browser/in_app_browser_manager.h"
|
||||||
#include "in_app_webview/in_app_webview_manager.h"
|
#include "in_app_webview/in_app_webview_manager.h"
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ namespace flutter_inappwebview_plugin
|
||||||
{
|
{
|
||||||
inAppWebViewManager = std::make_unique<InAppWebViewManager>(this);
|
inAppWebViewManager = std::make_unique<InAppWebViewManager>(this);
|
||||||
inAppBrowserManager = std::make_unique<InAppBrowserManager>(this);
|
inAppBrowserManager = std::make_unique<InAppBrowserManager>(this);
|
||||||
|
headlessInAppWebViewManager = std::make_unique<HeadlessInAppWebViewManager>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
FlutterInappwebviewWindowsPlugin::~FlutterInappwebviewWindowsPlugin()
|
FlutterInappwebviewWindowsPlugin::~FlutterInappwebviewWindowsPlugin()
|
||||||
|
|
|
@ -8,12 +8,14 @@ namespace flutter_inappwebview_plugin
|
||||||
{
|
{
|
||||||
class InAppWebViewManager;
|
class InAppWebViewManager;
|
||||||
class InAppBrowserManager;
|
class InAppBrowserManager;
|
||||||
|
class HeadlessInAppWebViewManager;
|
||||||
|
|
||||||
class FlutterInappwebviewWindowsPlugin : public flutter::Plugin {
|
class FlutterInappwebviewWindowsPlugin : public flutter::Plugin {
|
||||||
public:
|
public:
|
||||||
flutter::PluginRegistrarWindows* registrar;
|
flutter::PluginRegistrarWindows* registrar;
|
||||||
std::unique_ptr<InAppWebViewManager> inAppWebViewManager;
|
std::unique_ptr<InAppWebViewManager> inAppWebViewManager;
|
||||||
std::unique_ptr<InAppBrowserManager> inAppBrowserManager;
|
std::unique_ptr<InAppBrowserManager> inAppBrowserManager;
|
||||||
|
std::unique_ptr<HeadlessInAppWebViewManager> headlessInAppWebViewManager;
|
||||||
|
|
||||||
static void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar);
|
static void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include "../utils/log.h"
|
||||||
|
#include "headless_in_app_webview.h"
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
|
HeadlessInAppWebView::HeadlessInAppWebView(const FlutterInappwebviewWindowsPlugin* plugin, const HeadlessInAppWebViewCreationParams& params, const HWND parentWindow, std::unique_ptr<InAppWebView> webView)
|
||||||
|
: plugin(plugin), id(params.id),
|
||||||
|
webView(std::move(webView)),
|
||||||
|
channelDelegate(std::make_unique<HeadlessWebViewChannelDelegate>(this, plugin->registrar->messenger()))
|
||||||
|
{
|
||||||
|
prepare(params);
|
||||||
|
ShowWindow(parentWindow, SW_HIDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadlessInAppWebView::prepare(const HeadlessInAppWebViewCreationParams& params)
|
||||||
|
{
|
||||||
|
if (!webView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
webView->webViewController->put_IsVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadlessInAppWebView::setSize(const std::shared_ptr<Size2D> size) const
|
||||||
|
{
|
||||||
|
if (!webView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RECT rect = {
|
||||||
|
0, 0, (LONG)size->width, (LONG)size->height
|
||||||
|
};
|
||||||
|
webView->webViewController->put_Bounds(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Size2D> HeadlessInAppWebView::getSize() const
|
||||||
|
{
|
||||||
|
if (!webView) {
|
||||||
|
return std::make_shared<Size2D>(-1.0, -1.0);
|
||||||
|
}
|
||||||
|
RECT rect;
|
||||||
|
webView->webViewController->get_Bounds(&rect);
|
||||||
|
auto width = rect.right - rect.left;
|
||||||
|
auto height = rect.bottom - rect.top;
|
||||||
|
return std::make_shared<Size2D>((double)width, (double)height);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeadlessInAppWebView::~HeadlessInAppWebView()
|
||||||
|
{
|
||||||
|
debugLog("dealloc HeadlessInAppWebView");
|
||||||
|
if (webView && webView->webViewController) {
|
||||||
|
HWND parentWindow;
|
||||||
|
if (succeededOrLog(webView->webViewController->get_ParentWindow(&parentWindow))) {
|
||||||
|
DestroyWindow(parentWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
webView = nullptr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_HEADLESS_IN_APP_WEBVIEW_H_
|
||||||
|
#define FLUTTER_INAPPWEBVIEW_PLUGIN_HEADLESS_IN_APP_WEBVIEW_H_
|
||||||
|
|
||||||
|
#include "../flutter_inappwebview_windows_plugin.h"
|
||||||
|
#include "../in_app_webview/in_app_webview.h"
|
||||||
|
#include "../types/size_2d.h"
|
||||||
|
#include "headless_webview_channel_delegate.h"
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
struct HeadlessInAppWebViewCreationParams {
|
||||||
|
const std::string id;
|
||||||
|
const std::shared_ptr<Size2D> initialSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HeadlessInAppWebView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline const wchar_t* CLASS_NAME = L"HeadlessInAppWebView";
|
||||||
|
static inline const std::string METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_headless_inappwebview_";
|
||||||
|
|
||||||
|
const FlutterInappwebviewWindowsPlugin* plugin;
|
||||||
|
std::string id;
|
||||||
|
std::unique_ptr<InAppWebView> webView;
|
||||||
|
std::unique_ptr<HeadlessWebViewChannelDelegate> channelDelegate;
|
||||||
|
|
||||||
|
HeadlessInAppWebView(const FlutterInappwebviewWindowsPlugin* plugin, const HeadlessInAppWebViewCreationParams& params, const HWND parentWindow, std::unique_ptr<InAppWebView> webView);
|
||||||
|
~HeadlessInAppWebView();
|
||||||
|
|
||||||
|
void prepare(const HeadlessInAppWebViewCreationParams& params);
|
||||||
|
void setSize(const std::shared_ptr<Size2D> size) const;
|
||||||
|
std::shared_ptr<Size2D> getSize() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_HEADLESS_IN_APP_WEBVIEW_H_
|
|
@ -0,0 +1,136 @@
|
||||||
|
#include <DispatcherQueue.h>
|
||||||
|
#include <flutter/method_channel.h>
|
||||||
|
#include <flutter/standard_method_codec.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <windows.graphics.capture.h>
|
||||||
|
|
||||||
|
#include "../in_app_webview/in_app_webview_settings.h"
|
||||||
|
#include "../types/size_2d.h"
|
||||||
|
#include "../types/url_request.h"
|
||||||
|
#include "../types/user_script.h"
|
||||||
|
#include "../utils/flutter.h"
|
||||||
|
#include "../utils/log.h"
|
||||||
|
#include "../utils/string.h"
|
||||||
|
#include "../utils/vector.h"
|
||||||
|
#include "headless_in_app_webview_manager.h"
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
HeadlessInAppWebViewManager::HeadlessInAppWebViewManager(const FlutterInappwebviewWindowsPlugin* plugin)
|
||||||
|
: plugin(plugin),
|
||||||
|
ChannelDelegate(plugin->registrar->messenger(), HeadlessInAppWebViewManager::METHOD_CHANNEL_NAME)
|
||||||
|
{
|
||||||
|
windowClass_.lpszClassName = HeadlessInAppWebView::CLASS_NAME;
|
||||||
|
windowClass_.lpfnWndProc = &DefWindowProc;
|
||||||
|
|
||||||
|
RegisterClass(&windowClass_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadlessInAppWebViewManager::HandleMethodCall(const flutter::MethodCall<flutter::EncodableValue>& method_call,
|
||||||
|
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result)
|
||||||
|
{
|
||||||
|
auto* arguments = std::get_if<flutter::EncodableMap>(method_call.arguments());
|
||||||
|
auto& methodName = method_call.method_name();
|
||||||
|
|
||||||
|
if (string_equals(methodName, "run")) {
|
||||||
|
run(arguments, std::move(result));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result->NotImplemented();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadlessInAppWebViewManager::run(const flutter::EncodableMap* arguments, std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result)
|
||||||
|
{
|
||||||
|
auto result_ = std::shared_ptr<flutter::MethodResult<flutter::EncodableValue>>(std::move(result));
|
||||||
|
|
||||||
|
auto id = get_fl_map_value<std::string>(*arguments, "id");
|
||||||
|
auto params = get_fl_map_value<flutter::EncodableMap>(*arguments, "params");
|
||||||
|
|
||||||
|
auto initialSize = std::make_shared<Size2D>(get_fl_map_value<flutter::EncodableMap>(params, "initialSize"));
|
||||||
|
|
||||||
|
auto settingsMap = get_fl_map_value<flutter::EncodableMap>(params, "initialSettings");
|
||||||
|
auto urlRequestMap = get_optional_fl_map_value<flutter::EncodableMap>(params, "initialUrlRequest");
|
||||||
|
auto initialFile = get_optional_fl_map_value<std::string>(params, "initialFile");
|
||||||
|
auto initialDataMap = get_optional_fl_map_value<flutter::EncodableMap>(params, "initialData");
|
||||||
|
auto initialUserScriptList = get_optional_fl_map_value<flutter::EncodableList>(params, "initialUserScripts");
|
||||||
|
|
||||||
|
RECT bounds;
|
||||||
|
GetClientRect(plugin->registrar->GetView()->GetNativeWindow(), &bounds);
|
||||||
|
|
||||||
|
auto initialWidth = initialSize->width >= 0 ? initialSize->width : bounds.right - bounds.left;
|
||||||
|
auto initialHeight = initialSize->height >= 0 ? initialSize->height : bounds.bottom - bounds.top;
|
||||||
|
|
||||||
|
auto hwnd = CreateWindowEx(0, windowClass_.lpszClassName, L"", 0, 0,
|
||||||
|
0, (int)initialWidth, (int)initialHeight,
|
||||||
|
plugin->registrar->GetView()->GetNativeWindow(),
|
||||||
|
nullptr,
|
||||||
|
windowClass_.hInstance, nullptr);
|
||||||
|
|
||||||
|
InAppWebView::createInAppWebViewEnv(hwnd, false,
|
||||||
|
[=](wil::com_ptr<ICoreWebView2Environment> webViewEnv,
|
||||||
|
wil::com_ptr<ICoreWebView2Controller> webViewController,
|
||||||
|
wil::com_ptr<ICoreWebView2CompositionController> webViewCompositionController)
|
||||||
|
{
|
||||||
|
if (webViewEnv && webViewController) {
|
||||||
|
auto initialSettings = std::make_unique<InAppWebViewSettings>(settingsMap);
|
||||||
|
std::optional<std::vector<std::shared_ptr<UserScript>>> initialUserScripts = initialUserScriptList.has_value() ?
|
||||||
|
functional_map(initialUserScriptList.value(), [](const flutter::EncodableValue& map) { return std::make_shared<UserScript>(std::get<flutter::EncodableMap>(map)); }) :
|
||||||
|
std::optional<std::vector<std::shared_ptr<UserScript>>>{};
|
||||||
|
|
||||||
|
InAppWebViewCreationParams params = {
|
||||||
|
id,
|
||||||
|
std::move(initialSettings),
|
||||||
|
initialUserScripts
|
||||||
|
};
|
||||||
|
|
||||||
|
auto inAppWebView = std::make_unique<InAppWebView>(plugin, params, hwnd,
|
||||||
|
std::move(webViewEnv), std::move(webViewController), nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
HeadlessInAppWebViewCreationParams headlessParams = {
|
||||||
|
id,
|
||||||
|
std::move(initialSize)
|
||||||
|
};
|
||||||
|
|
||||||
|
auto headlessInAppWebView = std::make_unique<HeadlessInAppWebView>(plugin,
|
||||||
|
headlessParams,
|
||||||
|
hwnd,
|
||||||
|
std::move(inAppWebView));
|
||||||
|
|
||||||
|
headlessInAppWebView->webView->initChannel(std::nullopt, std::nullopt);
|
||||||
|
|
||||||
|
if (headlessInAppWebView->channelDelegate) {
|
||||||
|
headlessInAppWebView->channelDelegate->onWebViewCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::shared_ptr<URLRequest>> urlRequest = urlRequestMap.has_value() ? std::make_shared<URLRequest>(urlRequestMap.value()) : std::optional<std::shared_ptr<URLRequest>>{};
|
||||||
|
if (urlRequest.has_value()) {
|
||||||
|
headlessInAppWebView->webView->loadUrl(urlRequest.value());
|
||||||
|
}
|
||||||
|
else if (initialFile.has_value()) {
|
||||||
|
headlessInAppWebView->webView->loadFile(initialFile.value());
|
||||||
|
}
|
||||||
|
else if (initialDataMap.has_value()) {
|
||||||
|
headlessInAppWebView->webView->loadData(get_fl_map_value<std::string>(initialDataMap.value(), "data"));
|
||||||
|
}
|
||||||
|
|
||||||
|
webViews.insert({ id, std::move(headlessInAppWebView) });
|
||||||
|
|
||||||
|
result_->Success(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result_->Error("0", "Cannot create the HeadlessInAppWebView instance!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeadlessInAppWebViewManager::~HeadlessInAppWebViewManager()
|
||||||
|
{
|
||||||
|
debugLog("dealloc HeadlessInAppWebViewManager");
|
||||||
|
webViews.clear();
|
||||||
|
UnregisterClass(windowClass_.lpszClassName, nullptr);
|
||||||
|
plugin = nullptr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_HEADLESS_IN_APP_WEBVIEW_MANAGER_H_
|
||||||
|
#define FLUTTER_INAPPWEBVIEW_PLUGIN_HEADLESS_IN_APP_WEBVIEW_MANAGER_H_
|
||||||
|
|
||||||
|
#include <flutter/method_channel.h>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <wil/com.h>
|
||||||
|
#include <winrt/base.h>
|
||||||
|
|
||||||
|
#include "../flutter_inappwebview_windows_plugin.h"
|
||||||
|
#include "../types/channel_delegate.h"
|
||||||
|
#include "headless_in_app_webview.h"
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
class HeadlessInAppWebViewManager : public ChannelDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline const std::string METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_headless_inappwebview";
|
||||||
|
|
||||||
|
const FlutterInappwebviewWindowsPlugin* plugin;
|
||||||
|
std::map<std::string, std::unique_ptr<HeadlessInAppWebView>> webViews;
|
||||||
|
|
||||||
|
HeadlessInAppWebViewManager(const FlutterInappwebviewWindowsPlugin* plugin);
|
||||||
|
~HeadlessInAppWebViewManager();
|
||||||
|
|
||||||
|
void HandleMethodCall(
|
||||||
|
const flutter::MethodCall<flutter::EncodableValue>& method_call,
|
||||||
|
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
|
||||||
|
|
||||||
|
void run(const flutter::EncodableMap* arguments, std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
|
||||||
|
private:
|
||||||
|
WNDCLASS windowClass_ = {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_HEADLESS_IN_APP_WEBVIEW_MANAGER_H_
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include "../utils/flutter.h"
|
||||||
|
#include "../utils/log.h"
|
||||||
|
#include "../utils/strconv.h"
|
||||||
|
#include "../utils/string.h"
|
||||||
|
#include "headless_in_app_webview.h"
|
||||||
|
#include "headless_webview_channel_delegate.h"
|
||||||
|
|
||||||
|
#include "headless_in_app_webview_manager.h"
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
HeadlessWebViewChannelDelegate::HeadlessWebViewChannelDelegate(HeadlessInAppWebView* webView, flutter::BinaryMessenger* messenger)
|
||||||
|
: webView(webView), ChannelDelegate(messenger, HeadlessInAppWebView::METHOD_CHANNEL_NAME_PREFIX + variant_to_string(webView->id))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void HeadlessWebViewChannelDelegate::HandleMethodCall(const flutter::MethodCall<flutter::EncodableValue>& method_call,
|
||||||
|
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result)
|
||||||
|
{
|
||||||
|
if (!webView) {
|
||||||
|
result->Success();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto& arguments = std::get<flutter::EncodableMap>(*method_call.arguments());
|
||||||
|
auto& methodName = method_call.method_name();
|
||||||
|
|
||||||
|
if (string_equals(methodName, "dispose")) {
|
||||||
|
if (webView->plugin && webView->plugin->headlessInAppWebViewManager) {
|
||||||
|
std::map<std::string, std::unique_ptr<HeadlessInAppWebView>>& webViews = webView->plugin->headlessInAppWebViewManager->webViews;
|
||||||
|
auto& id = webView->id;
|
||||||
|
if (map_contains(webViews, id)) {
|
||||||
|
webViews.erase(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result->Success();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result->NotImplemented();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadlessWebViewChannelDelegate::onWebViewCreated() const
|
||||||
|
{
|
||||||
|
if (!channel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel->InvokeMethod("onWebViewCreated", nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeadlessWebViewChannelDelegate::~HeadlessWebViewChannelDelegate()
|
||||||
|
{
|
||||||
|
debugLog("dealloc HeadlessWebViewChannelDelegate");
|
||||||
|
webView = nullptr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_HEADLESS_WEBVIEW_CHANNEL_DELEGATE_H_
|
||||||
|
#define FLUTTER_INAPPWEBVIEW_PLUGIN_HEADLESS_WEBVIEW_CHANNEL_DELEGATE_H_
|
||||||
|
|
||||||
|
#include "../types/channel_delegate.h"
|
||||||
|
#include <flutter/method_channel.h>
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
class HeadlessInAppWebView;
|
||||||
|
|
||||||
|
class HeadlessWebViewChannelDelegate : public ChannelDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HeadlessInAppWebView* webView;
|
||||||
|
|
||||||
|
HeadlessWebViewChannelDelegate(HeadlessInAppWebView* webView, flutter::BinaryMessenger* messenger);
|
||||||
|
~HeadlessWebViewChannelDelegate();
|
||||||
|
|
||||||
|
void HandleMethodCall(
|
||||||
|
const flutter::MethodCall<flutter::EncodableValue>& method_call,
|
||||||
|
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
|
||||||
|
|
||||||
|
void onWebViewCreated() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_HEADLESS_WEBVIEW_CHANNEL_DELEGATE_H_
|
|
@ -274,7 +274,7 @@ namespace flutter_inappwebview_plugin
|
||||||
navigationActions_.insert({ navigationId, navigationAction });
|
navigationActions_.insert({ navigationId, navigationAction });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callShouldOverrideUrlLoading_ && requestMethod == nullptr) {
|
if (settings->useShouldOverrideUrlLoading && callShouldOverrideUrlLoading_ && requestMethod == nullptr) {
|
||||||
// for some reason, we can't cancel and load an URL with other HTTP methods than GET,
|
// for some reason, we can't cancel and load an URL with other HTTP methods than GET,
|
||||||
// so ignore the shouldOverrideUrlLoading event.
|
// so ignore the shouldOverrideUrlLoading event.
|
||||||
|
|
||||||
|
@ -1187,21 +1187,20 @@ namespace flutter_inappwebview_plugin
|
||||||
InAppWebView::~InAppWebView()
|
InAppWebView::~InAppWebView()
|
||||||
{
|
{
|
||||||
debugLog("dealloc InAppWebView");
|
debugLog("dealloc InAppWebView");
|
||||||
HWND parentWindow;
|
HWND parentWindow = nullptr;
|
||||||
webViewController->get_ParentWindow(&parentWindow);
|
if (webViewCompositionController && succeededOrLog(webViewController->get_ParentWindow(&parentWindow))) {
|
||||||
if (webView) {
|
|
||||||
webView->Stop();
|
|
||||||
}
|
|
||||||
if (webViewController) {
|
|
||||||
webViewController->Close();
|
|
||||||
}
|
|
||||||
navigationActions_.clear();
|
|
||||||
inAppBrowser = nullptr;
|
|
||||||
plugin = nullptr;
|
|
||||||
if (webViewCompositionController) {
|
|
||||||
// if it's an InAppWebView,
|
// if it's an InAppWebView,
|
||||||
// then destroy the Window created with it
|
// then destroy the Window created with it
|
||||||
DestroyWindow(parentWindow);
|
DestroyWindow(parentWindow);
|
||||||
}
|
}
|
||||||
|
if (webView) {
|
||||||
|
failedLog(webView->Stop());
|
||||||
|
}
|
||||||
|
if (webViewController) {
|
||||||
|
failedLog(webViewController->Close());
|
||||||
|
}
|
||||||
|
navigationActions_.clear();
|
||||||
|
inAppBrowser = nullptr;
|
||||||
|
plugin = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ namespace flutter_inappwebview_plugin
|
||||||
{
|
{
|
||||||
decodeResult = [](const flutter::EncodableValue* value)
|
decodeResult = [](const flutter::EncodableValue* value)
|
||||||
{
|
{
|
||||||
if (value->IsNull()) {
|
if (!value || value->IsNull()) {
|
||||||
return NavigationActionPolicy::cancel;
|
return NavigationActionPolicy::cancel;
|
||||||
}
|
}
|
||||||
auto navigationPolicy = std::get<int>(*value);
|
auto navigationPolicy = std::get<int>(*value);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include "size_2d.h"
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
Size2D::Size2D(const double& width, const double& height)
|
||||||
|
: width(width), height(height)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Size2D::Size2D(const flutter::EncodableMap& map)
|
||||||
|
: width(get_fl_map_value<double>(map, "width")),
|
||||||
|
height(get_fl_map_value<double>(map, "height"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
flutter::EncodableMap Size2D::toEncodableMap() const
|
||||||
|
{
|
||||||
|
return flutter::EncodableMap{
|
||||||
|
{"width", width},
|
||||||
|
{"height", height}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef FLUTTER_INAPPWEBVIEW_PLUGIN_SIZE_2D_H_
|
||||||
|
#define FLUTTER_INAPPWEBVIEW_PLUGIN_SIZE_2D_H_
|
||||||
|
|
||||||
|
#include <flutter/standard_method_codec.h>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "../utils/flutter.h"
|
||||||
|
|
||||||
|
namespace flutter_inappwebview_plugin
|
||||||
|
{
|
||||||
|
class Size2D
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const double width;
|
||||||
|
const double height;
|
||||||
|
|
||||||
|
Size2D(const double& width, const double& height);
|
||||||
|
Size2D(const flutter::EncodableMap& map);
|
||||||
|
~Size2D() = default;
|
||||||
|
|
||||||
|
flutter::EncodableMap toEncodableMap() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //FLUTTER_INAPPWEBVIEW_PLUGIN_SIZE_2D_H_
|
Loading…
Reference in New Issue