LCOV - code coverage report
Current view: top level - dom/media/gmp - GMPPlatform.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 152 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 37 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 "GMPPlatform.h"
       7             : #include "GMPStorageChild.h"
       8             : #include "GMPTimerChild.h"
       9             : #include "mozilla/Monitor.h"
      10             : #include "GMPChild.h"
      11             : #include "mozilla/Mutex.h"
      12             : #include "base/thread.h"
      13             : #include "base/time.h"
      14             : #include "mozilla/ReentrantMonitor.h"
      15             : 
      16             : #include <ctime>
      17             : 
      18             : namespace mozilla {
      19             : namespace gmp {
      20             : 
      21             : static MessageLoop* sMainLoop = nullptr;
      22             : static GMPChild* sChild = nullptr;
      23             : 
      24             : static bool
      25           0 : IsOnChildMainThread()
      26             : {
      27           0 :   return sMainLoop && sMainLoop == MessageLoop::current();
      28             : }
      29             : 
      30             : // We just need a refcounted wrapper for GMPTask objects.
      31             : class GMPRunnable final
      32             : {
      33             : public:
      34           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPRunnable)
      35             : 
      36           0 :   explicit GMPRunnable(GMPTask* aTask)
      37           0 :   : mTask(aTask)
      38             :   {
      39           0 :     MOZ_ASSERT(mTask);
      40           0 :   }
      41             : 
      42           0 :   void Run()
      43             :   {
      44           0 :     mTask->Run();
      45           0 :     mTask->Destroy();
      46           0 :     mTask = nullptr;
      47           0 :   }
      48             : 
      49             : private:
      50           0 :   ~GMPRunnable()
      51           0 :   {
      52           0 :   }
      53             : 
      54             :   GMPTask* mTask;
      55             : };
      56             : 
      57             : class GMPSyncRunnable final
      58             : {
      59             : public:
      60           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPSyncRunnable)
      61             : 
      62           0 :   GMPSyncRunnable(GMPTask* aTask, MessageLoop* aMessageLoop)
      63           0 :   : mDone(false)
      64             :   , mTask(aTask)
      65             :   , mMessageLoop(aMessageLoop)
      66           0 :   , mMonitor("GMPSyncRunnable")
      67             :   {
      68           0 :     MOZ_ASSERT(mTask);
      69           0 :     MOZ_ASSERT(mMessageLoop);
      70           0 :   }
      71             : 
      72           0 :   void Post()
      73             :   {
      74             :     // We assert here for two reasons.
      75             :     // 1) Nobody should be blocking the main thread.
      76             :     // 2) This prevents deadlocks when doing sync calls to main which if the
      77             :     //    main thread tries to do a sync call back to the calling thread.
      78           0 :     MOZ_ASSERT(!IsOnChildMainThread());
      79             : 
      80           0 :     mMessageLoop->PostTask(NewRunnableMethod(
      81           0 :       "gmp::GMPSyncRunnable::Run", this, &GMPSyncRunnable::Run));
      82           0 :     MonitorAutoLock lock(mMonitor);
      83           0 :     while (!mDone) {
      84           0 :       lock.Wait();
      85             :     }
      86           0 :   }
      87             : 
      88           0 :   void Run()
      89             :   {
      90           0 :     mTask->Run();
      91           0 :     mTask->Destroy();
      92           0 :     mTask = nullptr;
      93           0 :     MonitorAutoLock lock(mMonitor);
      94           0 :     mDone = true;
      95           0 :     lock.Notify();
      96           0 :   }
      97             : 
      98             : private:
      99           0 :   ~GMPSyncRunnable()
     100           0 :   {
     101           0 :   }
     102             : 
     103             :   bool mDone;
     104             :   GMPTask* mTask;
     105             :   MessageLoop* mMessageLoop;
     106             :   Monitor mMonitor;
     107             : };
     108             : 
     109             : class GMPThreadImpl : public GMPThread
     110             : {
     111             : public:
     112             :   GMPThreadImpl();
     113             :   virtual ~GMPThreadImpl();
     114             : 
     115             :   // GMPThread
     116             :   void Post(GMPTask* aTask) override;
     117             :   void Join() override;
     118             : 
     119             : private:
     120             :   Mutex mMutex;
     121             :   base::Thread mThread;
     122             : };
     123             : 
     124             : GMPErr
     125           0 : CreateThread(GMPThread** aThread)
     126             : {
     127           0 :   if (!aThread) {
     128           0 :     return GMPGenericErr;
     129             :   }
     130             : 
     131           0 :   *aThread = new GMPThreadImpl();
     132             : 
     133           0 :   return GMPNoErr;
     134             : }
     135             : 
     136             : GMPErr
     137           0 : RunOnMainThread(GMPTask* aTask)
     138             : {
     139           0 :   if (!aTask || !sMainLoop) {
     140           0 :     return GMPGenericErr;
     141             :   }
     142             : 
     143           0 :   RefPtr<GMPRunnable> r = new GMPRunnable(aTask);
     144           0 :   sMainLoop->PostTask(
     145           0 :     NewRunnableMethod("gmp::GMPRunnable::Run", r, &GMPRunnable::Run));
     146             : 
     147           0 :   return GMPNoErr;
     148             : }
     149             : 
     150             : GMPErr
     151           0 : SyncRunOnMainThread(GMPTask* aTask)
     152             : {
     153           0 :   if (!aTask || !sMainLoop || IsOnChildMainThread()) {
     154           0 :     return GMPGenericErr;
     155             :   }
     156             : 
     157           0 :   RefPtr<GMPSyncRunnable> r = new GMPSyncRunnable(aTask, sMainLoop);
     158             : 
     159           0 :   r->Post();
     160             : 
     161           0 :   return GMPNoErr;
     162             : }
     163             : 
     164             : class GMPMutexImpl : public GMPMutex
     165             : {
     166             : public:
     167             :   GMPMutexImpl();
     168             :   virtual ~GMPMutexImpl();
     169             : 
     170             :   // GMPMutex
     171             :   void Acquire() override;
     172             :   void Release() override;
     173             :   void Destroy() override;
     174             : 
     175             : private:
     176             :   ReentrantMonitor mMonitor;
     177             : };
     178             : 
     179             : GMPErr
     180           0 : CreateMutex(GMPMutex** aMutex)
     181             : {
     182           0 :   if (!aMutex) {
     183           0 :     return GMPGenericErr;
     184             :   }
     185             : 
     186           0 :   *aMutex = new GMPMutexImpl();
     187             : 
     188           0 :   return GMPNoErr;
     189             : }
     190             : 
     191             : GMPErr
     192           0 : CreateRecord(const char* aRecordName,
     193             :              uint32_t aRecordNameSize,
     194             :              GMPRecord** aOutRecord,
     195             :              GMPRecordClient* aClient)
     196             : {
     197           0 :   if (aRecordNameSize > GMP_MAX_RECORD_NAME_SIZE ||
     198             :       aRecordNameSize == 0) {
     199           0 :     NS_WARNING("GMP tried to CreateRecord with too long or 0 record name");
     200           0 :     return GMPGenericErr;
     201             :   }
     202           0 :   GMPStorageChild* storage = sChild->GetGMPStorage();
     203           0 :   if (!storage) {
     204           0 :     return GMPGenericErr;
     205             :   }
     206           0 :   MOZ_ASSERT(storage);
     207           0 :   return storage->CreateRecord(nsDependentCString(aRecordName, aRecordNameSize),
     208             :                                aOutRecord,
     209           0 :                                aClient);
     210             : }
     211             : 
     212             : GMPErr
     213           0 : SetTimerOnMainThread(GMPTask* aTask, int64_t aTimeoutMS)
     214             : {
     215           0 :   if (!aTask || !sMainLoop || !IsOnChildMainThread()) {
     216           0 :     return GMPGenericErr;
     217             :   }
     218           0 :   GMPTimerChild* timers = sChild->GetGMPTimers();
     219           0 :   NS_ENSURE_TRUE(timers, GMPGenericErr);
     220           0 :   return timers->SetTimer(aTask, aTimeoutMS);
     221             : }
     222             : 
     223             : GMPErr
     224           0 : GetClock(GMPTimestamp* aOutTime)
     225             : {
     226           0 :   if (!aOutTime) {
     227           0 :     return GMPGenericErr;
     228             :   }
     229           0 :   *aOutTime = base::Time::Now().ToDoubleT() * 1000.0;
     230           0 :  return GMPNoErr;
     231             : }
     232             : 
     233             : void
     234           0 : InitPlatformAPI(GMPPlatformAPI& aPlatformAPI, GMPChild* aChild)
     235             : {
     236           0 :   if (!sMainLoop) {
     237           0 :     sMainLoop = MessageLoop::current();
     238             :   }
     239           0 :   if (!sChild) {
     240           0 :     sChild = aChild;
     241             :   }
     242             : 
     243           0 :   aPlatformAPI.version = 0;
     244           0 :   aPlatformAPI.createthread = &CreateThread;
     245           0 :   aPlatformAPI.runonmainthread = &RunOnMainThread;
     246           0 :   aPlatformAPI.syncrunonmainthread = &SyncRunOnMainThread;
     247           0 :   aPlatformAPI.createmutex = &CreateMutex;
     248           0 :   aPlatformAPI.createrecord = &CreateRecord;
     249           0 :   aPlatformAPI.settimer = &SetTimerOnMainThread;
     250           0 :   aPlatformAPI.getcurrenttime = &GetClock;
     251           0 : }
     252             : 
     253           0 : GMPThreadImpl::GMPThreadImpl()
     254             : : mMutex("GMPThreadImpl"),
     255           0 :   mThread("GMPThread")
     256             : {
     257           0 :   MOZ_COUNT_CTOR(GMPThread);
     258           0 : }
     259             : 
     260           0 : GMPThreadImpl::~GMPThreadImpl()
     261             : {
     262           0 :   MOZ_COUNT_DTOR(GMPThread);
     263           0 : }
     264             : 
     265             : void
     266           0 : GMPThreadImpl::Post(GMPTask* aTask)
     267             : {
     268           0 :   MutexAutoLock lock(mMutex);
     269             : 
     270           0 :   if (!mThread.IsRunning()) {
     271           0 :     bool started = mThread.Start();
     272           0 :     if (!started) {
     273           0 :       NS_WARNING("Unable to start GMPThread!");
     274           0 :       return;
     275             :     }
     276             :   }
     277             : 
     278           0 :   RefPtr<GMPRunnable> r = new GMPRunnable(aTask);
     279           0 :   mThread.message_loop()->PostTask(
     280           0 :     NewRunnableMethod("gmp::GMPRunnable::Run", r.get(), &GMPRunnable::Run));
     281             : }
     282             : 
     283             : void
     284           0 : GMPThreadImpl::Join()
     285             : {
     286             :   {
     287           0 :     MutexAutoLock lock(mMutex);
     288           0 :     if (mThread.IsRunning()) {
     289           0 :       mThread.Stop();
     290             :     }
     291             :   }
     292           0 :   delete this;
     293           0 : }
     294             : 
     295           0 : GMPMutexImpl::GMPMutexImpl()
     296           0 : : mMonitor("gmp-mutex")
     297             : {
     298           0 :   MOZ_COUNT_CTOR(GMPMutexImpl);
     299           0 : }
     300             : 
     301           0 : GMPMutexImpl::~GMPMutexImpl()
     302             : {
     303           0 :   MOZ_COUNT_DTOR(GMPMutexImpl);
     304           0 : }
     305             : 
     306             : void
     307           0 : GMPMutexImpl::Destroy()
     308             : {
     309           0 :   delete this;
     310           0 : }
     311             : 
     312             : void
     313           0 : GMPMutexImpl::Acquire()
     314             : {
     315           0 :   mMonitor.Enter();
     316           0 : }
     317             : 
     318             : void
     319           0 : GMPMutexImpl::Release()
     320             : {
     321           0 :   mMonitor.Exit();
     322           0 : }
     323             : 
     324             : GMPTask*
     325           0 : NewGMPTask(std::function<void()>&& aFunction)
     326             : {
     327             :   class Task : public GMPTask
     328             :   {
     329             :   public:
     330           0 :     explicit Task(std::function<void()>&& aFunction)
     331           0 :       : mFunction(Move(aFunction))
     332             :     {
     333           0 :     }
     334           0 :     void Destroy() override
     335             :     {
     336           0 :       delete this;
     337           0 :     }
     338           0 :     ~Task() override
     339           0 :     {
     340           0 :     }
     341           0 :     void Run() override
     342             :     {
     343           0 :       mFunction();
     344           0 :     }
     345             :   private:
     346             :     std::function<void()> mFunction;
     347             :   };
     348           0 :   return new Task(Move(aFunction));
     349             : }
     350             : 
     351             : } // namespace gmp
     352             : } // namespace mozilla

Generated by: LCOV version 1.13