michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/dom/ContentChild.h" michael@0: #include "mozilla/dom/PermissionMessageUtils.h" michael@0: #include "nsXULAppAPI.h" michael@0: michael@0: #include "nsAlertsService.h" michael@0: michael@0: #ifdef MOZ_WIDGET_ANDROID michael@0: #include "AndroidBridge.h" michael@0: using namespace mozilla::widget::android; michael@0: #else michael@0: michael@0: #include "nsXPCOM.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsIDOMWindow.h" michael@0: #include "nsPromiseFlatString.h" michael@0: #include "nsToolkitCompsCID.h" michael@0: michael@0: #endif // !MOZ_WIDGET_ANDROID michael@0: michael@0: using namespace mozilla; michael@0: michael@0: using mozilla::dom::ContentChild; michael@0: michael@0: NS_IMPL_ISUPPORTS(nsAlertsService, nsIAlertsService, nsIAlertsProgressListener) michael@0: michael@0: nsAlertsService::nsAlertsService() michael@0: { michael@0: } michael@0: michael@0: nsAlertsService::~nsAlertsService() michael@0: {} michael@0: michael@0: bool nsAlertsService::ShouldShowAlert() michael@0: { michael@0: bool result = true; michael@0: michael@0: #ifdef XP_WIN michael@0: HMODULE shellDLL = ::LoadLibraryW(L"shell32.dll"); michael@0: if (!shellDLL) michael@0: return result; michael@0: michael@0: SHQueryUserNotificationStatePtr pSHQueryUserNotificationState = michael@0: (SHQueryUserNotificationStatePtr) ::GetProcAddress(shellDLL, "SHQueryUserNotificationState"); michael@0: michael@0: if (pSHQueryUserNotificationState) { michael@0: MOZ_QUERY_USER_NOTIFICATION_STATE qstate; michael@0: if (SUCCEEDED(pSHQueryUserNotificationState(&qstate))) { michael@0: if (qstate != QUNS_ACCEPTS_NOTIFICATIONS) { michael@0: result = false; michael@0: } michael@0: } michael@0: } michael@0: michael@0: ::FreeLibrary(shellDLL); michael@0: #endif michael@0: michael@0: return result; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle, michael@0: const nsAString & aAlertText, bool aAlertTextClickable, michael@0: const nsAString & aAlertCookie, michael@0: nsIObserver * aAlertListener, michael@0: const nsAString & aAlertName, michael@0: const nsAString & aBidi, michael@0: const nsAString & aLang, michael@0: nsIPrincipal * aPrincipal) michael@0: { michael@0: if (XRE_GetProcessType() == GeckoProcessType_Content) { michael@0: ContentChild* cpc = ContentChild::GetSingleton(); michael@0: michael@0: if (aAlertListener) michael@0: cpc->AddRemoteAlertObserver(PromiseFlatString(aAlertCookie), aAlertListener); michael@0: michael@0: cpc->SendShowAlertNotification(PromiseFlatString(aImageUrl), michael@0: PromiseFlatString(aAlertTitle), michael@0: PromiseFlatString(aAlertText), michael@0: aAlertTextClickable, michael@0: PromiseFlatString(aAlertCookie), michael@0: PromiseFlatString(aAlertName), michael@0: PromiseFlatString(aBidi), michael@0: PromiseFlatString(aLang), michael@0: IPC::Principal(aPrincipal)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: #ifdef MOZ_WIDGET_ANDROID michael@0: mozilla::AndroidBridge::Bridge()->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, michael@0: aAlertListener, aAlertName); michael@0: return NS_OK; michael@0: #else michael@0: // Check if there is an optional service that handles system-level notifications michael@0: nsCOMPtr sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID)); michael@0: nsresult rv; michael@0: if (sysAlerts) { michael@0: return sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, michael@0: aAlertCookie, aAlertListener, aAlertName, michael@0: aBidi, aLang, IPC::Principal(aPrincipal)); michael@0: } michael@0: michael@0: if (!ShouldShowAlert()) { michael@0: // Do not display the alert. Instead call alertfinished and get out. michael@0: if (aAlertListener) michael@0: aAlertListener->Observe(nullptr, "alertfinished", PromiseFlatString(aAlertCookie).get()); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // Use XUL notifications as a fallback if above methods have failed. michael@0: rv = mXULAlerts.ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, michael@0: aAlertCookie, aAlertListener, aAlertName, michael@0: aBidi, aLang); michael@0: return rv; michael@0: #endif // !MOZ_WIDGET_ANDROID michael@0: } michael@0: michael@0: NS_IMETHODIMP nsAlertsService::CloseAlert(const nsAString& aAlertName, michael@0: nsIPrincipal* aPrincipal) michael@0: { michael@0: if (XRE_GetProcessType() == GeckoProcessType_Content) { michael@0: ContentChild* cpc = ContentChild::GetSingleton(); michael@0: cpc->SendCloseAlert(nsAutoString(aAlertName), IPC::Principal(aPrincipal)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: #ifdef MOZ_WIDGET_ANDROID michael@0: mozilla::widget::android::GeckoAppShell::CloseNotification(aAlertName); michael@0: return NS_OK; michael@0: #else michael@0: michael@0: // Try the system notification service. michael@0: nsCOMPtr sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID)); michael@0: if (sysAlerts) { michael@0: return sysAlerts->CloseAlert(aAlertName, nullptr); michael@0: } michael@0: michael@0: return mXULAlerts.CloseAlert(aAlertName); michael@0: #endif // !MOZ_WIDGET_ANDROID michael@0: } michael@0: michael@0: michael@0: NS_IMETHODIMP nsAlertsService::OnProgress(const nsAString & aAlertName, michael@0: int64_t aProgress, michael@0: int64_t aProgressMax, michael@0: const nsAString & aAlertText) michael@0: { michael@0: #ifdef MOZ_WIDGET_ANDROID michael@0: mozilla::widget::android::GeckoAppShell::AlertsProgressListener_OnProgress(aAlertName, michael@0: aProgress, aProgressMax, michael@0: aAlertText); michael@0: return NS_OK; michael@0: #else michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: #endif // !MOZ_WIDGET_ANDROID michael@0: } michael@0: michael@0: NS_IMETHODIMP nsAlertsService::OnCancel(const nsAString & aAlertName) michael@0: { michael@0: #ifdef MOZ_WIDGET_ANDROID michael@0: mozilla::widget::android::GeckoAppShell::CloseNotification(aAlertName); michael@0: return NS_OK; michael@0: #else michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: #endif // !MOZ_WIDGET_ANDROID michael@0: }