Bug 1420836 - Part2 - Add a class to compute the storage id. draft
authorJames Cheng <jacheng@mozilla.com>
Fri, 15 Dec 2017 14:50:38 -0600
changeset 712297 d077e22ab929af875cd74af6874df1af52f30969
parent 712296 da76d066015df7e078459da092958f249e6c22fd
child 712298 ac35e79343152d46308098cf6f4e226e4bb9ab9c
push id93304
push userbmo:jacheng@mozilla.com
push dateFri, 15 Dec 2017 22:09:01 +0000
bugs1420836
milestone59.0a1
Bug 1420836 - Part2 - Add a class to compute the storage id. Every version will have its own prerequisite factor to compute the storage id. If we need to change the storage id computation algorithm, we should specialize the template class and increase the current version. Now, we only have version 1 for computing storage id. MozReview-Commit-ID: 52W2OOmtgI5
dom/media/gmp/CDMStorageIdProvider.cpp
dom/media/gmp/CDMStorageIdProvider.h
dom/media/gmp/moz.build
new file mode 100644
--- /dev/null
+++ b/dom/media/gmp/CDMStorageIdProvider.cpp
@@ -0,0 +1,29 @@
+/* -*- 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 "CDMStorageIdProvider.h"
+
+namespace mozilla {
+
+UniquePtr<CDMStorageIdProviderBase>
+CDMStorageIdProviderBase::CreateProvider(int aVersion)
+{
+  UniquePtr<CDMStorageIdProviderBase> provider;
+  switch (aVersion) {
+    case CDMStorageIdProviderBase::kCDMRequestLatestVersion:
+      provider.reset(new CDMStorageIdProvider<CDMStorageIdProviderBase::kCurrentVersion>());
+      break;
+    case 1: // CDMStorageIdProviderBase::kCurrentVersion
+      provider.reset(new CDMStorageIdProvider<CDMStorageIdProviderBase::kCurrentVersion>());
+      break;
+    default:
+      MOZ_ASSERT(aVersion <= CDMStorageIdProviderBase::kCurrentVersion,
+                 "Creating provider with unsupported version.");
+      break;
+  }
+  return provider;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/gmp/CDMStorageIdProvider.h
@@ -0,0 +1,147 @@
+/* -*- 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/. */
+
+#ifndef CDMStorageIdProvider_h_
+#define CDMStorageIdProvider_h_
+
+#include <string>
+
+#include "mozilla/UniquePtr.h"
+
+#ifdef SUPPORT_STORAGE_ID
+#include "rlz/lib/string_utils.h"
+#include "rlz/sha256.h"
+#endif
+
+/**
+ * CDM will try to request a latest version of storage id.
+ * If the storage id computation algorithm changed, we should increase the kCurrentVersion
+ * and write a template specialization for the new version.
+ * Make sure the ``CreateProvider`` returns the corresponding version of CDMStorageIdProvider.
+ */
+
+namespace mozilla {
+
+class CDMStorageIdProviderBase
+{
+protected:
+  static constexpr const char* kBrowserIdentifier =
+    "mozilla_firefox_gecko";
+
+public:
+  // Should increase the value when the storage id algorithm changed.
+  static constexpr int kCurrentVersion = 1;
+  static constexpr int kCDMRequestLatestVersion = 0;
+
+  struct PrerequisiteFactorsBase
+  {
+    virtual ~PrerequisiteFactorsBase() = default;
+  };
+
+  CDMStorageIdProviderBase() = default;
+
+  virtual ~CDMStorageIdProviderBase() = default;
+
+  virtual bool ComputeStorageId(std::string& aOutStorageId,
+                                const PrerequisiteFactorsBase& aFactors) = 0;
+  virtual int GetVersion() = 0;
+
+  static UniquePtr<CDMStorageIdProviderBase> CreateProvider(int aVersion);
+};
+
+template<int VERSION>
+class CDMStorageIdProvider : public CDMStorageIdProviderBase
+{
+  friend class CDMStorageIdProviderBase;
+
+public:
+  bool ComputeStorageId(std::string& aOutStorageId,
+                        const PrerequisiteFactorsBase& aFactors) override
+  {
+    MOZ_ASSERT_UNREACHABLE("CreateProvider should always return the specialization class of CDMStorageIdProvider");
+    return false;
+  }
+
+  int GetVersion() override { return VERSION; }
+
+  CDMStorageIdProvider(const CDMStorageIdProvider&) = delete;
+  void operator=(const CDMStorageIdProvider&) = delete;
+};
+
+//Current version.
+template<>
+class CDMStorageIdProvider<1> : public CDMStorageIdProviderBase
+{
+  friend class CDMStorageIdProviderBase;
+  template<typename... Args>
+  friend UniquePtr<CDMStorageIdProviderBase::PrerequisiteFactorsBase>
+  MakePrerequisiteFactors(int aVersion, Args&&... aArgs);
+
+  CDMStorageIdProvider() = default;
+
+  struct PrerequisiteFactors : PrerequisiteFactorsBase
+  {
+    PrerequisiteFactors(std::string aMachineId, std::string aOriginSalt)
+      : mMachineId(aMachineId),
+        mOriginSalt(aOriginSalt)
+    {}
+    std::string mMachineId;
+    std::string mOriginSalt;
+  };
+
+public:
+
+  // DO NOT modify the outcome of the ``ComputeStorageId``.
+  // Once the storage id computation should be changed, remember to specialize
+  // the template with the new version of storage id computation.
+  bool ComputeStorageId(std::string& aOutStorageId,
+                        const PrerequisiteFactorsBase& aFactors) override
+  {
+#ifdef SUPPORT_STORAGE_ID
+    SHA256Context ctx;
+    SHA256_Begin(&ctx);
+
+    const auto& factors = static_cast<const PrerequisiteFactors&>(aFactors);
+    std::string input = factors.mMachineId + factors.mOriginSalt + CDMStorageIdProviderBase::kBrowserIdentifier;
+
+    SHA256_Update(&ctx, reinterpret_cast<const unsigned char*>(input.c_str()), input.size());
+    uint8_t digest[SHA256_LENGTH] = {0};
+    unsigned int digestLen = 0;
+    SHA256_End(&ctx, digest, &digestLen, SHA256_LENGTH);
+    if (!rlz_lib::BytesToString(digest, SHA256_LENGTH, &aOutStorageId)) {
+      return false;
+    }
+    return true;
+#else
+    MOZ_ASSERT_UNREACHABLE("This platform does not support computing storage id.");
+    return false;
+#endif
+  }
+
+  int GetVersion() override { return 1; }
+
+  CDMStorageIdProvider(const CDMStorageIdProvider&) = delete;
+  void operator=(const CDMStorageIdProvider&) = delete;
+};
+
+template<typename... Args>
+UniquePtr<CDMStorageIdProviderBase::PrerequisiteFactorsBase>
+MakePrerequisiteFactors(int aVersion, Args&&... aArgs)
+{
+  switch (aVersion) {
+      case CDMStorageIdProviderBase::kCDMRequestLatestVersion:
+        return MakeUnique<CDMStorageIdProvider<CDMStorageIdProviderBase::kCurrentVersion>::PrerequisiteFactors>(Forward<Args>(aArgs)...);
+      case 1: // CDMStorageIdProviderBase::kCurrentVersion
+        return MakeUnique<CDMStorageIdProvider<CDMStorageIdProviderBase::kCurrentVersion>::PrerequisiteFactors>(Forward<Args>(aArgs)...);
+      default:
+        MOZ_ASSERT(aVersion <= CDMStorageIdProviderBase::kCurrentVersion,
+                   "Creating PrerequisiteFactor with unsupported version.");
+        return nullptr;
+  }
+}
+
+} // namespace mozilla
+
+#endif //CDMStorageIdProvider_h_
--- a/dom/media/gmp/moz.build
+++ b/dom/media/gmp/moz.build
@@ -61,16 +61,17 @@ EXPORTS += [
     'GMPVideoi420FrameImpl.h',
     'GMPVideoPlaneImpl.h',
     'widevine-adapter/content_decryption_module.h',
     'widevine-adapter/content_decryption_module_export.h',
     'widevine-adapter/content_decryption_module_ext.h',
 ]
 
 UNIFIED_SOURCES += [
+    'CDMStorageIdProvider.cpp',
     'ChromiumCDMAdapter.cpp',
     'ChromiumCDMCallbackProxy.cpp',
     'ChromiumCDMChild.cpp',
     'ChromiumCDMParent.cpp',
     'ChromiumCDMProxy.cpp',
     'DecryptJob.cpp',
     'GMPChild.cpp',
     'GMPContentChild.cpp',
@@ -115,16 +116,19 @@ IPDL_SOURCES += [
   'PGMPContent.ipdl',
   'PGMPService.ipdl',
   'PGMPStorage.ipdl',
   'PGMPTimer.ipdl',
   'PGMPVideoDecoder.ipdl',
   'PGMPVideoEncoder.ipdl',
 ]
 
+if CONFIG['OS_TARGET'] in ['WINNT', 'Darwin']:
+    DEFINES['SUPPORT_STORAGE_ID'] = 1;
+
 # comment this out to use Unsafe Shmem for more performance
 DEFINES['GMP_SAFE_SHMEM'] = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 if CONFIG['MOZ_SANDBOX']:
     # For sandbox includes and the include dependencies those have
     LOCAL_INCLUDES += [