diff --git a/brightray/brightray.gyp b/brightray/brightray.gyp index db04f5672ceb..9b548e70a7fa 100644 --- a/brightray/brightray.gyp +++ b/brightray/brightray.gyp @@ -164,8 +164,11 @@ 'msvs_settings': { 'VCLinkerTool': { 'AdditionalDependencies': [ + # Windows Runtime. + 'crypt32.lib', 'runtimeobject.lib', - 'windowsapp.lib' + 'shlwapi.lib', + 'windowsapp.lib', ], }, }, @@ -203,8 +206,6 @@ 'msvs_settings': { 'VCLinkerTool': { 'AdditionalDependencies': [ - 'Shlwapi.lib', - 'Crypt32.lib', 'advapi32.lib', 'dbghelp.lib', 'delayimp.lib', diff --git a/brightray/browser/platform_notification_service_impl.cc b/brightray/browser/platform_notification_service_impl.cc index 36045f6db4f2..e93408ebe108 100644 --- a/brightray/browser/platform_notification_service_impl.cc +++ b/brightray/browser/platform_notification_service_impl.cc @@ -24,13 +24,13 @@ PlatformNotificationServiceImpl::PlatformNotificationServiceImpl() {} PlatformNotificationServiceImpl::~PlatformNotificationServiceImpl() {} NotificationPresenter* PlatformNotificationServiceImpl::notification_presenter() { + #if defined(OS_WIN) + // Bail out if on Windows 7 or even lower, no operating will follow + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return nullptr; + #endif + if (!notification_presenter_) { - #if defined(OS_WIN) - // Bail out if on Windows 7 or even lower, no operating will follow - if (base::win::GetVersion() < base::win::VERSION_WIN8) { - return notification_presenter_.get(); - } - #endif // Create a new presenter if on OS X, Linux, or Windows 8+ notification_presenter_.reset(NotificationPresenter::Create()); } diff --git a/brightray/browser/win/notification_presenter_win.cc b/brightray/browser/win/notification_presenter_win.cc index 8870de36e3e1..9b981443dcbc 100644 --- a/brightray/browser/win/notification_presenter_win.cc +++ b/brightray/browser/win/notification_presenter_win.cc @@ -4,16 +4,16 @@ // found in the LICENSE-CHROMIUM file. #include "browser/win/notification_presenter_win.h" + #include "base/win/windows_version.h" +#include "browser/win/windows_toast_notification.h" +#include "common/application_info.h" #include "content/public/browser/desktop_notification_delegate.h" #include "content/public/common/platform_notification_data.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "common/application_info.h" #pragma comment(lib, "runtimeobject.lib") -#pragma comment(lib, "Crypt32.lib") -using namespace WinToasts; using namespace Microsoft::WRL; using namespace ABI::Windows::UI::Notifications; using namespace ABI::Windows::Data::Xml::Dom; @@ -21,47 +21,40 @@ using namespace ABI::Windows::Foundation; namespace brightray { +namespace { + +void RemoveNotification(base::WeakPtr notification) { + if (notification) + notification->DismissNotification(); +} + +} // namespace + // static NotificationPresenter* NotificationPresenter::Create() { return new NotificationPresenterWin; } NotificationPresenterWin::NotificationPresenterWin() { - m_lastNotification = nullptr; } NotificationPresenterWin::~NotificationPresenterWin() { } void NotificationPresenterWin::ShowNotification( - const content::PlatformNotificationData& data, - const SkBitmap& icon, - scoped_ptr delegate_ptr, - base::Closure* cancel_callback) { - - std::wstring title = data.title; - std::wstring body = data.body; - std::string iconPath = data.icon.spec(); - std::string appName = GetApplicationName(); + const content::PlatformNotificationData& data, + const SkBitmap& icon, + scoped_ptr delegate, + base::Closure* cancel_callback) { + // This class manages itself. + auto notification = new WindowsToastNotification( + GetApplicationName(), delegate.Pass()); + notification->ShowNotification(data.title, data.body, data.icon.spec()); - // toast notification supported in version >= Windows 8 - // for prior versions, use Tray.displayBalloon - if (base::win::GetVersion() >= base::win::VERSION_WIN8) { - wtn = new WindowsToastNotification(appName.c_str(), delegate_ptr.release()); - wtn->ShowNotification(title.c_str(), body.c_str(), iconPath, m_lastNotification); - } - if (cancel_callback) { *cancel_callback = base::Bind( - &NotificationPresenterWin::RemoveNotification, - base::Unretained(this)); + &RemoveNotification, notification->GetWeakPtr()); } } -void NotificationPresenterWin::RemoveNotification() { - if (m_lastNotification != nullptr && wtn != NULL) { - wtn->DismissNotification(m_lastNotification); - } -} - -} // namespace brightray \ No newline at end of file +} // namespace brightray diff --git a/brightray/browser/win/notification_presenter_win.h b/brightray/browser/win/notification_presenter_win.h index a2ecd81b9526..5bc84feb92af 100644 --- a/brightray/browser/win/notification_presenter_win.h +++ b/brightray/browser/win/notification_presenter_win.h @@ -13,18 +13,10 @@ // windowsNotification.onclick = function () { console.log("Notification clicked") }; // windowsNotification.onclose = function () { console.log("Notification dismissed") }; +#ifndef BRIGHTRAY_BROWSER_WIN_NOTIFICATION_PRESENTER_WIN_H_ +#define BRIGHTRAY_BROWSER_WIN_NOTIFICATION_PRESENTER_WIN_H_ -#ifndef BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_WIN_H_ -#define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_WIN_H_ - -#include "base/compiler_specific.h" #include "browser/notification_presenter.h" -#include "windows_toast_notification.h" - -#include -#include -#include -#include namespace brightray { @@ -38,14 +30,11 @@ class NotificationPresenterWin : public NotificationPresenter { const SkBitmap& icon, scoped_ptr delegate, base::Closure* cancel_callback) override; - - void RemoveNotification(); private: - WinToasts::WindowsToastNotification* wtn; - Microsoft::WRL::ComPtr m_lastNotification; + DISALLOW_COPY_AND_ASSIGN(NotificationPresenterWin); }; } // namespace -#endif // BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_WIN_H_ +#endif // BRIGHTRAY_BROWSER_WIN_NOTIFICATION_PRESENTER_WIN_H_ diff --git a/brightray/browser/win/scoped_hstring.cc b/brightray/browser/win/scoped_hstring.cc new file mode 100644 index 000000000000..e3f5cbd29bbb --- /dev/null +++ b/brightray/browser/win/scoped_hstring.cc @@ -0,0 +1,33 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE-CHROMIUM file. + +#include "browser/win/scoped_hstring.h" + +#include + +ScopedHString::ScopedHString(const wchar_t* source) + : str_(nullptr) { + Set(source); +} + +ScopedHString::ScopedHString(const std::wstring& source) + : str_(nullptr) { + WindowsCreateString(source.c_str(), source.length(), &str_); +} + +ScopedHString::ScopedHString() : str_(nullptr) { +} + +ScopedHString::~ScopedHString() { + if (str_) + WindowsDeleteString(str_); +} + +void ScopedHString::Set(const wchar_t* source) { + if (str_) { + WindowsDeleteString(str_); + str_ = nullptr; + } + WindowsCreateString(source, wcslen(source), &str_); +} diff --git a/brightray/browser/win/scoped_hstring.h b/brightray/browser/win/scoped_hstring.h new file mode 100644 index 000000000000..de03c0469b3a --- /dev/null +++ b/brightray/browser/win/scoped_hstring.h @@ -0,0 +1,39 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE-CHROMIUM file. + +#ifndef BRIGHTRAY_BROWSER_WIN_SCOPED_HSTRING_H_ +#define BRIGHTRAY_BROWSER_WIN_SCOPED_HSTRING_H_ + +#include + +#include +#include + +#include "base/basictypes.h" + +class ScopedHString { + public: + // Copy from |source|. + ScopedHString(const wchar_t* source); + ScopedHString(const std::wstring& source); + // Create empty string. + ScopedHString(); + ~ScopedHString(); + + // Sets to |source|. + void Set(const wchar_t* source); + + // Returns string. + operator HSTRING() const { return str_; } + + // Whether there is a string created. + bool success() const { return str_; } + + private: + HSTRING str_; + + DISALLOW_COPY_AND_ASSIGN(ScopedHString); +}; + +#endif // BRIGHTRAY_BROWSER_WIN_SCOPED_HSTRING_H_ diff --git a/brightray/browser/win/windows_toast_notification.cc b/brightray/browser/win/windows_toast_notification.cc index 830a6f670035..cbeda90c360a 100644 --- a/brightray/browser/win/windows_toast_notification.cc +++ b/brightray/browser/win/windows_toast_notification.cc @@ -3,364 +3,266 @@ // Thanks to both of those folks mentioned above who first thought up a bunch of this code // and released it as MIT to the world. -#include "windows_toast_notification.h" +#include "browser/win/windows_toast_notification.h" + +#include "base/strings/utf_string_conversions.h" +#include "browser/win/scoped_hstring.h" #include "content/public/browser/desktop_notification_delegate.h" -using namespace WinToasts; -using namespace Microsoft::WRL; -using namespace ABI::Windows::UI::Notifications; using namespace ABI::Windows::Data::Xml::Dom; -#define BREAK_IF_BAD(hr) if(!SUCCEEDED(hr)) break; +namespace brightray { -namespace WinToasts { +namespace { // Initialize Windows Runtime -static HRESULT init = Windows::Foundation::Initialize(RO_INIT_MULTITHREADED); +HRESULT init = Windows::Foundation::Initialize(RO_INIT_MULTITHREADED); -WindowsToastNotification::WindowsToastNotification(const char* appName, content::DesktopNotificationDelegate* delegate) -{ - HSTRING toastNotifMgrStr = NULL; - HSTRING appId = NULL; +} // namespace - HRESULT hr = CreateHString(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager, &toastNotifMgrStr); +WindowsToastNotification::WindowsToastNotification( + const std::string& app_name, + scoped_ptr delegate) + : delegate_(delegate.Pass()), + weak_factory_(this) { + ScopedHString toast_manager_str( + RuntimeClass_Windows_UI_Notifications_ToastNotificationManager); + if (!toast_manager_str.success()) + return; + HRESULT hr = Windows::Foundation::GetActivationFactory( + toast_manager_str, &toast_manager_); + if (FAILED(hr)) + return; - hr = Windows::Foundation::GetActivationFactory(toastNotifMgrStr, &m_toastManager); + ScopedHString app_id(base::UTF8ToUTF16(app_name).c_str()); + if (!app_id.success()) + return; - WCHAR wAppName[MAX_PATH]; - swprintf(wAppName, ARRAYSIZE(wAppName), L"%S", appName); - hr = CreateHString(wAppName, &appId); - - m_toastManager->CreateToastNotifierWithId(appId, &m_toastNotifier); - - if (toastNotifMgrStr != NULL) { - WindowsDeleteString(toastNotifMgrStr); - } - - if (appId != NULL) { - WindowsDeleteString(appId); - } - - n_delegate = delegate; + toast_manager_->CreateToastNotifierWithId(app_id, &toast_notifier_); } -WindowsToastNotification::~WindowsToastNotification() -{ - if (n_delegate) { - delete n_delegate; - } +WindowsToastNotification::~WindowsToastNotification() { } -void WindowsToastNotification::ShowNotification(const WCHAR* title, const WCHAR* msg, std::string iconPath, ComPtr& toast) -{ - HRESULT hr; - HSTRING toastNotifStr = NULL; +void WindowsToastNotification::ShowNotification( + const std::wstring& title, + const std::wstring& msg, + std::string icon_path) { + ComPtr toast_xml; + if(FAILED(GetToastXml(toast_manager_.Get(), title, msg, icon_path, &toast_xml))) + return; - do { - ComPtr toastXml; - hr = GetToastXml(m_toastManager.Get(), title, msg, iconPath, &toastXml); - BREAK_IF_BAD(hr); + ScopedHString toast_str( + RuntimeClass_Windows_UI_Notifications_ToastNotification); + if (!toast_str.success()) + return; - hr = CreateHString(RuntimeClass_Windows_UI_Notifications_ToastNotification, &toastNotifStr); - BREAK_IF_BAD(hr); + ComPtr toast_factory; + if (FAILED(Windows::Foundation::GetActivationFactory(toast_str, + &toast_factory))) + return; - ComPtr toastFactory; - hr = Windows::Foundation::GetActivationFactory(toastNotifStr, &toastFactory); - BREAK_IF_BAD(hr); + if (FAILED(toast_factory->CreateToastNotification(toast_xml.Get(), + &toast_notification_))) + return; - hr = toastFactory->CreateToastNotification(toastXml.Get(), &toast); - BREAK_IF_BAD(hr); + if (FAILED(SetupCallbacks(toast_notification_.Get()))) + return; - hr = SetupCallbacks(toast.Get()); - BREAK_IF_BAD(hr); + if (FAILED(toast_notifier_->Show(toast_notification_.Get()))) + return; - hr = m_toastNotifier->Show(toast.Get()); - BREAK_IF_BAD(hr); - - n_delegate->NotificationDisplayed(); - } while (FALSE); - - if (toastNotifStr != NULL) { - WindowsDeleteString(toastNotifStr); - } + delegate_->NotificationDisplayed(); } -void WindowsToastNotification::DismissNotification(ComPtr toast) -{ - m_toastNotifier->Hide(toast.Get()); +void WindowsToastNotification::DismissNotification() { + toast_notifier_->Hide(toast_notification_.Get()); } -void WindowsToastNotification::NotificationClicked() -{ - delete this; +void WindowsToastNotification::NotificationClicked() { + delegate_->NotificationClick(); + delete this; } -void WindowsToastNotification::NotificationDismissed() -{ - delete this; +void WindowsToastNotification::NotificationDismissed() { + delegate_->NotificationClosed(); + delete this; } -HRESULT WindowsToastNotification::GetToastXml( +bool WindowsToastNotification::GetToastXml( IToastNotificationManagerStatics* toastManager, - const WCHAR* title, - const WCHAR* msg, - std::string iconPath, - IXmlDocument** toastXml) { - - HRESULT hr; - ToastTemplateType templateType; - if (title == NULL || msg == NULL) { - // Single line toast - templateType = iconPath.length() == 0 ? ToastTemplateType_ToastText01 : ToastTemplateType_ToastImageAndText01; - hr = m_toastManager->GetTemplateContent(templateType, toastXml); - if (SUCCEEDED(hr)) { - const WCHAR* text = title != NULL ? title : msg; - hr = SetXmlText(*toastXml, text); - } - } else { - // Title and body toast - templateType = iconPath.length() == 0 ? ToastTemplateType_ToastText02 : ToastTemplateType_ToastImageAndText02; - hr = toastManager->GetTemplateContent(templateType, toastXml); - if (SUCCEEDED(hr)) { - hr = SetXmlText(*toastXml, title, msg); - } - } + const std::wstring& title, + const std::wstring& msg, + std::string icon_path, + IXmlDocument** toast_xml) { + ToastTemplateType template_type; + if (title.empty() || msg.empty()) { + // Single line toast. + template_type = icon_path.empty() ? ToastTemplateType_ToastText01 : + ToastTemplateType_ToastImageAndText01; + if (FAILED(toast_manager_->GetTemplateContent(template_type, toast_xml))) + return false; + if (!SetXmlText(*toast_xml, title.empty() ? msg : title)) + return false; + } else { + // Title and body toast. + template_type = icon_path.empty() ? ToastTemplateType_ToastText02 : + ToastTemplateType_ToastImageAndText02; + if (FAILED(toastManager->GetTemplateContent(template_type, toast_xml))) + return false; + if (!SetXmlText(*toast_xml, title, msg)) + return false; + } - if (iconPath.length() != 0 && SUCCEEDED(hr)) { - // Toast has image - if (SUCCEEDED(hr)) { - hr = SetXmlImage(*toastXml, iconPath); - } + // Toast has image + if (!icon_path.empty()) + return SetXmlImage(*toast_xml, icon_path); - // Don't stop a notification from showing just because an image couldn't be displayed. By default the app icon will be shown. - hr = S_OK; - } - - return hr; + return true; } -HRESULT WindowsToastNotification::SetXmlText(IXmlDocument* doc, const WCHAR* text) -{ - HSTRING tag = NULL; +bool WindowsToastNotification::SetXmlText( + IXmlDocument* doc, const std::wstring& text) { + ScopedHString tag; + ComPtr node_list; + if (!GetTextNodeList(&tag, doc, &node_list, 1)) + return false; - ComPtr nodeList; - HRESULT hr = GetTextNodeList(&tag, doc, &nodeList, 1); - do { - BREAK_IF_BAD(hr); + ComPtr node; + if (FAILED(node_list->Item(0, &node))) + return false; - ComPtr node; - hr = nodeList->Item(0, &node); - BREAK_IF_BAD(hr); - - hr = AppendTextToXml(doc, node.Get(), text); - } while (FALSE); - - if (tag != NULL) { - WindowsDeleteString(tag); - } - - return hr; + return AppendTextToXml(doc, node.Get(), text); } -HRESULT WindowsToastNotification::SetXmlText(IXmlDocument* doc, const WCHAR* title, const WCHAR* body) -{ - HSTRING tag = NULL; - ComPtr nodeList; - HRESULT hr = GetTextNodeList(&tag, doc, &nodeList, 2); - do { - BREAK_IF_BAD(hr); +bool WindowsToastNotification::SetXmlText( + IXmlDocument* doc, const std::wstring& title, const std::wstring& body) { + ScopedHString tag; + ComPtr node_list; + if (!GetTextNodeList(&tag, doc, &node_list, 2)) + return false; - ComPtr node; - hr = nodeList->Item(0, &node); - BREAK_IF_BAD(hr); + ComPtr node; + if (FAILED(node_list->Item(0, &node))) + return false; - hr = AppendTextToXml(doc, node.Get(), title); - BREAK_IF_BAD(hr); + if (!AppendTextToXml(doc, node.Get(), title)) + return false; - hr = nodeList->Item(1, &node); - BREAK_IF_BAD(hr); + if (FAILED(node_list->Item(1, &node))) + return false; - hr = AppendTextToXml(doc, node.Get(), body); - } while (FALSE); - - if (tag != NULL) { - WindowsDeleteString(tag); - } - - return hr; + return AppendTextToXml(doc, node.Get(), body); } -HRESULT WindowsToastNotification::SetXmlImage(IXmlDocument* doc, std::string iconPath) -{ - HSTRING tag = NULL; - HSTRING src = NULL; - HSTRING imgPath = NULL; - HRESULT hr = CreateHString(L"image", &tag); +bool WindowsToastNotification::SetXmlImage( + IXmlDocument* doc, std::string icon_path) { + ScopedHString tag(L"imag"); + if (!tag.success()) + return false; - do { - BREAK_IF_BAD(hr); + ComPtr node_list; + if (FAILED(doc->GetElementsByTagName(tag, &node_list))) + return false; - ComPtr nodeList; - hr = doc->GetElementsByTagName(tag, &nodeList); - BREAK_IF_BAD(hr); + ComPtr image_node; + if (FAILED(node_list->Item(0, &image_node))) + return false; - ComPtr imageNode; - hr = nodeList->Item(0, &imageNode); - BREAK_IF_BAD(hr); + ComPtr attrs; + if (FAILED(image_node->get_Attributes(&attrs))) + return false; - ComPtr attrs; - hr = imageNode->get_Attributes(&attrs); - BREAK_IF_BAD(hr); + ScopedHString src(L"src"); + if (!src.success()) + return false; - hr = CreateHString(L"src", &src); - BREAK_IF_BAD(hr); + ComPtr src_attr; + if (FAILED(attrs->GetNamedItem(src, &src_attr))) + return false; - ComPtr srcAttr; - hr = attrs->GetNamedItem(src, &srcAttr); - BREAK_IF_BAD(hr); + ScopedHString img_path(base::UTF8ToUTF16(icon_path).c_str()); + if (!img_path.success()) + return false; - WCHAR xmlPath[MAX_PATH]; - swprintf(xmlPath, ARRAYSIZE(xmlPath), L"%S", iconPath); - hr = CreateHString(xmlPath, &imgPath); - BREAK_IF_BAD(hr); + ComPtr src_text; + if (FAILED(doc->CreateTextNode(img_path, &src_text))) + return false; - ComPtr srcText; - hr = doc->CreateTextNode(imgPath, &srcText); - BREAK_IF_BAD(hr); + ComPtr src_node; + if (FAILED(src_text.As(&src_node))) + return false; - ComPtr srcNode; - hr = srcText.As(&srcNode); - BREAK_IF_BAD(hr); - - ComPtr childNode; - hr = srcAttr->AppendChild(srcNode.Get(), &childNode); - } while (FALSE); - - if (tag != NULL) { - WindowsDeleteString(tag); - } - if (src != NULL) { - WindowsDeleteString(src); - } - if (imgPath != NULL) { - WindowsDeleteString(imgPath); - } - - return hr; + ComPtr child_node; + return SUCCEEDED(src_attr->AppendChild(src_node.Get(), &child_node)); } -HRESULT WindowsToastNotification::GetTextNodeList(HSTRING* tag, IXmlDocument* doc, IXmlNodeList** nodeList, UINT32 reqLength) -{ - HRESULT hr = CreateHString(L"text", tag); - do{ - BREAK_IF_BAD(hr); +bool WindowsToastNotification::GetTextNodeList( + ScopedHString* tag, + IXmlDocument* doc, + IXmlNodeList** node_list, + UINT32 req_length) { + tag->Set(L"text"); + if (!tag->success()) + return false; - hr = doc->GetElementsByTagName(*tag, nodeList); - BREAK_IF_BAD(hr); + if (FAILED(doc->GetElementsByTagName(*tag, node_list))) + return false; - UINT32 nodeLength; - hr = (*nodeList)->get_Length(&nodeLength); - BREAK_IF_BAD(hr); + UINT32 node_length; + if (FAILED((*node_list)->get_Length(&node_length))) + return false; - if (nodeLength < reqLength) { - hr = E_INVALIDARG; - } - } while (FALSE); - - if (!SUCCEEDED(hr)) { - // Allow the caller to delete this string on success - WindowsDeleteString(*tag); - } - - return hr; + return node_length >= req_length; } -HRESULT WindowsToastNotification::AppendTextToXml(IXmlDocument* doc, IXmlNode* node, const WCHAR* text) -{ - HSTRING str = NULL; - HRESULT hr = CreateHString(text, &str); - do { - BREAK_IF_BAD(hr); +bool WindowsToastNotification::AppendTextToXml( + IXmlDocument* doc, IXmlNode* node, const std::wstring& text) { + ScopedHString str(text); + if (!str.success()) + return false; - ComPtr xmlText; - hr = doc->CreateTextNode(str, &xmlText); - BREAK_IF_BAD(hr); + ComPtr xml_text; + if (FAILED(doc->CreateTextNode(str, &xml_text))) + return false; - ComPtr textNode; - hr = xmlText.As(&textNode); - BREAK_IF_BAD(hr); + ComPtr text_node; + if (FAILED(xml_text.As(&text_node))) + return false; - ComPtr appendNode; - hr = node->AppendChild(textNode.Get(), &appendNode); - } while (FALSE); - - if (str != NULL) { - WindowsDeleteString(str); - } - - return hr; + ComPtr append_node; + return SUCCEEDED(node->AppendChild(text_node.Get(), &append_node)); } -HRESULT WindowsToastNotification::SetupCallbacks(IToastNotification* toast) -{ - EventRegistrationToken activatedToken, dismissedToken; - m_eventHandler = Make(this, n_delegate); - HRESULT hr = toast->add_Activated(m_eventHandler.Get(), &activatedToken); +bool WindowsToastNotification::SetupCallbacks(IToastNotification* toast) { + EventRegistrationToken activatedToken, dismissedToken; + event_handler_ = Make(this); + if (FAILED(toast->add_Activated(event_handler_.Get(), &activatedToken))) + return false; - if (SUCCEEDED(hr)) { - hr = toast->add_Dismissed(m_eventHandler.Get(), &dismissedToken); - } - - return hr; -} - -HRESULT WindowsToastNotification::CreateHString(const WCHAR* source, HSTRING* dest) -{ - if (source == NULL || dest == NULL) { - return E_INVALIDARG; - } - - HRESULT hr = WindowsCreateString(source, wcslen(source), dest); - return hr; + return SUCCEEDED(toast->add_Dismissed(event_handler_.Get(), &dismissedToken)); } /* / Toast Event Handler */ -ToastEventHandler::ToastEventHandler(WindowsToastNotification* notification, content::DesktopNotificationDelegate* delegate) -{ - m_notification = notification; - n_delegate = delegate; +ToastEventHandler::ToastEventHandler(WindowsToastNotification* notification) + : notification_(notification) { } -ToastEventHandler::~ToastEventHandler() -{ - // Empty +ToastEventHandler::~ToastEventHandler() { } -IFACEMETHODIMP ToastEventHandler::Invoke(IToastNotification* sender, IInspectable* args) -{ - // Notification "activated" (clicked) - n_delegate->NotificationClick(); - - if (m_notification != NULL) { - m_notification->NotificationClicked(); - } - - return S_OK; +IFACEMETHODIMP ToastEventHandler::Invoke( + IToastNotification* sender, IInspectable* args) { + notification_->NotificationClicked(); + return S_OK; } -IFACEMETHODIMP ToastEventHandler::Invoke(IToastNotification* sender, IToastDismissedEventArgs* e) -{ - // Notification dismissed - n_delegate->NotificationClosed(); - - if (m_notification != NULL) { - m_notification->NotificationDismissed(); - - } - - return S_OK; +IFACEMETHODIMP ToastEventHandler::Invoke( + IToastNotification* sender, IToastDismissedEventArgs* e) { + notification_->NotificationDismissed(); + return S_OK; } -} //namespace +} // namespace brightray diff --git a/brightray/browser/win/windows_toast_notification.h b/brightray/browser/win/windows_toast_notification.h index d501954ec5c3..bab6612c9f3e 100644 --- a/brightray/browser/win/windows_toast_notification.h +++ b/brightray/browser/win/windows_toast_notification.h @@ -3,70 +3,102 @@ // Thanks to both of those folks mentioned above who first thought up a bunch of this code // and released it as MIT to the world. -#ifndef __WINDOWS_TOAST_NOTIFICATION_H__ -#define __WINDOWS_TOAST_NOTIFICATION_H__ - -#include "content/public/browser/desktop_notification_delegate.h" -#include "content/public/common/platform_notification_data.h" -#include "base/bind.h" +#ifndef BRIGHTRAY_BROWSER_WIN_WINDOWS_TOAST_NOTIFICATION_H_ +#define BRIGHTRAY_BROWSER_WIN_WINDOWS_TOAST_NOTIFICATION_H_ #include #include #include +#include "base/bind.h" +#include "base/memory/weak_ptr.h" +#include "content/public/browser/desktop_notification_delegate.h" +#include "content/public/common/platform_notification_data.h" + using namespace Microsoft::WRL; using namespace ABI::Windows::UI::Notifications; using namespace ABI::Windows::Foundation; -namespace WinToasts { +class ScopedHString; - typedef ITypedEventHandler DesktopToastActivatedEventHandler; - typedef ITypedEventHandler DesktopToastDismissedEventHandler; +namespace brightray { - class ToastEventHandler; +using DesktopToastActivatedEventHandler = + ITypedEventHandler; +using DesktopToastDismissedEventHandler = + ITypedEventHandler; - class WindowsToastNotification - { - public: - WindowsToastNotification(const char* appName, content::DesktopNotificationDelegate* delegate); - ~WindowsToastNotification(); - void ShowNotification(const WCHAR* title, const WCHAR* msg, std::string iconPath, ComPtr& toast); - void DismissNotification(ComPtr toast); - void NotificationClicked(); - void NotificationDismissed(); +class WindowsToastNotification { + public: + WindowsToastNotification( + const std::string& app_name, + scoped_ptr delegate); + ~WindowsToastNotification(); - private: - ComPtr m_eventHandler; + void ShowNotification(const std::wstring& title, + const std::wstring& msg, + std::string icon_path); + void DismissNotification(); - content::DesktopNotificationDelegate* n_delegate; - ComPtr m_toastManager; - ComPtr m_toastNotifier; + base::WeakPtr GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } - HRESULT GetToastXml(IToastNotificationManagerStatics* toastManager, const WCHAR* title, const WCHAR* msg, std::string iconPath, ABI::Windows::Data::Xml::Dom::IXmlDocument** toastXml); - HRESULT SetXmlText(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, const WCHAR* text); - HRESULT SetXmlText(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, const WCHAR* title, const WCHAR* body); - HRESULT SetXmlImage(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, std::string iconPath); - HRESULT GetTextNodeList(HSTRING* tag, ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, ABI::Windows::Data::Xml::Dom::IXmlNodeList** nodeList, UINT32 reqLength); - HRESULT AppendTextToXml(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, ABI::Windows::Data::Xml::Dom::IXmlNode* node, const WCHAR* text); - HRESULT SetupCallbacks(IToastNotification* toast); - HRESULT CreateHString(const WCHAR* source, HSTRING* dest); - }; + private: + friend class ToastEventHandler; + + void NotificationClicked(); + void NotificationDismissed(); + + bool GetToastXml(IToastNotificationManagerStatics* toastManager, + const std::wstring& title, + const std::wstring& msg, + std::string icon_path, + ABI::Windows::Data::Xml::Dom::IXmlDocument** toastXml); + bool SetXmlText(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, + const std::wstring& text); + bool SetXmlText(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, + const std::wstring& title, + const std::wstring& body); + bool SetXmlImage(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, + std::string icon_path); + bool GetTextNodeList(ScopedHString* tag, + ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, + ABI::Windows::Data::Xml::Dom::IXmlNodeList** nodeList, + UINT32 reqLength); + bool AppendTextToXml(ABI::Windows::Data::Xml::Dom::IXmlDocument* doc, + ABI::Windows::Data::Xml::Dom::IXmlNode* node, + const std::wstring& text); + bool SetupCallbacks(IToastNotification* toast); + + scoped_ptr delegate_; + ComPtr event_handler_; + ComPtr toast_manager_; + ComPtr toast_notifier_; + ComPtr toast_notification_; + + base::WeakPtrFactory weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(WindowsToastNotification); +}; - class ToastEventHandler : - public RuntimeClass, DesktopToastActivatedEventHandler, DesktopToastDismissedEventHandler> - { - public: - ToastEventHandler(WindowsToastNotification* notification, content::DesktopNotificationDelegate* delegate); - ~ToastEventHandler(); - IFACEMETHODIMP Invoke(IToastNotification* sender, IInspectable* args); - IFACEMETHODIMP Invoke(IToastNotification* sender, IToastDismissedEventArgs* e); +class ToastEventHandler : public RuntimeClass, + DesktopToastActivatedEventHandler, + DesktopToastDismissedEventHandler> { + public: + ToastEventHandler(WindowsToastNotification* notification); + ~ToastEventHandler(); - private: - WindowsToastNotification* m_notification; - content::DesktopNotificationDelegate* n_delegate; - }; + IFACEMETHODIMP Invoke(IToastNotification* sender, IInspectable* args); + IFACEMETHODIMP Invoke(IToastNotification* sender, IToastDismissedEventArgs* e); -} // namespace + private: + WindowsToastNotification* notification_; // weak ref. -#endif //__WINDOWS_TOAST_NOTIFICATION_H__ \ No newline at end of file + DISALLOW_COPY_AND_ASSIGN(ToastEventHandler); +}; + +} // namespace brightray + +#endif // BRIGHTRAY_BROWSER_WIN_WINDOWS_TOAST_NOTIFICATION_H_ diff --git a/brightray/filenames.gypi b/brightray/filenames.gypi index 84dc4291ed2f..5b0fd733c998 100644 --- a/brightray/filenames.gypi +++ b/brightray/filenames.gypi @@ -67,6 +67,8 @@ 'browser/win/notification_presenter_win.cc', 'browser/win/windows_toast_notification.h', 'browser/win/windows_toast_notification.cc', + 'browser/win/scoped_hstring.h', + 'browser/win/scoped_hstring.cc', 'browser/special_storage_policy.cc', 'browser/special_storage_policy.h', 'browser/url_request_context_getter.cc',