@@ -6,7 +6,9 @@ This API provides a setting to expose the webview2 specific JS APIs on service w
66
77# Description
88
9- We propose adding ` ServiceWorkerJSAPIsEnabled ` setting API as it allows developers to expose the webview2 specific JS APIs on service worker script. When enabled this would enable the developers to use webview2's service worker postmessage APIs to communicate directly between the service worker script and webview2 host.
9+ We propose adding the ` ServiceWorkerJSAPIsEnabled ` 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+
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.
1012
1113# Examples
1214
@@ -15,43 +17,151 @@ We propose adding `ServiceWorkerJSAPIsEnabled` setting API as it allows develope
1517``` cpp
1618void ToggleServiceWorkerJsApiSetting ()
1719{
18- wil::com_ptr<ICoreWebView2StagingSettings> webviewStagingSettings;
19- webviewStagingSettings = m_settings.try_query<ICoreWebView2StagingSettings>();
20+ // Unregister every service worker so that for all the newly installed service worker
21+ // the new settings can be applied.
22+ m_webView->ExecuteScript(
23+ L"navigator.serviceWorker.getRegistrations().then(function(registrations) {"
24+ L" for(let registration of registrations) {"
25+ L" registration.unregister();"
26+ L" }"
27+ L"});",
28+ nullptr);
29+
30+ wil::com_ptr<ICoreWebView2Settings> webViewSettings;
31+ CHECK_FAILURE (m_webView->get_Settings(&webViewSettings));
32+ auto webViewSettingsStaging =
33+ webViewSettings.try_query<ICoreWebView2StagingSettings >();
2034
21- if (webviewStagingSettings )
35+ if (webViewSettingsStaging )
2236 {
23- BOOL value;
24- webviewStagingSettings->get_IsServiceWorkerJSAPIsEnabled(&value);
25- CHECK_FAILURE (webviewStagingSettings->put_IsServiceWorkerJSAPIsEnabled(!value));
37+ // Toggle the service worker post message setting.
38+ BOOL isEnabled;
39+ CHECK_FAILURE (webViewSettingsStaging->get_IsServiceWorkerJSAPIsEnabled(&isEnabled));
40+ CHECK_FAILURE(webViewSettingsStaging->put_IsServiceWorkerJSAPIsEnabled(!isEnabled));
41+
2642 MessageBox(
2743 nullptr,
2844 (std::wstring(L"Service Worker JS API setting has been ") +
29- (!value ? L"enabled." : L"disabled."))
45+ (!isEnabled ? L"enabled." : L"disabled."))
3046 .c_str(),
3147 L"Service Worker JS API Setting", MB_OK);
3248 }
49+
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()));
3354}
55+
56+ ```
57+
58+ ** index.html** :
59+ ``` html
60+ <!DOCTYPE html>
61+ <html lang =" en" >
62+ <head >
63+ <meta charset =" UTF-8" >
64+ <meta name =" viewport" content =" width=device-width, initial-scale=1.0" >
65+ <title >Service Worker Post Message Setting</title >
66+ <script >
67+ " use strict" ;
68+
69+ // Register the service worker
70+ navigator .serviceWorker .register (" service_worker.js" ).then (function (registration ) {
71+
72+ // Wait for the service worker to be ready
73+ return navigator .serviceWorker .ready ;
74+ }).then (function (registration ) {
75+ const serviceWorker = registration .active ;
76+
77+ // Post a message to the service worker with CHECK_CHROME_WEBVIEW command
78+ if (serviceWorker) {
79+ serviceWorker .postMessage ({command: ' CHECK_CHROME_WEBVIEW' });
80+ console .log (" Message posted to service worker" );
81+ }
82+ }).catch (function (error ) {
83+ console .error (" Service worker registration or messaging failed:" , error);
84+ });
85+
86+ // Listen to messages from the service worker
87+ // Messages sent via event.source.postMessage() are received here
88+ navigator .serviceWorker .addEventListener (' message' , function (event ) {
89+ console .log (" Message received from service worker:" , event .data );
90+
91+ // Display the result in the HTML element
92+ const resultElement = document .getElementById (' result' );
93+ if (event .data === ' chromeWebViewAvailable' ) {
94+ resultElement .textContent = ' chrome.webview is AVAILABLE in Service Worker' ;
95+ resultElement .style .color = ' green' ;
96+ } else if (event .data === ' chromeWebViewNotAvailable' ) {
97+ resultElement .textContent = ' chrome.webview is NOT AVAILABLE in Service Worker' ;
98+ resultElement .style .color = ' red' ;
99+ } else {
100+ resultElement .textContent = ' Received: ' + event .data ;
101+ resultElement .style .color = ' blue' ;
102+ }
103+ });
104+ </script >
105+ </head >
106+ <body >
107+ <h1 >Service Worker Post Message Setting</h1 >
108+ <p >This page registers a service worker, posts a message to it, and listens for responses.</p >
109+ <p >Check the console for debug information.</p >
110+ <div id =" result" style =" font-size : 18px ; font-weight : bold ; margin-top : 20px ; padding : 10px ; border : 2px solid #ccc ; border-radius : 5px ;" >
111+ Waiting for service worker response...
112+ </div >
113+ </body >
114+ </html >
115+ ```
116+
117+ ** service_worker.js**
118+ ``` js
119+ self .addEventListener (' message' , (event ) => {
120+ if (event .data .command === ' CHECK_CHROME_WEBVIEW' ) {
121+ if (self .chrome && self .chrome .webview ) {
122+ event .source .postMessage (' chromeWebViewAvailable' );
123+ } else {
124+ event .source .postMessage (' chromeWebViewNotAvailable' );
125+ }
126+ }
127+ });
34128```
35129
36130## C#/.NET
37131
38132``` c#
39133private void ToggleServiceWorkerJsApiSetting ()
40134{
41- WebViewSettings .IsServiceWorkerJSAPIsEnabled = ! WebViewSettings .AreDefaultScriptDialogsEnabled ;
135+ // Unregister every service worker so that for all the newly installed service worker
136+ // the new settings can be applied.
137+ webView .CoreWebView2 .ExecuteScriptAsync (
138+ @" navigator.serviceWorker.getRegistrations().then(function(registrations) {
139+ for(let registration of registrations) {
140+ registration.unregister();
141+ }
142+ });" );
143+
144+ // Toggle the service worker post message setting.
145+ WebViewSettings .IsServiceWorkerJSAPIsEnabled = ! WebViewSettings .IsServiceWorkerJSAPIsEnabled ;
42146
43147 MessageBox .Show (this ,
44148 $" IsServiceWorkerJSAPIsEnabled is now set to: {WebViewSettings .IsServiceWorkerJSAPIsEnabled }" ,
45- " Trusted Origins" , MessageBoxButtons .OK , MessageBoxIcon .Information );
149+ " Service Worker JS API Setting" , MessageBoxButtons .OK , MessageBoxIcon .Information );
150+
151+ // Navigate to index.html which will register a new service worker and
152+ // check if chrome and webview objects are available in service worker script.
153+ sampleUri = GetLocalUri (" index.html" );
154+ webView .CoreWebView2 .Navigate (sampleUri );
46155}
47156```
48157
158+ ** index.html** and ** service_worker.js** : Same as the Win32 C++ example above.
159+
49160# API Details
50161
51162## Win32 C++
52163``` cpp
53- // / A continuation of the ICoreWebView2Settings interface to manage Service Worker JS APIs.
54- interface ICoreWebView2StagingSettings : IUnknown {
164+ interface ICoreWebView2Settings : IUnknown {
55165 /// Gets the ` IsServiceWorkerJSAPIsEnabled ` property.
56166 [ propget] HRESULT IsServiceWorkerJSAPIsEnabled([ out, retval] BOOL* value);
57167
@@ -60,8 +170,7 @@ interface ICoreWebView2StagingSettings : IUnknown {
60170 /// chrome.webview exposes APIs to interact with the WebView from Service Workers.
61171 /// The default value is ` FALSE ` .
62172 /// When enabled, this setting takes effect for all the newly installed Service Workers.
63- /// \snippet SettingsComponent.cpp ToggleServiceWorkerJSAPIsEnabled
64- [ propput] HRESULT IsServiceWorkerJSAPIsEnabled([ in] BOOL value);
173+ [ propput] HRESULT IsServiceWorkerJSAPIsEnabled([ in] BOOL value)
65174}
66175
67176```
0 commit comments