Skip to content

Commit 898b37b

Browse files
authored
Merge pull request #1051 from MicrosoftEdge/TryUpdateRuntime
API for triggering Edge WebView2 Runtime Update
2 parents fac2d6a + c7f573e commit 898b37b

1 file changed

Lines changed: 281 additions & 0 deletions

File tree

specs/UpdateRuntime.md

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
# Background
2+
The new version of an app might require a newer version of Edge WebView2 Runtime.
3+
4+
An app updater may wish to ensure that a particular minimum version of the Edge WebView2 Runtime is installed before upgrading the app to a version that requires those features.
5+
6+
Alternatively, the newer version of the app could use feature detection to disable portions of the app that rely on new WebView2 Runtime features. In this alternate scenario, the app updater would install the new version of the app immediately, and then request that the Edge WebView2 Runtime be updated, so that the updated app can start taking advantage of the new features once the Edge WebView2 Runtime is updated.
7+
8+
Edge WebView2 Runtime is auto updated and normally the latest version should be already installed. However, there could be cases that we need trigger Edge WebView2 Runtime
9+
update to ensure coordinated app and WebView2 Runtime update.
10+
11+
# Description
12+
You may call the `UpdateRuntime` API to check and install updates for the installed Edge WebView2 Runtime. This is useful when the app wants to coordinate app and
13+
Edge WebView2 Runtime update.
14+
15+
# Examples
16+
## .NET, WinRT
17+
```c#
18+
using Microsoft.Web.WebView2.Core;
19+
async protected bool EnsureWebView2RuntimeVersion(string minimalVersionRequired)
20+
{
21+
string currentRuntimeVersion = CoreWebView2Environment.GetAvailableBrowserVersionString();
22+
if (CoreWebView2Environment.CompareBrowserVersions(currentRuntimeVersion, minimalVersionRequired) < 0)
23+
{
24+
auto environment = await CoreWebView2Environment.CreateAsync();
25+
auto updateResult = await environment.UpdateRuntimeAsync();
26+
if (updateResult.UpdateRuntimeStatus != CoreWebView2RuntimeUpdateStatus.LatestVersionInstalled)
27+
return false;
28+
// check runtime version again
29+
currentRuntimeVersion = CoreWebView2Environment.GetAvailableBrowserVersionString();
30+
}
31+
return (CoreWebView2Environment.CompareBrowserVersions(currentRuntimeVersion, minimalVersionRequired) >= 0);
32+
}
33+
34+
// For the scenario where the app wants to light up features fast while running with the old version.
35+
{
36+
// We could be running with a WebView2 Runtime version that has or doesn't have some features.
37+
// Therefore, check the version that we are running the WebView2 with, and skip the new feature if running old version.
38+
string currentRunningVersion = webView2Environment.NewBrowserVersionAvailable;
39+
if (CoreWebView2Environment.CompareBrowserVersions(currentRunningVersion, minimalVersionHasFeartures) >= 0) {
40+
// Light up the app features that make usage of APIs that only works in newer version.
41+
}
42+
43+
...
44+
// Listen to NewBrowserVersionAvailable event to switch to newer version when it is available.
45+
webView2Environment.NewBrowserVersionAvailable += delegate (object sender, object args)
46+
{
47+
// See the NewBrowserVersionAvailable documentation for more information
48+
// Close current WebView2 Control
49+
// Wait for it to completely shutdown
50+
// Recreate WebView2 Control to run with newer version
51+
};
52+
53+
// Trigger Edge WebView2 Runtime update, ignore update result and rely on NewBrowserVersionAvailable to take action.
54+
_ = EnsureWebView2RuntimeVersion(desiredVersion);
55+
}
56+
57+
```
58+
## Win32 C++
59+
```cpp
60+
bool IsCurrentVersionSameOrNewer(std::wstring minimalVersionRequired)
61+
{
62+
wil::unique_cotaskmem_string currentVersion;
63+
HRESULT hr = GetAvailableCoreWebView2BrowserVersionString(nullptr, &currentVersion);
64+
if (FAILED(hr) || (currentVersion == nullptr))
65+
{
66+
return false;
67+
}
68+
int versionComparisonResult;
69+
CompareBrowserVersions(currentVersion.get(), minimalVersionRequired.c_str(), &versionComparisonResult);
70+
return (versionComparisonResult >= 0)
71+
}
72+
73+
void EnsureWebView2RuntimeVersion(std::function<void(bool)> const& callback, std::wstring minimalVersionRequired)
74+
{
75+
if (IsCurrentVersionSameOrNewer(minimalVersionRequired))
76+
{
77+
callback(true);
78+
return;
79+
}
80+
auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
81+
CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, options.Get(),
82+
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
83+
[callback, minimalVersionRequired](HRESULT result, ICoreWebView2Environment* environment) -> HRESULT {
84+
wil::com_ptr<ICoreWebView2Environment> webViewEnvironment = environment;
85+
auto experimentalEnvironment3 = webViewEnvironment.try_query<ICoreWebView2ExperimentalEnvironment3>();
86+
HRESULT hr = experimentalEnvironment3->UpdateRuntime(
87+
Callback<ICoreWebView2ExperimentalUpdateRuntimeCompletedHandler>(
88+
[callback, minimalVersionRequired, experimentalEnvironment3](HRESULT errorCode,
89+
ICoreWebView2ExperimentalUpdateRuntimeResult* result) -> HRESULT {
90+
COREWEBVIEW2_RUNTIME_UPDATE_STATUS updateStatus =
91+
COREWEBVIEW2_RUNTIME_UPDATE_STATUS_FAILED;
92+
if ((errorCode == S_OK) && result)
93+
{
94+
CHECK_FAILURE(result->get_UpdateRuntimeStatus(&updateStatus));
95+
}
96+
if (updateStatus != COREWEBVIEW2_UPDATE_RUNTIME_STATUS_LATEST_VERSION_INSTALLED)
97+
{
98+
callback(false);
99+
}
100+
else
101+
{
102+
callback(IsCurrentVersionSameOrNewer(minimalVersionRequired));
103+
}
104+
return S_OK;
105+
})
106+
.Get());
107+
return S_OK;
108+
})
109+
.Get());
110+
}
111+
112+
```
113+
114+
# Remarks
115+
See comments in [API Details](#api-details) section below.
116+
117+
# API Notes
118+
See [API Details](#api-details) section below for API reference.
119+
120+
# API Details
121+
122+
## Win32 C++
123+
```IDL
124+
/// Status of UpdateRuntime operation result.
125+
[v1_enum] typedef enum COREWEBVIEW2_UPDATE_RUNTIME_STATUS {
126+
127+
/// Latest version of Edge WebView2 Runtime is installed.
128+
/// No update for Edge WebView2 Runtime is available, or Edge WebView2
129+
/// Runtime is updated successfully and latest version is now installed.
130+
COREWEBVIEW2_UPDATE_RUNTIME_STATUS_LATEST_VERSION_INSTALLED,
131+
132+
/// Edge WebView2 Runtime update is already running, which could be
133+
/// triggered by auto update or by other UpdateRuntime request from some app.
134+
COREWEBVIEW2_UPDATE_RUNTIME_STATUS_UPDATE_ALREADY_RUNNING,
135+
136+
/// Edge WebView2 Runtime update is blocked by group policy.
137+
COREWEBVIEW2_UPDATE_RUNTIME_STATUS_BLOCKED_BY_POLICY,
138+
139+
/// Edge WebView2 Runtime update failed.
140+
/// See `ExtendedError` property of UpdateRuntimeResult for more
141+
/// information about the failure.
142+
COREWEBVIEW2_UPDATE_RUNTIME_STATUS_FAILED,
143+
} COREWEBVIEW2_UPDATE_RUNTIME_STATUS;
144+
145+
/// The UpdateRuntime operation result.
146+
[uuid(DD503E49-AB19-47C0-B2AD-6DDD09CC3E3A), object, pointer_default(unique)]
147+
interface ICoreWebView2ExperimentalUpdateRuntimeResult : IUnknown {
148+
149+
/// The status for the UpdateRuntime operation.
150+
[propget] HRESULT Status(
151+
[out, retval] COREWEBVIEW2_UPDATE_RUNTIME_STATUS* status);
152+
153+
/// The update error happened while trying to update Edge WebView2 Runtime.
154+
/// ExtendedError will be S_OK if Status is not `COREWEBVIEW2_UPDATE_RUNTIME_STATUS_FAILED`
155+
/// or `COREWEBVIEW2_UPDATE_RUNTIME_STATUS_BLOCKED_BY_POLICY`.
156+
[propget] HRESULT ExtendedError([out, retval] HRESULT* error);
157+
}
158+
159+
/// The caller implements this interface to receive the UpdateRuntime result.
160+
[uuid(F1D2D722-3721-499C-87F5-4C405260697A), object, pointer_default(unique)]
161+
interface ICoreWebView2ExperimentalUpdateRuntimeCompletedHandler : IUnknown {
162+
163+
/// Provides the result for the UpdateRuntime operation.
164+
/// `errorCode` will be S_OK if the update operation can be performed
165+
/// normally, regardless of whether we could update the Edge WebView2
166+
/// Runtime. If an unexpected error interrupts the update operation, error
167+
/// code of that unexpected error would be set as `errorCode`.
168+
/// When update operation can be performed normally, but update resulted in
169+
/// failure, like download failed, the error code would be presented as
170+
/// `ExtendedError` property of ICoreWebView2ExperimentalUpdateRuntimeResult.
171+
HRESULT Invoke([in] HRESULT errorCode,
172+
[in] ICoreWebView2ExperimentalUpdateRuntimeResult* result);
173+
}
174+
175+
/// This interface is an extension of the ICoreWebView2Environment. An object
176+
/// implementing the ICoreWebView2ExperimentalEnvironment3 interface will also
177+
/// implement ICoreWebView2Environment.
178+
[uuid(9A2BE885-7F0B-4B26-B6DD-C969BAA00BF1), object, pointer_default(unique)]
179+
interface ICoreWebView2ExperimentalEnvironment3 : IUnknown {
180+
/// Try to update the installed Microsoft Edge WebView2 Runtime.
181+
/// This will potentially result in a new version of the Edge WebView2
182+
/// Runtime being installed and `NewBrowserVersionAvailable` event being raised.
183+
/// There is no guarantee on the order of that event being raised and
184+
/// UpdateRuntime's completed handler being invoked. Besides the
185+
/// `NewBrowserVersionAvailable` event, there will be no impact to any
186+
/// currently running WebView2s when the update is installed.
187+
/// Even though the Edge WebView2 Runtime update is installed for the machine
188+
/// and available to all users, the update will happen silently and not show
189+
/// elevation prompt.
190+
/// This will not impact Edge browser installations.
191+
/// The latest version can always be queried using the
192+
/// `GetAvailableCoreWebView2BrowserVersionString` API.
193+
/// The UpdateRuntime method is only supported for an installed Edge WebView2
194+
/// Runtime. When running a fixed version Edge WebView2 Runtime or non stable
195+
/// channel Edge browser, this API will return `HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)`.
196+
/// There could only be one active UpdateRuntime operation in an app process,
197+
/// and calling this API before the completed handler for a previous call is invoked
198+
/// will fail with `HRESULT_FROM_WIN32(ERROR_BUSY)`.
199+
/// Calling this API repeatedly in a short period of time, will also fail with
200+
/// `HRESULT_FROM_WIN32(ERROR_BUSY)`. To protect accidental abuse of the update
201+
/// service, the implementation throttles the calls of this API to 3 times within
202+
/// 5 minutes in a process. The exact throttling limit can change in the future.
203+
/// Edge update service can only support one update request at a time globally.
204+
/// If there is already an update operation running in the Edge update service,
205+
// UpdateRuntime request will result in the completed handler being invoked with a
206+
/// result that has `Status` of `COREWEBVIEW2_UPDATE_RUNTIME_STATUS_UPDATE_ALREADY_RUNNING`.
207+
/// As the running update could succeed or fail, the app should retry later if
208+
/// `NewBrowserVersionAvailable` event has not been raised.
209+
/// The UpdateRuntime operation is associated with the CoreWebView2Environment
210+
/// object and any ongoing UpdateRuntime operation will be aborted when the
211+
/// associated CoreWebView2Environment along with the CoreWebView2 objects that
212+
/// are created by the CoreWebView2Environment object are all released. In this
213+
/// case, the completed handler will be invoked with `S_OK` as `errorCode` and a
214+
/// result object with `Status` of COREWEBVIEW2_UPDATE_RUNTIME_STATUS_FAILED and
215+
/// `ExtendedError` as `E_ABORT`.
216+
///
217+
/// \snippet AppWindow.cpp UpdateRuntime
218+
HRESULT UpdateRuntime(
219+
[in] ICoreWebView2ExperimentalUpdateRuntimeCompletedHandler* handler);
220+
}
221+
```
222+
## WinRT
223+
```c#
224+
namespace Microsoft.Web.WebView2.Core
225+
{
226+
public enum CoreWebView2UpdateRuntimeStatus
227+
{
228+
LatestVersionInstalled = 0,
229+
UpdateAlreadyRunning = 1,
230+
BlockedByPolicy = 2,
231+
Failed = 3,
232+
}
233+
234+
public partial class CoreWebView2UpdateRuntimeResult
235+
{
236+
public CoreWebView2UpdateRuntimeStatus Status
237+
{
238+
get;
239+
}
240+
public Windows.Foundation.HResult ExtendedError
241+
{
242+
get;
243+
}
244+
}
245+
246+
public partial class CoreWebView2Environment
247+
{
248+
public async Task<CoreWebView2UpdateRuntimeResult> UpdateRuntimeAsync()
249+
}
250+
}
251+
```
252+
## .NET
253+
```c#
254+
namespace Microsoft.Web.WebView2.Core
255+
{
256+
public enum CoreWebView2UpdateRuntimeStatus
257+
{
258+
LatestVersionInstalled = 0,
259+
UpdateAlreadyRunning = 1,
260+
BlockedByPolicy = 2,
261+
Failed = 3,
262+
}
263+
264+
public partial class CoreWebView2UpdateRuntimeResult
265+
{
266+
public CoreWebView2UpdateRuntimeStatus Status
267+
{
268+
get;
269+
}
270+
public int ExtendedError
271+
{
272+
get;
273+
}
274+
}
275+
276+
public partial class CoreWebView2Environment
277+
{
278+
public async Task<CoreWebView2UpdateRuntimeResult> UpdateRuntimeAsync()
279+
}
280+
}
281+
```

0 commit comments

Comments
 (0)