🏁 🍎 Add Silent Notification Support

* Implements support for silent notifications on Windows and OS X
 * Exposes bool `silent` to Linux notification presenters
This commit is contained in:
Felix Rieseberg 2016-01-20 16:36:41 -08:00
parent c9993ccc26
commit 728f0f985b
8 changed files with 95 additions and 10 deletions

View file

@ -89,7 +89,8 @@ LibnotifyNotification::~LibnotifyNotification() {
void LibnotifyNotification::Show(const base::string16& title, void LibnotifyNotification::Show(const base::string16& title,
const base::string16& body, const base::string16& body,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon) { const SkBitmap& icon,
const bool silent) {
notification_ = libnotify_loader_.notify_notification_new( notification_ = libnotify_loader_.notify_notification_new(
base::UTF16ToUTF8(title).c_str(), base::UTF16ToUTF8(title).c_str(),
base::UTF16ToUTF8(body).c_str(), base::UTF16ToUTF8(body).c_str(),

View file

@ -23,7 +23,8 @@ class LibnotifyNotification : public Notification {
void Show(const base::string16& title, void Show(const base::string16& title,
const base::string16& msg, const base::string16& msg,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon) override; const SkBitmap& icon,
const bool silent) override;
void Dismiss() override; void Dismiss() override;
private: private:

View file

@ -23,7 +23,8 @@ class CocoaNotification : public Notification {
void Show(const base::string16& title, void Show(const base::string16& title,
const base::string16& msg, const base::string16& msg,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon) override; const SkBitmap& icon,
const bool silent) override;
void Dismiss() override; void Dismiss() override;
void NotifyDisplayed(); void NotifyDisplayed();

View file

@ -31,7 +31,8 @@ CocoaNotification::~CocoaNotification() {
void CocoaNotification::Show(const base::string16& title, void CocoaNotification::Show(const base::string16& title,
const base::string16& body, const base::string16& body,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon) { const SkBitmap& icon,
const bool silent) {
notification_.reset([[NSUserNotification alloc] init]); notification_.reset([[NSUserNotification alloc] init]);
[notification_ setTitle:base::SysUTF16ToNSString(title)]; [notification_ setTitle:base::SysUTF16ToNSString(title)];
[notification_ setInformativeText:base::SysUTF16ToNSString(body)]; [notification_ setInformativeText:base::SysUTF16ToNSString(body)];
@ -42,6 +43,12 @@ void CocoaNotification::Show(const base::string16& title,
icon, base::mac::GetGenericRGBColorSpace()); icon, base::mac::GetGenericRGBColorSpace());
[notification_ setContentImage:image]; [notification_ setContentImage:image];
} }
if (silent) {
[notification_ setSoundName:nil];
} else {
[notification_ setSoundName:NSUserNotificationDefaultSoundName];
}
[NSUserNotificationCenter.defaultUserNotificationCenter [NSUserNotificationCenter.defaultUserNotificationCenter
deliverNotification:notification_]; deliverNotification:notification_];

View file

@ -22,7 +22,8 @@ class Notification {
virtual void Show(const base::string16& title, virtual void Show(const base::string16& title,
const base::string16& msg, const base::string16& msg,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon) = 0; const SkBitmap& icon,
const bool silent) = 0;
// Closes the notification, this instance will be destroyed after the // Closes the notification, this instance will be destroyed after the
// notification gets closed. // notification gets closed.
virtual void Dismiss() = 0; virtual void Dismiss() = 0;

View file

@ -57,7 +57,7 @@ void PlatformNotificationService::DisplayNotification(
auto notification = presenter->CreateNotification(adapter.get()); auto notification = presenter->CreateNotification(adapter.get());
if (notification) { if (notification) {
ignore_result(adapter.release()); // it will release itself automatically. ignore_result(adapter.release()); // it will release itself automatically.
notification->Show(data.title, data.body, data.icon, icon); notification->Show(data.title, data.body, data.icon, icon, data.silent);
*cancel_callback = base::Bind(&RemoveNotification, notification); *cancel_callback = base::Bind(&RemoveNotification, notification);
} }
} }

View file

@ -85,12 +85,13 @@ void WindowsToastNotification::Show(
const base::string16& title, const base::string16& title,
const base::string16& msg, const base::string16& msg,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon) { const SkBitmap& icon,
const bool silent) {
auto presenter_win = static_cast<NotificationPresenterWin*>(presenter()); auto presenter_win = static_cast<NotificationPresenterWin*>(presenter());
std::wstring icon_path = presenter_win->SaveIconToFilesystem(icon, icon_url); std::wstring icon_path = presenter_win->SaveIconToFilesystem(icon, icon_url);
ComPtr<IXmlDocument> toast_xml; ComPtr<IXmlDocument> toast_xml;
if(FAILED(GetToastXml(toast_manager_.Get(), title, msg, icon_path, &toast_xml))) { if(FAILED(GetToastXml(toast_manager_.Get(), title, msg, icon_path, silent, &toast_xml))) {
NotificationFailed(); NotificationFailed();
return; return;
} }
@ -152,6 +153,7 @@ bool WindowsToastNotification::GetToastXml(
const std::wstring& title, const std::wstring& title,
const std::wstring& msg, const std::wstring& msg,
const std::wstring& icon_path, const std::wstring& icon_path,
const bool silent,
IXmlDocument** toast_xml) { IXmlDocument** toast_xml) {
ABI::Windows::UI::Notifications::ToastTemplateType template_type; ABI::Windows::UI::Notifications::ToastTemplateType template_type;
if (title.empty() || msg.empty()) { if (title.empty() || msg.empty()) {
@ -171,14 +173,83 @@ bool WindowsToastNotification::GetToastXml(
if (!SetXmlText(*toast_xml, title, msg)) if (!SetXmlText(*toast_xml, title, msg))
return false; return false;
} }
// Configure the toast's notification sound
if (silent) {
if (FAILED(SetXmlAudioSilent(*toast_xml)))
return false;
}
// Toast has image // Configure the toast's image
if (!icon_path.empty()) if (!icon_path.empty())
return SetXmlImage(*toast_xml, icon_path); return SetXmlImage(*toast_xml, icon_path);
return true; return true;
} }
bool WindowsToastNotification::SetXmlAudioSilent(
IXmlDocument* doc) {
ScopedHString tag(L"toast");
if (!tag.success())
return false;
ComPtr<IXmlNodeList> node_list;
if (FAILED(doc->GetElementsByTagName(tag, &node_list)))
return false;
ComPtr<IXmlNode> root;
if (FAILED(node_list->Item(0, &root)))
return false;
ComPtr<IXmlElement> audio_element;
ScopedHString audio_str(L"audio");
if (FAILED(doc->CreateElement(audio_str, &audio_element)))
return false;
ComPtr<IXmlNode> audio_node_tmp;
if (FAILED(audio_element.As(&audio_node_tmp)))
return false;
// Append audio node to toast xml
ComPtr<IXmlNode> audio_node;
if (FAILED(root->AppendChild(audio_node_tmp.Get(), &audio_node)))
return false;
// Create silent attribute
ComPtr<IXmlNamedNodeMap> attributes;
if (FAILED(audio_node->get_Attributes(&attributes)))
return false;
ComPtr<IXmlAttribute> silent_attribute;
ScopedHString silent_str(L"silent");
if (FAILED(doc->CreateAttribute(silent_str, &silent_attribute)))
return false;
ComPtr<IXmlNode> silent_attribute_node;
if (FAILED(silent_attribute.As(&silent_attribute_node)))
return false;
// Set silent attribute to true
ScopedHString silent_value(L"true");
if (!silent_value.success())
return false;
ComPtr<IXmlText> silent_text;
if (FAILED(doc->CreateTextNode(silent_value, &silent_text)))
return false;
ComPtr<IXmlNode> silent_node;
if (FAILED(silent_text.As(&silent_node)))
return false;
ComPtr<IXmlNode> child_node;
if (FAILED(silent_attribute_node->AppendChild(silent_node.Get(), &child_node)))
return false;
ComPtr<IXmlNode> silent_attribute_pnode;
return SUCCEEDED(attributes.Get()->SetNamedItem(silent_attribute_node.Get(), &silent_attribute_pnode));
}
bool WindowsToastNotification::SetXmlText( bool WindowsToastNotification::SetXmlText(
IXmlDocument* doc, const std::wstring& text) { IXmlDocument* doc, const std::wstring& text) {
ScopedHString tag; ScopedHString tag;

View file

@ -42,7 +42,8 @@ class WindowsToastNotification : public Notification {
void Show(const base::string16& title, void Show(const base::string16& title,
const base::string16& msg, const base::string16& msg,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon) override; const SkBitmap& icon,
const bool silent) override;
void Dismiss() override; void Dismiss() override;
private: private:
@ -56,7 +57,9 @@ class WindowsToastNotification : public Notification {
const std::wstring& title, const std::wstring& title,
const std::wstring& msg, const std::wstring& msg,
const std::wstring& icon_path, const std::wstring& icon_path,
const bool silent,
ABI::Windows::Data::Xml::Dom::IXmlDocument** toastXml); ABI::Windows::Data::Xml::Dom::IXmlDocument** toastXml);
bool SetXmlAudioSilent(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc);
bool SetXmlText(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, bool SetXmlText(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc,
const std::wstring& text); const std::wstring& text);
bool SetXmlText(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, bool SetXmlText(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc,