LCOV - code coverage report
Current view: top level - dom/media/imagecapture - ImageCapture.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 97 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 22 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             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       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             : 
       7             : #include "ImageCapture.h"
       8             : #include "mozilla/dom/BlobEvent.h"
       9             : #include "mozilla/dom/DOMException.h"
      10             : #include "mozilla/dom/File.h"
      11             : #include "mozilla/dom/ImageCaptureError.h"
      12             : #include "mozilla/dom/ImageCaptureErrorEvent.h"
      13             : #include "mozilla/dom/ImageCaptureErrorEventBinding.h"
      14             : #include "mozilla/dom/VideoStreamTrack.h"
      15             : #include "nsIDocument.h"
      16             : #include "CaptureTask.h"
      17             : #include "MediaEngine.h"
      18             : 
      19             : namespace mozilla {
      20             : 
      21           0 : LogModule* GetICLog()
      22             : {
      23             :   static LazyLogModule log("ImageCapture");
      24           0 :   return log;
      25             : }
      26             : 
      27             : namespace dom {
      28             : 
      29           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(ImageCapture, DOMEventTargetHelper,
      30             :                                    mVideoStreamTrack)
      31             : 
      32           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ImageCapture)
      33           0 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
      34             : 
      35           0 : NS_IMPL_ADDREF_INHERITED(ImageCapture, DOMEventTargetHelper)
      36           0 : NS_IMPL_RELEASE_INHERITED(ImageCapture, DOMEventTargetHelper)
      37             : 
      38           0 : ImageCapture::ImageCapture(VideoStreamTrack* aVideoStreamTrack,
      39           0 :                            nsPIDOMWindowInner* aOwnerWindow)
      40           0 :   : DOMEventTargetHelper(aOwnerWindow)
      41             : {
      42           0 :   MOZ_ASSERT(aOwnerWindow);
      43           0 :   MOZ_ASSERT(aVideoStreamTrack);
      44             : 
      45           0 :   mVideoStreamTrack = aVideoStreamTrack;
      46           0 : }
      47             : 
      48           0 : ImageCapture::~ImageCapture()
      49             : {
      50           0 :   MOZ_ASSERT(NS_IsMainThread());
      51           0 : }
      52             : 
      53             : already_AddRefed<ImageCapture>
      54           0 : ImageCapture::Constructor(const GlobalObject& aGlobal,
      55             :                           VideoStreamTrack& aTrack,
      56             :                           ErrorResult& aRv)
      57             : {
      58           0 :   nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aGlobal.GetAsSupports());
      59           0 :   if (!win) {
      60           0 :     aRv.Throw(NS_ERROR_FAILURE);
      61           0 :     return nullptr;
      62             :   }
      63             : 
      64           0 :   RefPtr<ImageCapture> object = new ImageCapture(&aTrack, win);
      65             : 
      66           0 :   return object.forget();
      67             : }
      68             : 
      69             : VideoStreamTrack*
      70           0 : ImageCapture::GetVideoStreamTrack() const
      71             : {
      72           0 :   return mVideoStreamTrack;
      73             : }
      74             : 
      75             : nsresult
      76           0 : ImageCapture::TakePhotoByMediaEngine()
      77             : {
      78             :   // Callback for TakPhoto(), it also monitor the principal. If principal
      79             :   // changes, it returns PHOTO_ERROR with security error.
      80             :   class TakePhotoCallback : public MediaEnginePhotoCallback,
      81             :                             public PrincipalChangeObserver<MediaStreamTrack>
      82             :   {
      83             :   public:
      84           0 :     TakePhotoCallback(VideoStreamTrack* aVideoTrack, ImageCapture* aImageCapture)
      85           0 :       : mVideoTrack(aVideoTrack)
      86             :       , mImageCapture(aImageCapture)
      87           0 :       , mPrincipalChanged(false)
      88             :     {
      89           0 :       MOZ_ASSERT(NS_IsMainThread());
      90           0 :       mVideoTrack->AddPrincipalChangeObserver(this);
      91           0 :     }
      92             : 
      93           0 :     void PrincipalChanged(MediaStreamTrack* aMediaStream) override
      94             :     {
      95           0 :       mPrincipalChanged = true;
      96           0 :     }
      97             : 
      98           0 :     nsresult PhotoComplete(already_AddRefed<Blob> aBlob) override
      99             :     {
     100           0 :       RefPtr<Blob> blob = aBlob;
     101             : 
     102           0 :       if (mPrincipalChanged) {
     103           0 :         return PhotoError(NS_ERROR_DOM_SECURITY_ERR);
     104             :       }
     105           0 :       return mImageCapture->PostBlobEvent(blob);
     106             :     }
     107             : 
     108           0 :     nsresult PhotoError(nsresult aRv) override
     109             :     {
     110           0 :       return mImageCapture->PostErrorEvent(ImageCaptureError::PHOTO_ERROR, aRv);
     111             :     }
     112             : 
     113             :   protected:
     114           0 :     ~TakePhotoCallback()
     115           0 :     {
     116           0 :       MOZ_ASSERT(NS_IsMainThread());
     117           0 :       mVideoTrack->RemovePrincipalChangeObserver(this);
     118           0 :     }
     119             : 
     120             :     RefPtr<VideoStreamTrack> mVideoTrack;
     121             :     RefPtr<ImageCapture> mImageCapture;
     122             :     bool mPrincipalChanged;
     123             :   };
     124             : 
     125             :   RefPtr<MediaEnginePhotoCallback> callback =
     126           0 :     new TakePhotoCallback(mVideoStreamTrack, this);
     127           0 :   return mVideoStreamTrack->GetSource().TakePhoto(callback);
     128             : }
     129             : 
     130             : void
     131           0 : ImageCapture::TakePhoto(ErrorResult& aResult)
     132             : {
     133             :   // According to spec, VideoStreamTrack.readyState must be "live"; however
     134             :   // gecko doesn't implement it yet (bug 910249). Instead of readyState, we
     135             :   // check VideoStreamTrack.enable before bug 910249 is fixed.
     136             :   // The error code should be INVALID_TRACK, but spec doesn't define it in
     137             :   // ImageCaptureError. So it returns PHOTO_ERROR here before spec updates.
     138           0 :   if (!mVideoStreamTrack->Enabled()) {
     139           0 :     PostErrorEvent(ImageCaptureError::PHOTO_ERROR, NS_ERROR_FAILURE);
     140           0 :     return;
     141             :   }
     142             : 
     143             :   // Try if MediaEngine supports taking photo.
     144           0 :   nsresult rv = TakePhotoByMediaEngine();
     145             : 
     146             :   // It falls back to MediaStreamGraph image capture if MediaEngine doesn't
     147             :   // support TakePhoto().
     148           0 :   if (rv == NS_ERROR_NOT_IMPLEMENTED) {
     149           0 :     IC_LOG("MediaEngine doesn't support TakePhoto(), it falls back to MediaStreamGraph.");
     150           0 :     RefPtr<CaptureTask> task = new CaptureTask(this);
     151             : 
     152             :     // It adds itself into MediaStreamGraph, so ImageCapture doesn't need to hold
     153             :     // the reference.
     154           0 :     task->AttachTrack();
     155             :   }
     156             : }
     157             : 
     158             : nsresult
     159           0 : ImageCapture::PostBlobEvent(Blob* aBlob)
     160             : {
     161           0 :   MOZ_ASSERT(NS_IsMainThread());
     162           0 :   if (!CheckPrincipal()) {
     163             :     // Media is not same-origin, don't allow the data out.
     164           0 :     return PostErrorEvent(ImageCaptureError::PHOTO_ERROR, NS_ERROR_DOM_SECURITY_ERR);
     165             :   }
     166             : 
     167           0 :   BlobEventInit init;
     168           0 :   init.mBubbles = false;
     169           0 :   init.mCancelable = false;
     170           0 :   init.mData = aBlob;
     171             : 
     172             :   RefPtr<BlobEvent> blob_event =
     173           0 :     BlobEvent::Constructor(this, NS_LITERAL_STRING("photo"), init);
     174             : 
     175           0 :   return DispatchTrustedEvent(blob_event);
     176             : }
     177             : 
     178             : nsresult
     179           0 : ImageCapture::PostErrorEvent(uint16_t aErrorCode, nsresult aReason)
     180             : {
     181           0 :   MOZ_ASSERT(NS_IsMainThread());
     182           0 :   nsresult rv = CheckInnerWindowCorrectness();
     183           0 :   NS_ENSURE_SUCCESS(rv, rv);
     184             : 
     185           0 :   nsString errorMsg;
     186           0 :   if (NS_FAILED(aReason)) {
     187           0 :     nsCString name, message;
     188           0 :     rv = NS_GetNameAndMessageForDOMNSResult(aReason, name, message);
     189           0 :     if (NS_SUCCEEDED(rv)) {
     190           0 :       CopyASCIItoUTF16(message, errorMsg);
     191             :     }
     192             :   }
     193             : 
     194             :   RefPtr<ImageCaptureError> error =
     195           0 :     new ImageCaptureError(this, aErrorCode, errorMsg);
     196             : 
     197           0 :   ImageCaptureErrorEventInit init;
     198           0 :   init.mBubbles = false;
     199           0 :   init.mCancelable = false;
     200           0 :   init.mImageCaptureError = error;
     201             : 
     202             :   nsCOMPtr<nsIDOMEvent> event =
     203           0 :     ImageCaptureErrorEvent::Constructor(this, NS_LITERAL_STRING("error"), init);
     204             : 
     205           0 :   return DispatchTrustedEvent(event);
     206             : }
     207             : 
     208             : bool
     209           0 : ImageCapture::CheckPrincipal()
     210             : {
     211           0 :   MOZ_ASSERT(NS_IsMainThread());
     212             : 
     213           0 :   nsCOMPtr<nsIPrincipal> principal = mVideoStreamTrack->GetPrincipal();
     214             : 
     215           0 :   if (!GetOwner()) {
     216           0 :     return false;
     217             :   }
     218           0 :   nsCOMPtr<nsIDocument> doc = GetOwner()->GetExtantDoc();
     219           0 :   if (!doc || !principal) {
     220           0 :     return false;
     221             :   }
     222             : 
     223             :   bool subsumes;
     224           0 :   if (NS_FAILED(doc->NodePrincipal()->Subsumes(principal, &subsumes))) {
     225           0 :     return false;
     226             :   }
     227             : 
     228           0 :   return subsumes;
     229             : }
     230             : 
     231             : } // namespace dom
     232             : } // namespace mozilla

Generated by: LCOV version 1.13