diff --git a/docs/api/notification.md b/docs/api/notification.md index 5ebdf77fbc7a4..420bb9a4a7621 100644 --- a/docs/api/notification.md +++ b/docs/api/notification.md @@ -35,7 +35,7 @@ Returns `Boolean` - Whether or not desktop notifications are supported on the cu * `silent` Boolean (optional) - Whether or not to emit an OS notification noise when showing the notification. * `icon` (String | [NativeImage](native-image.md)) (optional) - An icon to use in the notification. * `hasReply` Boolean (optional) _macOS_ - Whether or not to add an inline reply option to the notification. - * `timeoutType` String (optional) _Linux_ - The timeout duration of the notification. + * `timeoutType` String (optional) _Linux_ _Windows_ - The timeout duration of the notification. Can be 'default' or 'never'. * `replyPlaceholder` String (optional) _macOS_ - The placeholder to write in the inline reply input field. * `sound` String (optional) _macOS_ - The name of the sound file to play when the notification is shown. * `actions` [NotificationAction[]](structures/notification-action.md) (optional) _macOS_ - Actions to add to the notification. Please read the available actions and limitations in the `NotificationAction` documentation. @@ -145,11 +145,11 @@ A `Boolean` property representing whether the notification is silent. A `Boolean` property representing whether the notification has a reply action. -#### `notification.timeoutType` _Linux_ +#### `notification.timeoutType` _Linux_ _Windows_ A `String` property representing the type of timeout duration for the notification. Can be 'default' or 'never'. -If 'never' is set, te notification never expires. It stays open until closed by the calling API or the user. +If `timeoutType` is set to 'never', the notification never expires. It stays open until closed by the calling API or the user. #### `notification.actions` diff --git a/shell/browser/api/atom_api_notification.cc b/shell/browser/api/atom_api_notification.cc index c23ffb359e167..be0c893a7c55a 100644 --- a/shell/browser/api/atom_api_notification.cc +++ b/shell/browser/api/atom_api_notification.cc @@ -152,7 +152,7 @@ void Notification::SetHasReply(bool new_has_reply) { has_reply_ = new_has_reply; } -void Notification::SetTimeoutType(bool new_timeout_type) { +void Notification::SetTimeoutType(const base::string16& new_timeout_type) { timeout_type_ = new_timeout_type; } diff --git a/shell/browser/notifications/win/windows_toast_notification.cc b/shell/browser/notifications/win/windows_toast_notification.cc index 7306e39f6cdf9..611e3090a671a 100644 --- a/shell/browser/notifications/win/windows_toast_notification.cc +++ b/shell/browser/notifications/win/windows_toast_notification.cc @@ -149,6 +149,7 @@ bool WindowsToastNotification::GetToastXml( const std::wstring& title, const std::wstring& msg, const std::wstring& icon_path, + const std::wstring& timeout_type, bool silent, IXmlDocument** toast_xml) { ABI::Windows::UI::Notifications::ToastTemplateType template_type; @@ -183,6 +184,15 @@ bool WindowsToastNotification::GetToastXml( } } + // Configure the toast's timeout settings + if (timeout_type == base::ASCIIToUTF16("never")) { + if (FAILED(SetXmlScenarioReminder(*toast_xml))) { + if (IsDebuggingNotifications()) + LOG(INFO) << "Setting \"scenario\" option on notification failed"; + return false; + } + } + // Configure the toast's notification sound if (silent) { if (FAILED(SetXmlAudioSilent(*toast_xml))) { @@ -201,6 +211,56 @@ bool WindowsToastNotification::GetToastXml( return true; } +bool WindowsToastNotification::SetXmlScenarioReminder(IXmlDocument* doc) { + ScopedHString tag(L"toast"); + if (!tag.success()) + return false; + + ComPtr node_list; + if (FAILED(doc->GetElementsByTagName(tag, &node_list))) + return false; + + // Check that root "toast" node exists + ComPtr root; + if (FAILED(node_list->Item(0, &root))) + return false; + + // get attributes of root "toast" node + ComPtr attributes; + if (FAILED(root->get_Attributes(&attributes))) + return false; + + ComPtr scenario_attribute; + ScopedHString scenario_str(L"scenario"); + if (FAILED(doc->CreateAttribute(scenario_str, &scenario_attribute))) + return false; + + ComPtr scenario_attribute_node; + if (FAILED(scenario_attribute.As(&scenario_attribute_node))) + return false; + + ScopedHString scenario_value(L"reminder"); + if (!scenario_value.success()) + return false; + + ComPtr scenario_text; + if (FAILED(doc->CreateTextNode(scenario_value, &scenario_text))) + return false; + + ComPtr scenario_node; + if (FAILED(scenario_text.As(&scenario_node))) + return false; + + ComPtr child_node; + if (FAILED(scenario_attribute_node->AppendChild(scenario_node.Get(), + &child_node))) + return false; + + ComPtr scenario_attribute_pnode; + return SUCCEEDED(attributes.Get()->SetNamedItem(scenario_attribute_node.Get(), + &scenario_attribute_pnode)); +} + bool WindowsToastNotification::SetXmlAudioSilent(IXmlDocument* doc) { ScopedHString tag(L"toast"); if (!tag.success()) diff --git a/shell/browser/notifications/win/windows_toast_notification.h b/shell/browser/notifications/win/windows_toast_notification.h index 10c378480782e..eed2e2bed5d08 100644 --- a/shell/browser/notifications/win/windows_toast_notification.h +++ b/shell/browser/notifications/win/windows_toast_notification.h @@ -63,9 +63,11 @@ class WindowsToastNotification : public Notification { const std::wstring& title, const std::wstring& msg, const std::wstring& icon_path, + const std::wstring& timeout_type, const bool silent, ABI::Windows::Data::Xml::Dom::IXmlDocument** toastXml); bool SetXmlAudioSilent(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc); + bool SetXmlScenarioReminder(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc); bool SetXmlText(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, const std::wstring& text); bool SetXmlText(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc,