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/file_path.h" |
| 11 #include "base/logging.h" |
| 12 #include "base/path_service.h" |
| 13 #include "base/utf_string_conversions.h" |
| 14 // TODO(ananta) |
| 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" |
| 18 |
| 19 typedef winfoundtn::ITypedEventHandler< |
| 20 winui::Notifications::ToastNotification*, IInspectable*> |
| 21 ToastActivationHandler; |
| 22 |
| 23 typedef winfoundtn::ITypedEventHandler< |
| 24 winui::Notifications::ToastNotification*, |
| 25 winui::Notifications::ToastDismissedEventArgs*> ToastDismissedHandler; |
| 26 |
| 27 namespace { |
| 28 |
| 29 // Helper function to return the text node root identified by the index passed |
| 30 // in. |
| 31 HRESULT GetTextNodeRoot( |
| 32 unsigned int index, |
| 33 winxml::Dom::IXmlDocument* xml_doc, |
| 34 winxml::Dom::IXmlNode** node) { |
| 35 DCHECK(xml_doc); |
| 36 DCHECK(node); |
| 37 |
| 38 mswr::ComPtr<winxml::Dom::IXmlElement> document_element; |
| 39 HRESULT hr = xml_doc->get_DocumentElement(&document_element); |
| 40 CheckHR(hr); |
| 41 |
| 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(), |
| 46 &elements); |
| 47 CheckHR(hr); |
| 48 |
| 49 unsigned int count = 0; |
| 50 elements->get_Length(&count); |
| 51 |
| 52 if (index > count) { |
| 53 DVLOG(1) << "Invalid text node index passed in : " << index; |
| 54 return E_FAIL; |
| 55 } |
| 56 hr = elements->Item(index, node); |
| 57 CheckHR(hr); |
| 58 return hr; |
| 59 } |
| 60 |
| 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, |
| 65 int index, |
| 66 const string16& text_string) { |
| 67 DCHECK(xml_doc); |
| 68 |
| 69 mswr::ComPtr<winxml::Dom::IXmlElement> document_element; |
| 70 HRESULT hr = xml_doc->get_DocumentElement(&document_element); |
| 71 CheckHR(hr); |
| 72 |
| 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); |
| 77 CheckHR(hr); |
| 78 |
| 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())); |
| 83 CheckHR(hr); |
| 84 |
| 85 mswr::ComPtr<winxml::Dom::IXmlNode> text_node_root; |
| 86 hr = GetTextNodeRoot(index, xml_doc, &text_node_root); |
| 87 CheckHR(hr); |
| 88 |
| 89 mswr::ComPtr<winxml::Dom::IXmlNode> appended_node; |
| 90 hr = text_node_root->AppendChild(created_node.Get(), &appended_node); |
| 91 CheckHR(hr); |
| 92 return hr; |
| 93 } |
| 94 |
| 95 } // namespace |
| 96 |
| 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 : origin_url(notification_origin), |
| 105 icon_url(notification_icon), |
| 106 title(notification_title), |
| 107 body(notification_body), |
| 108 display_source(notification_display_source), |
| 109 id(notification_id) { |
| 110 } |
| 111 |
| 112 |
| 113 ToastNotificationHandler::ToastNotificationHandler() { |
| 114 DVLOG(1) << __FUNCTION__; |
| 115 } |
| 116 |
| 117 ToastNotificationHandler::~ToastNotificationHandler() { |
| 118 DVLOG(1) << __FUNCTION__; |
| 119 |
| 120 if (notifier_ && notification_) |
| 121 CancelNotification(); |
| 122 } |
| 123 |
| 124 void ToastNotificationHandler::DisplayNotification( |
| 125 const DesktopNotification& notification) { |
| 126 DVLOG(1) << __FUNCTION__; |
| 127 |
| 128 DCHECK(notifier_.Get() == NULL); |
| 129 DCHECK(notification_.Get() == NULL); |
| 130 |
| 131 mswr::ComPtr<winui::Notifications::IToastNotificationManagerStatics> |
| 132 toast_manager; |
| 133 |
| 134 HRESULT hr = winrt_utils::CreateActivationFactory( |
| 135 RuntimeClass_Windows_UI_Notifications_ToastNotificationManager, |
| 136 toast_manager.GetAddressOf()); |
| 137 CheckHR(hr); |
| 138 |
| 139 mswr::ComPtr<winxml::Dom::IXmlDocument> toast_xml; |
| 140 hr = toast_manager->GetTemplateContent( |
| 141 winui::Notifications::ToastTemplateType_ToastText02, |
| 142 &toast_xml); |
| 143 CheckHR(hr); |
| 144 |
| 145 if (!toast_xml) |
| 146 return; |
| 147 |
| 148 mswr::ComPtr<winxml::Dom::IXmlElement> document_element; |
| 149 hr = toast_xml->get_DocumentElement(&document_element); |
| 150 CheckHR(hr); |
| 151 |
| 152 if (!document_element) |
| 153 return; |
| 154 |
| 155 hr = CreateTextNode(toast_xml.Get(), 0, notification.title); |
| 156 CheckHR(hr); |
| 157 |
| 158 hr = CreateTextNode(toast_xml.Get(), 1, notification.body); |
| 159 CheckHR(hr); |
| 160 |
| 161 mswrw::HString duration_attribute_name; |
| 162 duration_attribute_name.Attach(MakeHString(L"duration")); |
| 163 mswrw::HString duration_attribute_value; |
| 164 duration_attribute_value.Attach(MakeHString(L"long")); |
| 165 |
| 166 hr = document_element->SetAttribute(duration_attribute_name.Get(), |
| 167 duration_attribute_value.Get()); |
| 168 CheckHR(hr); |
| 169 |
| 170 // TODO(ananta) |
| 171 // We should set the image and launch params attribute in the notification |
| 172 // XNL as described here: http://msdn.microsoft.com/en-us/library/hh465448 |
| 173 // To set the image we may have to extract the image and specify it in the |
| 174 // following url form. ms-appx:///images/foo.png |
| 175 // The launch params as described don't get passed back to us via the |
| 176 // winapp::Activation::ILaunchActivatedEventArgs argument. Needs to be |
| 177 // investigated. |
| 178 mswr::ComPtr<winui::Notifications::IToastNotificationFactory> |
| 179 toast_notification_factory; |
| 180 hr = winrt_utils::CreateActivationFactory( |
| 181 RuntimeClass_Windows_UI_Notifications_ToastNotification, |
| 182 toast_notification_factory.GetAddressOf()); |
| 183 CheckHR(hr); |
| 184 |
| 185 hr = toast_notification_factory->CreateToastNotification( |
| 186 toast_xml.Get(), ¬ification_); |
| 187 CheckHR(hr); |
| 188 |
| 189 FilePath chrome_path; |
| 190 if (!PathService::Get(base::FILE_EXE, &chrome_path)) { |
| 191 NOTREACHED() << "Failed to get chrome exe path"; |
| 192 return; |
| 193 } |
| 194 string16 appid = delegate_execute::GetAppId(chrome_path); |
| 195 DVLOG(1) << "Chrome Appid is " << appid.c_str(); |
| 196 |
| 197 // TODO(ananta) |
| 198 // We should probably use BrowserDistribution here to get the product name. |
| 199 mswrw::HString app_user_model_id; |
| 200 app_user_model_id.Attach(MakeHString(appid)); |
| 201 |
| 202 hr = toast_manager->CreateToastNotifierWithId(app_user_model_id.Get(), |
| 203 ¬ifier_); |
| 204 CheckHR(hr); |
| 205 |
| 206 hr = notification_->add_Activated( |
| 207 mswr::Callback<ToastActivationHandler>( |
| 208 this, &ToastNotificationHandler::OnActivate).Get(), |
| 209 &activated_token_); |
| 210 CheckHR(hr); |
| 211 |
| 212 hr = notifier_->Show(notification_.Get()); |
| 213 CheckHR(hr); |
| 214 } |
| 215 |
| 216 void ToastNotificationHandler::CancelNotification() { |
| 217 DVLOG(1) << __FUNCTION__; |
| 218 |
| 219 DCHECK(notifier_); |
| 220 DCHECK(notification_); |
| 221 |
| 222 notifier_->Hide(notification_.Get()); |
| 223 } |
| 224 |
| 225 HRESULT ToastNotificationHandler::OnActivate( |
| 226 winui::Notifications::IToastNotification* notification, |
| 227 IInspectable* inspectable) { |
| 228 // TODO(ananta) |
| 229 // We should pass back information from the notification like the source url |
| 230 // etc to ChromeAppView which would enable it to ensure that the |
| 231 // correct tab in chrome is activated. |
| 232 DVLOG(1) << __FUNCTION__; |
| 233 return S_OK; |
| 234 } |
OLD | NEW |