1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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/. */
9 #include "mozilla/Attributes.h"
10 #include "nsExceptionHandler.h"
11 #include "gmp-entrypoints.h"
15 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
16 # include "mozilla/sandboxTarget.h"
17 # include "mozilla/sandboxing/SandboxInitialization.h"
18 # include "mozilla/sandboxing/sandboxLogging.h"
20 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
21 # include "mozilla/Sandbox.h"
22 # include "mozilla/SandboxInfo.h"
23 # include "mozilla/SandboxProfilerObserver.h"
32 namespace mozilla::gmp
{
33 class PassThroughGMPAdapter
: public GMPAdapter
{
35 ~PassThroughGMPAdapter() override
{
36 // Ensure we're always shutdown, even if caller forgets to call
41 void SetAdaptee(PRLibrary
* aLib
) override
{ mLib
= aLib
; }
43 GMPErr
GMPInit(const GMPPlatformAPI
* aPlatformAPI
) override
{
44 if (NS_WARN_IF(!mLib
)) {
45 MOZ_CRASH("Missing library!");
48 GMPInitFunc initFunc
=
49 reinterpret_cast<GMPInitFunc
>(PR_FindFunctionSymbol(mLib
, "GMPInit"));
51 MOZ_CRASH("Missing init method!");
52 return GMPNotImplementedErr
;
54 return initFunc(aPlatformAPI
);
57 GMPErr
GMPGetAPI(const char* aAPIName
, void* aHostAPI
, void** aPluginAPI
,
58 const nsACString
& /* aKeySystem */) override
{
62 GMPGetAPIFunc getapiFunc
= reinterpret_cast<GMPGetAPIFunc
>(
63 PR_FindFunctionSymbol(mLib
, "GMPGetAPI"));
65 return GMPNotImplementedErr
;
67 return getapiFunc(aAPIName
, aHostAPI
, aPluginAPI
);
70 void GMPShutdown() override
{
72 GMPShutdownFunc shutdownFunc
= reinterpret_cast<GMPShutdownFunc
>(
73 PR_FindFunctionSymbol(mLib
, "GMPShutdown"));
77 PR_UnloadLibrary(mLib
);
83 PRLibrary
* mLib
= nullptr;
86 bool GMPLoader::Load(const char* aUTF8LibPath
, uint32_t aUTF8LibPathLen
,
87 const GMPPlatformAPI
* aPlatformAPI
, GMPAdapter
* aAdapter
) {
88 CrashReporter::AutoRecordAnnotation
autoLibPath(
89 CrashReporter::Annotation::GMPLibraryPath
,
90 nsDependentCString(aUTF8LibPath
));
92 if (!getenv("MOZ_DISABLE_GMP_SANDBOX") && mSandboxStarter
&&
93 !mSandboxStarter
->Start(aUTF8LibPath
)) {
94 MOZ_CRASH("Cannot start sandbox!");
101 int pathLen
= MultiByteToWideChar(CP_UTF8
, 0, aUTF8LibPath
, -1, nullptr, 0);
103 MOZ_CRASH("Cannot get path length as wide char!");
107 auto widePath
= MakeUnique
<wchar_t[]>(pathLen
);
108 if (MultiByteToWideChar(CP_UTF8
, 0, aUTF8LibPath
, -1, widePath
.get(),
110 MOZ_CRASH("Cannot convert path to wide char!");
114 libSpec
.value
.pathname_u
= widePath
.get();
115 libSpec
.type
= PR_LibSpec_PathnameU
;
117 libSpec
.value
.pathname
= aUTF8LibPath
;
118 libSpec
.type
= PR_LibSpec_Pathname
;
120 PRLibrary
* lib
= PR_LoadLibraryWithFlags(libSpec
, 0);
122 MOZ_CRASH_UNSAFE_PRINTF("Cannot load plugin as library %d %d",
123 PR_GetError(), PR_GetOSError());
127 mAdapter
.reset((!aAdapter
) ? new PassThroughGMPAdapter() : aAdapter
);
128 mAdapter
->SetAdaptee(lib
);
130 if (mAdapter
->GMPInit(aPlatformAPI
) != GMPNoErr
) {
131 MOZ_CRASH("Cannot initialize plugin adapter!");
138 GMPErr
GMPLoader::GetAPI(const char* aAPIName
, void* aHostAPI
,
139 void** aPluginAPI
, const nsACString
& aKeySystem
) {
140 return mAdapter
->GMPGetAPI(aAPIName
, aHostAPI
, aPluginAPI
, aKeySystem
);
143 void GMPLoader::Shutdown() {
145 mAdapter
->GMPShutdown();
149 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
150 class WinSandboxStarter
: public mozilla::gmp::SandboxStarter
{
152 bool Start(const char* aLibPath
) override
{
153 // Cause advapi32 to load before the sandbox is turned on, as
154 // Widevine version 970 and later require it and the sandbox
155 // blocks it on Win7.
156 unsigned int dummy_rand
;
159 mozilla::SandboxTarget::Instance()->StartSandbox();
165 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
167 class LinuxSandboxStarter
: public mozilla::gmp::SandboxStarter
{
169 LinuxSandboxStarter() = default;
170 friend mozilla::detail::UniqueSelector
<LinuxSandboxStarter
>::SingleObject
171 mozilla::MakeUnique
<LinuxSandboxStarter
>();
174 static UniquePtr
<SandboxStarter
> Make() {
175 if (mozilla::SandboxInfo::Get().CanSandboxMedia()) {
176 return MakeUnique
<LinuxSandboxStarter
>();
178 // Sandboxing isn't possible, but the parent has already
179 // checked that this plugin doesn't require it. (Bug 1074561)
182 bool Start(const char* aLibPath
) override
{
183 RegisterProfilerObserversForSandboxProfiler();
184 mozilla::SetMediaPluginSandbox(aLibPath
);
188 } // anonymous namespace
189 #endif // XP_LINUX && MOZ_SANDBOX
191 static UniquePtr
<SandboxStarter
> MakeSandboxStarter() {
192 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
193 return mozilla::MakeUnique
<WinSandboxStarter
>();
194 #elif defined(XP_LINUX) && defined(MOZ_SANDBOX)
195 return LinuxSandboxStarter::Make();
201 GMPLoader::GMPLoader() : mSandboxStarter(MakeSandboxStarter()) {}
203 bool GMPLoader::CanSandbox() const { return !!mSandboxStarter
; }
205 } // namespace mozilla::gmp