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;
4442using namespace Windows ::Foundation;
4543
4644namespace 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
213227HRESULT NotificationManagerToastWin::SetNodeValueString (_In_ HSTRING inputString, _In_ IXmlNode *node, _In_ IXmlDocument *xml)
214228{
@@ -326,37 +340,28 @@ HRESULT NotificationManagerToastWin::CreateToastXml(_In_ IToastNotificationManag
326340HRESULT 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 (), ¬ifier);
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
368373bool 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
383388NotificationManagerToastWin::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 (), ¬ifier_);
397+ }
384398}
385399
386400NotificationManagerToastWin::~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
415426bool 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
0 commit comments