OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include <string> | |
6 | |
7 #include "win8/metro_driver/stdafx.h" | |
8 #include "win8/metro_driver/toast_notification_handler.h" | |
9 | |
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" | |
17 | |
18 #include "win8/metro_driver/winrt_utils.h" | |
19 | |
20 typedef winfoundtn::ITypedEventHandler< | |
21 winui::Notifications::ToastNotification*, IInspectable*> | |
22 ToastActivationHandler; | |
23 | |
24 typedef winfoundtn::ITypedEventHandler< | |
25 winui::Notifications::ToastNotification*, | |
26 winui::Notifications::ToastDismissedEventArgs*> ToastDismissedHandler; | |
27 | |
28 namespace { | |
29 | |
30 // Helper function to return the text node root identified by the index passed | |
31 // in. | |
32 HRESULT GetTextNodeRoot( | |
33 unsigned int index, | |
34 winxml::Dom::IXmlDocument* xml_doc, | |
35 winxml::Dom::IXmlNode** node) { | |
36 DCHECK(xml_doc); | |
37 DCHECK(node); | |
38 | |
39 mswr::ComPtr<winxml::Dom::IXmlElement> document_element; | |
40 HRESULT hr = xml_doc->get_DocumentElement(&document_element); | |
41 CheckHR(hr); | |
42 | |
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(), | |
47 &elements); | |
48 CheckHR(hr); | |
49 | |
50 unsigned int count = 0; | |
51 elements->get_Length(&count); | |
52 | |
53 if (index > count) { | |
54 DVLOG(1) << "Invalid text node index passed in : " << index; | |
55 return E_FAIL; | |
56 } | |
57 hr = elements->Item(index, node); | |
58 CheckHR(hr); | |
59 return hr; | |
60 } | |
61 | |
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, | |
66 int index, | |
67 const base::string16& text_string) { | |
68 DCHECK(xml_doc); | |
69 | |
70 mswr::ComPtr<winxml::Dom::IXmlElement> document_element; | |
71 HRESULT hr = xml_doc->get_DocumentElement(&document_element); | |
72 CheckHR(hr); | |
73 | |
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); | |
78 CheckHR(hr); | |
79 | |
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())); | |
84 CheckHR(hr); | |
85 | |
86 mswr::ComPtr<winxml::Dom::IXmlNode> text_node_root; | |
87 hr = GetTextNodeRoot(index, xml_doc, &text_node_root); | |
88 CheckHR(hr); | |
89 | |
90 mswr::ComPtr<winxml::Dom::IXmlNode> appended_node; | |
91 hr = text_node_root->AppendChild(created_node.Get(), &appended_node); | |
92 CheckHR(hr); | |
93 return hr; | |
94 } | |
95 | |
96 } // namespace | |
97 | |
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), | |
112 id(notification_id), | |
113 notification_handler(handler) { | |
114 if (handler_context) | |
115 notification_context = handler_context; | |
116 } | |
117 | |
118 ToastNotificationHandler::DesktopNotification::DesktopNotification() | |
119 : notification_handler(NULL) { | |
120 } | |
121 | |
122 ToastNotificationHandler::ToastNotificationHandler() { | |
123 DVLOG(1) << __FUNCTION__; | |
124 } | |
125 | |
126 ToastNotificationHandler::~ToastNotificationHandler() { | |
127 DVLOG(1) << __FUNCTION__; | |
128 | |
129 if (notifier_ && notification_) | |
130 CancelNotification(); | |
131 } | |
132 | |
133 void ToastNotificationHandler::DisplayNotification( | |
134 const DesktopNotification& notification) { | |
135 DVLOG(1) << __FUNCTION__; | |
136 | |
137 DCHECK(notifier_.Get() == NULL); | |
138 DCHECK(notification_.Get() == NULL); | |
139 | |
140 notification_info_ = notification; | |
141 | |
142 mswr::ComPtr<winui::Notifications::IToastNotificationManagerStatics> | |
143 toast_manager; | |
144 | |
145 HRESULT hr = winrt_utils::CreateActivationFactory( | |
146 RuntimeClass_Windows_UI_Notifications_ToastNotificationManager, | |
147 toast_manager.GetAddressOf()); | |
148 CheckHR(hr); | |
149 | |
150 mswr::ComPtr<winxml::Dom::IXmlDocument> toast_xml; | |
151 hr = toast_manager->GetTemplateContent( | |
152 winui::Notifications::ToastTemplateType_ToastText02, | |
153 &toast_xml); | |
154 CheckHR(hr); | |
155 | |
156 if (!toast_xml) | |
157 return; | |
158 | |
159 mswr::ComPtr<winxml::Dom::IXmlElement> document_element; | |
160 hr = toast_xml->get_DocumentElement(&document_element); | |
161 CheckHR(hr); | |
162 | |
163 if (!document_element) | |
164 return; | |
165 | |
166 hr = CreateTextNode(toast_xml.Get(), 0, notification.title); | |
167 CheckHR(hr); | |
168 | |
169 hr = CreateTextNode(toast_xml.Get(), 1, notification.body); | |
170 CheckHR(hr); | |
171 | |
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")); | |
176 | |
177 hr = document_element->SetAttribute(duration_attribute_name.Get(), | |
178 duration_attribute_value.Get()); | |
179 CheckHR(hr); | |
180 | |
181 // TODO(ananta) | |
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 | |
188 // investigated. | |
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()); | |
194 CheckHR(hr); | |
195 | |
196 hr = toast_notification_factory->CreateToastNotification( | |
197 toast_xml.Get(), ¬ification_); | |
198 CheckHR(hr); | |
199 | |
200 base::FilePath chrome_path; | |
201 if (!PathService::Get(base::FILE_EXE, &chrome_path)) { | |
202 NOTREACHED() << "Failed to get chrome exe path"; | |
203 return; | |
204 } | |
205 | |
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(); | |
212 | |
213 mswrw::HString app_user_model_id; | |
214 app_user_model_id.Attach(MakeHString(appid)); | |
215 | |
216 hr = toast_manager->CreateToastNotifierWithId(app_user_model_id.Get(), | |
217 ¬ifier_); | |
218 CheckHR(hr); | |
219 | |
220 hr = notification_->add_Activated( | |
221 mswr::Callback<ToastActivationHandler>( | |
222 this, &ToastNotificationHandler::OnActivate).Get(), | |
223 &activated_token_); | |
224 CheckHR(hr); | |
225 | |
226 hr = notifier_->Show(notification_.Get()); | |
227 CheckHR(hr); | |
228 } | |
229 | |
230 void ToastNotificationHandler::CancelNotification() { | |
231 DVLOG(1) << __FUNCTION__; | |
232 | |
233 DCHECK(notifier_); | |
234 DCHECK(notification_); | |
235 | |
236 notifier_->Hide(notification_.Get()); | |
237 } | |
238 | |
239 HRESULT ToastNotificationHandler::OnActivate( | |
240 winui::Notifications::IToastNotification* notification, | |
241 IInspectable* inspectable) { | |
242 // TODO(ananta) | |
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__; | |
247 | |
248 if (notification_info_.notification_handler) { | |
249 notification_info_.notification_handler( | |
250 notification_info_.notification_context.c_str()); | |
251 } | |
252 return S_OK; | |
253 } | |
OLD | NEW |