LCOV - code coverage report
Current view: top level - toolkit/components/alerts - nsAlertsService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 118 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "mozilla/dom/ContentChild.h"
       7             : #include "mozilla/dom/PermissionMessageUtils.h"
       8             : #include "mozilla/Preferences.h"
       9             : #include "mozilla/Telemetry.h"
      10             : #include "nsXULAppAPI.h"
      11             : 
      12             : #include "nsAlertsService.h"
      13             : 
      14             : #include "nsXPCOM.h"
      15             : #include "nsIServiceManager.h"
      16             : #include "nsIDOMWindow.h"
      17             : #include "nsPromiseFlatString.h"
      18             : #include "nsToolkitCompsCID.h"
      19             : 
      20             : #ifdef MOZ_PLACES
      21             : #include "mozIAsyncFavicons.h"
      22             : #include "nsIFaviconService.h"
      23             : #endif // MOZ_PLACES
      24             : 
      25             : #ifdef XP_WIN
      26             : #include <shellapi.h>
      27             : #endif
      28             : 
      29             : using namespace mozilla;
      30             : 
      31             : using mozilla::dom::ContentChild;
      32             : 
      33             : namespace {
      34             : 
      35             : #ifdef MOZ_PLACES
      36             : 
      37             : class IconCallback final : public nsIFaviconDataCallback
      38             : {
      39             : public:
      40             :   NS_DECL_ISUPPORTS
      41             : 
      42           0 :   IconCallback(nsIAlertsService* aBackend,
      43             :                nsIAlertNotification* aAlert,
      44             :                nsIObserver* aAlertListener)
      45           0 :     : mBackend(aBackend)
      46             :     , mAlert(aAlert)
      47           0 :     , mAlertListener(aAlertListener)
      48           0 :   {}
      49             : 
      50             :   NS_IMETHOD
      51           0 :   OnComplete(nsIURI *aIconURI, uint32_t aIconSize, const uint8_t *aIconData,
      52             :              const nsACString &aMimeType, uint16_t aWidth) override
      53             :   {
      54           0 :     nsresult rv = NS_ERROR_FAILURE;
      55           0 :     if (aIconSize > 0) {
      56           0 :       nsCOMPtr<nsIAlertsIconData> alertsIconData(do_QueryInterface(mBackend));
      57           0 :       if (alertsIconData) {
      58           0 :         rv = alertsIconData->ShowAlertWithIconData(mAlert, mAlertListener,
      59           0 :                                                    aIconSize, aIconData);
      60             :       }
      61           0 :     } else if (aIconURI) {
      62           0 :       nsCOMPtr<nsIAlertsIconURI> alertsIconURI(do_QueryInterface(mBackend));
      63           0 :       if (alertsIconURI) {
      64           0 :         rv = alertsIconURI->ShowAlertWithIconURI(mAlert, mAlertListener,
      65           0 :                                                  aIconURI);
      66             :       }
      67             :     }
      68           0 :     if (NS_FAILED(rv)) {
      69           0 :       rv = mBackend->ShowAlert(mAlert, mAlertListener);
      70             :     }
      71           0 :     return rv;
      72             :   }
      73             : 
      74             : private:
      75           0 :   virtual ~IconCallback() {}
      76             : 
      77             :   nsCOMPtr<nsIAlertsService> mBackend;
      78             :   nsCOMPtr<nsIAlertNotification> mAlert;
      79             :   nsCOMPtr<nsIObserver> mAlertListener;
      80             : };
      81             : 
      82           0 : NS_IMPL_ISUPPORTS(IconCallback, nsIFaviconDataCallback)
      83             : 
      84             : #endif // MOZ_PLACES
      85             : 
      86             : nsresult
      87           0 : ShowWithIconBackend(nsIAlertsService* aBackend, nsIAlertNotification* aAlert,
      88             :                     nsIObserver* aAlertListener)
      89             : {
      90             : #ifdef MOZ_PLACES
      91           0 :   nsCOMPtr<nsIURI> uri;
      92           0 :   nsresult rv = aAlert->GetURI(getter_AddRefs(uri));
      93           0 :   if (NS_FAILED(rv) || !uri) {
      94           0 :     return NS_ERROR_FAILURE;
      95             :   }
      96             : 
      97             :   // Ensure the backend supports favicons.
      98           0 :   nsCOMPtr<nsIAlertsIconData> alertsIconData(do_QueryInterface(aBackend));
      99           0 :   nsCOMPtr<nsIAlertsIconURI> alertsIconURI;
     100           0 :   if (!alertsIconData) {
     101           0 :     alertsIconURI = do_QueryInterface(aBackend);
     102             :   }
     103           0 :   if (!alertsIconData && !alertsIconURI) {
     104           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     105             :   }
     106             : 
     107             :   nsCOMPtr<mozIAsyncFavicons> favicons(do_GetService(
     108           0 :     "@mozilla.org/browser/favicon-service;1"));
     109           0 :   NS_ENSURE_TRUE(favicons, NS_ERROR_FAILURE);
     110             : 
     111             :   nsCOMPtr<nsIFaviconDataCallback> callback =
     112           0 :     new IconCallback(aBackend, aAlert, aAlertListener);
     113           0 :   if (alertsIconData) {
     114           0 :     return favicons->GetFaviconDataForPage(uri, callback, 0);
     115             :   }
     116           0 :   return favicons->GetFaviconURLForPage(uri, callback, 0);
     117             : #else
     118             :   return NS_ERROR_NOT_IMPLEMENTED;
     119             : #endif // !MOZ_PLACES
     120             : }
     121             : 
     122             : nsresult
     123           0 : ShowWithBackend(nsIAlertsService* aBackend, nsIAlertNotification* aAlert,
     124             :                 nsIObserver* aAlertListener, const nsAString& aPersistentData)
     125             : {
     126           0 :   if (!aPersistentData.IsEmpty()) {
     127             :     return aBackend->ShowPersistentNotification(
     128           0 :         aPersistentData, aAlert, aAlertListener);
     129             :   }
     130             : 
     131           0 :   if (Preferences::GetBool("alerts.showFavicons")) {
     132           0 :     nsresult rv = ShowWithIconBackend(aBackend, aAlert, aAlertListener);
     133           0 :     if (NS_SUCCEEDED(rv)) {
     134           0 :       return rv;
     135             :     }
     136             :   }
     137             : 
     138             :   // If favicons are disabled, or the backend doesn't support them, show the
     139             :   // alert without one.
     140           0 :   return aBackend->ShowAlert(aAlert, aAlertListener);
     141             : }
     142             : 
     143             : } // anonymous namespace
     144             : 
     145           0 : NS_IMPL_ISUPPORTS(nsAlertsService, nsIAlertsService, nsIAlertsDoNotDisturb)
     146             : 
     147           0 : nsAlertsService::nsAlertsService() :
     148           0 :   mBackend(nullptr)
     149             : {
     150           0 :   mBackend = do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID);
     151           0 : }
     152             : 
     153           0 : nsAlertsService::~nsAlertsService()
     154           0 : {}
     155             : 
     156           0 : bool nsAlertsService::ShouldShowAlert()
     157             : {
     158           0 :   bool result = true;
     159             : 
     160             : #ifdef XP_WIN
     161             :   QUERY_USER_NOTIFICATION_STATE qstate;
     162             :   if (SUCCEEDED(SHQueryUserNotificationState(&qstate))) {
     163             :     if (qstate != QUNS_ACCEPTS_NOTIFICATIONS) {
     164             :        result = false;
     165             :     }
     166             :   }
     167             : #endif
     168             : 
     169           0 :   return result;
     170             : }
     171             : 
     172           0 : NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle,
     173             :                                                      const nsAString & aAlertText, bool aAlertTextClickable,
     174             :                                                      const nsAString & aAlertCookie,
     175             :                                                      nsIObserver * aAlertListener,
     176             :                                                      const nsAString & aAlertName,
     177             :                                                      const nsAString & aBidi,
     178             :                                                      const nsAString & aLang,
     179             :                                                      const nsAString & aData,
     180             :                                                      nsIPrincipal * aPrincipal,
     181             :                                                      bool aInPrivateBrowsing,
     182             :                                                      bool aRequireInteraction)
     183             : {
     184             :   nsCOMPtr<nsIAlertNotification> alert =
     185           0 :     do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
     186           0 :   NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
     187           0 :   nsresult rv = alert->Init(aAlertName, aImageUrl, aAlertTitle,
     188             :                             aAlertText, aAlertTextClickable,
     189             :                             aAlertCookie, aBidi, aLang, aData,
     190             :                             aPrincipal, aInPrivateBrowsing,
     191           0 :                             aRequireInteraction);
     192           0 :   NS_ENSURE_SUCCESS(rv, rv);
     193           0 :   return ShowAlert(alert, aAlertListener);
     194             : }
     195             : 
     196             : 
     197           0 : NS_IMETHODIMP nsAlertsService::ShowAlert(nsIAlertNotification * aAlert,
     198             :                                          nsIObserver * aAlertListener)
     199             : {
     200           0 :   return ShowPersistentNotification(EmptyString(), aAlert, aAlertListener);
     201             : }
     202             : 
     203           0 : NS_IMETHODIMP nsAlertsService::ShowPersistentNotification(const nsAString & aPersistentData,
     204             :                                                           nsIAlertNotification * aAlert,
     205             :                                                           nsIObserver * aAlertListener)
     206             : {
     207           0 :   NS_ENSURE_ARG(aAlert);
     208             : 
     209           0 :   nsAutoString cookie;
     210           0 :   nsresult rv = aAlert->GetCookie(cookie);
     211           0 :   NS_ENSURE_SUCCESS(rv, rv);
     212             : 
     213           0 :   if (XRE_IsContentProcess()) {
     214           0 :     ContentChild* cpc = ContentChild::GetSingleton();
     215             : 
     216           0 :     if (aAlertListener)
     217           0 :       cpc->AddRemoteAlertObserver(cookie, aAlertListener);
     218             : 
     219           0 :     cpc->SendShowAlert(aAlert);
     220           0 :     return NS_OK;
     221             :   }
     222             : 
     223             :   // Check if there is an optional service that handles system-level notifications
     224           0 :   if (mBackend) {
     225           0 :     rv = ShowWithBackend(mBackend, aAlert, aAlertListener, aPersistentData);
     226           0 :     if (NS_SUCCEEDED(rv)) {
     227           0 :       return rv;
     228             :     }
     229             :     // If the system backend failed to show the alert, clear the backend and
     230             :     // retry with XUL notifications. Future alerts will always use XUL.
     231           0 :     mBackend = nullptr;
     232             :   }
     233             : 
     234           0 :   if (!ShouldShowAlert()) {
     235             :     // Do not display the alert. Instead call alertfinished and get out.
     236           0 :     if (aAlertListener)
     237           0 :       aAlertListener->Observe(nullptr, "alertfinished", cookie.get());
     238           0 :     return NS_OK;
     239             :   }
     240             : 
     241             :   // Use XUL notifications as a fallback if above methods have failed.
     242           0 :   nsCOMPtr<nsIAlertsService> xulBackend(nsXULAlerts::GetInstance());
     243           0 :   NS_ENSURE_TRUE(xulBackend, NS_ERROR_FAILURE);
     244           0 :   return ShowWithBackend(xulBackend, aAlert, aAlertListener, aPersistentData);
     245             : }
     246             : 
     247           0 : NS_IMETHODIMP nsAlertsService::CloseAlert(const nsAString& aAlertName,
     248             :                                           nsIPrincipal* aPrincipal)
     249             : {
     250           0 :   if (XRE_IsContentProcess()) {
     251           0 :     ContentChild* cpc = ContentChild::GetSingleton();
     252           0 :     cpc->SendCloseAlert(nsAutoString(aAlertName), IPC::Principal(aPrincipal));
     253           0 :     return NS_OK;
     254             :   }
     255             : 
     256             :   nsresult rv;
     257             :   // Try the system notification service.
     258           0 :   if (mBackend) {
     259           0 :     rv = mBackend->CloseAlert(aAlertName, aPrincipal);
     260           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     261             :       // If the system backend failed to close the alert, fall back to XUL for
     262             :       // future alerts.
     263           0 :       mBackend = nullptr;
     264             :     }
     265             :   } else {
     266           0 :     nsCOMPtr<nsIAlertsService> xulBackend(nsXULAlerts::GetInstance());
     267           0 :     NS_ENSURE_TRUE(xulBackend, NS_ERROR_FAILURE);
     268           0 :     rv = xulBackend->CloseAlert(aAlertName, aPrincipal);
     269             :   }
     270           0 :   return rv;
     271             : }
     272             : 
     273             : 
     274             : // nsIAlertsDoNotDisturb
     275           0 : NS_IMETHODIMP nsAlertsService::GetManualDoNotDisturb(bool* aRetVal)
     276             : {
     277             : #ifdef MOZ_WIDGET_ANDROID
     278             :   return NS_ERROR_NOT_IMPLEMENTED;
     279             : #else
     280           0 :   nsCOMPtr<nsIAlertsDoNotDisturb> alertsDND(GetDNDBackend());
     281           0 :   NS_ENSURE_TRUE(alertsDND, NS_ERROR_NOT_IMPLEMENTED);
     282           0 :   return alertsDND->GetManualDoNotDisturb(aRetVal);
     283             : #endif
     284             : }
     285             : 
     286           0 : NS_IMETHODIMP nsAlertsService::SetManualDoNotDisturb(bool aDoNotDisturb)
     287             : {
     288             : #ifdef MOZ_WIDGET_ANDROID
     289             :   return NS_ERROR_NOT_IMPLEMENTED;
     290             : #else
     291           0 :   nsCOMPtr<nsIAlertsDoNotDisturb> alertsDND(GetDNDBackend());
     292           0 :   NS_ENSURE_TRUE(alertsDND, NS_ERROR_NOT_IMPLEMENTED);
     293             : 
     294           0 :   nsresult rv = alertsDND->SetManualDoNotDisturb(aDoNotDisturb);
     295           0 :   if (NS_SUCCEEDED(rv)) {
     296           0 :     Telemetry::Accumulate(Telemetry::ALERTS_SERVICE_DND_ENABLED, 1);
     297             :   }
     298           0 :   return rv;
     299             : #endif
     300             : }
     301             : 
     302             : already_AddRefed<nsIAlertsDoNotDisturb>
     303           0 : nsAlertsService::GetDNDBackend()
     304             : {
     305             :   // Try the system notification service.
     306           0 :   nsCOMPtr<nsIAlertsService> backend = mBackend;
     307           0 :   if (!backend) {
     308           0 :     backend = nsXULAlerts::GetInstance();
     309             :   }
     310             : 
     311           0 :   nsCOMPtr<nsIAlertsDoNotDisturb> alertsDND(do_QueryInterface(backend));
     312           0 :   return alertsDND.forget();
     313             : }

Generated by: LCOV version 1.13