| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  | // Copyright (c) 2015 Felix Rieseberg <feriese@microsoft.com> and Jason Poon
 | 
					
						
							|  |  |  | // <jason.poon@microsoft.com>. All rights reserved.
 | 
					
						
							|  |  |  | // Copyright (c) 2015 Ryan McShane <rmcshane@bandwidth.com> and Brandon Smith
 | 
					
						
							|  |  |  | // <bsmith@bandwidth.com>
 | 
					
						
							|  |  |  | // Thanks to both of those folks mentioned above who first thought up a bunch of
 | 
					
						
							|  |  |  | // this code
 | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | // and released it as MIT to the world.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/browser/notifications/win/windows_toast_notification.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-20 13:28:37 +08:00
										 |  |  | #include <shlobj.h>
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | #include <wrl\wrappers\corewrappers.h>
 | 
					
						
							| 
									
										
										
										
											2017-06-23 20:39:42 +10:00
										 |  |  | #include <vector>
 | 
					
						
							| 
									
										
										
										
											2015-11-20 13:28:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-13 16:25:49 -08:00
										 |  |  | #include "base/environment.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  | #include "base/strings/utf_string_conversions.h"
 | 
					
						
							| 
									
										
										
										
											2019-01-12 06:30:43 +05:30
										 |  |  | #include "base/task/post_task.h"
 | 
					
						
							|  |  |  | #include "content/public/browser/browser_task_traits.h"
 | 
					
						
							| 
									
										
										
										
											2016-04-15 16:20:36 +09:00
										 |  |  | #include "content/public/browser/browser_thread.h"
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/browser/notifications/notification_delegate.h"
 | 
					
						
							|  |  |  | #include "shell/browser/notifications/win/notification_presenter_win.h"
 | 
					
						
							|  |  |  | #include "shell/browser/win/scoped_hstring.h"
 | 
					
						
							|  |  |  | #include "shell/common/application_info.h"
 | 
					
						
							| 
									
										
										
										
											2020-10-09 08:26:39 -07:00
										 |  |  | #include "ui/base/l10n/l10n_util.h"
 | 
					
						
							|  |  |  | #include "ui/strings/grit/ui_strings.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-07 19:41:29 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  | using ABI::Windows::Data::Xml::Dom::IXmlAttribute; | 
					
						
							|  |  |  | using ABI::Windows::Data::Xml::Dom::IXmlDocument; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | using ABI::Windows::Data::Xml::Dom::IXmlDocumentIO; | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  | using ABI::Windows::Data::Xml::Dom::IXmlElement; | 
					
						
							|  |  |  | using ABI::Windows::Data::Xml::Dom::IXmlNamedNodeMap; | 
					
						
							|  |  |  | using ABI::Windows::Data::Xml::Dom::IXmlNode; | 
					
						
							|  |  |  | using ABI::Windows::Data::Xml::Dom::IXmlNodeList; | 
					
						
							|  |  |  | using ABI::Windows::Data::Xml::Dom::IXmlText; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | using Microsoft::WRL::Wrappers::HStringReference; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define RETURN_IF_FAILED(hr) \
 | 
					
						
							|  |  |  |   do {                       \ | 
					
						
							|  |  |  |     HRESULT _hrTemp = hr;    \ | 
					
						
							|  |  |  |     if (FAILED(_hrTemp)) {   \ | 
					
						
							|  |  |  |       return _hrTemp;        \ | 
					
						
							|  |  |  |     }                        \ | 
					
						
							|  |  |  |   } while (false) | 
					
						
							|  |  |  | #define REPORT_AND_RETURN_IF_FAILED(hr, msg)                             \
 | 
					
						
							|  |  |  |   do {                                                                   \ | 
					
						
							|  |  |  |     HRESULT _hrTemp = hr;                                                \ | 
					
						
							|  |  |  |     std::string _msgTemp = msg;                                          \ | 
					
						
							|  |  |  |     if (FAILED(_hrTemp)) {                                               \ | 
					
						
							|  |  |  |       std::string _err = _msgTemp + ",ERROR " + std::to_string(_hrTemp); \ | 
					
						
							|  |  |  |       if (IsDebuggingNotifications())                                    \ | 
					
						
							|  |  |  |         LOG(INFO) << _err;                                               \ | 
					
						
							|  |  |  |       Notification::NotificationFailed(_err);                            \ | 
					
						
							|  |  |  |       return _hrTemp;                                                    \ | 
					
						
							|  |  |  |     }                                                                    \ | 
					
						
							|  |  |  |   } while (false) | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 14:23:04 -07:00
										 |  |  | namespace electron { | 
					
						
							| 
									
										
										
										
											2015-11-16 16:47:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-20 13:28:37 +08:00
										 |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-13 16:25:49 -08:00
										 |  |  | bool IsDebuggingNotifications() { | 
					
						
							|  |  |  |   return base::Environment::Create()->HasVar("ELECTRON_DEBUG_NOTIFICATIONS"); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-20 13:28:37 +08:00
										 |  |  | }  // namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-24 14:40:58 +08:00
										 |  |  | // static
 | 
					
						
							|  |  |  | ComPtr<ABI::Windows::UI::Notifications::IToastNotificationManagerStatics> | 
					
						
							|  |  |  |     WindowsToastNotification::toast_manager_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // static
 | 
					
						
							|  |  |  | ComPtr<ABI::Windows::UI::Notifications::IToastNotifier> | 
					
						
							|  |  |  |     WindowsToastNotification::toast_notifier_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // static
 | 
					
						
							|  |  |  | bool WindowsToastNotification::Initialize() { | 
					
						
							|  |  |  |   // Just initialize, don't care if it fails or already initialized.
 | 
					
						
							|  |  |  |   Windows::Foundation::Initialize(RO_INIT_MULTITHREADED); | 
					
						
							| 
									
										
										
										
											2015-11-16 16:47:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ScopedHString toast_manager_str( | 
					
						
							|  |  |  |       RuntimeClass_Windows_UI_Notifications_ToastNotificationManager); | 
					
						
							|  |  |  |   if (!toast_manager_str.success()) | 
					
						
							| 
									
										
										
										
											2015-11-24 14:40:58 +08:00
										 |  |  |     return false; | 
					
						
							|  |  |  |   if (FAILED(Windows::Foundation::GetActivationFactory(toast_manager_str, | 
					
						
							|  |  |  |                                                        &toast_manager_))) | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-24 12:49:10 +02:00
										 |  |  |   if (IsRunningInDesktopBridge()) { | 
					
						
							| 
									
										
										
										
											2018-09-05 09:06:29 -07:00
										 |  |  |     // Ironically, the Desktop Bridge / UWP environment
 | 
					
						
							|  |  |  |     // requires us to not give Windows an appUserModelId.
 | 
					
						
							| 
									
										
										
										
											2018-09-19 13:10:26 +02:00
										 |  |  |     return SUCCEEDED(toast_manager_->CreateToastNotifier(&toast_notifier_)); | 
					
						
							| 
									
										
										
										
											2018-09-05 09:06:29 -07:00
										 |  |  |   } else { | 
					
						
							|  |  |  |     ScopedHString app_id; | 
					
						
							| 
									
										
										
										
											2018-10-24 12:49:10 +02:00
										 |  |  |     if (!GetAppUserModelID(&app_id)) | 
					
						
							| 
									
										
										
										
											2018-09-05 09:06:29 -07:00
										 |  |  |       return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return SUCCEEDED( | 
					
						
							| 
									
										
										
										
											2018-09-19 13:10:26 +02:00
										 |  |  |         toast_manager_->CreateToastNotifierWithId(app_id, &toast_notifier_)); | 
					
						
							| 
									
										
										
										
											2018-09-05 09:06:29 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-24 14:40:58 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-24 14:40:58 +08:00
										 |  |  | WindowsToastNotification::WindowsToastNotification( | 
					
						
							| 
									
										
										
										
											2015-12-25 11:05:48 +08:00
										 |  |  |     NotificationDelegate* delegate, | 
					
						
							|  |  |  |     NotificationPresenter* presenter) | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  |     : Notification(delegate, presenter) {} | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | WindowsToastNotification::~WindowsToastNotification() { | 
					
						
							| 
									
										
										
										
											2015-12-25 11:17:35 +08:00
										 |  |  |   // Remove the notification on exit.
 | 
					
						
							|  |  |  |   if (toast_notification_) { | 
					
						
							|  |  |  |     RemoveCallbacks(toast_notification_.Get()); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-24 21:03:27 +10:00
										 |  |  | void WindowsToastNotification::Show(const NotificationOptions& options) { | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   if (SUCCEEDED(ShowInternal(options))) { | 
					
						
							|  |  |  |     if (IsDebuggingNotifications()) | 
					
						
							|  |  |  |       LOG(INFO) << "Notification created"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (delegate()) | 
					
						
							|  |  |  |       delegate()->NotificationDisplayed(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WindowsToastNotification::Dismiss() { | 
					
						
							|  |  |  |   if (IsDebuggingNotifications()) | 
					
						
							|  |  |  |     LOG(INFO) << "Hiding notification"; | 
					
						
							|  |  |  |   toast_notifier_->Hide(toast_notification_.Get()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-13 16:31:02 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | HRESULT WindowsToastNotification::ShowInternal( | 
					
						
							|  |  |  |     const NotificationOptions& options) { | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlDocument> toast_xml; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   // The custom xml takes priority over the preset template.
 | 
					
						
							|  |  |  |   if (!options.toast_xml.empty()) { | 
					
						
							|  |  |  |     REPORT_AND_RETURN_IF_FAILED( | 
					
						
							|  |  |  |         XmlDocumentFromString(options.toast_xml.c_str(), &toast_xml), | 
					
						
							|  |  |  |         "XML: Invalid XML"); | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     auto* presenter_win = static_cast<NotificationPresenterWin*>(presenter()); | 
					
						
							|  |  |  |     std::wstring icon_path = | 
					
						
							|  |  |  |         presenter_win->SaveIconToFilesystem(options.icon, options.icon_url); | 
					
						
							|  |  |  |     REPORT_AND_RETURN_IF_FAILED( | 
					
						
							|  |  |  |         GetToastXml(toast_manager_.Get(), options.title, options.msg, icon_path, | 
					
						
							|  |  |  |                     options.timeout_type, options.silent, &toast_xml), | 
					
						
							|  |  |  |         "XML: Failed to create XML document"); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:17:35 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ScopedHString toast_str( | 
					
						
							|  |  |  |       RuntimeClass_Windows_UI_Notifications_ToastNotification); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:17:35 +08:00
										 |  |  |   if (!toast_str.success()) { | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     NotificationFailed("Creating ScopedHString failed"); | 
					
						
							|  |  |  |     return E_FAIL; | 
					
						
							| 
									
										
										
										
											2015-12-25 11:17:35 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  |   ComPtr<ABI::Windows::UI::Notifications::IToastNotificationFactory> | 
					
						
							|  |  |  |       toast_factory; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   REPORT_AND_RETURN_IF_FAILED( | 
					
						
							|  |  |  |       Windows::Foundation::GetActivationFactory(toast_str, &toast_factory), | 
					
						
							|  |  |  |       "WinAPI: GetActivationFactory failed"); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   REPORT_AND_RETURN_IF_FAILED(toast_factory->CreateToastNotification( | 
					
						
							|  |  |  |                                   toast_xml.Get(), &toast_notification_), | 
					
						
							|  |  |  |                               "WinAPI: CreateToastNotification failed"); | 
					
						
							| 
									
										
										
										
											2017-12-13 16:25:49 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   REPORT_AND_RETURN_IF_FAILED(SetupCallbacks(toast_notification_.Get()), | 
					
						
							|  |  |  |                               "WinAPI: SetupCallbacks failed"); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   REPORT_AND_RETURN_IF_FAILED(toast_notifier_->Show(toast_notification_.Get()), | 
					
						
							|  |  |  |                               "WinAPI: Show failed"); | 
					
						
							|  |  |  |   return S_OK; | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | HRESULT WindowsToastNotification::GetToastXml( | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  |     ABI::Windows::UI::Notifications::IToastNotificationManagerStatics* | 
					
						
							|  |  |  |         toastManager, | 
					
						
							| 
									
										
										
										
											2015-11-10 20:07:12 +08:00
										 |  |  |     const std::wstring& title, | 
					
						
							|  |  |  |     const std::wstring& msg, | 
					
						
							| 
									
										
										
										
											2015-12-24 20:03:54 +08:00
										 |  |  |     const std::wstring& icon_path, | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  |     const std::wstring& timeout_type, | 
					
						
							| 
									
										
										
										
											2017-05-30 19:06:51 +10:00
										 |  |  |     bool silent, | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |     IXmlDocument** toast_xml) { | 
					
						
							| 
									
										
										
										
											2015-11-10 18:04:09 -08:00
										 |  |  |   ABI::Windows::UI::Notifications::ToastTemplateType template_type; | 
					
						
							| 
									
										
										
										
											2015-11-10 20:07:12 +08:00
										 |  |  |   if (title.empty() || msg.empty()) { | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |     // Single line toast.
 | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  |     template_type = | 
					
						
							|  |  |  |         icon_path.empty() | 
					
						
							|  |  |  |             ? ABI::Windows::UI::Notifications::ToastTemplateType_ToastText01 | 
					
						
							|  |  |  |             : ABI::Windows::UI::Notifications:: | 
					
						
							|  |  |  |                   ToastTemplateType_ToastImageAndText01; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     REPORT_AND_RETURN_IF_FAILED( | 
					
						
							|  |  |  |         toast_manager_->GetTemplateContent(template_type, toast_xml), | 
					
						
							|  |  |  |         "XML: Fetching XML ToastImageAndText01 template failed"); | 
					
						
							|  |  |  |     std::wstring toastMsg = title.empty() ? msg : title; | 
					
						
							|  |  |  |     // we can't create an empty notification
 | 
					
						
							|  |  |  |     toastMsg = toastMsg.empty() ? L"[no message]" : toastMsg; | 
					
						
							|  |  |  |     REPORT_AND_RETURN_IF_FAILED( | 
					
						
							|  |  |  |         SetXmlText(*toast_xml, toastMsg), | 
					
						
							|  |  |  |         "XML: Filling XML ToastImageAndText01 template failed"); | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |     // Title and body toast.
 | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  |     template_type = | 
					
						
							|  |  |  |         icon_path.empty() | 
					
						
							|  |  |  |             ? ABI::Windows::UI::Notifications::ToastTemplateType_ToastText02 | 
					
						
							|  |  |  |             : ABI::Windows::UI::Notifications:: | 
					
						
							|  |  |  |                   ToastTemplateType_ToastImageAndText02; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     REPORT_AND_RETURN_IF_FAILED( | 
					
						
							|  |  |  |         toastManager->GetTemplateContent(template_type, toast_xml), | 
					
						
							|  |  |  |         "XML: Fetching XML ToastImageAndText02 template failed"); | 
					
						
							|  |  |  |     REPORT_AND_RETURN_IF_FAILED( | 
					
						
							|  |  |  |         SetXmlText(*toast_xml, title, msg), | 
					
						
							|  |  |  |         "XML: Filling XML ToastImageAndText02 template failed"); | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  |   // Configure the toast's timeout settings
 | 
					
						
							|  |  |  |   if (timeout_type == base::ASCIIToUTF16("never")) { | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     REPORT_AND_RETURN_IF_FAILED( | 
					
						
							|  |  |  |         (SetXmlScenarioReminder(*toast_xml)), | 
					
						
							|  |  |  |         "XML: Setting \"scenario\" option on notification failed"); | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   // Configure the toast's notification sound
 | 
					
						
							|  |  |  |   if (silent) { | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     REPORT_AND_RETURN_IF_FAILED( | 
					
						
							|  |  |  |         SetXmlAudioSilent(*toast_xml), | 
					
						
							|  |  |  |         "XML: Setting \"silent\" option on notification failed"); | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   // Configure the toast's image
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   if (!icon_path.empty()) { | 
					
						
							|  |  |  |     REPORT_AND_RETURN_IF_FAILED( | 
					
						
							|  |  |  |         SetXmlImage(*toast_xml, icon_path), | 
					
						
							|  |  |  |         "XML: Setting \"icon\" option on notification failed"); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   return S_OK; | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | HRESULT WindowsToastNotification::SetXmlScenarioReminder(IXmlDocument* doc) { | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  |   ScopedHString tag(L"toast"); | 
					
						
							|  |  |  |   if (!tag.success()) | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNodeList> node_list; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->GetElementsByTagName(tag, &node_list)); | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Check that root "toast" node exists
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> root; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(node_list->Item(0, &root)); | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // get attributes of root "toast" node
 | 
					
						
							| 
									
										
										
										
											2020-10-09 08:26:39 -07:00
										 |  |  |   ComPtr<IXmlNamedNodeMap> toast_attributes; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(root->get_Attributes(&toast_attributes)); | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlAttribute> scenario_attribute; | 
					
						
							|  |  |  |   ScopedHString scenario_str(L"scenario"); | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->CreateAttribute(scenario_str, &scenario_attribute)); | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> scenario_attribute_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(scenario_attribute.As(&scenario_attribute_node)); | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ScopedHString scenario_value(L"reminder"); | 
					
						
							|  |  |  |   if (!scenario_value.success()) | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     return E_FAIL; | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlText> scenario_text; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->CreateTextNode(scenario_value, &scenario_text)); | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> scenario_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(scenario_text.As(&scenario_node)); | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-09 08:26:39 -07:00
										 |  |  |   ComPtr<IXmlNode> scenario_backup_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(scenario_attribute_node->AppendChild(scenario_node.Get(), | 
					
						
							|  |  |  |                                                         &scenario_backup_node)); | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> scenario_attribute_pnode; | 
					
						
							| 
									
										
										
										
											2020-10-09 08:26:39 -07:00
										 |  |  |   RETURN_IF_FAILED(toast_attributes.Get()->SetNamedItem( | 
					
						
							|  |  |  |       scenario_attribute_node.Get(), &scenario_attribute_pnode)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Create "actions" wrapper
 | 
					
						
							|  |  |  |   ComPtr<IXmlElement> actions_wrapper_element; | 
					
						
							|  |  |  |   ScopedHString actions_wrapper_str(L"actions"); | 
					
						
							|  |  |  |   RETURN_IF_FAILED( | 
					
						
							|  |  |  |       doc->CreateElement(actions_wrapper_str, &actions_wrapper_element)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> actions_wrapper_node_tmp; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(actions_wrapper_element.As(&actions_wrapper_node_tmp)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Append actions wrapper node to toast xml
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> actions_wrapper_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED( | 
					
						
							|  |  |  |       root->AppendChild(actions_wrapper_node_tmp.Get(), &actions_wrapper_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNamedNodeMap> attributes_actions_wrapper; | 
					
						
							|  |  |  |   RETURN_IF_FAILED( | 
					
						
							|  |  |  |       actions_wrapper_node->get_Attributes(&attributes_actions_wrapper)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Add a "Dismiss" button
 | 
					
						
							|  |  |  |   // Create "action" tag
 | 
					
						
							|  |  |  |   ComPtr<IXmlElement> action_element; | 
					
						
							|  |  |  |   ScopedHString action_str(L"action"); | 
					
						
							|  |  |  |   RETURN_IF_FAILED(doc->CreateElement(action_str, &action_element)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> action_node_tmp; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(action_element.As(&action_node_tmp)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Append action node to actions wrapper in toast xml
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> action_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED( | 
					
						
							|  |  |  |       actions_wrapper_node->AppendChild(action_node_tmp.Get(), &action_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Setup attributes for action
 | 
					
						
							|  |  |  |   ComPtr<IXmlNamedNodeMap> action_attributes; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(action_node->get_Attributes(&action_attributes)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Create activationType attribute
 | 
					
						
							|  |  |  |   ComPtr<IXmlAttribute> activation_type_attribute; | 
					
						
							|  |  |  |   ScopedHString activation_type_str(L"activationType"); | 
					
						
							|  |  |  |   RETURN_IF_FAILED( | 
					
						
							|  |  |  |       doc->CreateAttribute(activation_type_str, &activation_type_attribute)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> activation_type_attribute_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED( | 
					
						
							|  |  |  |       activation_type_attribute.As(&activation_type_attribute_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Set activationType attribute to system
 | 
					
						
							|  |  |  |   ScopedHString activation_type_value(L"system"); | 
					
						
							|  |  |  |   if (!activation_type_value.success()) | 
					
						
							|  |  |  |     return E_FAIL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlText> activation_type_text; | 
					
						
							|  |  |  |   RETURN_IF_FAILED( | 
					
						
							|  |  |  |       doc->CreateTextNode(activation_type_value, &activation_type_text)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> activation_type_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(activation_type_text.As(&activation_type_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> activation_type_backup_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(activation_type_attribute_node->AppendChild( | 
					
						
							|  |  |  |       activation_type_node.Get(), &activation_type_backup_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Add activation type to the action attributes
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> activation_type_attribute_pnode; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(action_attributes.Get()->SetNamedItem( | 
					
						
							|  |  |  |       activation_type_attribute_node.Get(), &activation_type_attribute_pnode)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Create arguments attribute
 | 
					
						
							|  |  |  |   ComPtr<IXmlAttribute> arguments_attribute; | 
					
						
							|  |  |  |   ScopedHString arguments_str(L"arguments"); | 
					
						
							|  |  |  |   RETURN_IF_FAILED(doc->CreateAttribute(arguments_str, &arguments_attribute)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> arguments_attribute_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(arguments_attribute.As(&arguments_attribute_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Set arguments attribute to dismiss
 | 
					
						
							|  |  |  |   ScopedHString arguments_value(L"dismiss"); | 
					
						
							|  |  |  |   if (!arguments_value.success()) | 
					
						
							|  |  |  |     return E_FAIL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlText> arguments_text; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(doc->CreateTextNode(arguments_value, &arguments_text)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> arguments_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(arguments_text.As(&arguments_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> arguments_backup_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(arguments_attribute_node->AppendChild( | 
					
						
							|  |  |  |       arguments_node.Get(), &arguments_backup_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Add arguments to the action attributes
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> arguments_attribute_pnode; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(action_attributes.Get()->SetNamedItem( | 
					
						
							|  |  |  |       arguments_attribute_node.Get(), &arguments_attribute_pnode)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Create content attribute
 | 
					
						
							|  |  |  |   ComPtr<IXmlAttribute> content_attribute; | 
					
						
							|  |  |  |   ScopedHString content_str(L"content"); | 
					
						
							|  |  |  |   RETURN_IF_FAILED(doc->CreateAttribute(content_str, &content_attribute)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> content_attribute_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(content_attribute.As(&content_attribute_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Set content attribute to Dismiss
 | 
					
						
							|  |  |  |   ScopedHString content_value(l10n_util::GetStringUTF16(IDS_APP_CLOSE)); | 
					
						
							|  |  |  |   if (!content_value.success()) | 
					
						
							|  |  |  |     return E_FAIL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlText> content_text; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(doc->CreateTextNode(content_value, &content_text)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> content_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(content_text.As(&content_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> content_backup_node; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(content_attribute_node->AppendChild(content_node.Get(), | 
					
						
							|  |  |  |                                                        &content_backup_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Add content to the action attributes
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> content_attribute_pnode; | 
					
						
							|  |  |  |   return action_attributes.Get()->SetNamedItem(content_attribute_node.Get(), | 
					
						
							|  |  |  |                                                &content_attribute_pnode); | 
					
						
							| 
									
										
										
										
											2019-10-09 17:22:21 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | HRESULT WindowsToastNotification::SetXmlAudioSilent(IXmlDocument* doc) { | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  |   ScopedHString tag(L"toast"); | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   if (!tag.success()) | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     return E_FAIL; | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNodeList> node_list; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->GetElementsByTagName(tag, &node_list)); | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> root; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(node_list->Item(0, &root)); | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   ComPtr<IXmlElement> audio_element; | 
					
						
							|  |  |  |   ScopedHString audio_str(L"audio"); | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->CreateElement(audio_str, &audio_element)); | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   ComPtr<IXmlNode> audio_node_tmp; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(audio_element.As(&audio_node_tmp)); | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   // Append audio node to toast xml
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> audio_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(root->AppendChild(audio_node_tmp.Get(), &audio_node)); | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   // Create silent attribute
 | 
					
						
							|  |  |  |   ComPtr<IXmlNamedNodeMap> attributes; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(audio_node->get_Attributes(&attributes)); | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   ComPtr<IXmlAttribute> silent_attribute; | 
					
						
							|  |  |  |   ScopedHString silent_str(L"silent"); | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->CreateAttribute(silent_str, &silent_attribute)); | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   ComPtr<IXmlNode> silent_attribute_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(silent_attribute.As(&silent_attribute_node)); | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   // Set silent attribute to true
 | 
					
						
							|  |  |  |   ScopedHString silent_value(L"true"); | 
					
						
							|  |  |  |   if (!silent_value.success()) | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     return E_FAIL; | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   ComPtr<IXmlText> silent_text; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->CreateTextNode(silent_value, &silent_text)); | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IXmlNode> silent_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(silent_text.As(&silent_node)); | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   ComPtr<IXmlNode> child_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED( | 
					
						
							|  |  |  |       silent_attribute_node->AppendChild(silent_node.Get(), &child_node)); | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  |   ComPtr<IXmlNode> silent_attribute_pnode; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   return attributes.Get()->SetNamedItem(silent_attribute_node.Get(), | 
					
						
							|  |  |  |                                         &silent_attribute_pnode); | 
					
						
							| 
									
										
										
										
											2016-01-20 16:36:41 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | HRESULT WindowsToastNotification::SetXmlText(IXmlDocument* doc, | 
					
						
							|  |  |  |                                              const std::wstring& text) { | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ScopedHString tag; | 
					
						
							|  |  |  |   ComPtr<IXmlNodeList> node_list; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(GetTextNodeList(&tag, doc, &node_list, 1)); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlNode> node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(node_list->Item(0, &node)); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   return AppendTextToXml(doc, node.Get(), text); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | HRESULT WindowsToastNotification::SetXmlText(IXmlDocument* doc, | 
					
						
							|  |  |  |                                              const std::wstring& title, | 
					
						
							|  |  |  |                                              const std::wstring& body) { | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ScopedHString tag; | 
					
						
							|  |  |  |   ComPtr<IXmlNodeList> node_list; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(GetTextNodeList(&tag, doc, &node_list, 2)); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlNode> node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(node_list->Item(0, &node)); | 
					
						
							|  |  |  |   RETURN_IF_FAILED(AppendTextToXml(doc, node.Get(), title)); | 
					
						
							|  |  |  |   RETURN_IF_FAILED(node_list->Item(1, &node)); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   return AppendTextToXml(doc, node.Get(), body); | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | HRESULT WindowsToastNotification::SetXmlImage(IXmlDocument* doc, | 
					
						
							|  |  |  |                                               const std::wstring& icon_path) { | 
					
						
							| 
									
										
										
										
											2015-11-16 07:41:37 -08:00
										 |  |  |   ScopedHString tag(L"image"); | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   if (!tag.success()) | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     return E_FAIL; | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlNodeList> node_list; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->GetElementsByTagName(tag, &node_list)); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlNode> image_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(node_list->Item(0, &image_node)); | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlNamedNodeMap> attrs; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(image_node->get_Attributes(&attrs)); | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ScopedHString src(L"src"); | 
					
						
							|  |  |  |   if (!src.success()) | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     return E_FAIL; | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlNode> src_attr; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(attrs->GetNamedItem(src, &src_attr)); | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-24 20:03:54 +08:00
										 |  |  |   ScopedHString img_path(icon_path.c_str()); | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   if (!img_path.success()) | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     return E_FAIL; | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlText> src_text; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->CreateTextNode(img_path, &src_text)); | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlNode> src_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(src_text.As(&src_node)); | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlNode> child_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   return src_attr->AppendChild(src_node.Get(), &child_node); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | HRESULT WindowsToastNotification::GetTextNodeList(ScopedHString* tag, | 
					
						
							|  |  |  |                                                   IXmlDocument* doc, | 
					
						
							|  |  |  |                                                   IXmlNodeList** node_list, | 
					
						
							|  |  |  |                                                   uint32_t req_length) { | 
					
						
							| 
									
										
										
										
											2015-11-24 15:11:43 +08:00
										 |  |  |   tag->Reset(L"text"); | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   if (!tag->success()) | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     return E_FAIL; | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->GetElementsByTagName(*tag, node_list)); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-07 22:02:42 -08:00
										 |  |  |   uint32_t node_length; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED((*node_list)->get_Length(&node_length)); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   return node_length >= req_length; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | HRESULT WindowsToastNotification::AppendTextToXml(IXmlDocument* doc, | 
					
						
							|  |  |  |                                                   IXmlNode* node, | 
					
						
							|  |  |  |                                                   const std::wstring& text) { | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ScopedHString str(text); | 
					
						
							|  |  |  |   if (!str.success()) | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     return E_FAIL; | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlText> xml_text; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(doc->CreateTextNode(str, &xml_text)); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlNode> text_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(xml_text.As(&text_node)); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |   ComPtr<IXmlNode> append_node; | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(node->AppendChild(text_node.Get(), &append_node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return S_OK; | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  | HRESULT WindowsToastNotification::XmlDocumentFromString( | 
					
						
							|  |  |  |     const wchar_t* xmlString, | 
					
						
							|  |  |  |     IXmlDocument** doc) { | 
					
						
							|  |  |  |   ComPtr<IXmlDocument> xmlDoc; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(Windows::Foundation::ActivateInstance( | 
					
						
							|  |  |  |       HStringReference(RuntimeClass_Windows_Data_Xml_Dom_XmlDocument).Get(), | 
					
						
							|  |  |  |       &xmlDoc)); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:05:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   ComPtr<IXmlDocumentIO> docIO; | 
					
						
							|  |  |  |   RETURN_IF_FAILED(xmlDoc.As(&docIO)); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:05:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   RETURN_IF_FAILED(docIO->LoadXml(HStringReference(xmlString).Get())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return xmlDoc.CopyTo(doc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | HRESULT WindowsToastNotification::SetupCallbacks( | 
					
						
							|  |  |  |     ABI::Windows::UI::Notifications::IToastNotification* toast) { | 
					
						
							|  |  |  |   event_handler_ = Make<ToastEventHandler>(this); | 
					
						
							|  |  |  |   RETURN_IF_FAILED( | 
					
						
							|  |  |  |       toast->add_Activated(event_handler_.Get(), &activated_token_)); | 
					
						
							|  |  |  |   RETURN_IF_FAILED( | 
					
						
							|  |  |  |       toast->add_Dismissed(event_handler_.Get(), &dismissed_token_)); | 
					
						
							|  |  |  |   RETURN_IF_FAILED(toast->add_Failed(event_handler_.Get(), &failed_token_)); | 
					
						
							|  |  |  |   return S_OK; | 
					
						
							| 
									
										
										
										
											2015-12-25 11:05:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool WindowsToastNotification::RemoveCallbacks( | 
					
						
							|  |  |  |     ABI::Windows::UI::Notifications::IToastNotification* toast) { | 
					
						
							|  |  |  |   if (FAILED(toast->remove_Activated(activated_token_))) | 
					
						
							| 
									
										
										
										
											2015-11-10 19:50:38 +08:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2015-11-09 20:47:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-25 11:05:48 +08:00
										 |  |  |   if (FAILED(toast->remove_Dismissed(dismissed_token_))) | 
					
						
							| 
									
										
										
										
											2015-11-10 20:39:24 +01:00
										 |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-25 11:05:48 +08:00
										 |  |  |   return SUCCEEDED(toast->remove_Failed(failed_token_)); | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-07 19:41:29 -08:00
										 |  |  | /*
 | 
					
						
							|  |  |  | / Toast Event Handler | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2016-04-15 16:14:13 +09:00
										 |  |  | ToastEventHandler::ToastEventHandler(Notification* notification) | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  |     : notification_(notification->GetWeakPtr()) {} | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  | ToastEventHandler::~ToastEventHandler() {} | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | IFACEMETHODIMP ToastEventHandler::Invoke( | 
					
						
							| 
									
										
										
										
											2017-03-23 12:48:22 -07:00
										 |  |  |     ABI::Windows::UI::Notifications::IToastNotification* sender, | 
					
						
							|  |  |  |     IInspectable* args) { | 
					
						
							| 
									
										
										
										
											2019-09-18 15:58:00 -04:00
										 |  |  |   base::PostTask( | 
					
						
							| 
									
										
										
										
											2019-01-12 06:30:43 +05:30
										 |  |  |       FROM_HERE, {content::BrowserThread::UI}, | 
					
						
							| 
									
										
										
										
											2020-09-01 18:02:47 -07:00
										 |  |  |       base::BindOnce(&Notification::NotificationClicked, notification_)); | 
					
						
							| 
									
										
										
										
											2018-04-17 21:56:12 -04:00
										 |  |  |   if (IsDebuggingNotifications()) | 
					
						
							|  |  |  |     LOG(INFO) << "Notification clicked"; | 
					
						
							| 
									
										
										
										
											2017-12-13 16:25:49 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  |   return S_OK; | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  | IFACEMETHODIMP ToastEventHandler::Invoke( | 
					
						
							| 
									
										
										
										
											2015-11-10 18:04:09 -08:00
										 |  |  |     ABI::Windows::UI::Notifications::IToastNotification* sender, | 
					
						
							|  |  |  |     ABI::Windows::UI::Notifications::IToastDismissedEventArgs* e) { | 
					
						
							| 
									
										
										
										
											2019-09-18 15:58:00 -04:00
										 |  |  |   base::PostTask( | 
					
						
							| 
									
										
										
										
											2019-01-12 06:30:43 +05:30
										 |  |  |       FROM_HERE, {content::BrowserThread::UI}, | 
					
						
							| 
									
										
										
										
											2019-05-03 12:08:41 -07:00
										 |  |  |       base::BindOnce(&Notification::NotificationDismissed, notification_)); | 
					
						
							| 
									
										
										
										
											2018-04-17 21:56:12 -04:00
										 |  |  |   if (IsDebuggingNotifications()) | 
					
						
							|  |  |  |     LOG(INFO) << "Notification dismissed"; | 
					
						
							| 
									
										
										
										
											2017-12-13 16:31:02 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:27:18 +08:00
										 |  |  |   return S_OK; | 
					
						
							| 
									
										
										
										
											2015-11-04 10:13:52 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 20:39:24 +01:00
										 |  |  | IFACEMETHODIMP ToastEventHandler::Invoke( | 
					
						
							|  |  |  |     ABI::Windows::UI::Notifications::IToastNotification* sender, | 
					
						
							|  |  |  |     ABI::Windows::UI::Notifications::IToastFailedEventArgs* e) { | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |   HRESULT error; | 
					
						
							|  |  |  |   e->get_ErrorCode(&error); | 
					
						
							|  |  |  |   std::string errorMessage = | 
					
						
							|  |  |  |       "Notification failed. HRESULT:" + std::to_string(error); | 
					
						
							|  |  |  |   base::PostTask(FROM_HERE, {content::BrowserThread::UI}, | 
					
						
							|  |  |  |                  base::BindOnce(&Notification::NotificationFailed, | 
					
						
							|  |  |  |                                 notification_, errorMessage)); | 
					
						
							| 
									
										
										
										
											2018-04-17 21:56:12 -04:00
										 |  |  |   if (IsDebuggingNotifications()) | 
					
						
							| 
									
										
										
										
											2020-09-29 12:20:10 -07:00
										 |  |  |     LOG(INFO) << errorMessage; | 
					
						
							| 
									
										
										
										
											2017-12-13 16:25:49 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 20:39:24 +01:00
										 |  |  |   return S_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 14:23:04 -07:00
										 |  |  | }  // namespace electron
 |