Skip to content

Commit 34bde97

Browse files
committed
Merge pull request nwjs#2639 from jtg-gg/notification-fixes
Notification fixes
2 parents 9134c47 + 60d2ecb commit 34bde97

File tree

4 files changed

+76
-35
lines changed

4 files changed

+76
-35
lines changed

src/api/app/app.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#if defined(OS_WIN)
2929
#include "base/strings/utf_string_conversions.h"
3030
#include "base/files/file_path.h"
31+
#include "base/files/file_util.h"
3132
#include "base/win/shortcut.h"
3233
#include "base/path_service.h"
3334
#include "content/nw/src/common/shell_switches.h"
@@ -162,7 +163,10 @@ void App::Call(Shell* shell,
162163
base::FilePath processPath;
163164
PathService::Get(base::FILE_EXE, &processPath);
164165
props.set_target(processPath);
165-
result->AppendBoolean(base::win::CreateOrUpdateShortcutLink(base::FilePath(path), props, base::win::SHORTCUT_CREATE_ALWAYS));
166+
167+
base::FilePath shortcutPath(path);
168+
result->AppendBoolean(base::win::CreateOrUpdateShortcutLink(shortcutPath, props,
169+
base::PathExists(shortcutPath) ? base::win::SHORTCUT_UPDATE_EXISTING : base::win::SHORTCUT_CREATE_ALWAYS));
166170
#else
167171
result->AppendBoolean(false);
168172
#endif

src/nw_notification_manager_toast_win.cc

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,8 @@
3737

3838
#include <intsafe.h>
3939
#include <strsafe.h>
40-
#include <wrl\client.h>
4140
#include <wrl\implements.h>
4241

43-
using namespace Microsoft::WRL;
4442
using namespace Windows::Foundation;
4543

4644
namespace nw {
@@ -198,17 +196,33 @@ IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */,
198196
BOOL succeeded = nw::NotificationManager::getSingleton()->DesktopNotificationPostClose(_render_process_id, _render_frame_id, _notification_id, tdr == ToastDismissalReason_UserCanceled);
199197
hr = succeeded ? S_OK : E_FAIL;
200198
}
199+
nw::NotificationManager::getSingleton()->CancelDesktopNotification(_render_process_id, _render_frame_id, _notification_id);
201200
return hr;
202201
}
203202

204203
// DesktopToastFailedEventHandler
205-
IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IToastFailedEventArgs* /* e */)
204+
IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IToastFailedEventArgs* e)
206205
{
207-
BOOL succeeded = nw::NotificationManager::getSingleton()->DesktopNotificationPostError(_render_process_id, _render_frame_id, _notification_id, L"The toast encountered an error.");
206+
HRESULT errCode;
207+
e->get_ErrorCode(&errCode);
208+
nw::NotificationManagerToastWin* nmtw = static_cast<nw::NotificationManagerToastWin*>(nw::NotificationManager::getSingleton());
209+
std::wstringstream errMsg; errMsg << L"The toast encountered an error code (0x" << std::hex << errCode <<").";
210+
const bool fallBack = errCode == 0x80070490;
211+
if (fallBack)
212+
errMsg << " Fallback to balloon notification!";
213+
214+
BOOL succeeded = nmtw->DesktopNotificationPostError(_render_process_id, _render_frame_id, _notification_id, errMsg.str().c_str());
215+
nmtw->notification_map_.erase(_notification_id);
216+
217+
if (fallBack) {
218+
NotificationManagerToastWin::ForceDisable = true;
219+
delete nmtw;
220+
}
208221
return succeeded ? S_OK : E_FAIL;
209222
}
210223

211224
// ============= NotificationManagerToastWin Implementation =============
225+
bool NotificationManagerToastWin::ForceDisable = false;
212226

213227
HRESULT NotificationManagerToastWin::SetNodeValueString(_In_ HSTRING inputString, _In_ IXmlNode *node, _In_ IXmlDocument *xml)
214228
{
@@ -326,37 +340,28 @@ HRESULT NotificationManagerToastWin::CreateToastXml(_In_ IToastNotificationManag
326340
HRESULT NotificationManagerToastWin::CreateToast(_In_ IToastNotificationManagerStatics *toastManager, _In_ IXmlDocument *xml,
327341
const int render_process_id, const int render_frame_id, const int notification_id)
328342
{
329-
base::string16 appID;
330-
if (content::Shell::GetPackage()->root()->GetString("app-id", &appID) == false)
331-
content::Shell::GetPackage()->root()->GetString(switches::kmName, &appID);
332-
333-
ComPtr<IToastNotifier> notifier;
334-
HRESULT hr = toastManager->CreateToastNotifierWithId(StringReferenceWrapper(appID.c_str(), appID.length()).Get(), &notifier);
343+
ComPtr<IToastNotificationFactory> factory;
344+
HRESULT hr = GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &factory);
335345
if (SUCCEEDED(hr))
336346
{
337-
ComPtr<IToastNotificationFactory> factory;
338-
hr = GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &factory);
347+
ComPtr<IToastNotification>& toast = notification_map_[notification_id];
348+
hr = factory->CreateToastNotification(xml, &toast);
339349
if (SUCCEEDED(hr))
340350
{
341-
ComPtr<IToastNotification> toast;
342-
hr = factory->CreateToastNotification(xml, &toast);
351+
// Register the event handlers
352+
EventRegistrationToken activatedToken, dismissedToken, failedToken;
353+
ComPtr<ToastEventHandler> eventHandler = new ToastEventHandler(render_process_id, render_frame_id, notification_id);
354+
355+
hr = toast->add_Activated(eventHandler.Get(), &activatedToken);
343356
if (SUCCEEDED(hr))
344357
{
345-
// Register the event handlers
346-
EventRegistrationToken activatedToken, dismissedToken, failedToken;
347-
ComPtr<ToastEventHandler> eventHandler = new ToastEventHandler(render_process_id, render_frame_id, notification_id);
348-
349-
hr = toast->add_Activated(eventHandler.Get(), &activatedToken);
358+
hr = toast->add_Dismissed(eventHandler.Get(), &dismissedToken);
350359
if (SUCCEEDED(hr))
351360
{
352-
hr = toast->add_Dismissed(eventHandler.Get(), &dismissedToken);
361+
hr = toast->add_Failed(eventHandler.Get(), &failedToken);
353362
if (SUCCEEDED(hr))
354363
{
355-
hr = toast->add_Failed(eventHandler.Get(), &failedToken);
356-
if (SUCCEEDED(hr))
357-
{
358-
hr = notifier->Show(toast.Get());
359-
}
364+
hr = notifier_->Show(toast.Get());
360365
}
361366
}
362367
}
@@ -367,7 +372,7 @@ HRESULT NotificationManagerToastWin::CreateToast(_In_ IToastNotificationManagerS
367372

368373
bool NotificationManagerToastWin::IsSupported() {
369374
static char cachedRes = -1;
370-
375+
if (ForceDisable) return false;
371376
if (cachedRes > -1) return cachedRes;
372377
cachedRes = 0;
373378

@@ -381,6 +386,15 @@ bool NotificationManagerToastWin::IsSupported() {
381386
}
382387

383388
NotificationManagerToastWin::NotificationManagerToastWin() {
389+
HRESULT hr = GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &toastStatics_);
390+
if (SUCCEEDED(hr))
391+
{
392+
base::string16 appID;
393+
if (content::Shell::GetPackage()->root()->GetString("app-id", &appID) == false)
394+
content::Shell::GetPackage()->root()->GetString(switches::kmName, &appID);
395+
396+
HRESULT hr = toastStatics_->CreateToastNotifierWithId(StringReferenceWrapper(appID.c_str(), appID.length()).Get(), &notifier_);
397+
}
384398
}
385399

386400
NotificationManagerToastWin::~NotificationManagerToastWin() {
@@ -395,24 +409,28 @@ bool NotificationManagerToastWin::AddDesktopNotification(const content::ShowDesk
395409
if (host == NULL)
396410
return false;
397411

398-
ComPtr<IToastNotificationManagerStatics> toastStatics;
399-
HRESULT hr = GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &toastStatics);
400-
if (SUCCEEDED(hr))
401-
{
412+
402413
ComPtr<IXmlDocument> toastXml;
403-
hr = CreateToastXml(toastStatics.Get(), params, &toastXml);
414+
HRESULT hr = CreateToastXml(toastStatics_.Get(), params, &toastXml);
404415
if (SUCCEEDED(hr))
405416
{
406-
hr = CreateToast(toastStatics.Get(), toastXml.Get(), render_process_id, render_frame_id, notification_id);
417+
hr = CreateToast(toastStatics_.Get(), toastXml.Get(), render_process_id, render_frame_id, notification_id);
407418
if (SUCCEEDED(hr))
408419
DesktopNotificationPostDisplay(render_process_id, render_frame_id, notification_id);
409420
}
410-
}
421+
411422

412423
return SUCCEEDED(hr);
413424
}
414425

415426
bool NotificationManagerToastWin::CancelDesktopNotification(int render_process_id, int render_frame_id, int notification_id) {
416-
return true;
427+
std::map<int, ComPtr<IToastNotification>>::iterator i = notification_map_.find(notification_id);
428+
if (i == notification_map_.end())
429+
return false;
430+
431+
ComPtr<IToastNotification> toast = i->second;
432+
notification_map_.erase(i);
433+
434+
return SUCCEEDED(notifier_->Hide(toast.Get()));
417435
}
418436
} // namespace nw

src/nw_notification_manager_toast_win.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,21 @@
2222

2323
#include "content/nw/src/nw_notification_manager.h"
2424
#include <windows.ui.notifications.h>
25+
#include <wrl\client.h>
26+
2527

2628
namespace nw {
29+
using namespace Microsoft::WRL;
2730
using namespace ABI::Windows::UI::Notifications;
2831
using namespace ABI::Windows::Data::Xml::Dom;
2932

3033
class NotificationManagerToastWin : public NotificationManager{
34+
friend class ToastEventHandler;
35+
36+
ComPtr<IToastNotificationManagerStatics> toastStatics_;
37+
ComPtr<IToastNotifier> notifier_;
38+
std::map<int, ComPtr<IToastNotification>> notification_map_;
39+
static bool ForceDisable;
3140

3241
// internal function for AddDesktopNotification
3342
virtual bool AddDesktopNotification(const content::ShowDesktopNotificationHostMsgParams& params,

src/shell_content_browser_client.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,15 @@ ShellContentBrowserClient::CreateQuotaPermissionContext() {
495495
return new ShellQuotaPermissionContext();
496496
}
497497

498+
void CancelDesktopNotification(int render_process_id, int render_frame_id, int notification_id) {
499+
nw::NotificationManager *notificationManager = nw::NotificationManager::getSingleton();
500+
if (notificationManager == NULL) {
501+
NOTIMPLEMENTED();
502+
return;
503+
}
504+
notificationManager->CancelDesktopNotification(render_process_id, render_frame_id, notification_id);
505+
}
506+
498507
void ShellContentBrowserClient::ShowDesktopNotification(
499508
const ShowDesktopNotificationHostMsgParams& params,
500509
RenderFrameHost* render_frame_host,
@@ -511,6 +520,7 @@ void ShellContentBrowserClient::ShowDesktopNotification(
511520
render_frame_host->GetRoutingID(),
512521
delegate->notification_id(),
513522
false);
523+
*cancel_callback = base::Bind(&CancelDesktopNotification, process->GetID(), render_frame_host->GetRoutingID(), delegate->notification_id());
514524
#else
515525
NOTIMPLEMENTED();
516526
#endif

0 commit comments

Comments
 (0)