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/strings/utf_string_conversions.h"
14 #include "chrome/installer/util/browser_distribution.h"
15 #include "chrome/installer/util/install_util.h"
16 #include "chrome/installer/util/shell_util.h"
18 #include "win8/metro_driver/winrt_utils.h"
20 typedef winfoundtn::ITypedEventHandler
<
21 winui::Notifications::ToastNotification
*, IInspectable
*>
22 ToastActivationHandler
;
24 typedef winfoundtn::ITypedEventHandler
<
25 winui::Notifications::ToastNotification
*,
26 winui::Notifications::ToastDismissedEventArgs
*> ToastDismissedHandler
;
30 // Helper function to return the text node root identified by the index passed
32 HRESULT
GetTextNodeRoot(
34 winxml::Dom::IXmlDocument
* xml_doc
,
35 winxml::Dom::IXmlNode
** node
) {
39 mswr::ComPtr
<winxml::Dom::IXmlElement
> document_element
;
40 HRESULT hr
= xml_doc
->get_DocumentElement(&document_element
);
43 mswr::ComPtr
<winxml::Dom::IXmlNodeList
> elements
;
44 mswrw::HString tag_name
;
45 tag_name
.Attach(MakeHString(L
"text"));
46 hr
= document_element
->GetElementsByTagName(tag_name
.Get(),
50 unsigned int count
= 0;
51 elements
->get_Length(&count
);
54 DVLOG(1) << "Invalid text node index passed in : " << index
;
57 hr
= elements
->Item(index
, node
);
62 // Helper function to append a text element to the text section in the
63 // XML document passed in.
64 // The index parameter identifies which text node we append to.
65 HRESULT
CreateTextNode(winxml::Dom::IXmlDocument
* xml_doc
,
67 const base::string16
& text_string
) {
70 mswr::ComPtr
<winxml::Dom::IXmlElement
> document_element
;
71 HRESULT hr
= xml_doc
->get_DocumentElement(&document_element
);
74 mswr::ComPtr
<winxml::Dom::IXmlText
> xml_text_node
;
75 mswrw::HString data_hstring
;
76 data_hstring
.Attach(MakeHString(text_string
.c_str()));
77 hr
= xml_doc
->CreateTextNode(data_hstring
.Get(), &xml_text_node
);
80 mswr::ComPtr
<winxml::Dom::IXmlNode
> created_node
;
81 hr
= xml_text_node
.CopyTo(
82 winxml::Dom::IID_IXmlNode
,
83 reinterpret_cast<void**>(created_node
.GetAddressOf()));
86 mswr::ComPtr
<winxml::Dom::IXmlNode
> text_node_root
;
87 hr
= GetTextNodeRoot(index
, xml_doc
, &text_node_root
);
90 mswr::ComPtr
<winxml::Dom::IXmlNode
> appended_node
;
91 hr
= text_node_root
->AppendChild(created_node
.Get(), &appended_node
);
98 ToastNotificationHandler::DesktopNotification::DesktopNotification(
99 const char* notification_origin
,
100 const char* notification_icon
,
101 const wchar_t* notification_title
,
102 const wchar_t* notification_body
,
103 const wchar_t* notification_display_source
,
104 const char* notification_id
,
105 base::win::MetroNotificationClickedHandler handler
,
106 const wchar_t* handler_context
)
107 : origin_url(notification_origin
),
108 icon_url(notification_icon
),
109 title(notification_title
),
110 body(notification_body
),
111 display_source(notification_display_source
),
113 notification_handler(handler
) {
115 notification_context
= handler_context
;
118 ToastNotificationHandler::DesktopNotification::DesktopNotification()
119 : notification_handler(NULL
) {
122 ToastNotificationHandler::ToastNotificationHandler() {
123 DVLOG(1) << __FUNCTION__
;
126 ToastNotificationHandler::~ToastNotificationHandler() {
127 DVLOG(1) << __FUNCTION__
;
129 if (notifier_
&& notification_
)
130 CancelNotification();
133 void ToastNotificationHandler::DisplayNotification(
134 const DesktopNotification
& notification
) {
135 DVLOG(1) << __FUNCTION__
;
137 DCHECK(notifier_
.Get() == NULL
);
138 DCHECK(notification_
.Get() == NULL
);
140 notification_info_
= notification
;
142 mswr::ComPtr
<winui::Notifications::IToastNotificationManagerStatics
>
145 HRESULT hr
= winrt_utils::CreateActivationFactory(
146 RuntimeClass_Windows_UI_Notifications_ToastNotificationManager
,
147 toast_manager
.GetAddressOf());
150 mswr::ComPtr
<winxml::Dom::IXmlDocument
> toast_xml
;
151 hr
= toast_manager
->GetTemplateContent(
152 winui::Notifications::ToastTemplateType_ToastText02
,
159 mswr::ComPtr
<winxml::Dom::IXmlElement
> document_element
;
160 hr
= toast_xml
->get_DocumentElement(&document_element
);
163 if (!document_element
)
166 hr
= CreateTextNode(toast_xml
.Get(), 0, notification
.title
);
169 hr
= CreateTextNode(toast_xml
.Get(), 1, notification
.body
);
172 mswrw::HString duration_attribute_name
;
173 duration_attribute_name
.Attach(MakeHString(L
"duration"));
174 mswrw::HString duration_attribute_value
;
175 duration_attribute_value
.Attach(MakeHString(L
"long"));
177 hr
= document_element
->SetAttribute(duration_attribute_name
.Get(),
178 duration_attribute_value
.Get());
182 // We should set the image and launch params attribute in the notification
183 // XNL as described here: http://msdn.microsoft.com/en-us/library/hh465448
184 // To set the image we may have to extract the image and specify it in the
185 // following url form. ms-appx:///images/foo.png
186 // The launch params as described don't get passed back to us via the
187 // winapp::Activation::ILaunchActivatedEventArgs argument. Needs to be
189 mswr::ComPtr
<winui::Notifications::IToastNotificationFactory
>
190 toast_notification_factory
;
191 hr
= winrt_utils::CreateActivationFactory(
192 RuntimeClass_Windows_UI_Notifications_ToastNotification
,
193 toast_notification_factory
.GetAddressOf());
196 hr
= toast_notification_factory
->CreateToastNotification(
197 toast_xml
.Get(), ¬ification_
);
200 base::FilePath chrome_path
;
201 if (!PathService::Get(base::FILE_EXE
, &chrome_path
)) {
202 NOTREACHED() << "Failed to get chrome exe path";
206 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
207 bool is_per_user_install
= InstallUtil::IsPerUserInstall(
208 chrome_path
.value().c_str());
209 base::string16 appid
=
210 ShellUtil::GetBrowserModelId(dist
, is_per_user_install
);
211 DVLOG(1) << "Chrome Appid is " << appid
.c_str();
213 mswrw::HString app_user_model_id
;
214 app_user_model_id
.Attach(MakeHString(appid
));
216 hr
= toast_manager
->CreateToastNotifierWithId(app_user_model_id
.Get(),
220 hr
= notification_
->add_Activated(
221 mswr::Callback
<ToastActivationHandler
>(
222 this, &ToastNotificationHandler::OnActivate
).Get(),
226 hr
= notifier_
->Show(notification_
.Get());
230 void ToastNotificationHandler::CancelNotification() {
231 DVLOG(1) << __FUNCTION__
;
234 DCHECK(notification_
);
236 notifier_
->Hide(notification_
.Get());
239 HRESULT
ToastNotificationHandler::OnActivate(
240 winui::Notifications::IToastNotification
* notification
,
241 IInspectable
* inspectable
) {
243 // We should pass back information from the notification like the source url
244 // etc to ChromeAppView which would enable it to ensure that the
245 // correct tab in chrome is activated.
246 DVLOG(1) << __FUNCTION__
;
248 if (notification_info_
.notification_handler
) {
249 notification_info_
.notification_handler(
250 notification_info_
.notification_context
.c_str());