Working with MS WebView2 in C++ I can see a number of "Sec-*"-headers if visiting https://manytools.org/http-html-text/http-request-headers/
Example of a few:
Sec-Fetch-Dest document
Sec-Fetch-User ?1
Sec-Fetch-Mode navigate
Sec-Fetch-Site none
Sec-Ch-Ua-Mobile ?0
Sec-Ch-Ua "Not A;Brand";v="99", "Chromium";v="100", "Microsoft Edge";v="100", "Microsoft Edge WebView2";v="100"
These new headers are mentioned in https://wicg.github.io/ua-client-hints/
Is there any way to access/edit those headers, preferably in C++?
It's possible to disable the Sec-Ch headers with a command line option:
--disable-features=UserAgentClientHint
and to do that from C++:
Microsoft::WRL::ComPtr<CoreWebView2EnvironmentOptions> options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
options->put_AdditionalBrowserArguments(L"--disable-features=UserAgentClientHint");
However, I want to be able to edit those values.
Further googling revealed this page which I guess answers this post: https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name
You are correct that the sec-*
headers are part of the "forbidden header" lists. But they are forbidden for client code like the JS that runs on the user-agent. But user-agents like the browser can set those fields.
You can change some of the sec-*
headers inside a callback added to add_WebResourceRequested
. Some fields like Sec-Fetch-Site
get overwritten afterwards, others like Sec-Fetch-Mode
can be set, but can't be deleted because they will get a default value, if not set after the WebResourceRequestedEvent. But you can change most of the sec-ch
ones like this:
NOTE: this code is only to demonstrate the approach, it's missing a bunch of error handling
EventRegistrationToken webResourceRequestedToken;
webviewWindow->AddWebResourceRequestedFilter(L"*", COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL);
webviewWindow->add_WebResourceRequested(
Callback<ICoreWebView2WebResourceRequestedEventHandler>([](ICoreWebView2* sender,
ICoreWebView2WebResourceRequestedEventArgs* args) {
COREWEBVIEW2_WEB_RESOURCE_CONTEXT resourceContext;
args->get_ResourceContext(&resourceContext);
ICoreWebView2WebResourceRequest* req = nullptr;
ICoreWebView2HttpRequestHeaders* headers = nullptr;
ICoreWebView2HttpHeadersCollectionIterator* iter = nullptr;
args->get_Request(&req);
req->get_Headers(&headers);
headers->GetIterator(&iter);
BOOL hasCurrent = FALSE;
iter->get_HasCurrentHeader(&hasCurrent);
std::vector<std::wstring> headersToDelete;
std::wstring secChPrefix = L"sec-ch";
while (hasCurrent) {
LPWSTR name = nullptr, value = nullptr;
iter->GetCurrentHeader(&name, &value);
if (secChPrefix.compare(0, secChPrefix.size(), name, secChPrefix.size()) == 0) {
headersToDelete.push_back(name);
}
iter->MoveNext(&hasCurrent);
}
for (auto header : headersToDelete) {
headers->RemoveHeader(header.c_str());
}
// Setting "Sec-Fetch-Site" will have no effect, will get overwritten afterwards
headers->SetHeader(L"Sec-Fetch-Site", L"same-origin");
// This will work, but removing this key will just make it take the default value
headers->SetHeader(L"Sec-Fetch-Mode", L"same-origin");
return S_OK;
}).Get(),
&webResourceRequestedToken);