Skip to content

Commit 007e915

Browse files
committed
BrowserProcessExited event API spec
1 parent 324cacd commit 007e915

1 file changed

Lines changed: 186 additions & 0 deletions

File tree

specs/BrowserProcessExited.md

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
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

Comments
 (0)