18
18
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
19
20
20
21
+ #include " config.h"
21
22
#include " content/public/browser/web_contents.h"
22
23
#include " content/public/browser/render_frame_host.h"
23
24
#include " content/public/browser/render_view_host.h"
29
30
#include " base/strings/utf_string_conversions.h"
30
31
#include " content/nw/src/common/shell_switches.h"
31
32
#include " content/nw/src/nw_notification_manager_toast_win.h"
33
+ #include " platform/image-encoders/skia/PNGImageEncoder.h"
32
34
33
35
#include < Psapi.h>
34
36
#include < ShObjIdl.h>
@@ -43,70 +45,54 @@ using namespace Windows::Foundation;
43
45
44
46
namespace nw {
45
47
46
- class StringReferenceWrapper
47
- {
48
+ class StringReferenceWrapper {
48
49
public:
49
-
50
50
// Constructor which takes an existing string buffer and its length as the parameters.
51
51
// It fills an HSTRING_HEADER struct with the parameter.
52
52
// Warning: The caller must ensure the lifetime of the buffer outlives this
53
53
// object as it does not make a copy of the wide string memory.
54
54
55
- static bool isSupported ()
56
- {
55
+ static bool isSupported () {
57
56
static char cachedRes = -1 ;
58
57
if (cachedRes > -1 ) return cachedRes;
59
58
cachedRes = ::LoadLibrary (L" API-MS-WIN-CORE-WINRT-STRING-L1-1-0.DLL" ) != 0 ;
60
59
return cachedRes;
61
60
}
62
61
63
- StringReferenceWrapper (_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw ()
64
- {
62
+ StringReferenceWrapper (_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw () {
65
63
HRESULT hr = WindowsCreateStringReference (stringRef, length, &_header, &_hstring);
66
-
67
- if (FAILED (hr))
68
- {
64
+ if (FAILED (hr)) {
69
65
RaiseException (static_cast <DWORD>(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0 , nullptr );
70
66
}
71
67
}
72
68
73
- ~StringReferenceWrapper ()
74
- {
69
+ ~StringReferenceWrapper () {
75
70
WindowsDeleteString (_hstring);
76
71
}
77
72
78
73
template <size_t N>
79
- StringReferenceWrapper (_In_reads_(N) wchar_t const (&stringRef)[N]) throw()
80
- {
74
+ StringReferenceWrapper (_In_reads_(N) wchar_t const (&stringRef)[N]) throw() {
81
75
UINT32 length = N - 1 ;
82
76
HRESULT hr = WindowsCreateStringReference (stringRef, length, &_header, &_hstring);
83
-
84
- if (FAILED (hr))
85
- {
77
+ if (FAILED (hr)) {
86
78
RaiseException (static_cast <DWORD>(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0 , nullptr );
87
79
}
88
80
}
89
81
90
82
template <size_t _>
91
- StringReferenceWrapper (_In_reads_(_) wchar_t (&stringRef)[_]) throw ()
92
- {
83
+ StringReferenceWrapper (_In_reads_(_) wchar_t (&stringRef)[_]) throw () {
93
84
UINT32 length;
94
85
HRESULT hr = SizeTToUInt32 (wcslen (stringRef), &length);
95
-
96
- if (FAILED (hr))
97
- {
86
+ if (FAILED (hr)) {
98
87
RaiseException (static_cast <DWORD>(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0 , nullptr );
99
88
}
100
-
101
89
WindowsCreateStringReference (stringRef, length, &_header, &_hstring);
102
90
}
103
91
104
- HSTRING Get () const throw()
105
- {
92
+ HSTRING Get () const throw() {
106
93
return _hstring;
107
94
}
108
95
109
-
110
96
private:
111
97
HSTRING _hstring;
112
98
HSTRING_HEADER _header;
@@ -117,8 +103,7 @@ typedef ABI::Windows::Foundation::ITypedEventHandler<ABI::Windows::UI::Notificat
117
103
typedef ABI::Windows::Foundation::ITypedEventHandler<ABI::Windows::UI::Notifications::ToastNotification *, ABI::Windows::UI::Notifications::ToastFailedEventArgs *> DesktopToastFailedEventHandler;
118
104
119
105
class ToastEventHandler :
120
- public Microsoft::WRL::Implements<DesktopToastActivatedEventHandler, DesktopToastDismissedEventHandler, DesktopToastFailedEventHandler>
121
- {
106
+ public Microsoft::WRL::Implements<DesktopToastActivatedEventHandler, DesktopToastDismissedEventHandler, DesktopToastFailedEventHandler> {
122
107
public:
123
108
ToastEventHandler::ToastEventHandler (const int render_process_id, const int notification_id);
124
109
~ToastEventHandler ();
@@ -169,30 +154,23 @@ class ToastEventHandler :
169
154
// ============= ToastEventHandler Implementation =============
170
155
171
156
ToastEventHandler::ToastEventHandler (const int render_process_id, const int notification_id) :
172
- _ref (0 ), _render_process_id(render_process_id), _notification_id(notification_id)
173
- {
174
-
157
+ _ref (0 ), _render_process_id(render_process_id), _notification_id(notification_id) {
175
158
}
176
159
177
- ToastEventHandler::~ToastEventHandler ()
178
- {
179
-
160
+ ToastEventHandler::~ToastEventHandler () {
180
161
}
181
162
182
163
// DesktopToastActivatedEventHandler
183
- IFACEMETHODIMP ToastEventHandler::Invoke (_In_ IToastNotification* /* sender */ , _In_ IInspectable* /* args */ )
184
- {
164
+ IFACEMETHODIMP ToastEventHandler::Invoke (_In_ IToastNotification* /* sender */ , _In_ IInspectable* /* args */ ) {
185
165
BOOL succeeded = nw::NotificationManager::getSingleton ()->DesktopNotificationPostClick (_render_process_id, _notification_id);
186
166
return succeeded ? S_OK : E_FAIL;
187
167
}
188
168
189
169
// DesktopToastDismissedEventHandler
190
- IFACEMETHODIMP ToastEventHandler::Invoke (_In_ IToastNotification* /* sender */ , _In_ IToastDismissedEventArgs* e)
191
- {
170
+ IFACEMETHODIMP ToastEventHandler::Invoke (_In_ IToastNotification* /* sender */ , _In_ IToastDismissedEventArgs* e) {
192
171
ToastDismissalReason tdr;
193
172
HRESULT hr = e->get_Reason (&tdr);
194
- if (SUCCEEDED (hr))
195
- {
173
+ if (SUCCEEDED (hr)) {
196
174
BOOL succeeded = nw::NotificationManager::getSingleton ()->DesktopNotificationPostClose (_render_process_id, _notification_id, tdr == ToastDismissalReason_UserCanceled);
197
175
hr = succeeded ? S_OK : E_FAIL;
198
176
}
@@ -201,8 +179,7 @@ IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */,
201
179
}
202
180
203
181
// DesktopToastFailedEventHandler
204
- IFACEMETHODIMP ToastEventHandler::Invoke (_In_ IToastNotification* /* sender */ , _In_ IToastFailedEventArgs* e)
205
- {
182
+ IFACEMETHODIMP ToastEventHandler::Invoke (_In_ IToastNotification* /* sender */ , _In_ IToastFailedEventArgs* e) {
206
183
HRESULT errCode;
207
184
e->get_ErrorCode (&errCode);
208
185
nw::NotificationManagerToastWin* nmtw = static_cast <nw::NotificationManagerToastWin*>(nw::NotificationManager::getSingleton ());
@@ -224,18 +201,14 @@ IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */,
224
201
// ============= NotificationManagerToastWin Implementation =============
225
202
bool NotificationManagerToastWin::ForceDisable = false ;
226
203
227
- HRESULT NotificationManagerToastWin::SetNodeValueString (_In_ HSTRING inputString, _In_ IXmlNode *node, _In_ IXmlDocument *xml)
228
- {
204
+ HRESULT NotificationManagerToastWin::SetNodeValueString (_In_ HSTRING inputString, _In_ IXmlNode *node, _In_ IXmlDocument *xml) {
229
205
ComPtr<IXmlText> inputText;
230
206
231
207
HRESULT hr = xml->CreateTextNode (inputString, &inputText);
232
- if (SUCCEEDED (hr))
233
- {
208
+ if (SUCCEEDED (hr)) {
234
209
ComPtr<IXmlNode> inputTextNode;
235
-
236
210
hr = inputText.As (&inputTextNode);
237
- if (SUCCEEDED (hr))
238
- {
211
+ if (SUCCEEDED (hr)) {
239
212
ComPtr<IXmlNode> pAppendedChild;
240
213
hr = node->AppendChild (inputTextNode.Get (), &pAppendedChild);
241
214
}
@@ -245,28 +218,21 @@ HRESULT NotificationManagerToastWin::SetNodeValueString(_In_ HSTRING inputString
245
218
}
246
219
247
220
HRESULT NotificationManagerToastWin::SetTextValues (_In_reads_(textValuesCount) const wchar_t **textValues, _In_ UINT32 textValuesCount,
248
- _In_reads_(textValuesCount) UINT32 *textValuesLengths, _In_ IXmlDocument *toastXml)
249
- {
221
+ _In_reads_(textValuesCount) UINT32 *textValuesLengths, _In_ IXmlDocument *toastXml) {
250
222
HRESULT hr = textValues != nullptr && textValuesCount > 0 ? S_OK : E_INVALIDARG;
251
- if (SUCCEEDED (hr))
252
- {
223
+ if (SUCCEEDED (hr)) {
253
224
ComPtr<IXmlNodeList> nodeList;
254
225
hr = toastXml->GetElementsByTagName (StringReferenceWrapper (L" text" ).Get (), &nodeList);
255
- if (SUCCEEDED (hr))
256
- {
226
+ if (SUCCEEDED (hr)) {
257
227
UINT32 nodeListLength;
258
228
hr = nodeList->get_Length (&nodeListLength);
259
- if (SUCCEEDED (hr))
260
- {
229
+ if (SUCCEEDED (hr)) {
261
230
hr = textValuesCount <= nodeListLength ? S_OK : E_INVALIDARG;
262
- if (SUCCEEDED (hr))
263
- {
264
- for (UINT32 i = 0 ; i < textValuesCount; i++)
265
- {
231
+ if (SUCCEEDED (hr)) {
232
+ for (UINT32 i = 0 ; i < textValuesCount; i++) {
266
233
ComPtr<IXmlNode> textNode;
267
234
hr = nodeList->Item (i, &textNode);
268
- if (SUCCEEDED (hr))
269
- {
235
+ if (SUCCEEDED (hr)) {
270
236
hr = SetNodeValueString (StringReferenceWrapper (textValues[i], textValuesLengths[i]).Get (), textNode.Get (), toastXml);
271
237
}
272
238
}
@@ -277,30 +243,22 @@ HRESULT NotificationManagerToastWin::SetTextValues(_In_reads_(textValuesCount) c
277
243
return hr;
278
244
}
279
245
280
- HRESULT NotificationManagerToastWin::SetImageSrc (_In_z_ const wchar_t *imagePath, _In_ IXmlDocument *toastXml)
281
- {
246
+ HRESULT NotificationManagerToastWin::SetImageSrc (_In_z_ const wchar_t *imagePath, _In_ IXmlDocument *toastXml) {
282
247
wchar_t imageSrc[MAX_PATH] = L" " ;
283
248
HRESULT hr = StringCchCat (imageSrc, ARRAYSIZE (imageSrc), imagePath);
284
- if (SUCCEEDED (hr))
285
- {
249
+ if (SUCCEEDED (hr)) {
286
250
ComPtr<IXmlNodeList> nodeList;
287
251
hr = toastXml->GetElementsByTagName (StringReferenceWrapper (L" image" ).Get (), &nodeList);
288
- if (SUCCEEDED (hr))
289
- {
252
+ if (SUCCEEDED (hr)) {
290
253
ComPtr<IXmlNode> imageNode;
291
254
hr = nodeList->Item (0 , &imageNode);
292
- if (SUCCEEDED (hr))
293
- {
255
+ if (SUCCEEDED (hr)) {
294
256
ComPtr<IXmlNamedNodeMap> attributes;
295
-
296
257
hr = imageNode->get_Attributes (&attributes);
297
- if (SUCCEEDED (hr))
298
- {
258
+ if (SUCCEEDED (hr)) {
299
259
ComPtr<IXmlNode> srcAttribute;
300
-
301
260
hr = attributes->GetNamedItem (StringReferenceWrapper (L" src" ).Get (), &srcAttribute);
302
- if (SUCCEEDED (hr))
303
- {
261
+ if (SUCCEEDED (hr)) {
304
262
hr = SetNodeValueString (StringReferenceWrapper (imageSrc).Get (), srcAttribute.Get (), toastXml);
305
263
}
306
264
}
@@ -311,59 +269,59 @@ HRESULT NotificationManagerToastWin::SetImageSrc(_In_z_ const wchar_t *imagePath
311
269
}
312
270
313
271
HRESULT NotificationManagerToastWin::CreateToastXml (_In_ IToastNotificationManagerStatics *toastManager,
314
- const content::ShowDesktopNotificationHostMsgParams& params, _Outptr_ IXmlDocument** inputXml)
315
- {
316
- const bool bImage = params.icon .width () > 0 ;
272
+ const content::ShowDesktopNotificationHostMsgParams& params, _Outptr_ IXmlDocument** inputXml) {
273
+ bool bImage = params.icon .getSize () > 0 ;
274
+ char tempFileName[MAX_PATH];
275
+
276
+ if (bImage) {
277
+ char temp[MAX_PATH];
278
+ GetTempPathA (MAX_PATH, tempFileName);
279
+ GetTempFileNameA (tempFileName, " NTF" , 0 , temp);
280
+
281
+ Vector<char > encodedImage;
282
+ bImage = blink::PNGImageEncoder::encode (params.icon , reinterpret_cast <Vector<unsigned char >*>(&encodedImage));
283
+
284
+ FILE *f = fopen (temp, " wb" );
285
+ fwrite (encodedImage.data (), sizeof (char ), encodedImage.size (), f);
286
+ fclose (f);
287
+
288
+ sprintf_s (tempFileName, " file:///%s" , temp);
289
+ }
290
+
317
291
// Retrieve the template XML
318
292
HRESULT hr = toastManager->GetTemplateContent (bImage ? ToastTemplateType_ToastImageAndText03 : ToastTemplateType_ToastText03, inputXml);
319
- if (SUCCEEDED (hr))
320
- {
321
- if (SUCCEEDED (hr))
322
- {
323
- // FIXME
324
- #if 0
325
- hr = bImage ? SetImageSrc(base::UTF8ToWide(params.icon_url.spec()).c_str(), *inputXml) : S_OK;
326
- if (SUCCEEDED(hr))
327
- #endif
328
- {
329
- const wchar_t * textValues[] = {
330
- params.title .c_str (),
331
- params.body .c_str ()
332
- };
333
-
334
- UINT32 textLengths[] = { params.title .length (), params.body .length () };
335
-
336
- hr = SetTextValues (textValues, 2 , textLengths, *inputXml);
337
- }
293
+ if (SUCCEEDED (hr)) {
294
+ hr = bImage ? SetImageSrc (base::UTF8ToWide (tempFileName).c_str (), *inputXml) : S_OK;
295
+ if (SUCCEEDED (hr)) {
296
+ const wchar_t * textValues[] = {
297
+ params.title .c_str (),
298
+ params.body .c_str ()
299
+ };
300
+ UINT32 textLengths[] = { params.title .length (), params.body .length () };
301
+ hr = SetTextValues (textValues, 2 , textLengths, *inputXml);
338
302
}
339
303
}
340
304
return hr;
341
305
}
342
306
343
307
HRESULT NotificationManagerToastWin::CreateToast (_In_ IToastNotificationManagerStatics *toastManager, _In_ IXmlDocument *xml,
344
- const int render_process_id, const int notification_id)
345
- {
308
+ const int render_process_id, const int notification_id) {
346
309
ComPtr<IToastNotificationFactory> factory;
347
310
HRESULT hr = GetActivationFactory (StringReferenceWrapper (RuntimeClass_Windows_UI_Notifications_ToastNotification).Get (), &factory);
348
- if (SUCCEEDED (hr))
349
- {
311
+ if (SUCCEEDED (hr)) {
350
312
ComPtr<IToastNotification>& toast = notification_map_[notification_id];
351
313
hr = factory->CreateToastNotification (xml, &toast);
352
- if (SUCCEEDED (hr))
353
- {
314
+ if (SUCCEEDED (hr)) {
354
315
// Register the event handlers
355
316
EventRegistrationToken activatedToken, dismissedToken, failedToken;
356
317
ComPtr<ToastEventHandler> eventHandler = new ToastEventHandler (render_process_id, notification_id);
357
318
358
319
hr = toast->add_Activated (eventHandler.Get (), &activatedToken);
359
- if (SUCCEEDED (hr))
360
- {
320
+ if (SUCCEEDED (hr)) {
361
321
hr = toast->add_Dismissed (eventHandler.Get (), &dismissedToken);
362
- if (SUCCEEDED (hr))
363
- {
322
+ if (SUCCEEDED (hr)) {
364
323
hr = toast->add_Failed (eventHandler.Get (), &failedToken);
365
- if (SUCCEEDED (hr))
366
- {
324
+ if (SUCCEEDED (hr)) {
367
325
hr = notifier_->Show (toast.Get ());
368
326
}
369
327
}
@@ -390,8 +348,7 @@ bool NotificationManagerToastWin::IsSupported() {
390
348
391
349
NotificationManagerToastWin::NotificationManagerToastWin () {
392
350
HRESULT hr = GetActivationFactory (StringReferenceWrapper (RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get (), &toastStatics_);
393
- if (SUCCEEDED (hr))
394
- {
351
+ if (SUCCEEDED (hr)) {
395
352
base::string16 appID;
396
353
if (content::Shell::GetPackage ()->root ()->GetString (" app-id" , &appID) == false )
397
354
content::Shell::GetPackage ()->root ()->GetString (switches::kmName, &appID);
@@ -401,21 +358,18 @@ NotificationManagerToastWin::NotificationManagerToastWin() {
401
358
}
402
359
403
360
NotificationManagerToastWin::~NotificationManagerToastWin () {
404
-
405
361
}
406
362
407
363
bool NotificationManagerToastWin::AddDesktopNotification (const content::ShowDesktopNotificationHostMsgParams& params,
408
364
const int render_process_id, const int notification_id, const bool worker) {
409
365
410
- ComPtr<IXmlDocument> toastXml;
411
- HRESULT hr = CreateToastXml (toastStatics_.Get (), params, &toastXml);
366
+ ComPtr<IXmlDocument> toastXml;
367
+ HRESULT hr = CreateToastXml (toastStatics_.Get (), params, &toastXml);
368
+ if (SUCCEEDED (hr)) {
369
+ hr = CreateToast (toastStatics_.Get (), toastXml.Get (), render_process_id, notification_id);
412
370
if (SUCCEEDED (hr))
413
- {
414
- hr = CreateToast (toastStatics_.Get (), toastXml.Get (), render_process_id, notification_id);
415
- if (SUCCEEDED (hr))
416
- DesktopNotificationPostDisplay (render_process_id, notification_id);
417
- }
418
-
371
+ DesktopNotificationPostDisplay (render_process_id, notification_id);
372
+ }
419
373
420
374
return SUCCEEDED (hr);
421
375
}
0 commit comments