Bug 1420836 - Part3 - Try to compute the storage id in GMP process and implement RequestStorageId for CDM.
GMPParent has computed the origin salt so I try to pass it to GMPChild.
Then, try to compute the storage id before sandboxing.
Pass the storage id to ChromiumCDMChild by its Init function.
MozReview-Commit-ID: HIur4dH9Hn8
--- a/dom/media/gmp/ChromiumCDMChild.cpp
+++ b/dom/media/gmp/ChromiumCDMChild.cpp
@@ -1,14 +1,15 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ChromiumCDMChild.h"
+#include "CDMStorageIdProvider.h"
#include "GMPContentChild.h"
#include "WidevineUtils.h"
#include "WidevineFileIO.h"
#include "WidevineVideoFrame.h"
#include "GMPLog.h"
#include "GMPPlatform.h"
#include "mozilla/Unused.h"
#include "nsPrintfCString.h"
@@ -22,21 +23,23 @@ namespace gmp {
ChromiumCDMChild::ChromiumCDMChild(GMPContentChild* aPlugin)
: mPlugin(aPlugin)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild:: ctor this=%p", this);
}
void
-ChromiumCDMChild::Init(cdm::ContentDecryptionModule_9* aCDM)
+ChromiumCDMChild::Init(cdm::ContentDecryptionModule_9* aCDM,
+ const nsCString& aStorageId)
{
MOZ_ASSERT(IsOnMessageLoopThread());
mCDM = aCDM;
MOZ_ASSERT(mCDM);
+ mCurrentStorageId = aStorageId;
}
void
ChromiumCDMChild::TimerExpired(void* aContext)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::TimerExpired(context=0x%p)", aContext);
if (mCDM) {
@@ -471,16 +474,36 @@ ChromiumCDMChild::CreateFileIO(cdm::File
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::CreateFileIO()");
if (!mPersistentStateAllowed) {
return nullptr;
}
return new WidevineFileIO(aClient);
}
+void
+ChromiumCDMChild::RequestStorageId(uint32_t aVersion)
+{
+ MOZ_ASSERT(IsOnMessageLoopThread());
+ GMP_LOG("ChromiumCDMChild::RequestStorageId() aVersion = %u", aVersion);
+ // aVersion >= 0x80000000 are reserved.
+ if (aVersion >= 0x80000000) {
+ mCDM->OnStorageId(aVersion, nullptr, 0);
+ return;
+ }
+ if (aVersion > CDMStorageIdProviderBase::kCurrentVersion) {
+ mCDM->OnStorageId(aVersion, nullptr, 0);
+ return;
+ }
+ // mCurrentStorageId will be empty if we compute storage failed.
+ mCDM->OnStorageId(CDMStorageIdProviderBase::kCurrentVersion,
+ reinterpret_cast<const uint8_t*>(mCurrentStorageId.get()),
+ mCurrentStorageId.Length());
+}
+
ChromiumCDMChild::~ChromiumCDMChild()
{
GMP_LOG("ChromiumCDMChild:: dtor this=%p", this);
}
bool
ChromiumCDMChild::IsOnMessageLoopThread()
{
--- a/dom/media/gmp/ChromiumCDMChild.h
+++ b/dom/media/gmp/ChromiumCDMChild.h
@@ -20,17 +20,17 @@ class ChromiumCDMChild : public PChromiu
, public cdm::Host_8
, public cdm::Host_9
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChromiumCDMChild);
explicit ChromiumCDMChild(GMPContentChild* aPlugin);
- void Init(cdm::ContentDecryptionModule_9* aCDM);
+ void Init(cdm::ContentDecryptionModule_9* aCDM, const nsCString& aStorageId);
void TimerExpired(void* aContext);
// cdm::Host_9 implementation
cdm::Buffer* Allocate(uint32_t aCapacity) override;
void SetTimer(int64_t aDelayMs, void* aContext) override;
cdm::Time GetCurrentWallTime() override;
// cdm::Host_9 interface
@@ -66,17 +66,17 @@ public:
uint32_t aServiceIdSize,
const char* aChallenge,
uint32_t aChallengeSize) override {}
void EnableOutputProtection(uint32_t aDesiredProtectionMask) override {}
void QueryOutputProtectionStatus() override {}
void OnDeferredInitializationDone(cdm::StreamType aStreamType,
cdm::Status aDecoderStatus) override {}
// cdm::Host_9 interface
- void RequestStorageId(uint32_t aVersion) override {}
+ void RequestStorageId(uint32_t aVersion) override;
cdm::FileIO* CreateFileIO(cdm::FileIOClient* aClient) override;
// cdm::Host_8 implementation
void OnSessionMessage(const char* aSessionId,
uint32_t aSessionIdSize,
cdm::MessageType aMessageType,
const char* aMessage,
uint32_t aMessageSize,
@@ -157,14 +157,15 @@ protected:
nsTArray<uint32_t> mLoadSessionPromiseIds;
cdm::Size mCodedSize;
nsTArray<ipc::Shmem> mBuffers;
bool mDecoderInitialized = false;
bool mPersistentStateAllowed = false;
bool mDestroyed = false;
+ nsCString mCurrentStorageId;
};
} // namespace gmp
} // namespace mozilla
#endif // ChromiumCDMChild_h_
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -1,14 +1,15 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPChild.h"
+#include "CDMStorageIdProvider.h"
#include "GMPContentChild.h"
#include "GMPProcessChild.h"
#include "GMPLoader.h"
#include "GMPVideoDecoderChild.h"
#include "GMPVideoEncoderChild.h"
#include "GMPVideoHost.h"
#include "nsDebugImpl.h"
#include "nsExceptionHandler.h"
@@ -21,16 +22,20 @@
#include "mozilla/ipc/ProcessChild.h"
#include "GMPUtils.h"
#include "prio.h"
#include "base/task.h"
#include "base/command_line.h"
#include "ChromiumCDMAdapter.h"
#include "GMPLog.h"
+#ifdef SUPPORT_STORAGE_ID
+#include "rlz/lib/machine_id.h"
+#endif
+
using namespace mozilla::ipc;
#ifdef XP_WIN
#include <stdlib.h> // for _exit()
#include "WinUtils.h"
#else
#include <unistd.h> // for _exit()
#endif
@@ -249,16 +254,46 @@ GMPChild::Init(const nsAString& aPluginP
CrashReporterClient::InitSingleton(this);
mPluginPath = aPluginPath;
return true;
}
+mozilla::ipc::IPCResult
+GMPChild::RecvProvideOriginSalt(const nsCString& aOriginSalt)
+{
+ LOGD("%s", __FUNCTION__);
+
+ // Compute the current storage id here before starting gmp sandboxing.
+ // Store it and it will be passed to ChromiumCDMChild.
+ mCurrentStorageId = "";
+#ifdef SUPPORT_STORAGE_ID
+ std::string machineId;
+ if (!rlz_lib::GetMachineId(&machineId)) {
+ LOGD("%s get machineId failed.", __FUNCTION__);
+ return IPC_OK();
+ }
+ std::string originSalt(aOriginSalt.BeginReading(), aOriginSalt.Length());
+ auto provider = CDMStorageIdProviderBase::CreateProvider(CDMStorageIdProviderBase::kCDMRequestLatestVersion);
+ auto factors = MakePrerequisiteFactors(CDMStorageIdProviderBase::kCDMRequestLatestVersion,
+ machineId,
+ originSalt);
+
+ std::string storageId;
+ if (!provider->ComputeStorageId(storageId, *factors)) {
+ LOGD("%s failed to compute storage id.", __FUNCTION__);
+ return IPC_OK();
+ }
+ mCurrentStorageId = storageId.c_str();
+#endif
+ return IPC_OK();
+}
+
GMPErr
GMPChild::GetAPI(const char* aAPIName,
void* aHostAPI,
void** aPluginAPI,
uint32_t aDecryptorId)
{
if (!mGMPLoader) {
return GMPGenericErr;
--- a/dom/media/gmp/GMPChild.h
+++ b/dom/media/gmp/GMPChild.h
@@ -41,16 +41,17 @@ public:
private:
friend class GMPContentChild;
bool ResolveLinks(nsCOMPtr<nsIFile>& aPath);
bool GetUTF8LibPath(nsACString& aOutLibPath);
+ mozilla::ipc::IPCResult RecvProvideOriginSalt(const nsCString& aOriginSalt) override;
mozilla::ipc::IPCResult AnswerStartPlugin(const nsString& aAdapter) override;
mozilla::ipc::IPCResult RecvPreloadLibs(const nsCString& aLibs) override;
PGMPTimerChild* AllocPGMPTimerChild() override;
bool DeallocPGMPTimerChild(PGMPTimerChild* aActor) override;
PGMPStorageChild* AllocPGMPStorageChild() override;
bool DeallocPGMPStorageChild(PGMPStorageChild* aActor) override;
@@ -71,15 +72,16 @@ private:
nsTArray<UniquePtr<GMPContentChild>> mGMPContentChildren;
RefPtr<GMPTimerChild> mTimerChild;
RefPtr<GMPStorageChild> mStorage;
MessageLoop* mGMPMessageLoop;
nsString mPluginPath;
+ nsCString mCurrentStorageId;
UniquePtr<GMPLoader> mGMPLoader;
};
} // namespace gmp
} // namespace mozilla
#endif // GMPChild_h_
--- a/dom/media/gmp/GMPContentChild.cpp
+++ b/dom/media/gmp/GMPContentChild.cpp
@@ -300,17 +300,18 @@ GMPContentChild::RecvPChromiumCDMConstru
return IPC_FAIL_NO_REASON(this);
}
cdm =
new ChromiumCDM8BackwardsCompat(
host9,
static_cast<cdm::ContentDecryptionModule_8*>(cdm));
}
- child->Init(static_cast<cdm::ContentDecryptionModule_9*>(cdm));
+ child->Init(static_cast<cdm::ContentDecryptionModule_9*>(cdm),
+ mGMPChild->mCurrentStorageId);
return IPC_OK();
}
void
GMPContentChild::CloseActive()
{
// Invalidate and remove any remaining API objects.
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -170,16 +170,24 @@ GMPParent::LoadProcess()
if (!opened) {
LOGD("%s: Failed to open channel to new child process", __FUNCTION__);
mProcess->Delete();
mProcess = nullptr;
return NS_ERROR_FAILURE;
}
LOGD("%s: Opened channel to new child process", __FUNCTION__);
+
+ bool ok = SendProvideOriginSalt(mNodeId);
+ if (!ok) {
+ LOGD("%s: Failed to send origin salt to child process", __FUNCTION__);
+ return NS_ERROR_FAILURE;
+ }
+ LOGD("%s: Sent origin salt to child process", __FUNCTION__);
+
#ifdef XP_WIN
if (!mLibs.IsEmpty()) {
bool ok = SendPreloadLibs(mLibs);
if (!ok) {
LOGD("%s: Failed to send preload-libs to child process", __FUNCTION__);
return NS_ERROR_FAILURE;
}
LOGD("%s: Sent preload-libs ('%s') to child process", __FUNCTION__, mLibs.get());
--- a/dom/media/gmp/PGMP.ipdl
+++ b/dom/media/gmp/PGMP.ipdl
@@ -22,15 +22,16 @@ parent:
async PGMPTimer();
async PGMPStorage();
async PGMPContentChildDestroyed();
child:
async CrashPluginNow();
intr StartPlugin(nsString adapter);
+ async ProvideOriginSalt(nsCString originSalt);
async PreloadLibs(nsCString libs);
async CloseActive();
async InitGMPContentChild(Endpoint<PGMPContentChild> endpoint);
};
} // namespace gmp
} // namespace mozilla