From f72a3a10295a4cbacddc2fffa12bf082ca156e84 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 7 May 2024 15:58:34 -0700 Subject: [PATCH 01/17] Add Periodic Background Sync and Background Sync API --- .../PeriodicBackgoundSyncAndBackgroundSync.md | 545 ++++++++++++++++++ 1 file changed, 545 insertions(+) create mode 100644 specs/PeriodicBackgoundSyncAndBackgroundSync.md diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md new file mode 100644 index 000000000..f44f80470 --- /dev/null +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -0,0 +1,545 @@ +Periodic Background Synchronization and Background Synchronization APIs +=== + +# Background +There're WebView2 customers who want to run tasks in the background at +periodic intervals for purposes such as updating code, caching data, +and pre-loading resources. Based on that, the WebView2 team is adding +support for [Periodic_Background_Synchronization](https://developer.mozilla.org/docs/Web/API/Web_Periodic_Background_Synchronization_API). +In the meanwhile, the WebView2 team is also adding support for +[Background_Synchronization](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API) +which enhances the offline experience for web applications. + +Unlike [Progressive Web App](https://learn.microsoft.com/microsoft-edge/progressive-web-apps-chromium/how-to/background-syncs#use-the-periodic-background-sync-api-to-regularly-get-fresh-content) +which passively run periodic background tasks based on the browser's +heuristic, WebView2 exposes an API to give developers complete control +over how to run a periodic background synchronization task. + +# Description +We propose following APIs: + +**SyncRegistrationManager API**: This API gives developers the ability +to manage the periodic background synchronizations and background sync +synchronizations in that service worker. + +**PeriodicSyncRegistered API**: This API gives developers the ability +to subscribe to the event when a new Periodic Background synchronization +task is registered. + +**BackgroundSyncRegistered API**: This API gives developers the ability +to subscribe to the event when a new Background synchronization task is +registered. + +**GetSyncRegistrations API**: This asynchronous call returns the +collection of all periodic background synchronization registrations or +background synchronization registrations based on the +`CoreWebView2ServiceWorkerSynchronizationKind` provided. We add +`CoreWebView2ServiceWorkerSyncRegistrationInfo` with `Tag` and +`MinInterval` properties to represent a synchronization registration. + +**DispatchPeriodicSyncEvent API**: This API gives developers the ability +to trigger a periodic background synchronization task based on the +tag name. Developers can use native OS timer to implement a scheduler +to trigger periodic synchronization task according to their own logic. + +# API Details +## C++ +``` +/// Indicates the service worker background synchronization type. +[v1_enum] +typedef enum COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND { + /// Indicates that the synchronization is a background synchronization. + /// See [Background Synchronization](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API) + /// for more information. + COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND_BACKGROUND_SYNC, + /// Indicates that the synchronization is a periodic background synchronization. + /// See [Periodic Background Synchronization](https://developer.mozilla.org/docs/Web/API/Web_Periodic_Background_Synchronization_API) + /// for more information. + COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND_PERIODIC_SYNC, +} COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND; + +/// This is the ICoreWebView2ServiceWorkerRegistration interface. +[uuid(08a80c87-d2b7-5163-bce3-4a28cfed142d), object, pointer_default(unique)] +interface ICoreWebView2ServiceWorkerRegistration : IUnknown { + /// Get the synchronization task registration manager for the service worker. + /// See ICoreWebView2ServiceWorkerSyncRegistrationManager. + /// + /// \snippet ScenarioWebView2ServiceWorkerSyncRegistrationManager.cpp SyncRegistrationManager + /// + [propget] HRESULT SyncRegistrationManager([out, retval] ICoreWebView2ServiceWorkerSyncRegistrationManager** value); +} + +/// This is the ICoreWebView2ServiceWorkerSyncRegistrationManager interface for the +/// Service Worker Periodic Background Synchronization and Background Synchronization +/// registration management APIs. +interface ICoreWebView2ServiceWorkerSyncRegistrationManager : IUnknown { + /// Add an event handler for the `BackgroundSyncRegistered` event. + /// + /// \snippet ScenarioSyncRegistrationManager.cpp BackgroundSyncRegistered + /// + HRESULT add_BackgroundSyncRegistered( + [in] ICoreWebView2SyncRegisteredEventHandler* eventHandler, + [out] EventRegistrationToken* token); + + /// Removes an event handler previously added with `add_BackgroundSyncRegistered`. + HRESULT remove_BackgroundSyncRegistered( + [in] EventRegistrationToken token); + + /// Add an event handler for the `PeriodicSyncRegistered` event. + /// + /// \snippet ScenarioServiceWorkerSyncRegistrationManager.cpp PeriodicSyncRegistered + /// + HRESULT add_PeriodicSyncRegistered( + [in] ICoreWebView2SyncRegisteredEventHandler* eventHandler, + [out] EventRegistrationToken* token); + + /// Removes an event handler previously added with `add_PeriodicSyncRegistered`. + HRESULT remove_PeriodicSyncRegistered( + [in] EventRegistrationToken token); + + /// Gets all background synchronization or periodic background synchronization + /// registrations. + HRESULT GetSyncRegistrations( + [in] COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND kind + , [in] ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler* handler + ); +} + +/// Event args for the `PeriodicSyncRegistered` event or the `BackgroundSyncRegistered` event. +[uuid(ff0810cc-a7aa-5149-88cb-2a342233d7bf), object, pointer_default(unique)] +interface ICoreWebView2ServiceWorkerSyncRegisteredEventArgs : IUnknown { + /// The background synchronization task or periodic background synchronization task registration info. + /// + /// See `ICoreWebView2ServiceWorkerSyncRegistrationInfo` for details on synchronization task registration + /// properties. + /// + [propget] HRESULT RegistrationInfo([out, retval] ICoreWebView2ServiceWorkerSyncRegistrationInfo** value); +} + +/// Provides a set of properties for a service worker synchronization registration. +[uuid(8ab3dbf2-9207-5231-9241-167e96d8cf56), object, pointer_default(unique)] +interface ICoreWebView2ServiceWorkerSyncRegistrationInfo : IUnknown { + /// The minimum interval time, in milliseconds, at which the minimum time + /// interval between periodic background synchronizations should occur. + /// You should not call `CoreWebView2ServiceWorkerSyncRegistrationManager.DispatchPeriodicSyncEventAsync` + /// to dispatch periodic synchronization tasks less than its minimum time interval. + /// This property is always returns an invalid value `-1` for the background synchronization registration. + /// + [propget] HRESULT MinInterval([out, retval] INT64* value); + + /// A string representing an unique identifier for the synchronization event. + /// + /// The caller must free the returned string with `CoTaskMemFree`. See + /// [API Conventions](/microsoft-edge/webview2/concepts/win32-api-conventions#strings). + [propget] HRESULT Tag([out, retval] LPWSTR* value); +} + +/// A collection of ICoreWebView2ServiceWorkerSyncRegistrationInfo. +[uuid(2fc909da-5cc2-548d-bb54-6b6ac4cb36dd), object, pointer_default(unique)] +interface ICoreWebView2ServiceWorkerSyncRegistrationInfoCollectionView : IUnknown { + /// Gets the number of synchronization task registration information contained in the collection. + /// + [propget] HRESULT Count([out, retval] UINT32* value); + + /// Gets the synchronization task registration information at the specified index. + /// + HRESULT GetValueAtIndex( + [in] UINT32 index + , [out, retval] ICoreWebView2ServiceWorkerSyncRegistrationInfo** value + ); +} + +/// Receives the result of the `GetSyncRegistrations` method. +[uuid(f0ab53ac-75dd-5fb0-a2a6-aa5ca88e88fb), object, pointer_default(unique)] +interface ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler : IUnknown { + /// Provides the result of the corresponding asynchronous method. + HRESULT Invoke([in] HRESULT errorCode, [in] ICoreWebView2ServiceWorkerSyncRegistrationInfoCollectionView* result); +} + +/// Receives `PeriodicSyncRegistered` or `BackgroundSyncRegistered` events. +[uuid(551ce0e3-bef4-559b-b962-d94069b7df67), object, pointer_default(unique)] +interface ICoreWebView2SyncRegisteredEventHandler : IUnknown { + /// Provides the event args for the corresponding event. + HRESULT Invoke( + [in] ICoreWebView2ServiceWorkerSyncRegistrationManager* sender, + [in] ICoreWebView2ServiceWorkerSyncRegisteredEventArgs* args); +} + +/// This is the ICoreWebView2ServiceWorker interface. +[uuid(feb08591-560a-5102-ab1b-26435eb261b3), object, pointer_default(unique)] +interface ICoreWebView2ServiceWorker : IUnknown { + /// Dispatches periodic background synchronization task. + /// Noted that WebView2 does not automatically dispatch periodic synchronization + /// tasks. You have the flexibility to manually execute specific periodic + /// background synchronization tasks using your own heuristic approach, + /// leveraging the support of OS timer APIs. There're different ways to implement + /// the timer to call the WebView2 API when needed. + /// + /// You can use [chrono](https://learn.microsoft.com/cpp/standard-library/chrono) + /// library and [thread](https://learn.microsoft.com/cpp/standard-library/thread-class) + /// library to call the periodic synchronization task periodically. + /// + HRESULT DispatchPeriodicSyncEvent( + [in] LPCWSTR tag + , [in] ICoreWebView2ServiceWorkerDispatchPeriodicSyncEventCompletedHandler* handler + ); +} + +/// Receives the result of the `DispatchPeriodicSyncEvent` method. +[uuid(86815a3e-ebc8-58b0-84ce-069d15d67d38), object, pointer_default(unique)] +interface ICoreWebView2ServiceWorkerDispatchPeriodicSyncEventCompletedHandler : IUnknown { + /// Provides the result of the corresponding asynchronous method. + HRESULT Invoke([in] HRESULT errorCode, [in] BOOL result); +} +``` + +C# +```c# +namespace Microsoft.Web.WebView2.Core +{ + runtimeclass CoreWebView2ServiceWorkerRegistration + { + CoreWebView2ServiceWorkerSyncRegistrationManager SyncRegistrationManager { get; }; + } + + runtimeclass CoreWebView2ServiceWorkerSyncRegistrationManager + { + + event Windows.Foundation.TypedEventHandler BackgroundSyncRegistered; + + event Windows.Foundation.TypedEventHandler PeriodicSyncRegistered; + + Windows.Foundation.IAsyncOperation> GetSyncRegistrationsAsync(CoreWebView2ServiceWorkerSynchronizationKind Kind); + + Windows.Foundation.IAsyncOperation DispatchPeriodicSyncEventAsync(String Tag); + } +} +``` + + +# Examples +### C++ Sample +```cpp +static constexpr WCHAR c_samplePath[] = L"ScenarioServiceWorkerSyncRegistrationManager.html"; + +ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrationManager( + AppWindow* appWindow) + : m_appWindow(appWindow), m_webView(appWindow->GetWebView()) +{ + m_sampleUri = m_appWindow->GetLocalUri(c_samplePath); + + auto webView2_13 = m_webView.try_query(); + CHECK_FEATURE_RETURN_EMPTY(webView2_13); + + wil::com_ptr webView2Profile; + CHECK_FAILURE(webView2_13->get_Profile(&webView2Profile)); + auto webViewProfile3 = webView2Profile.try_query(); + CHECK_FEATURE_RETURN_EMPTY(webViewProfile3); + wil::com_ptr serviceWorkerManager; + CHECK_FAILURE(webViewProfile3->get_ServiceWorkerManager(&serviceWorkerManager)); + + if (serviceWorkerManager) + { + CHECK_FAILURE(serviceWorkerManager->GetServiceWorkerRegistration( + m_appWindow->GetLocalUri(L"").c_str(), + Callback( + [this]( + HRESULT error, + ICoreWebView2ServiceWorkerRegistration* serviceWorkerRegistration) + -> HRESULT + { + if (serviceWorkerRegistration) + { + serviceWorkerRegistration->QueryInterface( + IID_PPV_ARGS(&m_serviceWorkerRegistration)); + //! [SyncRegistrationManager] + CHECK_FAILURE(serviceWorkerRegistration->get_SyncRegistrationManager( + &m_syncRegistrationManager)); + if (m_syncRegistrationManager) + { + //! [BackgroundSyncRegistered] + CHECK_FAILURE(m_syncRegistrationManager->add_BackgroundSyncRegistered( + Microsoft::WRL::Callback< + ICoreWebView2SyncRegisteredEventHandler>( + [this]( + ICoreWebView2ServiceWorkerSyncRegistrationManager* + sender, + ICoreWebView2ServiceWorkerSyncRegisteredEventArgs* + args) + { + wil::com_ptr< + ICoreWebView2ServiceWorkerSyncRegistrationInfo> + syncRegistrationInfo; + CHECK_FAILURE( + args->get_RegistrationInfo(&syncRegistrationInfo)); + std::wstringstream message; + AppendSyncRegistrationInfo( + syncRegistrationInfo, false, message); + m_appWindow->AsyncMessageBox( + message.str(), L"Background Sync"); + + return S_OK; + }) + .Get(), + &m_backgroundSyncRegisteredToken)); + //! [BackgroundSyncRegistered] + //! [PeriodicSyncRegistered] + CHECK_FAILURE(m_syncRegistrationManager->add_PeriodicSyncRegistered( + Microsoft::WRL::Callback< + ICoreWebView2SyncRegisteredEventHandler>( + [this]( + ICoreWebView2ServiceWorkerSyncRegistrationManager* + sender, + ICoreWebView2ServiceWorkerSyncRegisteredEventArgs* + args) + { + wil::com_ptr< + ICoreWebView2ServiceWorkerSyncRegistrationInfo> + syncRegistrationInfo; + CHECK_FAILURE( + args->get_RegistrationInfo(&syncRegistrationInfo)); + std::wstringstream message; + AppendSyncRegistrationInfo( + syncRegistrationInfo, true, message); + m_appWindow->AsyncMessageBox( + message.str(), L"Periodic Background Sync"); + return S_OK; + }) + .Get(), + &m_periodicSyncRegisteredToken)); + //! [PeriodicSyncRegistered] + } + //! [SyncRegistrationManager] + } + return S_OK; + }) + .Get())); + } + + // Receive dispatch periodic sync task request + CHECK_FAILURE(m_webView->add_WebMessageReceived( + Callback( + [this](ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args) + -> HRESULT + { + wil::unique_cotaskmem_string source; + CHECK_FAILURE(args->get_Source(&source)); + wil::unique_cotaskmem_string webMessageAsString; + if (SUCCEEDED(args->TryGetWebMessageAsString(&webMessageAsString))) + { + if (wcscmp(source.get(), m_sampleUri.c_str()) == 0) + { + std::wstring message = webMessageAsString.get(); + if (message.compare(0, 26, L"DispatchPeriodicSyncEvent ") == 0) + { + DispatchPeriodicBackgroundSyncTask(message.substr(26).c_str()); + } + else if (wcscmp(message.c_str(), L"GetPeriodicSyncRegistrations") == 0) + { + ShowAllSyncRegistrationInfos(COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND_PERIODIC_SYNC); + } + else if ( + wcscmp(message.c_str(), L"GetBackgroundSyncRegistrations") == 0) + { + ShowAllSyncRegistrationInfos(COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND_BACKGROUND_SYNC); + } + } + } + return S_OK; + }) + .Get(), + nullptr)); + + CHECK_FAILURE(m_webView->Navigate(m_sampleUri.c_str())); +} + +void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyncTask( + const std::wstring& tag) +{ + if (m_serviceWorkerRegistration) + { + CHECK_FAILURE(m_serviceWorkerRegistration->GetServiceWorker( + Callback( + [this, &tag]( + HRESULT error, ICoreWebView2ServiceWorker* serviceWorker) -> HRESULT + { + wil::com_ptr worker; + wil::unique_cotaskmem_string scriptUrl; + std::wstringstream message; + // ![DispatchPeriodicSyncEvent] + if (serviceWorker != nullptr) + { + CHECK_FAILURE(serviceWorker->DispatchPeriodicSyncEvent( + tag.c_str(), + Microsoft::WRL::Callback< + ICoreWebView2ServiceWorkerDispatchPeriodicSyncEventCompletedHandler>( + [this](HRESULT errorCode, BOOL isSuccessful) -> HRESULT + { + CHECK_FAILURE(errorCode); + m_appWindow->AsyncMessageBox( + (isSuccessful) ? L"Dispatch Periodic Sync task success" + : L"Dispatch Periodic Sync task failed", + L"Dispatch periodic sync task Completed"); + return S_OK; + }) + .Get())); + } + return S_OK; + // ![DispatchPeriodicSyncEvent] + }) + .Get())); + } +} + +void ScenarioServiceWorkerSyncRegistrationManager::ShowAllSyncRegistrationInfos( + const COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND kind) +{ + if (m_syncRegistrationManager) + { + //! [GetSyncRegistrations] + CHECK_FAILURE(m_syncRegistrationManager->GetSyncRegistrations( + kind, + Callback< + ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler>( + [this]( + HRESULT error, + ICoreWebView2ServiceWorkerSyncRegistrationInfoCollectionView* + collectionView) -> HRESULT + { + UINT32 count; + collectionView->get_Count(&count); + bool isPeriodicSync = + COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND_PERIODIC_SYNC ? true + : false; + for (UINT32 i = 0; i < count; i++) + { + wil::com_ptr + registrationInfo; + CHECK_FAILURE(collectionView->GetValueAtIndex(i, ®istrationInfo)); + std::wstringstream message; + AppendSyncRegistrationInfo(registrationInfo, isPeriodicSync, message); + message << L"\n"; + m_appWindow->AsyncMessageBox( + std::move(message.str()), isPeriodicSync + ? L"Periodic Sync Registrations" + : L"Background Sync Registrations"); + } + return S_OK; + }) + .Get())); + //! [GetSyncRegistrations] + } +} + +void ScenarioServiceWorkerSyncRegistrationManager::AppendSyncRegistrationInfo( + wil::com_ptr syncRegistrationInfo, + bool isPeriodicSync, std::wstringstream& message) +{ + if (syncRegistrationInfo) + { + wil::unique_cotaskmem_string tag; + CHECK_FAILURE(syncRegistrationInfo->get_Tag(&tag)); + message << L" Tag: " << tag.get(); + if (isPeriodicSync) + { + INT64 minInterval = 0; + CHECK_FAILURE(syncRegistrationInfo->get_MinInterval(&minInterval)); + message << L" MinInterval: " << minInterval; + } + } +} +``` +### C# Sample +```c# +CoreWebView2ServiceWorkerSyncRegistrationManager syncRegistrationManager_; +CoreWebView2ServiceWorkerRegistration serviceWorkerRegistration_; +async void ServiceWorkerSyncManagerExecuted(object target, ExecutedRoutedEventArgs e) +{ + webView.Source = new Uri("https://appassets.example/ScenarioServiceWorkerSyncRegistrationManager.html"); + webView.CoreWebView2.WebMessageReceived += ServiceWorkerSyncEvent_WebMessageReceived; + + CoreWebView2Profile WebViewProfile = webView.CoreWebView2.Profile; + CoreWebView2ServiceWorkerManager ServiceWorkerManager = WebViewProfile.ServiceWorkerManager; + if (ServiceWorkerManager != null) { + serviceWorkerRegistration_ = + await ServiceWorkerManager.GetServiceWorkerRegistrationAsync("https://appassets.example.com"); + if (serviceWorkerRegistration_ != null) { + syncRegistrationManager_ = serviceWorkerRegistration_.SyncRegistrationManager; + if (syncRegistrationManager_ != null) + { + try + { + syncRegistrationManager_.PeriodicSyncRegistered += (sender, args) => + { + MessageBox.Show($"Periodic Sync Task Tag: {args.RegistrationInfo.Tag}, + MinInterval: {args.RegistrationInfo.MinInterval} registered"); + }; + syncRegistrationManager_.BackgroundSyncRegistered += (sender, args) => + { + MessageBox.Show($"Background Sync Task Tag: {args.RegistrationInfo.Tag} registered"); + }; + } + catch (NotImplementedException exception) + { + MessageBox.Show(this, "ServiceWorkerSyncRegistrationManager Failed: " + exception.Message, + "ServiceWorkerSyncRegistrationManager"); + } + } + } + } +} + +async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs args) +{ + async void ShowServiceWorkerSyncRegistrations(bool isPeriodicSync) + { + if (syncRegistrationManager_) { + IReadOnlyList registrationList = + await syncRegistrationManager_.GetSyncRegistrationsAsync(isPeriodicSync ? + CoreWebView2ServiceWorkerSynchronizationKind.PeriodicSync : + CoreWebView2ServiceWorkerSynchronizationKind.BackgroundSync); + + int registrationCount = registrationList.Count; + StringBuilder messageBuilder = new StringBuilder(); + messageBuilder.AppendLine(isPeriodicSync ? + "No of periodic background sync created: " : + "No of background sync created: "); + messageBuilder.Append($"{registrationCount}"); + + for (int i = 0; i < registrationCount; ++i) + { + var tag = registrationList[i].Tag; + messageBuilder.AppendLine($"Tag: {tag}"); + if (isPeriodicSync) { + var interval = registrationList[i].MinInterval; + messageBuilder.Append($" MinInterval: {interval}"); + } + }; + + MessageBox.Show(messageBuilder.ToString(), isPeriodicSync ? + "Periodic Background Sync Registrations" : + "Background Sync Registrations", MessageBoxButton.OK); + } + } + + if (args.Source != "https://appassets.example/ScenarioServiceWorkerSyncRegistrationManager.html") + { + return; + } + + string message = args.TryGetWebMessageAsString(); + if (message.Contains("DispatchPeriodicSyncEvent")) + { + int msgLength = "DispatchPeriodicSyncEvent".Length; + var tag = message.Substring(msgLength); + CoreWebView2ServiceWorker serviceWorker = await serviceWorkerRegistration_.GetServiceWorkerAsync(); + if (serviceWorker != null) { + await serviceWorker.DispatchPeriodicSyncEventAsync(tag); + } + } else if (message.Contains("GetPeriodicSyncRegistrations")) { + ShowServiceWorkerSyncRegistrations(true); + } else if (message.Contains("GetBackgroundSyncRegistrations")) { + ShowServiceWorkerSyncRegistrations(false); + } +} +``` From c6fbe447ff6980312b95accae41902d56c4e2bdd Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 7 May 2024 16:07:45 -0700 Subject: [PATCH 02/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- specs/PeriodicBackgoundSyncAndBackgroundSync.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index f44f80470..2245e096f 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -3,8 +3,8 @@ Periodic Background Synchronization and Background Synchronization APIs # Background There're WebView2 customers who want to run tasks in the background at -periodic intervals for purposes such as updating code, caching data, -and pre-loading resources. Based on that, the WebView2 team is adding +periodic intervals for purposes such as updating code, caching data, +and pre-loading resources. Based on that, the WebView2 team is adding support for [Periodic_Background_Synchronization](https://developer.mozilla.org/docs/Web/API/Web_Periodic_Background_Synchronization_API). In the meanwhile, the WebView2 team is also adding support for [Background_Synchronization](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API) @@ -18,16 +18,16 @@ over how to run a periodic background synchronization task. # Description We propose following APIs: -**SyncRegistrationManager API**: This API gives developers the ability +**SyncRegistrationManager API**: This API gives developers the ability to manage the periodic background synchronizations and background sync synchronizations in that service worker. -**PeriodicSyncRegistered API**: This API gives developers the ability +**PeriodicSyncRegistered API**: This API gives developers the ability to subscribe to the event when a new Periodic Background synchronization task is registered. **BackgroundSyncRegistered API**: This API gives developers the ability -to subscribe to the event when a new Background synchronization task is +to subscribe to the event when a new Background synchronization task is registered. **GetSyncRegistrations API**: This asynchronous call returns the From 023f6c1ea95d2d392412be2432817bb4cb6c9ccf Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Wed, 8 May 2024 14:34:14 -0700 Subject: [PATCH 03/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- .../PeriodicBackgoundSyncAndBackgroundSync.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index 2245e096f..32fb0eb5d 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -197,11 +197,28 @@ C# ```c# namespace Microsoft.Web.WebView2.Core { + enum CoreWebView2ServiceWorkerSynchronizationKind + { + // Indicates that the synchronization is a background synchronization. + // See [Background Synchronization](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API) + // for more information. + BackgroundSync = 0, + // Indicates that the synchronization is a periodic background synchronization. + // See [Periodic Background Synchronization](https://developer.mozilla.org/docs/Web/API/Web_Periodic_Background_Synchronization_API) + // for more information. + PeriodicSync = 1, + }; + runtimeclass CoreWebView2ServiceWorkerRegistration { CoreWebView2ServiceWorkerSyncRegistrationManager SyncRegistrationManager { get; }; } + runtimeclass CoreWebView2ServiceWorker + { + Windows.Foundation.IAsyncOperation DispatchPeriodicSyncEventAsync(String Tag); + } + runtimeclass CoreWebView2ServiceWorkerSyncRegistrationManager { @@ -210,8 +227,6 @@ namespace Microsoft.Web.WebView2.Core event Windows.Foundation.TypedEventHandler PeriodicSyncRegistered; Windows.Foundation.IAsyncOperation> GetSyncRegistrationsAsync(CoreWebView2ServiceWorkerSynchronizationKind Kind); - - Windows.Foundation.IAsyncOperation DispatchPeriodicSyncEventAsync(String Tag); } } ``` From 410196a7bab585b884c7aa8f2ae0b292ed1a85c2 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Wed, 8 May 2024 14:39:43 -0700 Subject: [PATCH 04/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- specs/PeriodicBackgoundSyncAndBackgroundSync.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index 32fb0eb5d..d2456840f 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -228,6 +228,17 @@ namespace Microsoft.Web.WebView2.Core Windows.Foundation.IAsyncOperation> GetSyncRegistrationsAsync(CoreWebView2ServiceWorkerSynchronizationKind Kind); } + + runtimeclass CoreWebView2ServiceWorkerSyncRegisteredEventArgs + { + CoreWebView2ServiceWorkerSyncRegistrationInfo RegistrationInfo { get; }; + } + + runtimeclass CoreWebView2ServiceWorkerSyncRegistrationInfo + { + Int64 MinInterval { get; }; + String Tag { get; }; + } } ``` From e0f291ae3e332bcbe9b8e74f525b3b35bec43c88 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Wed, 8 May 2024 14:54:29 -0700 Subject: [PATCH 05/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- .../PeriodicBackgoundSyncAndBackgroundSync.md | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index d2456840f..3b0681a2d 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -477,30 +477,32 @@ void ScenarioServiceWorkerSyncRegistrationManager::AppendSyncRegistrationInfo( ``` ### C# Sample ```c# -CoreWebView2ServiceWorkerSyncRegistrationManager syncRegistrationManager_; -CoreWebView2ServiceWorkerRegistration serviceWorkerRegistration_; +CoreWebView2ServiceWorkerSyncRegistrationManager SyncRegistrationManager_; +CoreWebView2ServiceWorkerRegistration ServiceWorkerRegistration_; async void ServiceWorkerSyncManagerExecuted(object target, ExecutedRoutedEventArgs e) { webView.Source = new Uri("https://appassets.example/ScenarioServiceWorkerSyncRegistrationManager.html"); webView.CoreWebView2.WebMessageReceived += ServiceWorkerSyncEvent_WebMessageReceived; - CoreWebView2Profile WebViewProfile = webView.CoreWebView2.Profile; - CoreWebView2ServiceWorkerManager ServiceWorkerManager = WebViewProfile.ServiceWorkerManager; - if (ServiceWorkerManager != null) { - serviceWorkerRegistration_ = - await ServiceWorkerManager.GetServiceWorkerRegistrationAsync("https://appassets.example.com"); - if (serviceWorkerRegistration_ != null) { - syncRegistrationManager_ = serviceWorkerRegistration_.SyncRegistrationManager; - if (syncRegistrationManager_ != null) + CoreWebView2Profile webViewProfile = webView.CoreWebView2.Profile; + CoreWebView2ServiceWorkerManager serviceWorkerManager = webViewProfile.ServiceWorkerManager; + if (serviceWorkerManager != null) + { + ServiceWorkerRegistration_ = + await serviceWorkerManager.GetServiceWorkerRegistrationAsync("https://appassets.example.com"); + if (ServiceWorkerRegistration_ != null) + { + SyncRegistrationManager_ = ServiceWorkerRegistration_.SyncRegistrationManager; + if (SyncRegistrationManager_ != null) { try { - syncRegistrationManager_.PeriodicSyncRegistered += (sender, args) => + SyncRegistrationManager_.PeriodicSyncRegistered += (sender, args) => { MessageBox.Show($"Periodic Sync Task Tag: {args.RegistrationInfo.Tag}, MinInterval: {args.RegistrationInfo.MinInterval} registered"); }; - syncRegistrationManager_.BackgroundSyncRegistered += (sender, args) => + SyncRegistrationManager_.BackgroundSyncRegistered += (sender, args) => { MessageBox.Show($"Background Sync Task Tag: {args.RegistrationInfo.Tag} registered"); }; @@ -519,9 +521,10 @@ async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2 { async void ShowServiceWorkerSyncRegistrations(bool isPeriodicSync) { - if (syncRegistrationManager_) { + if (SyncRegistrationManager_ != null) + { IReadOnlyList registrationList = - await syncRegistrationManager_.GetSyncRegistrationsAsync(isPeriodicSync ? + await SyncRegistrationManager_.GetSyncRegistrationsAsync(isPeriodicSync ? CoreWebView2ServiceWorkerSynchronizationKind.PeriodicSync : CoreWebView2ServiceWorkerSynchronizationKind.BackgroundSync); @@ -556,15 +559,21 @@ async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2 string message = args.TryGetWebMessageAsString(); if (message.Contains("DispatchPeriodicSyncEvent")) { - int msgLength = "DispatchPeriodicSyncEvent".Length; - var tag = message.Substring(msgLength); - CoreWebView2ServiceWorker serviceWorker = await serviceWorkerRegistration_.GetServiceWorkerAsync(); - if (serviceWorker != null) { - await serviceWorker.DispatchPeriodicSyncEventAsync(tag); + if (ServiceWorkerRegistration_ != null) + { + int msgLength = "DispatchPeriodicSyncEvent".Length; + var tag = message.Substring(msgLength); + CoreWebView2ServiceWorker serviceWorker = await ServiceWorkerRegistration_.GetServiceWorkerAsync(); + if (serviceWorker != null) + { + await serviceWorker.DispatchPeriodicSyncEventAsync(tag); + } } - } else if (message.Contains("GetPeriodicSyncRegistrations")) { + } else if (message.Contains("GetPeriodicSyncRegistrations")) + { ShowServiceWorkerSyncRegistrations(true); - } else if (message.Contains("GetBackgroundSyncRegistrations")) { + } else if (message.Contains("GetBackgroundSyncRegistrations")) + { ShowServiceWorkerSyncRegistrations(false); } } From 7990801771869f255e960ce18b5800c7489668fa Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Wed, 8 May 2024 14:56:17 -0700 Subject: [PATCH 06/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- specs/PeriodicBackgoundSyncAndBackgroundSync.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index 3b0681a2d..e4896f41d 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -539,7 +539,8 @@ async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2 { var tag = registrationList[i].Tag; messageBuilder.AppendLine($"Tag: {tag}"); - if (isPeriodicSync) { + if (isPeriodicSync) + { var interval = registrationList[i].MinInterval; messageBuilder.Append($" MinInterval: {interval}"); } From ab4bfb57b49b24632a6d4442e19a4fa186bc596a Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 21 May 2024 16:03:01 -0700 Subject: [PATCH 07/17] Update PeriodicBackgoundSyncAndBackgroundSync.md`` --- .../PeriodicBackgoundSyncAndBackgroundSync.md | 702 +++++++++--------- 1 file changed, 349 insertions(+), 353 deletions(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index e4896f41d..debda2ba2 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -15,12 +15,16 @@ which passively run periodic background tasks based on the browser's heuristic, WebView2 exposes an API to give developers complete control over how to run a periodic background synchronization task. +This API depends on the support of the Service Worker in the WebView2, please see +[Add Workers management APIs](https://github.com/MicrosoftEdge/WebView2Feedback/pull/4540) +for more information. + # Description We propose following APIs: **SyncRegistrationManager API**: This API gives developers the ability to manage the periodic background synchronizations and background sync -synchronizations in that service worker. +synchronizations in a service worker. **PeriodicSyncRegistered API**: This API gives developers the ability to subscribe to the event when a new Periodic Background synchronization @@ -35,28 +39,344 @@ collection of all periodic background synchronization registrations or background synchronization registrations based on the `CoreWebView2ServiceWorkerSynchronizationKind` provided. We add `CoreWebView2ServiceWorkerSyncRegistrationInfo` with `Tag` and -`MinInterval` properties to represent a synchronization registration. +`MinIntervalInMilliseconds` properties to represent a synchronization registration. **DispatchPeriodicSyncEvent API**: This API gives developers the ability to trigger a periodic background synchronization task based on the tag name. Developers can use native OS timer to implement a scheduler to trigger periodic synchronization task according to their own logic. +# Examples +### C++ Sample +```cpp +wil::com_ptr m_webView; +wil::com_ptr m_syncRegistrationManager; +wil::com_ptr m_serviceWorkerRegistration; +wil::com_ptr m_serviceWorker; +EventRegistrationToken m_backgroundSyncRegisteredToken = {}; +EventRegistrationToken m_periodicSyncRegisteredToken = {}; + +static constexpr WCHAR c_samplePath[] = L"ScenarioServiceWorkerSyncRegistrationManager.html"; + +ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrationManager( + AppWindow* appWindow) + : m_appWindow(appWindow), m_webView(appWindow->GetWebView()) +{ + std::wstring sampleUri = m_appWindow->GetLocalUri(c_samplePath); + + auto webView2_13 = m_webView.try_query(); + CHECK_FEATURE_RETURN_EMPTY(webView2_13); + + wil::com_ptr webView2Profile; + CHECK_FAILURE(webView2_13->get_Profile(&webView2Profile)); + auto webViewProfile3 = webView2Profile.try_query(); + CHECK_FEATURE_RETURN_EMPTY(webViewProfile3); + wil::com_ptr serviceWorkerManager; + CHECK_FAILURE(webViewProfile3->get_ServiceWorkerManager(&serviceWorkerManager)); + + + CHECK_FAILURE(serviceWorkerManager->GetServiceWorkerRegistration( + m_appWindow->GetLocalUri(L"").c_str(), + Callback( + [this]( + HRESULT error, + ICoreWebView2ServiceWorkerRegistration* serviceWorkerRegistration) + -> HRESULT + { + if (serviceWorkerRegistration) + { + serviceWorkerRegistration->QueryInterface( + IID_PPV_ARGS(&m_serviceWorkerRegistration)); + + CHECK_FAILURE(m_serviceWorkerRegistration->GetServiceWorker( + Callback( + [this]( + HRESULT error, ICoreWebView2ServiceWorker* serviceWorker) -> HRESULT + { + if (serviceWorker) + { + serviceWorker->QueryInterface(IID_PPV_ARGS(&m_serviceWorker)); + } + return S_OK; + }) + .Get())); + + //! [SyncRegistrationManager] + CHECK_FAILURE(serviceWorkerRegistration->get_SyncRegistrationManager( + &m_syncRegistrationManager)); + //! [BackgroundSyncRegistered] + CHECK_FAILURE(m_syncRegistrationManager->add_BackgroundSyncRegistered( + Microsoft::WRL::Callback< + ICoreWebView2SyncRegisteredEventHandler>( + [this]( + ICoreWebView2ServiceWorkerSyncRegistrationManager* + sender, + ICoreWebView2ServiceWorkerSyncRegisteredEventArgs* + args) + { + wil::com_ptr< + ICoreWebView2ServiceWorkerSyncRegistrationInfo> + syncRegistrationInfo; + CHECK_FAILURE( + args->get_RegistrationInfo(&syncRegistrationInfo)); + std::wstringstream message; + AppendSyncRegistrationInfo( + syncRegistrationInfo, false, message); + m_appWindow->AsyncMessageBox( + message.str(), L"Background Sync"); + + return S_OK; + }) + .Get(), + &m_backgroundSyncRegisteredToken)); + //! [BackgroundSyncRegistered] + //! [PeriodicSyncRegistered] + CHECK_FAILURE(m_syncRegistrationManager->add_PeriodicSyncRegistered( + Microsoft::WRL::Callback< + ICoreWebView2SyncRegisteredEventHandler>( + [this]( + ICoreWebView2ServiceWorkerSyncRegistrationManager* + sender, + ICoreWebView2ServiceWorkerSyncRegisteredEventArgs* + args) + { + wil::com_ptr< + ICoreWebView2ServiceWorkerSyncRegistrationInfo> + syncRegistrationInfo; + CHECK_FAILURE( + args->get_RegistrationInfo(&syncRegistrationInfo)); + std::wstringstream message; + AppendSyncRegistrationInfo( + syncRegistrationInfo, true, message); + m_appWindow->AsyncMessageBox( + message.str(), L"Periodic Background Sync"); + return S_OK; + }) + .Get(), + &m_periodicSyncRegisteredToken)); + //! [PeriodicSyncRegistered] + } + //! [SyncRegistrationManager] + return S_OK; + }) + .Get())); + + + // Receive the message of dispatching all periodic sync tasks from the page, + // `chrome.webview.postMessage(`DispatchAllPeriodicSyncEvents ${times}`)`. + CHECK_FAILURE(m_webView->add_WebMessageReceived( + Callback( + [this, &sampleUri]( + ICoreWebView2* sender, + ICoreWebView2WebMessageReceivedEventArgs* args) + -> HRESULT + { + wil::unique_cotaskmem_string source; + CHECK_FAILURE(args->get_Source(&source)); + wil::unique_cotaskmem_string webMessageAsString; + if (SUCCEEDED(args->TryGetWebMessageAsString(&webMessageAsString))) + { + if (wcscmp(source.get(), sampleUri.c_str()) == 0) + { + std::wstring message = webMessageAsString.get(); + std::wstring targetString = L"DispatchAllPeriodicSyncEvents "; + if (message.compare(0, targetString.size(), targetString) == 0) + { + std::wstring timeString = message.substr(targetString.size().c_str()); + DispatchAllPeriodicBackgroundSyncTasks(std::stoi(timeString)); + } + } + } + return S_OK; + }) + .Get(), + nullptr)); + + CHECK_FAILURE(m_webView->Navigate(sampleUri.c_str())); +} + +void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyncTask( + const std::wstring& tag) +{ + if (m_serviceWorker) + { + // ![DispatchPeriodicSyncEvent] + CHECK_FAILURE(m_serviceWorker->DispatchPeriodicSyncEvent( + tag.c_str(), + Microsoft::WRL::Callback< + ICoreWebView2ServiceWorkerDispatchPeriodicSyncEventCompletedHandler>( + [this](HRESULT errorCode, BOOL isSuccessful) -> HRESULT + { + CHECK_FAILURE(errorCode); + m_appWindow->AsyncMessageBox( + (isSuccessful) ? L"Dispatch Periodic Sync task success" + : L"Dispatch Periodic Sync task failed", + L"Dispatch periodic sync task Completed"); + return S_OK; + }) + .Get())); + // ![DispatchPeriodicSyncEvent] + } +} + +// This method fetches all periodic synchronization tasks in the current service worker, +// and executes each task multiple(time) times with a specified minimum interval(min_interval) +// between consecutive executions. +void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyncTasks( + const int time) +{ + if (m_syncRegistrationManager) + { + //! [GetSyncRegistrations] + CHECK_FAILURE(m_syncRegistrationManager->GetSyncRegistrations( + COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND_PERIODIC_SYNC, + Callback< + ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler>( + [this, time]( + HRESULT error, + ICoreWebView2ServiceWorkerSyncRegistrationInfoCollectionView* + collectionView) -> HRESULT + { + UINT32 count; + collectionView->get_Count(&count); + for (UINT32 i = 0; i < count; i++) + { + wil::com_ptr + registrationInfo; + CHECK_FAILURE(collectionView->GetValueAtIndex(i, ®istrationInfo)); + wil::unique_cotaskmem_string tag; + CHECK_FAILURE(registrationInfo->get_Tag(&tag)); + UINT32 minInterval = 0; + CHECK_FAILURE(registrationInfo->get_MinIntervalInMilliseconds(&minInterval)); + int executeTime = time; + for (int i = 0; i < executeTime; i++) { + DispatchPeriodicBackgroundSyncTask(tag.get()); + // Wait min_interval before triggering the periodic sync task again. + const auto interval = std::chrono::milliseconds(minInterval); + std::this_thread::sleep_for(interval); + } + } + return S_OK; + }) + .Get())); + //! [GetSyncRegistrations] + } +} + +void ScenarioServiceWorkerSyncRegistrationManager::AppendSyncRegistrationInfo( + wil::com_ptr syncRegistrationInfo, + bool isPeriodicSync, std::wstringstream& message) +{ + if (syncRegistrationInfo) + { + wil::unique_cotaskmem_string tag; + CHECK_FAILURE(syncRegistrationInfo->get_Tag(&tag)); + message << L" Tag: " << tag.get(); + if (isPeriodicSync) + { + INT64 minInterval = 0; + CHECK_FAILURE(syncRegistrationInfo->get_MinIntervalInMilliseconds(&minInterval)); + message << L" MinInterval: " << minInterval; + } + } +} +``` +### C# Sample +```c# +CoreWebView2ServiceWorkerSyncRegistrationManager SyncRegistrationManager_; +CoreWebView2ServiceWorkerRegistration ServiceWorkerRegistration_; +CoreWebView2ServiceWorker ServiceWorker_; +async void ServiceWorkerSyncManagerExecuted(object target, ExecutedRoutedEventArgs e) +{ + webView.Source = new Uri("https://appassets.example/ScenarioServiceWorkerSyncRegistrationManager.html"); + webView.CoreWebView2.WebMessageReceived += ServiceWorkerSyncEvent_WebMessageReceived; + + CoreWebView2Profile webViewProfile = webView.CoreWebView2.Profile; + CoreWebView2ServiceWorkerManager serviceWorkerManager = webViewProfile.ServiceWorkerManager; + if (serviceWorkerManager != null) + { + ServiceWorkerRegistration_ = + await serviceWorkerManager.GetServiceWorkerRegistrationAsync("https://appassets.example.com"); + if (ServiceWorkerRegistration_ != null) + { + SyncRegistrationManager_ = ServiceWorkerRegistration_.SyncRegistrationManager; + if (SyncRegistrationManager_ != null) + { + ServiceWorker_ = await ServiceWorkerRegistration_.GetServiceWorkerAsync(); + try + { + SyncRegistrationManager_.PeriodicSyncRegistered += (sender, args) => + { + MessageBox.Show($"Periodic Sync Task Tag: {args.RegistrationInfo.Tag}, + MinInterval: {args.RegistrationInfo.MinIntervalInMilliseconds} registered"); + }; + SyncRegistrationManager_.BackgroundSyncRegistered += (sender, args) => + { + MessageBox.Show($"Background Sync Task Tag: {args.RegistrationInfo.Tag} registered"); + }; + } + catch (NotImplementedException exception) + { + MessageBox.Show(this, "ServiceWorkerSyncRegistrationManager Failed: " + exception.Message, + "ServiceWorkerSyncRegistrationManager"); + } + } + } + } +} + +async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs args) +{ + if (args.Source != "https://appassets.example/ScenarioServiceWorkerSyncRegistrationManager.html") + { + return; + } + + // Received `chrome.webview.postMessage(`DispatchAllPeriodicSyncEvents ${times}`)` message + // from the page. + // This method will fetch all periodic synchronization tasks in the current service worker, + // and executes each task multiple(time) times with a specified minimum interval(min_interval) + // between consecutive executions. + string message = args.TryGetWebMessageAsString(); + if (message.Contains("DispatchPeriodicSyncEvents")) + { + int msgLength = "DispatchPeriodicSyncEvents".Length; + var times = message.Substring(msgLength); + IReadOnlyList registrationList = + await SyncRegistrationManager_.GetSyncRegistrationsAsync( + CoreWebView2ServiceWorkerSynchronizationKind.PeriodicSync); + int registrationCount = registrationList.Count; + for (int i = 0; i < registrationCount; ++i) + { + var tag = registrationList[i].Tag; + var interval = registrationList[i].MinIntervalInMilliseconds; + if (ServiceWorker_ != null) + { + for (int j = 0; j < times; ++j) { + await ServiceWorker_.DispatchPeriodicSyncEventAsync(tag); + System.Threading.Thread.Sleep((int)interval); + } + } + }; + } +} +``` + # API Details ## C++ ``` /// Indicates the service worker background synchronization type. [v1_enum] -typedef enum COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND { +typedef enum COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND { /// Indicates that the synchronization is a background synchronization. /// See [Background Synchronization](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API) /// for more information. - COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND_BACKGROUND_SYNC, + COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND_BACKGROUND_SYNC, /// Indicates that the synchronization is a periodic background synchronization. /// See [Periodic Background Synchronization](https://developer.mozilla.org/docs/Web/API/Web_Periodic_Background_Synchronization_API) /// for more information. - COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND_PERIODIC_SYNC, -} COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND; + COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND_PERIODIC_SYNC, +} COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND; /// This is the ICoreWebView2ServiceWorkerRegistration interface. [uuid(08a80c87-d2b7-5163-bce3-4a28cfed142d), object, pointer_default(unique)] @@ -74,6 +394,11 @@ interface ICoreWebView2ServiceWorkerRegistration : IUnknown { /// registration management APIs. interface ICoreWebView2ServiceWorkerSyncRegistrationManager : IUnknown { /// Add an event handler for the `BackgroundSyncRegistered` event. + /// + /// This event is raised when a web application registers a background sync task + /// using the `navigator.serviceWorker.sync.register('tag')` + /// method. Please see the [Requesting a Background Sync](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API#requesting_a_background_sync) + /// for more information. /// /// \snippet ScenarioSyncRegistrationManager.cpp BackgroundSyncRegistered /// @@ -87,6 +412,11 @@ interface ICoreWebView2ServiceWorkerSyncRegistrationManager : IUnknown { /// Add an event handler for the `PeriodicSyncRegistered` event. /// + /// This event is raised when a web application registers a periodic sync task + /// using the `navigator.serviceWorker.periodicSync.register('tag', {minInterval: 1000})` + /// method. Please see the [Requesting a Periodic Background Sync](https://developer.mozilla.org/docs/Web/API/Web_Periodic_Background_Synchronization_API#requesting_a_periodic_background_sync) + /// for more information. + /// /// \snippet ScenarioServiceWorkerSyncRegistrationManager.cpp PeriodicSyncRegistered /// HRESULT add_PeriodicSyncRegistered( @@ -100,7 +430,7 @@ interface ICoreWebView2ServiceWorkerSyncRegistrationManager : IUnknown { /// Gets all background synchronization or periodic background synchronization /// registrations. HRESULT GetSyncRegistrations( - [in] COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND kind + [in] COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND kind , [in] ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler* handler ); } @@ -119,16 +449,20 @@ interface ICoreWebView2ServiceWorkerSyncRegisteredEventArgs : IUnknown { /// Provides a set of properties for a service worker synchronization registration. [uuid(8ab3dbf2-9207-5231-9241-167e96d8cf56), object, pointer_default(unique)] interface ICoreWebView2ServiceWorkerSyncRegistrationInfo : IUnknown { - /// The minimum interval time, in milliseconds, at which the minimum time - /// interval between periodic background synchronizations should occur. - /// You should not call `CoreWebView2ServiceWorkerSyncRegistrationManager.DispatchPeriodicSyncEventAsync` - /// to dispatch periodic synchronization tasks less than its minimum time interval. - /// This property is always returns an invalid value `-1` for the background synchronization registration. + /// The minimum interval time, at which the minimum time interval between periodic background + /// synchronizations should occur. + /// From the [Web Standard](https://wicg.github.io/periodic-background-sync/#periodic-sync-registration-minimum-interval), + /// you're not suggested to run periodic sync tasks + /// `CoreWebView2ServiceWorkerSyncRegistrationManager.DispatchPeriodicSyncEventAsync` + /// less than the value of this property. And this property is always returns an invalid + /// value `-1` for the background synchronization registration. /// - [propget] HRESULT MinInterval([out, retval] INT64* value); + [propget] HRESULT MinIntervalInMilliseconds([out, retval] INT64* value); /// A string representing an unique identifier for the synchronization event. /// + /// It represents the [Periodic Sync Tag][https://developer.mozilla.org/docs/Web/API/PeriodicSyncEvent/tag] + /// and [Background Sync Tag][https://developer.mozilla.org/docs/Web/API/SyncEvent/tag]. /// The caller must free the returned string with `CoTaskMemFree`. See /// [API Conventions](/microsoft-edge/webview2/concepts/win32-api-conventions#strings). [propget] HRESULT Tag([out, retval] LPWSTR* value); @@ -216,7 +550,7 @@ namespace Microsoft.Web.WebView2.Core runtimeclass CoreWebView2ServiceWorker { - Windows.Foundation.IAsyncOperation DispatchPeriodicSyncEventAsync(String Tag); + Windows.Foundation.IAsyncOperation DispatchPeriodicSyncEventAsync(String tag); } runtimeclass CoreWebView2ServiceWorkerSyncRegistrationManager @@ -236,346 +570,8 @@ namespace Microsoft.Web.WebView2.Core runtimeclass CoreWebView2ServiceWorkerSyncRegistrationInfo { - Int64 MinInterval { get; }; + Int64 MinIntervalInMilliseconds { get; }; String Tag { get; }; } } ``` - - -# Examples -### C++ Sample -```cpp -static constexpr WCHAR c_samplePath[] = L"ScenarioServiceWorkerSyncRegistrationManager.html"; - -ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrationManager( - AppWindow* appWindow) - : m_appWindow(appWindow), m_webView(appWindow->GetWebView()) -{ - m_sampleUri = m_appWindow->GetLocalUri(c_samplePath); - - auto webView2_13 = m_webView.try_query(); - CHECK_FEATURE_RETURN_EMPTY(webView2_13); - - wil::com_ptr webView2Profile; - CHECK_FAILURE(webView2_13->get_Profile(&webView2Profile)); - auto webViewProfile3 = webView2Profile.try_query(); - CHECK_FEATURE_RETURN_EMPTY(webViewProfile3); - wil::com_ptr serviceWorkerManager; - CHECK_FAILURE(webViewProfile3->get_ServiceWorkerManager(&serviceWorkerManager)); - - if (serviceWorkerManager) - { - CHECK_FAILURE(serviceWorkerManager->GetServiceWorkerRegistration( - m_appWindow->GetLocalUri(L"").c_str(), - Callback( - [this]( - HRESULT error, - ICoreWebView2ServiceWorkerRegistration* serviceWorkerRegistration) - -> HRESULT - { - if (serviceWorkerRegistration) - { - serviceWorkerRegistration->QueryInterface( - IID_PPV_ARGS(&m_serviceWorkerRegistration)); - //! [SyncRegistrationManager] - CHECK_FAILURE(serviceWorkerRegistration->get_SyncRegistrationManager( - &m_syncRegistrationManager)); - if (m_syncRegistrationManager) - { - //! [BackgroundSyncRegistered] - CHECK_FAILURE(m_syncRegistrationManager->add_BackgroundSyncRegistered( - Microsoft::WRL::Callback< - ICoreWebView2SyncRegisteredEventHandler>( - [this]( - ICoreWebView2ServiceWorkerSyncRegistrationManager* - sender, - ICoreWebView2ServiceWorkerSyncRegisteredEventArgs* - args) - { - wil::com_ptr< - ICoreWebView2ServiceWorkerSyncRegistrationInfo> - syncRegistrationInfo; - CHECK_FAILURE( - args->get_RegistrationInfo(&syncRegistrationInfo)); - std::wstringstream message; - AppendSyncRegistrationInfo( - syncRegistrationInfo, false, message); - m_appWindow->AsyncMessageBox( - message.str(), L"Background Sync"); - - return S_OK; - }) - .Get(), - &m_backgroundSyncRegisteredToken)); - //! [BackgroundSyncRegistered] - //! [PeriodicSyncRegistered] - CHECK_FAILURE(m_syncRegistrationManager->add_PeriodicSyncRegistered( - Microsoft::WRL::Callback< - ICoreWebView2SyncRegisteredEventHandler>( - [this]( - ICoreWebView2ServiceWorkerSyncRegistrationManager* - sender, - ICoreWebView2ServiceWorkerSyncRegisteredEventArgs* - args) - { - wil::com_ptr< - ICoreWebView2ServiceWorkerSyncRegistrationInfo> - syncRegistrationInfo; - CHECK_FAILURE( - args->get_RegistrationInfo(&syncRegistrationInfo)); - std::wstringstream message; - AppendSyncRegistrationInfo( - syncRegistrationInfo, true, message); - m_appWindow->AsyncMessageBox( - message.str(), L"Periodic Background Sync"); - return S_OK; - }) - .Get(), - &m_periodicSyncRegisteredToken)); - //! [PeriodicSyncRegistered] - } - //! [SyncRegistrationManager] - } - return S_OK; - }) - .Get())); - } - - // Receive dispatch periodic sync task request - CHECK_FAILURE(m_webView->add_WebMessageReceived( - Callback( - [this](ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args) - -> HRESULT - { - wil::unique_cotaskmem_string source; - CHECK_FAILURE(args->get_Source(&source)); - wil::unique_cotaskmem_string webMessageAsString; - if (SUCCEEDED(args->TryGetWebMessageAsString(&webMessageAsString))) - { - if (wcscmp(source.get(), m_sampleUri.c_str()) == 0) - { - std::wstring message = webMessageAsString.get(); - if (message.compare(0, 26, L"DispatchPeriodicSyncEvent ") == 0) - { - DispatchPeriodicBackgroundSyncTask(message.substr(26).c_str()); - } - else if (wcscmp(message.c_str(), L"GetPeriodicSyncRegistrations") == 0) - { - ShowAllSyncRegistrationInfos(COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND_PERIODIC_SYNC); - } - else if ( - wcscmp(message.c_str(), L"GetBackgroundSyncRegistrations") == 0) - { - ShowAllSyncRegistrationInfos(COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND_BACKGROUND_SYNC); - } - } - } - return S_OK; - }) - .Get(), - nullptr)); - - CHECK_FAILURE(m_webView->Navigate(m_sampleUri.c_str())); -} - -void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyncTask( - const std::wstring& tag) -{ - if (m_serviceWorkerRegistration) - { - CHECK_FAILURE(m_serviceWorkerRegistration->GetServiceWorker( - Callback( - [this, &tag]( - HRESULT error, ICoreWebView2ServiceWorker* serviceWorker) -> HRESULT - { - wil::com_ptr worker; - wil::unique_cotaskmem_string scriptUrl; - std::wstringstream message; - // ![DispatchPeriodicSyncEvent] - if (serviceWorker != nullptr) - { - CHECK_FAILURE(serviceWorker->DispatchPeriodicSyncEvent( - tag.c_str(), - Microsoft::WRL::Callback< - ICoreWebView2ServiceWorkerDispatchPeriodicSyncEventCompletedHandler>( - [this](HRESULT errorCode, BOOL isSuccessful) -> HRESULT - { - CHECK_FAILURE(errorCode); - m_appWindow->AsyncMessageBox( - (isSuccessful) ? L"Dispatch Periodic Sync task success" - : L"Dispatch Periodic Sync task failed", - L"Dispatch periodic sync task Completed"); - return S_OK; - }) - .Get())); - } - return S_OK; - // ![DispatchPeriodicSyncEvent] - }) - .Get())); - } -} - -void ScenarioServiceWorkerSyncRegistrationManager::ShowAllSyncRegistrationInfos( - const COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND kind) -{ - if (m_syncRegistrationManager) - { - //! [GetSyncRegistrations] - CHECK_FAILURE(m_syncRegistrationManager->GetSyncRegistrations( - kind, - Callback< - ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler>( - [this]( - HRESULT error, - ICoreWebView2ServiceWorkerSyncRegistrationInfoCollectionView* - collectionView) -> HRESULT - { - UINT32 count; - collectionView->get_Count(&count); - bool isPeriodicSync = - COREWEBVIEW2_SERVICE_WORKER_SYNCHRONIZATION_KIND_PERIODIC_SYNC ? true - : false; - for (UINT32 i = 0; i < count; i++) - { - wil::com_ptr - registrationInfo; - CHECK_FAILURE(collectionView->GetValueAtIndex(i, ®istrationInfo)); - std::wstringstream message; - AppendSyncRegistrationInfo(registrationInfo, isPeriodicSync, message); - message << L"\n"; - m_appWindow->AsyncMessageBox( - std::move(message.str()), isPeriodicSync - ? L"Periodic Sync Registrations" - : L"Background Sync Registrations"); - } - return S_OK; - }) - .Get())); - //! [GetSyncRegistrations] - } -} - -void ScenarioServiceWorkerSyncRegistrationManager::AppendSyncRegistrationInfo( - wil::com_ptr syncRegistrationInfo, - bool isPeriodicSync, std::wstringstream& message) -{ - if (syncRegistrationInfo) - { - wil::unique_cotaskmem_string tag; - CHECK_FAILURE(syncRegistrationInfo->get_Tag(&tag)); - message << L" Tag: " << tag.get(); - if (isPeriodicSync) - { - INT64 minInterval = 0; - CHECK_FAILURE(syncRegistrationInfo->get_MinInterval(&minInterval)); - message << L" MinInterval: " << minInterval; - } - } -} -``` -### C# Sample -```c# -CoreWebView2ServiceWorkerSyncRegistrationManager SyncRegistrationManager_; -CoreWebView2ServiceWorkerRegistration ServiceWorkerRegistration_; -async void ServiceWorkerSyncManagerExecuted(object target, ExecutedRoutedEventArgs e) -{ - webView.Source = new Uri("https://appassets.example/ScenarioServiceWorkerSyncRegistrationManager.html"); - webView.CoreWebView2.WebMessageReceived += ServiceWorkerSyncEvent_WebMessageReceived; - - CoreWebView2Profile webViewProfile = webView.CoreWebView2.Profile; - CoreWebView2ServiceWorkerManager serviceWorkerManager = webViewProfile.ServiceWorkerManager; - if (serviceWorkerManager != null) - { - ServiceWorkerRegistration_ = - await serviceWorkerManager.GetServiceWorkerRegistrationAsync("https://appassets.example.com"); - if (ServiceWorkerRegistration_ != null) - { - SyncRegistrationManager_ = ServiceWorkerRegistration_.SyncRegistrationManager; - if (SyncRegistrationManager_ != null) - { - try - { - SyncRegistrationManager_.PeriodicSyncRegistered += (sender, args) => - { - MessageBox.Show($"Periodic Sync Task Tag: {args.RegistrationInfo.Tag}, - MinInterval: {args.RegistrationInfo.MinInterval} registered"); - }; - SyncRegistrationManager_.BackgroundSyncRegistered += (sender, args) => - { - MessageBox.Show($"Background Sync Task Tag: {args.RegistrationInfo.Tag} registered"); - }; - } - catch (NotImplementedException exception) - { - MessageBox.Show(this, "ServiceWorkerSyncRegistrationManager Failed: " + exception.Message, - "ServiceWorkerSyncRegistrationManager"); - } - } - } - } -} - -async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs args) -{ - async void ShowServiceWorkerSyncRegistrations(bool isPeriodicSync) - { - if (SyncRegistrationManager_ != null) - { - IReadOnlyList registrationList = - await SyncRegistrationManager_.GetSyncRegistrationsAsync(isPeriodicSync ? - CoreWebView2ServiceWorkerSynchronizationKind.PeriodicSync : - CoreWebView2ServiceWorkerSynchronizationKind.BackgroundSync); - - int registrationCount = registrationList.Count; - StringBuilder messageBuilder = new StringBuilder(); - messageBuilder.AppendLine(isPeriodicSync ? - "No of periodic background sync created: " : - "No of background sync created: "); - messageBuilder.Append($"{registrationCount}"); - - for (int i = 0; i < registrationCount; ++i) - { - var tag = registrationList[i].Tag; - messageBuilder.AppendLine($"Tag: {tag}"); - if (isPeriodicSync) - { - var interval = registrationList[i].MinInterval; - messageBuilder.Append($" MinInterval: {interval}"); - } - }; - - MessageBox.Show(messageBuilder.ToString(), isPeriodicSync ? - "Periodic Background Sync Registrations" : - "Background Sync Registrations", MessageBoxButton.OK); - } - } - - if (args.Source != "https://appassets.example/ScenarioServiceWorkerSyncRegistrationManager.html") - { - return; - } - - string message = args.TryGetWebMessageAsString(); - if (message.Contains("DispatchPeriodicSyncEvent")) - { - if (ServiceWorkerRegistration_ != null) - { - int msgLength = "DispatchPeriodicSyncEvent".Length; - var tag = message.Substring(msgLength); - CoreWebView2ServiceWorker serviceWorker = await ServiceWorkerRegistration_.GetServiceWorkerAsync(); - if (serviceWorker != null) - { - await serviceWorker.DispatchPeriodicSyncEventAsync(tag); - } - } - } else if (message.Contains("GetPeriodicSyncRegistrations")) - { - ShowServiceWorkerSyncRegistrations(true); - } else if (message.Contains("GetBackgroundSyncRegistrations")) - { - ShowServiceWorkerSyncRegistrations(false); - } -} -``` From 83bdcff52352283b9eb81f8e0d24c9f9d2917030 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 21 May 2024 16:16:28 -0700 Subject: [PATCH 08/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- specs/PeriodicBackgoundSyncAndBackgroundSync.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index debda2ba2..8026035e9 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -74,7 +74,6 @@ ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrat wil::com_ptr serviceWorkerManager; CHECK_FAILURE(webViewProfile3->get_ServiceWorkerManager(&serviceWorkerManager)); - CHECK_FAILURE(serviceWorkerManager->GetServiceWorkerRegistration( m_appWindow->GetLocalUri(L"").c_str(), Callback( @@ -83,6 +82,9 @@ ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrat ICoreWebView2ServiceWorkerRegistration* serviceWorkerRegistration) -> HRESULT { + CHECK_FAILURE(error); + // Service Worker registration could be null if target scope does not + // register a service worker. if (serviceWorkerRegistration) { serviceWorkerRegistration->QueryInterface( @@ -93,6 +95,7 @@ ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrat [this]( HRESULT error, ICoreWebView2ServiceWorker* serviceWorker) -> HRESULT { + CHECK_FAILURE(error); if (serviceWorker) { serviceWorker->QueryInterface(IID_PPV_ARGS(&m_serviceWorker)); @@ -162,8 +165,8 @@ ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrat .Get())); - // Receive the message of dispatching all periodic sync tasks from the page, - // `chrome.webview.postMessage(`DispatchAllPeriodicSyncEvents ${times}`)`. + // Received `chrome.webview.postMessage(`DispatchAllPeriodicSyncEvents ${times}`)` + // message from the page. CHECK_FAILURE(m_webView->add_WebMessageReceived( Callback( [this, &sampleUri]( @@ -237,6 +240,7 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn ICoreWebView2ServiceWorkerSyncRegistrationInfoCollectionView* collectionView) -> HRESULT { + CHECK_FAILURE(error); UINT32 count; collectionView->get_Count(&count); for (UINT32 i = 0; i < count; i++) @@ -463,6 +467,7 @@ interface ICoreWebView2ServiceWorkerSyncRegistrationInfo : IUnknown { /// /// It represents the [Periodic Sync Tag][https://developer.mozilla.org/docs/Web/API/PeriodicSyncEvent/tag] /// and [Background Sync Tag][https://developer.mozilla.org/docs/Web/API/SyncEvent/tag]. + /// /// The caller must free the returned string with `CoTaskMemFree`. See /// [API Conventions](/microsoft-edge/webview2/concepts/win32-api-conventions#strings). [propget] HRESULT Tag([out, retval] LPWSTR* value); From 8c091935059f1ff4ce944a6305111741bb7ca4f7 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 21 May 2024 16:18:25 -0700 Subject: [PATCH 09/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- specs/PeriodicBackgoundSyncAndBackgroundSync.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index 8026035e9..dc276c5fc 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -255,7 +255,7 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn int executeTime = time; for (int i = 0; i < executeTime; i++) { DispatchPeriodicBackgroundSyncTask(tag.get()); - // Wait min_interval before triggering the periodic sync task again. + // Wait for min_interval(ms) before triggering the periodic sync task again. const auto interval = std::chrono::milliseconds(minInterval); std::this_thread::sleep_for(interval); } @@ -358,6 +358,7 @@ async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2 { for (int j = 0; j < times; ++j) { await ServiceWorker_.DispatchPeriodicSyncEventAsync(tag); + // Wait for min_interval(ms) before triggering the periodic sync task again. System.Threading.Thread.Sleep((int)interval); } } From 7c7e240950a14bc9df84d007f82dbe7fd157ba6d Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 21 May 2024 16:24:28 -0700 Subject: [PATCH 10/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- specs/PeriodicBackgoundSyncAndBackgroundSync.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index dc276c5fc..1d5a0c146 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -252,8 +252,7 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn CHECK_FAILURE(registrationInfo->get_Tag(&tag)); UINT32 minInterval = 0; CHECK_FAILURE(registrationInfo->get_MinIntervalInMilliseconds(&minInterval)); - int executeTime = time; - for (int i = 0; i < executeTime; i++) { + for (int i = 0; i < time; i++) { DispatchPeriodicBackgroundSyncTask(tag.get()); // Wait for min_interval(ms) before triggering the periodic sync task again. const auto interval = std::chrono::milliseconds(minInterval); @@ -469,7 +468,7 @@ interface ICoreWebView2ServiceWorkerSyncRegistrationInfo : IUnknown { /// It represents the [Periodic Sync Tag][https://developer.mozilla.org/docs/Web/API/PeriodicSyncEvent/tag] /// and [Background Sync Tag][https://developer.mozilla.org/docs/Web/API/SyncEvent/tag]. /// - /// The caller must free the returned string with `CoTaskMemFree`. See + /// The caller must free the returned string with `CoTaskMemFree`. See /// [API Conventions](/microsoft-edge/webview2/concepts/win32-api-conventions#strings). [propget] HRESULT Tag([out, retval] LPWSTR* value); } From 15aa3d8deb1fefec532a63a9423a5a76c5b4f887 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 21 May 2024 16:32:53 -0700 Subject: [PATCH 11/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- specs/PeriodicBackgoundSyncAndBackgroundSync.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index 1d5a0c146..f3fe674ee 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -37,7 +37,7 @@ registered. **GetSyncRegistrations API**: This asynchronous call returns the collection of all periodic background synchronization registrations or background synchronization registrations based on the -`CoreWebView2ServiceWorkerSynchronizationKind` provided. We add +`CoreWebView2ServiceWorkerSyncKind` provided. We add `CoreWebView2ServiceWorkerSyncRegistrationInfo` with `Tag` and `MinIntervalInMilliseconds` properties to represent a synchronization registration. @@ -213,7 +213,7 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn CHECK_FAILURE(errorCode); m_appWindow->AsyncMessageBox( (isSuccessful) ? L"Dispatch Periodic Sync task success" - : L"Dispatch Periodic Sync task failed", + : L"Dispatch Periodic Sync task failed", L"Dispatch periodic sync task Completed"); return S_OK; }) @@ -347,7 +347,7 @@ async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2 var times = message.Substring(msgLength); IReadOnlyList registrationList = await SyncRegistrationManager_.GetSyncRegistrationsAsync( - CoreWebView2ServiceWorkerSynchronizationKind.PeriodicSync); + CoreWebView2ServiceWorkerSyncKind.PeriodicSync); int registrationCount = registrationList.Count; for (int i = 0; i < registrationCount; ++i) { @@ -536,7 +536,7 @@ C# ```c# namespace Microsoft.Web.WebView2.Core { - enum CoreWebView2ServiceWorkerSynchronizationKind + enum CoreWebView2ServiceWorkerSyncKind { // Indicates that the synchronization is a background synchronization. // See [Background Synchronization](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API) @@ -565,7 +565,7 @@ namespace Microsoft.Web.WebView2.Core event Windows.Foundation.TypedEventHandler PeriodicSyncRegistered; - Windows.Foundation.IAsyncOperation> GetSyncRegistrationsAsync(CoreWebView2ServiceWorkerSynchronizationKind Kind); + Windows.Foundation.IAsyncOperation> GetSyncRegistrationsAsync(CoreWebView2ServiceWorkerSyncKind Kind); } runtimeclass CoreWebView2ServiceWorkerSyncRegisteredEventArgs From 896d59b4726e38a66eea238fd969395c34e50fd4 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Thu, 23 May 2024 12:02:57 -0700 Subject: [PATCH 12/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- specs/PeriodicBackgoundSyncAndBackgroundSync.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index f3fe674ee..f35e0cfa5 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -110,7 +110,7 @@ ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrat //! [BackgroundSyncRegistered] CHECK_FAILURE(m_syncRegistrationManager->add_BackgroundSyncRegistered( Microsoft::WRL::Callback< - ICoreWebView2SyncRegisteredEventHandler>( + ICoreWebView2ServiceWorkerSyncRegisteredEventHandler>( [this]( ICoreWebView2ServiceWorkerSyncRegistrationManager* sender, @@ -136,7 +136,7 @@ ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrat //! [PeriodicSyncRegistered] CHECK_FAILURE(m_syncRegistrationManager->add_PeriodicSyncRegistered( Microsoft::WRL::Callback< - ICoreWebView2SyncRegisteredEventHandler>( + ICoreWebView2ServiceWorkerSyncRegisteredEventHandler>( [this]( ICoreWebView2ServiceWorkerSyncRegistrationManager* sender, @@ -223,7 +223,7 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn } // This method fetches all periodic synchronization tasks in the current service worker, -// and executes each task multiple(time) times with a specified minimum interval(min_interval) +// and executes each task multiple(time) times with a specified interval(min_interval) // between consecutive executions. void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyncTasks( const int time) @@ -252,7 +252,7 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn CHECK_FAILURE(registrationInfo->get_Tag(&tag)); UINT32 minInterval = 0; CHECK_FAILURE(registrationInfo->get_MinIntervalInMilliseconds(&minInterval)); - for (int i = 0; i < time; i++) { + for (int j = 0; j < time; j++) { DispatchPeriodicBackgroundSyncTask(tag.get()); // Wait for min_interval(ms) before triggering the periodic sync task again. const auto interval = std::chrono::milliseconds(minInterval); @@ -344,7 +344,7 @@ async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2 if (message.Contains("DispatchPeriodicSyncEvents")) { int msgLength = "DispatchPeriodicSyncEvents".Length; - var times = message.Substring(msgLength); + int times = int.Parse(message.Substring(msgLength)); IReadOnlyList registrationList = await SyncRegistrationManager_.GetSyncRegistrationsAsync( CoreWebView2ServiceWorkerSyncKind.PeriodicSync); @@ -407,7 +407,7 @@ interface ICoreWebView2ServiceWorkerSyncRegistrationManager : IUnknown { /// \snippet ScenarioSyncRegistrationManager.cpp BackgroundSyncRegistered /// HRESULT add_BackgroundSyncRegistered( - [in] ICoreWebView2SyncRegisteredEventHandler* eventHandler, + [in] ICoreWebView2ServiceWorkerSyncRegisteredEventHandler* eventHandler, [out] EventRegistrationToken* token); /// Removes an event handler previously added with `add_BackgroundSyncRegistered`. @@ -424,7 +424,7 @@ interface ICoreWebView2ServiceWorkerSyncRegistrationManager : IUnknown { /// \snippet ScenarioServiceWorkerSyncRegistrationManager.cpp PeriodicSyncRegistered /// HRESULT add_PeriodicSyncRegistered( - [in] ICoreWebView2SyncRegisteredEventHandler* eventHandler, + [in] ICoreWebView2ServiceWorkerSyncRegisteredEventHandler* eventHandler, [out] EventRegistrationToken* token); /// Removes an event handler previously added with `add_PeriodicSyncRegistered`. @@ -497,7 +497,7 @@ interface ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsC /// Receives `PeriodicSyncRegistered` or `BackgroundSyncRegistered` events. [uuid(551ce0e3-bef4-559b-b962-d94069b7df67), object, pointer_default(unique)] -interface ICoreWebView2SyncRegisteredEventHandler : IUnknown { +interface ICoreWebView2ServiceWorkerSyncRegisteredEventHandler : IUnknown { /// Provides the event args for the corresponding event. HRESULT Invoke( [in] ICoreWebView2ServiceWorkerSyncRegistrationManager* sender, From 857653ecca129d285a0ed96f7b6e3c08db35e51c Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Mon, 3 Jun 2024 17:16:03 -0700 Subject: [PATCH 13/17] Update PeriodicBackgoundSyncAndBackgroundSync.md --- .../PeriodicBackgoundSyncAndBackgroundSync.md | 70 +++++++------------ 1 file changed, 24 insertions(+), 46 deletions(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index f35e0cfa5..be322388e 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -34,12 +34,14 @@ task is registered. to subscribe to the event when a new Background synchronization task is registered. -**GetSyncRegistrations API**: This asynchronous call returns the -collection of all periodic background synchronization registrations or -background synchronization registrations based on the -`CoreWebView2ServiceWorkerSyncKind` provided. We add -`CoreWebView2ServiceWorkerSyncRegistrationInfo` with `Tag` and -`MinIntervalInMilliseconds` properties to represent a synchronization registration. +**GetPeriodicSyncRegistrations API**: This asynchronous call returns +the collection of all periodic background synchronization registrations. +We add `CoreWebView2ServiceWorkerSyncRegistrationInfo` with `Tag` and +`MinIntervalInMilliseconds` properties to represent a synchronization +registration. + +**GetBackgroundSyncRegistrations API**: This asynchronous call returns +the collection of all background synchronization registrations. **DispatchPeriodicSyncEvent API**: This API gives developers the ability to trigger a periodic background synchronization task based on the @@ -230,9 +232,8 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn { if (m_syncRegistrationManager) { - //! [GetSyncRegistrations] - CHECK_FAILURE(m_syncRegistrationManager->GetSyncRegistrations( - COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND_PERIODIC_SYNC, + //! [GetPeriodicSyncRegistrations] + CHECK_FAILURE(m_syncRegistrationManager->GetPeriodicSyncRegistrations( Callback< ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler>( [this, time]( @@ -262,7 +263,7 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn return S_OK; }) .Get())); - //! [GetSyncRegistrations] + //! [GetPeriodicSyncRegistrations] } } @@ -346,8 +347,7 @@ async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2 int msgLength = "DispatchPeriodicSyncEvents".Length; int times = int.Parse(message.Substring(msgLength)); IReadOnlyList registrationList = - await SyncRegistrationManager_.GetSyncRegistrationsAsync( - CoreWebView2ServiceWorkerSyncKind.PeriodicSync); + await SyncRegistrationManager_.GetPeriodicSyncRegistrationsAsync(); int registrationCount = registrationList.Count; for (int i = 0; i < registrationCount; ++i) { @@ -369,19 +369,6 @@ async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2 # API Details ## C++ ``` -/// Indicates the service worker background synchronization type. -[v1_enum] -typedef enum COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND { - /// Indicates that the synchronization is a background synchronization. - /// See [Background Synchronization](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API) - /// for more information. - COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND_BACKGROUND_SYNC, - /// Indicates that the synchronization is a periodic background synchronization. - /// See [Periodic Background Synchronization](https://developer.mozilla.org/docs/Web/API/Web_Periodic_Background_Synchronization_API) - /// for more information. - COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND_PERIODIC_SYNC, -} COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND; - /// This is the ICoreWebView2ServiceWorkerRegistration interface. [uuid(08a80c87-d2b7-5163-bce3-4a28cfed142d), object, pointer_default(unique)] interface ICoreWebView2ServiceWorkerRegistration : IUnknown { @@ -431,12 +418,13 @@ interface ICoreWebView2ServiceWorkerSyncRegistrationManager : IUnknown { HRESULT remove_PeriodicSyncRegistered( [in] EventRegistrationToken token); - /// Gets all background synchronization or periodic background synchronization - /// registrations. - HRESULT GetSyncRegistrations( - [in] COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND kind - , [in] ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler* handler - ); + /// Gets all background synchronization registrations. + HRESULT GetBackgroundSyncRegistrations( + [in] ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler* handler); + + /// Gets all periodic synchronization registrations. + HRESULT GetPeriodicSyncRegistrations( + [in] ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler* handler); } /// Event args for the `PeriodicSyncRegistered` event or the `BackgroundSyncRegistered` event. @@ -458,8 +446,8 @@ interface ICoreWebView2ServiceWorkerSyncRegistrationInfo : IUnknown { /// From the [Web Standard](https://wicg.github.io/periodic-background-sync/#periodic-sync-registration-minimum-interval), /// you're not suggested to run periodic sync tasks /// `CoreWebView2ServiceWorkerSyncRegistrationManager.DispatchPeriodicSyncEventAsync` - /// less than the value of this property. And this property is always returns an invalid - /// value `-1` for the background synchronization registration. + /// less than the value of this property. This property is `-1` for all background + /// synchronization registrations. /// [propget] HRESULT MinIntervalInMilliseconds([out, retval] INT64* value); @@ -536,18 +524,6 @@ C# ```c# namespace Microsoft.Web.WebView2.Core { - enum CoreWebView2ServiceWorkerSyncKind - { - // Indicates that the synchronization is a background synchronization. - // See [Background Synchronization](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API) - // for more information. - BackgroundSync = 0, - // Indicates that the synchronization is a periodic background synchronization. - // See [Periodic Background Synchronization](https://developer.mozilla.org/docs/Web/API/Web_Periodic_Background_Synchronization_API) - // for more information. - PeriodicSync = 1, - }; - runtimeclass CoreWebView2ServiceWorkerRegistration { CoreWebView2ServiceWorkerSyncRegistrationManager SyncRegistrationManager { get; }; @@ -565,7 +541,9 @@ namespace Microsoft.Web.WebView2.Core event Windows.Foundation.TypedEventHandler PeriodicSyncRegistered; - Windows.Foundation.IAsyncOperation> GetSyncRegistrationsAsync(CoreWebView2ServiceWorkerSyncKind Kind); + Windows.Foundation.IAsyncOperation> GetPeriodicSyncRegistrationsAsync(); + + Windows.Foundation.IAsyncOperation> GetBackgroundSyncRegistrationsAsync(); } runtimeclass CoreWebView2ServiceWorkerSyncRegisteredEventArgs From cd3a9f3eb66021da72a8b67918bddea6640cadcb Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Wed, 10 Jul 2024 09:57:55 -0700 Subject: [PATCH 14/17] update PeriodicBackgoundSyncAndBackgroundSync.md --- .../PeriodicBackgoundSyncAndBackgroundSync.md | 108 ++++++++++++++---- 1 file changed, 84 insertions(+), 24 deletions(-) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgoundSyncAndBackgroundSync.md index be322388e..f7967b5a5 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgoundSyncAndBackgroundSync.md @@ -34,15 +34,14 @@ task is registered. to subscribe to the event when a new Background synchronization task is registered. -**GetPeriodicSyncRegistrations API**: This asynchronous call returns -the collection of all periodic background synchronization registrations. -We add `CoreWebView2ServiceWorkerSyncRegistrationInfo` with `Tag` and +**GetSyncRegistrations API**: This asynchronous call returns the +collection of all periodic background synchronization registrations or +background synchronization registrations based on the +`CoreWebView2ServiceWorkerSyncKind` provided. We add +`CoreWebView2ServiceWorkerSyncRegistrationInfo` with `Tag` and `MinIntervalInMilliseconds` properties to represent a synchronization registration. -**GetBackgroundSyncRegistrations API**: This asynchronous call returns -the collection of all background synchronization registrations. - **DispatchPeriodicSyncEvent API**: This API gives developers the ability to trigger a periodic background synchronization task based on the tag name. Developers can use native OS timer to implement a scheduler @@ -210,11 +209,12 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn tag.c_str(), Microsoft::WRL::Callback< ICoreWebView2ServiceWorkerDispatchPeriodicSyncEventCompletedHandler>( - [this](HRESULT errorCode, BOOL isSuccessful) -> HRESULT + [this](HRESULT errorCode, COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS status) -> HRESULT { CHECK_FAILURE(errorCode); m_appWindow->AsyncMessageBox( - (isSuccessful) ? L"Dispatch Periodic Sync task success" + (COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_SUCCEEDED == status) + ? L"Dispatch Periodic Sync task success" : L"Dispatch Periodic Sync task failed", L"Dispatch periodic sync task Completed"); return S_OK; @@ -232,8 +232,9 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn { if (m_syncRegistrationManager) { - //! [GetPeriodicSyncRegistrations] - CHECK_FAILURE(m_syncRegistrationManager->GetPeriodicSyncRegistrations( + //! [GetSyncRegistrations] + CHECK_FAILURE(m_syncRegistrationManager->GetSyncRegistrations( + COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND_PERIODIC_SYNC, Callback< ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler>( [this, time]( @@ -263,7 +264,7 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn return S_OK; }) .Get())); - //! [GetPeriodicSyncRegistrations] + //! [GetSyncRegistrations] } } @@ -347,7 +348,8 @@ async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2 int msgLength = "DispatchPeriodicSyncEvents".Length; int times = int.Parse(message.Substring(msgLength)); IReadOnlyList registrationList = - await SyncRegistrationManager_.GetPeriodicSyncRegistrationsAsync(); + await SyncRegistrationManager_.GetSyncRegistrationsAsync( + CoreWebView2ServiceWorkerSyncKind.PeriodicSync); int registrationCount = registrationList.Count; for (int i = 0; i < registrationCount; ++i) { @@ -369,6 +371,38 @@ async void ServiceWorkerSyncEvent_WebMessageReceived(object sender, CoreWebView2 # API Details ## C++ ``` +/// Indicates the service worker background synchronization type. +[v1_enum] +typedef enum COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND { + /// Indicates that the synchronization is a background synchronization. + /// See [Background Synchronization](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API) + /// for more information. + COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND_BACKGROUND_SYNC, + /// Indicates that the synchronization is a periodic background synchronization. + /// See [Periodic Background Synchronization](https://developer.mozilla.org/docs/Web/API/Web_Periodic_Background_Synchronization_API) + /// for more information. + COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND_PERIODIC_SYNC, +} COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND; + +/// Indicates the status for the service worker dispatch periodic sync +/// task operation. +[v1_enum] +typedef enum COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS { + /// Indicates that the operation is succeeded. + COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_SUCCEEDED, + /// Indicates that the operation is failed. + COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_OTHER_ERROR, + /// Indicates that the is failed for [ExtendableEvent.waitUntil()](https:/-/developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil) + /// method's parameter promise is rejected. + COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_REJECTED, + /// Indicates that the operation is failed for [ExtendableEvent.waitUntil()](https:/-/developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil) + /// method's parameter promise is timeout. + COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_TIMEOUT, + /// Indicates that the dispatch periodic task operation is failed for + /// for tag is not existed. + COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_TAG_NOT_EXISTED, +} COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS; + /// This is the ICoreWebView2ServiceWorkerRegistration interface. [uuid(08a80c87-d2b7-5163-bce3-4a28cfed142d), object, pointer_default(unique)] interface ICoreWebView2ServiceWorkerRegistration : IUnknown { @@ -418,13 +452,12 @@ interface ICoreWebView2ServiceWorkerSyncRegistrationManager : IUnknown { HRESULT remove_PeriodicSyncRegistered( [in] EventRegistrationToken token); - /// Gets all background synchronization registrations. - HRESULT GetBackgroundSyncRegistrations( - [in] ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler* handler); - - /// Gets all periodic synchronization registrations. - HRESULT GetPeriodicSyncRegistrations( - [in] ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler* handler); + /// Gets all background synchronization or periodic background synchronization + /// registrations. + HRESULT GetSyncRegistrations( + [in] COREWEBVIEW2_SERVICE_WORKER_SYNC_KIND kind + , [in] ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler* handler + ); } /// Event args for the `PeriodicSyncRegistered` event or the `BackgroundSyncRegistered` event. @@ -516,7 +549,7 @@ interface ICoreWebView2ServiceWorker : IUnknown { [uuid(86815a3e-ebc8-58b0-84ce-069d15d67d38), object, pointer_default(unique)] interface ICoreWebView2ServiceWorkerDispatchPeriodicSyncEventCompletedHandler : IUnknown { /// Provides the result of the corresponding asynchronous method. - HRESULT Invoke([in] HRESULT errorCode, [in] BOOL result); + HRESULT Invoke([in] HRESULT errorCode, [in] COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS status); } ``` @@ -524,6 +557,35 @@ C# ```c# namespace Microsoft.Web.WebView2.Core { + enum CoreWebView2ServiceWorkerSyncKind + { + // Indicates that the synchronization is a background synchronization. + // See [Background Synchronization](https://developer.mozilla.org/docs/Web/API/Background_Synchronization_API) + // for more information. + BackgroundSync = 0, + // Indicates that the synchronization is a periodic background synchronization. + // See [Periodic Background Synchronization](https://developer.mozilla.org/docs/Web/API/Web_Periodic_Background_Synchronization_API) + // for more information. + PeriodicSync = 1, + }; + + enum CoreWebView2ServiceWorkerSyncOperationStatus + { + /// Indicates that the operation is succeeded. + Succeeded = 0, + /// Indicates that the operation is failed. + OtherError = 1, + /// Indicates that the is failed for [ExtendableEvent.waitUntil()](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil) + /// method's parameter promise is rejected. + Rejected = 2, + /// Indicates that the operation is failed for [ExtendableEvent.waitUntil()](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil) + /// method's parameter promise is timeout. + Timeout = 3, + /// Indicates that the dispatch periodic task operation is failed for + /// for tag is not existed. + TagNotExisted = 4, + }; + runtimeclass CoreWebView2ServiceWorkerRegistration { CoreWebView2ServiceWorkerSyncRegistrationManager SyncRegistrationManager { get; }; @@ -531,7 +593,7 @@ namespace Microsoft.Web.WebView2.Core runtimeclass CoreWebView2ServiceWorker { - Windows.Foundation.IAsyncOperation DispatchPeriodicSyncEventAsync(String tag); + Windows.Foundation.IAsyncOperation DispatchPeriodicSyncEventAsync(String tag); } runtimeclass CoreWebView2ServiceWorkerSyncRegistrationManager @@ -541,9 +603,7 @@ namespace Microsoft.Web.WebView2.Core event Windows.Foundation.TypedEventHandler PeriodicSyncRegistered; - Windows.Foundation.IAsyncOperation> GetPeriodicSyncRegistrationsAsync(); - - Windows.Foundation.IAsyncOperation> GetBackgroundSyncRegistrationsAsync(); + Windows.Foundation.IAsyncOperation> GetSyncRegistrationsAsync(CoreWebView2ServiceWorkerSyncKind Kind); } runtimeclass CoreWebView2ServiceWorkerSyncRegisteredEventArgs From 162a61414d21163a72beb6807f0da32b73094d88 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Thu, 11 Jul 2024 15:23:23 -0700 Subject: [PATCH 15/17] update PeriodicBackgoundSyncAndBackgroundSync.md --- ... PeriodicBackgroundSyncAndBackgroundSync.md} | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) rename specs/{PeriodicBackgoundSyncAndBackgroundSync.md => PeriodicBackgroundSyncAndBackgroundSync.md} (95%) diff --git a/specs/PeriodicBackgoundSyncAndBackgroundSync.md b/specs/PeriodicBackgroundSyncAndBackgroundSync.md similarity index 95% rename from specs/PeriodicBackgoundSyncAndBackgroundSync.md rename to specs/PeriodicBackgroundSyncAndBackgroundSync.md index f7967b5a5..fac3516a9 100644 --- a/specs/PeriodicBackgoundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgroundSyncAndBackgroundSync.md @@ -90,21 +90,8 @@ ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrat { serviceWorkerRegistration->QueryInterface( IID_PPV_ARGS(&m_serviceWorkerRegistration)); - - CHECK_FAILURE(m_serviceWorkerRegistration->GetServiceWorker( - Callback( - [this]( - HRESULT error, ICoreWebView2ServiceWorker* serviceWorker) -> HRESULT - { - CHECK_FAILURE(error); - if (serviceWorker) - { - serviceWorker->QueryInterface(IID_PPV_ARGS(&m_serviceWorker)); - } - return S_OK; - }) - .Get())); - + + CHECK_FAILURE(serviceWorkerRegistration->get_ActiveServiceWorker(&m_serviceWorker)); //! [SyncRegistrationManager] CHECK_FAILURE(serviceWorkerRegistration->get_SyncRegistrationManager( &m_syncRegistrationManager)); From c95b6db75933e3fb027d0888e40383054118afa3 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 16 Jul 2024 15:10:15 -0700 Subject: [PATCH 16/17] update PeriodicBackgroundSyncAndBackgroundSync.md --- ...PeriodicBackgroundSyncAndBackgroundSync.md | 56 ++++++++++++++----- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/specs/PeriodicBackgroundSyncAndBackgroundSync.md b/specs/PeriodicBackgroundSyncAndBackgroundSync.md index fac3516a9..ace93b1b4 100644 --- a/specs/PeriodicBackgroundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgroundSyncAndBackgroundSync.md @@ -186,6 +186,21 @@ ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrat CHECK_FAILURE(m_webView->Navigate(sampleUri.c_str())); } +std::wstring SyncOperationKindToString(COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS type) +{ + switch (type) + { + case COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_SUCCEEDED: + return L"Succeeded"; + case COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_REJECTED: + return L"Javascript promise rejected"; + case COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_TIMEOUT: + return L"Javascript promise timeout"; + default: + return L"Unknown"; + } +} + void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyncTask( const std::wstring& tag) { @@ -196,14 +211,23 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn tag.c_str(), Microsoft::WRL::Callback< ICoreWebView2ServiceWorkerDispatchPeriodicSyncEventCompletedHandler>( - [this](HRESULT errorCode, COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS status) -> HRESULT + [this]( + HRESULT errorCode, + COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS status) + -> HRESULT { CHECK_FAILURE(errorCode); + std::wstring status_string = + SyncOperationKindToString(status); + std::wstring message = L"Dispatch Periodic Sync task "; + if (COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_SUCCEEDED != + status) + { + message += L"failed with "; + } + message += status_string; m_appWindow->AsyncMessageBox( - (COREWEBVIEW2_SERVICE_WORKER_SYNC_OPERATION_STATUS_SUCCEEDED == status) - ? L"Dispatch Periodic Sync task success" - : L"Dispatch Periodic Sync task failed", - L"Dispatch periodic sync task Completed"); + message, L"Dispatch periodic sync task Completed"); return S_OK; }) .Get())); @@ -211,13 +235,13 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn } } -// This method fetches all periodic synchronization tasks in the current service worker, -// and executes each task multiple(time) times with a specified interval(min_interval) +// This method fetches all periodic synchronization tasks in the current service worker, +// and executes each task multiple(time) times with a specified interval(min_interval) // between consecutive executions. void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyncTasks( const int time) { - if (m_syncRegistrationManager) + if (m_syncRegistrationManager) { //! [GetSyncRegistrations] CHECK_FAILURE(m_syncRegistrationManager->GetSyncRegistrations( @@ -225,9 +249,8 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn Callback< ICoreWebView2ServiceWorkerSyncRegistrationManagerGetSyncRegistrationsCompletedHandler>( [this, time]( - HRESULT error, - ICoreWebView2ServiceWorkerSyncRegistrationInfoCollectionView* - collectionView) -> HRESULT + HRESULT error, ICoreWebView2ServiceWorkerSyncRegistrationInfoCollectionView* + collectionView) -> HRESULT { CHECK_FAILURE(error); UINT32 count; @@ -240,10 +263,13 @@ void ScenarioServiceWorkerSyncRegistrationManager::DispatchPeriodicBackgroundSyn wil::unique_cotaskmem_string tag; CHECK_FAILURE(registrationInfo->get_Tag(&tag)); UINT32 minInterval = 0; - CHECK_FAILURE(registrationInfo->get_MinIntervalInMilliseconds(&minInterval)); - for (int j = 0; j < time; j++) { + CHECK_FAILURE( + registrationInfo->get_MinIntervalInMilliseconds(&minInterval)); + for (int j = 0; j < time; j++) + { DispatchPeriodicBackgroundSyncTask(tag.get()); - // Wait for min_interval(ms) before triggering the periodic sync task again. + // Wait for min_interval(ms) before triggering the periodic sync + // task again. const auto interval = std::chrono::milliseconds(minInterval); std::this_thread::sleep_for(interval); } @@ -562,7 +588,7 @@ namespace Microsoft.Web.WebView2.Core Succeeded = 0, /// Indicates that the operation is failed. OtherError = 1, - /// Indicates that the is failed for [ExtendableEvent.waitUntil()](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil) + /// Indicates that the operation is failed for [ExtendableEvent.waitUntil()](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil) /// method's parameter promise is rejected. Rejected = 2, /// Indicates that the operation is failed for [ExtendableEvent.waitUntil()](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil) From df26c967469c26a219268e22d5f8b31f4ecd900c Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 16 Jul 2024 15:14:34 -0700 Subject: [PATCH 17/17] update PeriodicBackgroundSyncAndBackgroundSync.md --- specs/PeriodicBackgroundSyncAndBackgroundSync.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/specs/PeriodicBackgroundSyncAndBackgroundSync.md b/specs/PeriodicBackgroundSyncAndBackgroundSync.md index ace93b1b4..c7acf085d 100644 --- a/specs/PeriodicBackgroundSyncAndBackgroundSync.md +++ b/specs/PeriodicBackgroundSyncAndBackgroundSync.md @@ -152,15 +152,13 @@ ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrat }) .Get())); - - // Received `chrome.webview.postMessage(`DispatchAllPeriodicSyncEvents ${times}`)` + // Received `chrome.webview.postMessage(`DispatchAllPeriodicSyncEvents ${times}`)` // message from the page. CHECK_FAILURE(m_webView->add_WebMessageReceived( Callback( [this, &sampleUri]( ICoreWebView2* sender, - ICoreWebView2WebMessageReceivedEventArgs* args) - -> HRESULT + ICoreWebView2WebMessageReceivedEventArgs* args) -> HRESULT { wil::unique_cotaskmem_string source; CHECK_FAILURE(args->get_Source(&source)); @@ -173,7 +171,8 @@ ScenarioServiceWorkerSyncRegistrationManager::ScenarioServiceWorkerSyncRegistrat std::wstring targetString = L"DispatchAllPeriodicSyncEvents "; if (message.compare(0, targetString.size(), targetString) == 0) { - std::wstring timeString = message.substr(targetString.size().c_str()); + std::wstring timeString = + message.substr(targetString.size().c_str()); DispatchAllPeriodicBackgroundSyncTasks(std::stoi(timeString)); } }