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

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Pub
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with t
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "mozilla/AlertNotification.h"
       6             : 
       7             : #include "imgIContainer.h"
       8             : #include "imgINotificationObserver.h"
       9             : #include "imgIRequest.h"
      10             : #include "imgLoader.h"
      11             : #include "nsAlertsUtils.h"
      12             : #include "nsComponentManagerUtils.h"
      13             : #include "nsContentUtils.h"
      14             : #include "nsNetUtil.h"
      15             : #include "nsServiceManagerUtils.h"
      16             : 
      17             : #include "mozilla/Unused.h"
      18             : 
      19             : namespace mozilla {
      20             : 
      21           0 : NS_IMPL_ISUPPORTS(AlertNotification, nsIAlertNotification)
      22             : 
      23           0 : AlertNotification::AlertNotification()
      24             :   : mTextClickable(false)
      25           0 :   , mInPrivateBrowsing(false)
      26           0 : {}
      27             : 
      28           0 : AlertNotification::~AlertNotification()
      29           0 : {}
      30             : 
      31             : NS_IMETHODIMP
      32           0 : AlertNotification::Init(const nsAString& aName, const nsAString& aImageURL,
      33             :                         const nsAString& aTitle, const nsAString& aText,
      34             :                         bool aTextClickable, const nsAString& aCookie,
      35             :                         const nsAString& aDir, const nsAString& aLang,
      36             :                         const nsAString& aData, nsIPrincipal* aPrincipal,
      37             :                         bool aInPrivateBrowsing, bool aRequireInteraction)
      38             : {
      39           0 :   mName = aName;
      40           0 :   mImageURL = aImageURL;
      41           0 :   mTitle = aTitle;
      42           0 :   mText = aText;
      43           0 :   mTextClickable = aTextClickable;
      44           0 :   mCookie = aCookie;
      45           0 :   mDir = aDir;
      46           0 :   mLang = aLang;
      47           0 :   mData = aData;
      48           0 :   mPrincipal = aPrincipal;
      49           0 :   mInPrivateBrowsing = aInPrivateBrowsing;
      50           0 :   mRequireInteraction = aRequireInteraction;
      51           0 :   return NS_OK;
      52             : }
      53             : 
      54             : NS_IMETHODIMP
      55           0 : AlertNotification::GetName(nsAString& aName)
      56             : {
      57           0 :   aName = mName;
      58           0 :   return NS_OK;
      59             : }
      60             : 
      61             : NS_IMETHODIMP
      62           0 : AlertNotification::GetImageURL(nsAString& aImageURL)
      63             : {
      64           0 :   aImageURL = mImageURL;
      65           0 :   return NS_OK;
      66             : }
      67             : 
      68             : NS_IMETHODIMP
      69           0 : AlertNotification::GetTitle(nsAString& aTitle)
      70             : {
      71           0 :   aTitle = mTitle;
      72           0 :   return NS_OK;
      73             : }
      74             : 
      75             : NS_IMETHODIMP
      76           0 : AlertNotification::GetText(nsAString& aText)
      77             : {
      78           0 :   aText = mText;
      79           0 :   return NS_OK;
      80             : }
      81             : 
      82             : NS_IMETHODIMP
      83           0 : AlertNotification::GetTextClickable(bool* aTextClickable)
      84             : {
      85           0 :   *aTextClickable = mTextClickable;
      86           0 :   return NS_OK;
      87             : }
      88             : 
      89             : NS_IMETHODIMP
      90           0 : AlertNotification::GetCookie(nsAString& aCookie)
      91             : {
      92           0 :   aCookie = mCookie;
      93           0 :   return NS_OK;
      94             : }
      95             : 
      96             : NS_IMETHODIMP
      97           0 : AlertNotification::GetDir(nsAString& aDir)
      98             : {
      99           0 :   aDir = mDir;
     100           0 :   return NS_OK;
     101             : }
     102             : 
     103             : NS_IMETHODIMP
     104           0 : AlertNotification::GetLang(nsAString& aLang)
     105             : {
     106           0 :   aLang = mLang;
     107           0 :   return NS_OK;
     108             : }
     109             : 
     110             : NS_IMETHODIMP
     111           0 : AlertNotification::GetRequireInteraction(bool* aRequireInteraction)
     112             : {
     113           0 :   *aRequireInteraction = mRequireInteraction;
     114           0 :   return NS_OK;
     115             : }
     116             : 
     117             : NS_IMETHODIMP
     118           0 : AlertNotification::GetData(nsAString& aData)
     119             : {
     120           0 :   aData = mData;
     121           0 :   return NS_OK;
     122             : }
     123             : 
     124             : NS_IMETHODIMP
     125           0 : AlertNotification::GetPrincipal(nsIPrincipal** aPrincipal)
     126             : {
     127           0 :   NS_IF_ADDREF(*aPrincipal = mPrincipal);
     128           0 :   return NS_OK;
     129             : }
     130             : 
     131             : NS_IMETHODIMP
     132           0 : AlertNotification::GetURI(nsIURI** aURI)
     133             : {
     134           0 :   if (!nsAlertsUtils::IsActionablePrincipal(mPrincipal)) {
     135           0 :     *aURI = nullptr;
     136           0 :     return NS_OK;
     137             :   }
     138           0 :   return mPrincipal->GetURI(aURI);
     139             : }
     140             : 
     141             : NS_IMETHODIMP
     142           0 : AlertNotification::GetInPrivateBrowsing(bool* aInPrivateBrowsing)
     143             : {
     144           0 :   *aInPrivateBrowsing = mInPrivateBrowsing;
     145           0 :   return NS_OK;
     146             : }
     147             : 
     148             : NS_IMETHODIMP
     149           0 : AlertNotification::GetActionable(bool* aActionable)
     150             : {
     151           0 :   *aActionable = nsAlertsUtils::IsActionablePrincipal(mPrincipal);
     152           0 :   return NS_OK;
     153             : }
     154             : 
     155             : NS_IMETHODIMP
     156           0 : AlertNotification::GetSource(nsAString& aSource)
     157             : {
     158           0 :   nsAlertsUtils::GetSourceHostPort(mPrincipal, aSource);
     159           0 :   return NS_OK;
     160             : }
     161             : 
     162             : NS_IMETHODIMP
     163           0 : AlertNotification::LoadImage(uint32_t aTimeout,
     164             :                              nsIAlertNotificationImageListener* aListener,
     165             :                              nsISupports* aUserData,
     166             :                              nsICancelable** aRequest)
     167             : {
     168           0 :   NS_ENSURE_ARG(aListener);
     169           0 :   NS_ENSURE_ARG_POINTER(aRequest);
     170           0 :   *aRequest = nullptr;
     171             : 
     172             :   // Exit early if this alert doesn't have an image.
     173           0 :   if (mImageURL.IsEmpty()) {
     174           0 :     return aListener->OnImageMissing(aUserData);
     175             :   }
     176           0 :   nsCOMPtr<nsIURI> imageURI;
     177           0 :   NS_NewURI(getter_AddRefs(imageURI), mImageURL);
     178           0 :   if (!imageURI) {
     179           0 :     return aListener->OnImageMissing(aUserData);
     180             :   }
     181             : 
     182             :   RefPtr<AlertImageRequest> request = new AlertImageRequest(imageURI, mPrincipal,
     183           0 :                                                             mInPrivateBrowsing,
     184             :                                                             aTimeout, aListener,
     185           0 :                                                             aUserData);
     186           0 :   nsresult rv = request->Start();
     187           0 :   request.forget(aRequest);
     188           0 :   return rv;
     189             : }
     190             : 
     191           0 : NS_IMPL_CYCLE_COLLECTION(AlertImageRequest, mURI, mPrincipal, mListener,
     192             :                          mUserData)
     193             : 
     194           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AlertImageRequest)
     195           0 :   NS_INTERFACE_MAP_ENTRY(imgINotificationObserver)
     196           0 :   NS_INTERFACE_MAP_ENTRY(nsICancelable)
     197           0 :   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
     198           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, imgINotificationObserver)
     199           0 : NS_INTERFACE_MAP_END
     200             : 
     201           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(AlertImageRequest)
     202           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(AlertImageRequest)
     203             : 
     204           0 : AlertImageRequest::AlertImageRequest(nsIURI* aURI, nsIPrincipal* aPrincipal,
     205             :                                      bool aInPrivateBrowsing, uint32_t aTimeout,
     206             :                                      nsIAlertNotificationImageListener* aListener,
     207           0 :                                      nsISupports* aUserData)
     208             :   : mURI(aURI)
     209             :   , mPrincipal(aPrincipal)
     210             :   , mInPrivateBrowsing(aInPrivateBrowsing)
     211             :   , mTimeout(aTimeout)
     212             :   , mListener(aListener)
     213           0 :   , mUserData(aUserData)
     214           0 : {}
     215             : 
     216           0 : AlertImageRequest::~AlertImageRequest()
     217             : {
     218           0 :   if (mRequest) {
     219           0 :     mRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
     220             :   }
     221           0 : }
     222             : 
     223             : NS_IMETHODIMP
     224           0 : AlertImageRequest::Notify(imgIRequest* aRequest, int32_t aType,
     225             :                           const nsIntRect* aData)
     226             : {
     227           0 :   MOZ_ASSERT(aRequest == mRequest);
     228             : 
     229           0 :   uint32_t imgStatus = imgIRequest::STATUS_ERROR;
     230           0 :   nsresult rv = aRequest->GetImageStatus(&imgStatus);
     231           0 :   if (NS_WARN_IF(NS_FAILED(rv)) ||
     232           0 :       (imgStatus & imgIRequest::STATUS_ERROR)) {
     233           0 :     return NotifyMissing();
     234             :   }
     235             : 
     236             :   // If the image is already decoded, `FRAME_COMPLETE` will fire before
     237             :   // `LOAD_COMPLETE`, so we can notify the listener immediately. Otherwise,
     238             :   // we'll need to request a decode when `LOAD_COMPLETE` fires, and wait
     239             :   // for the first frame.
     240             : 
     241           0 :   if (aType == imgINotificationObserver::LOAD_COMPLETE) {
     242           0 :     if (!(imgStatus & imgIRequest::STATUS_FRAME_COMPLETE)) {
     243           0 :       nsCOMPtr<imgIContainer> image;
     244           0 :       rv = aRequest->GetImage(getter_AddRefs(image));
     245           0 :       if (NS_WARN_IF(NS_FAILED(rv) || !image)) {
     246           0 :         return NotifyMissing();
     247             :       }
     248             : 
     249             :       // Ask the image to decode at its intrinsic size.
     250           0 :       int32_t width = 0, height = 0;
     251           0 :       image->GetWidth(&width);
     252           0 :       image->GetHeight(&height);
     253           0 :       image->RequestDecodeForSize(gfx::IntSize(width, height), imgIContainer::FLAG_NONE);
     254             :     }
     255           0 :     return NS_OK;
     256             :   }
     257             : 
     258           0 :   if (aType == imgINotificationObserver::FRAME_COMPLETE) {
     259           0 :     return NotifyComplete();
     260             :   }
     261             : 
     262           0 :   return NS_OK;
     263             : }
     264             : 
     265             : NS_IMETHODIMP
     266           0 : AlertImageRequest::Notify(nsITimer* aTimer)
     267             : {
     268           0 :   MOZ_ASSERT(aTimer == mTimer);
     269           0 :   return NotifyMissing();
     270             : }
     271             : 
     272             : NS_IMETHODIMP
     273           0 : AlertImageRequest::Cancel(nsresult aReason)
     274             : {
     275           0 :   if (mRequest) {
     276           0 :     mRequest->Cancel(aReason);
     277             :   }
     278             :   // We call `NotifyMissing` here because we won't receive a `LOAD_COMPLETE`
     279             :   // notification if we cancel the request before it loads (bug 1233086,
     280             :   // comment 33). Once that's fixed, `nsIAlertNotification::loadImage` could
     281             :   // return the underlying `imgIRequest` instead of the wrapper.
     282           0 :   return NotifyMissing();
     283             : }
     284             : 
     285             : nsresult
     286           0 : AlertImageRequest::Start()
     287             : {
     288             :   // Keep the request alive until we notify the image listener.
     289           0 :   NS_ADDREF_THIS();
     290             : 
     291             :   nsresult rv;
     292           0 :   if (mTimeout > 0) {
     293           0 :     mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
     294           0 :     if (NS_WARN_IF(!mTimer)) {
     295           0 :       return NotifyMissing();
     296             :     }
     297           0 :     rv = mTimer->InitWithCallback(this, mTimeout,
     298           0 :                                   nsITimer::TYPE_ONE_SHOT);
     299           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     300           0 :       return NotifyMissing();
     301             :     }
     302             :   }
     303             : 
     304             :   // Begin loading the image.
     305           0 :   imgLoader* il = imgLoader::NormalLoader();
     306           0 :   if (!il) {
     307           0 :     return NotifyMissing();
     308             :   }
     309             : 
     310             :   // Bug 1237405: `LOAD_ANONYMOUS` disables cookies, but we want to use a
     311             :   // temporary cookie jar instead. We should also use
     312             :   // `imgLoader::PrivateBrowsingLoader()` instead of the normal loader.
     313             :   // Unfortunately, the PB loader checks the load group, and asserts if its
     314             :   // load context's PB flag isn't set. The fix is to pass the load group to
     315             :   // `nsIAlertNotification::loadImage`.
     316           0 :   int32_t loadFlags = mInPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS :
     317           0 :                       nsIRequest::LOAD_NORMAL;
     318             : 
     319           0 :   rv = il->LoadImageXPCOM(mURI, nullptr, nullptr,
     320           0 :                           NS_LITERAL_STRING("default"), mPrincipal, nullptr,
     321             :                           this, nullptr, loadFlags, nullptr,
     322             :                           nsIContentPolicy::TYPE_INTERNAL_IMAGE,
     323           0 :                           getter_AddRefs(mRequest));
     324           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     325           0 :     return NotifyMissing();
     326             :   }
     327             : 
     328           0 :   return NS_OK;
     329             : }
     330             : 
     331             : nsresult
     332           0 : AlertImageRequest::NotifyMissing()
     333             : {
     334           0 :   if (mTimer) {
     335           0 :     mTimer->Cancel();
     336           0 :     mTimer = nullptr;
     337             :   }
     338           0 :   if (nsCOMPtr<nsIAlertNotificationImageListener> listener = mListener.forget()) {
     339           0 :     nsresult rv = listener->OnImageMissing(mUserData);
     340           0 :     NS_RELEASE_THIS();
     341           0 :     return rv;
     342             :   }
     343           0 :   return NS_OK;
     344             : }
     345             : 
     346             : nsresult
     347           0 : AlertImageRequest::NotifyComplete()
     348             : {
     349           0 :   if (mTimer) {
     350           0 :     mTimer->Cancel();
     351           0 :     mTimer = nullptr;
     352             :   }
     353           0 :   if (nsCOMPtr<nsIAlertNotificationImageListener> listener = mListener.forget()) {
     354           0 :     nsresult rv = listener->OnImageReady(mUserData, mRequest);
     355           0 :     NS_RELEASE_THIS();
     356           0 :     return rv;
     357             :   }
     358           0 :   return NS_OK;
     359             : }
     360             : 
     361             : } // namespace mozilla

Generated by: LCOV version 1.13