1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "win8/metro_driver/stdafx.h"
8 #include "win8/metro_driver/toast_notification_handler.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/path_service.h"
13 #include "base/utf_string_conversions.h"
15 // Refactor the chrome_util and shell_util code from chrome into a common lib
16 #include "win8/delegate_execute/chrome_util.h"
17 #include "win8/metro_driver/winrt_utils.h"
19 typedef winfoundtn::ITypedEventHandler
<
20 winui::Notifications::ToastNotification
*, IInspectable
*>
21 ToastActivationHandler
;
23 typedef winfoundtn::ITypedEventHandler
<
24 winui::Notifications::ToastNotification
*,
25 winui::Notifications::ToastDismissedEventArgs
*> ToastDismissedHandler
;
29 // Helper function to return the text node root identified by the index passed
31 HRESULT
GetTextNodeRoot(
33 winxml::Dom::IXmlDocument
* xml_doc
,
34 winxml::Dom::IXmlNode
** node
) {
38 mswr::ComPtr
<winxml::Dom::IXmlElement
> document_element
;
39 HRESULT hr
= xml_doc
->get_DocumentElement(&document_element
);
42 mswr::ComPtr
<winxml::Dom::IXmlNodeList
> elements
;
43 mswrw::HString tag_name
;
44 tag_name
.Attach(MakeHString(L
"text"));
45 hr
= document_element
->GetElementsByTagName(tag_name
.Get(),
49 unsigned int count
= 0;
50 elements
->get_Length(&count
);
53 DVLOG(1) << "Invalid text node index passed in : " << index
;
56 hr
= elements
->Item(index
, node
);
61 // Helper function to append a text element to the text section in the
62 // XML document passed in.
63 // The index parameter identifies which text node we append to.
64 HRESULT
CreateTextNode(winxml::Dom::IXmlDocument
* xml_doc
,
66 const string16
& text_string
) {
69 mswr::ComPtr
<winxml::Dom::IXmlElement
> document_element
;
70 HRESULT hr
= xml_doc
->get_DocumentElement(&document_element
);
73 mswr::ComPtr
<winxml::Dom::IXmlText
> xml_text_node
;
74 mswrw::HString data_hstring
;
75 data_hstring
.Attach(MakeHString(text_string
.c_str()));
76 hr
= xml_doc
->CreateTextNode(data_hstring
.Get(), &xml_text_node
);
79 mswr::ComPtr
<winxml::Dom::IXmlNode
> created_node
;
80 hr
= xml_text_node
.CopyTo(
81 winxml::Dom::IID_IXmlNode
,
82 reinterpret_cast<void**>(created_node
.GetAddressOf()));
85 mswr::ComPtr
<winxml::Dom::IXmlNode
> text_node_root
;
86 hr
= GetTextNodeRoot(index
, xml_doc
, &text_node_root
);
89 mswr::ComPtr
<winxml::Dom::IXmlNode
> appended_node
;
90 hr
= text_node_root
->AppendChild(created_node
.Get(), &appended_node
);
97 ToastNotificationHandler::DesktopNotification::DesktopNotification(
98 const char* notification_origin
,
99 const char* notification_icon
,
100 const wchar_t* notification_title
,
101 const wchar_t* notification_body
,
102 const wchar_t* notification_display_source
,
103 const char* notification_id
,
104 base::win::MetroNotificationClickedHandler handler
,
105 const wchar_t* handler_context
)
106 : origin_url(notification_origin
),
107 icon_url(notification_icon
),
108 title(notification_title
),
109 body(notification_body
),
110 display_source(notification_display_source
),
112 notification_handler(handler
) {
114 notification_context
= handler_context
;
117 ToastNotificationHandler::DesktopNotification::DesktopNotification()
118 : notification_handler(NULL
) {
121 ToastNotificationHandler::ToastNotificationHandler() {
122 DVLOG(1) << __FUNCTION__
;
125 ToastNotificationHandler::~ToastNotificationHandler() {
126 DVLOG(1) << __FUNCTION__
;
128 if (notifier_
&& notification_
)
129 CancelNotification();
132 void ToastNotificationHandler::DisplayNotification(
133 const DesktopNotification
& notification
) {
134 DVLOG(1) << __FUNCTION__
;
136 DCHECK(notifier_
.Get() == NULL
);
137 DCHECK(notification_
.Get() == NULL
);
139 notification_info_
= notification
;
141 mswr::ComPtr
<winui::Notifications::IToastNotificationManagerStatics
>
144 HRESULT hr
= winrt_utils::CreateActivationFactory(
145 RuntimeClass_Windows_UI_Notifications_ToastNotificationManager
,
146 toast_manager
.GetAddressOf());
149 mswr::ComPtr
<winxml::Dom::IXmlDocument
> toast_xml
;
150 hr
= toast_manager
->GetTemplateContent(
151 winui::Notifications::ToastTemplateType_ToastText02
,
158 mswr::ComPtr
<winxml::Dom::IXmlElement
> document_element
;
159 hr
= toast_xml
->get_DocumentElement(&document_element
);
162 if (!document_element
)
165 hr
= CreateTextNode(toast_xml
.Get(), 0, notification
.title
);
168 hr
= CreateTextNode(toast_xml
.Get(), 1, notification
.body
);
171 mswrw::HString duration_attribute_name
;
172 duration_attribute_name
.Attach(MakeHString(L
"duration"));
173 mswrw::HString duration_attribute_value
;
174 duration_attribute_value
.Attach(MakeHString(L
"long"));
176 hr
= document_element
->SetAttribute(duration_attribute_name
.Get(),
177 duration_attribute_value
.Get());
181 // We should set the image and launch params attribute in the notification
182 // XNL as described here: http://msdn.microsoft.com/en-us/library/hh465448
183 // To set the image we may have to extract the image and specify it in the
184 // following url form. ms-appx:///images/foo.png
185 // The launch params as described don't get passed back to us via the
186 // winapp::Activation::ILaunchActivatedEventArgs argument. Needs to be
188 mswr::ComPtr
<winui::Notifications::IToastNotificationFactory
>
189 toast_notification_factory
;
190 hr
= winrt_utils::CreateActivationFactory(
191 RuntimeClass_Windows_UI_Notifications_ToastNotification
,
192 toast_notification_factory
.GetAddressOf());
195 hr
= toast_notification_factory
->CreateToastNotification(
196 toast_xml
.Get(), ¬ification_
);
199 base::FilePath chrome_path
;
200 if (!PathService::Get(base::FILE_EXE
, &chrome_path
)) {
201 NOTREACHED() << "Failed to get chrome exe path";
204 string16 appid
= delegate_execute::GetAppId(chrome_path
);
205 DVLOG(1) << "Chrome Appid is " << appid
.c_str();
208 // We should probably use BrowserDistribution here to get the product name.
209 mswrw::HString app_user_model_id
;
210 app_user_model_id
.Attach(MakeHString(appid
));
212 hr
= toast_manager
->CreateToastNotifierWithId(app_user_model_id
.Get(),
216 hr
= notification_
->add_Activated(
217 mswr::Callback
<ToastActivationHandler
>(
218 this, &ToastNotificationHandler::OnActivate
).Get(),
222 hr
= notifier_
->Show(notification_
.Get());
226 void ToastNotificationHandler::CancelNotification() {
227 DVLOG(1) << __FUNCTION__
;
230 DCHECK(notification_
);
232 notifier_
->Hide(notification_
.Get());
235 HRESULT
ToastNotificationHandler::OnActivate(
236 winui::Notifications::IToastNotification
* notification
,
237 IInspectable
* inspectable
) {
239 // We should pass back information from the notification like the source url
240 // etc to ChromeAppView which would enable it to ensure that the
241 // correct tab in chrome is activated.
242 DVLOG(1) << __FUNCTION__
;
244 if (notification_info_
.notification_handler
) {
245 notification_info_
.notification_handler(
246 notification_info_
.notification_context
.c_str());