| Index: chrome/browser/notifications/notification_toast_helper_win.cc
|
| diff --git a/chrome/browser/notifications/notification_toast_helper_win.cc b/chrome/browser/notifications/notification_toast_helper_win.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d8ae1eb9a349fcfa9f6309e4e1fd9d02853fe584
|
| --- /dev/null
|
| +++ b/chrome/browser/notifications/notification_toast_helper_win.cc
|
| @@ -0,0 +1,321 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/notifications/notification_toast_helper_win.h"
|
| +
|
| +#include <vector>
|
| +
|
| +#include "base/files/file_path.h"
|
| +#include "chrome/installer/util/install_util.h"
|
| +#include "chrome/installer/util/shell_util.h"
|
| +
|
| +namespace {
|
| +
|
| +// Templated wrapper for winfoundtn::GetActivationFactory().
|
| +template<unsigned int size, typename T>
|
| +HRESULT CreateActivationFactory(wchar_t const (&class_name)[size], T** object) {
|
| + mswrw::HStringReference ref_class_name(class_name);
|
| + return winfoundtn::GetActivationFactory(ref_class_name.Get(), object);
|
| +}
|
| +
|
| +// Returns Chrome's AppId on success, and empty string on failure.
|
| +base::string16 GetChromeAppId() {
|
| + bool is_per_user_install = InstallUtil::IsPerUserInstall();
|
| + base::string16 appid = ShellUtil::GetBrowserModelId(is_per_user_install);
|
| + DVLOG(1) << "Chrome Appid is " << appid.c_str();
|
| + return appid;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +void NotificationToastHelperWin::CreateToastManager() {
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = CreateActivationFactory(
|
| + RuntimeClass_Windows_UI_Notifications_ToastNotificationManager,
|
| + toast_manager_.GetAddressOf());
|
| +}
|
| +
|
| +void NotificationToastHelperWin::LoadXMLFromTemplate(
|
| + winui::Notifications::ToastTemplateType type) {
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = toast_manager_->GetTemplateContent(type, &toast_xml_);
|
| + if (!toast_xml_) {
|
| + hr_ = E_FAIL;
|
| + return;
|
| + }
|
| + hr_ = toast_xml_->get_DocumentElement(&document_element_);
|
| + if (!document_element_)
|
| + hr_ = E_FAIL;
|
| +}
|
| +
|
| +void NotificationToastHelperWin::LoadXMLFromString(
|
| + const base::string16& xml_str) {
|
| + if (HasFailed())
|
| + return;
|
| + mswr::ComPtr<winxml::Dom::IXmlDocumentIO> xml_document;
|
| +
|
| + mswrw::HStringReference ref_class_name(
|
| + RuntimeClass_Windows_Data_Xml_Dom_XmlDocument);
|
| + hr_ = Windows::Foundation::ActivateInstance(ref_class_name.Get(),
|
| + &xml_document);
|
| + // hr_ = CreateActivationFactory(
|
| + // RuntimeClass_Windows_Data_Xml_Dom_XmlDocument,
|
| + // xml_document.GetAddressOf());
|
| + if (HasFailed())
|
| + return;
|
| +
|
| + mswrw::HString xml_hs;
|
| + xml_hs.Attach(MakeHString(xml_str));
|
| + hr_ = xml_document->LoadXml(xml_hs.Get());
|
| + if (HasFailed())
|
| + return;
|
| +
|
| + winxml::Dom::IXmlDocument** xml = &toast_xml_;
|
| + hr_ = xml_document.CopyTo(xml);
|
| + if (!document_element_)
|
| + hr_ = E_FAIL;
|
| +
|
| + hr_ = toast_xml_->get_DocumentElement(&document_element_);
|
| +}
|
| +
|
| +// For debugging.
|
| +// TODO(huangs): Remove.
|
| +void NotificationToastHelperWin::AlertToastXml() {
|
| + if (HasFailed())
|
| + return;
|
| + mswr::ComPtr<ABI::Windows::Data::Xml::Dom::IXmlNodeSerializer> s;
|
| + toast_xml_.As(&s);
|
| + HSTRING xml_string;
|
| + hr_ = s->GetXml(&xml_string);
|
| + if (StillOkay()) {
|
| + PCWSTR str = WindowsGetStringRawBuffer(xml_string, NULL);
|
| + ::MessageBox(NULL, str, L"Title", MB_OK);
|
| + }
|
| +}
|
| +
|
| +void NotificationToastHelperWin::SelectDocument() {
|
| + if (HasFailed())
|
| + return;
|
| + if (document_element_)
|
| + cur_element_ = document_element_;
|
| + else
|
| + hr_ = E_FAIL;
|
| +}
|
| +
|
| +void NotificationToastHelperWin::SelectElementByTagNameAndIndex(
|
| + const base::string16& tag_name, unsigned int index) {
|
| + if (HasFailed())
|
| + return;
|
| + mswrw::HString hs_tag_name;
|
| + hs_tag_name.Attach(MakeHString(tag_name));
|
| + if (HasFailed())
|
| + return;
|
| + mswr::ComPtr<winxml::Dom::IXmlNodeList> elements;
|
| + hr_ = document_element_->GetElementsByTagName(hs_tag_name.Get(), &elements);
|
| + if (HasFailed())
|
| + return;
|
| + unsigned int count = 0;
|
| + elements->get_Length(&count);
|
| + if (index >= count) {
|
| + DVLOG(1) << "Requesting nonexistent node with tag_name " << tag_name
|
| + << " and index " << index;
|
| + hr_ = E_FAIL;
|
| + return;
|
| + }
|
| + mswr::ComPtr<winxml::Dom::IXmlNode> cur_node;
|
| + hr_ = elements->Item(index, &cur_node);
|
| + if (StillOkay())
|
| + hr_ = cur_node.As(&cur_element_);
|
| +}
|
| +
|
| +// Converts a file path, e.g., "C:\\User\\test\\AppData\\Local\\Temp\\a.tmp"
|
| +// to a file URL, e.g., "file:///C:/User/test/AppData/Local/Temp/a.tmp".
|
| +base::string16 NotificationToastHelperWin::FilePathToFileUrl(
|
| + const base::FilePath& file_path) {
|
| + if (HasFailed())
|
| + return L"";
|
| + const size_t kFileUrlExtraSize = 10; // Acommodates L"file:///". and L'\0'.
|
| + base::string16 file_str = file_path.AsUTF16Unsafe();
|
| + DWORD size = static_cast<DWORD>(file_str.size() + kFileUrlExtraSize);
|
| + std::vector<base::char16> buffer(size);
|
| + hr_ = ::UrlCreateFromPathW(file_str.c_str(), &buffer[0], &size, NULL);
|
| + if (HasFailed())
|
| + return L"";
|
| + return base::string16(&buffer[0]);
|
| +}
|
| +
|
| +void NotificationToastHelperWin::RemoveElement() {
|
| + if (HasFailed())
|
| + return;
|
| + mswr::ComPtr<winxml::Dom::IXmlNode> cur_node;
|
| + hr_ = cur_element_.As(&cur_node);
|
| + if (HasFailed())
|
| + return;
|
| + mswr::ComPtr<winxml::Dom::IXmlNode> parent_node;
|
| + hr_ = cur_node->get_ParentNode(&parent_node);
|
| + if (HasFailed())
|
| + return;
|
| + mswr::ComPtr<winxml::Dom::IXmlNode> removed_node;
|
| + hr_ = parent_node->RemoveChild(cur_node.Get(), &removed_node);
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = parent_node.As(&cur_element_);
|
| +}
|
| +
|
| +void NotificationToastHelperWin::AppendText(const base::string16& text) {
|
| + if (HasFailed())
|
| + return;
|
| + if (!cur_element_) {
|
| + hr_ = E_FAIL;
|
| + return;
|
| + }
|
| + mswr::ComPtr<winxml::Dom::IXmlNode> text_node;
|
| + CreateTextNode(text, &text_node);
|
| + if (HasFailed())
|
| + return;
|
| + mswr::ComPtr<winxml::Dom::IXmlNode> cur_node;
|
| + hr_ = cur_element_.As(&cur_node);
|
| + if (HasFailed())
|
| + return;
|
| + mswr::ComPtr<winxml::Dom::IXmlNode> appended_node;
|
| + hr_ = cur_node->AppendChild(text_node.Get(), &appended_node);
|
| +}
|
| +
|
| +void NotificationToastHelperWin::SetAttribute(const base::string16& name,
|
| + const base::string16& value) {
|
| + if (HasFailed())
|
| + return;
|
| + if (!cur_element_) {
|
| + hr_ = E_FAIL;
|
| + return;
|
| + }
|
| + mswrw::HString name_hs;
|
| + name_hs.Attach(MakeHString(name));
|
| + if (HasFailed())
|
| + return;
|
| + mswrw::HString value_hs;
|
| + value_hs.Attach(MakeHString(value));
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = cur_element_->SetAttribute(name_hs.Get(), value_hs.Get());
|
| +}
|
| +
|
| +base::string16 NotificationToastHelperWin::GetAttribute(
|
| + const base::string16& name) {
|
| + if (HasFailed())
|
| + return L"";
|
| + if (!cur_element_) {
|
| + hr_ = E_FAIL;
|
| + return L"";
|
| + }
|
| + mswrw::HString name_hs;
|
| + name_hs.Attach(MakeHString(name));
|
| + if (HasFailed())
|
| + return L"";
|
| + HSTRING value;
|
| + hr_ = cur_element_->GetAttribute(name_hs.Get(), &value);
|
| + if (HasFailed())
|
| + return L"";
|
| + PCWSTR str = WindowsGetStringRawBuffer(value, NULL);
|
| + return base::string16(str);
|
| +}
|
| +
|
| +void NotificationToastHelperWin::CreateToastNotifier() {
|
| + if (HasFailed())
|
| + return;
|
| + base::string16 appid = GetChromeAppId();
|
| + if (appid.empty()) {
|
| + hr_ = E_FAIL;
|
| + return;
|
| + }
|
| + mswrw::HString app_user_model_id;
|
| + app_user_model_id.Attach(MakeHString(appid));
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = toast_manager_->CreateToastNotifierWithId(app_user_model_id.Get(),
|
| + ¬ifier_);
|
| +}
|
| +
|
| +void NotificationToastHelperWin::CreateToastNotification() {
|
| + if (HasFailed())
|
| + return;
|
| + mswr::ComPtr<winui::Notifications::IToastNotificationFactory>
|
| + toast_notification_factory;
|
| + hr_ = CreateActivationFactory(
|
| + RuntimeClass_Windows_UI_Notifications_ToastNotification,
|
| + toast_notification_factory.GetAddressOf());
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = toast_notification_factory->CreateToastNotification(
|
| + toast_xml_.Get(), &toast_notification_);
|
| +}
|
| +
|
| +void NotificationToastHelperWin::LoadNotificationAndXml(
|
| + winui::Notifications::IToastNotification* toast_notification) {
|
| + if (HasFailed())
|
| + return;
|
| + toast_notification_ = toast_notification;
|
| + hr_ = toast_notification_->get_Content(&toast_xml_);
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = toast_xml_->get_DocumentElement(&document_element_);
|
| + if (!document_element_)
|
| + hr_ = E_FAIL;
|
| +}
|
| +
|
| +void NotificationToastHelperWin::Show(
|
| + mswr::ComPtr<ToastActivatedHandler> activated_handler,
|
| + mswr::ComPtr<ToastDismissedHandler> dismissed_handler,
|
| + mswr::ComPtr<ToastFailedHandler> failed_handler,
|
| + EventRegistrationToken* activated_token,
|
| + EventRegistrationToken* dismissed_token,
|
| + EventRegistrationToken* failed_token) {
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = toast_notification_->add_Activated(activated_handler.Get(),
|
| + activated_token);
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = toast_notification_->add_Dismissed(dismissed_handler.Get(),
|
| + dismissed_token);
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = toast_notification_->add_Failed(failed_handler.Get(), failed_token);
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = notifier_->Show(toast_notification_.Get());
|
| +}
|
| +
|
| +// Returned HSTRING should be deallocated by ::WindowsDeleteString(). This can
|
| +// be done by attaching the return value to mswrw::HString.
|
| +HSTRING NotificationToastHelperWin::MakeHString(const base::string16& str) {
|
| + if (HasFailed())
|
| + return NULL;
|
| + HSTRING hstr;
|
| + hr_ = ::WindowsCreateString(str.c_str(),
|
| + static_cast<UINT32>(str.size()),
|
| + &hstr);
|
| + if (HasFailed()) {
|
| + DVLOG(1) << "HString creation failed.";
|
| + return NULL;
|
| + }
|
| + return hstr;
|
| +}
|
| +
|
| +void NotificationToastHelperWin::CreateTextNode(const base::string16& text,
|
| + mswr::ComPtr<winxml::Dom::IXmlNode>* node) {
|
| + if (HasFailed())
|
| + return;
|
| + mswrw::HString text_hs;
|
| + text_hs.Attach(MakeHString(text));
|
| + if (HasFailed())
|
| + return;
|
| + mswr::ComPtr<winxml::Dom::IXmlText> text_xml;
|
| + hr_ = toast_xml_->CreateTextNode(text_hs.Get(), &text_xml);
|
| + if (HasFailed())
|
| + return;
|
| + hr_ = text_xml.As(node);
|
| +}
|
|
|