From 9501cf6f2d0999fd0ab7c0237a3d3772f42475c2 Mon Sep 17 00:00:00 2001 From: peiche-jessica <55165503+peiche-jessica@users.noreply.github.com> Date: Wed, 26 Feb 2020 10:36:39 -0800 Subject: [PATCH] Move project to use latest WebView2 SDK 0.9.430 (#8) * Update WebView2 sdk to 0.9.430 * Revert "Add arm64 config" This reverts commit 7f16c081533f48b60318c68eda970f15b122dc78. * Update minimum browser version * Rename m_contentReceiver to m_securityStateChangedReceiver --- BrowserWindow.cpp | 106 ++++++++++++++------------ BrowserWindow.h | 25 ++++--- README.md | 151 +++++++++++++++++++++++--------------- Tab.cpp | 46 +++++++----- Tab.h | 11 ++- WebViewBrowserApp.sln | 4 - WebViewBrowserApp.vcxproj | 92 +---------------------- packages.config | 2 +- 8 files changed, 204 insertions(+), 233 deletions(-) diff --git a/BrowserWindow.cpp b/BrowserWindow.cpp index 9f6c709..9a3af7e 100644 --- a/BrowserWindow.cpp +++ b/BrowserWindow.cpp @@ -186,9 +186,9 @@ BOOL BrowserWindow::InitInstance(HINSTANCE hInstance, int nCmdShow) // tabs will be created from this environment and kept isolated from the // browser UI. This enviroment is created first so the UI can request new // tabs when it's ready. - HRESULT hr = CreateWebView2EnvironmentWithDetails(nullptr, userDataDirectory.c_str(), - L"", Callback( - [this](HRESULT result, IWebView2Environment* env) -> HRESULT + HRESULT hr = CreateCoreWebView2EnvironmentWithDetails(nullptr, userDataDirectory.c_str(), + L"", Callback( + [this](HRESULT result, ICoreWebView2Environment* env) -> HRESULT { RETURN_IF_FAILED(result); @@ -220,9 +220,9 @@ HRESULT BrowserWindow::InitUIWebViews() // Create WebView environment for browser UI. A separate data directory is // used to isolate the browser UI from web content requested by the user. - return CreateWebView2EnvironmentWithDetails(nullptr, browserDataDirectory.c_str(), - L"", Callback( - [this](HRESULT result, IWebView2Environment* env) -> HRESULT + return CreateCoreWebView2EnvironmentWithDetails(nullptr, browserDataDirectory.c_str(), + L"", Callback( + [this](HRESULT result, ICoreWebView2Environment* env) -> HRESULT { // Environment is ready, create the WebView m_uiEnv = env; @@ -236,8 +236,8 @@ HRESULT BrowserWindow::InitUIWebViews() HRESULT BrowserWindow::CreateBrowserControlsWebView() { - return m_uiEnv->CreateWebView(m_hWnd, Callback( - [this](HRESULT result, IWebView2WebView* webview) -> HRESULT + return m_uiEnv->CreateCoreWebView2Host(m_hWnd, Callback( + [this](HRESULT result, ICoreWebView2Host* host) -> HRESULT { if (!SUCCEEDED(result)) { @@ -245,17 +245,17 @@ HRESULT BrowserWindow::CreateBrowserControlsWebView() return result; } // WebView created - m_controlsWebView = webview; + m_controlsHost = host; + CheckFailure(m_controlsHost->get_CoreWebView2(&m_controlsWebView), L""); - wil::com_ptr settings; + wil::com_ptr settings; RETURN_IF_FAILED(m_controlsWebView->get_Settings(&settings)); RETURN_IF_FAILED(settings->put_AreDevToolsEnabled(FALSE)); - RETURN_IF_FAILED(settings->put_IsFullscreenAllowed(FALSE)); - RETURN_IF_FAILED(m_controlsWebView->add_ZoomFactorChanged(Callback( - [](IWebView2WebView* webview, IUnknown* args) -> HRESULT + RETURN_IF_FAILED(m_controlsHost->add_ZoomFactorChanged(Callback( + [](ICoreWebView2Host* host, IUnknown* args) -> HRESULT { - webview->put_ZoomFactor(1.0); + host->put_ZoomFactor(1.0); return S_OK; } ).Get(), &m_controlsZoomToken)); @@ -272,8 +272,8 @@ HRESULT BrowserWindow::CreateBrowserControlsWebView() HRESULT BrowserWindow::CreateBrowserOptionsWebView() { - return m_uiEnv->CreateWebView(m_hWnd, Callback( - [this](HRESULT result, IWebView2WebView* webview) -> HRESULT + return m_uiEnv->CreateCoreWebView2Host(m_hWnd, Callback( + [this](HRESULT result, ICoreWebView2Host* host) -> HRESULT { if (!SUCCEEDED(result)) { @@ -281,28 +281,28 @@ HRESULT BrowserWindow::CreateBrowserOptionsWebView() return result; } // WebView created - m_optionsWebView = webview; + m_optionsHost = host; + CheckFailure(m_optionsHost->get_CoreWebView2(&m_optionsWebView), L""); - wil::com_ptr settings; + wil::com_ptr settings; RETURN_IF_FAILED(m_optionsWebView->get_Settings(&settings)); RETURN_IF_FAILED(settings->put_AreDevToolsEnabled(FALSE)); - RETURN_IF_FAILED(settings->put_IsFullscreenAllowed(FALSE)); - RETURN_IF_FAILED(m_optionsWebView->add_ZoomFactorChanged(Callback( - [](IWebView2WebView* webview, IUnknown* args) -> HRESULT + RETURN_IF_FAILED(m_optionsHost->add_ZoomFactorChanged(Callback( + [](ICoreWebView2Host* host, IUnknown* args) -> HRESULT { - webview->put_ZoomFactor(1.0); + host->put_ZoomFactor(1.0); return S_OK; } ).Get(), &m_optionsZoomToken)); // Hide by default - RETURN_IF_FAILED(m_optionsWebView->put_IsVisible(FALSE)); + RETURN_IF_FAILED(m_optionsHost->put_IsVisible(FALSE)); RETURN_IF_FAILED(m_optionsWebView->add_WebMessageReceived(m_uiMessageBroker.Get(), &m_optionsUIMessageBrokerToken)); // Hide menu when focus is lost - RETURN_IF_FAILED(m_optionsWebView->add_LostFocus(Callback( - [this](IWebView2WebView* sender, IUnknown* args) -> HRESULT + RETURN_IF_FAILED(m_optionsHost->add_LostFocus(Callback( + [this](ICoreWebView2Host* sender, IUnknown* args) -> HRESULT { web::json::value jsonObj = web::json::value::parse(L"{}"); jsonObj[L"message"] = web::json::value(MG_OPTIONS_LOST_FOCUS); @@ -326,8 +326,8 @@ HRESULT BrowserWindow::CreateBrowserOptionsWebView() // Lambda is used to capture the instance while satisfying Microsoft::WRL::Callback() void BrowserWindow::SetUIMessageBroker() { - m_uiMessageBroker = Callback( - [this](IWebView2WebView* webview, IWebView2WebMessageReceivedEventArgs* eventArgs) -> HRESULT + m_uiMessageBroker = Callback( + [this](ICoreWebView2* webview, ICoreWebView2WebMessageReceivedEventArgs* eventArgs) -> HRESULT { wil::unique_cotaskmem_string jsonString; CheckFailure(eventArgs->get_WebMessageAsJson(&jsonString), L""); // Get the message from the UI WebView as JSON formatted string @@ -363,7 +363,7 @@ void BrowserWindow::SetUIMessageBroker() } else { - m_tabs.at(id)->m_contentWebView->Close(); + m_tabs.at(id)->m_contentHost->Close(); it->second = std::move(newTab); } } @@ -428,7 +428,7 @@ void BrowserWindow::SetUIMessageBroker() case MG_CLOSE_TAB: { size_t id = args.at(L"tabId").as_number().to_uint32(); - m_tabs.at(id)->m_contentWebView->Close(); + m_tabs.at(id)->m_contentHost->Close(); m_tabs.erase(id); } break; @@ -439,18 +439,18 @@ void BrowserWindow::SetUIMessageBroker() break; case MG_SHOW_OPTIONS: { - CheckFailure(m_optionsWebView->put_IsVisible(TRUE), L""); - m_optionsWebView->MoveFocus(WEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); + CheckFailure(m_optionsHost->put_IsVisible(TRUE), L""); + m_optionsHost->MoveFocus(CORE_WEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); } break; case MG_HIDE_OPTIONS: { - CheckFailure(m_optionsWebView->put_IsVisible(FALSE), L"Something went wrong when trying to close the options dropdown."); + CheckFailure(m_optionsHost->put_IsVisible(FALSE), L"Something went wrong when trying to close the options dropdown."); } break; case MG_OPTION_SELECTED: { - m_tabs.at(m_activeTabId)->m_contentWebView->MoveFocus(WEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); + m_tabs.at(m_activeTabId)->m_contentHost->MoveFocus(CORE_WEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); } break; case MG_GET_FAVORITES: @@ -480,18 +480,18 @@ HRESULT BrowserWindow::SwitchToTab(size_t tabId) size_t previousActiveTab = m_activeTabId; RETURN_IF_FAILED(m_tabs.at(tabId)->ResizeWebView()); - RETURN_IF_FAILED(m_tabs.at(tabId)->m_contentWebView->put_IsVisible(TRUE)); + RETURN_IF_FAILED(m_tabs.at(tabId)->m_contentHost->put_IsVisible(TRUE)); m_activeTabId = tabId; if (previousActiveTab != INVALID_TAB_ID && previousActiveTab != m_activeTabId) { - RETURN_IF_FAILED(m_tabs.at(previousActiveTab)->m_contentWebView->put_IsVisible(FALSE)); + RETURN_IF_FAILED(m_tabs.at(previousActiveTab)->m_contentHost->put_IsVisible(FALSE)); } return S_OK; } -HRESULT BrowserWindow::HandleTabURIUpdate(size_t tabId, IWebView2WebView* webview) +HRESULT BrowserWindow::HandleTabURIUpdate(size_t tabId, ICoreWebView2* webview) { wil::unique_cotaskmem_string source; RETURN_IF_FAILED(webview->get_Source(&source)); @@ -520,6 +520,22 @@ HRESULT BrowserWindow::HandleTabURIUpdate(size_t tabId, IWebView2WebView* webvie jsonObj[L"args"][L"uriToShow"] = web::json::value(L"browser://history"); } + RETURN_IF_FAILED(PostJsonToWebView(jsonObj, m_controlsWebView.Get())); + + return S_OK; +} + +HRESULT BrowserWindow::HandleTabHistoryUpdate(size_t tabId, ICoreWebView2* webview) +{ + wil::unique_cotaskmem_string source; + RETURN_IF_FAILED(webview->get_Source(&source)); + + web::json::value jsonObj = web::json::value::parse(L"{}"); + jsonObj[L"message"] = web::json::value(MG_UPDATE_URI); + jsonObj[L"args"] = web::json::value::parse(L"{}"); + jsonObj[L"args"][L"tabId"] = web::json::value::number(tabId); + jsonObj[L"args"][L"uri"] = web::json::value(source.get()); + BOOL canGoForward = FALSE; RETURN_IF_FAILED(webview->get_CanGoForward(&canGoForward)); jsonObj[L"args"][L"canGoForward"] = web::json::value::boolean(canGoForward); @@ -533,7 +549,7 @@ HRESULT BrowserWindow::HandleTabURIUpdate(size_t tabId, IWebView2WebView* webvie return S_OK; } -HRESULT BrowserWindow::HandleTabNavStarting(size_t tabId, IWebView2WebView* webview) +HRESULT BrowserWindow::HandleTabNavStarting(size_t tabId, ICoreWebView2* webview) { web::json::value jsonObj = web::json::value::parse(L"{}"); jsonObj[L"message"] = web::json::value(MG_NAV_STARTING); @@ -543,7 +559,7 @@ HRESULT BrowserWindow::HandleTabNavStarting(size_t tabId, IWebView2WebView* webv return PostJsonToWebView(jsonObj, m_controlsWebView.Get()); } -HRESULT BrowserWindow::HandleTabNavCompleted(size_t tabId, IWebView2WebView* webview, IWebView2NavigationCompletedEventArgs* args) +HRESULT BrowserWindow::HandleTabNavCompleted(size_t tabId, ICoreWebView2* webview, ICoreWebView2NavigationCompletedEventArgs* args) { std::wstring getTitleScript( // Look for a title tag @@ -602,7 +618,7 @@ HRESULT BrowserWindow::HandleTabNavCompleted(size_t tabId, IWebView2WebView* web L"})();" ); - CheckFailure(webview->ExecuteScript(getTitleScript.c_str(), Callback( + CheckFailure(webview->ExecuteScript(getTitleScript.c_str(), Callback( [this, tabId](HRESULT error, PCWSTR result) -> HRESULT { RETURN_IF_FAILED(error); @@ -617,7 +633,7 @@ HRESULT BrowserWindow::HandleTabNavCompleted(size_t tabId, IWebView2WebView* web return S_OK; }).Get()), L"Can't update title."); - CheckFailure(webview->ExecuteScript(getFaviconURI.c_str(), Callback( + CheckFailure(webview->ExecuteScript(getFaviconURI.c_str(), Callback( [this, tabId](HRESULT error, PCWSTR result) -> HRESULT { RETURN_IF_FAILED(error); @@ -646,7 +662,7 @@ HRESULT BrowserWindow::HandleTabNavCompleted(size_t tabId, IWebView2WebView* web return PostJsonToWebView(jsonObj, m_controlsWebView.Get()); } -HRESULT BrowserWindow::HandleTabSecurityUpdate(size_t tabId, IWebView2WebView* webview, IWebView2DevToolsProtocolEventReceivedEventArgs* args) +HRESULT BrowserWindow::HandleTabSecurityUpdate(size_t tabId, ICoreWebView2* webview, ICoreWebView2DevToolsProtocolEventReceivedEventArgs* args) { wil::unique_cotaskmem_string jsonArgs; RETURN_IF_FAILED(args->get_ParameterObjectAsJson(&jsonArgs)); @@ -669,7 +685,7 @@ void BrowserWindow::HandleTabCreated(size_t tabId, bool shouldBeActive) } } -HRESULT BrowserWindow::HandleTabMessageReceived(size_t tabId, IWebView2WebView* webview, IWebView2WebMessageReceivedEventArgs* eventArgs) +HRESULT BrowserWindow::HandleTabMessageReceived(size_t tabId, ICoreWebView2* webview, ICoreWebView2WebMessageReceivedEventArgs* eventArgs) { wil::unique_cotaskmem_string jsonString; RETURN_IF_FAILED(eventArgs->get_WebMessageAsJson(&jsonString)); @@ -808,7 +824,7 @@ HRESULT BrowserWindow::ResizeUIWebViews() bounds.bottom = bounds.top + GetDPIAwareBound(c_uiBarHeight); bounds.bottom += 1; - RETURN_IF_FAILED(m_controlsWebView->put_Bounds(bounds)); + RETURN_IF_FAILED(m_controlsHost->put_Bounds(bounds)); } if (m_optionsWebView != nullptr) @@ -819,7 +835,7 @@ HRESULT BrowserWindow::ResizeUIWebViews() bounds.bottom = bounds.top + GetDPIAwareBound(c_optionsDropdownHeight); bounds.left = bounds.right - GetDPIAwareBound(c_optionsDropdownWidth); - RETURN_IF_FAILED(m_optionsWebView->put_Bounds(bounds)); + RETURN_IF_FAILED(m_optionsHost->put_Bounds(bounds)); } // Workaround for black controls WebView issue in Windows 7 @@ -922,7 +938,7 @@ std::wstring BrowserWindow::GetFilePathAsURI(std::wstring fullPath) return fileURI; } -HRESULT BrowserWindow::PostJsonToWebView(web::json::value jsonObj, IWebView2WebView* webview) +HRESULT BrowserWindow::PostJsonToWebView(web::json::value jsonObj, ICoreWebView2* webview) { utility::stringstream_t stream; jsonObj.serialize(stream); diff --git a/BrowserWindow.h b/BrowserWindow.h index 7017712..600015f 100644 --- a/BrowserWindow.h +++ b/BrowserWindow.h @@ -21,12 +21,13 @@ public: static BOOL LaunchWindow(_In_ HINSTANCE hInstance, _In_ int nCmdShow); static std::wstring GetAppDataDirectory(); std::wstring GetFullPathFor(LPCWSTR relativePath); - HRESULT HandleTabURIUpdate(size_t tabId, IWebView2WebView* webview); - HRESULT HandleTabNavStarting(size_t tabId, IWebView2WebView* webview); - HRESULT HandleTabNavCompleted(size_t tabId, IWebView2WebView* webview, IWebView2NavigationCompletedEventArgs* args); - HRESULT HandleTabSecurityUpdate(size_t tabId, IWebView2WebView* webview, IWebView2DevToolsProtocolEventReceivedEventArgs* args); + HRESULT HandleTabURIUpdate(size_t tabId, ICoreWebView2* webview); + HRESULT HandleTabHistoryUpdate(size_t tabId, ICoreWebView2* webview); + HRESULT HandleTabNavStarting(size_t tabId, ICoreWebView2* webview); + HRESULT HandleTabNavCompleted(size_t tabId, ICoreWebView2* webview, ICoreWebView2NavigationCompletedEventArgs* args); + HRESULT HandleTabSecurityUpdate(size_t tabId, ICoreWebView2* webview, ICoreWebView2DevToolsProtocolEventReceivedEventArgs* args); void HandleTabCreated(size_t tabId, bool shouldBeActive); - HRESULT HandleTabMessageReceived(size_t tabId, IWebView2WebView* webview, IWebView2WebMessageReceivedEventArgs* eventArgs); + HRESULT HandleTabMessageReceived(size_t tabId, ICoreWebView2* webview, ICoreWebView2WebMessageReceivedEventArgs* eventArgs); int GetDPIAwareBound(int bound); static void CheckFailure(HRESULT hr, LPCWSTR errorMessage); protected: @@ -39,10 +40,12 @@ protected: int m_minWindowWidth = 0; int m_minWindowHeight = 0; - Microsoft::WRL::ComPtr m_uiEnv; - Microsoft::WRL::ComPtr m_contentEnv; - Microsoft::WRL::ComPtr m_controlsWebView; - Microsoft::WRL::ComPtr m_optionsWebView; + Microsoft::WRL::ComPtr m_uiEnv; + Microsoft::WRL::ComPtr m_contentEnv; + Microsoft::WRL::ComPtr m_controlsHost; + Microsoft::WRL::ComPtr m_optionsHost; + Microsoft::WRL::ComPtr m_controlsWebView; + Microsoft::WRL::ComPtr m_optionsWebView; std::map> m_tabs; size_t m_activeTabId = 0; @@ -51,7 +54,7 @@ protected: EventRegistrationToken m_optionsUIMessageBrokerToken = {}; // Token for the UI message handler in options WebView EventRegistrationToken m_optionsZoomToken = {}; EventRegistrationToken m_lostOptionsFocus = {}; // Token for the lost focus handler in options WebView - Microsoft::WRL::ComPtr m_uiMessageBroker; + Microsoft::WRL::ComPtr m_uiMessageBroker; BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); HRESULT InitUIWebViews(); @@ -65,7 +68,7 @@ protected: void SetUIMessageBroker(); HRESULT ResizeUIWebViews(); void UpdateMinWindowSize(); - HRESULT PostJsonToWebView(web::json::value jsonObj, IWebView2WebView* webview); + HRESULT PostJsonToWebView(web::json::value jsonObj, ICoreWebView2* webview); HRESULT SwitchToTab(size_t tabId); std::wstring GetFilePathAsURI(std::wstring fullPath); }; diff --git a/README.md b/README.md index 0b31c3c..119c2dd 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # WebView2Browser -A web browser built with the [Microsoft Edge WebView2](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2) control. +A web browser built with the [Microsoft Edge WebView2](https://docs.microsoft.com/microsoft-edge/hosting/webview2) control. -![WebView2Browser](https://github.com/MicrosoftEdge/WebView2Browser/raw/master/screenshots/WebView2Browser.png) +![WebView2Browser](/screenshots/WebView2Browser.png) WebView2Browser is a sample Windows desktop application demonstrating the WebView2 control capabilities. It is built as a Win32 [Visual Studio 2019](https://visualstudio.microsoft.com/vs/) project and makes use of both C++ and JavaScript in the WebView2 environment to power its features. -WebView2Browser shows some of the simplest uses of WebView2 -such as creating and navigating a WebView, but also some more complex workflows like using the [PostWebMessageAsJson API](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/iwebview2webview#postwebmessageasjson) to communicate WebViews in separate environments. It is intended as a rich code sample to look at how you can use WebView2 APIs to build your own app. +WebView2Browser shows some of the simplest uses of WebView2 -such as creating and navigating a WebView, but also some more complex workflows like using the [PostWebMessageAsJson API](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference/icorewebview2#postwebmessageasjson) to communicate WebViews in separate environments. It is intended as a rich code sample to look at how you can use WebView2 APIs to build your own app. ## Requisites -- [Microsoft Edge (Chromium)](https://www.microsoftedgeinsider.com/en-us/download/) installed on a supported OS. +- [Microsoft Edge (Chromium)](https://www.microsoftedgeinsider.com/download/) installed on a supported OS. - [Visual Studio](https://visualstudio.microsoft.com/vs/) with C++ support installed. -The Edge Canary channel is recommended for the installation and the minimum version is 78.0.240.0. +The Edge Canary channel is recommended for the installation and the minimum version is 82.0.430.0. ## Build the browser Clone the repository and open the solution in Visual Studio. WebView2 is already included as a NuGet package* in the project! @@ -50,7 +50,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, // ... ``` -In `WebViewBrowser.cpp`, you will need to remove the call to `GetDpiForWindow`. +In `BrowserWindow.cpp`, you will need to remove the call to `GetDpiForWindow`. ```cpp int BrowserWindow::GetDPIAwareBound(int bound) { @@ -82,30 +82,38 @@ WebView2Browser provides all the functionalities to make a basic web browser, bu - Clearing cache and cookies ## WebView2 APIs -WebView2Browser makes use of a handful of the APIs available in WebView2. For the APIs not used here, you can find more about them in the [Microsoft Edge WebView2 Reference](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference-webview2). The following is a list of the most interesting APIs WebView2Browser uses and the feature(s) they enable. +WebView2Browser makes use of a handful of the APIs available in WebView2. For the APIs not used here, you can find more about them in the [Microsoft Edge WebView2 Reference](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference-webview2). The following is a list of the most interesting APIs WebView2Browser uses and the feature(s) they enable. API | Feature(s) :--- | :--- -CreateWebView2EnvironmentWithDetails | Used to create the environments for UI and content WebViews. Different user data directories are passed to isolate UI from web content. | -IWebView2DevToolsProtocolEventReceivedEventHandler | Used along with add_DevToolsProtocolEventReceived to listen for CDP security events to update the lock icon in the browser UI. | -IWebView2DocumentStateChangedEventHandler | Used along with add_DocumentStateChanged to udpate the address bar and navigation buttons in the browser UI. | -IWebView2ExecuteScriptCompletedHandler | Used along with ExecuteScript to get the title and favicon from the visited page. | -IWebView2FocusChangedEventHandler | Used along with add_LostFocus to hide the browser options dropdown when it loses focus. -IWebView2NavigationCompletedEventHandler | Used along with add_NavigationCompleted to udpate the reload button in the browser UI. -IWebView2Settings | Used to disable DevTools in the browser UI. -IWebView2WebMessageReceivedEventHandler | This is one of the most important APIs to WebView2Browser. Most functionalities involving communication across WebViews use this. -IWebView2WebView | There are several WebViews in WebView2Browser and most features make use of members in this interface, the table below shows how they're used. +CreateCoreWebView2EnvironmentWithDetails | Used to create the environments for UI and content WebViews. Different user data directories are passed to isolate UI from web content. | +ICoreWebView2 | There are several WebViews in WebView2Browser and most features make use of members in this interface, the table below shows how they're used. +ICoreWebView2DevToolsProtocolEventReceivedEventHandler | Used along with add_DevToolsProtocolEventReceived to listen for CDP security events to update the lock icon in the browser UI. | +ICoreWebView2DevToolsProtocolEventReceiver | Used along with add_DevToolsProtocolEventReceived to listen for CDP security events to update the lock icon in the browser UI. | +ICoreWebView2ExecuteScriptCompletedHandler | Used along with ExecuteScript to get the title and favicon from the visited page. | +ICoreWebView2FocusChangedEventHandler | Used along with add_LostFocus to hide the browser options dropdown when it loses focus. +ICoreWebView2HistoryChangedEventHandler | Used along with add_HistoryChanged to udpate the navigation buttons in the browser UI. | +ICoreWebView2Host | There are several WebViewHosts in WebView2Browser and we fetch the associated WebViews from them. +ICoreWebView2NavigationCompletedEventHandler | Used along with add_NavigationCompleted to udpate the reload button in the browser UI. +ICoreWebView2Settings | Used to disable DevTools in the browser UI. +ICoreWebView2SourceChangedEventHandler | Used along with add_SourceChanged to udpate the address bar in the browser UI. | +ICoreWebView2WebMessageReceivedEventHandler | This is one of the most important APIs to WebView2Browser. Most functionalities involving communication across WebViews use this. -IWebView2WebView API | Feature(s) +ICoreWebView2 API | Feature(s) :--- | :--- add_NavigationStarting | Used to display the cancel navigation button in the controls WebView. -add_DocumentStateChanged | Used to update the address bar and go back/forward buttons. +add_SourceChanged | Used to update the address bar. +add_HistoryChanged | Used to update go back/forward buttons. add_NavigationCompleted | Used to display the reload button once a navigation completes. -add_LostFocus | Used to hide the options dropdown when the user clicks away of it. ExecuteScript | Used to get the title and favicon of a visited page. PostWebMessageAsJson | Used to communicate WebViews. All messages use JSON to pass parameters needed. add_WebMessageReceived | Used to handle web messages posted to the WebView. CallDevToolsProtocolMethod | Used to enable listening for security events, which will notify of security status changes in a document. + +ICoreWebView2Host API | Feature(s) +:--- | :--- +get_CoreWebView2 | Used to get the CoreWebView2 associated with this CoreWebView2Host. +add_LostFocus | Used to hide the options dropdown when the user clicks away of it.
## Implementing the features @@ -125,7 +133,7 @@ The sections below describe how some of the features in WebView2Browser were imp ## The basics ### Set up the environment, create a WebView -WebView2 allows you to host web content in your Windows app. It exposes the globals [CreateWebView2Environment](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/webview2.idl#createwebview2environment) and [CreateWebView2EnvironmentWithDetails](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/webview2.idl#createwebview2environmentwithdetails) from which we can create the two separate environments for the browser's UI and content. +WebView2 allows you to host web content in your Windows app. It exposes the globals [CreateCoreWebView2Environment](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference/webview2.idl#createcorewebview2environment) and [CreateCoreWebView2EnvironmentWithDetails](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference/webview2.idl#createcorewebview2environmentwithdetails) from which we can create the two separate environments for the browser's UI and content. ```cpp // Get directory for user data. This will be kept separated from the @@ -137,9 +145,9 @@ WebView2 allows you to host web content in your Windows app. It exposes the glob // tabs will be created from this environment and kept isolated from the // browser UI. This enviroment is created first so the UI can request new // tabs when it's ready. - HRESULT hr = CreateWebView2EnvironmentWithDetails(nullptr, userDataDirectory.c_str(), WEBVIEW2_RELEASE_CHANNEL_PREFERENCE_STABLE, - L"", Callback( - [this](HRESULT result, IWebView2Environment* env) -> HRESULT + HRESULT hr = CreateCoreWebView2EnvironmentWithDetails(nullptr, userDataDirectory.c_str(), + L"", Callback( + [this](HRESULT result, ICoreWebView2Environment* env) -> HRESULT { RETURN_IF_FAILED(result); @@ -163,9 +171,9 @@ HRESULT BrowserWindow::InitUIWebViews() // Create WebView environment for browser UI. A separate data directory is // used to isolate the browser UI from web content requested by the user. - return CreateWebView2EnvironmentWithDetails(nullptr, browserDataDirectory.c_str(), WEBVIEW2_RELEASE_CHANNEL_PREFERENCE_STABLE, - L"", Callback( - [this](HRESULT result, IWebView2Environment* env) -> HRESULT + return CreateCoreWebView2EnvironmentWithDetails(nullptr, browserDataDirectory.c_str(), + L"", Callback( + [this](HRESULT result, ICoreWebView2Environment* env) -> HRESULT { // Environment is ready, create the WebView m_uiEnv = env; @@ -178,13 +186,13 @@ HRESULT BrowserWindow::InitUIWebViews() } ``` -We use the [IWebView2CreateWebView2EnvironmentCompletedHandler](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/iwebview2createwebview2environmentcompletedhandler#interface_i_web_view2_create_web_view2_environment_completed_handler) to create the UI WebViews once the environment is ready. +We use the [ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference/icorewebview2createcorewebview2environmentcompletedhandler) to create the UI WebViews once the environment is ready. ```cpp HRESULT BrowserWindow::CreateBrowserControlsWebView() { - return m_uiEnv->CreateWebView(m_hWnd, Callback( - [this](HRESULT result, IWebView2WebView* webview) -> HRESULT + return m_uiEnv->CreateCoreWebView2Host(m_hWnd, Callback( + [this](HRESULT result, ICoreWebView2Host* host) -> HRESULT { if (!SUCCEEDED(result)) { @@ -192,17 +200,17 @@ HRESULT BrowserWindow::CreateBrowserControlsWebView() return result; } // WebView created - m_controlsWebView = webview; + m_controlsHost = host; + CheckFailure(m_controlsHost->get_CoreWebView2(&m_controlsWebView), L""); - wil::com_ptr settings; + wil::com_ptr settings; RETURN_IF_FAILED(m_controlsWebView->get_Settings(&settings)); RETURN_IF_FAILED(settings->put_AreDevToolsEnabled(FALSE)); - RETURN_IF_FAILED(settings->put_IsFullscreenAllowed(FALSE)); - RETURN_IF_FAILED(m_controlsWebView->add_ZoomFactorChanged(Callback( - [](IWebView2WebView* webview, IUnknown* args) -> HRESULT + RETURN_IF_FAILED(m_controlsHost->add_ZoomFactorChanged(Callback( + [](ICoreWebView2Host* host, IUnknown* args) -> HRESULT { - webview->put_ZoomFactor(1.0); + host->put_ZoomFactor(1.0); return S_OK; } ).Get(), &m_controlsZoomToken)); @@ -217,7 +225,7 @@ HRESULT BrowserWindow::CreateBrowserControlsWebView() }).Get()); } ``` -We're setting up a few things here. The [IWebView2Settings](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/iwebview2settings) interface is used to disable DevTools in the WebView powering the browser controls. We're also adding a handler for received web messages. This handler will enable us to do something when the user interacts with the controls in this WebView. +We're setting up a few things here. The [ICoreWebView2Settings](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference/icorewebview2settings) interface is used to disable DevTools in the WebView powering the browser controls. We're also adding a handler for received web messages. This handler will enable us to do something when the user interacts with the controls in this WebView. ### Navigate to web page You can navigate to a web page by entering its URI in the address bar. When pressing Enter, the controls WebView will post a web message to the host app so it can navigate the active tab to the specified location. Code below shows how the host Win32 application will handle that message. @@ -261,8 +269,8 @@ The address bar is updated every time there is a change in the active tab's docu ```cpp // Register event handler for doc state change - RETURN_IF_FAILED(m_contentWebView->add_DocumentStateChanged(Callback( - [this, browserWindow](IWebView2WebView* webview, IWebView2DocumentStateChangedEventArgs* args) -> HRESULT + RETURN_IF_FAILED(m_contentWebView->add_SourceChanged(Callback( + [this, browserWindow](ICoreWebView2* webview, ICoreWebView2SourceChangedEventArgs* args) -> HRESULT { BrowserWindow::CheckFailure(browserWindow->HandleTabURIUpdate(m_tabId, webview), L"Can't update address bar"); @@ -270,7 +278,7 @@ The address bar is updated every time there is a change in the active tab's docu }).Get(), &m_uriUpdateForwarderToken)); ``` ```cpp -HRESULT BrowserWindow::HandleTabURIUpdate(size_t tabId, IWebView2WebView* webview) +HRESULT BrowserWindow::HandleTabURIUpdate(size_t tabId, ICoreWebView2* webview) { wil::unique_cotaskmem_string source; RETURN_IF_FAILED(webview->get_Source(&source)); @@ -283,6 +291,15 @@ HRESULT BrowserWindow::HandleTabURIUpdate(size_t tabId, IWebView2WebView* webvie // ... + RETURN_IF_FAILED(PostJsonToWebView(jsonObj, m_controlsWebView.Get())); + + return S_OK; +} + +HRESULT BrowserWindow::HandleTabHistoryUpdate(size_t tabId, ICoreWebView2* webview) +{ + // ... + BOOL canGoForward = FALSE; RETURN_IF_FAILED(webview->get_CanGoForward(&canGoForward)); jsonObj[L"args"][L"canGoForward"] = web::json::value::boolean(canGoForward); @@ -398,12 +415,12 @@ function reloadActiveTabContent() { ## Some interesting features ### Communicating the WebViews -We need to communicate the WebViews powering tabs and UI so that user interactions in one have the desired effect in the other. WebView2Browser makes use of set of very useful WebView2 APIs for this purpose, including [PostWebMessageAsJson](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/iwebview2webview#postwebmessageasjson), [add_WebMessageReceived](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/iwebview2webview#add_webmessagereceived) and [IWebView2WebMessageReceivedEventHandler](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/iwebview2webmessagereceivedeventhandler). On the JavaScript side, we're making use of the `window.chrome.webview` object exposed to call the `postMessage` method and add an event lister for received messages. +We need to communicate the WebViews powering tabs and UI so that user interactions in one have the desired effect in the other. WebView2Browser makes use of set of very useful WebView2 APIs for this purpose, including [PostWebMessageAsJson](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference/icorewebview2#postwebmessageasjson), [add_WebMessageReceived](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference/icorewebview2#add_webmessagereceived) and [ICoreWebView2WebMessageReceivedEventHandler](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference/icorewebview2webmessagereceivedeventhandler). On the JavaScript side, we're making use of the `window.chrome.webview` object exposed to call the `postMessage` method and add an event lister for received messages. ```cpp HRESULT BrowserWindow::CreateBrowserControlsWebView() { - return m_uiEnv->CreateWebView(m_hWnd, Callback( - [this](HRESULT result, IWebView2WebView* webview) -> HRESULT + return m_uiEnv->CreateCoreWebView2Host(m_hWnd, Callback( + [this](HRESULT result, ICoreWebView2Host* host) -> HRESULT { // ... @@ -416,7 +433,7 @@ HRESULT BrowserWindow::CreateBrowserControlsWebView() } ``` ```cpp -HRESULT BrowserWindow::PostJsonToWebView(web::json::value jsonObj, IWebView2WebView* webview) +HRESULT BrowserWindow::PostJsonToWebView(web::json::value jsonObj, ICoreWebView2* webview) { utility::stringstream_t stream; jsonObj.serialize(stream); @@ -426,7 +443,7 @@ HRESULT BrowserWindow::PostJsonToWebView(web::json::value jsonObj, IWebView2WebV // ... -HRESULT BrowserWindow::HandleTabNavStarting(size_t tabId, IWebView2WebView* webview) +HRESULT BrowserWindow::HandleTabNavStarting(size_t tabId, ICoreWebView2* webview) { web::json::value jsonObj = web::json::value::parse(L"{}"); jsonObj[L"message"] = web::json::value(MG_NAV_STARTING); @@ -491,7 +508,7 @@ function createNewTab(shouldBeActive) { } } ``` -On the host app side, the registered [IWebView2WebMessageReceivedEventHandler](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/iwebview2webmessagereceivedeventhandler) will catch the message and create the WebView for that tab. +On the host app side, the registered [ICoreWebView2WebMessageReceivedEventHandler](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference/icorewebview2webmessagereceivedeventhandler) will catch the message and create the WebView for that tab. ```cpp case MG_CREATE_TAB: { @@ -513,7 +530,7 @@ On the host app side, the registered [IWebView2WebMessageReceivedEventHandler](h break; ``` ```cpp -std::unique_ptr Tab::CreateNewTab(HWND hWnd, IWebView2Environment* env, size_t id, bool shouldBeActive) +std::unique_ptr Tab::CreateNewTab(HWND hWnd, ICoreWebView2Environment* env, size_t id, bool shouldBeActive) { std::unique_ptr tab = std::make_unique(); @@ -525,38 +542,48 @@ std::unique_ptr Tab::CreateNewTab(HWND hWnd, IWebView2Environment* env, siz return tab; } -HRESULT Tab::Init(IWebView2Environment* env, bool shouldBeActive) +HRESULT Tab::Init(ICoreWebView2Environment* env, bool shouldBeActive) { - return env->CreateWebView(m_parentHWnd, Callback( - [this, shouldBeActive](HRESULT result, IWebView2WebView* webview) -> HRESULT { + return env->CreateCoreWebView2Host(m_parentHWnd, Callback( + [this, shouldBeActive](HRESULT result, ICoreWebView2Host* host) -> HRESULT { if (!SUCCEEDED(result)) { OutputDebugString(L"Tab WebView creation failed\n"); return result; } - m_contentWebView = webview; + m_contentHost = host; + BrowserWindow::CheckFailure(m_contentHost->get_CoreWebView2(&m_contentWebView), L""); BrowserWindow* browserWindow = reinterpret_cast(GetWindowLongPtr(m_parentHWnd, GWLP_USERDATA)); RETURN_IF_FAILED(m_contentWebView->add_WebMessageReceived(m_messageBroker.Get(), &m_messageBrokerToken)); - // Register event handler for doc state change - RETURN_IF_FAILED(m_contentWebView->add_DocumentStateChanged(Callback( - [this, browserWindow](IWebView2WebView* webview, IWebView2DocumentStateChangedEventArgs* args) -> HRESULT + // Register event handler for history change + RETURN_IF_FAILED(m_contentWebView->add_HistoryChanged(Callback( + [this, browserWindow](ICoreWebView2* webview, IUnknown* args) -> HRESULT + { + BrowserWindow::CheckFailure(browserWindow->HandleTabHistoryUpdate(m_tabId, webview), L"Can't update go back/forward buttons."); + + return S_OK; + }).Get(), &m_historyUpdateForwarderToken)); + + // Register event handler for source change + RETURN_IF_FAILED(m_contentWebView->add_SourceChanged(Callback( + [this, browserWindow](ICoreWebView2* webview, ICoreWebView2SourceChangedEventArgs* args) -> HRESULT { BrowserWindow::CheckFailure(browserWindow->HandleTabURIUpdate(m_tabId, webview), L"Can't update address bar"); return S_OK; }).Get(), &m_uriUpdateForwarderToken)); - RETURN_IF_FAILED(m_contentWebView->add_NavigationStarting(Callback( - [this, browserWindow](IWebView2WebView* webview, IWebView2NavigationStartingEventArgs* args) -> HRESULT + RETURN_IF_FAILED(m_contentWebView->add_NavigationStarting(Callback( + [this, browserWindow](ICoreWebView2* webview, ICoreWebView2NavigationStartingEventArgs* args) -> HRESULT { BrowserWindow::CheckFailure(browserWindow->HandleTabNavStarting(m_tabId, webview), L"Can't update reload button"); return S_OK; }).Get(), &m_navStartingToken)); - RETURN_IF_FAILED(m_contentWebView->add_NavigationCompleted(Callback( - [this, browserWindow](IWebView2WebView* webview, IWebView2NavigationCompletedEventArgs* args) -> HRESULT + RETURN_IF_FAILED(m_contentWebView->add_NavigationCompleted(Callback( + [this, browserWindow](ICoreWebView2* webview, ICoreWebView2NavigationCompletedEventArgs* args) -> HRESULT { BrowserWindow::CheckFailure(browserWindow->HandleTabNavCompleted(m_tabId, webview, args), L"Can't udpate reload button"); return S_OK; @@ -591,21 +618,23 @@ HRESULT BrowserWindow::SwitchToTab(size_t tabId) ``` ### Updating the security icon -We use the [CallDevToolsProtocolMethod](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/iwebview2webview#calldevtoolsprotocolmethod) to enable listening for security events. Whenever a `securityStateChanged` event is fired, we will use the new state to update the security icon on the controls WebView. +We use the [CallDevToolsProtocolMethod](https://docs.microsoft.com/microsoft-edge/hosting/webview2/reference/icorewebview2#calldevtoolsprotocolmethod) to enable listening for security events. Whenever a `securityStateChanged` event is fired, we will use the new state to update the security icon on the controls WebView. ```cpp // Enable listening for security events to update secure icon RETURN_IF_FAILED(m_contentWebView->CallDevToolsProtocolMethod(L"Security.enable", L"{}", nullptr)); + BrowserWindow::CheckFailure(m_contentWebView->GetDevToolsProtocolEventReceiver(L"Security.securityStateChanged", &m_securityStateChangedReceiver), L""); + // Forward security status updates to browser - RETURN_IF_FAILED(m_contentWebView->add_DevToolsProtocolEventReceived(L"Security.securityStateChanged", Callback( - [this, browserWindow](IWebView2WebView* webview, IWebView2DevToolsProtocolEventReceivedEventArgs* args) -> HRESULT + RETURN_IF_FAILED(m_securityStateChangedReceiver->add_DevToolsProtocolEventReceived(Callback( + [this, browserWindow](ICoreWebView2* webview, ICoreWebView2DevToolsProtocolEventReceivedEventArgs* args) -> HRESULT { BrowserWindow::CheckFailure(browserWindow->HandleTabSecurityUpdate(m_tabId, webview, args), L"Can't udpate security icon"); return S_OK; }).Get(), &m_securityUpdateToken)); ``` ```cpp -HRESULT BrowserWindow::HandleTabSecurityUpdate(size_t tabId, IWebView2WebView* webview, IWebView2DevToolsProtocolEventReceivedEventArgs* args) +HRESULT BrowserWindow::HandleTabSecurityUpdate(size_t tabId, ICoreWebView2* webview, ICoreWebView2DevToolsProtocolEventReceivedEventArgs* args) { wil::unique_cotaskmem_string jsonArgs; RETURN_IF_FAILED(args->get_ParameterObjectAsJson(&jsonArgs)); diff --git a/Tab.cpp b/Tab.cpp index f45d554..437efe6 100644 --- a/Tab.cpp +++ b/Tab.cpp @@ -7,7 +7,7 @@ using namespace Microsoft::WRL; -std::unique_ptr Tab::CreateNewTab(HWND hWnd, IWebView2Environment* env, size_t id, bool shouldBeActive) +std::unique_ptr Tab::CreateNewTab(HWND hWnd, ICoreWebView2Environment* env, size_t id, bool shouldBeActive) { std::unique_ptr tab = std::make_unique(); @@ -19,38 +19,48 @@ std::unique_ptr Tab::CreateNewTab(HWND hWnd, IWebView2Environment* env, siz return tab; } -HRESULT Tab::Init(IWebView2Environment* env, bool shouldBeActive) +HRESULT Tab::Init(ICoreWebView2Environment* env, bool shouldBeActive) { - return env->CreateWebView(m_parentHWnd, Callback( - [this, shouldBeActive](HRESULT result, IWebView2WebView* webview) -> HRESULT { + return env->CreateCoreWebView2Host(m_parentHWnd, Callback( + [this, shouldBeActive](HRESULT result, ICoreWebView2Host* host) -> HRESULT { if (!SUCCEEDED(result)) { OutputDebugString(L"Tab WebView creation failed\n"); return result; } - m_contentWebView = webview; + m_contentHost = host; + BrowserWindow::CheckFailure(m_contentHost->get_CoreWebView2(&m_contentWebView), L""); BrowserWindow* browserWindow = reinterpret_cast(GetWindowLongPtr(m_parentHWnd, GWLP_USERDATA)); RETURN_IF_FAILED(m_contentWebView->add_WebMessageReceived(m_messageBroker.Get(), &m_messageBrokerToken)); - // Register event handler for doc state change - RETURN_IF_FAILED(m_contentWebView->add_DocumentStateChanged(Callback( - [this, browserWindow](IWebView2WebView* webview, IWebView2DocumentStateChangedEventArgs* args) -> HRESULT + // Register event handler for history change + RETURN_IF_FAILED(m_contentWebView->add_HistoryChanged(Callback( + [this, browserWindow](ICoreWebView2* webview, IUnknown* args) -> HRESULT + { + BrowserWindow::CheckFailure(browserWindow->HandleTabHistoryUpdate(m_tabId, webview), L"Can't update go back/forward buttons."); + + return S_OK; + }).Get(), &m_historyUpdateForwarderToken)); + + // Register event handler for source change + RETURN_IF_FAILED(m_contentWebView->add_SourceChanged(Callback( + [this, browserWindow](ICoreWebView2* webview, ICoreWebView2SourceChangedEventArgs* args) -> HRESULT { BrowserWindow::CheckFailure(browserWindow->HandleTabURIUpdate(m_tabId, webview), L"Can't update address bar"); return S_OK; }).Get(), &m_uriUpdateForwarderToken)); - RETURN_IF_FAILED(m_contentWebView->add_NavigationStarting(Callback( - [this, browserWindow](IWebView2WebView* webview, IWebView2NavigationStartingEventArgs* args) -> HRESULT + RETURN_IF_FAILED(m_contentWebView->add_NavigationStarting(Callback( + [this, browserWindow](ICoreWebView2* webview, ICoreWebView2NavigationStartingEventArgs* args) -> HRESULT { BrowserWindow::CheckFailure(browserWindow->HandleTabNavStarting(m_tabId, webview), L"Can't update reload button"); return S_OK; }).Get(), &m_navStartingToken)); - RETURN_IF_FAILED(m_contentWebView->add_NavigationCompleted(Callback( - [this, browserWindow](IWebView2WebView* webview, IWebView2NavigationCompletedEventArgs* args) -> HRESULT + RETURN_IF_FAILED(m_contentWebView->add_NavigationCompleted(Callback( + [this, browserWindow](ICoreWebView2* webview, ICoreWebView2NavigationCompletedEventArgs* args) -> HRESULT { BrowserWindow::CheckFailure(browserWindow->HandleTabNavCompleted(m_tabId, webview, args), L"Can't udpate reload button"); return S_OK; @@ -59,9 +69,11 @@ HRESULT Tab::Init(IWebView2Environment* env, bool shouldBeActive) // Enable listening for security events to update secure icon RETURN_IF_FAILED(m_contentWebView->CallDevToolsProtocolMethod(L"Security.enable", L"{}", nullptr)); + BrowserWindow::CheckFailure(m_contentWebView->GetDevToolsProtocolEventReceiver(L"Security.securityStateChanged", &m_securityStateChangedReceiver), L""); + // Forward security status updates to browser - RETURN_IF_FAILED(m_contentWebView->add_DevToolsProtocolEventReceived(L"Security.securityStateChanged", Callback( - [this, browserWindow](IWebView2WebView* webview, IWebView2DevToolsProtocolEventReceivedEventArgs* args) -> HRESULT + RETURN_IF_FAILED(m_securityStateChangedReceiver->add_DevToolsProtocolEventReceived(Callback( + [this, browserWindow](ICoreWebView2* webview, ICoreWebView2DevToolsProtocolEventReceivedEventArgs* args) -> HRESULT { BrowserWindow::CheckFailure(browserWindow->HandleTabSecurityUpdate(m_tabId, webview, args), L"Can't udpate security icon"); return S_OK; @@ -76,8 +88,8 @@ HRESULT Tab::Init(IWebView2Environment* env, bool shouldBeActive) void Tab::SetMessageBroker() { - m_messageBroker = Callback( - [this](IWebView2WebView* webview, IWebView2WebMessageReceivedEventArgs* eventArgs) -> HRESULT + m_messageBroker = Callback( + [this](ICoreWebView2* webview, ICoreWebView2WebMessageReceivedEventArgs* eventArgs) -> HRESULT { BrowserWindow* browserWindow = reinterpret_cast(GetWindowLongPtr(m_parentHWnd, GWLP_USERDATA)); BrowserWindow::CheckFailure(browserWindow->HandleTabMessageReceived(m_tabId, webview, eventArgs), L""); @@ -94,5 +106,5 @@ HRESULT Tab::ResizeWebView() BrowserWindow* browserWindow = reinterpret_cast(GetWindowLongPtr(m_parentHWnd, GWLP_USERDATA)); bounds.top += browserWindow->GetDPIAwareBound(BrowserWindow::c_uiBarHeight); - return m_contentWebView->put_Bounds(bounds); + return m_contentHost->put_Bounds(bounds); } diff --git a/Tab.h b/Tab.h index 89f12d6..ff28172 100644 --- a/Tab.h +++ b/Tab.h @@ -9,20 +9,23 @@ class Tab { public: - Microsoft::WRL::ComPtr m_contentWebView; + Microsoft::WRL::ComPtr m_contentHost; + Microsoft::WRL::ComPtr m_contentWebView; + Microsoft::WRL::ComPtr m_securityStateChangedReceiver; - static std::unique_ptr CreateNewTab(HWND hWnd, IWebView2Environment* env, size_t id, bool shouldBeActive); + static std::unique_ptr CreateNewTab(HWND hWnd, ICoreWebView2Environment* env, size_t id, bool shouldBeActive); HRESULT ResizeWebView(); protected: HWND m_parentHWnd = nullptr; size_t m_tabId = INVALID_TAB_ID; + EventRegistrationToken m_historyUpdateForwarderToken = {}; EventRegistrationToken m_uriUpdateForwarderToken = {}; EventRegistrationToken m_navStartingToken = {}; EventRegistrationToken m_navCompletedToken = {}; EventRegistrationToken m_securityUpdateToken = {}; EventRegistrationToken m_messageBrokerToken = {}; // Message broker for browser pages loaded in a tab - Microsoft::WRL::ComPtr m_messageBroker; + Microsoft::WRL::ComPtr m_messageBroker; - HRESULT Init(IWebView2Environment* env, bool shouldBeActive); + HRESULT Init(ICoreWebView2Environment* env, bool shouldBeActive); void SetMessageBroker(); }; diff --git a/WebViewBrowserApp.sln b/WebViewBrowserApp.sln index c1f9e56..c663953 100644 --- a/WebViewBrowserApp.sln +++ b/WebViewBrowserApp.sln @@ -13,14 +13,10 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Debug|ARM64.Build.0 = Debug|ARM64 {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Debug|x64.ActiveCfg = Debug|x64 {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Debug|x64.Build.0 = Debug|x64 {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Debug|x86.ActiveCfg = Debug|Win32 {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Debug|x86.Build.0 = Debug|Win32 - {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Release|ARM64.ActiveCfg = Release|ARM64 - {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Release|ARM64.Build.0 = Release|ARM64 {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Release|x64.ActiveCfg = Release|x64 {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Release|x64.Build.0 = Release|x64 {D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Release|x86.ActiveCfg = Release|Win32 diff --git a/WebViewBrowserApp.vcxproj b/WebViewBrowserApp.vcxproj index 65666d8..3df920a 100644 --- a/WebViewBrowserApp.vcxproj +++ b/WebViewBrowserApp.vcxproj @@ -17,14 +17,6 @@ Release x64 - - Debug - ARM64 - - - Release - ARM64 - 16.0 @@ -61,19 +53,6 @@ true Unicode - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - @@ -91,12 +70,6 @@ - - - - - - true @@ -111,13 +84,6 @@ $(ProjectName) $(Configuration)\ - - true - $(Configuration)_$(Platform) - $(IncludePath) - $(ProjectName) - $(Configuration)\ - false $(Configuration)_x86 @@ -130,12 +96,6 @@ $(ProjectName) $(Configuration)\ - - false - $(Configuration)_$(Platform) - $(ProjectName) - $(Configuration)\ - @@ -145,7 +105,6 @@ true WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true - MultiThreadedDebug Windows @@ -164,28 +123,6 @@ true _DEBUG;_WINDOWS;%(PreprocessorDefinitions) true - MultiThreadedDebug - - - Windows - true - - - - - xcopy "$(ProjectDir)wvbrowser_ui" "$(OutDir)wvbrowser_ui" /S /I /Y - - - - - - - Level3 - Disabled - true - _DEBUG;_WINDOWS;%(PreprocessorDefinitions) - true - MultiThreadedDebug Windows @@ -208,7 +145,6 @@ true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true - MultiThreaded Windows @@ -231,30 +167,6 @@ true NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true - MultiThreaded - - - Windows - true - true - true - - - xcopy "$(ProjectDir)wvbrowser_ui" "$(OutDir)wvbrowser_ui" /S /I /Y - - - - - - - Level3 - MaxSpeed - true - true - true - NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - true - MultiThreaded Windows @@ -294,7 +206,7 @@ - + @@ -302,6 +214,6 @@ - + \ No newline at end of file diff --git a/packages.config b/packages.config index 73f8237..973741d 100644 --- a/packages.config +++ b/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file