diff -r 000000000000 -r 6474c204b198 widget/windows/winrt/ToastNotificationHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widget/windows/winrt/ToastNotificationHandler.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "ToastNotificationHandler.h" +#include "MetroUtils.h" +#include "mozilla/Services.h" +#include "FrameworkView.h" + +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Data::Xml::Dom; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace mozilla; +using namespace ABI::Windows::UI::Notifications; + +typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_IInspectable_t ToastActivationHandler; +typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_Windows__CUI__CNotifications__CToastDismissedEventArgs ToastDismissHandler; + +bool +ToastNotificationHandler::DisplayNotification(HSTRING title, + HSTRING msg, + HSTRING imagePath, + const nsAString& aCookie, + const nsAString& aAppId) +{ + mCookie = aCookie; + + Microsoft::WRL::ComPtr toastXml = + InitializeXmlForTemplate(ToastTemplateType::ToastTemplateType_ToastImageAndText03); + Microsoft::WRL::ComPtr toastTextElements, toastImageElements; + Microsoft::WRL::ComPtr titleTextNodeRoot, msgTextNodeRoot, imageNodeRoot, srcAttribute; + + HSTRING textNodeStr, imageNodeStr, srcNodeStr; + HSTRING_HEADER textHeader, imageHeader, srcHeader; + WindowsCreateStringReference(L"text", 4, &textHeader, &textNodeStr); + WindowsCreateStringReference(L"image", 5, &imageHeader, &imageNodeStr); + WindowsCreateStringReference(L"src", 3, &srcHeader, &srcNodeStr); + toastXml->GetElementsByTagName(textNodeStr, &toastTextElements); + toastXml->GetElementsByTagName(imageNodeStr, &toastImageElements); + + AssertRetHRESULT(toastTextElements->Item(0, &titleTextNodeRoot), false); + AssertRetHRESULT(toastTextElements->Item(1, &msgTextNodeRoot), false); + AssertRetHRESULT(toastImageElements->Item(0, &imageNodeRoot), false); + + Microsoft::WRL::ComPtr attributes; + AssertRetHRESULT(imageNodeRoot->get_Attributes(&attributes), false); + AssertRetHRESULT(attributes->GetNamedItem(srcNodeStr, &srcAttribute), false); + + SetNodeValueString(title, titleTextNodeRoot.Get(), toastXml.Get()); + SetNodeValueString(msg, msgTextNodeRoot.Get(), toastXml.Get()); + SetNodeValueString(imagePath, srcAttribute.Get(), toastXml.Get()); + + return CreateWindowsNotificationFromXml(toastXml.Get(), aAppId); +} + +bool +ToastNotificationHandler::DisplayTextNotification(HSTRING title, + HSTRING msg, + const nsAString& aCookie, + const nsAString& aAppId) +{ + mCookie = aCookie; + + Microsoft::WRL::ComPtr toastXml = + InitializeXmlForTemplate(ToastTemplateType::ToastTemplateType_ToastText03); + Microsoft::WRL::ComPtr toastTextElements; + Microsoft::WRL::ComPtr titleTextNodeRoot, msgTextNodeRoot; + + HSTRING textNodeStr; + HSTRING_HEADER textHeader; + WindowsCreateStringReference(L"text", 4, &textHeader, &textNodeStr); + toastXml->GetElementsByTagName(textNodeStr, &toastTextElements); + + AssertRetHRESULT(toastTextElements->Item(0, &titleTextNodeRoot), false); + AssertRetHRESULT(toastTextElements->Item(1, &msgTextNodeRoot), false); + + SetNodeValueString(title, titleTextNodeRoot.Get(), toastXml.Get()); + SetNodeValueString(msg, msgTextNodeRoot.Get(), toastXml.Get()); + + return CreateWindowsNotificationFromXml(toastXml.Get(), aAppId); +} + +Microsoft::WRL::ComPtr +ToastNotificationHandler::InitializeXmlForTemplate(ToastTemplateType templateType) { + Microsoft::WRL::ComPtr toastXml; + + AssertRetHRESULT(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), + mToastNotificationManagerStatics.GetAddressOf()), nullptr); + + mToastNotificationManagerStatics->GetTemplateContent(templateType, &toastXml); + + return toastXml; +} + +bool +ToastNotificationHandler::CreateWindowsNotificationFromXml(IXmlDocument *toastXml, + const nsAString& aAppId) +{ + Microsoft::WRL::ComPtr notification; + Microsoft::WRL::ComPtr factory; + AssertRetHRESULT(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), + factory.GetAddressOf()), false); + AssertRetHRESULT(factory->CreateToastNotification(toastXml, ¬ification), + false); + + EventRegistrationToken activatedToken; + AssertRetHRESULT(notification->add_Activated(Callback(this, + &ToastNotificationHandler::OnActivate).Get(), &activatedToken), false); + EventRegistrationToken dismissedToken; + AssertRetHRESULT(notification->add_Dismissed(Callback(this, + &ToastNotificationHandler::OnDismiss).Get(), &dismissedToken), false); + + Microsoft::WRL::ComPtr notifier; + if (aAppId.IsEmpty()) { + AssertRetHRESULT(mToastNotificationManagerStatics->CreateToastNotifier( + ¬ifier), false); + } else { + AssertRetHRESULT(mToastNotificationManagerStatics->CreateToastNotifierWithId( + HStringReference(PromiseFlatString(aAppId).get()).Get(), + ¬ifier), false); + } + AssertRetHRESULT(notifier->Show(notification.Get()), false); + + MetroUtils::FireObserver("metro_native_toast_shown", mCookie.get()); + + return true; +} + +void ToastNotificationHandler::SetNodeValueString(HSTRING inputString, + Microsoft::WRL::ComPtr node, Microsoft::WRL::ComPtr xml) { + Microsoft::WRL::ComPtr inputText; + Microsoft::WRL::ComPtr inputTextNode, pAppendedChild; + + AssertHRESULT(xml->CreateTextNode(inputString, &inputText)); + AssertHRESULT(inputText.As(&inputTextNode)); + AssertHRESULT(node->AppendChild(inputTextNode.Get(), &pAppendedChild)); +} + +HRESULT ToastNotificationHandler::OnActivate(IToastNotification *notification, IInspectable *inspectable) { + MetroUtils::FireObserver("metro_native_toast_clicked", mCookie.get()); + return S_OK; +} + +HRESULT +ToastNotificationHandler::OnDismiss(IToastNotification *notification, + IToastDismissedEventArgs* aArgs) +{ + MetroUtils::FireObserver("metro_native_toast_dismissed", mCookie.get()); + delete this; + return S_OK; +}