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
|
|
|
|
2023-10-18 01:33:00 +02:00
|
|
|
#include <string_view>
|
|
|
|
|
2015-11-20 13:28:37 +08:00
|
|
|
#include <shlobj.h>
|
2020-09-29 12:20:10 -07:00
|
|
|
#include <wrl\wrappers\corewrappers.h>
|
2015-11-20 13:28:37 +08:00
|
|
|
|
2024-05-25 03:20:59 +08:00
|
|
|
#include "base/hash/hash.h"
|
2022-02-09 18:58:52 -08:00
|
|
|
#include "base/logging.h"
|
2024-01-24 16:43:31 -06:00
|
|
|
#include "base/strings/strcat.h"
|
2025-06-30 17:07:00 -04:00
|
|
|
#include "base/strings/string_number_conversions.h"
|
2025-08-22 14:38:13 -04:00
|
|
|
#include "base/strings/string_util.h"
|
2021-07-12 13:33:26 +09:00
|
|
|
#include "base/strings/string_util_win.h"
|
2025-08-22 14:38:13 -04:00
|
|
|
#include "base/strings/utf_string_conversions.h"
|
2019-01-12 06:30:43 +05:30
|
|
|
#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"
|
2025-08-22 14:38:13 -04:00
|
|
|
#include "third_party/libxml/chromium/xml_writer.h"
|
2021-03-18 15:55:51 -04:00
|
|
|
#include "ui/base/l10n/l10n_util_win.h"
|
2020-10-09 08:26:39 -07:00
|
|
|
#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::IXmlDocument;
|
2020-09-29 12:20:10 -07:00
|
|
|
using ABI::Windows::Data::Xml::Dom::IXmlDocumentIO;
|
|
|
|
using Microsoft::WRL::Wrappers::HStringReference;
|
|
|
|
|
2023-10-18 01:33:00 +02:00
|
|
|
namespace winui = ABI::Windows::UI;
|
|
|
|
|
2024-01-24 16:43:31 -06:00
|
|
|
#define RETURN_IF_FAILED(hr) \
|
|
|
|
do { \
|
|
|
|
if (const HRESULT _hrTemp = hr; FAILED(_hrTemp)) { \
|
|
|
|
return _hrTemp; \
|
|
|
|
} \
|
2020-09-29 12:20:10 -07:00
|
|
|
} while (false)
|
2024-01-24 16:43:31 -06:00
|
|
|
|
|
|
|
#define REPORT_AND_RETURN_IF_FAILED(hr, msg) \
|
|
|
|
do { \
|
|
|
|
if (const HRESULT _hrTemp = hr; FAILED(_hrTemp)) { \
|
|
|
|
std::string _err = \
|
|
|
|
base::StrCat({msg, ", ERROR ", base::NumberToString(_hrTemp)}); \
|
|
|
|
DebugLog(_err); \
|
|
|
|
Notification::NotificationFailed(_err); \
|
|
|
|
return _hrTemp; \
|
|
|
|
} \
|
2020-09-29 12:20:10 -07:00
|
|
|
} while (false)
|
2015-11-04 10:13:52 -08:00
|
|
|
|
2018-10-17 20:01:11 +02:00
|
|
|
namespace electron {
|
2015-11-16 16:47:34 +08:00
|
|
|
|
2015-11-20 13:28:37 +08:00
|
|
|
namespace {
|
|
|
|
|
2023-10-18 01:33:00 +02:00
|
|
|
// This string needs to be max 16 characters to work on Windows 10 prior to
|
|
|
|
// applying Creators Update (build 15063).
|
|
|
|
constexpr wchar_t kGroup[] = L"Notifications";
|
|
|
|
|
|
|
|
void DebugLog(std::string_view log_msg) {
|
2025-01-08 20:46:17 -06:00
|
|
|
if (electron::debug_notifications)
|
2023-10-18 01:33:00 +02:00
|
|
|
LOG(INFO) << log_msg;
|
2017-12-13 16:25:49 -08:00
|
|
|
}
|
2023-10-18 01:33:00 +02:00
|
|
|
|
2024-10-02 15:36:06 -05:00
|
|
|
std::wstring GetTag(const std::string_view notification_id) {
|
|
|
|
return base::NumberToWString(base::FastHash(notification_id));
|
2024-05-25 03:20:59 +08:00
|
|
|
}
|
|
|
|
|
2025-08-22 14:38:13 -04:00
|
|
|
constexpr char kToast[] = "toast";
|
|
|
|
constexpr char kVisual[] = "visual";
|
|
|
|
constexpr char kBinding[] = "binding";
|
|
|
|
constexpr char kTemplate[] = "template";
|
|
|
|
constexpr char kToastText01[] = "ToastText01";
|
|
|
|
constexpr char kToastText02[] = "ToastText02";
|
|
|
|
constexpr char kToastImageAndText01[] = "ToastImageAndText01";
|
|
|
|
constexpr char kToastImageAndText02[] = "ToastImageAndText02";
|
|
|
|
constexpr char kText[] = "text";
|
|
|
|
constexpr char kImage[] = "image";
|
|
|
|
constexpr char kPlacement[] = "placement";
|
|
|
|
constexpr char kAppLogoOverride[] = "appLogoOverride";
|
|
|
|
constexpr char kHintCrop[] = "hint-crop";
|
|
|
|
constexpr char kHintCropNone[] = "none";
|
|
|
|
constexpr char kSrc[] = "src";
|
|
|
|
constexpr char kAudio[] = "audio";
|
|
|
|
constexpr char kSilent[] = "silent";
|
|
|
|
constexpr char kTrue[] = "true";
|
|
|
|
constexpr char kID[] = "id";
|
|
|
|
constexpr char kScenario[] = "scenario";
|
|
|
|
constexpr char kReminder[] = "reminder";
|
|
|
|
constexpr char kActions[] = "actions";
|
|
|
|
constexpr char kAction[] = "action";
|
|
|
|
constexpr char kActivationType[] = "activationType";
|
|
|
|
constexpr char kSystem[] = "system";
|
|
|
|
constexpr char kArguments[] = "arguments";
|
|
|
|
constexpr char kDismiss[] = "dismiss";
|
|
|
|
// The XML version header that has to be stripped from the output.
|
|
|
|
constexpr char kXmlVersionHeader[] = "<?xml version=\"1.0\"?>\n";
|
|
|
|
|
|
|
|
const char* GetTemplateType(bool two_lines, bool has_icon) {
|
|
|
|
if (has_icon) {
|
|
|
|
return two_lines ? kToastImageAndText02 : kToastImageAndText01;
|
|
|
|
}
|
|
|
|
return two_lines ? kToastText02 : kToastText01;
|
|
|
|
}
|
|
|
|
|
2015-11-20 13:28:37 +08:00
|
|
|
} // namespace
|
|
|
|
|
2015-11-24 14:40:58 +08:00
|
|
|
// static
|
2023-10-18 01:33:00 +02:00
|
|
|
ComPtr<winui::Notifications::IToastNotificationManagerStatics>
|
2015-11-24 14:40:58 +08:00
|
|
|
WindowsToastNotification::toast_manager_;
|
|
|
|
|
|
|
|
// static
|
2023-10-18 01:33:00 +02:00
|
|
|
ComPtr<winui::Notifications::IToastNotifier>
|
2015-11-24 14:40:58 +08:00
|
|
|
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))) {
|
2023-10-18 01:33:00 +02:00
|
|
|
DebugLog("Notification created");
|
2020-09-29 12:20:10 -07:00
|
|
|
|
|
|
|
if (delegate())
|
|
|
|
delegate()->NotificationDisplayed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-18 01:33:00 +02:00
|
|
|
void WindowsToastNotification::Remove() {
|
|
|
|
DebugLog("Removing notification from action center");
|
|
|
|
|
|
|
|
ComPtr<winui::Notifications::IToastNotificationManagerStatics2>
|
|
|
|
toast_manager2;
|
|
|
|
if (FAILED(toast_manager_.As(&toast_manager2)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
ComPtr<winui::Notifications::IToastNotificationHistory> notification_history;
|
|
|
|
if (FAILED(toast_manager2->get_History(¬ification_history)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
ScopedHString app_id;
|
|
|
|
if (!GetAppUserModelID(&app_id))
|
|
|
|
return;
|
|
|
|
|
|
|
|
ScopedHString group(kGroup);
|
2024-05-25 03:20:59 +08:00
|
|
|
ScopedHString tag(GetTag(notification_id()));
|
2023-10-18 01:33:00 +02:00
|
|
|
notification_history->RemoveGroupedTagWithId(tag, group, app_id);
|
|
|
|
}
|
|
|
|
|
2020-09-29 12:20:10 -07:00
|
|
|
void WindowsToastNotification::Dismiss() {
|
2023-10-18 01:33:00 +02:00
|
|
|
DebugLog("Hiding notification");
|
|
|
|
|
2020-09-29 12:20:10 -07:00
|
|
|
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(
|
2021-07-12 13:33:26 +09:00
|
|
|
XmlDocumentFromString(base::as_wcstr(options.toast_xml), &toast_xml),
|
2020-09-29 12:20:10 -07:00
|
|
|
"XML: Invalid XML");
|
|
|
|
} else {
|
|
|
|
auto* presenter_win = static_cast<NotificationPresenterWin*>(presenter());
|
|
|
|
std::wstring icon_path =
|
|
|
|
presenter_win->SaveIconToFilesystem(options.icon, options.icon_url);
|
2025-08-22 14:38:13 -04:00
|
|
|
std::u16string toast_xml_str =
|
|
|
|
GetToastXml(options.title, options.msg, icon_path, options.timeout_type,
|
|
|
|
options.silent);
|
2020-09-29 12:20:10 -07:00
|
|
|
REPORT_AND_RETURN_IF_FAILED(
|
2025-08-22 14:38:13 -04:00
|
|
|
XmlDocumentFromString(base::as_wcstr(toast_xml_str), &toast_xml),
|
|
|
|
"XML: Invalid XML");
|
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
|
|
|
|
2023-10-18 01:33:00 +02:00
|
|
|
ComPtr<winui::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
|
|
|
|
2023-10-18 01:33:00 +02:00
|
|
|
ComPtr<winui::Notifications::IToastNotification2> toast2;
|
|
|
|
REPORT_AND_RETURN_IF_FAILED(
|
|
|
|
toast_notification_->QueryInterface(IID_PPV_ARGS(&toast2)),
|
|
|
|
"WinAPI: Getting Notification interface failed");
|
|
|
|
|
|
|
|
ScopedHString group(kGroup);
|
|
|
|
REPORT_AND_RETURN_IF_FAILED(toast2->put_Group(group),
|
|
|
|
"WinAPI: Setting group failed");
|
|
|
|
|
2024-05-25 03:20:59 +08:00
|
|
|
ScopedHString tag(GetTag(notification_id()));
|
2023-10-18 01:33:00 +02:00
|
|
|
REPORT_AND_RETURN_IF_FAILED(toast2->put_Tag(tag),
|
|
|
|
"WinAPI: Setting tag failed");
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2025-08-22 14:38:13 -04:00
|
|
|
std::u16string WindowsToastNotification::GetToastXml(
|
2021-07-12 13:33:26 +09:00
|
|
|
const std::u16string& title,
|
|
|
|
const std::u16string& msg,
|
2015-12-24 20:03:54 +08:00
|
|
|
const std::wstring& icon_path,
|
2021-07-12 13:33:26 +09:00
|
|
|
const std::u16string& timeout_type,
|
2025-08-22 14:38:13 -04:00
|
|
|
bool silent) {
|
|
|
|
XmlWriter xml_writer;
|
|
|
|
xml_writer.StartWriting();
|
2016-03-07 22:02:42 -08:00
|
|
|
|
2025-08-22 14:38:13 -04:00
|
|
|
// <toast ...>
|
|
|
|
xml_writer.StartElement(kToast);
|
|
|
|
|
|
|
|
const bool is_reminder = (timeout_type == u"never");
|
|
|
|
if (is_reminder) {
|
|
|
|
xml_writer.AddAttribute(kScenario, kReminder);
|
2019-10-09 17:22:21 +02:00
|
|
|
}
|
|
|
|
|
2025-08-22 14:38:13 -04:00
|
|
|
// <visual>
|
|
|
|
xml_writer.StartElement(kVisual);
|
|
|
|
// <binding template="<template>">
|
|
|
|
xml_writer.StartElement(kBinding);
|
|
|
|
const bool two_lines = (!title.empty() && !msg.empty());
|
|
|
|
xml_writer.AddAttribute(kTemplate,
|
|
|
|
GetTemplateType(two_lines, !icon_path.empty()));
|
|
|
|
|
|
|
|
// Add text nodes.
|
|
|
|
std::u16string line1;
|
|
|
|
std::u16string line2;
|
|
|
|
if (title.empty() || msg.empty()) {
|
|
|
|
line1 = title.empty() ? msg : title;
|
|
|
|
if (line1.empty())
|
|
|
|
line1 = u"[no message]";
|
|
|
|
xml_writer.StartElement(kText);
|
|
|
|
xml_writer.AddAttribute(kID, "1");
|
|
|
|
xml_writer.AppendElementContent(base::UTF16ToUTF8(line1));
|
|
|
|
xml_writer.EndElement(); // </text>
|
|
|
|
} else {
|
|
|
|
line1 = title;
|
|
|
|
line2 = msg;
|
|
|
|
xml_writer.StartElement(kText);
|
|
|
|
xml_writer.AddAttribute(kID, "1");
|
|
|
|
xml_writer.AppendElementContent(base::UTF16ToUTF8(line1));
|
|
|
|
xml_writer.EndElement();
|
|
|
|
xml_writer.StartElement(kText);
|
|
|
|
xml_writer.AddAttribute(kID, "2");
|
|
|
|
xml_writer.AppendElementContent(base::UTF16ToUTF8(line2));
|
|
|
|
xml_writer.EndElement();
|
2016-01-20 16:36:41 -08:00
|
|
|
}
|
2015-11-04 10:13:52 -08:00
|
|
|
|
2025-08-22 14:38:13 -04:00
|
|
|
// Optional icon as app logo override (small icon).
|
2020-09-29 12:20:10 -07:00
|
|
|
if (!icon_path.empty()) {
|
2025-08-22 14:38:13 -04:00
|
|
|
xml_writer.StartElement(kImage);
|
|
|
|
xml_writer.AddAttribute(kPlacement, kAppLogoOverride);
|
|
|
|
xml_writer.AddAttribute(kHintCrop, kHintCropNone);
|
|
|
|
xml_writer.AddAttribute(kSrc, base::WideToUTF8(icon_path));
|
|
|
|
xml_writer.EndElement(); // </image>
|
2020-09-29 12:20:10 -07:00
|
|
|
}
|
2015-11-04 10:13:52 -08:00
|
|
|
|
2025-08-22 14:38:13 -04:00
|
|
|
xml_writer.EndElement(); // </binding>
|
|
|
|
xml_writer.EndElement(); // </visual>
|
|
|
|
|
|
|
|
// <actions> (only to ensure reminder has a dismiss button).
|
|
|
|
if (is_reminder) {
|
|
|
|
xml_writer.StartElement(kActions);
|
|
|
|
xml_writer.StartElement(kAction);
|
|
|
|
xml_writer.AddAttribute(kActivationType, kSystem);
|
|
|
|
xml_writer.AddAttribute(kArguments, kDismiss);
|
|
|
|
xml_writer.AddAttribute(
|
|
|
|
"content", base::WideToUTF8(l10n_util::GetWideString(IDS_APP_CLOSE)));
|
|
|
|
xml_writer.EndElement(); // </action>
|
|
|
|
xml_writer.EndElement(); // </actions>
|
|
|
|
}
|
2015-11-04 10:13:52 -08:00
|
|
|
|
2025-08-22 14:38:13 -04:00
|
|
|
// Silent audio if requested.
|
|
|
|
if (silent) {
|
|
|
|
xml_writer.StartElement(kAudio);
|
|
|
|
xml_writer.AddAttribute(kSilent, kTrue);
|
|
|
|
xml_writer.EndElement(); // </audio>
|
|
|
|
}
|
2015-11-04 10:13:52 -08:00
|
|
|
|
2025-08-22 14:38:13 -04:00
|
|
|
xml_writer.EndElement(); // </toast>
|
2015-11-04 10:13:52 -08:00
|
|
|
|
2025-08-22 14:38:13 -04:00
|
|
|
xml_writer.StopWriting();
|
|
|
|
std::string xml = xml_writer.GetWrittenString();
|
|
|
|
if (base::StartsWith(xml, kXmlVersionHeader, base::CompareCase::SENSITIVE)) {
|
|
|
|
xml.erase(0, sizeof(kXmlVersionHeader) - 1);
|
|
|
|
}
|
2020-09-29 12:20:10 -07:00
|
|
|
|
2025-08-22 14:38:13 -04:00
|
|
|
return base::UTF8ToUTF16(xml);
|
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(
|
2023-10-18 01:33:00 +02:00
|
|
|
winui::Notifications::IToastNotification* toast) {
|
2020-09-29 12:20:10 -07:00
|
|
|
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(
|
2023-10-18 01:33:00 +02:00
|
|
|
winui::Notifications::IToastNotification* toast) {
|
2015-12-25 11:05:48 +08:00
|
|
|
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
|
|
|
|
2021-06-03 21:16:13 -07:00
|
|
|
ToastEventHandler::~ToastEventHandler() = default;
|
2015-11-04 10:13:52 -08:00
|
|
|
|
2015-11-10 18:27:18 +08:00
|
|
|
IFACEMETHODIMP ToastEventHandler::Invoke(
|
2023-10-18 01:33:00 +02:00
|
|
|
winui::Notifications::IToastNotification* sender,
|
2017-03-23 12:48:22 -07:00
|
|
|
IInspectable* args) {
|
2022-05-17 12:48:40 -04:00
|
|
|
content::GetUIThreadTaskRunner({})->PostTask(
|
|
|
|
FROM_HERE,
|
2020-09-01 18:02:47 -07:00
|
|
|
base::BindOnce(&Notification::NotificationClicked, notification_));
|
2023-10-18 01:33:00 +02:00
|
|
|
DebugLog("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(
|
2023-10-18 01:33:00 +02:00
|
|
|
winui::Notifications::IToastNotification* sender,
|
|
|
|
winui::Notifications::IToastDismissedEventArgs* e) {
|
2022-05-17 12:48:40 -04:00
|
|
|
content::GetUIThreadTaskRunner({})->PostTask(
|
2023-10-18 01:33:00 +02:00
|
|
|
FROM_HERE, base::BindOnce(&Notification::NotificationDismissed,
|
|
|
|
notification_, false));
|
|
|
|
DebugLog("Notification dismissed");
|
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(
|
2023-10-18 01:33:00 +02:00
|
|
|
winui::Notifications::IToastNotification* sender,
|
|
|
|
winui::Notifications::IToastFailedEventArgs* e) {
|
2020-09-29 12:20:10 -07:00
|
|
|
HRESULT error;
|
|
|
|
e->get_ErrorCode(&error);
|
2024-11-04 15:42:42 -06:00
|
|
|
std::string errorMessage = base::StrCat(
|
|
|
|
{"Notification failed. HRESULT:", base::NumberToString(error)});
|
2022-05-17 12:48:40 -04:00
|
|
|
content::GetUIThreadTaskRunner({})->PostTask(
|
|
|
|
FROM_HERE, base::BindOnce(&Notification::NotificationFailed,
|
2020-09-29 12:20:10 -07:00
|
|
|
notification_, errorMessage));
|
2023-10-18 01:33:00 +02:00
|
|
|
DebugLog(errorMessage);
|
2017-12-13 16:25:49 -08:00
|
|
|
|
2015-11-10 20:39:24 +01:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2018-10-17 20:01:11 +02:00
|
|
|
} // namespace electron
|