LCOV - code coverage report
Current view: top level - dom/notification - DesktopNotification.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 127 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : #include "mozilla/dom/DesktopNotification.h"
       7             : #include "mozilla/dom/DesktopNotificationBinding.h"
       8             : #include "mozilla/dom/AppNotificationServiceOptionsBinding.h"
       9             : #include "mozilla/dom/ToJSValue.h"
      10             : #include "nsComponentManagerUtils.h"
      11             : #include "nsContentPermissionHelper.h"
      12             : #include "nsXULAppAPI.h"
      13             : #include "mozilla/dom/PBrowserChild.h"
      14             : #include "mozilla/Preferences.h"
      15             : #include "nsGlobalWindow.h"
      16             : #include "nsIScriptSecurityManager.h"
      17             : #include "nsServiceManagerUtils.h"
      18             : #include "PermissionMessageUtils.h"
      19             : #include "nsILoadContext.h"
      20             : 
      21             : namespace mozilla {
      22             : namespace dom {
      23             : 
      24             : /*
      25             :  * Simple Request
      26             :  */
      27             : class DesktopNotificationRequest : public nsIContentPermissionRequest
      28             :                                  , public Runnable
      29             : {
      30           0 :   virtual ~DesktopNotificationRequest()
      31           0 :   {
      32           0 :   }
      33             : 
      34             :   nsCOMPtr<nsIContentPermissionRequester> mRequester;
      35             : public:
      36             :   NS_DECL_ISUPPORTS_INHERITED
      37             :   NS_DECL_NSICONTENTPERMISSIONREQUEST
      38             : 
      39           0 :   explicit DesktopNotificationRequest(DesktopNotification* aNotification)
      40           0 :     : Runnable("dom::DesktopNotificationRequest")
      41           0 :     , mDesktopNotification(aNotification)
      42             :   {
      43           0 :     mRequester = new nsContentPermissionRequester(mDesktopNotification->GetOwner());
      44           0 :   }
      45             : 
      46           0 :   NS_IMETHOD Run() override
      47             :   {
      48           0 :     nsCOMPtr<nsPIDOMWindowInner> window = mDesktopNotification->GetOwner();
      49           0 :     nsContentPermissionUtils::AskPermission(this, window);
      50           0 :     return NS_OK;
      51             :   }
      52             : 
      53             :   RefPtr<DesktopNotification> mDesktopNotification;
      54             : };
      55             : 
      56             : /* ------------------------------------------------------------------------ */
      57             : /* AlertServiceObserver                                                     */
      58             : /* ------------------------------------------------------------------------ */
      59             : 
      60           0 : NS_IMPL_ISUPPORTS(AlertServiceObserver, nsIObserver)
      61             : 
      62             : /* ------------------------------------------------------------------------ */
      63             : /* DesktopNotification                                                      */
      64             : /* ------------------------------------------------------------------------ */
      65             : 
      66             : uint32_t DesktopNotification::sCount = 0;
      67             : 
      68             : nsresult
      69           0 : DesktopNotification::PostDesktopNotification()
      70             : {
      71           0 :   if (!mObserver) {
      72           0 :     mObserver = new AlertServiceObserver(this);
      73             :   }
      74             : 
      75           0 :   nsCOMPtr<nsIAlertsService> alerts = do_GetService("@mozilla.org/alerts-service;1");
      76           0 :   if (!alerts) {
      77           0 :     return NS_ERROR_NOT_IMPLEMENTED;
      78             :   }
      79             : 
      80             :   // Generate a unique name (which will also be used as a cookie) because
      81             :   // the nsIAlertsService will coalesce notifications with the same name.
      82             :   // In the case of IPC, the parent process will use the cookie to map
      83             :   // to nsIObservers, thus cookies must be unique to differentiate observers.
      84           0 :   nsString uniqueName = NS_LITERAL_STRING("desktop-notification:");
      85           0 :   uniqueName.AppendInt(sCount++);
      86           0 :   nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
      87           0 :   if (!owner) {
      88           0 :     return NS_ERROR_FAILURE;
      89             :   }
      90           0 :   nsCOMPtr<nsIDocument> doc = owner->GetDoc();
      91           0 :   nsIPrincipal* principal = doc->NodePrincipal();
      92           0 :   nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
      93           0 :   bool inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
      94             :   nsCOMPtr<nsIAlertNotification> alert =
      95           0 :     do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
      96           0 :   NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
      97           0 :   nsresult rv = alert->Init(uniqueName, mIconURL, mTitle,
      98             :                             mDescription,
      99             :                             true,
     100             :                             uniqueName,
     101           0 :                             NS_LITERAL_STRING("auto"),
     102           0 :                             EmptyString(),
     103           0 :                             EmptyString(),
     104             :                             principal,
     105             :                             inPrivateBrowsing,
     106           0 :                             false /* requireInteraction */);
     107           0 :   NS_ENSURE_SUCCESS(rv, rv);
     108           0 :   return alerts->ShowAlert(alert, mObserver);
     109             : }
     110             : 
     111           0 : DesktopNotification::DesktopNotification(const nsAString & title,
     112             :                                          const nsAString & description,
     113             :                                          const nsAString & iconURL,
     114             :                                          nsPIDOMWindowInner* aWindow,
     115           0 :                                          nsIPrincipal* principal)
     116             :   : DOMEventTargetHelper(aWindow)
     117             :   , mTitle(title)
     118             :   , mDescription(description)
     119             :   , mIconURL(iconURL)
     120             :   , mPrincipal(principal)
     121             :   , mAllow(false)
     122           0 :   , mShowHasBeenCalled(false)
     123             : {
     124           0 :   if (Preferences::GetBool("notification.disabled", false)) {
     125           0 :     return;
     126             :   }
     127             : 
     128             :   // If we are in testing mode (running mochitests, for example)
     129             :   // and we are suppose to allow requests, then just post an allow event.
     130           0 :   if (Preferences::GetBool("notification.prompt.testing", false) &&
     131           0 :       Preferences::GetBool("notification.prompt.testing.allow", true)) {
     132           0 :     mAllow = true;
     133             :   }
     134             : }
     135             : 
     136             : void
     137           0 : DesktopNotification::Init()
     138             : {
     139           0 :   RefPtr<DesktopNotificationRequest> request = new DesktopNotificationRequest(this);
     140             : 
     141           0 :   NS_DispatchToMainThread(request);
     142           0 : }
     143             : 
     144           0 : DesktopNotification::~DesktopNotification()
     145             : {
     146           0 :   if (mObserver) {
     147           0 :     mObserver->Disconnect();
     148             :   }
     149           0 : }
     150             : 
     151             : void
     152           0 : DesktopNotification::DispatchNotificationEvent(const nsString& aName)
     153             : {
     154           0 :   if (NS_FAILED(CheckInnerWindowCorrectness())) {
     155           0 :     return;
     156             :   }
     157             : 
     158           0 :   RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
     159             :   // it doesn't bubble, and it isn't cancelable
     160           0 :   event->InitEvent(aName, false, false);
     161           0 :   event->SetTrusted(true);
     162           0 :   DispatchDOMEvent(nullptr, event, nullptr, nullptr);
     163             : }
     164             : 
     165             : nsresult
     166           0 : DesktopNotification::SetAllow(bool aAllow)
     167             : {
     168           0 :   mAllow = aAllow;
     169             : 
     170             :   // if we have called Show() already, lets go ahead and post a notification
     171           0 :   if (mShowHasBeenCalled && aAllow) {
     172           0 :     return PostDesktopNotification();
     173             :   }
     174             : 
     175           0 :   return NS_OK;
     176             : }
     177             : 
     178             : void
     179           0 : DesktopNotification::HandleAlertServiceNotification(const char *aTopic)
     180             : {
     181           0 :   if (NS_FAILED(CheckInnerWindowCorrectness())) {
     182           0 :     return;
     183             :   }
     184             : 
     185           0 :   if (!strcmp("alertclickcallback", aTopic)) {
     186           0 :     DispatchNotificationEvent(NS_LITERAL_STRING("click"));
     187           0 :   } else if (!strcmp("alertfinished", aTopic)) {
     188           0 :     DispatchNotificationEvent(NS_LITERAL_STRING("close"));
     189             :   }
     190             : }
     191             : 
     192             : void
     193           0 : DesktopNotification::Show(ErrorResult& aRv)
     194             : {
     195           0 :   mShowHasBeenCalled = true;
     196             : 
     197           0 :   if (!mAllow) {
     198           0 :     return;
     199             :   }
     200             : 
     201           0 :   aRv = PostDesktopNotification();
     202             : }
     203             : 
     204             : JSObject*
     205           0 : DesktopNotification::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     206             : {
     207           0 :   return DesktopNotificationBinding::Wrap(aCx, this, aGivenProto);
     208             : }
     209             : 
     210             : /* ------------------------------------------------------------------------ */
     211             : /* DesktopNotificationCenter                                                */
     212             : /* ------------------------------------------------------------------------ */
     213             : 
     214           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(DesktopNotificationCenter)
     215           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DesktopNotificationCenter)
     216           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DesktopNotificationCenter)
     217           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DesktopNotificationCenter)
     218           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     219           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     220           0 : NS_INTERFACE_MAP_END
     221             : 
     222             : already_AddRefed<DesktopNotification>
     223           0 : DesktopNotificationCenter::CreateNotification(const nsAString& aTitle,
     224             :                                               const nsAString& aDescription,
     225             :                                               const nsAString& aIconURL)
     226             : {
     227           0 :   MOZ_ASSERT(mOwner);
     228             : 
     229             :   RefPtr<DesktopNotification> notification =
     230             :     new DesktopNotification(aTitle,
     231             :                             aDescription,
     232             :                             aIconURL,
     233             :                             mOwner,
     234           0 :                             mPrincipal);
     235           0 :   notification->Init();
     236           0 :   return notification.forget();
     237             : }
     238             : 
     239             : JSObject*
     240           0 : DesktopNotificationCenter::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     241             : {
     242           0 :   return DesktopNotificationCenterBinding::Wrap(aCx, this, aGivenProto);
     243             : }
     244             : 
     245             : /* ------------------------------------------------------------------------ */
     246             : /* DesktopNotificationRequest                                               */
     247             : /* ------------------------------------------------------------------------ */
     248             : 
     249           0 : NS_IMPL_ISUPPORTS_INHERITED(DesktopNotificationRequest, Runnable,
     250             :                             nsIContentPermissionRequest)
     251             : 
     252             : NS_IMETHODIMP
     253           0 : DesktopNotificationRequest::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
     254             : {
     255           0 :   if (!mDesktopNotification) {
     256           0 :     return NS_ERROR_NOT_INITIALIZED;
     257             :   }
     258             : 
     259           0 :   NS_IF_ADDREF(*aRequestingPrincipal = mDesktopNotification->mPrincipal);
     260           0 :   return NS_OK;
     261             : }
     262             : 
     263             : NS_IMETHODIMP
     264           0 : DesktopNotificationRequest::GetWindow(mozIDOMWindow** aRequestingWindow)
     265             : {
     266           0 :   if (!mDesktopNotification) {
     267           0 :     return NS_ERROR_NOT_INITIALIZED;
     268             :   }
     269             : 
     270           0 :   NS_IF_ADDREF(*aRequestingWindow = mDesktopNotification->GetOwner());
     271           0 :   return NS_OK;
     272             : }
     273             : 
     274             : NS_IMETHODIMP
     275           0 : DesktopNotificationRequest::GetElement(nsIDOMElement * *aElement)
     276             : {
     277           0 :   NS_ENSURE_ARG_POINTER(aElement);
     278           0 :   *aElement = nullptr;
     279           0 :   return NS_OK;
     280             : }
     281             : 
     282             : NS_IMETHODIMP
     283           0 : DesktopNotificationRequest::Cancel()
     284             : {
     285           0 :   nsresult rv = mDesktopNotification->SetAllow(false);
     286           0 :   mDesktopNotification = nullptr;
     287           0 :   return rv;
     288             : }
     289             : 
     290             : NS_IMETHODIMP
     291           0 : DesktopNotificationRequest::Allow(JS::HandleValue aChoices)
     292             : {
     293           0 :   MOZ_ASSERT(aChoices.isUndefined());
     294           0 :   nsresult rv = mDesktopNotification->SetAllow(true);
     295           0 :   mDesktopNotification = nullptr;
     296           0 :   return rv;
     297             : }
     298             : 
     299             : NS_IMETHODIMP
     300           0 : DesktopNotificationRequest::GetRequester(nsIContentPermissionRequester** aRequester)
     301             : {
     302           0 :   NS_ENSURE_ARG_POINTER(aRequester);
     303             : 
     304           0 :   nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
     305           0 :   requester.forget(aRequester);
     306           0 :   return NS_OK;
     307             : }
     308             : 
     309             : NS_IMETHODIMP
     310           0 : DesktopNotificationRequest::GetTypes(nsIArray** aTypes)
     311             : {
     312           0 :   nsTArray<nsString> emptyOptions;
     313           0 :   return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
     314           0 :                                                          NS_LITERAL_CSTRING("unused"),
     315             :                                                          emptyOptions,
     316           0 :                                                          aTypes);
     317             : }
     318             : 
     319             : } // namespace dom
     320             : } // namespace mozilla

Generated by: LCOV version 1.13