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/. */
6 #include "GMPPlatform.h"
7 #include "GMPStorageChild.h"
8 #include "GMPTimerChild.h"
9 #include "mozilla/Monitor.h"
11 #include "mozilla/Mutex.h"
12 #include "base/thread.h"
13 #include "base/time.h"
14 #include "mozilla/ReentrantMonitor.h"
17 # include "mozilla/UntrustedModulesProcessor.h"
22 namespace mozilla::gmp
{
24 static MessageLoop
* sMainLoop
= nullptr;
25 static GMPChild
* sChild
= nullptr;
27 static bool IsOnChildMainThread() {
28 return sMainLoop
&& sMainLoop
== MessageLoop::current();
31 // We just need a refcounted wrapper for GMPTask objects.
32 class GMPRunnable final
{
34 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPRunnable
)
36 explicit GMPRunnable(GMPTask
* aTask
) : mTask(aTask
) { MOZ_ASSERT(mTask
); }
45 ~GMPRunnable() = default;
50 class GMPSyncRunnable final
{
52 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPSyncRunnable
)
54 GMPSyncRunnable(GMPTask
* aTask
, MessageLoop
* aMessageLoop
)
57 mMessageLoop(aMessageLoop
),
58 mMonitor("GMPSyncRunnable") {
60 MOZ_ASSERT(mMessageLoop
);
64 // We assert here for two reasons.
65 // 1) Nobody should be blocking the main thread.
66 // 2) This prevents deadlocks when doing sync calls to main which if the
67 // main thread tries to do a sync call back to the calling thread.
68 MOZ_ASSERT(!IsOnChildMainThread());
70 mMessageLoop
->PostTask(NewRunnableMethod("gmp::GMPSyncRunnable::Run", this,
71 &GMPSyncRunnable::Run
));
72 MonitorAutoLock
lock(mMonitor
);
82 MonitorAutoLock
lock(mMonitor
);
88 ~GMPSyncRunnable() = default;
90 bool mDone
MOZ_GUARDED_BY(mMonitor
);
92 MessageLoop
* mMessageLoop
;
96 class GMPThreadImpl
: public GMPThread
{
99 virtual ~GMPThreadImpl();
102 void Post(GMPTask
* aTask
) override
;
103 void Join() override
;
106 Mutex mMutex MOZ_UNANNOTATED
;
107 base::Thread mThread
MOZ_GUARDED_BY(mMutex
);
110 GMPErr
CreateThread(GMPThread
** aThread
) {
112 return GMPGenericErr
;
115 *aThread
= new GMPThreadImpl();
120 GMPErr
RunOnMainThread(GMPTask
* aTask
) {
121 if (!aTask
|| !sMainLoop
) {
122 return GMPGenericErr
;
125 RefPtr
<GMPRunnable
> r
= new GMPRunnable(aTask
);
127 NewRunnableMethod("gmp::GMPRunnable::Run", r
, &GMPRunnable::Run
));
132 GMPErr
SyncRunOnMainThread(GMPTask
* aTask
) {
133 if (!aTask
|| !sMainLoop
|| IsOnChildMainThread()) {
134 return GMPGenericErr
;
137 RefPtr
<GMPSyncRunnable
> r
= new GMPSyncRunnable(aTask
, sMainLoop
);
144 class MOZ_CAPABILITY("mutex") GMPMutexImpl
: public GMPMutex
{
147 virtual ~GMPMutexImpl();
150 void Acquire() override
MOZ_CAPABILITY_ACQUIRE();
151 void Release() override
MOZ_CAPABILITY_RELEASE();
152 void Destroy() override
;
155 ReentrantMonitor mMonitor MOZ_UNANNOTATED
;
158 GMPErr
CreateMutex(GMPMutex
** aMutex
) {
160 return GMPGenericErr
;
163 *aMutex
= new GMPMutexImpl();
168 GMPErr
CreateRecord(const char* aRecordName
, uint32_t aRecordNameSize
,
169 GMPRecord
** aOutRecord
, GMPRecordClient
* aClient
) {
170 if (aRecordNameSize
> GMP_MAX_RECORD_NAME_SIZE
|| aRecordNameSize
== 0) {
171 NS_WARNING("GMP tried to CreateRecord with too long or 0 record name");
172 return GMPGenericErr
;
174 GMPStorageChild
* storage
= sChild
->GetGMPStorage();
176 return GMPGenericErr
;
179 return storage
->CreateRecord(nsDependentCString(aRecordName
, aRecordNameSize
),
180 aOutRecord
, aClient
);
183 GMPErr
SetTimerOnMainThread(GMPTask
* aTask
, int64_t aTimeoutMS
) {
184 if (!aTask
|| !sMainLoop
|| !IsOnChildMainThread()) {
185 return GMPGenericErr
;
187 GMPTimerChild
* timers
= sChild
->GetGMPTimers();
188 NS_ENSURE_TRUE(timers
, GMPGenericErr
);
189 return timers
->SetTimer(aTask
, aTimeoutMS
);
192 GMPErr
GetClock(GMPTimestamp
* aOutTime
) {
194 return GMPGenericErr
;
196 *aOutTime
= base::Time::Now().ToDoubleT() * 1000.0;
200 void InitPlatformAPI(GMPPlatformAPI
& aPlatformAPI
, GMPChild
* aChild
) {
202 sMainLoop
= MessageLoop::current();
208 aPlatformAPI
.version
= 0;
209 aPlatformAPI
.createthread
= &CreateThread
;
210 aPlatformAPI
.runonmainthread
= &RunOnMainThread
;
211 aPlatformAPI
.syncrunonmainthread
= &SyncRunOnMainThread
;
212 aPlatformAPI
.createmutex
= &CreateMutex
;
213 aPlatformAPI
.createrecord
= &CreateRecord
;
214 aPlatformAPI
.settimer
= &SetTimerOnMainThread
;
215 aPlatformAPI
.getcurrenttime
= &GetClock
;
218 void SendFOGData(ipc::ByteBuf
&& buf
) {
220 sChild
->SendFOGData(std::move(buf
));
225 RefPtr
<PGMPChild::GetModulesTrustPromise
> SendGetModulesTrust(
226 ModulePaths
&& aModules
, bool aRunAtNormalPriority
) {
228 return PGMPChild::GetModulesTrustPromise::CreateAndReject(
229 ipc::ResponseRejectReason::SendError
, __func__
);
231 return sChild
->SendGetModulesTrust(std::move(aModules
), aRunAtNormalPriority
);
235 GMPThreadImpl::GMPThreadImpl() : mMutex("GMPThreadImpl"), mThread("GMPThread") {
236 MOZ_COUNT_CTOR(GMPThread
);
239 GMPThreadImpl::~GMPThreadImpl() { MOZ_COUNT_DTOR(GMPThread
); }
241 void GMPThreadImpl::Post(GMPTask
* aTask
) {
242 MutexAutoLock
lock(mMutex
);
244 if (!mThread
.IsRunning()) {
245 bool started
= mThread
.Start();
247 NS_WARNING("Unable to start GMPThread!");
252 RefPtr
<GMPRunnable
> r
= new GMPRunnable(aTask
);
253 mThread
.message_loop()->PostTask(
254 NewRunnableMethod("gmp::GMPRunnable::Run", r
.get(), &GMPRunnable::Run
));
257 void GMPThreadImpl::Join() {
259 MutexAutoLock
lock(mMutex
);
260 if (mThread
.IsRunning()) {
267 GMPMutexImpl::GMPMutexImpl() : mMonitor("gmp-mutex") {
268 MOZ_COUNT_CTOR(GMPMutexImpl
);
271 GMPMutexImpl::~GMPMutexImpl() { MOZ_COUNT_DTOR(GMPMutexImpl
); }
273 void GMPMutexImpl::Destroy() { delete this; }
275 MOZ_PUSH_IGNORE_THREAD_SAFETY
276 void GMPMutexImpl::Acquire() { mMonitor
.Enter(); }
278 void GMPMutexImpl::Release() { mMonitor
.Exit(); }
279 MOZ_POP_THREAD_SAFETY
281 GMPTask
* NewGMPTask(std::function
<void()>&& aFunction
) {
282 class Task
: public GMPTask
{
284 explicit Task(std::function
<void()>&& aFunction
)
285 : mFunction(std::move(aFunction
)) {}
286 void Destroy() override
{ delete this; }
287 ~Task() override
= default;
288 void Run() override
{ mFunction(); }
291 std::function
<void()> mFunction
;
293 return new Task(std::move(aFunction
));
296 } // namespace mozilla::gmp