Bug 1271169 - Add gtest to ensure EME device binding works. r=gerald
authorChris Pearce <cpearce@mozilla.com>
Tue, 10 May 2016 13:40:05 +1200
changeset 298518 57fa89168a44c8f49ac50c92a5632c4f6893cfe9
parent 298517 4da6cece7b58ff4bca9dd599db0eddd3f4d78af3
child 298519 705b7365e3e5f36716e06a828fe08731b376a747
push id77210
push usercpearce@mozilla.com
push dateTue, 24 May 2016 02:16:54 +0000
treeherdermozilla-inbound@57fa89168a44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald
bugs1271169
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1271169 - Add gtest to ensure EME device binding works. r=gerald Call the device binding code in gtests, and have a test GMP which returns the device ID it was passed in a message, so that we can verify that the id the GMP was passed is the same as the id generated in the parent. MozReview-Commit-ID: Gjqvo6dRK1D
dom/media/gmp-plugin/gmp-fake.cpp
dom/media/gmp-plugin/gmp-test-decryptor.cpp
dom/media/gmp-plugin/gmp-test-decryptor.h
dom/media/gtest/TestGMPCrossOrigin.cpp
--- a/dom/media/gmp-plugin/gmp-fake.cpp
+++ b/dom/media/gmp-plugin/gmp-fake.cpp
@@ -83,9 +83,16 @@ extern "C" {
     return GMPGenericErr;
   }
 
   PUBLIC_FUNC void
   GMPShutdown (void) {
     g_platform_api = NULL;
   }
 
+#if defined(GMP_FAKE_SUPPORT_DECRYPT)
+  PUBLIC_FUNC void
+  GMPSetNodeId(const char* aNodeId, uint32_t aLength) {
+    FakeDecryptor::SetNodeId(aNodeId, aLength);
+  }
+#endif
+
 } // extern "C"
--- a/dom/media/gmp-plugin/gmp-test-decryptor.cpp
+++ b/dom/media/gmp-plugin/gmp-test-decryptor.cpp
@@ -15,16 +15,18 @@
 #include <sstream>
 #include <set>
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 
 using namespace std;
 
+std::string FakeDecryptor::sNodeId;
+
 FakeDecryptor* FakeDecryptor::sInstance = nullptr;
 extern GMPPlatformAPI* g_platform_api; // Defined in gmp-fake.cpp
 
 class GMPMutexAutoLock
 {
 public:
   explicit GMPMutexAutoLock(GMPMutex* aMutex) : mMutex(aMutex) {
     mMutex->Acquire();
@@ -562,16 +564,18 @@ FakeDecryptor::UpdateSession(uint32_t aP
   } else if (task == "retrieve-plugin-voucher") {
     const uint8_t* rawVoucher = nullptr;
     uint32_t length = 0;
     mHost->GetPluginVoucher(&rawVoucher, &length);
     std::string voucher((const char*)rawVoucher, (const char*)(rawVoucher + length));
     Message("retrieved plugin-voucher: " + voucher);
   } else if (task == "retrieve-record-names") {
     GMPEnumRecordNames(&RecvGMPRecordIterator, this);
+  } else if (task == "retrieve-node-id") {
+    Message("node-id " + sNodeId);
   }
 }
 
 class CompleteShutdownTask : public GMPTask {
 public:
   explicit CompleteShutdownTask(GMPAsyncShutdownHost* aHost)
     : mHost(aHost)
   {
--- a/dom/media/gmp-plugin/gmp-test-decryptor.h
+++ b/dom/media/gmp-plugin/gmp-test-decryptor.h
@@ -67,20 +67,25 @@ public:
 
   void DecryptingComplete() override;
 
   static void Message(const std::string& aMessage);
 
   void ProcessRecordNames(GMPRecordIterator* aRecordIterator,
                           GMPErr aStatus);
 
+  static void SetNodeId(const char* aNodeId, uint32_t aLength) {
+    sNodeId = std::string(aNodeId, aNodeId + aLength);
+  }
+
 private:
 
   virtual ~FakeDecryptor() {}
   static FakeDecryptor* sInstance;
+  static std::string sNodeId;
 
   void TestStorage();
 
   GMPDecryptorCallback* mCallback;
   GMPDecryptorHost* mHost;
 };
 
 class TestAsyncShutdown : public GMPAsyncShutdown {
--- a/dom/media/gtest/TestGMPCrossOrigin.cpp
+++ b/dom/media/gtest/TestGMPCrossOrigin.cpp
@@ -15,16 +15,17 @@
 #include "GMPServiceParent.h"
 #include "MediaPrefs.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsIFile.h"
 #include "nsISimpleEnumerator.h"
 #include "mozilla/Atomics.h"
 #include "nsNSSComponent.h"
 #include "mozilla/DebugOnly.h"
+#include "GMPDeviceBinding.h"
 
 #if defined(XP_WIN)
 #include "mozilla/WindowsVersion.h"
 #endif
 
 using namespace std;
 
 using namespace mozilla;
@@ -609,31 +610,40 @@ class GMPStorageTest : public GMPDecrypt
       thread->Dispatch(mContinuation, NS_DISPATCH_NORMAL);
     }
 
   private:
     RefPtr<GMPStorageTest> mRunner;
     nsCOMPtr<nsIRunnable> mContinuation;
   };
 
+  void CreateDecryptor(const nsCString& aNodeId,
+                       const nsCString& aUpdate)
+  {
+    nsTArray<nsCString> updates;
+    updates.AppendElement(aUpdate);
+    nsCOMPtr<nsIRunnable> continuation(new Updates(this, Move(updates)));
+    CreateDecryptor(aNodeId, continuation);
+  }
+
   void CreateDecryptor(const nsAString& aOrigin,
                        const nsAString& aTopLevelOrigin,
                        bool aInPBMode,
                        const nsCString& aUpdate)
   {
     nsTArray<nsCString> updates;
     updates.AppendElement(aUpdate);
     CreateDecryptor(aOrigin, aTopLevelOrigin, aInPBMode, Move(updates));
   }
   class Updates : public Runnable
   {
   public:
     Updates(GMPStorageTest* aRunner, nsTArray<nsCString>&& aUpdates)
       : mRunner(aRunner),
-        mUpdates(aUpdates)
+        mUpdates(Move(aUpdates))
     {
     }
 
     NS_IMETHOD Run()
     {
       for (auto& update : mUpdates) {
         mRunner->Update(update);
       }
@@ -644,27 +654,26 @@ class GMPStorageTest : public GMPDecrypt
     RefPtr<GMPStorageTest> mRunner;
     nsTArray<nsCString> mUpdates;
   };
   void CreateDecryptor(const nsAString& aOrigin,
                        const nsAString& aTopLevelOrigin,
                        bool aInPBMode,
                        nsTArray<nsCString>&& aUpdates) {
     nsCOMPtr<nsIRunnable> updates(new Updates(this, Move(aUpdates)));
-    CreateDecryptor(aOrigin, aTopLevelOrigin, aInPBMode, updates);
+    CreateDecryptor(GetNodeId(aOrigin, aTopLevelOrigin, aInPBMode), updates);
   }
-  void CreateDecryptor(const nsAString& aOrigin,
-                       const nsAString& aTopLevelOrigin,
-                       bool aInPBMode,
+
+  void CreateDecryptor(const nsCString& aNodeId,
                        nsIRunnable* aContinuation) {
     RefPtr<GeckoMediaPluginService> service =
       GeckoMediaPluginService::GetGeckoMediaPluginService();
     EXPECT_TRUE(service);
 
-    mNodeId = GetNodeId(aOrigin, aTopLevelOrigin, aInPBMode);
+    mNodeId = aNodeId;
     EXPECT_TRUE(!mNodeId.IsEmpty());
 
     nsTArray<nsCString> tags;
     tags.AppendElement(NS_LITERAL_CSTRING("fake"));
 
     UniquePtr<GetGMPDecryptorCallback> callback(
       new CreateDecryptorDone(this, aContinuation));
     nsresult rv =
@@ -1075,17 +1084,17 @@ class GMPStorageTest : public GMPDecrypt
                                      const nsAString& aOrigin2,
                                      void (GMPStorageTest::*aCallback)()) {
     nsCOMPtr<nsIRunnable> continuation(
       NewRunnableMethod<nsCOMPtr<nsIRunnable>>(
         this,
         &GMPStorageTest::NextAsyncShutdownTimeoutTest,
         NewRunnableMethod(this, aCallback)));
 
-    CreateDecryptor(aOrigin1, aOrigin2, false, continuation);
+    CreateDecryptor(GetNodeId(aOrigin1, aOrigin2, false), continuation);
   }
 
   void TestAsyncShutdownTimeout() {
     // Create decryptors that timeout in their async shutdown.
     // If the gtest hangs on shutdown, test fails!
     CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("http://example7.com"),
                                   NS_LITERAL_STRING("http://example8.com"),
                                   &GMPStorageTest::TestAsyncShutdownTimeout2);
@@ -1269,16 +1278,34 @@ class GMPStorageTest : public GMPDecrypt
     update.AppendLiteral(" ");
     update.Append(data);
     CreateDecryptor(NS_LITERAL_STRING("http://fuz.com"),
                     NS_LITERAL_STRING("http://baz.com"),
                     false,
                     update);
   }
 
+  void TestNodeId() {
+    // Calculate the nodeId, and the device bound nodeId. Start a GMP, and
+    // have it return the device bound nodeId that it's been passed. Assert
+    // they have the same value.
+    const nsString origin = NS_LITERAL_STRING("http://example-fuz-baz.com");
+    nsCString originSalt1 = GetNodeId(origin, origin, false);
+
+    nsCString salt = originSalt1;
+    std::string nodeId;
+    EXPECT_TRUE(CalculateGMPDeviceId(salt.BeginWriting(), salt.Length(), nodeId));
+
+    std::string expected = "node-id " + nodeId;
+    Expect(nsDependentCString(expected.c_str()), NewRunnableMethod(this, &GMPStorageTest::SetFinished));
+
+    CreateDecryptor(originSalt1,
+                    NS_LITERAL_CSTRING("retrieve-node-id"));
+  }
+
   void Expect(const nsCString& aMessage, already_AddRefed<nsIRunnable> aContinuation) {
     mExpected.AppendElement(ExpectedMessage(aMessage, Move(aContinuation)));
   }
 
   void AwaitFinished() {
     while (!mFinished) {
       NS_ProcessNextEvent(nullptr, true);
     }
@@ -1485,8 +1512,13 @@ TEST(GeckoMediaPlugins, GMPStorageGetRec
   RefPtr<GMPStorageTest> runner = new GMPStorageTest();
   runner->DoTest(&GMPStorageTest::GetRecordNamesPersistentStorage);
 }
 
 TEST(GeckoMediaPlugins, GMPStorageLongRecordNames) {
   RefPtr<GMPStorageTest> runner = new GMPStorageTest();
   runner->DoTest(&GMPStorageTest::TestLongRecordNames);
 }
+
+TEST(GeckoMediaPlugins, GMPNodeId) {
+  RefPtr<GMPStorageTest> runner = new GMPStorageTest();
+  runner->DoTest(&GMPStorageTest::TestNodeId);
+}