Bug 1842773 - Part 5: Add ArrayBuffer.prototype.{maxByteLength,resizable} getters...
[gecko.git] / dom / media / gmp / GMPLoader.cpp
blob9fa7756165e4c11a76404d311e3295990089611f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=4 et :
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/. */
7 #include "GMPLoader.h"
8 #include <stdio.h>
9 #include "mozilla/Attributes.h"
10 #include "nsExceptionHandler.h"
11 #include "gmp-entrypoints.h"
12 #include "prlink.h"
13 #include "prenv.h"
14 #include "prerror.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"
19 #endif
20 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
21 # include "mozilla/Sandbox.h"
22 # include "mozilla/SandboxInfo.h"
23 #endif
25 #include <string>
27 #ifdef XP_WIN
28 # include <windows.h>
29 #endif
31 namespace mozilla::gmp {
32 class PassThroughGMPAdapter : public GMPAdapter {
33 public:
34 ~PassThroughGMPAdapter() override {
35 // Ensure we're always shutdown, even if caller forgets to call
36 // GMPShutdown().
37 GMPShutdown();
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!");
45 return GMPGenericErr;
47 GMPInitFunc initFunc =
48 reinterpret_cast<GMPInitFunc>(PR_FindFunctionSymbol(mLib, "GMPInit"));
49 if (!initFunc) {
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 {
58 if (!mLib) {
59 return GMPGenericErr;
61 GMPGetAPIFunc getapiFunc = reinterpret_cast<GMPGetAPIFunc>(
62 PR_FindFunctionSymbol(mLib, "GMPGetAPI"));
63 if (!getapiFunc) {
64 return GMPNotImplementedErr;
66 return getapiFunc(aAPIName, aHostAPI, aPluginAPI);
69 void GMPShutdown() override {
70 if (mLib) {
71 GMPShutdownFunc shutdownFunc = reinterpret_cast<GMPShutdownFunc>(
72 PR_FindFunctionSymbol(mLib, "GMPShutdown"));
73 if (shutdownFunc) {
74 shutdownFunc();
76 PR_UnloadLibrary(mLib);
77 mLib = nullptr;
81 private:
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!");
94 return false;
97 // Load the GMP.
98 PRLibSpec libSpec;
99 #ifdef XP_WIN
100 int pathLen = MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, nullptr, 0);
101 if (pathLen == 0) {
102 MOZ_CRASH("Cannot get path length as wide char!");
103 return false;
106 auto widePath = MakeUnique<wchar_t[]>(pathLen);
107 if (MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, widePath.get(),
108 pathLen) == 0) {
109 MOZ_CRASH("Cannot convert path to wide char!");
110 return false;
113 libSpec.value.pathname_u = widePath.get();
114 libSpec.type = PR_LibSpec_PathnameU;
115 #else
116 libSpec.value.pathname = aUTF8LibPath;
117 libSpec.type = PR_LibSpec_Pathname;
118 #endif
119 PRLibrary* lib = PR_LoadLibraryWithFlags(libSpec, 0);
120 if (!lib) {
121 MOZ_CRASH_UNSAFE_PRINTF("Cannot load plugin as library %d %d",
122 PR_GetError(), PR_GetOSError());
123 return false;
126 mAdapter.reset((!aAdapter) ? new PassThroughGMPAdapter() : aAdapter);
127 mAdapter->SetAdaptee(lib);
129 if (mAdapter->GMPInit(aPlatformAPI) != GMPNoErr) {
130 MOZ_CRASH("Cannot initialize plugin adapter!");
131 return false;
134 return true;
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() {
143 if (mAdapter) {
144 mAdapter->GMPShutdown();
148 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
149 class WinSandboxStarter : public mozilla::gmp::SandboxStarter {
150 public:
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;
156 rand_s(&dummy_rand);
158 mozilla::SandboxTarget::Instance()->StartSandbox();
159 return true;
162 #endif
164 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
165 namespace {
166 class LinuxSandboxStarter : public mozilla::gmp::SandboxStarter {
167 private:
168 LinuxSandboxStarter() = default;
169 friend mozilla::detail::UniqueSelector<LinuxSandboxStarter>::SingleObject
170 mozilla::MakeUnique<LinuxSandboxStarter>();
172 public:
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)
179 return nullptr;
181 bool Start(const char* aLibPath) override {
182 mozilla::SetMediaPluginSandbox(aLibPath);
183 return true;
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();
194 #else
195 return nullptr;
196 #endif
199 GMPLoader::GMPLoader() : mSandboxStarter(MakeSandboxStarter()) {}
201 bool GMPLoader::CanSandbox() const { return !!mSandboxStarter; }
203 } // namespace mozilla::gmp