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

Side by Side 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, 6 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 unified diff | Download patch
OLDNEW
(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_platform_bridge_win.h"
6
7 #include <activation.h>
8 #include <d2d1_1.h>
9 #include <d3d11_1.h>
10 #include <roapi.h>
11 #include <stdio.h>
12 #include <wincodec.h>
13 #include <windows.h>
14 #include <windows.applicationModel.core.h>
15 #include <windows.applicationModel.datatransfer.h>
16 #include <windows.graphics.printing.h>
17 #include <windows.storage.pickers.h>
18 #include <windows.ui.notifications.h>
19 #include <wrl/implements.h>
20 #include <wrl/module.h>
21 #include <wrl/event.h>
22 #include <wrl/wrappers/corewrappers.h>
23
24 #include "base/files/file_path.h"
25 #include "base/path_service.h"
26 #include "base/strings/string16.h"
27 #include "base/win/scoped_comptr.h"
28 #include "chrome/browser/notifications/notification.h"
29 #include "chrome/installer/util/browser_distribution.h"
30 #include "chrome/installer/util/install_util.h"
31 #include "chrome/installer/util/shell_util.h"
32
33 namespace mswr = Microsoft::WRL;
34 namespace mswrw = Microsoft::WRL::Wrappers;
35
36 namespace winapp = ABI::Windows::ApplicationModel;
37 namespace windata = ABI::Windows::Data;
38 namespace winxml = ABI::Windows::Data::Xml;
39 namespace windevs = ABI::Windows::Devices;
40 namespace winfoundtn = ABI::Windows::Foundation;
41 namespace wingfx = ABI::Windows::Graphics;
42 namespace winui = ABI::Windows::UI;
43 namespace winsys = ABI::Windows::System;
44 namespace winstorage = ABI::Windows::Storage;
45
46 typedef winfoundtn::ITypedEventHandler<
47 winui::Notifications::ToastNotification*, IInspectable*>
48 ToastActivationHandler;
49
50 typedef winfoundtn::ITypedEventHandler<
51 winui::Notifications::ToastNotification*,
52 winui::Notifications::ToastDismissedEventArgs*> ToastDismissedHandler;
53
54 namespace {
55
56 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
57 if (FAILED(hr)) {
58 if (message)
59 PLOG(DFATAL) << message << ", hr = " << std::hex << hr;
60 else
61 PLOG(DFATAL) << "COM ERROR" << ", hr = " << std::hex << hr;
62 }
63 }
64
65 template<unsigned int size, typename T>
66 HRESULT CreateActivationFactory(wchar_t const (&class_name)[size], T** object) {
67 mswrw::HStringReference ref_class_name(class_name);
68 return winfoundtn::GetActivationFactory(ref_class_name.Get(), object);
69 }
70
71 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;
72 HSTRING hstr;
73 if (FAILED(::WindowsCreateString(str.c_str(), static_cast<UINT32>(str.size()),
74 &hstr))) {
75 PLOG(DFATAL) << "Hstring creation failed";
76 }
77 return hstr;
78 }
79
80
81 // Helper function to return the text node root identified by the index passed
82 // in.
83 HRESULT GetTextNodeRoot(
84 unsigned int index,
85 winxml::Dom::IXmlDocument* xml_doc,
86 winxml::Dom::IXmlNode** node) {
87 DCHECK(xml_doc);
88 DCHECK(node);
89
90 mswr::ComPtr<winxml::Dom::IXmlElement> document_element;
91 HRESULT hr = xml_doc->get_DocumentElement(&document_element);
92 CheckHR(hr);
93
94 mswr::ComPtr<winxml::Dom::IXmlNodeList> elements;
95 mswrw::HString tag_name;
96 tag_name.Attach(MakeHString(L"text"));
97 hr = document_element->GetElementsByTagName(tag_name.Get(),
98 &elements);
99 CheckHR(hr);
100
101 unsigned int count = 0;
102 elements->get_Length(&count);
103
104 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.
105 DVLOG(1) << "Invalid text node index passed in : " << index;
106 return E_FAIL;
107 }
108 hr = elements->Item(index, node);
109 CheckHR(hr);
110 return hr;
111 }
112
113 // Helper function to append a text element to the text section in the
114 // XML document passed in.
115 // The index parameter identifies which text node we append to.
116 HRESULT CreateTextNode(winxml::Dom::IXmlDocument* xml_doc,
117 int index,
118 const base::string16& text_string) {
119 DCHECK(xml_doc);
120
121 mswr::ComPtr<winxml::Dom::IXmlElement> document_element;
122 HRESULT hr = xml_doc->get_DocumentElement(&document_element);
123 CheckHR(hr);
124
125 mswr::ComPtr<winxml::Dom::IXmlText> xml_text_node;
126 mswrw::HString data_hstring;
127 data_hstring.Attach(MakeHString(text_string.c_str()));
128 hr = xml_doc->CreateTextNode(data_hstring.Get(), &xml_text_node);
129 CheckHR(hr);
130
131 mswr::ComPtr<winxml::Dom::IXmlNode> created_node;
132 hr = xml_text_node.CopyTo(
133 winxml::Dom::IID_IXmlNode,
134 reinterpret_cast<void**>(created_node.GetAddressOf()));
135 CheckHR(hr);
136
137 mswr::ComPtr<winxml::Dom::IXmlNode> text_node_root;
138 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
139 CheckHR(hr);
140
141 mswr::ComPtr<winxml::Dom::IXmlNode> appended_node;
142 hr = text_node_root->AppendChild(created_node.Get(), &appended_node);
143 CheckHR(hr);
144 return hr;
145 }
146
147 } // namespace
148
149 // static
150 NotificationPlatformBridge* NotificationPlatformBridge::Create() {
151 return new NotificationPlatformBridgeWin();
152 }
153
154 NotificationPlatformBridgeWin::NotificationPlatformBridgeWin() {}
155
156 NotificationPlatformBridgeWin::~NotificationPlatformBridgeWin() {}
157
158 void NotificationPlatformBridgeWin::Display(const std::string& notification_id,
159 const std::string& profile_id,
160 bool incognito,
161 const Notification& notification) {
162 mswr::ComPtr<winui::Notifications::IToastNotifier> notifier_;
163 mswr::ComPtr<winui::Notifications::IToastNotification> toast_notification_;
164
165 DCHECK(notifier_.Get() == NULL);
166 DCHECK(toast_notification_.Get() == NULL);
167
168 mswr::ComPtr<winui::Notifications::IToastNotificationManagerStatics>
169 toast_manager;
170
171 HRESULT hr = CreateActivationFactory(
172 RuntimeClass_Windows_UI_Notifications_ToastNotificationManager,
173 toast_manager.GetAddressOf());
174 CheckHR(hr);
175
176 mswr::ComPtr<winxml::Dom::IXmlDocument> toast_xml;
177 hr = toast_manager->GetTemplateContent(
178 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
179 &toast_xml);
180 CheckHR(hr);
181
182 if (!toast_xml)
183 return;
184
185 mswr::ComPtr<winxml::Dom::IXmlElement> document_element;
186 hr = toast_xml->get_DocumentElement(&document_element);
187 CheckHR(hr);
188
189 if (!document_element)
190 return;
191
192 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
193 CheckHR(hr);
194
195 hr = CreateTextNode(toast_xml.Get(), 1, notification.message());
chrisha 2016/06/02 21:14:10 Ditto '1'? Maybe make these constants describing w
196 CheckHR(hr);
197
198 mswrw::HString duration_attribute_name;
199 duration_attribute_name.Attach(MakeHString(L"duration"));
200 mswrw::HString duration_attribute_value;
201 duration_attribute_value.Attach(MakeHString(L"long"));
202
203 hr = document_element->SetAttribute(duration_attribute_name.Get(),
204 duration_attribute_value.Get());
205 CheckHR(hr);
206
207 // TODO(ananta)
208 // We should set the image and launch params attribute in the notification
209 // XNL as described here: http://msdn.microsoft.com/en-us/library/hh465448
210 // To set the image we may have to extract the image and specify it in the
211 // following url form. ms-appx:///images/foo.png
212 // The launch params as described don't get passed back to us via the
213 // winapp::Activation::ILaunchActivatedEventArgs argument. Needs to be
214 // investigated.
215 mswr::ComPtr<winui::Notifications::IToastNotificationFactory>
216 toast_notification_factory;
217 hr = CreateActivationFactory(
218 RuntimeClass_Windows_UI_Notifications_ToastNotification,
219 toast_notification_factory.GetAddressOf());
220 CheckHR(hr);
221
222 hr = toast_notification_factory->CreateToastNotification(
223 toast_xml.Get(), &toast_notification_);
224 CheckHR(hr);
225
226 base::FilePath chrome_path;
227 if (!PathService::Get(base::FILE_EXE, &chrome_path)) {
228 NOTREACHED() << "Failed to get chrome exe path";
229 return;
230 }
231
232 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
233 bool is_per_user_install = InstallUtil::IsPerUserInstall(chrome_path);
234 base::string16 appid =
235 ShellUtil::GetBrowserModelId(dist, is_per_user_install);
236 DVLOG(1) << "Chrome Appid is " << appid.c_str();
237
238 mswrw::HString app_user_model_id;
239 app_user_model_id.Attach(MakeHString(appid));
240
241 hr = toast_manager->CreateToastNotifierWithId(app_user_model_id.Get(),
242 &notifier_);
243 CheckHR(hr);
244
245 EventRegistrationToken activated_token_;
246 hr = toast_notification_->add_Activated(
247 mswr::Callback<ToastActivationHandler>(
248 this, &NotificationPlatformBridgeWin::OnActivate).Get(),
249 &activated_token_);
250 CheckHR(hr);
251
252 hr = notifier_->Show(toast_notification_.Get());
253 CheckHR(hr);
254 }
255
256 void NotificationPlatformBridgeWin::Close(
257 const std::string& profile_id,
258 const std::string& notification_id) {
259 // TODO(huangs): Implement.
260 }
261
262 bool NotificationPlatformBridgeWin::GetDisplayed(
263 const std::string& profile_id,
264 bool incognito,
265 std::set<std::string>* notifications) const {
266 // TODO(huangs): Implement.
Peter Beverloo 2016/06/07 15:48:29 Do you expect any issues in supporting these two T
267 return true;
268 }
269
270 bool NotificationPlatformBridgeWin::SupportsNotificationCenter() const {
271 return true;
272 }
273
274 HRESULT NotificationPlatformBridgeWin::OnActivate(
275 winui::Notifications::IToastNotification* notification,
276 IInspectable* inspectable) {
277 return S_OK;
278 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698