Skip to content

Commit b37b36c

Browse files
committed
Add docs for race conditions, update C# code
1 parent cf65df0 commit b37b36c

1 file changed

Lines changed: 110 additions & 14 deletions

File tree

specs/BrowserProcessExited.md

Lines changed: 110 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,29 @@ document we describe the new API. We'd appreciate your feedback.
1212
# Description
1313
The `BrowserProcessExited` event allows developers to subscribe event handlers
1414
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
15+
`CoreWebView2Environment` terminates. Key scenarios are cleanup of the use data
1616
folder used by the `WebView2 Runtime`, which is locked while the runtime's
17-
browser process is active.
17+
browser process is active, and moving to a new `WebView2 Runtime` version after
18+
a `NewBrowserVersionAvailable` event.
1819

1920
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.
21+
termination, after all resources, including the user data folder, used by the
22+
browser process (and related processes) have been released. The
23+
`ICoreWebView2BrowserProcessExitedEventArgs` interface lets app developers get
24+
the `BrowserProcessExitKind` so they can decide how to handle different exit
25+
kinds or bypass handling if an event handler for the `CoreWebView2`s
26+
`ProcessFailed` event (for `CoreWebView2ProcessFailedKind.BrowserProcessFailed`)
27+
is already registered. In case of a browser process crash, both
28+
`BrowserProcessExited` and `ProcessFailed` events are raised, but the order is
29+
not guaranteed.
30+
31+
All `CoreWebView2Environment` objects across different app processes that use
32+
the same browser process receive this event when the browser process exits.
33+
If the browser process (and therefore the user data folder) in use by the app
34+
process (through the `CoreWebView2Environment` options used) is shared with
35+
other processes, these processes need to coordinate to handle the potential race
36+
condition on the use of the resources. E.g., if one app process tries to clear
37+
the user data folder, while other tries to recreate its WebViews on crash.
2538

2639

2740
# Examples
@@ -62,14 +75,68 @@ CHECK_FAILURE(m_webViewEnvironment->add_BrowserProcessExited(
6275
6376
## .NET C#
6477
```c#
65-
// Get the environment from the CoreWebView2 and add a handler.
66-
webView.CoreWebView2.Environment.BrowserProcessExited += Environment_BrowserProcessExited;
78+
// URI or other state to save/restore when the WebView is recreated.
79+
private Uri _uriToRestore;
80+
81+
async void RegisterForNewVersion()
82+
{
83+
// We need to make sure the CoreWebView2 property is not null, so we can get
84+
// the environment from it. Alternatively, if the WebView was created from
85+
// an environment provided to the control, we can use that environment
86+
// object directly.
87+
await webView.EnsureCoreWebView2Async();
88+
_coreWebView2Environment = webView.CoreWebView2.Environment;
89+
_coreWebView2Environment.NewBrowserVersionAvailable += Environment_NewBrowserVersionAvailable;
90+
}
91+
92+
// A new version of the WebView2 Runtime is available, our handler gets called.
93+
// We close our WebView and set a handler to reinitialize it once the browser
94+
// process is gone, so we get the new version of the WebView2 Runtime.
95+
void Environment_NewBrowserVersionAvailable(object sender, object e)
96+
{
97+
StringBuilder messageBuilder = new StringBuilder(256);
98+
messageBuilder.Append("We detected there is a new version of the WebView2 Runtime installed. ");
99+
messageBuilder.Append("Do you want to switch to it now? This will re-create the WebView.");
100+
var selection = MessageBox.Show(this, messageBuilder.ToString(), "New WebView2 Runtime detected", MessageBoxButton.YesNo);
101+
if (selection == MessageBoxResult.Yes)
102+
{
103+
// Save URI or other state you want to restore when the WebView is recreated.
104+
_uriToRestore = webView.Source;
105+
_coreWebView2Environment.BrowserProcessExited += Environment_BrowserProcessExited;
106+
// We dispose of the control so the internal WebView objects are released
107+
// and the associated browser process exits. If there are any other WebViews
108+
// from the same environment configuration, they need to be closed too.
109+
webView.Dispose();
110+
webView = null;
111+
}
112+
}
67113
68-
// Check and report browser process exit kind.
69114
void Environment_BrowserProcessExited(object sender, CoreWebView2BrowserProcessExitedEventArgs e)
70115
{
71-
var exitKind = (e.BrowserProcessExitKind == CoreWebView2BrowserProcessExitKind.NormalExit) ? "normally" : "unexpectedly";
72-
MessageBox.Show(this, $"The browser process has exited {exitKind}.", "Browser Process Exited");
116+
((CoreWebView2Environment)sender).BrowserProcessExited -= Environment_BrowserProcessExited;
117+
ReinitializeWebView();
118+
}
119+
120+
void ReinitializeWebView()
121+
{
122+
webView = new WebView2();
123+
124+
// Restore URI and other WebView state/setup.
125+
webView.CreationProperties = (CoreWebView2CreationProperties)this.FindResource("EvergreenWebView2CreationProperties");
126+
webView.NavigationStarting += WebView_NavigationStarting;
127+
webView.NavigationCompleted += WebView_NavigationCompleted;
128+
129+
Binding urlBinding = new Binding()
130+
{
131+
Source = webView,
132+
Path = new PropertyPath("Source"),
133+
Mode = BindingMode.OneWay
134+
};
135+
url.SetBinding(TextBox.TextProperty, urlBinding);
136+
137+
MyWindow.MyDockPanel.Children.Add(webView);
138+
webView.Source = (_uriToRestore != null) ? _uriToRestore : new Uri("https://www.bing.com");
139+
RegisterForNewVersion();
73140
}
74141
```
75142

@@ -83,6 +150,9 @@ raised for any (expected and unexpected) **browser process** exits, while
83150
**render process** exits/unresponsiveness. To learn more about the WebView2
84151
Process Model, go to [Process model](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/process-model).
85152

153+
In the case the browser process crashes, both `BrowserProcessExited` and
154+
`ProcessFailed` events are raised, but the order is not guaranteed.
155+
86156

87157
# API Notes
88158
See [API Details](#api-details) section below for API reference.
@@ -115,19 +185,32 @@ interface ICoreWebView2Environment3 : ICoreWebView2Environment2
115185
/// Add an event handler for the `BrowserProcessExited` event.
116186
/// The `BrowserProcessExited` event is raised when the browser process of the
117187
/// WebView2 Runtime associated to this environment terminates due to an error
118-
/// or normal shutdown (e.g., when all its WebViews are closed).
188+
/// or normal shutdown (e.g., when all its WebViews are closed), after all
189+
/// resources (including the user data folder) used by the browser process
190+
/// (and related processes) have been released.
119191
///
120192
/// A handler added with this method is called until removed with
121193
/// `remove_BrowserProcessExited`, even if a new browser process is bound to
122194
/// this environment after earlier `BrowserProcessExited` events are raised.
123195
///
196+
/// All `CoreWebView2Environment` objects across different app processes that use
197+
/// the same browser process receive this event when the browser process exits.
198+
/// If the browser process (and therefore the user data folder) in use by the app
199+
/// process (through the `CoreWebView2Environment` options used) is shared with
200+
/// other processes, these processes need to coordinate to handle the potential race
201+
/// condition on the use of the resources. E.g., if one app process tries to clear
202+
/// the user data folder, while other tries to recreate its WebViews on crash.
203+
///
124204
/// Note this is an event from the `ICoreWebView2Environment3` interface, not the
125205
/// `ICoreWebView2`. The difference between this `BrowserProcessExited` event and
126206
/// the `CoreWebView2`'s `ProcessFailed` event is that `BrowserProcessExited` is
127207
/// raised for any (expected and unexpected) **browser process** exits, while
128208
/// `ProcessFailed` is raised only for **unexpected** browser process exits, or for
129209
/// **render process** exits/unresponsiveness. To learn more about the WebView2
130210
/// Process Model, go to [Process model](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/process-model).
211+
///
212+
/// In the case the browser process crashes, both `BrowserProcessExited` and
213+
/// `ProcessFailed` events are raised, but the order is not guaranteed.
131214
HRESULT add_BrowserProcessExited(
132215
[in] ICoreWebView2BrowserProcessExitedEventHandler* eventHandler,
133216
[out] EventRegistrationToken* token);
@@ -180,7 +263,17 @@ namespace Microsoft.Web.WebView2.Core
180263
/// `BrowserProcessExited` is raised when the browser process of the
181264
/// `WebView2 Runtime` associated to this `CoreWebView2Environment`
182265
/// terminates due to an error or normal shutdown (e.g., when all its
183-
/// WebViews are closed).
266+
/// WebViews are closed), after all resources (including the user data
267+
/// folder) used by the browser process (and related processes) have
268+
/// been released.
269+
///
270+
/// All `CoreWebView2Environment` objects across different app processes that use
271+
/// the same browser process receive this event when the browser process exits.
272+
/// If the browser process (and therefore the user data folder) in use by the app
273+
/// process (through the `CoreWebView2Environment` options used) is shared with
274+
/// other processes, these processes need to coordinate to handle the potential race
275+
/// condition on the use of the resources. E.g., if one app process tries to clear
276+
/// the user data folder, while other tries to recreate its WebViews on crash.
184277
///
185278
/// Note this is an event from `CoreWebView2Environment`, not the
186279
/// `CoreWebView2`. The difference between this `BrowserProcessExited` event and
@@ -189,6 +282,9 @@ namespace Microsoft.Web.WebView2.Core
189282
/// `ProcessFailed` is raised only for **unexpected** browser process exits, or for
190283
/// **render process** exits/unresponsiveness. To learn more about the WebView2
191284
/// Process Model, go to [Process model](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/process-model).
285+
///
286+
/// In the case the browser process crashes, both `BrowserProcessExited` and
287+
/// `ProcessFailed` events are raised, but the order is not guaranteed.
192288
event Windows.Foundation.TypedEventHandler<CoreWebView2Environment, CoreWebView2BrowserProcessExitedEventArgs> BrowserProcessExited;
193289
}
194290

0 commit comments

Comments
 (0)