Skip to content

Commit 10261a1

Browse files
resolving PR comments
1 parent 26f2ecd commit 10261a1

File tree

1 file changed

+105
-46
lines changed

1 file changed

+105
-46
lines changed

specs/ServiceWorkerPostMessageSetting.md

Lines changed: 105 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,23 @@ Service Worker PostMessage Setting
22
===
33
# Background
44

5-
This API provides a setting to expose the webview2 specific JS APIs on service worker script.
5+
This API provides a setting to expose the webview2 specific JS APIs on service
6+
worker script.
67

78
# Description
89

9-
We propose adding the `WebViewScriptApisForServiceWorkerEnabled` setting API to control the exposure of WebView2-specific JavaScript APIs in service worker scripts. When enabled, developers can use WebView2's service worker postmessage APIs to communicate directly between service worker scripts and the WebView2 host.
10+
We propose adding the `AreWebViewScriptApisEnabledForServiceWorkers` setting
11+
API to control the exposure of WebView2-specific JavaScript APIs in service
12+
worker scripts. When enabled, developers can use WebView2's service worker
13+
postmessage APIs to communicate directly between service worker scripts and
14+
the WebView2 host.
1015

11-
Previously, WebView2-specific JavaScript APIs were only exposed to service worker scripts when developers subscribed to the `ServiceWorkerRegistered` event. This approach was unreliable because developers could obtain service worker registrations through the `GetServiceWorkerRegistrations` API and attempt to use service worker postmessage APIs, which would fail since the JavaScript APIs were not exposed.
16+
Previously, WebView2-specific JavaScript APIs were only exposed to service
17+
worker scripts when developers subscribed to the `ServiceWorkerRegistered`
18+
event. This approach was unreliable because developers could obtain service
19+
worker registrations through the `GetServiceWorkerRegistrations` API and
20+
attempt to use service worker postmessage APIs, which would fail since the
21+
JavaScript APIs were not exposed.
1222

1323
# Examples
1424

@@ -40,18 +50,40 @@ void ToggleServiceWorkerJsApiSetting()
4050
CHECK_FAILURE(webViewSettingsStaging->put_IsWebViewScriptApisForServiceWorkerEnabled(!isEnabled));
4151

4252
MessageBox(
43-
nullptr,
53+
reinterpret_cast<HWND>(m_appWindow.Id().Value),
4454
(std::wstring(L"Service Worker JS API setting has been ") +
4555
(!isEnabled ? L"enabled." : L"disabled."))
4656
.c_str(),
4757
L"Service Worker JS API Setting", MB_OK);
4858
}
59+
}
4960

50-
// Navigate to index.html which will register a new service worker and
51-
// check if chrome and webview objects are available in service worker script.
52-
m_sampleUri = m_appWindow->GetLocalUri(L"index.html");
53-
CHECK_FAILURE(m_webView->Navigate(m_sampleUri.c_str()));
61+
void SetupEventsOnServiceWorker(
62+
wil::com_ptr<ICoreWebView2ExperimentalServiceWorker> serviceWorker)
63+
{
64+
serviceWorker->add_WebMessageReceived(
65+
Callback<ICoreWebView2ExperimentalServiceWorkerWebMessageReceivedEventHandler>(
66+
[this](
67+
ICoreWebView2ExperimentalServiceWorker* sender,
68+
ICoreWebView2WebMessageReceivedEventArgs* args) -> HRESULT
69+
{
70+
71+
wil::unique_cotaskmem_string messageRaw;
72+
CHECK_FAILURE(args->TryGetWebMessageAsString(&messageRaw));
73+
std::wstring messageFromWorker = messageRaw.get();
74+
75+
std::wstringstream message{};
76+
message << L"Message: " << std::endl << messageFromWorker << std::endl;
77+
m_appWindow->AsyncMessageBox(message.str(), L"Message from Service Worker");
5478

79+
return S_OK;
80+
})
81+
.Get(),
82+
nullptr);
83+
}
84+
85+
void SetUpEventsAndNavigate()
86+
{
5587
// Setup WebMessageReceived event to receive message from main thread.
5688
m_webView->add_WebMessageReceived(
5789
Callback<ICoreWebView2WebMessageReceivedEventHandler>(
@@ -65,7 +97,7 @@ void ToggleServiceWorkerJsApiSetting()
6597
{
6698
std::wstringstream message{};
6799
message << L"Message: " << std::endl << L"Service Worker Message from Main thread" << std::endl;
68-
m_appWindow->AsyncMessageBox(message.str(), L"Message from Service Worker");
100+
m_appWindow->AsyncMessageBox(message.str(), L"Message from Service Worker (relayed by Main Thread)");
69101
}
70102
return S_OK;
71103
})
@@ -96,10 +128,6 @@ void ToggleServiceWorkerJsApiSetting()
96128

97129
if (serviceWorkerRegistration)
98130
{
99-
wil::unique_cotaskmem_string scopeUri;
100-
CHECK_FAILURE(serviceWorkerRegistration->get_ScopeUri(&scopeUri));
101-
std::wstring scopeUriStr(scopeUri.get());
102-
103131
wil::com_ptr<ICoreWebView2ExperimentalServiceWorker> serviceWorker;
104132
CHECK_FAILURE(
105133
serviceWorkerRegistration->get_ActiveServiceWorker(&serviceWorker));
@@ -135,32 +163,12 @@ void ToggleServiceWorkerJsApiSetting()
135163
})
136164
.Get(),
137165
&m_serviceWorkerRegisteredToken));
138-
}
139166

140-
void SetupEventsOnServiceWorker(
141-
wil::com_ptr<ICoreWebView2ExperimentalServiceWorker> serviceWorker)
142-
{
143-
serviceWorker->add_WebMessageReceived(
144-
Callback<ICoreWebView2ExperimentalServiceWorkerWebMessageReceivedEventHandler>(
145-
[this](
146-
ICoreWebView2ExperimentalServiceWorker* sender,
147-
ICoreWebView2WebMessageReceivedEventArgs* args) -> HRESULT
148-
{
149-
150-
wil::unique_cotaskmem_string messageRaw;
151-
CHECK_FAILURE(args->TryGetWebMessageAsString(&messageRaw));
152-
std::wstring messageFromWorker = messageRaw.get();
153-
154-
std::wstringstream message{};
155-
message << L"Message: " << std::endl << messageFromWorker << std::endl;
156-
m_appWindow->AsyncMessageBox(message.str(), L"Message from Service Worker");
157-
158-
return S_OK;
159-
})
160-
.Get(),
161-
nullptr);
167+
// Navigate to index.html which will register a new service worker and
168+
// check if chrome and webview objects are available in service worker script.
169+
m_sampleUri = m_appWindow->GetLocalUri(L"index.html");
170+
CHECK_FAILURE(m_webView->Navigate(m_sampleUri.c_str()));
162171
}
163-
164172
```
165173
166174
**index.html**:
@@ -232,25 +240,76 @@ private void ToggleServiceWorkerJsApiSetting()
232240
{
233241
// Unregister every service worker so that for all the newly installed service worker
234242
// the new settings can be applied.
235-
webView.CoreWebView2.ExecuteScriptAsync(
243+
_ = await webView.CoreWebView2.ExecuteScriptAsync(
236244
@"navigator.serviceWorker.getRegistrations().then(function(registrations) {
237245
for(let registration of registrations) {
238246
registration.unregister();
239247
}
240248
});");
241249

242250
// Toggle the service worker post message setting.
243-
WebViewSettings.IsWebViewScriptApisForServiceWorkerEnabled = !WebViewSettings.IsWebViewScriptApisForServiceWorkerEnabled;
251+
var settings = webView.CoreWebView2.Settings;
252+
settings.AreWebViewScriptApisEnabledForServiceWorkers = !settings.AreWebViewScriptApisEnabledForServiceWorkers;
244253

245254
MessageBox.Show(this,
246-
$"IsWebViewScriptApisForServiceWorkerEnabled is now set to: {WebViewSettings.IsWebViewScriptApisForServiceWorkerEnabled}",
255+
$"AreWebViewScriptApisEnabledForServiceWorkers is now set to: {settings.AreWebViewScriptApisEnabledForServiceWorkers}",
247256
"Service Worker JS API Setting", MessageBoxButtons.OK, MessageBoxIcon.Information);
257+
}
258+
259+
private void SetupEventsOnServiceWorker(CoreWebView2ServiceWorker serviceWorker)
260+
{
261+
serviceWorker.WebMessageReceived += (sender, args) =>
262+
{
263+
string messageFromWorker = args.TryGetWebMessageAsString();
264+
MessageBox.Show(this, $"Message: \n{messageFromWorker}", "Message from Service Worker");
265+
};
266+
}
267+
268+
private void SetUpEventsAndNavigate()
269+
{
270+
// Setup WebMessageReceived event to receive message from main thread.
271+
webView.CoreWebView2.WebMessageReceived += (sender, args) =>
272+
{
273+
string message = args.TryGetWebMessageAsString();
274+
if (message == "MessageFromMainThread")
275+
{
276+
MessageBox.Show(this,
277+
"Message: \nService Worker Message from Main thread",
278+
"Message from Service Worker (relayed by Main Thread)");
279+
}
280+
};
281+
282+
// Get ServiceWorkerManager from profile and setup events to listen to service worker post messages.
283+
var serviceWorkerManager = webView.CoreWebView2.Profile.ServiceWorkerManager;
284+
285+
serviceWorkerManager.ServiceWorkerRegistered += (sender, args) =>
286+
{
287+
var serviceWorkerRegistration = args.ServiceWorkerRegistration;
288+
289+
if (serviceWorkerRegistration != null)
290+
{
291+
var serviceWorker = serviceWorkerRegistration.ActiveServiceWorker;
292+
293+
if (serviceWorker != null)
294+
{
295+
SetupEventsOnServiceWorker(serviceWorker);
296+
}
297+
else
298+
{
299+
serviceWorkerRegistration.ServiceWorkerActivated += (s, e) =>
300+
{
301+
SetupEventsOnServiceWorker(e.ActiveServiceWorker);
302+
};
303+
}
304+
}
305+
};
248306

249307
// Navigate to index.html which will register a new service worker and
250308
// check if chrome and webview objects are available in service worker script.
251309
sampleUri = GetLocalUri("index.html");
252310
webView.CoreWebView2.Navigate(sampleUri);
253311
}
312+
254313
```
255314

256315
**index.html** and **service_worker.js**: Same as the Win32 C++ example above.
@@ -259,16 +318,16 @@ private void ToggleServiceWorkerJsApiSetting()
259318

260319
## Win32 C++
261320
```cpp
262-
interface ICoreWebView2Settings : IUnknown {
263-
/// Gets the `IsWebViewScriptApisForServiceWorkerEnabled` property.
264-
[propget] HRESULT IsWebViewScriptApisForServiceWorkerEnabled([out, retval] BOOL* value);
321+
interface ICoreWebView2Settings10 : ICoreWebView2Settings9 {
322+
/// Gets the `AreWebViewScriptApisEnabledForServiceWorkers` property.
323+
[propget] HRESULT AreWebViewScriptApisEnabledForServiceWorkers([out, retval] BOOL* value);
265324

266325
/// Enables or disables webview2 specific Service Worker JS APIs in the WebView2.
267326
/// When set to `TRUE`, chrome and webview objects are available in Service Workers .
268327
/// chrome.webview exposes APIs to interact with the WebView from Service Workers.
269328
/// The default value is `FALSE`.
270329
/// When enabled, this setting takes effect for all the newly installed Service Workers.
271-
[propput] HRESULT IsWebViewScriptApisForServiceWorkerEnabled([in] BOOL value)
330+
[propput] HRESULT AreWebViewScriptApisEnabledForServiceWorkers([in] BOOL value)
272331
}
273332

274333
```
@@ -279,9 +338,9 @@ namespace Microsoft.Web.WebView2.Core
279338
{
280339
runtimeclass CoreWebView2Settings
281340
{
282-
[interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2StagingSettings")]
341+
[interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2Settings10")]
283342
{
284-
Boolean IsWebViewScriptApisForServiceWorkerEnabled { get; set; };
343+
Boolean AreWebViewScriptApisEnabledForServiceWorkers { get; set; };
285344
}
286345
}
287346
}

0 commit comments

Comments
 (0)