OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 "chrome/browser/notifications/notification_toast_helper_win.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 9 #include "base/files/file_path.h" |
| 10 #include "chrome/installer/util/install_util.h" |
| 11 #include "chrome/installer/util/shell_util.h" |
| 12 |
| 13 namespace { |
| 14 |
| 15 // Templated wrapper for winfoundtn::GetActivationFactory(). |
| 16 template<unsigned int size, typename T> |
| 17 HRESULT CreateActivationFactory(wchar_t const (&class_name)[size], T** object) { |
| 18 mswrw::HStringReference ref_class_name(class_name); |
| 19 return winfoundtn::GetActivationFactory(ref_class_name.Get(), object); |
| 20 } |
| 21 |
| 22 // Returns Chrome's AppId on success, and empty string on failure. |
| 23 base::string16 GetChromeAppId() { |
| 24 bool is_per_user_install = InstallUtil::IsPerUserInstall(); |
| 25 base::string16 appid = ShellUtil::GetBrowserModelId(is_per_user_install); |
| 26 DVLOG(1) << "Chrome Appid is " << appid.c_str(); |
| 27 return appid; |
| 28 } |
| 29 |
| 30 } // namespace |
| 31 |
| 32 void NotificationToastHelperWin::CreateToastManager() { |
| 33 if (HasFailed()) |
| 34 return; |
| 35 hr_ = CreateActivationFactory( |
| 36 RuntimeClass_Windows_UI_Notifications_ToastNotificationManager, |
| 37 toast_manager_.GetAddressOf()); |
| 38 } |
| 39 |
| 40 void NotificationToastHelperWin::LoadXMLFromTemplate( |
| 41 winui::Notifications::ToastTemplateType type) { |
| 42 if (HasFailed()) |
| 43 return; |
| 44 hr_ = toast_manager_->GetTemplateContent(type, &toast_xml_); |
| 45 if (!toast_xml_) { |
| 46 hr_ = E_FAIL; |
| 47 return; |
| 48 } |
| 49 hr_ = toast_xml_->get_DocumentElement(&document_element_); |
| 50 if (!document_element_) |
| 51 hr_ = E_FAIL; |
| 52 } |
| 53 |
| 54 void NotificationToastHelperWin::LoadXMLFromString( |
| 55 const base::string16& xml_str) { |
| 56 if (HasFailed()) |
| 57 return; |
| 58 mswr::ComPtr<winxml::Dom::IXmlDocumentIO> xml_document; |
| 59 |
| 60 mswrw::HStringReference ref_class_name( |
| 61 RuntimeClass_Windows_Data_Xml_Dom_XmlDocument); |
| 62 hr_ = Windows::Foundation::ActivateInstance(ref_class_name.Get(), |
| 63 &xml_document); |
| 64 // hr_ = CreateActivationFactory( |
| 65 // RuntimeClass_Windows_Data_Xml_Dom_XmlDocument, |
| 66 // xml_document.GetAddressOf()); |
| 67 if (HasFailed()) |
| 68 return; |
| 69 |
| 70 mswrw::HString xml_hs; |
| 71 xml_hs.Attach(MakeHString(xml_str)); |
| 72 hr_ = xml_document->LoadXml(xml_hs.Get()); |
| 73 if (HasFailed()) |
| 74 return; |
| 75 |
| 76 winxml::Dom::IXmlDocument** xml = &toast_xml_; |
| 77 hr_ = xml_document.CopyTo(xml); |
| 78 if (!document_element_) |
| 79 hr_ = E_FAIL; |
| 80 |
| 81 hr_ = toast_xml_->get_DocumentElement(&document_element_); |
| 82 } |
| 83 |
| 84 // For debugging. |
| 85 // TODO(huangs): Remove. |
| 86 void NotificationToastHelperWin::AlertToastXml() { |
| 87 if (HasFailed()) |
| 88 return; |
| 89 mswr::ComPtr<ABI::Windows::Data::Xml::Dom::IXmlNodeSerializer> s; |
| 90 toast_xml_.As(&s); |
| 91 HSTRING xml_string; |
| 92 hr_ = s->GetXml(&xml_string); |
| 93 if (StillOkay()) { |
| 94 PCWSTR str = WindowsGetStringRawBuffer(xml_string, NULL); |
| 95 ::MessageBox(NULL, str, L"Title", MB_OK); |
| 96 } |
| 97 } |
| 98 |
| 99 void NotificationToastHelperWin::SelectDocument() { |
| 100 if (HasFailed()) |
| 101 return; |
| 102 if (document_element_) |
| 103 cur_element_ = document_element_; |
| 104 else |
| 105 hr_ = E_FAIL; |
| 106 } |
| 107 |
| 108 void NotificationToastHelperWin::SelectElementByTagNameAndIndex( |
| 109 const base::string16& tag_name, unsigned int index) { |
| 110 if (HasFailed()) |
| 111 return; |
| 112 mswrw::HString hs_tag_name; |
| 113 hs_tag_name.Attach(MakeHString(tag_name)); |
| 114 if (HasFailed()) |
| 115 return; |
| 116 mswr::ComPtr<winxml::Dom::IXmlNodeList> elements; |
| 117 hr_ = document_element_->GetElementsByTagName(hs_tag_name.Get(), &elements); |
| 118 if (HasFailed()) |
| 119 return; |
| 120 unsigned int count = 0; |
| 121 elements->get_Length(&count); |
| 122 if (index >= count) { |
| 123 DVLOG(1) << "Requesting nonexistent node with tag_name " << tag_name |
| 124 << " and index " << index; |
| 125 hr_ = E_FAIL; |
| 126 return; |
| 127 } |
| 128 mswr::ComPtr<winxml::Dom::IXmlNode> cur_node; |
| 129 hr_ = elements->Item(index, &cur_node); |
| 130 if (StillOkay()) |
| 131 hr_ = cur_node.As(&cur_element_); |
| 132 } |
| 133 |
| 134 // Converts a file path, e.g., "C:\\User\\test\\AppData\\Local\\Temp\\a.tmp" |
| 135 // to a file URL, e.g., "file:///C:/User/test/AppData/Local/Temp/a.tmp". |
| 136 base::string16 NotificationToastHelperWin::FilePathToFileUrl( |
| 137 const base::FilePath& file_path) { |
| 138 if (HasFailed()) |
| 139 return L""; |
| 140 const size_t kFileUrlExtraSize = 10; // Acommodates L"file:///". and L'\0'. |
| 141 base::string16 file_str = file_path.AsUTF16Unsafe(); |
| 142 DWORD size = static_cast<DWORD>(file_str.size() + kFileUrlExtraSize); |
| 143 std::vector<base::char16> buffer(size); |
| 144 hr_ = ::UrlCreateFromPathW(file_str.c_str(), &buffer[0], &size, NULL); |
| 145 if (HasFailed()) |
| 146 return L""; |
| 147 return base::string16(&buffer[0]); |
| 148 } |
| 149 |
| 150 void NotificationToastHelperWin::RemoveElement() { |
| 151 if (HasFailed()) |
| 152 return; |
| 153 mswr::ComPtr<winxml::Dom::IXmlNode> cur_node; |
| 154 hr_ = cur_element_.As(&cur_node); |
| 155 if (HasFailed()) |
| 156 return; |
| 157 mswr::ComPtr<winxml::Dom::IXmlNode> parent_node; |
| 158 hr_ = cur_node->get_ParentNode(&parent_node); |
| 159 if (HasFailed()) |
| 160 return; |
| 161 mswr::ComPtr<winxml::Dom::IXmlNode> removed_node; |
| 162 hr_ = parent_node->RemoveChild(cur_node.Get(), &removed_node); |
| 163 if (HasFailed()) |
| 164 return; |
| 165 hr_ = parent_node.As(&cur_element_); |
| 166 } |
| 167 |
| 168 void NotificationToastHelperWin::AppendText(const base::string16& text) { |
| 169 if (HasFailed()) |
| 170 return; |
| 171 if (!cur_element_) { |
| 172 hr_ = E_FAIL; |
| 173 return; |
| 174 } |
| 175 mswr::ComPtr<winxml::Dom::IXmlNode> text_node; |
| 176 CreateTextNode(text, &text_node); |
| 177 if (HasFailed()) |
| 178 return; |
| 179 mswr::ComPtr<winxml::Dom::IXmlNode> cur_node; |
| 180 hr_ = cur_element_.As(&cur_node); |
| 181 if (HasFailed()) |
| 182 return; |
| 183 mswr::ComPtr<winxml::Dom::IXmlNode> appended_node; |
| 184 hr_ = cur_node->AppendChild(text_node.Get(), &appended_node); |
| 185 } |
| 186 |
| 187 void NotificationToastHelperWin::SetAttribute(const base::string16& name, |
| 188 const base::string16& value) { |
| 189 if (HasFailed()) |
| 190 return; |
| 191 if (!cur_element_) { |
| 192 hr_ = E_FAIL; |
| 193 return; |
| 194 } |
| 195 mswrw::HString name_hs; |
| 196 name_hs.Attach(MakeHString(name)); |
| 197 if (HasFailed()) |
| 198 return; |
| 199 mswrw::HString value_hs; |
| 200 value_hs.Attach(MakeHString(value)); |
| 201 if (HasFailed()) |
| 202 return; |
| 203 hr_ = cur_element_->SetAttribute(name_hs.Get(), value_hs.Get()); |
| 204 } |
| 205 |
| 206 base::string16 NotificationToastHelperWin::GetAttribute( |
| 207 const base::string16& name) { |
| 208 if (HasFailed()) |
| 209 return L""; |
| 210 if (!cur_element_) { |
| 211 hr_ = E_FAIL; |
| 212 return L""; |
| 213 } |
| 214 mswrw::HString name_hs; |
| 215 name_hs.Attach(MakeHString(name)); |
| 216 if (HasFailed()) |
| 217 return L""; |
| 218 HSTRING value; |
| 219 hr_ = cur_element_->GetAttribute(name_hs.Get(), &value); |
| 220 if (HasFailed()) |
| 221 return L""; |
| 222 PCWSTR str = WindowsGetStringRawBuffer(value, NULL); |
| 223 return base::string16(str); |
| 224 } |
| 225 |
| 226 void NotificationToastHelperWin::CreateToastNotifier() { |
| 227 if (HasFailed()) |
| 228 return; |
| 229 base::string16 appid = GetChromeAppId(); |
| 230 if (appid.empty()) { |
| 231 hr_ = E_FAIL; |
| 232 return; |
| 233 } |
| 234 mswrw::HString app_user_model_id; |
| 235 app_user_model_id.Attach(MakeHString(appid)); |
| 236 if (HasFailed()) |
| 237 return; |
| 238 hr_ = toast_manager_->CreateToastNotifierWithId(app_user_model_id.Get(), |
| 239 ¬ifier_); |
| 240 } |
| 241 |
| 242 void NotificationToastHelperWin::CreateToastNotification() { |
| 243 if (HasFailed()) |
| 244 return; |
| 245 mswr::ComPtr<winui::Notifications::IToastNotificationFactory> |
| 246 toast_notification_factory; |
| 247 hr_ = CreateActivationFactory( |
| 248 RuntimeClass_Windows_UI_Notifications_ToastNotification, |
| 249 toast_notification_factory.GetAddressOf()); |
| 250 if (HasFailed()) |
| 251 return; |
| 252 hr_ = toast_notification_factory->CreateToastNotification( |
| 253 toast_xml_.Get(), &toast_notification_); |
| 254 } |
| 255 |
| 256 void NotificationToastHelperWin::LoadNotificationAndXml( |
| 257 winui::Notifications::IToastNotification* toast_notification) { |
| 258 if (HasFailed()) |
| 259 return; |
| 260 toast_notification_ = toast_notification; |
| 261 hr_ = toast_notification_->get_Content(&toast_xml_); |
| 262 if (HasFailed()) |
| 263 return; |
| 264 hr_ = toast_xml_->get_DocumentElement(&document_element_); |
| 265 if (!document_element_) |
| 266 hr_ = E_FAIL; |
| 267 } |
| 268 |
| 269 void NotificationToastHelperWin::Show( |
| 270 mswr::ComPtr<ToastActivatedHandler> activated_handler, |
| 271 mswr::ComPtr<ToastDismissedHandler> dismissed_handler, |
| 272 mswr::ComPtr<ToastFailedHandler> failed_handler, |
| 273 EventRegistrationToken* activated_token, |
| 274 EventRegistrationToken* dismissed_token, |
| 275 EventRegistrationToken* failed_token) { |
| 276 if (HasFailed()) |
| 277 return; |
| 278 hr_ = toast_notification_->add_Activated(activated_handler.Get(), |
| 279 activated_token); |
| 280 if (HasFailed()) |
| 281 return; |
| 282 hr_ = toast_notification_->add_Dismissed(dismissed_handler.Get(), |
| 283 dismissed_token); |
| 284 if (HasFailed()) |
| 285 return; |
| 286 hr_ = toast_notification_->add_Failed(failed_handler.Get(), failed_token); |
| 287 if (HasFailed()) |
| 288 return; |
| 289 hr_ = notifier_->Show(toast_notification_.Get()); |
| 290 } |
| 291 |
| 292 // Returned HSTRING should be deallocated by ::WindowsDeleteString(). This can |
| 293 // be done by attaching the return value to mswrw::HString. |
| 294 HSTRING NotificationToastHelperWin::MakeHString(const base::string16& str) { |
| 295 if (HasFailed()) |
| 296 return NULL; |
| 297 HSTRING hstr; |
| 298 hr_ = ::WindowsCreateString(str.c_str(), |
| 299 static_cast<UINT32>(str.size()), |
| 300 &hstr); |
| 301 if (HasFailed()) { |
| 302 DVLOG(1) << "HString creation failed."; |
| 303 return NULL; |
| 304 } |
| 305 return hstr; |
| 306 } |
| 307 |
| 308 void NotificationToastHelperWin::CreateTextNode(const base::string16& text, |
| 309 mswr::ComPtr<winxml::Dom::IXmlNode>* node) { |
| 310 if (HasFailed()) |
| 311 return; |
| 312 mswrw::HString text_hs; |
| 313 text_hs.Attach(MakeHString(text)); |
| 314 if (HasFailed()) |
| 315 return; |
| 316 mswr::ComPtr<winxml::Dom::IXmlText> text_xml; |
| 317 hr_ = toast_xml_->CreateTextNode(text_hs.Get(), &text_xml); |
| 318 if (HasFailed()) |
| 319 return; |
| 320 hr_ = text_xml.As(node); |
| 321 } |
OLD | NEW |