-
Notifications
You must be signed in to change notification settings - Fork 64
Description
What happened?
If you render a page from a custom scheme (like myapp://example/index.html) by intercepting WebResourceRequested, the page loads successfully. JavaScript-powered interactivity also works.
However, it's impossible to click on any links, or to programmatically (from C++) navigate to a different page.
The attached example application works in 143.0.3650.139, but fails with the latest version.
The following error is printed in the console when trying to navigate:
[0121/093233.305:ERROR:mojo\public\cpp\bindings\lib\validation_errors.cc:112] Invalid message: VALIDATION_ERROR_DESERIALIZATION_FAILED
[0121/093233.305:ERROR:mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:732] Message 1587913693 rejected by interface embedded_browser.mojom.EmbeddedBrowserClient
Importance
Blocking. My app's basic functions are not working due to this issue.
Runtime Channel
Stable release (WebView2 Runtime)
Runtime Version
144.0.3719.82
SDK Version
1.0.3240.44
Framework
Win32
Operating System
Windows 11
OS Version
26200.7623
Repro steps
Below is a minimal example CMake project that reproduces the issue. With an older WebView2 Runtime, when you click on "Go to another page", you are successfully navigated to "/asd.html". With the latest version, you stay on "/index.html".
CMakeLists.txt
cmake_minimum_required(VERSION 3.31)
project(webview2_test)
set(CMAKE_CXX_STANDARD 23)
add_executable(webview2_test WIN32 main.cpp)
find_package(wil CONFIG REQUIRED)
target_link_libraries(webview2_test PRIVATE WIL::WIL)
find_package(unofficial-webview2 CONFIG REQUIRED)
target_link_libraries(webview2_test PRIVATE unofficial::webview2::webview2)
target_link_libraries(webview2_test PRIVATE shlwapi)vcpkg.json
{
"name": "webview2-test",
"version-string": "1.0.0",
"builtin-baseline": "f9b54c1c539dda8d61c3001bb30eb9f0c5032086",
"dependencies": [
"webview2",
"wil"
]
}main.cpp
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shlwapi.h>
#include <wrl.h>
#include <wil/com.h>
#include <wil/result.h>
#include <WebView2.h>
#include <WebView2EnvironmentOptions.h>
#include <format>
#include <string>
#include <string_view>
#pragma comment(lib, "shlwapi.lib")
using Microsoft::WRL::Callback;
using Microsoft::WRL::ComPtr;
std::string to_utf8( std::wstring_view wstr )
{
if (wstr.empty()) return {};
int size_needed = WideCharToMultiByte( CP_UTF8, 0, wstr.data(), static_cast<int>(wstr.size()), nullptr, 0, nullptr,
nullptr );
FAIL_FAST_IF( size_needed <= 0 );
std::string result( size_needed, 0 );
WideCharToMultiByte( CP_UTF8, 0, wstr.data(), static_cast<int>(wstr.size()), result.data(), size_needed, nullptr,
nullptr );
return result;
}
wil::com_ptr<ICoreWebView2Controller> webviewController;
wil::com_ptr<ICoreWebView2> webviewWindow;
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch (message)
{
case WM_SIZE:
if (webviewController)
{
RECT bounds;
GetClientRect( hWnd, &bounds );
webviewController->put_Bounds( bounds );
}
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0;
}
void InitializeWebView( HWND hWnd )
{
auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
// Register a custom scheme
auto myScheme = Microsoft::WRL::Make<CoreWebView2CustomSchemeRegistration>( L"myapp" );
myScheme->put_HasAuthorityComponent( TRUE );
ICoreWebView2CustomSchemeRegistration* registrations[] = { myScheme.Get() };
FAIL_FAST_IF_FAILED( options->SetCustomSchemeRegistrations(1, registrations) );
FAIL_FAST_IF_FAILED( CreateCoreWebView2EnvironmentWithOptions(
nullptr, nullptr, options.Get(),
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[hWnd](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
FAIL_FAST_IF_FAILED(result);
env->CreateCoreWebView2Controller(hWnd,
Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
[hWnd, env = wil::com_ptr<ICoreWebView2Environment>(env)](HRESULT result, ICoreWebView2Controller*
controller) -> HRESULT {
FAIL_FAST_IF_FAILED(result);
webviewController = controller;
FAIL_FAST_IF_FAILED(webviewController->get_CoreWebView2(&webviewWindow));
RECT bounds;
GetClientRect(hWnd, &bounds);
webviewController->put_Bounds(bounds);
/////////////////////////////////////////////////////////////////////////
/// The important part: Register a WebResourceRequested filter
FAIL_FAST_IF_FAILED(webviewWindow->AddWebResourceRequestedFilter(
L"myapp://*", COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL));
FAIL_FAST_IF_FAILED(webviewWindow->add_WebResourceRequested(
Callback<ICoreWebView2WebResourceRequestedEventHandler>(
[env](ICoreWebView2* sender, ICoreWebView2WebResourceRequestedEventArgs* args) -> HRESULT {
wil::com_ptr<ICoreWebView2WebResourceRequest> request;
FAIL_FAST_IF_FAILED(args->get_Request(&request));
wil::unique_cotaskmem_string uri;
FAIL_FAST_IF_FAILED(request->get_Uri(&uri));
// Construct a simple response that contains the current URL
// as well as a link to a different page
std::string content = std::format(
R"(<html><body><p>You are on {}</p><p><a href="/asd.html">Go to another page</a></p></body></html>)"
,
to_utf8(std::wstring_view(uri.get())));
wil::com_ptr<IStream> stream;
stream.attach(SHCreateMemStream(
reinterpret_cast<const BYTE*>(content.data()),
static_cast<UINT>(content.size())));
wil::com_ptr<ICoreWebView2WebResourceResponse> response;
FAIL_FAST_IF_FAILED(env->CreateWebResourceResponse(
stream.get(), 200, L"OK", L"Content-Type: text/html", &response));
FAIL_FAST_IF_FAILED(args->put_Response(response.get()));
return S_OK;
}).Get(), nullptr));
FAIL_FAST_IF_FAILED(webviewWindow->Navigate(L"myapp://example/index.html"));
return S_OK;
}).Get());
return S_OK;
}).Get()) );
}
int APIENTRY WinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine,
_In_ int nCmdShow )
{
FAIL_FAST_IF_FAILED( CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED) );
WNDCLASSEXW wcex = {};
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor( nullptr, IDC_ARROW );
wcex.lpszClassName = L"WebView2WindowClass";
RegisterClassExW( &wcex );
HWND hWnd = CreateWindowW( L"WebView2WindowClass", L"WebView2 Regression Repro", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 1024, 768, nullptr, nullptr, hInstance, nullptr );
FAIL_FAST_IF_NULL( hWnd );
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
InitializeWebView( hWnd );
MSG msg;
while (GetMessage( &msg, nullptr, 0, 0 ))
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return (int) msg.wParam;
}Repros in Edge Browser
No, issue does not reproduce in the corresponding Edge version
Regression
Regression in newer Runtime
Last working version (if regression)
Runtime 143.0.3650.139