Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3262)

Unified Diff: chrome/browser/notifications/notification_platform_bridge_win.cc

Issue 2033093003: [Notification] Make HTML5 Notification use ActionCenter on Windows 10, behind Flags. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/notifications/notification_platform_bridge_win.cc
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.cc b/chrome/browser/notifications/notification_platform_bridge_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..74389f95962343feb83e3a959b8d3619eafa610b
--- /dev/null
+++ b/chrome/browser/notifications/notification_platform_bridge_win.cc
@@ -0,0 +1,278 @@
+// 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_platform_bridge_win.h"
+
+#include <activation.h>
+#include <d2d1_1.h>
+#include <d3d11_1.h>
+#include <roapi.h>
+#include <stdio.h>
+#include <wincodec.h>
+#include <windows.h>
+#include <windows.applicationModel.core.h>
+#include <windows.applicationModel.datatransfer.h>
+#include <windows.graphics.printing.h>
+#include <windows.storage.pickers.h>
+#include <windows.ui.notifications.h>
+#include <wrl/implements.h>
+#include <wrl/module.h>
+#include <wrl/event.h>
+#include <wrl/wrappers/corewrappers.h>
+
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/strings/string16.h"
+#include "base/win/scoped_comptr.h"
+#include "chrome/browser/notifications/notification.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/shell_util.h"
+
+namespace mswr = Microsoft::WRL;
+namespace mswrw = Microsoft::WRL::Wrappers;
+
+namespace winapp = ABI::Windows::ApplicationModel;
+namespace windata = ABI::Windows::Data;
+namespace winxml = ABI::Windows::Data::Xml;
+namespace windevs = ABI::Windows::Devices;
+namespace winfoundtn = ABI::Windows::Foundation;
+namespace wingfx = ABI::Windows::Graphics;
+namespace winui = ABI::Windows::UI;
+namespace winsys = ABI::Windows::System;
+namespace winstorage = ABI::Windows::Storage;
+
+typedef winfoundtn::ITypedEventHandler<
+ winui::Notifications::ToastNotification*, IInspectable*>
+ ToastActivationHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+ winui::Notifications::ToastNotification*,
+ winui::Notifications::ToastDismissedEventArgs*> ToastDismissedHandler;
+
+namespace {
+
+void CheckHR(HRESULT hr, const char* message = nullptr) {
chrisha 2016/06/02 21:14:10 Worth documenting that this is non-returning and c
Peter Beverloo 2016/06/07 15:48:29 I don't know if this is common for Windows code, b
huangs 2016/06/07 23:27:46 Done.
huangs 2016/06/07 23:27:46 From sample code, looks the style should be a chai
+ if (FAILED(hr)) {
+ if (message)
+ PLOG(DFATAL) << message << ", hr = " << std::hex << hr;
+ else
+ PLOG(DFATAL) << "COM ERROR" << ", hr = " << std::hex << hr;
+ }
+}
+
+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);
+}
+
+HSTRING MakeHString(const base::string16& str) {
Peter Beverloo 2016/06/07 15:48:29 Dito here, although as I understand it a NULL HSTR
huangs 2016/06/08 22:12:13 Done. Made the entire thing defensive in Patch #3;
+ HSTRING hstr;
+ if (FAILED(::WindowsCreateString(str.c_str(), static_cast<UINT32>(str.size()),
+ &hstr))) {
+ PLOG(DFATAL) << "Hstring creation failed";
+ }
+ return hstr;
+}
+
+
+// Helper function to return the text node root identified by the index passed
+// in.
+HRESULT GetTextNodeRoot(
+ unsigned int index,
+ winxml::Dom::IXmlDocument* xml_doc,
+ winxml::Dom::IXmlNode** node) {
+ DCHECK(xml_doc);
+ DCHECK(node);
+
+ mswr::ComPtr<winxml::Dom::IXmlElement> document_element;
+ HRESULT hr = xml_doc->get_DocumentElement(&document_element);
+ CheckHR(hr);
+
+ mswr::ComPtr<winxml::Dom::IXmlNodeList> elements;
+ mswrw::HString tag_name;
+ tag_name.Attach(MakeHString(L"text"));
+ hr = document_element->GetElementsByTagName(tag_name.Get(),
+ &elements);
+ CheckHR(hr);
+
+ unsigned int count = 0;
+ elements->get_Length(&count);
+
+ if (index > count) {
Peter Beverloo 2016/06/07 15:48:29 It sounds like the index to IXmlNode::Item() is ze
huangs 2016/06/14 01:12:35 Done.
+ DVLOG(1) << "Invalid text node index passed in : " << index;
+ return E_FAIL;
+ }
+ hr = elements->Item(index, node);
+ CheckHR(hr);
+ return hr;
+}
+
+// Helper function to append a text element to the text section in the
+// XML document passed in.
+// The index parameter identifies which text node we append to.
+HRESULT CreateTextNode(winxml::Dom::IXmlDocument* xml_doc,
+ int index,
+ const base::string16& text_string) {
+ DCHECK(xml_doc);
+
+ mswr::ComPtr<winxml::Dom::IXmlElement> document_element;
+ HRESULT hr = xml_doc->get_DocumentElement(&document_element);
+ CheckHR(hr);
+
+ mswr::ComPtr<winxml::Dom::IXmlText> xml_text_node;
+ mswrw::HString data_hstring;
+ data_hstring.Attach(MakeHString(text_string.c_str()));
+ hr = xml_doc->CreateTextNode(data_hstring.Get(), &xml_text_node);
+ CheckHR(hr);
+
+ mswr::ComPtr<winxml::Dom::IXmlNode> created_node;
+ hr = xml_text_node.CopyTo(
+ winxml::Dom::IID_IXmlNode,
+ reinterpret_cast<void**>(created_node.GetAddressOf()));
+ CheckHR(hr);
+
+ mswr::ComPtr<winxml::Dom::IXmlNode> text_node_root;
+ hr = GetTextNodeRoot(index, xml_doc, &text_node_root);
Peter Beverloo 2016/06/07 15:48:29 nit: CreateTextNode takes |index| as an (int), but
huangs 2016/06/08 22:12:13 Refactoring removed this difference. Now using un
+ CheckHR(hr);
+
+ mswr::ComPtr<winxml::Dom::IXmlNode> appended_node;
+ hr = text_node_root->AppendChild(created_node.Get(), &appended_node);
+ CheckHR(hr);
+ return hr;
+}
+
+} // namespace
+
+// static
+NotificationPlatformBridge* NotificationPlatformBridge::Create() {
+ return new NotificationPlatformBridgeWin();
+}
+
+NotificationPlatformBridgeWin::NotificationPlatformBridgeWin() {}
+
+NotificationPlatformBridgeWin::~NotificationPlatformBridgeWin() {}
+
+void NotificationPlatformBridgeWin::Display(const std::string& notification_id,
+ const std::string& profile_id,
+ bool incognito,
+ const Notification& notification) {
+ mswr::ComPtr<winui::Notifications::IToastNotifier> notifier_;
+ mswr::ComPtr<winui::Notifications::IToastNotification> toast_notification_;
+
+ DCHECK(notifier_.Get() == NULL);
+ DCHECK(toast_notification_.Get() == NULL);
+
+ mswr::ComPtr<winui::Notifications::IToastNotificationManagerStatics>
+ toast_manager;
+
+ HRESULT hr = CreateActivationFactory(
+ RuntimeClass_Windows_UI_Notifications_ToastNotificationManager,
+ toast_manager.GetAddressOf());
+ CheckHR(hr);
+
+ mswr::ComPtr<winxml::Dom::IXmlDocument> toast_xml;
+ hr = toast_manager->GetTemplateContent(
+ winui::Notifications::ToastTemplateType_ToastText02,
Peter Beverloo 2016/06/07 15:48:29 I agree with starting with ToastText02, but could
huangs 2016/06/08 22:12:13 Refactored code to shuffle ugliness in helper clas
+ &toast_xml);
+ CheckHR(hr);
+
+ if (!toast_xml)
+ return;
+
+ mswr::ComPtr<winxml::Dom::IXmlElement> document_element;
+ hr = toast_xml->get_DocumentElement(&document_element);
+ CheckHR(hr);
+
+ if (!document_element)
+ return;
+
+ hr = CreateTextNode(toast_xml.Get(), 0, notification.title());
chrisha 2016/06/02 21:14:10 Where does the constant '0' come from?
huangs 2016/06/08 22:12:13 First <text> element in the template, which looks
+ CheckHR(hr);
+
+ hr = CreateTextNode(toast_xml.Get(), 1, notification.message());
chrisha 2016/06/02 21:14:10 Ditto '1'? Maybe make these constants describing w
+ CheckHR(hr);
+
+ mswrw::HString duration_attribute_name;
+ duration_attribute_name.Attach(MakeHString(L"duration"));
+ mswrw::HString duration_attribute_value;
+ duration_attribute_value.Attach(MakeHString(L"long"));
+
+ hr = document_element->SetAttribute(duration_attribute_name.Get(),
+ duration_attribute_value.Get());
+ CheckHR(hr);
+
+ // TODO(ananta)
+ // We should set the image and launch params attribute in the notification
+ // XNL as described here: http://msdn.microsoft.com/en-us/library/hh465448
+ // To set the image we may have to extract the image and specify it in the
+ // following url form. ms-appx:///images/foo.png
+ // The launch params as described don't get passed back to us via the
+ // winapp::Activation::ILaunchActivatedEventArgs argument. Needs to be
+ // investigated.
+ mswr::ComPtr<winui::Notifications::IToastNotificationFactory>
+ toast_notification_factory;
+ hr = CreateActivationFactory(
+ RuntimeClass_Windows_UI_Notifications_ToastNotification,
+ toast_notification_factory.GetAddressOf());
+ CheckHR(hr);
+
+ hr = toast_notification_factory->CreateToastNotification(
+ toast_xml.Get(), &toast_notification_);
+ CheckHR(hr);
+
+ base::FilePath chrome_path;
+ if (!PathService::Get(base::FILE_EXE, &chrome_path)) {
+ NOTREACHED() << "Failed to get chrome exe path";
+ return;
+ }
+
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ bool is_per_user_install = InstallUtil::IsPerUserInstall(chrome_path);
+ base::string16 appid =
+ ShellUtil::GetBrowserModelId(dist, is_per_user_install);
+ DVLOG(1) << "Chrome Appid is " << appid.c_str();
+
+ mswrw::HString app_user_model_id;
+ app_user_model_id.Attach(MakeHString(appid));
+
+ hr = toast_manager->CreateToastNotifierWithId(app_user_model_id.Get(),
+ &notifier_);
+ CheckHR(hr);
+
+ EventRegistrationToken activated_token_;
+ hr = toast_notification_->add_Activated(
+ mswr::Callback<ToastActivationHandler>(
+ this, &NotificationPlatformBridgeWin::OnActivate).Get(),
+ &activated_token_);
+ CheckHR(hr);
+
+ hr = notifier_->Show(toast_notification_.Get());
+ CheckHR(hr);
+}
+
+void NotificationPlatformBridgeWin::Close(
+ const std::string& profile_id,
+ const std::string& notification_id) {
+ // TODO(huangs): Implement.
+}
+
+bool NotificationPlatformBridgeWin::GetDisplayed(
+ const std::string& profile_id,
+ bool incognito,
+ std::set<std::string>* notifications) const {
+ // TODO(huangs): Implement.
Peter Beverloo 2016/06/07 15:48:29 Do you expect any issues in supporting these two T
+ return true;
+}
+
+bool NotificationPlatformBridgeWin::SupportsNotificationCenter() const {
+ return true;
+}
+
+HRESULT NotificationPlatformBridgeWin::OnActivate(
+ winui::Notifications::IToastNotification* notification,
+ IInspectable* inspectable) {
+ return S_OK;
+}

Powered by Google App Engine
This is Rietveld 408576698