blob: c0d5a2a0d25acb6ef62da016492e9abde734bebd [file] [log] [blame]
// Copyright 2018 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/win/notification_util.h"
#include <wrl/client.h>
#include "base/win/scoped_hstring.h"
#include "chrome/browser/notifications/win/notification_launch_id.h"
#include "chrome/browser/notifications/win/notification_metrics.h"
#include "chrome/browser/notifications/win/notification_template_builder.h"
namespace mswr = Microsoft::WRL;
namespace winfoundtn = ABI::Windows::Foundation;
namespace winui = ABI::Windows::UI;
namespace winxml = ABI::Windows::Data::Xml;
using notifications_uma::GetNotificationLaunchIdStatus;
using base::win::ScopedHString;
NotificationLaunchId GetNotificationLaunchId(
winui::Notifications::IToastNotification* notification) {
mswr::ComPtr<winxml::Dom::IXmlDocument> document;
HRESULT hr = notification->get_Content(&document);
if (FAILED(hr)) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::NOTIFICATION_GET_CONTENT_FAILED);
DLOG(ERROR) << "Failed to get XML document";
return NotificationLaunchId();
}
ScopedHString tag = ScopedHString::Create(kNotificationToastElement);
mswr::ComPtr<winxml::Dom::IXmlNodeList> elements;
hr = document->GetElementsByTagName(tag.get(), &elements);
if (FAILED(hr)) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::GET_ELEMENTS_BY_TAG_FAILED);
DLOG(ERROR) << "Failed to get <toast> elements from document";
return NotificationLaunchId();
}
UINT32 length;
hr = elements->get_Length(&length);
if (length == 0) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::MISSING_TOAST_ELEMENT_IN_DOC);
DLOG(ERROR) << "No <toast> elements in document.";
return NotificationLaunchId();
}
mswr::ComPtr<winxml::Dom::IXmlNode> node;
hr = elements->Item(0, &node);
if (FAILED(hr)) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::ITEM_AT_FAILED);
DLOG(ERROR) << "Failed to get first <toast> element";
return NotificationLaunchId();
}
mswr::ComPtr<winxml::Dom::IXmlNamedNodeMap> attributes;
hr = node->get_Attributes(&attributes);
if (FAILED(hr)) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::GET_ATTRIBUTES_FAILED);
DLOG(ERROR) << "Failed to get attributes of <toast>";
return NotificationLaunchId();
}
mswr::ComPtr<winxml::Dom::IXmlNode> leaf;
ScopedHString id = ScopedHString::Create(kNotificationLaunchAttribute);
hr = attributes->GetNamedItem(id.get(), &leaf);
if (FAILED(hr)) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::GET_NAMED_ITEM_FAILED);
DLOG(ERROR) << "Failed to get launch attribute of <toast>";
return NotificationLaunchId();
}
if (!leaf) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::GET_NAMED_ITEM_NULL);
DLOG(ERROR) << "GetNamedItem returned null querying for 'launch' attribute";
return NotificationLaunchId();
}
mswr::ComPtr<winxml::Dom::IXmlNode> child;
hr = leaf->get_FirstChild(&child);
if (FAILED(hr)) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::GET_FIRST_CHILD_FAILED);
DLOG(ERROR) << "Failed to get content of launch attribute";
return NotificationLaunchId();
}
if (!child) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::GET_FIRST_CHILD_NULL);
DLOG(ERROR) << "Launch attribute is a null node";
return NotificationLaunchId();
}
mswr::ComPtr<IInspectable> inspectable;
hr = child->get_NodeValue(&inspectable);
if (FAILED(hr)) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::GET_NODE_VALUE_FAILED);
DLOG(ERROR) << "Failed to get node value of launch attribute";
return NotificationLaunchId();
}
mswr::ComPtr<winfoundtn::IPropertyValue> property_value;
hr = inspectable.As<winfoundtn::IPropertyValue>(&property_value);
if (FAILED(hr)) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::CONVERSION_TO_PROP_VALUE_FAILED);
DLOG(ERROR) << "Failed to convert node value of launch attribute";
return NotificationLaunchId();
}
HSTRING value_hstring;
hr = property_value->GetString(&value_hstring);
if (FAILED(hr)) {
LogGetNotificationLaunchIdStatus(
GetNotificationLaunchIdStatus::GET_STRING_FAILED);
DLOG(ERROR) << "Failed to get string for launch attribute";
return NotificationLaunchId();
}
LogGetNotificationLaunchIdStatus(GetNotificationLaunchIdStatus::SUCCESS);
ScopedHString value(value_hstring);
return NotificationLaunchId(value.GetAsUTF8());
}