Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/gmp/GMPChild.cpp
Line
Count
Source (jump to first uncovered line)
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 "GMPChild.h"
7
#include "GMPContentChild.h"
8
#include "GMPProcessChild.h"
9
#include "GMPLoader.h"
10
#include "GMPVideoDecoderChild.h"
11
#include "GMPVideoEncoderChild.h"
12
#include "GMPVideoHost.h"
13
#include "nsDebugImpl.h"
14
#include "nsExceptionHandler.h"
15
#include "nsIFile.h"
16
#include "nsXULAppAPI.h"
17
#include "gmp-video-decode.h"
18
#include "gmp-video-encode.h"
19
#include "GMPPlatform.h"
20
#include "mozilla/Algorithm.h"
21
#include "mozilla/ipc/CrashReporterClient.h"
22
#include "mozilla/ipc/ProcessChild.h"
23
#include "GMPUtils.h"
24
#include "prio.h"
25
#include "base/task.h"
26
#include "base/command_line.h"
27
#include "ChromiumCDMAdapter.h"
28
#include "GMPLog.h"
29
30
using namespace mozilla::ipc;
31
32
#ifdef XP_WIN
33
#include <stdlib.h> // for _exit()
34
#include "WinUtils.h"
35
#else
36
#include <unistd.h> // for _exit()
37
#endif
38
39
#if defined(MOZ_GMP_SANDBOX)
40
#if defined(XP_MACOSX)
41
#include "mozilla/Sandbox.h"
42
#endif
43
#endif
44
45
namespace mozilla {
46
47
#undef LOG
48
#undef LOGD
49
50
extern LogModule* GetGMPLog();
51
0
#define LOG(level, x, ...) MOZ_LOG(GetGMPLog(), (level), (x, ##__VA_ARGS__))
52
0
#define LOGD(x, ...) LOG(mozilla::LogLevel::Debug, "GMPChild[pid=%d] " x, (int)base::GetCurrentProcId(), ##__VA_ARGS__)
53
54
namespace gmp {
55
56
GMPChild::GMPChild()
57
  : mGMPMessageLoop(MessageLoop::current())
58
  , mGMPLoader(nullptr)
59
0
{
60
0
  LOGD("GMPChild ctor");
61
0
  nsDebugImpl::SetMultiprocessMode("GMP");
62
0
}
63
64
GMPChild::~GMPChild()
65
0
{
66
0
  LOGD("GMPChild dtor");
67
0
}
68
69
static bool
70
GetFileBase(const nsAString& aPluginPath,
71
            nsCOMPtr<nsIFile>& aLibDirectory,
72
            nsCOMPtr<nsIFile>& aFileBase,
73
            nsAutoString& aBaseName)
74
0
{
75
0
  nsresult rv = NS_NewLocalFile(aPluginPath,
76
0
                                true, getter_AddRefs(aFileBase));
77
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
78
0
    return false;
79
0
  }
80
0
81
0
  if (NS_WARN_IF(NS_FAILED(aFileBase->Clone(getter_AddRefs(aLibDirectory))))) {
82
0
    return false;
83
0
  }
84
0
85
0
  nsCOMPtr<nsIFile> parent;
86
0
  rv = aFileBase->GetParent(getter_AddRefs(parent));
87
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
88
0
    return false;
89
0
  }
90
0
91
0
  nsAutoString parentLeafName;
92
0
  rv = parent->GetLeafName(parentLeafName);
93
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
94
0
    return false;
95
0
  }
96
0
97
0
  aBaseName = Substring(parentLeafName,
98
0
                        4,
99
0
                        parentLeafName.Length() - 1);
100
0
  return true;
101
0
}
102
103
static bool
104
GetPluginFile(const nsAString& aPluginPath,
105
              nsCOMPtr<nsIFile>& aLibDirectory,
106
              nsCOMPtr<nsIFile>& aLibFile)
107
0
{
108
0
  nsAutoString baseName;
109
0
  GetFileBase(aPluginPath, aLibDirectory, aLibFile, baseName);
110
0
111
#if defined(XP_MACOSX)
112
  nsAutoString binaryName = NS_LITERAL_STRING("lib") + baseName + NS_LITERAL_STRING(".dylib");
113
#elif defined(OS_POSIX)
114
0
  nsAutoString binaryName = NS_LITERAL_STRING("lib") + baseName + NS_LITERAL_STRING(".so");
115
#elif defined(XP_WIN)
116
  nsAutoString binaryName =                            baseName + NS_LITERAL_STRING(".dll");
117
#else
118
#error not defined
119
#endif
120
  aLibFile->AppendRelativePath(binaryName);
121
0
  return true;
122
0
}
123
124
static bool
125
GetPluginFile(const nsAString& aPluginPath,
126
              nsCOMPtr<nsIFile>& aLibFile)
127
0
{
128
0
  nsCOMPtr<nsIFile> unusedlibDir;
129
0
  return GetPluginFile(aPluginPath, unusedlibDir, aLibFile);
130
0
}
131
132
#if defined(XP_MACOSX)
133
static nsCString
134
GetNativeTarget(nsIFile* aFile)
135
{
136
  bool isLink;
137
  nsCString path;
138
  aFile->IsSymlink(&isLink);
139
  if (isLink) {
140
    aFile->GetNativeTarget(path);
141
  } else {
142
    aFile->GetNativePath(path);
143
  }
144
  return path;
145
}
146
147
#if defined(MOZ_GMP_SANDBOX)
148
static bool
149
GetPluginPaths(const nsAString& aPluginPath,
150
               nsCString &aPluginDirectoryPath,
151
               nsCString &aPluginFilePath)
152
{
153
  nsCOMPtr<nsIFile> libDirectory, libFile;
154
  if (!GetPluginFile(aPluginPath, libDirectory, libFile)) {
155
    return false;
156
  }
157
158
  // Mac sandbox rules expect paths to actual files and directories -- not
159
  // soft links.
160
  libDirectory->Normalize();
161
  aPluginDirectoryPath = GetNativeTarget(libDirectory);
162
163
  libFile->Normalize();
164
  aPluginFilePath = GetNativeTarget(libFile);
165
166
  return true;
167
}
168
169
static bool
170
GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath)
171
{
172
  nsAutoCString appPath;
173
  nsAutoCString appBinaryPath(
174
    (CommandLine::ForCurrentProcess()->argv()[0]).c_str());
175
176
  nsAutoCString::const_iterator start, end;
177
  appBinaryPath.BeginReading(start);
178
  appBinaryPath.EndReading(end);
179
  if (RFindInReadable(NS_LITERAL_CSTRING(".app/Contents/MacOS/"), start, end)) {
180
    end = start;
181
    ++end; ++end; ++end; ++end;
182
    appBinaryPath.BeginReading(start);
183
    appPath.Assign(Substring(start, end));
184
  } else {
185
    return false;
186
  }
187
188
  nsCOMPtr<nsIFile> app, appBinary;
189
  nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appPath),
190
                                true, getter_AddRefs(app));
191
  if (NS_WARN_IF(NS_FAILED(rv))) {
192
    return false;
193
  }
194
  rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appBinaryPath),
195
                       true, getter_AddRefs(appBinary));
196
  if (NS_WARN_IF(NS_FAILED(rv))) {
197
    return false;
198
  }
199
200
  // Mac sandbox rules expect paths to actual files and directories -- not
201
  // soft links.
202
  aAppPath = GetNativeTarget(app);
203
  appBinaryPath = GetNativeTarget(appBinary);
204
205
  return true;
206
}
207
208
bool
209
GMPChild::SetMacSandboxInfo(MacSandboxPluginType aPluginType)
210
{
211
  if (!mGMPLoader) {
212
    return false;
213
  }
214
  nsAutoCString pluginDirectoryPath, pluginFilePath;
215
  if (!GetPluginPaths(mPluginPath, pluginDirectoryPath, pluginFilePath)) {
216
    return false;
217
  }
218
  nsAutoCString appPath, appBinaryPath;
219
  if (!GetAppPaths(appPath, appBinaryPath)) {
220
    return false;
221
  }
222
223
  MacSandboxInfo info;
224
  info.type = MacSandboxType_Plugin;
225
  info.shouldLog = Preferences::GetBool("security.sandbox.logging.enabled") ||
226
                   PR_GetEnv("MOZ_SANDBOX_LOGGING");
227
  info.pluginInfo.type = aPluginType;
228
  info.pluginInfo.pluginPath.assign(pluginDirectoryPath.get());
229
  info.pluginInfo.pluginBinaryPath.assign(pluginFilePath.get());
230
  info.appPath.assign(appPath.get());
231
  info.appBinaryPath.assign(appBinaryPath.get());
232
233
  mGMPLoader->SetSandboxInfo(&info);
234
  return true;
235
}
236
#endif // MOZ_GMP_SANDBOX
237
#endif // XP_MACOSX
238
239
bool
240
GMPChild::Init(const nsAString& aPluginPath,
241
               base::ProcessId aParentPid,
242
               MessageLoop* aIOLoop,
243
               IPC::Channel* aChannel)
244
0
{
245
0
  LOGD("%s pluginPath=%s", __FUNCTION__, NS_ConvertUTF16toUTF8(aPluginPath).get());
246
0
247
0
  if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
248
0
    return false;
249
0
  }
250
0
251
0
  CrashReporterClient::InitSingleton(this);
252
0
253
0
  mPluginPath = aPluginPath;
254
0
255
0
  return true;
256
0
}
257
258
mozilla::ipc::IPCResult
259
GMPChild::RecvProvideStorageId(const nsCString& aStorageId)
260
0
{
261
0
  LOGD("%s", __FUNCTION__);
262
0
  mStorageId = aStorageId;
263
0
  return IPC_OK();
264
0
}
265
266
GMPErr
267
GMPChild::GetAPI(const char* aAPIName,
268
                 void* aHostAPI,
269
                 void** aPluginAPI,
270
                 uint32_t aDecryptorId)
271
0
{
272
0
  if (!mGMPLoader) {
273
0
    return GMPGenericErr;
274
0
  }
275
0
  return mGMPLoader->GetAPI(aAPIName, aHostAPI, aPluginAPI, aDecryptorId);
276
0
}
277
278
mozilla::ipc::IPCResult
279
GMPChild::RecvPreloadLibs(const nsCString& aLibs)
280
0
{
281
#ifdef XP_WIN
282
  // Pre-load DLLs that need to be used by the EME plugin but that can't be
283
  // loaded after the sandbox has started
284
  // Items in this must be lowercase!
285
  constexpr static const char16_t* whitelist[] = {
286
    u"dxva2.dll", // Get monitor information
287
    u"evr.dll", // MFGetStrideForBitmapInfoHeader
288
    u"mfplat.dll", // MFCreateSample, MFCreateAlignedMemoryBuffer, MFCreateMediaType
289
    u"msmpeg2vdec.dll", // H.264 decoder
290
    u"psapi.dll", // For GetMappedFileNameW, see bug 1383611
291
  };
292
  constexpr static bool (*IsASCII)(const char16_t*) = NS_IsAscii;
293
  static_assert(AllOf(std::begin(whitelist), std::end(whitelist), IsASCII),
294
                "Items in the whitelist must not contain non-ASCII "
295
                "characters!");
296
297
  nsTArray<nsCString> libs;
298
  SplitAt(", ", aLibs, libs);
299
  for (nsCString lib : libs) {
300
    ToLowerCase(lib);
301
    for (const char16_t* whiteListedLib : whitelist) {
302
      if (nsDependentString(whiteListedLib).EqualsASCII(lib.Data(),
303
                                                        lib.Length())) {
304
        LoadLibraryW(char16ptr_t(whiteListedLib));
305
        break;
306
      }
307
    }
308
  }
309
#endif
310
0
  return IPC_OK();
311
0
}
312
313
bool
314
GMPChild::ResolveLinks(nsCOMPtr<nsIFile>& aPath)
315
0
{
316
#if defined(XP_WIN)
317
  return widget::WinUtils::ResolveJunctionPointsAndSymLinks(aPath);
318
#elif defined(XP_MACOSX)
319
  nsCString targetPath = GetNativeTarget(aPath);
320
  nsCOMPtr<nsIFile> newFile;
321
  if (NS_WARN_IF(NS_FAILED(
322
        NS_NewNativeLocalFile(targetPath, true, getter_AddRefs(newFile))))) {
323
    return false;
324
  }
325
  aPath = newFile;
326
  return true;
327
#else
328
  return true;
329
0
#endif
330
0
}
331
332
bool
333
GMPChild::GetUTF8LibPath(nsACString& aOutLibPath)
334
0
{
335
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
336
  nsAutoCString pluginDirectoryPath, pluginFilePath;
337
  if (!GetPluginPaths(mPluginPath, pluginDirectoryPath, pluginFilePath)) {
338
    MOZ_CRASH("Error scanning plugin path");
339
  }
340
  aOutLibPath.Assign(pluginFilePath);
341
  return true;
342
#else
343
  nsCOMPtr<nsIFile> libFile;
344
0
  if (!GetPluginFile(mPluginPath, libFile)) {
345
0
    return false;
346
0
  }
347
0
348
0
  if (!FileExists(libFile)) {
349
0
    NS_WARNING("Can't find GMP library file!");
350
0
    return false;
351
0
  }
352
0
353
0
  nsAutoString path;
354
0
  libFile->GetPath(path);
355
0
  aOutLibPath = NS_ConvertUTF16toUTF8(path);
356
0
357
0
  return true;
358
0
#endif
359
0
}
360
361
#if defined(XP_WIN)
362
#define FIREFOX_FILE NS_LITERAL_STRING("firefox.exe")
363
#define XUL_LIB_FILE NS_LITERAL_STRING("xul.dll")
364
#elif defined(XP_MACOSX)
365
#define FIREFOX_FILE NS_LITERAL_STRING("firefox")
366
#define XUL_LIB_FILE NS_LITERAL_STRING("XUL")
367
#else
368
#define FIREFOX_FILE NS_LITERAL_STRING("firefox")
369
#define XUL_LIB_FILE NS_LITERAL_STRING("libxul.so")
370
#endif
371
372
#if defined(XP_MACOSX)
373
static bool
374
GetFirefoxAppPath(nsCOMPtr<nsIFile> aPluginContainerPath,
375
                  nsCOMPtr<nsIFile>& aOutFirefoxAppPath)
376
{
377
  // aPluginContainerPath will end with something like:
378
  // xxxx/NightlyDebug.app/Contents/MacOS/plugin-container.app/Contents/MacOS/plugin-container
379
  MOZ_ASSERT(aPluginContainerPath);
380
  nsCOMPtr<nsIFile> path = aPluginContainerPath;
381
  for (int i = 0; i < 4; i++) {
382
    nsCOMPtr<nsIFile> parent;
383
    if (NS_WARN_IF(NS_FAILED(path->GetParent(getter_AddRefs(parent))))) {
384
      return false;
385
    }
386
    path = parent;
387
  }
388
  MOZ_ASSERT(path);
389
  aOutFirefoxAppPath = path;
390
  return true;
391
}
392
393
static bool
394
GetSigPath(const int aRelativeLayers,
395
           const nsString& aTargetSigFileName,
396
           nsCOMPtr<nsIFile> aExecutablePath,
397
           nsCOMPtr<nsIFile>& aOutSigPath)
398
{
399
  // The sig file will be located in
400
  // xxxx/NightlyDebug.app/Contents/Resources/XUL.sig
401
  // xxxx/NightlyDebug.app/Contents/Resources/firefox.sig
402
  // xxxx/NightlyDebug.app/Contents/MacOS/plugin-container.app/Contents/Resources/plugin-container.sig
403
  // On MacOS the sig file is a few parent directories up from
404
  // its executable file.
405
  // Start to search the path from the path of the executable file we provided.
406
  MOZ_ASSERT(aExecutablePath);
407
  nsCOMPtr<nsIFile> path = aExecutablePath;
408
  for (int i = 0; i < aRelativeLayers; i++) {
409
    nsCOMPtr<nsIFile> parent;
410
    if (NS_WARN_IF(NS_FAILED(path->GetParent(getter_AddRefs(parent))))) {
411
      return false;
412
    }
413
    path = parent;
414
  }
415
  MOZ_ASSERT(path);
416
  aOutSigPath = path;
417
  return NS_SUCCEEDED(path->Append(NS_LITERAL_STRING("Resources"))) &&
418
         NS_SUCCEEDED(path->Append(aTargetSigFileName));
419
}
420
#endif
421
422
nsTArray<Pair<nsCString, nsCString>>
423
GMPChild::MakeCDMHostVerificationPaths()
424
0
{
425
0
  // Record the file path and its sig file path.
426
0
  nsTArray<Pair<nsCString, nsCString>> paths;
427
0
  // Plugin binary path.
428
0
  nsCOMPtr<nsIFile> path;
429
0
  nsString str;
430
0
  if (GetPluginFile(mPluginPath, path) && FileExists(path) &&
431
0
      ResolveLinks(path) && NS_SUCCEEDED(path->GetPath(str))) {
432
0
    paths.AppendElement(
433
0
      MakePair(nsCString(NS_ConvertUTF16toUTF8(str)),
434
0
               nsCString(NS_ConvertUTF16toUTF8(str) + NS_LITERAL_CSTRING(".sig"))));
435
0
  }
436
0
437
0
  // Plugin-container binary path.
438
0
  // Note: clang won't let us initialize an nsString from a wstring, so we
439
0
  // need to go through UTF8 to get to an nsString.
440
0
  const std::string pluginContainer =
441
0
    WideToUTF8(CommandLine::ForCurrentProcess()->program());
442
0
  path = nullptr;
443
0
  str = NS_ConvertUTF8toUTF16(nsDependentCString(pluginContainer.c_str()));
444
0
  if (NS_SUCCEEDED(NS_NewLocalFile(str,
445
0
                                   true, /* aFollowLinks */
446
0
                                   getter_AddRefs(path))) &&
447
0
      FileExists(path) && ResolveLinks(path) &&
448
0
      NS_SUCCEEDED(path->GetPath(str))) {
449
0
    nsCString filePath = NS_ConvertUTF16toUTF8(str);
450
0
    nsCString sigFilePath;
451
#if defined(XP_MACOSX)
452
    nsCOMPtr<nsIFile> sigFile;
453
    if (GetSigPath(2, NS_LITERAL_STRING("plugin-container.sig"), path, sigFile) &&
454
        NS_SUCCEEDED(sigFile->GetPath(str))) {
455
      sigFilePath = NS_ConvertUTF16toUTF8(str);
456
    } else {
457
      // Cannot successfully get the sig file path.
458
      // Assume it is located at the same place as plugin-container alternatively.
459
      sigFilePath = nsCString(NS_ConvertUTF16toUTF8(str) +
460
                              NS_LITERAL_CSTRING(".sig"));
461
    }
462
#else
463
    sigFilePath = nsCString(NS_ConvertUTF16toUTF8(str) +
464
0
                            NS_LITERAL_CSTRING(".sig"));
465
0
#endif
466
0
    paths.AppendElement(
467
0
      MakePair(std::move(filePath),
468
0
               std::move(sigFilePath)));
469
0
  } else {
470
0
    // Without successfully determining plugin-container's path, we can't
471
0
    // determine libxul's or Firefox's. So give up.
472
0
    return paths;
473
0
  }
474
0
475
0
  // Firefox application binary path.
476
0
  nsCOMPtr<nsIFile> appDir;
477
#if defined(XP_MACOSX)
478
  // On MacOS the firefox binary is a few parent directories up from
479
  // plugin-container.
480
  if (GetFirefoxAppPath(path, appDir) &&
481
      NS_SUCCEEDED(appDir->Clone(getter_AddRefs(path))) &&
482
      NS_SUCCEEDED(path->Append(FIREFOX_FILE)) && FileExists(path) &&
483
      ResolveLinks(path) && NS_SUCCEEDED(path->GetPath(str))) {
484
    nsCString filePath = NS_ConvertUTF16toUTF8(str);
485
    nsCString sigFilePath;
486
    nsCOMPtr<nsIFile> sigFile;
487
    if (GetSigPath(2, NS_LITERAL_STRING("firefox.sig"), path, sigFile) &&
488
        NS_SUCCEEDED(sigFile->GetPath(str))) {
489
      sigFilePath = NS_ConvertUTF16toUTF8(str);
490
    } else {
491
      // Cannot successfully get the sig file path.
492
      // Assume it is located at the same place as firefox alternatively.
493
      sigFilePath = nsCString(NS_ConvertUTF16toUTF8(str) +
494
                              NS_LITERAL_CSTRING(".sig"));
495
    }
496
    paths.AppendElement(
497
      MakePair(std::move(filePath),
498
               std::move(sigFilePath)));
499
  }
500
#else
501
  // Note: re-using 'path' var here, as on Windows/Linux we assume Firefox
502
0
  // executable is in the same directory as plugin-container.
503
0
  if (NS_SUCCEEDED(path->GetParent(getter_AddRefs(appDir))) &&
504
0
      NS_SUCCEEDED(appDir->Clone(getter_AddRefs(path))) &&
505
0
      NS_SUCCEEDED(path->Append(FIREFOX_FILE)) && FileExists(path) &&
506
0
      ResolveLinks(path) && NS_SUCCEEDED(path->GetPath(str))) {
507
0
    paths.AppendElement(
508
0
      MakePair(nsCString(NS_ConvertUTF16toUTF8(str)),
509
0
               nsCString(NS_ConvertUTF16toUTF8(str) + NS_LITERAL_CSTRING(".sig"))));
510
0
  }
511
0
#endif
512
0
  // Libxul path. Note: re-using 'path' var here, as we assume libxul is in
513
0
  // the same directory as Firefox executable.
514
0
  appDir->GetPath(str);
515
0
  if (NS_SUCCEEDED(appDir->Clone(getter_AddRefs(path))) &&
516
0
      NS_SUCCEEDED(path->Append(XUL_LIB_FILE)) && FileExists(path) &&
517
0
      ResolveLinks(path) && NS_SUCCEEDED(path->GetPath(str))) {
518
0
    nsCString filePath = NS_ConvertUTF16toUTF8(str);
519
0
    nsCString sigFilePath;
520
#if defined(XP_MACOSX)
521
    nsCOMPtr<nsIFile> sigFile;
522
    if (GetSigPath(2, NS_LITERAL_STRING("XUL.sig"), path, sigFile) &&
523
        NS_SUCCEEDED(sigFile->GetPath(str))) {
524
      sigFilePath = NS_ConvertUTF16toUTF8(str);
525
    } else {
526
      // Cannot successfully get the sig file path.
527
      // Assume it is located at the same place as XUL alternatively.
528
      sigFilePath = nsCString(NS_ConvertUTF16toUTF8(str) +
529
                              NS_LITERAL_CSTRING(".sig"));
530
    }
531
#else
532
    sigFilePath = nsCString(NS_ConvertUTF16toUTF8(str) +
533
0
                            NS_LITERAL_CSTRING(".sig"));
534
0
#endif
535
0
    paths.AppendElement(
536
0
      MakePair(std::move(filePath),
537
0
               std::move(sigFilePath)));
538
0
  }
539
0
540
0
  return paths;
541
0
}
542
543
static nsCString
544
ToCString(const nsTArray<Pair<nsCString, nsCString>>& aPairs)
545
0
{
546
0
  nsCString result;
547
0
  for (const auto& p : aPairs) {
548
0
    if (!result.IsEmpty()) {
549
0
      result.AppendLiteral(",");
550
0
    }
551
0
    result.Append(nsPrintfCString("(%s,%s)", p.first().get(), p.second().get()));
552
0
  }
553
0
  return result;
554
0
}
555
556
mozilla::ipc::IPCResult
557
GMPChild::AnswerStartPlugin(const nsString& aAdapter)
558
0
{
559
0
  LOGD("%s", __FUNCTION__);
560
0
561
0
  nsCString libPath;
562
0
  if (!GetUTF8LibPath(libPath)) {
563
0
    CrashReporter::AnnotateCrashReport(
564
0
      CrashReporter::Annotation::GMPLibraryPath,
565
0
      NS_ConvertUTF16toUTF8(mPluginPath));
566
0
567
#ifdef XP_WIN
568
    return IPC_FAIL(
569
      this,
570
      nsPrintfCString("Failed to get lib path with error(%d).", GetLastError())
571
        .get());
572
#else
573
0
    return IPC_FAIL(
574
0
      this,
575
0
      "Failed to get lib path.");
576
0
#endif
577
0
  }
578
0
579
0
  auto platformAPI = new GMPPlatformAPI();
580
0
  InitPlatformAPI(*platformAPI, this);
581
0
582
0
  mGMPLoader = MakeUnique<GMPLoader>();
583
0
#if defined(MOZ_GMP_SANDBOX)
584
0
  if (!mGMPLoader->CanSandbox()) {
585
0
    LOGD("%s Can't sandbox GMP, failing", __FUNCTION__);
586
0
    delete platformAPI;
587
0
    return IPC_FAIL(this, "Can't sandbox GMP.");
588
0
  }
589
0
#endif
590
0
  bool isChromium = aAdapter.EqualsLiteral("chromium");
591
#if defined(MOZ_GMP_SANDBOX) && defined(XP_MACOSX)
592
  MacSandboxPluginType pluginType = MacSandboxPluginType_GMPlugin_Default;
593
  if (isChromium) {
594
    pluginType = MacSandboxPluginType_GMPlugin_EME_Widevine;
595
  }
596
  if (!SetMacSandboxInfo(pluginType)) {
597
    NS_WARNING("Failed to set Mac GMP sandbox info");
598
    delete platformAPI;
599
    return IPC_FAIL(
600
      this,
601
      nsPrintfCString("Failed to set Mac GMP sandbox info with plugin type %d.",
602
                      pluginType).get());
603
  }
604
#endif
605
606
0
  GMPAdapter* adapter = nullptr;
607
0
  if (isChromium) {
608
0
    auto&& paths = MakeCDMHostVerificationPaths();
609
0
    GMP_LOG("%s CDM host paths=%s", __func__, ToCString(paths).get());
610
0
    adapter = new ChromiumCDMAdapter(std::move(paths));
611
0
  }
612
0
613
0
  if (!mGMPLoader->Load(libPath.get(),
614
0
                        libPath.Length(),
615
0
                        platformAPI,
616
0
                        adapter)) {
617
0
    NS_WARNING("Failed to load GMP");
618
0
    delete platformAPI;
619
0
    CrashReporter::AnnotateCrashReport(
620
0
      CrashReporter::Annotation::GMPLibraryPath,
621
0
      NS_ConvertUTF16toUTF8(mPluginPath));
622
0
623
#ifdef XP_WIN
624
    return IPC_FAIL(
625
      this,
626
      nsPrintfCString("Failed to load GMP with error(%d).", GetLastError())
627
        .get());
628
#else
629
0
    return IPC_FAIL(
630
0
      this,
631
0
      "Failed to load GMP.");
632
0
#endif
633
0
  }
634
0
635
0
  return IPC_OK();
636
0
}
637
638
MessageLoop*
639
GMPChild::GMPMessageLoop()
640
0
{
641
0
  return mGMPMessageLoop;
642
0
}
643
644
void
645
GMPChild::ActorDestroy(ActorDestroyReason aWhy)
646
0
{
647
0
  LOGD("%s reason=%d", __FUNCTION__, aWhy);
648
0
649
0
  for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) {
650
0
    MOZ_ASSERT_IF(aWhy == NormalShutdown, !mGMPContentChildren[i - 1]->IsUsed());
651
0
    mGMPContentChildren[i - 1]->Close();
652
0
  }
653
0
654
0
  if (mGMPLoader) {
655
0
    mGMPLoader->Shutdown();
656
0
  }
657
0
  if (AbnormalShutdown == aWhy) {
658
0
    NS_WARNING("Abnormal shutdown of GMP process!");
659
0
    ProcessChild::QuickExit();
660
0
  }
661
0
662
0
  CrashReporterClient::DestroySingleton();
663
0
664
0
  XRE_ShutdownChildProcess();
665
0
}
666
667
void
668
GMPChild::ProcessingError(Result aCode, const char* aReason)
669
0
{
670
0
  switch (aCode) {
671
0
    case MsgDropped:
672
0
      _exit(0); // Don't trigger a crash report.
673
0
    case MsgNotKnown:
674
0
      MOZ_CRASH("aborting because of MsgNotKnown");
675
0
    case MsgNotAllowed:
676
0
      MOZ_CRASH("aborting because of MsgNotAllowed");
677
0
    case MsgPayloadError:
678
0
      MOZ_CRASH("aborting because of MsgPayloadError");
679
0
    case MsgProcessingError:
680
0
      MOZ_CRASH("aborting because of MsgProcessingError");
681
0
    case MsgRouteError:
682
0
      MOZ_CRASH("aborting because of MsgRouteError");
683
0
    case MsgValueError:
684
0
      MOZ_CRASH("aborting because of MsgValueError");
685
0
    default:
686
0
      MOZ_CRASH("not reached");
687
0
  }
688
0
}
689
690
PGMPTimerChild*
691
GMPChild::AllocPGMPTimerChild()
692
0
{
693
0
  return new GMPTimerChild(this);
694
0
}
695
696
bool
697
GMPChild::DeallocPGMPTimerChild(PGMPTimerChild* aActor)
698
0
{
699
0
  MOZ_ASSERT(mTimerChild == static_cast<GMPTimerChild*>(aActor));
700
0
  mTimerChild = nullptr;
701
0
  return true;
702
0
}
703
704
GMPTimerChild*
705
GMPChild::GetGMPTimers()
706
0
{
707
0
  if (!mTimerChild) {
708
0
    PGMPTimerChild* sc = SendPGMPTimerConstructor();
709
0
    if (!sc) {
710
0
      return nullptr;
711
0
    }
712
0
    mTimerChild = static_cast<GMPTimerChild*>(sc);
713
0
  }
714
0
  return mTimerChild;
715
0
}
716
717
PGMPStorageChild*
718
GMPChild::AllocPGMPStorageChild()
719
0
{
720
0
  return new GMPStorageChild(this);
721
0
}
722
723
bool
724
GMPChild::DeallocPGMPStorageChild(PGMPStorageChild* aActor)
725
0
{
726
0
  mStorage = nullptr;
727
0
  return true;
728
0
}
729
730
GMPStorageChild*
731
GMPChild::GetGMPStorage()
732
0
{
733
0
  if (!mStorage) {
734
0
    PGMPStorageChild* sc = SendPGMPStorageConstructor();
735
0
    if (!sc) {
736
0
      return nullptr;
737
0
    }
738
0
    mStorage = static_cast<GMPStorageChild*>(sc);
739
0
  }
740
0
  return mStorage;
741
0
}
742
743
mozilla::ipc::IPCResult
744
GMPChild::RecvCrashPluginNow()
745
0
{
746
0
  MOZ_CRASH();
747
0
  return IPC_OK();
748
0
}
749
750
mozilla::ipc::IPCResult
751
GMPChild::RecvCloseActive()
752
0
{
753
0
  for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) {
754
0
    mGMPContentChildren[i - 1]->CloseActive();
755
0
  }
756
0
  return IPC_OK();
757
0
}
758
759
mozilla::ipc::IPCResult
760
GMPChild::RecvInitGMPContentChild(Endpoint<PGMPContentChild>&& aEndpoint)
761
0
{
762
0
  GMPContentChild* child =
763
0
    mGMPContentChildren.AppendElement(new GMPContentChild(this))->get();
764
0
  aEndpoint.Bind(child);
765
0
  return IPC_OK();
766
0
}
767
768
void
769
GMPChild::GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild)
770
0
{
771
0
  for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) {
772
0
    UniquePtr<GMPContentChild>& toDestroy = mGMPContentChildren[i - 1];
773
0
    if (toDestroy.get() == aGMPContentChild) {
774
0
      SendPGMPContentChildDestroyed();
775
0
      RefPtr<DeleteTask<GMPContentChild>> task =
776
0
        new DeleteTask<GMPContentChild>(toDestroy.release());
777
0
      MessageLoop::current()->PostTask(task.forget());
778
0
      mGMPContentChildren.RemoveElementAt(i - 1);
779
0
      break;
780
0
    }
781
0
  }
782
0
}
783
784
} // namespace gmp
785
} // namespace mozilla
786
787
#undef LOG
788
#undef LOGD