Open
Description
What happened?
We used to have a custom error page that is displayed when NavigationCompleted
event reports an unsuccessful state. And recently (I think it's from 135->136 this behavior is broken), we found everytime I opened a new custom window in the NewWindowRequested
event handler and passing a url to it, the error page is shown, indicating a false positive navigation failed event.
Importance
Important. My app's user experience is significantly compromised.
Runtime Channel
Stable release (WebView2 Runtime)
Runtime Version
136
SDK Version
No response
Framework
Win32
Operating System
Windows 10, Windows 11
OS Version
No response
Repro steps
Use the official WebView2GettingStarted repro, change C++ standard to C++20 for std::format
. Replace the code
WebViewWindow.h
#pragma once
#include <tchar.h>
#include <string>
#include <wil/com.h>
#include <WebView2.h>
class WebViewWindow
{
static void registerIfNeeded();
// Forward declarations of functions included in this code module:
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
// The main window class name.
constexpr static TCHAR szWindowClass[] = _T("DesktopApp");
// The string that appears in the application's title bar.
constexpr static TCHAR szTitle[] = _T("WebView sample");
HWND m_hwnd{};
// Pointer to WebViewController
wil::com_ptr<ICoreWebView2Controller> webviewController;
// Pointer to WebView window
wil::com_ptr<ICoreWebView2> webview;
static inline wil::com_ptr<ICoreWebView2Environment> s_globalEnv;
public:
WebViewWindow(std::wstring url, ICoreWebView2NewWindowRequestedEventArgs* newWindowArgs = nullptr, wil::com_ptr<ICoreWebView2Deferral> deferral = {});
};
- WebViewWindow.cpp
#include <Windows.h>
#include "WebViewWindow.h"
#include <format>
#include <wrl.h>
#include <WebView2.h>
#include <format>
void WebViewWindow::registerIfNeeded()
{
static bool s_registered = false;
if (s_registered)
return;
WNDCLASSEX wcex{};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(void*);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("MiLineApi"),
NULL);
}
s_registered = true;
}
LRESULT WebViewWindow::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_CREATE:
{
SetWindowLongPtr(hwnd, 0, reinterpret_cast<LONG_PTR>(reinterpret_cast<CREATESTRUCT*>(lparam)->lpCreateParams));
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
break;
}
case WM_SIZE:
{
auto thisPtr = reinterpret_cast<WebViewWindow*>(GetWindowLongPtr(hwnd, 0));
if (thisPtr->webviewController)
{
RECT bounds;
GetWindowRect(hwnd, &bounds);
bounds.right = bounds.right - bounds.left;
bounds.left = 0;
bounds.bottom = bounds.bottom - bounds.top;
bounds.top = 0;
thisPtr->webviewController->put_Bounds(bounds);
};
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
WebViewWindow::WebViewWindow(std::wstring url, ICoreWebView2NewWindowRequestedEventArgs* args, wil::com_ptr<ICoreWebView2Deferral> deferral)
{
using namespace Microsoft::WRL;
registerIfNeeded();
m_hwnd = CreateWindowExW(0L, szWindowClass, szTitle, (0x00000000L | 0x00C00000L | 0x00080000L | 0x00040000L | 0x00020000L | 0x00010000L), ((int)0x80000000), ((int)0x80000000), 1200, 900, 0, 0, 0, this);
if (!m_hwnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("MiLineApi"),
NULL);
return;
}
ShowWindow(m_hwnd, SW_SHOW);
UpdateWindow(m_hwnd);
auto handler = [this, url = std::move(url), args = wil::com_ptr{ args }, deferral = std::move(deferral)](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
if (!s_globalEnv)
s_globalEnv = env;
// Create a CoreWebView2Controller and get the associated CoreWebView2 whose parent is the main window hWnd
env->CreateCoreWebView2Controller(m_hwnd, Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
[this, url = std::move(url), deferral = std::move(deferral), args = std::move(args)](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT {
if (controller != nullptr) {
webviewController = controller;
webviewController->get_CoreWebView2(&webview);
}
webview->OpenDevToolsWindow();
if (args)
{
args->put_NewWindow(webview.get());
args->put_Handled(true);
deferral->Complete();
}
// Add a few settings for the webview
// The demo step is redundant since the values are the default settings
wil::com_ptr<ICoreWebView2Settings> settings;
webview->get_Settings(&settings);
settings->put_IsScriptEnabled(TRUE);
settings->put_AreDefaultScriptDialogsEnabled(TRUE);
settings->put_IsWebMessageEnabled(TRUE);
auto settings_4 = settings.query<ICoreWebView2Settings4>();
settings_4->put_IsGeneralAutofillEnabled(true);
settings_4->put_IsPasswordAutosaveEnabled(true);
// Resize WebView to fit the bounds of the parent window
RECT bounds;
GetClientRect(m_hwnd, &bounds);
webviewController->put_Bounds(bounds);
webview->Navigate(url.data());
EventRegistrationToken token;
webview->add_NavigationCompleted(Callback<ICoreWebView2NavigationCompletedEventHandler>([](ICoreWebView2* sender, ICoreWebView2NavigationCompletedEventArgs* args)
{
BOOL isSuccess = true;
if (args->get_IsSuccess(&isSuccess) == S_OK && isSuccess == false)
{
wil::com_ptr<ICoreWebView2NavigationCompletedEventArgs2> args_2;
args->QueryInterface(args_2.put());
int code{};
args_2->get_HttpStatusCode(&code);
MessageBox(NULL, std::format(L"Failed, code: {}", code).data(), L"", 0);
}
return S_OK;
}).Get(), &token);
webview->add_NewWindowRequested(Callback<ICoreWebView2NewWindowRequestedEventHandler>(
[](ICoreWebView2* core, ICoreWebView2NewWindowRequestedEventArgs* args)
{
wil::unique_cotaskmem_string uri;
args->get_Uri(&uri);
wil::com_ptr<ICoreWebView2Deferral> deferral;
if (args)
{
args->GetDeferral(deferral.put());
}
new WebViewWindow{ uri.get(), args, deferral };
return S_OK;
}
).Get(), &token);
return S_OK;
}).Get());
return S_OK;
};
CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, nullptr,Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(handler).Get());
}
- main.cpp
#include <windows.h>
#include <stdlib.h>
#include "WebViewWindow.h"
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
{
WebViewWindow window{ L"https://www.google.com" };
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
- Build and run. Open
DevTool
, typewindow.open("https://www.google.com")
to trigger this. The messagebox will popup.
Repros in Edge Browser
No, issue does not reproduce in the corresponding Edge version
Regression
Regression in newer Runtime
Last working version (if regression)
134 or 135 maybe.