| 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 |