Skip to content

Commit 6d01248

Browse files
authored
Merge pull request #621 from MicrosoftEdge/freeze-draft
API review for TryFreeze/Unfreeze
2 parents 8dad30f + 728bd3f commit 6d01248

1 file changed

Lines changed: 155 additions & 0 deletions

File tree

specs/Freeze.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Background
2+
Edge browser has a sleeping tab feature which reduces resource usage when the tab is in the background. We are introducing WebView2 APIs
3+
to access this feature so that invisible WebView can use less resources. We'd appreciate your feedback.
4+
5+
6+
# Description
7+
You may call the `TryFeezeAsync` API to have the WebView2 consume less memory. This is useful when your Win32 app becomes invisible, or when your Universal Windows Platform app is suspended, during the suspended event handler before completing the suspended event.
8+
9+
# Examples
10+
## .Net, WinRT
11+
```c#
12+
async protected void OnSuspending(object sender, SuspendingEventArgs args)
13+
{
14+
SuspendingDeferral deferral = args.SuspendingOperation.GetDeferral();
15+
// Set webView.Visibility to false first.
16+
// WebView2 must be invisible for TryFreezeAsync to succeed.
17+
webView.Visibility = false;
18+
await webView.CoreWebView2.TryFreezeAsync();
19+
deferral.Complete();
20+
}
21+
async protected void OnSuspending(object sender, Object args)
22+
{
23+
// Making a WebView2 visible will automatically unfreeze it
24+
// But you can also explicitly call Unfreeze without making a WebView2 visible to unfreeze it.
25+
webView.CoreWebView2.Unfreeze();
26+
webView.Visibility = true;
27+
}
28+
```
29+
## Win32 C++
30+
As unfreeze is very fast and automatically happens when WebView becomes visible, the app can generaly immediately call `TryFreeze` when a WebView becomes invisible.
31+
```cpp
32+
bool ViewComponent::HandleWindowMessage(
33+
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT* result)
34+
{
35+
if (message == WM_SYSCOMMAND)
36+
{
37+
if (wParam == SC_MINIMIZE)
38+
{
39+
// Hide the webview when the app window is minimized, and freeze it.
40+
m_controller->put_IsVisible(FALSE);
41+
Freeze();
42+
}
43+
else if (wParam == SC_RESTORE)
44+
{
45+
// When the app window is restored, show the webview
46+
// (unless the user has toggle visibility off).
47+
if (m_isVisible)
48+
{
49+
Unfreeze();
50+
m_controller->put_IsVisible(TRUE);
51+
}
52+
}
53+
}
54+
}
55+
56+
void ViewComponent::Freeze()
57+
{
58+
HRESULT hr = webView->TryFreeze(
59+
Callback<ICoreWebView2StagingTryFreezeCompletedHandler>(
60+
[](HRESULT errorCode, BOOL isSuccessful) -> HRESULT {
61+
std::wstringstream formattedMessage;
62+
formattedMessage << "TryFreeze result (0x" << std::hex << errorCode
63+
<< ") " << (isSuccessful ? "succeeded" : "failed");
64+
MessageBox(nullptr, formattedMessage.str().c_str(), nullptr, MB_OK);
65+
return S_OK;
66+
})
67+
.Get());
68+
if (FAILED(hr))
69+
ShowFailure(hr, L"Call to TryFreeze failed");
70+
}
71+
72+
void ViewComponent::Unfreeze()
73+
{
74+
wil::com_ptr<ICoreWebView2Staging2> webView;
75+
webView = m_webView.query<ICoreWebView2Staging2>();
76+
webView->Unfreeze();
77+
}
78+
```
79+
80+
# Remarks
81+
The CoreWebView2Controller must be invisible when the API is called. Otherwise, the
82+
API fails with `HRESULT_FROM_WIN32(ERROR_INVALID_STATE)`.
83+
Freezing is similar to putting a tab to sleep in the Edge browser. Freezing pauses
84+
WebView script timers and animations, minimizes CPU usage for the associated
85+
browser renderer process and allows the operating system to reuse the memory that was
86+
used by the renderer process for other processes.
87+
Note that the freeze is best effort and considered completed successfully once the request
88+
is sent to browser renderer process. If there is a running script, the script will continue
89+
to run and the renderer process will be frozen after that script is done.
90+
See [Sleeping Tabs FAQ](https://techcommunity.microsoft.com/t5/articles/sleeping-tabs-faq/m-p/1705434)
91+
for conditions that might prevent WebView from being frozen. In those situations,
92+
The TryFreeze operation will fail and the completed handler will be invoked with isSuccessful as false.
93+
The WebView will be automatically unfrozen when it becomes visible. Therefore, the app normally doesn't have to call Unfreeze.
94+
The app can call `Unfreeze` and then `TryFreeze` periodically for an invisibile WebView so that the invisible WebView can sync up with
95+
latest data and the page ready to show fresh content when it becomes visible.
96+
97+
# API Notes
98+
See [API Details](#api-details) section below for API reference.
99+
100+
# API Details
101+
102+
## Win32 C++
103+
```IDL
104+
interface ICoreWebView2_2 : ICoreWebView2 {
105+
106+
/// An app may call the `TryFeezeAsync` API to have the WebView2 consume less memory.
107+
/// This is useful when a Win32 app becomes invisible, or when a Universal Windows
108+
/// Platform app is suspended, during the suspended event handler before completing
109+
/// the suspended event.
110+
/// The CoreWebView2Controller must be invisible when the API is called. Otherwise, the
111+
/// API fails with `HRESULT_FROM_WIN32(ERROR_INVALID_STATE)`.
112+
/// Freezing is similar to putting a tab to sleep in the Edge browser. Freezing pauses
113+
/// WebView script timers and animations, minimizes CPU usage for the associated
114+
/// browser renderer process and allows the operating system to reuse the memory that was
115+
/// used by the renderer process for other processes.
116+
/// Note that the freeze is best effort and considered completed successfully once the request
117+
/// is sent to browser renderer process. If there is a running script, the script will continue
118+
/// to run and the renderer process will be frozen after that script is done.
119+
/// See [Sleeping Tabs FAQ](https://techcommunity.microsoft.com/t5/articles/sleeping-tabs-faq/m-p/1705434)
120+
/// for conditions that might prevent WebView from being frozen. In those situations,
121+
/// The TryFreeze operation will fail and the completed handler will be invoked with isSuccessful as false.
122+
/// The WebView will be automatically unfrozen when it becomes visible. Therefore, the
123+
/// app normally doesn't have to call Unfreeze.
124+
/// The app can call `Unfreeze` and then `TryFreeze` periodically for an invisibile WebView so that
125+
/// the invisible WebView can sync up with latest data and the page ready to show fresh content
126+
/// when it becomes visible.
127+
HRESULT TryFreeze([in] ICoreWebView2StagingTryFreezeCompletedHandler* handler);
128+
129+
/// Unfreeze the WebView so that it would resume activities on the web page.
130+
/// This API can be called while the WebView2 controller is invisible.
131+
/// The app can interact with the WebView immediately after unfreeze.
132+
/// WebView will be automatically unfrozen when it becomes visible.
133+
HRESULT Unfreeze();
134+
}
135+
136+
/// The caller implements this interface to receive the TryFreeze result.
137+
[uuid(00F206A7-9D17-4605-91F6-4E8E4DE192E3), object, pointer_default(unique)]
138+
interface ICoreWebView2StagingTryFreezeCompletedHandler : IUnknown {
139+
140+
HRESULT Invoke([in] HRESULT errorCode, [in] BOOL isSuccessful);
141+
142+
}
143+
```
144+
## .Net WinRT
145+
```c#
146+
namespace Microsoft.Web.WebView2.Core
147+
{
148+
public partial class CoreWebView2
149+
{
150+
// There are other API in this interface that we are not showing
151+
public Task<bool> TryFreezeAsync();
152+
public void Unfreeze();
153+
}
154+
}
155+
```

0 commit comments

Comments
 (0)