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"
31 namespace mozilla::gmp
{
32 class PassThroughGMPAdapter
: public GMPAdapter
{
34 ~PassThroughGMPAdapter() override
{
35 // Ensure we're always shutdown, even if caller forgets to call
40 void SetAdaptee(PRLibrary
* aLib
) override
{ mLib
= aLib
; }
42 GMPErr
GMPInit(const GMPPlatformAPI
* aPlatformAPI
) override
{
43 if (NS_WARN_IF(!mLib
)) {
44 MOZ_CRASH("Missing library!");
47 GMPInitFunc initFunc
=
48 reinterpret_cast<GMPInitFunc
>(PR_FindFunctionSymbol(mLib
, "GMPInit"));
50 MOZ_CRASH("Missing init method!");
51 return GMPNotImplementedErr
;
53 return initFunc(aPlatformAPI
);
56 GMPErr
GMPGetAPI(const char* aAPIName
, void* aHostAPI
, void** aPluginAPI
,
57 const nsACString
& /* aKeySystem */) override
{
61 GMPGetAPIFunc getapiFunc
= reinterpret_cast<GMPGetAPIFunc
>(
62 PR_FindFunctionSymbol(mLib
, "GMPGetAPI"));
64 return GMPNotImplementedErr
;
66 return getapiFunc(aAPIName
, aHostAPI
, aPluginAPI
);
69 void GMPShutdown() override
{
71 GMPShutdownFunc shutdownFunc
= reinterpret_cast<GMPShutdownFunc
>(
72 PR_FindFunctionSymbol(mLib
, "GMPShutdown"));
76 PR_UnloadLibrary(mLib
);
82 PRLibrary
* mLib
= nullptr;
85 bool GMPLoader::Load(const char* aUTF8LibPath
, uint32_t aUTF8LibPathLen
,
86 const GMPPlatformAPI
* aPlatformAPI
, GMPAdapter
* aAdapter
) {
87 CrashReporter::AutoAnnotateCrashReport
autoLibPath(
88 CrashReporter::Annotation::GMPLibraryPath
,
89 nsDependentCString(aUTF8LibPath
));
91 if (!getenv("MOZ_DISABLE_GMP_SANDBOX") && mSandboxStarter
&&
92 !mSandboxStarter
->Start(aUTF8LibPath
)) {
93 MOZ_CRASH("Cannot start sandbox!");
100 int pathLen
= MultiByteToWideChar(CP_UTF8
, 0, aUTF8LibPath
, -1, nullptr, 0);
102 MOZ_CRASH("Cannot get path length as wide char!");
106 auto widePath
= MakeUnique
<wchar_t[]>(pathLen
);
107 if (MultiByteToWideChar(CP_UTF8
, 0, aUTF8LibPath
, -1, widePath
.get(),
109 MOZ_CRASH("Cannot convert path to wide char!");
113 libSpec
.value
.pathname_u
= widePath
.get();
114 libSpec
.type
= PR_LibSpec_PathnameU
;
116 libSpec
.value
.pathname
= aUTF8LibPath
;
117 libSpec
.type
= PR_LibSpec_Pathname
;
119 PRLibrary
* lib
= PR_LoadLibraryWithFlags(libSpec
, 0);
121 MOZ_CRASH_UNSAFE_PRINTF("Cannot load plugin as library %d %d",
122 PR_GetError(), PR_GetOSError());
126 mAdapter
.reset((!aAdapter
) ? new PassThroughGMPAdapter() : aAdapter
);
127 mAdapter
->SetAdaptee(lib
);
129 if (mAdapter
->GMPInit(aPlatformAPI
) != GMPNoErr
) {
130 MOZ_CRASH("Cannot initialize plugin adapter!");
137 GMPErr
GMPLoader::GetAPI(const char* aAPIName
, void* aHostAPI
,
138 void** aPluginAPI
, const nsACString
& aKeySystem
) {
139 return mAdapter
->GMPGetAPI(aAPIName
, aHostAPI
, aPluginAPI
, aKeySystem
);
142 void GMPLoader::Shutdown() {
144 mAdapter
->GMPShutdown();
148 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
149 class WinSandboxStarter
: public mozilla::gmp::SandboxStarter
{
151 bool Start(const char* aLibPath
) override
{
152 // Cause advapi32 to load before the sandbox is turned on, as
153 // Widevine version 970 and later require it and the sandbox
154 // blocks it on Win7.
155 unsigned int dummy_rand
;
158 mozilla::SandboxTarget::Instance()->StartSandbox();
164 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
166 class LinuxSandboxStarter
: public mozilla::gmp::SandboxStarter
{
168 LinuxSandboxStarter() = default;
169 friend mozilla::detail::UniqueSelector
<LinuxSandboxStarter
>::SingleObject
170 mozilla::MakeUnique
<LinuxSandboxStarter
>();
173 static UniquePtr
<SandboxStarter
> Make() {
174 if (mozilla::SandboxInfo::Get().CanSandboxMedia()) {
175 return MakeUnique
<LinuxSandboxStarter
>();
177 // Sandboxing isn't possible, but the parent has already
178 // checked that this plugin doesn't require it. (Bug 1074561)
181 bool Start(const char* aLibPath
) override
{
182 mozilla::SetMediaPluginSandbox(aLibPath
);
186 } // anonymous namespace
187 #endif // XP_LINUX && MOZ_SANDBOX
189 static UniquePtr
<SandboxStarter
> MakeSandboxStarter() {
190 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
191 return mozilla::MakeUnique
<WinSandboxStarter
>();
192 #elif defined(XP_LINUX) && defined(MOZ_SANDBOX)
193 return LinuxSandboxStarter::Make();
199 GMPLoader::GMPLoader() : mSandboxStarter(MakeSandboxStarter()) {}
201 bool GMPLoader::CanSandbox() const { return !!mSandboxStarter
; }
203 } // namespace mozilla::gmp