Files
bansonic_beta_main/fdGamer/third_party/webview_windows/windows/webview.cc
T
2026-07-15 01:59:32 +08:00

803 lines
25 KiB
C++

#include "webview.h"
#include <wrl.h>
#include <format>
#include <iostream>
#include "util/composition.desktop.interop.h"
#include "util/string_converter.h"
#include "webview_host.h"
using namespace Microsoft::WRL;
namespace {
inline void ConvertColor(COREWEBVIEW2_COLOR& webview_color, int32_t color) {
webview_color.B = color & 0xFF;
webview_color.G = (color >> 8) & 0xFF;
webview_color.R = (color >> 16) & 0xFF;
webview_color.A = (color >> 24) & 0xFF;
}
inline WebviewPermissionKind CW2PermissionKindToPermissionKind(
COREWEBVIEW2_PERMISSION_KIND kind) {
using k = COREWEBVIEW2_PERMISSION_KIND;
switch (kind) {
case k::COREWEBVIEW2_PERMISSION_KIND_MICROPHONE:
return WebviewPermissionKind::Microphone;
case k::COREWEBVIEW2_PERMISSION_KIND_CAMERA:
return WebviewPermissionKind::Camera;
case k::COREWEBVIEW2_PERMISSION_KIND_GEOLOCATION:
return WebviewPermissionKind::GeoLocation;
case k::COREWEBVIEW2_PERMISSION_KIND_NOTIFICATIONS:
return WebviewPermissionKind::Notifications;
case k::COREWEBVIEW2_PERMISSION_KIND_OTHER_SENSORS:
return WebviewPermissionKind::OtherSensors;
case k::COREWEBVIEW2_PERMISSION_KIND_CLIPBOARD_READ:
return WebviewPermissionKind::ClipboardRead;
default:
return WebviewPermissionKind::Unknown;
}
}
inline COREWEBVIEW2_PERMISSION_STATE WebViewPermissionStateToCW2PermissionState(
WebviewPermissionState state) {
using s = COREWEBVIEW2_PERMISSION_STATE;
switch (state) {
case WebviewPermissionState::Allow:
return s::COREWEBVIEW2_PERMISSION_STATE_ALLOW;
case WebviewPermissionState::Deny:
return s::COREWEBVIEW2_PERMISSION_STATE_DENY;
default:
return s::COREWEBVIEW2_PERMISSION_STATE_DEFAULT;
}
}
} // namespace
Webview::Webview(
wil::com_ptr<ICoreWebView2CompositionController> composition_controller,
WebviewHost* host, HWND hwnd, bool owns_window, bool offscreen_only)
: composition_controller_(std::move(composition_controller)),
host_(host),
hwnd_(hwnd),
owns_window_(owns_window) {
webview_controller_ =
composition_controller_.try_query<ICoreWebView2Controller3>();
if (!webview_controller_ ||
FAILED(webview_controller_->get_CoreWebView2(webview_.put()))) {
return;
}
webview_controller_->put_BoundsMode(COREWEBVIEW2_BOUNDS_MODE_USE_RAW_PIXELS);
webview_controller_->put_ShouldDetectMonitorScaleChanges(FALSE);
webview_controller_->put_RasterizationScale(1.0);
wil::com_ptr<ICoreWebView2Settings> settings;
if (SUCCEEDED(webview_->get_Settings(settings.put()))) {
settings2_ = settings.try_query<ICoreWebView2Settings2>();
auto settings3 = settings.try_query<ICoreWebView2Settings3>();
settings->put_IsStatusBarEnabled(FALSE);
settings->put_AreDevToolsEnabled(FALSE);
settings->put_AreDefaultContextMenusEnabled(FALSE);
if (settings3) {
settings3->put_AreBrowserAcceleratorKeysEnabled(FALSE);
}
}
EnableSecurityUpdates();
RegisterEventHandlers();
is_valid_ = CreateSurface(host->compositor(), hwnd, offscreen_only);
}
Webview::~Webview() {
if (owns_window_) {
DestroyWindow(hwnd_);
}
}
bool Webview::CreateSurface(
winrt::com_ptr<ABI::Windows::UI::Composition::ICompositor> compositor,
HWND hwnd, bool offscreen_only) {
winrt::com_ptr<ABI::Windows::UI::Composition::IContainerVisual> root;
if (FAILED(compositor->CreateContainerVisual(root.put()))) {
return false;
}
surface_ = root.try_as<ABI::Windows::UI::Composition::IVisual>();
assert(surface_);
// initial size. doesn't matter as we resize the surface anyway.
surface_->put_Size({1280, 720});
surface_->put_IsVisible(true);
// Create on-screen window for debugging purposes
if (!offscreen_only) {
window_target_ = util::TryCreateDesktopWindowTarget(compositor, hwnd);
auto composition_target =
window_target_
.try_as<ABI::Windows::UI::Composition::ICompositionTarget>();
if (composition_target) {
composition_target->put_Root(surface_.get());
}
}
winrt::com_ptr<ABI::Windows::UI::Composition::IVisual> webview_visual;
compositor->CreateContainerVisual(
reinterpret_cast<ABI::Windows::UI::Composition::IContainerVisual**>(
webview_visual.put()));
auto webview_visual2 =
webview_visual.try_as<ABI::Windows::UI::Composition::IVisual2>();
if (webview_visual2) {
webview_visual2->put_RelativeSizeAdjustment({1.0f, 1.0f});
}
winrt::com_ptr<ABI::Windows::UI::Composition::IVisualCollection> children;
root->get_Children(children.put());
children->InsertAtTop(webview_visual.get());
composition_controller_->put_RootVisualTarget(webview_visual2.get());
webview_controller_->put_IsVisible(true);
return true;
}
void Webview::EnableSecurityUpdates() {
if (SUCCEEDED(webview_->CallDevToolsProtocolMethod(L"Security.enable", L"{}",
nullptr)) &&
SUCCEEDED(webview_->GetDevToolsProtocolEventReceiver(
L"Security.securityStateChanged",
&devtools_protocol_event_receiver_))) {
devtools_protocol_event_receiver_->add_DevToolsProtocolEventReceived(
Callback<ICoreWebView2DevToolsProtocolEventReceivedEventHandler>(
[this](ICoreWebView2* sender,
ICoreWebView2DevToolsProtocolEventReceivedEventArgs* args)
-> HRESULT {
if (devtools_protocol_event_callback_) {
wil::unique_cotaskmem_string json_args;
if (args->get_ParameterObjectAsJson(&json_args) == S_OK) {
std::string json = util::Utf8FromUtf16(json_args.get());
devtools_protocol_event_callback_(json.c_str());
}
}
return S_OK;
})
.Get(),
&event_registrations_.devtools_protocol_event_token_);
}
}
void Webview::RegisterEventHandlers() {
if (!webview_) {
return;
}
webview_->add_ContentLoading(
Callback<ICoreWebView2ContentLoadingEventHandler>(
[this](ICoreWebView2* sender, IUnknown* args) -> HRESULT {
if (loading_state_changed_callback_) {
loading_state_changed_callback_(WebviewLoadingState::Loading);
}
return S_OK;
})
.Get(),
&event_registrations_.content_loading_token_);
webview_->add_NavigationCompleted(
Callback<ICoreWebView2NavigationCompletedEventHandler>(
[this](ICoreWebView2* sender,
ICoreWebView2NavigationCompletedEventArgs* args) -> HRESULT {
BOOL is_success;
args->get_IsSuccess(&is_success);
if (!is_success && on_load_error_callback_) {
COREWEBVIEW2_WEB_ERROR_STATUS web_error_status;
args->get_WebErrorStatus(&web_error_status);
on_load_error_callback_(web_error_status);
}
if (loading_state_changed_callback_) {
loading_state_changed_callback_(
WebviewLoadingState::NavigationCompleted);
}
return S_OK;
})
.Get(),
&event_registrations_.navigation_completed_token_);
webview_->add_HistoryChanged(
Callback<ICoreWebView2HistoryChangedEventHandler>(
[this](ICoreWebView2* sender, IUnknown* args) -> HRESULT {
if (history_changed_callback_) {
BOOL can_go_back;
BOOL can_go_forward;
sender->get_CanGoBack(&can_go_back);
sender->get_CanGoForward(&can_go_forward);
history_changed_callback_({can_go_back, can_go_forward});
}
return S_OK;
})
.Get(),
&event_registrations_.history_changed_token_);
webview_->add_SourceChanged(
Callback<ICoreWebView2SourceChangedEventHandler>(
[this](ICoreWebView2* sender, IUnknown* args) -> HRESULT {
LPWSTR wurl;
if (url_changed_callback_ && webview_->get_Source(&wurl) == S_OK) {
std::string url = util::Utf8FromUtf16(wurl);
url_changed_callback_(url);
}
return S_OK;
})
.Get(),
&event_registrations_.source_changed_token_);
webview_->add_DocumentTitleChanged(
Callback<ICoreWebView2DocumentTitleChangedEventHandler>(
[this](ICoreWebView2* sender, IUnknown* args) -> HRESULT {
LPWSTR wtitle;
if (document_title_changed_callback_ &&
webview_->get_DocumentTitle(&wtitle) == S_OK) {
std::string title = util::Utf8FromUtf16(wtitle);
document_title_changed_callback_(title);
}
return S_OK;
})
.Get(),
&event_registrations_.document_title_changed_token_);
composition_controller_->add_CursorChanged(
Callback<ICoreWebView2CursorChangedEventHandler>(
[this](ICoreWebView2CompositionController* sender,
IUnknown* args) -> HRESULT {
HCURSOR cursor;
if (cursor_changed_callback_ &&
sender->get_Cursor(&cursor) == S_OK) {
cursor_changed_callback_(cursor);
}
return S_OK;
})
.Get(),
&event_registrations_.cursor_changed_token_);
webview_controller_->add_GotFocus(
Callback<ICoreWebView2FocusChangedEventHandler>(
[this](ICoreWebView2Controller* sender, IUnknown* args) -> HRESULT {
if (focus_changed_callback_) {
focus_changed_callback_(true);
}
return S_OK;
})
.Get(),
&event_registrations_.got_focus_token_);
webview_controller_->add_LostFocus(
Callback<ICoreWebView2FocusChangedEventHandler>(
[this](ICoreWebView2Controller* sender, IUnknown* args) -> HRESULT {
if (focus_changed_callback_) {
focus_changed_callback_(false);
}
return S_OK;
})
.Get(),
&event_registrations_.lost_focus_token_);
webview_->add_WebMessageReceived(
Callback<ICoreWebView2WebMessageReceivedEventHandler>(
[this](ICoreWebView2* sender,
ICoreWebView2WebMessageReceivedEventArgs* args) -> HRESULT {
wil::unique_cotaskmem_string wmessage;
if (web_message_received_callback_ &&
args->get_WebMessageAsJson(&wmessage) == S_OK) {
const std::string message = util::Utf8FromUtf16(wmessage.get());
web_message_received_callback_(message);
}
return S_OK;
})
.Get(),
&event_registrations_.web_message_received_token_);
webview_->add_PermissionRequested(
Callback<ICoreWebView2PermissionRequestedEventHandler>(
[this](ICoreWebView2* sender,
ICoreWebView2PermissionRequestedEventArgs* args) -> HRESULT {
if (!permission_requested_callback_) {
return S_OK;
}
wil::unique_cotaskmem_string wuri;
COREWEBVIEW2_PERMISSION_KIND kind =
COREWEBVIEW2_PERMISSION_KIND_UNKNOWN_PERMISSION;
BOOL is_user_initiated = false;
if (args->get_Uri(&wuri) == S_OK &&
args->get_PermissionKind(&kind) == S_OK &&
args->get_IsUserInitiated(&is_user_initiated) == S_OK) {
wil::com_ptr<ICoreWebView2Deferral> deferral;
args->GetDeferral(deferral.put());
const std::string uri = util::Utf8FromUtf16(wuri.get());
permission_requested_callback_(
uri, CW2PermissionKindToPermissionKind(kind),
is_user_initiated == TRUE,
[deferral = std::move(deferral),
args = std::move(args)](WebviewPermissionState state) {
args->put_State(
WebViewPermissionStateToCW2PermissionState(state));
deferral->Complete();
});
}
return S_OK;
})
.Get(),
&event_registrations_.permission_requested_token_);
webview_->add_NewWindowRequested(
Callback<ICoreWebView2NewWindowRequestedEventHandler>(
[this](ICoreWebView2* sender,
ICoreWebView2NewWindowRequestedEventArgs* args) -> HRESULT {
switch (popup_window_policy_) {
case WebviewPopupWindowPolicy::Deny:
args->put_Handled(TRUE);
break;
case WebviewPopupWindowPolicy::ShowInSameWindow:
args->put_NewWindow(webview_.get());
args->put_Handled(TRUE);
break;
}
return S_OK;
})
.Get(),
&event_registrations_.new_windows_requested_token_);
webview_->add_ContainsFullScreenElementChanged(
Callback<ICoreWebView2ContainsFullScreenElementChangedEventHandler>(
[this](ICoreWebView2* sender, IUnknown* args) -> HRESULT {
BOOL flag = FALSE;
if (contains_fullscreen_element_changed_callback_ &&
SUCCEEDED(sender->get_ContainsFullScreenElement(&flag))) {
contains_fullscreen_element_changed_callback_(flag);
}
return S_OK;
})
.Get(),
&event_registrations_.contains_fullscreen_element_changed_token_);
}
void Webview::SetSurfaceSize(size_t width, size_t height, float scale_factor) {
if (!IsValid()) {
return;
}
if (surface_ && width > 0 && height > 0) {
scale_factor_ = scale_factor;
auto scaled_width = width * scale_factor;
auto scaled_height = height * scale_factor;
RECT bounds;
bounds.left = 0;
bounds.top = 0;
bounds.right = static_cast<LONG>(scaled_width);
bounds.bottom = static_cast<LONG>(scaled_height);
surface_->put_Size({scaled_width, scaled_height});
webview_controller_->put_RasterizationScale(scale_factor);
if (webview_controller_->put_Bounds(bounds) != S_OK) {
std::cerr << "Setting webview bounds failed." << std::endl;
}
if (surface_size_changed_callback_) {
surface_size_changed_callback_(width, height);
}
}
}
bool Webview::OpenDevTools() {
if (!IsValid()) {
return false;
}
webview_->OpenDevToolsWindow();
return true;
}
bool Webview::ClearCookies() {
if (!IsValid()) {
return false;
}
return webview_->CallDevToolsProtocolMethod(L"Network.clearBrowserCookies",
L"{}", nullptr) == S_OK;
}
bool Webview::ClearCache() {
if (!IsValid()) {
return false;
}
return webview_->CallDevToolsProtocolMethod(L"Network.clearBrowserCache",
L"{}", nullptr) == S_OK;
}
bool Webview::SetCacheDisabled(bool disabled) {
if (!IsValid()) {
return false;
}
std::string json = std::format("{{\"disableCache\":{}}}", disabled);
return webview_->CallDevToolsProtocolMethod(L"Network.setCacheDisabled",
util::Utf16FromUtf8(json).c_str(),
nullptr) == S_OK;
}
void Webview::SetPopupWindowPolicy(WebviewPopupWindowPolicy policy) {
popup_window_policy_ = policy;
}
bool Webview::SetUserAgent(const std::string& user_agent) {
if (settings2_) {
return settings2_->put_UserAgent(util::Utf16FromUtf8(user_agent).c_str()) ==
S_OK;
}
return false;
}
bool Webview::SetBackgroundColor(int32_t color) {
if (!IsValid()) {
return false;
}
COREWEBVIEW2_COLOR webview_color;
ConvertColor(webview_color, color);
// Semi-transparent backgrounds are not supported.
// Valid alpha values are 0 or 255.
if (webview_color.A > 0) {
webview_color.A = 0xFF;
}
return webview_controller_->put_DefaultBackgroundColor(webview_color) == S_OK;
}
bool Webview::SetZoomFactor(double factor) {
if (!IsValid()) {
return false;
}
return webview_controller_->put_ZoomFactor(factor) == S_OK;
}
void Webview::SetCursorPos(double x, double y) {
if (!IsValid()) {
return;
}
POINT point;
point.x = static_cast<LONG>(x * scale_factor_);
point.y = static_cast<LONG>(y * scale_factor_);
last_cursor_pos_ = point;
// https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.774.44
composition_controller_->SendMouseInput(
COREWEBVIEW2_MOUSE_EVENT_KIND::COREWEBVIEW2_MOUSE_EVENT_KIND_MOVE,
virtual_keys_.state(), 0, point);
}
void Webview::SetPointerUpdate(int32_t pointer,
WebviewPointerEventKind eventKind, double x,
double y, double size, double pressure) {
if (!IsValid()) {
return;
}
COREWEBVIEW2_POINTER_EVENT_KIND event =
COREWEBVIEW2_POINTER_EVENT_KIND_UPDATE;
UINT32 pointerFlags = POINTER_FLAG_NONE;
switch (eventKind) {
case WebviewPointerEventKind::Activate:
event = COREWEBVIEW2_POINTER_EVENT_KIND_ACTIVATE;
break;
case WebviewPointerEventKind::Down:
event = COREWEBVIEW2_POINTER_EVENT_KIND_DOWN;
pointerFlags =
POINTER_FLAG_DOWN | POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT;
break;
case WebviewPointerEventKind::Enter:
event = COREWEBVIEW2_POINTER_EVENT_KIND_ENTER;
break;
case WebviewPointerEventKind::Leave:
event = COREWEBVIEW2_POINTER_EVENT_KIND_LEAVE;
break;
case WebviewPointerEventKind::Up:
event = COREWEBVIEW2_POINTER_EVENT_KIND_UP;
pointerFlags = POINTER_FLAG_UP;
break;
case WebviewPointerEventKind::Update:
event = COREWEBVIEW2_POINTER_EVENT_KIND_UPDATE;
pointerFlags =
POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT;
break;
}
POINT point;
point.x = static_cast<LONG>(x * scale_factor_);
point.y = static_cast<LONG>(y * scale_factor_);
RECT rect;
rect.left = point.x - 2;
rect.right = point.x + 2;
rect.top = point.y - 2;
rect.bottom = point.y + 2;
host_->CreateWebViewPointerInfo(
[this, pointer, event, pointerFlags, point, rect, pressure](
wil::com_ptr<ICoreWebView2PointerInfo> pointerInfo,
std::unique_ptr<WebviewCreationError> error) {
if (pointerInfo) {
ICoreWebView2PointerInfo* pInfo = pointerInfo.get();
pInfo->put_PointerId(pointer);
pInfo->put_PointerKind(PT_TOUCH);
pInfo->put_PointerFlags(pointerFlags);
pInfo->put_TouchFlags(TOUCH_FLAG_NONE);
pInfo->put_TouchMask(TOUCH_MASK_CONTACTAREA | TOUCH_MASK_PRESSURE);
pInfo->put_TouchPressure(
std::clamp((UINT32)(pressure == 0.0 ? 1024 : 1024 * pressure),
(UINT32)0, (UINT32)1024));
pInfo->put_PixelLocationRaw(point);
pInfo->put_TouchContactRaw(rect);
composition_controller_->SendPointerInput(event, pInfo);
}
});
}
void Webview::SetPointerButtonState(WebviewPointerButton button, bool is_down) {
if (!IsValid()) {
return;
}
COREWEBVIEW2_MOUSE_EVENT_KIND kind;
switch (button) {
case WebviewPointerButton::Primary:
virtual_keys_.set_isLeftButtonDown(is_down);
kind = is_down ? COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_DOWN
: COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_UP;
break;
case WebviewPointerButton::Secondary:
virtual_keys_.set_isRightButtonDown(is_down);
kind = is_down ? COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_DOWN
: COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_UP;
break;
case WebviewPointerButton::Tertiary:
virtual_keys_.set_isMiddleButtonDown(is_down);
kind = is_down ? COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_DOWN
: COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_UP;
break;
default:
kind = static_cast<COREWEBVIEW2_MOUSE_EVENT_KIND>(0);
}
composition_controller_->SendMouseInput(kind, virtual_keys_.state(), 0,
last_cursor_pos_);
}
void Webview::SendScroll(double delta, bool horizontal) {
// delta * 6 gives me a multiple of WHEEL_DELTA (120)
constexpr auto kScrollMultiplier = 6;
auto offset = static_cast<short>(delta * kScrollMultiplier);
POINT point;
point.x = 0;
point.y = 0;
if (horizontal) {
composition_controller_->SendMouseInput(
COREWEBVIEW2_MOUSE_EVENT_KIND_HORIZONTAL_WHEEL, virtual_keys_.state(),
offset, point);
} else {
composition_controller_->SendMouseInput(COREWEBVIEW2_MOUSE_EVENT_KIND_WHEEL,
virtual_keys_.state(), offset,
point);
}
}
void Webview::SetScrollDelta(double delta_x, double delta_y) {
if (!IsValid()) {
return;
}
if (delta_x != 0.0) {
SendScroll(delta_x, true);
}
if (delta_y != 0.0) {
SendScroll(delta_y, false);
}
}
void Webview::LoadUrl(const std::string& url) {
if (IsValid()) {
webview_->Navigate(util::Utf16FromUtf8(url).c_str());
}
}
void Webview::LoadStringContent(const std::string& content) {
if (IsValid()) {
webview_->NavigateToString(util::Utf16FromUtf8(content).c_str());
}
}
bool Webview::Stop() {
if (!IsValid()) {
return false;
}
return SUCCEEDED(webview_->CallDevToolsProtocolMethod(L"Page.stopLoading",
L"{}", nullptr));
}
bool Webview::Reload() {
if (!IsValid()) {
return false;
}
return SUCCEEDED(webview_->Reload());
}
bool Webview::GoBack() {
if (!IsValid()) {
return false;
}
return SUCCEEDED(webview_->GoBack());
}
bool Webview::GoForward() {
if (!IsValid()) {
return false;
}
return SUCCEEDED(webview_->GoForward());
}
void Webview::AddScriptToExecuteOnDocumentCreated(
const std::string& script,
AddScriptToExecuteOnDocumentCreatedCallback callback) {
if (IsValid()) {
if (SUCCEEDED(webview_->AddScriptToExecuteOnDocumentCreated(
util::Utf16FromUtf8(script).c_str(),
Callback<
ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler>(
[callback](HRESULT result, LPCWSTR wsid) -> HRESULT {
std::string sid = util::Utf8FromUtf16(wsid);
callback(SUCCEEDED(result), sid);
return S_OK;
})
.Get()))) {
return;
}
}
callback(false, std::string());
}
void Webview::RemoveScriptToExecuteOnDocumentCreated(
const std::string& script_id) {
if (IsValid()) {
webview_->RemoveScriptToExecuteOnDocumentCreated(
util::Utf16FromUtf8(script_id).c_str());
}
}
void Webview::ExecuteScript(const std::string& script,
ScriptExecutedCallback callback) {
if (IsValid()) {
if (SUCCEEDED(webview_->ExecuteScript(
util::Utf16FromUtf8(script).c_str(),
Callback<ICoreWebView2ExecuteScriptCompletedHandler>(
[callback](HRESULT result, LPCWSTR json_result_object) {
callback(SUCCEEDED(result),
util::Utf8FromUtf16(json_result_object));
return S_OK;
})
.Get()))) {
return;
}
}
callback(false, std::string());
}
bool Webview::PostWebMessage(const std::string& json) {
if (!IsValid()) {
return false;
}
return webview_->PostWebMessageAsJson(util::Utf16FromUtf8(json).c_str()) ==
S_OK;
}
bool Webview::Suspend() {
if (!IsValid()) {
return false;
}
wil::com_ptr<ICoreWebView2_3> webview;
webview = webview_.query<ICoreWebView2_3>();
if (!webview) {
return false;
}
webview_controller_->put_IsVisible(false);
return webview->TrySuspend(
Callback<ICoreWebView2TrySuspendCompletedHandler>(
[](HRESULT error_code, BOOL is_successful) -> HRESULT {
return S_OK;
})
.Get()) == S_OK;
}
bool Webview::Resume() {
if (!IsValid()) {
return false;
}
wil::com_ptr<ICoreWebView2_3> webview;
webview = webview_.query<ICoreWebView2_3>();
if (!webview) {
return false;
}
return webview->Resume() == S_OK &&
webview_controller_->put_IsVisible(true) == S_OK;
}
bool Webview::SetVirtualHostNameMapping(
const std::string& hostName, const std::string& path,
WebviewHostResourceAccessKind accessKind) {
if (!IsValid()) {
return false;
}
wil::com_ptr<ICoreWebView2_3> webview;
webview = webview_.query<ICoreWebView2_3>();
if (!webview) {
return false;
}
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND accessKindIntValue =
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY;
switch (accessKind) {
case WebviewHostResourceAccessKind::Allow:
accessKindIntValue = COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_ALLOW;
break;
case WebviewHostResourceAccessKind::DenyCors:
accessKindIntValue = COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS;
break;
case WebviewHostResourceAccessKind::Deny:
accessKindIntValue = COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY;
break;
}
return webview->SetVirtualHostNameToFolderMapping(
util::Utf16FromUtf8(hostName).c_str(), util::Utf16FromUtf8(path).c_str(),
accessKindIntValue);
}
bool Webview::ClearVirtualHostNameMapping(const std::string& hostName) {
if (!IsValid()) {
return false;
}
wil::com_ptr<ICoreWebView2_3> webview;
webview = webview_.query<ICoreWebView2_3>();
if (!webview) {
return false;
}
return webview->ClearVirtualHostNameToFolderMapping(
util::Utf16FromUtf8(hostName).c_str());
}