|
| 1 | +# Background |
| 2 | +We have heard asks for a WebView2 API to easily track the `WebView2 Runtime`'s |
| 3 | +browser process exit. Manually waiting for the process to exit requires |
| 4 | +additional work on the host app, so we are proposing the `BrowserProcessExited` |
| 5 | +event. The `ProcessFailed` already lets app developers handle unexpected browser |
| 6 | +process exits for a WebView, this new API lets you listen to both expected and |
| 7 | +unexpected process termination from the `ICoreWebView2Environment` interface so |
| 8 | +you can, e.g., cleanup the user data folder when it's no longer in use. In this |
| 9 | +document we describe the new API. We'd appreciate your feedback. |
| 10 | + |
| 11 | + |
| 12 | +# Description |
| 13 | +The `BrowserProcessExited` event allows developers to subscribe event handlers |
| 14 | +to be run when the `WebView2 Runtime`'s browser process associated to a |
| 15 | +`CoreWebView2Environment` terminates. A key scenario is cleanup of the use data |
| 16 | +folder used by the `WebView2 Runtime`, which is locked while the runtime's |
| 17 | +browser process is active. |
| 18 | + |
| 19 | +This event is raised for both expected and unexpected browser process |
| 20 | +termination. The `ICoreWebView2BrowserProcessExitedEventArgs` interfaces lets |
| 21 | +app developers get the `BrowserProcessExitKind` so they can decide how to handle |
| 22 | +different exit kinds or bypass handling if an event handler for the |
| 23 | +`CoreWebView2`s `ProcessFailed` event (for |
| 24 | +`CoreWebView2ProcessFailedKind.BrowserProcessFailed`) is already registered. |
| 25 | + |
| 26 | + |
| 27 | +# Examples |
| 28 | +The following code snippets demonstrate how the `BrowserProcessExited` event can |
| 29 | +be used: |
| 30 | + |
| 31 | +## Win32 C++ |
| 32 | +```cpp |
| 33 | +// Before closing the WebView, register a handler with code to run once the |
| 34 | +// browser process is terminated. |
| 35 | +EventRegistrationToken browserExitedEventToken; |
| 36 | + |
| 37 | +CHECK_FAILURE(m_webViewEnvironment->add_BrowserProcessExited( |
| 38 | + Callback<ICoreWebView2BrowserProcessExitedEventHandler>( |
| 39 | + [browserExitedEventToken, this]( |
| 40 | + ICoreWebView2Environment* sender, |
| 41 | + ICoreWebView2BrowserProcessExitedEventArgs* args) { |
| 42 | + COREWEBVIEW2_BROWSER_PROCESS_EXIT_KIND kind; |
| 43 | + CHECK_FAILURE(args->get_BrowserProcessExitKind(&kind)); |
| 44 | + |
| 45 | + // Watch for graceful browser process exit. Let ProcessFailed event |
| 46 | + // handler take care of failed browser process termination. |
| 47 | + if (kind == COREWEBVIEW2_BROWSER_PROCESS_EXIT_KIND_NORMAL_EXIT) |
| 48 | + { |
| 49 | + CHECK_FAILURE( |
| 50 | + m_webViewEnvironment->remove_BrowserProcessExited(browserExitedEventToken)); |
| 51 | + // Release the environment only after the handler is invoked. |
| 52 | + // Otherwise, there will be no environment to raise the event when |
| 53 | + // the process exits. |
| 54 | + m_webViewEnvironment = nullptr; |
| 55 | + CleanupUserDataFolder(); |
| 56 | + } |
| 57 | + |
| 58 | + return S_OK; |
| 59 | + }).Get(), |
| 60 | + &browserExitedEventToken)); |
| 61 | +``` |
| 62 | +
|
| 63 | +## .NET C# |
| 64 | +```c# |
| 65 | +// Get the environment from the CoreWebView2 and add a handler. |
| 66 | +webView.CoreWebView2.Environment.BrowserProcessExited += Environment_BrowserProcessExited; |
| 67 | +
|
| 68 | +// Check and report browser process exit kind. |
| 69 | +void Environment_BrowserProcessExited(object sender, CoreWebView2BrowserProcessExitedEventArgs e) |
| 70 | +{ |
| 71 | + var exitKind = (e.BrowserProcessExitKind == CoreWebView2BrowserProcessExitKind.NormalExit) ? "normally" : "unexpectedly"; |
| 72 | + MessageBox.Show(this, $"The browser process has exited {exitKind}.", "Browser Process Exited"); |
| 73 | +} |
| 74 | +``` |
| 75 | + |
| 76 | + |
| 77 | +# Remarks |
| 78 | +Note this is an event from the `ICoreWebView2Environment` interface, not the |
| 79 | +`ICoreWebView2`. The difference between this `BrowserProcessExited` event and |
| 80 | +the `CoreWebView2`'s `ProcessFailed` event is that `BrowserProcessExited` is |
| 81 | +raised for any (expected and unexpected) **browser process** exits, while |
| 82 | +`ProcessFailed` is raised only for **unexpected** browser process exits, or for |
| 83 | +**render process** exits/unresponsiveness. To learn more about the WebView2 |
| 84 | +Process Model, go to (Process model)[https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/process-model]. |
| 85 | + |
| 86 | + |
| 87 | +# API Notes |
| 88 | +See [API Details](#api-details) section below for API reference. |
| 89 | + |
| 90 | + |
| 91 | +# API Details |
| 92 | + |
| 93 | +## COM |
| 94 | +```cpp |
| 95 | +library WebView2 |
| 96 | +{ |
| 97 | +// ... |
| 98 | + |
| 99 | +/// Specifies the browser process exit type used in the |
| 100 | +/// `ICoreWebView2StagingBrowserProcessExitedEventArgs` interface. |
| 101 | +typedef enum COREWEBVIEW2_BROWSER_PROCESS_EXIT_KIND { |
| 102 | + /// Indicates that the browser process ended normally. |
| 103 | + COREWEBVIEW2_BROWSER_PROCESS_EXIT_KIND_NORMAL_EXIT, |
| 104 | + |
| 105 | + /// Indicates that the browser process ended unexpectedly. |
| 106 | + /// A `ProcessFailed` event will also be sent to listening WebViews from the |
| 107 | + /// `ICoreWebView2Environment` associated to the failed process. |
| 108 | + COREWEBVIEW2_BROWSER_PROCESS_EXIT_KIND_FAILED_EXIT |
| 109 | +} COREWEBVIEW2_BROWSER_PROCESS_EXIT_KIND; |
| 110 | + |
| 111 | +interface ICoreWebView2Environment : IUnknown |
| 112 | +{ |
| 113 | + // ... |
| 114 | + |
| 115 | + /// Add an event handler for the `BrowserProcessExited` event. |
| 116 | + /// The `BrowserProcessExited` event is raised when the browser process of the |
| 117 | + /// WebView2 Runtime associated to this environment terminates due to an error |
| 118 | + /// or normal shutdown (e.g., when all its WebViews are closed). |
| 119 | + /// |
| 120 | + /// A handler added with this method is called until removed with |
| 121 | + /// `remove_BrowserProcessExited`, even if a new browser process is bound to |
| 122 | + /// this environment after earlier `BrowserProcessExited` events are raised. |
| 123 | + HRESULT add_BrowserProcessExited( |
| 124 | + [in] ICoreWebView2StagingBrowserProcessExitedEventHandler* eventHandler, |
| 125 | + [out] EventRegistrationToken* token); |
| 126 | + |
| 127 | + /// Remove an event handler previously added with `add_BrowserProcessExited`. |
| 128 | + HRESULT remove_BrowserProcessExited([in] EventRegistrationToken token); |
| 129 | +} |
| 130 | + |
| 131 | +/// Receives `BrowserProcessExited` events. |
| 132 | +interface ICoreWebView2StagingBrowserProcessExitedEventHandler : IUnknown |
| 133 | +{ |
| 134 | + /// Provides the event args for the corresponding event. |
| 135 | + HRESULT Invoke( |
| 136 | + [in] ICoreWebView2Environment* sender, |
| 137 | + [in] ICoreWebView2StagingBrowserProcessExitedEventArgs* args); |
| 138 | +} |
| 139 | + |
| 140 | +/// Event args for the `BrowserProcessExited` event. |
| 141 | +interface ICoreWebView2StagingBrowserProcessExitedEventArgs : IUnknown |
| 142 | +{ |
| 143 | + /// The kind of browser process exit that has occurred. |
| 144 | + [propget] HRESULT BrowserProcessExitKind( |
| 145 | + [out, retval] COREWEBVIEW2_BROWSER_PROCESS_EXIT_KIND* browserProcessExitKind); |
| 146 | +} |
| 147 | +``` |
| 148 | + |
| 149 | +## .NET and WinRT |
| 150 | +```c# |
| 151 | +namespace Microsoft.Web.WebView2.Core |
| 152 | +{ |
| 153 | + // ... |
| 154 | +
|
| 155 | + /// Specifies the browser process exit kind used in |
| 156 | + /// `CoreWebView2BrowserProcessExitedEventArgs`. |
| 157 | + enum CoreWebView2BrowserProcessExitKind |
| 158 | + { |
| 159 | + /// Indicates that the browser process ended normally. |
| 160 | + NormalExit, |
| 161 | + /// Indicates that the browser process ended unexpectedly. |
| 162 | + /// A `CoreWebView2.ProcessFailed` event will also be raised to |
| 163 | + /// listening WebViews from the `CoreWebView2Environment` associated to |
| 164 | + /// the failed process. |
| 165 | + FailedExit |
| 166 | + }; |
| 167 | + |
| 168 | + runtimeclass CoreWebView2Environment |
| 169 | + { |
| 170 | + // ... |
| 171 | +
|
| 172 | + /// `BrowserProcessExited` is raised when the browser process of the |
| 173 | + /// `WebView2 Runtime` associated to this `CoreWebView2Environment` |
| 174 | + /// terminates due to an error or normal shutdown (e.g., when all its |
| 175 | + /// WebViews are closed). |
| 176 | + event Windows.Foundation.TypedEventHandler<CoreWebView2Environment, CoreWebView2BrowserProcessExitedEventArgs> BrowserProcessExited; |
| 177 | + } |
| 178 | + |
| 179 | + /// Event args for the `CoreWebView2Environment.BrowserProcessExited` event. |
| 180 | + runtimeclass CoreWebView2BrowserProcessExitedEventArgs |
| 181 | + { |
| 182 | + /// The kind of browser process exit that has occurred. |
| 183 | + CoreWebView2BrowserProcessExitKind BrowserProcessExitKind { get; }; |
| 184 | + } |
| 185 | +} |
| 186 | +``` |
0 commit comments