Skip to content

Commit c9804c4

Browse files
committed
[Notification][WIN] fix toast notification with picture, fix indentation / formatting
1 parent 7cb2453 commit c9804c4

File tree

4 files changed

+79
-125
lines changed

4 files changed

+79
-125
lines changed

src/nw_notification_manager_toast_win.cc

Lines changed: 76 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1919

2020

21+
#include "config.h"
2122
#include "content/public/browser/web_contents.h"
2223
#include "content/public/browser/render_frame_host.h"
2324
#include "content/public/browser/render_view_host.h"
@@ -29,6 +30,7 @@
2930
#include "base/strings/utf_string_conversions.h"
3031
#include "content/nw/src/common/shell_switches.h"
3132
#include "content/nw/src/nw_notification_manager_toast_win.h"
33+
#include "platform/image-encoders/skia/PNGImageEncoder.h"
3234

3335
#include <Psapi.h>
3436
#include <ShObjIdl.h>
@@ -43,70 +45,54 @@ using namespace Windows::Foundation;
4345

4446
namespace nw {
4547

46-
class StringReferenceWrapper
47-
{
48+
class StringReferenceWrapper {
4849
public:
49-
5050
// Constructor which takes an existing string buffer and its length as the parameters.
5151
// It fills an HSTRING_HEADER struct with the parameter.
5252
// Warning: The caller must ensure the lifetime of the buffer outlives this
5353
// object as it does not make a copy of the wide string memory.
5454

55-
static bool isSupported()
56-
{
55+
static bool isSupported() {
5756
static char cachedRes = -1;
5857
if (cachedRes > -1) return cachedRes;
5958
cachedRes = ::LoadLibrary(L"API-MS-WIN-CORE-WINRT-STRING-L1-1-0.DLL") != 0;
6059
return cachedRes;
6160
}
6261

63-
StringReferenceWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw()
64-
{
62+
StringReferenceWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() {
6563
HRESULT hr = WindowsCreateStringReference(stringRef, length, &_header, &_hstring);
66-
67-
if (FAILED(hr))
68-
{
64+
if (FAILED(hr)) {
6965
RaiseException(static_cast<DWORD>(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr);
7066
}
7167
}
7268

73-
~StringReferenceWrapper()
74-
{
69+
~StringReferenceWrapper() {
7570
WindowsDeleteString(_hstring);
7671
}
7772

7873
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() {
8175
UINT32 length = N - 1;
8276
HRESULT hr = WindowsCreateStringReference(stringRef, length, &_header, &_hstring);
83-
84-
if (FAILED(hr))
85-
{
77+
if (FAILED(hr)) {
8678
RaiseException(static_cast<DWORD>(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr);
8779
}
8880
}
8981

9082
template <size_t _>
91-
StringReferenceWrapper(_In_reads_(_) wchar_t(&stringRef)[_]) throw()
92-
{
83+
StringReferenceWrapper(_In_reads_(_) wchar_t(&stringRef)[_]) throw() {
9384
UINT32 length;
9485
HRESULT hr = SizeTToUInt32(wcslen(stringRef), &length);
95-
96-
if (FAILED(hr))
97-
{
86+
if (FAILED(hr)) {
9887
RaiseException(static_cast<DWORD>(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr);
9988
}
100-
10189
WindowsCreateStringReference(stringRef, length, &_header, &_hstring);
10290
}
10391

104-
HSTRING Get() const throw()
105-
{
92+
HSTRING Get() const throw() {
10693
return _hstring;
10794
}
10895

109-
11096
private:
11197
HSTRING _hstring;
11298
HSTRING_HEADER _header;
@@ -117,8 +103,7 @@ typedef ABI::Windows::Foundation::ITypedEventHandler<ABI::Windows::UI::Notificat
117103
typedef ABI::Windows::Foundation::ITypedEventHandler<ABI::Windows::UI::Notifications::ToastNotification *, ABI::Windows::UI::Notifications::ToastFailedEventArgs *> DesktopToastFailedEventHandler;
118104

119105
class ToastEventHandler :
120-
public Microsoft::WRL::Implements<DesktopToastActivatedEventHandler, DesktopToastDismissedEventHandler, DesktopToastFailedEventHandler>
121-
{
106+
public Microsoft::WRL::Implements<DesktopToastActivatedEventHandler, DesktopToastDismissedEventHandler, DesktopToastFailedEventHandler> {
122107
public:
123108
ToastEventHandler::ToastEventHandler(const int render_process_id, const int notification_id);
124109
~ToastEventHandler();
@@ -169,30 +154,23 @@ class ToastEventHandler :
169154
// ============= ToastEventHandler Implementation =============
170155

171156
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) {
175158
}
176159

177-
ToastEventHandler::~ToastEventHandler()
178-
{
179-
160+
ToastEventHandler::~ToastEventHandler() {
180161
}
181162

182163
// DesktopToastActivatedEventHandler
183-
IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IInspectable* /* args */)
184-
{
164+
IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IInspectable* /* args */) {
185165
BOOL succeeded = nw::NotificationManager::getSingleton()->DesktopNotificationPostClick(_render_process_id, _notification_id);
186166
return succeeded ? S_OK : E_FAIL;
187167
}
188168

189169
// DesktopToastDismissedEventHandler
190-
IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IToastDismissedEventArgs* e)
191-
{
170+
IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IToastDismissedEventArgs* e) {
192171
ToastDismissalReason tdr;
193172
HRESULT hr = e->get_Reason(&tdr);
194-
if (SUCCEEDED(hr))
195-
{
173+
if (SUCCEEDED(hr)) {
196174
BOOL succeeded = nw::NotificationManager::getSingleton()->DesktopNotificationPostClose(_render_process_id, _notification_id, tdr == ToastDismissalReason_UserCanceled);
197175
hr = succeeded ? S_OK : E_FAIL;
198176
}
@@ -201,8 +179,7 @@ IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */,
201179
}
202180

203181
// DesktopToastFailedEventHandler
204-
IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IToastFailedEventArgs* e)
205-
{
182+
IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IToastFailedEventArgs* e) {
206183
HRESULT errCode;
207184
e->get_ErrorCode(&errCode);
208185
nw::NotificationManagerToastWin* nmtw = static_cast<nw::NotificationManagerToastWin*>(nw::NotificationManager::getSingleton());
@@ -224,18 +201,14 @@ IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */,
224201
// ============= NotificationManagerToastWin Implementation =============
225202
bool NotificationManagerToastWin::ForceDisable = false;
226203

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) {
229205
ComPtr<IXmlText> inputText;
230206

231207
HRESULT hr = xml->CreateTextNode(inputString, &inputText);
232-
if (SUCCEEDED(hr))
233-
{
208+
if (SUCCEEDED(hr)) {
234209
ComPtr<IXmlNode> inputTextNode;
235-
236210
hr = inputText.As(&inputTextNode);
237-
if (SUCCEEDED(hr))
238-
{
211+
if (SUCCEEDED(hr)) {
239212
ComPtr<IXmlNode> pAppendedChild;
240213
hr = node->AppendChild(inputTextNode.Get(), &pAppendedChild);
241214
}
@@ -245,28 +218,21 @@ HRESULT NotificationManagerToastWin::SetNodeValueString(_In_ HSTRING inputString
245218
}
246219

247220
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) {
250222
HRESULT hr = textValues != nullptr && textValuesCount > 0 ? S_OK : E_INVALIDARG;
251-
if (SUCCEEDED(hr))
252-
{
223+
if (SUCCEEDED(hr)) {
253224
ComPtr<IXmlNodeList> nodeList;
254225
hr = toastXml->GetElementsByTagName(StringReferenceWrapper(L"text").Get(), &nodeList);
255-
if (SUCCEEDED(hr))
256-
{
226+
if (SUCCEEDED(hr)) {
257227
UINT32 nodeListLength;
258228
hr = nodeList->get_Length(&nodeListLength);
259-
if (SUCCEEDED(hr))
260-
{
229+
if (SUCCEEDED(hr)) {
261230
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++) {
266233
ComPtr<IXmlNode> textNode;
267234
hr = nodeList->Item(i, &textNode);
268-
if (SUCCEEDED(hr))
269-
{
235+
if (SUCCEEDED(hr)) {
270236
hr = SetNodeValueString(StringReferenceWrapper(textValues[i], textValuesLengths[i]).Get(), textNode.Get(), toastXml);
271237
}
272238
}
@@ -277,30 +243,22 @@ HRESULT NotificationManagerToastWin::SetTextValues(_In_reads_(textValuesCount) c
277243
return hr;
278244
}
279245

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) {
282247
wchar_t imageSrc[MAX_PATH] = L"";
283248
HRESULT hr = StringCchCat(imageSrc, ARRAYSIZE(imageSrc), imagePath);
284-
if (SUCCEEDED(hr))
285-
{
249+
if (SUCCEEDED(hr)) {
286250
ComPtr<IXmlNodeList> nodeList;
287251
hr = toastXml->GetElementsByTagName(StringReferenceWrapper(L"image").Get(), &nodeList);
288-
if (SUCCEEDED(hr))
289-
{
252+
if (SUCCEEDED(hr)) {
290253
ComPtr<IXmlNode> imageNode;
291254
hr = nodeList->Item(0, &imageNode);
292-
if (SUCCEEDED(hr))
293-
{
255+
if (SUCCEEDED(hr)) {
294256
ComPtr<IXmlNamedNodeMap> attributes;
295-
296257
hr = imageNode->get_Attributes(&attributes);
297-
if (SUCCEEDED(hr))
298-
{
258+
if (SUCCEEDED(hr)) {
299259
ComPtr<IXmlNode> srcAttribute;
300-
301260
hr = attributes->GetNamedItem(StringReferenceWrapper(L"src").Get(), &srcAttribute);
302-
if (SUCCEEDED(hr))
303-
{
261+
if (SUCCEEDED(hr)) {
304262
hr = SetNodeValueString(StringReferenceWrapper(imageSrc).Get(), srcAttribute.Get(), toastXml);
305263
}
306264
}
@@ -311,59 +269,59 @@ HRESULT NotificationManagerToastWin::SetImageSrc(_In_z_ const wchar_t *imagePath
311269
}
312270

313271
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+
317291
// Retrieve the template XML
318292
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);
338302
}
339303
}
340304
return hr;
341305
}
342306

343307
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) {
346309
ComPtr<IToastNotificationFactory> factory;
347310
HRESULT hr = GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &factory);
348-
if (SUCCEEDED(hr))
349-
{
311+
if (SUCCEEDED(hr)) {
350312
ComPtr<IToastNotification>& toast = notification_map_[notification_id];
351313
hr = factory->CreateToastNotification(xml, &toast);
352-
if (SUCCEEDED(hr))
353-
{
314+
if (SUCCEEDED(hr)) {
354315
// Register the event handlers
355316
EventRegistrationToken activatedToken, dismissedToken, failedToken;
356317
ComPtr<ToastEventHandler> eventHandler = new ToastEventHandler(render_process_id, notification_id);
357318

358319
hr = toast->add_Activated(eventHandler.Get(), &activatedToken);
359-
if (SUCCEEDED(hr))
360-
{
320+
if (SUCCEEDED(hr)) {
361321
hr = toast->add_Dismissed(eventHandler.Get(), &dismissedToken);
362-
if (SUCCEEDED(hr))
363-
{
322+
if (SUCCEEDED(hr)) {
364323
hr = toast->add_Failed(eventHandler.Get(), &failedToken);
365-
if (SUCCEEDED(hr))
366-
{
324+
if (SUCCEEDED(hr)) {
367325
hr = notifier_->Show(toast.Get());
368326
}
369327
}
@@ -390,8 +348,7 @@ bool NotificationManagerToastWin::IsSupported() {
390348

391349
NotificationManagerToastWin::NotificationManagerToastWin() {
392350
HRESULT hr = GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &toastStatics_);
393-
if (SUCCEEDED(hr))
394-
{
351+
if (SUCCEEDED(hr)) {
395352
base::string16 appID;
396353
if (content::Shell::GetPackage()->root()->GetString("app-id", &appID) == false)
397354
content::Shell::GetPackage()->root()->GetString(switches::kmName, &appID);
@@ -401,21 +358,18 @@ NotificationManagerToastWin::NotificationManagerToastWin() {
401358
}
402359

403360
NotificationManagerToastWin::~NotificationManagerToastWin() {
404-
405361
}
406362

407363
bool NotificationManagerToastWin::AddDesktopNotification(const content::ShowDesktopNotificationHostMsgParams& params,
408364
const int render_process_id, const int notification_id, const bool worker) {
409365

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);
412370
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+
}
419373

420374
return SUCCEEDED(hr);
421375
}

src/nw_notification_manager_toast_win.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace nw {
3030
using namespace ABI::Windows::UI::Notifications;
3131
using namespace ABI::Windows::Data::Xml::Dom;
3232

33-
class NotificationManagerToastWin : public NotificationManager{
33+
class NotificationManagerToastWin : public NotificationManager {
3434
friend class ToastEventHandler;
3535

3636
ComPtr<IToastNotificationManagerStatics> toastStatics_;

src/nw_notification_manager_win.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ bool NotificationManagerWin::AddDesktopNotification(const content::ShowDesktopNo
146146
// add the counter
147147
notification_count_++;
148148
// try to get the notification icon image given by image download callback
149-
if (params.icon.width())
149+
if (params.icon.getSize())
150150
icon = gfx::Image::CreateFrom1xBitmap(params.icon);
151151

152152
//if body is empty string, the baloon won't shown

0 commit comments

Comments
 (0)