1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/. */
6
7 #include "gtest/gtest.h"
8
9 #include "mozilla/RefPtr.h"
10 #include "mozilla/SchedulerGroup.h"
11
12 #include "ChromiumCDMCallback.h"
13 #include "GMPTestMonitor.h"
14 #include "GMPServiceParent.h"
15 #include "MediaResult.h"
16 #include "nsIFile.h"
17 #include "nsNSSComponent.h" //For EnsureNSSInitializedChromeOrContent
18 #include "nsThreadUtils.h"
19
20 using namespace mozilla;
21 using namespace mozilla::gmp;
22
GetGMPThread()23 static already_AddRefed<nsIThread> GetGMPThread() {
24 RefPtr<GeckoMediaPluginService> service =
25 GeckoMediaPluginService::GetGeckoMediaPluginService();
26 nsCOMPtr<nsIThread> thread;
27 EXPECT_TRUE(NS_SUCCEEDED(service->GetThread(getter_AddRefs(thread))));
28 return thread.forget();
29 }
30
GetAbstractGMPThread()31 static RefPtr<AbstractThread> GetAbstractGMPThread() {
32 RefPtr<GeckoMediaPluginService> service =
33 GeckoMediaPluginService::GetGeckoMediaPluginService();
34 return service->GetAbstractGMPThread();
35 }
36 /**
37 * Enumerate files under |aPath| (non-recursive).
38 */
39 template <typename T>
EnumerateDir(nsIFile * aPath,T && aDirIter)40 static nsresult EnumerateDir(nsIFile* aPath, T&& aDirIter) {
41 nsCOMPtr<nsIDirectoryEnumerator> iter;
42 nsresult rv = aPath->GetDirectoryEntries(getter_AddRefs(iter));
43 if (NS_FAILED(rv)) {
44 return rv;
45 }
46
47 nsCOMPtr<nsIFile> entry;
48 while (NS_SUCCEEDED(iter->GetNextFile(getter_AddRefs(entry))) && entry) {
49 aDirIter(entry);
50 }
51 return NS_OK;
52 }
53
54 /**
55 * Enumerate files under $profileDir/gmp/$platform/gmp-fake/$aDir/
56 * (non-recursive).
57 */
58 template <typename T>
EnumerateCDMStorageDir(const nsACString & aDir,T && aDirIter)59 static nsresult EnumerateCDMStorageDir(const nsACString& aDir, T&& aDirIter) {
60 RefPtr<GeckoMediaPluginServiceParent> service =
61 GeckoMediaPluginServiceParent::GetSingleton();
62 MOZ_ASSERT(service);
63
64 // $profileDir/gmp/$platform/
65 nsCOMPtr<nsIFile> path;
66 nsresult rv = service->GetStorageDir(getter_AddRefs(path));
67 if (NS_FAILED(rv)) {
68 return rv;
69 }
70
71 // $profileDir/gmp/$platform/gmp-fake/
72 rv = path->Append(NS_LITERAL_STRING("gmp-fake"));
73 if (NS_FAILED(rv)) {
74 return rv;
75 }
76
77 // $profileDir/gmp/$platform/gmp-fake/$aDir/
78 rv = path->AppendNative(aDir);
79 if (NS_FAILED(rv)) {
80 return rv;
81 }
82
83 return EnumerateDir(path, aDirIter);
84 }
85
86 class GMPShutdownObserver : public nsIRunnable, public nsIObserver {
87 public:
GMPShutdownObserver(already_AddRefed<nsIRunnable> aShutdownTask,already_AddRefed<nsIRunnable> Continuation,const nsACString & aNodeId)88 GMPShutdownObserver(already_AddRefed<nsIRunnable> aShutdownTask,
89 already_AddRefed<nsIRunnable> Continuation,
90 const nsACString& aNodeId)
91 : mShutdownTask(aShutdownTask),
92 mContinuation(Continuation),
93 mNodeId(NS_ConvertUTF8toUTF16(aNodeId)) {}
94
95 NS_DECL_THREADSAFE_ISUPPORTS
96
Run()97 NS_IMETHOD Run() override {
98 MOZ_ASSERT(NS_IsMainThread());
99 nsCOMPtr<nsIObserverService> observerService =
100 mozilla::services::GetObserverService();
101 EXPECT_TRUE(observerService);
102 observerService->AddObserver(this, "gmp-shutdown", false);
103
104 nsCOMPtr<nsIThread> thread(GetGMPThread());
105 thread->Dispatch(mShutdownTask, NS_DISPATCH_NORMAL);
106 return NS_OK;
107 }
108
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * aSomeData)109 NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
110 const char16_t* aSomeData) override {
111 if (!strcmp(aTopic, "gmp-shutdown") &&
112 mNodeId.Equals(nsDependentString(aSomeData))) {
113 nsCOMPtr<nsIObserverService> observerService =
114 mozilla::services::GetObserverService();
115 EXPECT_TRUE(observerService);
116 observerService->RemoveObserver(this, "gmp-shutdown");
117 nsCOMPtr<nsIThread> thread(GetGMPThread());
118 thread->Dispatch(mContinuation, NS_DISPATCH_NORMAL);
119 }
120 return NS_OK;
121 }
122
123 private:
124 virtual ~GMPShutdownObserver() = default;
125 nsCOMPtr<nsIRunnable> mShutdownTask;
126 nsCOMPtr<nsIRunnable> mContinuation;
127 const nsString mNodeId;
128 };
129
130 NS_IMPL_ISUPPORTS(GMPShutdownObserver, nsIRunnable, nsIObserver)
131
132 class NotifyObserversTask : public Runnable {
133 public:
NotifyObserversTask(const char * aTopic)134 explicit NotifyObserversTask(const char* aTopic)
135 : mozilla::Runnable("NotifyObserversTask"), mTopic(aTopic) {}
Run()136 NS_IMETHOD Run() override {
137 MOZ_ASSERT(NS_IsMainThread());
138 nsCOMPtr<nsIObserverService> observerService =
139 mozilla::services::GetObserverService();
140 if (observerService) {
141 observerService->NotifyObservers(nullptr, mTopic, nullptr);
142 }
143 return NS_OK;
144 }
145 const char* mTopic;
146 };
147
148 class ClearCDMStorageTask : public nsIRunnable, public nsIObserver {
149 public:
ClearCDMStorageTask(already_AddRefed<nsIRunnable> Continuation,nsIThread * aTarget,PRTime aSince)150 ClearCDMStorageTask(already_AddRefed<nsIRunnable> Continuation,
151 nsIThread* aTarget, PRTime aSince)
152 : mContinuation(Continuation), mTarget(aTarget), mSince(aSince) {}
153
154 NS_DECL_THREADSAFE_ISUPPORTS
155
Run()156 NS_IMETHOD Run() override {
157 MOZ_ASSERT(NS_IsMainThread());
158 nsCOMPtr<nsIObserverService> observerService =
159 mozilla::services::GetObserverService();
160 EXPECT_TRUE(observerService);
161 observerService->AddObserver(this, "gmp-clear-storage-complete", false);
162 if (observerService) {
163 nsAutoString str;
164 if (mSince >= 0) {
165 str.AppendInt(static_cast<int64_t>(mSince));
166 }
167 observerService->NotifyObservers(nullptr, "browser:purge-session-history",
168 str.Data());
169 }
170 return NS_OK;
171 }
172
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * aSomeData)173 NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
174 const char16_t* aSomeData) override {
175 if (!strcmp(aTopic, "gmp-clear-storage-complete")) {
176 nsCOMPtr<nsIObserverService> observerService =
177 mozilla::services::GetObserverService();
178 EXPECT_TRUE(observerService);
179 observerService->RemoveObserver(this, "gmp-clear-storage-complete");
180 mTarget->Dispatch(mContinuation, NS_DISPATCH_NORMAL);
181 }
182 return NS_OK;
183 }
184
185 private:
186 virtual ~ClearCDMStorageTask() = default;
187 nsCOMPtr<nsIRunnable> mContinuation;
188 nsCOMPtr<nsIThread> mTarget;
189 const PRTime mSince;
190 };
191
NS_IMPL_ISUPPORTS(ClearCDMStorageTask,nsIRunnable,nsIObserver)192 NS_IMPL_ISUPPORTS(ClearCDMStorageTask, nsIRunnable, nsIObserver)
193
194 static void ClearCDMStorage(already_AddRefed<nsIRunnable> aContinuation,
195 nsIThread* aTarget, PRTime aSince = -1) {
196 RefPtr<ClearCDMStorageTask> task(
197 new ClearCDMStorageTask(std::move(aContinuation), aTarget, aSince));
198 SchedulerGroup::Dispatch(TaskCategory::Other, task.forget());
199 }
200
SimulatePBModeExit()201 static void SimulatePBModeExit() {
202 NS_DispatchToMainThread(new NotifyObserversTask("last-pb-context-exited"),
203 NS_DISPATCH_SYNC);
204 }
205
206 class TestGetNodeIdCallback : public GetNodeIdCallback {
207 public:
TestGetNodeIdCallback(nsCString & aNodeId,nsresult & aResult)208 TestGetNodeIdCallback(nsCString& aNodeId, nsresult& aResult)
209 : mNodeId(aNodeId), mResult(aResult) {}
210
Done(nsresult aResult,const nsACString & aNodeId)211 void Done(nsresult aResult, const nsACString& aNodeId) {
212 mResult = aResult;
213 mNodeId = aNodeId;
214 }
215
216 private:
217 nsCString& mNodeId;
218 nsresult& mResult;
219 };
220
GetNodeId(const nsAString & aOrigin,const nsAString & aTopLevelOrigin,const nsAString & aGmpName,bool aInPBMode)221 static NodeId GetNodeId(const nsAString& aOrigin,
222 const nsAString& aTopLevelOrigin,
223 const nsAString& aGmpName, bool aInPBMode) {
224 OriginAttributes attrs;
225 attrs.mPrivateBrowsingId = aInPBMode ? 1 : 0;
226
227 nsAutoCString suffix;
228 attrs.CreateSuffix(suffix);
229
230 nsAutoString origin;
231 origin.Assign(aOrigin);
232 origin.Append(NS_ConvertUTF8toUTF16(suffix));
233
234 nsAutoString topLevelOrigin;
235 topLevelOrigin.Assign(aTopLevelOrigin);
236 topLevelOrigin.Append(NS_ConvertUTF8toUTF16(suffix));
237 return NodeId(origin, topLevelOrigin, aGmpName);
238 }
239
GetNodeId(const nsAString & aOrigin,const nsAString & aTopLevelOrigin,bool aInPBMode)240 static nsCString GetNodeId(const nsAString& aOrigin,
241 const nsAString& aTopLevelOrigin, bool aInPBMode) {
242 RefPtr<GeckoMediaPluginServiceParent> service =
243 GeckoMediaPluginServiceParent::GetSingleton();
244 EXPECT_TRUE(service);
245 nsCString nodeId;
246 nsresult result;
247 UniquePtr<GetNodeIdCallback> callback(
248 new TestGetNodeIdCallback(nodeId, result));
249
250 OriginAttributes attrs;
251 attrs.mPrivateBrowsingId = aInPBMode ? 1 : 0;
252
253 nsAutoCString suffix;
254 attrs.CreateSuffix(suffix);
255
256 nsAutoString origin;
257 origin.Assign(aOrigin);
258 origin.Append(NS_ConvertUTF8toUTF16(suffix));
259
260 nsAutoString topLevelOrigin;
261 topLevelOrigin.Assign(aTopLevelOrigin);
262 topLevelOrigin.Append(NS_ConvertUTF8toUTF16(suffix));
263
264 // We rely on the fact that the GetNodeId implementation for
265 // GeckoMediaPluginServiceParent is synchronous.
266 nsresult rv =
267 service->GetNodeId(origin, topLevelOrigin, NS_LITERAL_STRING("gmp-fake"),
268 std::move(callback));
269 EXPECT_TRUE(NS_SUCCEEDED(rv) && NS_SUCCEEDED(result));
270 return nodeId;
271 }
272
IsCDMStorageIsEmpty()273 static bool IsCDMStorageIsEmpty() {
274 RefPtr<GeckoMediaPluginServiceParent> service =
275 GeckoMediaPluginServiceParent::GetSingleton();
276 MOZ_ASSERT(service);
277 nsCOMPtr<nsIFile> storage;
278 nsresult rv = service->GetStorageDir(getter_AddRefs(storage));
279 EXPECT_TRUE(NS_SUCCEEDED(rv));
280 bool exists = false;
281 if (storage) {
282 storage->Exists(&exists);
283 }
284 return !exists;
285 }
286
AssertIsOnGMPThread()287 static void AssertIsOnGMPThread() {
288 RefPtr<GeckoMediaPluginService> service =
289 GeckoMediaPluginService::GetGeckoMediaPluginService();
290 MOZ_ASSERT(service);
291 nsCOMPtr<nsIThread> thread;
292 service->GetThread(getter_AddRefs(thread));
293 MOZ_ASSERT(thread);
294 nsCOMPtr<nsIThread> currentThread;
295 DebugOnly<nsresult> rv = NS_GetCurrentThread(getter_AddRefs(currentThread));
296 MOZ_ASSERT(NS_SUCCEEDED(rv));
297 MOZ_ASSERT(currentThread == thread);
298 }
299
300 class CDMStorageTest {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMStorageTest)301 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMStorageTest)
302
303 void DoTest(void (CDMStorageTest::*aTestMethod)()) {
304 EnsureNSSInitializedChromeOrContent();
305 nsCOMPtr<nsIThread> thread(GetGMPThread());
306 ClearCDMStorage(
307 NewRunnableMethod("CDMStorageTest::DoTest", this, aTestMethod), thread);
308 AwaitFinished();
309 }
310
CDMStorageTest()311 CDMStorageTest() : mMonitor("CDMStorageTest"), mFinished(false) {}
312
Update(const nsCString & aMessage)313 void Update(const nsCString& aMessage) {
314 nsTArray<uint8_t> msg;
315 msg.AppendElements(aMessage.get(), aMessage.Length());
316 mCDM->UpdateSession(NS_LITERAL_CSTRING("fake-session-id"), 1, msg);
317 }
318
TestGetNodeId()319 void TestGetNodeId() {
320 AssertIsOnGMPThread();
321
322 EXPECT_TRUE(IsCDMStorageIsEmpty());
323
324 const nsString origin1 = NS_LITERAL_STRING("http://example1.com");
325 const nsString origin2 = NS_LITERAL_STRING("http://example2.org");
326
327 nsCString PBnodeId1 = GetNodeId(origin1, origin2, true);
328 nsCString PBnodeId2 = GetNodeId(origin1, origin2, true);
329
330 // Node ids for the same origins should be the same in PB mode.
331 EXPECT_TRUE(PBnodeId1.Equals(PBnodeId2));
332
333 nsCString PBnodeId3 = GetNodeId(origin2, origin1, true);
334
335 // Node ids with origin and top level origin swapped should be different.
336 EXPECT_TRUE(!PBnodeId3.Equals(PBnodeId1));
337
338 // Getting node ids in PB mode should not result in the node id being
339 // stored.
340 EXPECT_TRUE(IsCDMStorageIsEmpty());
341
342 nsCString nodeId1 = GetNodeId(origin1, origin2, false);
343 nsCString nodeId2 = GetNodeId(origin1, origin2, false);
344
345 // NodeIds for the same origin pair in non-pb mode should be the same.
346 EXPECT_TRUE(nodeId1.Equals(nodeId2));
347
348 // Node ids for a given origin pair should be different for the PB origins
349 // should be the same in PB mode.
350 EXPECT_TRUE(!PBnodeId1.Equals(nodeId1));
351 EXPECT_TRUE(!PBnodeId2.Equals(nodeId2));
352
353 nsCOMPtr<nsIThread> thread(GetGMPThread());
354 ClearCDMStorage(NewRunnableMethod<nsCString>(
355 "CDMStorageTest::TestGetNodeId_Continuation", this,
356 &CDMStorageTest::TestGetNodeId_Continuation, nodeId1),
357 thread);
358 }
359
TestGetNodeId_Continuation(nsCString aNodeId1)360 void TestGetNodeId_Continuation(nsCString aNodeId1) {
361 EXPECT_TRUE(IsCDMStorageIsEmpty());
362
363 // Once we clear storage, the node ids generated for the same origin-pair
364 // should be different.
365 const nsString origin1 = NS_LITERAL_STRING("http://example1.com");
366 const nsString origin2 = NS_LITERAL_STRING("http://example2.org");
367 nsCString nodeId3 = GetNodeId(origin1, origin2, false);
368 EXPECT_TRUE(!aNodeId1.Equals(nodeId3));
369
370 SetFinished();
371 }
372
CreateDecryptor(const nsAString & aOrigin,const nsAString & aTopLevelOrigin,bool aInPBMode,const nsCString & aUpdate)373 void CreateDecryptor(const nsAString& aOrigin,
374 const nsAString& aTopLevelOrigin, bool aInPBMode,
375 const nsCString& aUpdate) {
376 nsTArray<nsCString> updates;
377 updates.AppendElement(aUpdate);
378 CreateDecryptor(aOrigin, aTopLevelOrigin, aInPBMode, std::move(updates));
379 }
380
CreateDecryptor(const nsAString & aOrigin,const nsAString & aTopLevelOrigin,bool aInPBMode,nsTArray<nsCString> && aUpdates)381 void CreateDecryptor(const nsAString& aOrigin,
382 const nsAString& aTopLevelOrigin, bool aInPBMode,
383 nsTArray<nsCString>&& aUpdates) {
384 CreateDecryptor(GetNodeId(aOrigin, aTopLevelOrigin,
385 NS_LITERAL_STRING("gmp-fake"), aInPBMode),
386 std::move(aUpdates));
387 }
388
CreateDecryptor(const NodeId & aNodeId,nsTArray<nsCString> && aUpdates)389 void CreateDecryptor(const NodeId& aNodeId, nsTArray<nsCString>&& aUpdates) {
390 RefPtr<GeckoMediaPluginService> service =
391 GeckoMediaPluginService::GetGeckoMediaPluginService();
392 EXPECT_TRUE(service);
393
394 nsTArray<nsCString> tags;
395 tags.AppendElement(NS_LITERAL_CSTRING("fake"));
396
397 RefPtr<CDMStorageTest> self = this;
398 RefPtr<gmp::GetCDMParentPromise> promise =
399 service->GetCDM(aNodeId, std::move(tags), nullptr);
400 auto thread = GetAbstractGMPThread();
401 promise->Then(
402 thread, __func__,
403 [self, updates = std::move(aUpdates),
404 thread](RefPtr<gmp::ChromiumCDMParent> cdm) mutable {
405 self->mCDM = cdm;
406 EXPECT_TRUE(!!self->mCDM);
407 self->mCallback.reset(new CallbackProxy(self));
408 nsCString failureReason;
409 self->mCDM
410 ->Init(self->mCallback.get(), false, true,
411 GetMainThreadEventTarget())
412 ->Then(
413 thread, __func__,
414 [self, updates = std::move(updates)] {
415 for (const auto& update : updates) {
416 self->Update(update);
417 }
418 },
419 [](MediaResult rv) { EXPECT_TRUE(false); });
420 },
421 [](MediaResult rv) { EXPECT_TRUE(false); });
422 }
423
TestBasicStorage()424 void TestBasicStorage() {
425 AssertIsOnGMPThread();
426 EXPECT_TRUE(IsCDMStorageIsEmpty());
427
428 RefPtr<GeckoMediaPluginService> service =
429 GeckoMediaPluginService::GetGeckoMediaPluginService();
430
431 // Send a message to the fake GMP for it to run its own tests internally.
432 // It sends us a "test-storage complete" message when its passed, or
433 // some other message if its tests fail.
434 Expect(NS_LITERAL_CSTRING("test-storage complete"),
435 NewRunnableMethod("CDMStorageTest::SetFinished", this,
436 &CDMStorageTest::SetFinished));
437
438 CreateDecryptor(NS_LITERAL_STRING("http://example1.com"),
439 NS_LITERAL_STRING("http://example2.com"), false,
440 NS_LITERAL_CSTRING("test-storage"));
441 }
442
443 /**
444 * 1. Generate storage data for some sites.
445 * 2. Forget about one of the sites.
446 * 3. Check if the storage data for the forgotten site are erased correctly.
447 * 4. Check if the storage data for other sites remain unchanged.
448 */
TestForgetThisSite()449 void TestForgetThisSite() {
450 AssertIsOnGMPThread();
451 EXPECT_TRUE(IsCDMStorageIsEmpty());
452
453 // Generate storage data for some site.
454 nsCOMPtr<nsIRunnable> r = NewRunnableMethod(
455 "CDMStorageTest::TestForgetThisSite_AnotherSite", this,
456 &CDMStorageTest::TestForgetThisSite_AnotherSite);
457 Expect(NS_LITERAL_CSTRING("test-storage complete"), r.forget());
458
459 CreateDecryptor(NS_LITERAL_STRING("http://example1.com"),
460 NS_LITERAL_STRING("http://example2.com"), false,
461 NS_LITERAL_CSTRING("test-storage"));
462 }
463
TestForgetThisSite_AnotherSite()464 void TestForgetThisSite_AnotherSite() {
465 Shutdown();
466
467 // Generate storage data for another site.
468 nsCOMPtr<nsIRunnable> r = NewRunnableMethod(
469 "CDMStorageTest::TestForgetThisSite_CollectSiteInfo", this,
470 &CDMStorageTest::TestForgetThisSite_CollectSiteInfo);
471 Expect(NS_LITERAL_CSTRING("test-storage complete"), r.forget());
472
473 CreateDecryptor(NS_LITERAL_STRING("http://example3.com"),
474 NS_LITERAL_STRING("http://example4.com"), false,
475 NS_LITERAL_CSTRING("test-storage"));
476 }
477
478 struct NodeInfo {
NodeInfoCDMStorageTest::NodeInfo479 explicit NodeInfo(const nsACString& aSite,
480 const mozilla::OriginAttributesPattern& aPattern)
481 : siteToForget(aSite), mPattern(aPattern) {}
482 nsCString siteToForget;
483 mozilla::OriginAttributesPattern mPattern;
484 nsTArray<nsCString> expectedRemainingNodeIds;
485 };
486
487 class NodeIdCollector {
488 public:
NodeIdCollector(NodeInfo * aInfo)489 explicit NodeIdCollector(NodeInfo* aInfo) : mNodeInfo(aInfo) {}
operator ()(nsIFile * aFile)490 void operator()(nsIFile* aFile) {
491 nsCString salt;
492 nsresult rv = ReadSalt(aFile, salt);
493 ASSERT_TRUE(NS_SUCCEEDED(rv));
494 if (!MatchOrigin(aFile, mNodeInfo->siteToForget, mNodeInfo->mPattern)) {
495 mNodeInfo->expectedRemainingNodeIds.AppendElement(salt);
496 }
497 }
498
499 private:
500 NodeInfo* mNodeInfo;
501 };
502
TestForgetThisSite_CollectSiteInfo()503 void TestForgetThisSite_CollectSiteInfo() {
504 mozilla::OriginAttributesPattern pattern;
505
506 UniquePtr<NodeInfo> siteInfo(
507 new NodeInfo(NS_LITERAL_CSTRING("http://example1.com"), pattern));
508 // Collect nodeIds that are expected to remain for later comparison.
509 EnumerateCDMStorageDir(NS_LITERAL_CSTRING("id"),
510 NodeIdCollector(siteInfo.get()));
511 // Invoke "Forget this site" on the main thread.
512 SchedulerGroup::Dispatch(
513 TaskCategory::Other,
514 NewRunnableMethod<UniquePtr<NodeInfo>&&>(
515 "CDMStorageTest::TestForgetThisSite_Forget", this,
516 &CDMStorageTest::TestForgetThisSite_Forget, std::move(siteInfo)));
517 }
518
TestForgetThisSite_Forget(UniquePtr<NodeInfo> && aSiteInfo)519 void TestForgetThisSite_Forget(UniquePtr<NodeInfo>&& aSiteInfo) {
520 RefPtr<GeckoMediaPluginServiceParent> service =
521 GeckoMediaPluginServiceParent::GetSingleton();
522 service->ForgetThisSiteNative(
523 NS_ConvertUTF8toUTF16(aSiteInfo->siteToForget), aSiteInfo->mPattern);
524
525 nsCOMPtr<nsIThread> thread;
526 service->GetThread(getter_AddRefs(thread));
527
528 nsCOMPtr<nsIRunnable> r = NewRunnableMethod<UniquePtr<NodeInfo>&&>(
529 "CDMStorageTest::TestForgetThisSite_Verify", this,
530 &CDMStorageTest::TestForgetThisSite_Verify, std::move(aSiteInfo));
531 thread->Dispatch(r, NS_DISPATCH_NORMAL);
532
533 nsCOMPtr<nsIRunnable> f = NewRunnableMethod(
534 "CDMStorageTest::SetFinished", this, &CDMStorageTest::SetFinished);
535 thread->Dispatch(f, NS_DISPATCH_NORMAL);
536 }
537
538 class NodeIdVerifier {
539 public:
NodeIdVerifier(const NodeInfo * aInfo)540 explicit NodeIdVerifier(const NodeInfo* aInfo)
541 : mNodeInfo(aInfo),
542 mExpectedRemainingNodeIds(aInfo->expectedRemainingNodeIds.Clone()) {}
operator ()(nsIFile * aFile)543 void operator()(nsIFile* aFile) {
544 nsCString salt;
545 nsresult rv = ReadSalt(aFile, salt);
546 ASSERT_TRUE(NS_SUCCEEDED(rv));
547 // Shouldn't match the origin if we clear correctly.
548 EXPECT_FALSE(
549 MatchOrigin(aFile, mNodeInfo->siteToForget, mNodeInfo->mPattern));
550 // Check if remaining nodeIDs are as expected.
551 EXPECT_TRUE(mExpectedRemainingNodeIds.RemoveElement(salt));
552 }
~NodeIdVerifier()553 ~NodeIdVerifier() { EXPECT_TRUE(mExpectedRemainingNodeIds.IsEmpty()); }
554
555 private:
556 const NodeInfo* mNodeInfo;
557 nsTArray<nsCString> mExpectedRemainingNodeIds;
558 };
559
560 class StorageVerifier {
561 public:
StorageVerifier(const NodeInfo * aInfo)562 explicit StorageVerifier(const NodeInfo* aInfo)
563 : mExpectedRemainingNodeIds(aInfo->expectedRemainingNodeIds.Clone()) {}
operator ()(nsIFile * aFile)564 void operator()(nsIFile* aFile) {
565 nsCString salt;
566 nsresult rv = aFile->GetNativeLeafName(salt);
567 ASSERT_TRUE(NS_SUCCEEDED(rv));
568 EXPECT_TRUE(mExpectedRemainingNodeIds.RemoveElement(salt));
569 }
~StorageVerifier()570 ~StorageVerifier() { EXPECT_TRUE(mExpectedRemainingNodeIds.IsEmpty()); }
571
572 private:
573 nsTArray<nsCString> mExpectedRemainingNodeIds;
574 };
575
TestForgetThisSite_Verify(UniquePtr<NodeInfo> && aSiteInfo)576 void TestForgetThisSite_Verify(UniquePtr<NodeInfo>&& aSiteInfo) {
577 nsresult rv = EnumerateCDMStorageDir(NS_LITERAL_CSTRING("id"),
578 NodeIdVerifier(aSiteInfo.get()));
579 EXPECT_TRUE(NS_SUCCEEDED(rv));
580
581 rv = EnumerateCDMStorageDir(NS_LITERAL_CSTRING("storage"),
582 StorageVerifier(aSiteInfo.get()));
583 EXPECT_TRUE(NS_SUCCEEDED(rv));
584 }
585
586 /**
587 * 1. Generate some storage data.
588 * 2. Find the max mtime |t| in $profileDir/gmp/$platform/gmp-fake/id/.
589 * 3. Pass |t| to clear recent history.
590 * 4. Check if all directories in $profileDir/gmp/$platform/gmp-fake/id/ and
591 * $profileDir/gmp/$platform/gmp-fake/storage are removed.
592 */
TestClearRecentHistory1()593 void TestClearRecentHistory1() {
594 AssertIsOnGMPThread();
595 EXPECT_TRUE(IsCDMStorageIsEmpty());
596
597 // Generate storage data for some site.
598 nsCOMPtr<nsIRunnable> r =
599 NewRunnableMethod("CDMStorageTest::TestClearRecentHistory1_Clear", this,
600 &CDMStorageTest::TestClearRecentHistory1_Clear);
601 Expect(NS_LITERAL_CSTRING("test-storage complete"), r.forget());
602
603 CreateDecryptor(NS_LITERAL_STRING("http://example1.com"),
604 NS_LITERAL_STRING("http://example2.com"), false,
605 NS_LITERAL_CSTRING("test-storage"));
606 }
607
608 /**
609 * 1. Generate some storage data.
610 * 2. Find the max mtime |t| in $profileDir/gmp/$platform/gmp-fake/storage/.
611 * 3. Pass |t| to clear recent history.
612 * 4. Check if all directories in $profileDir/gmp/$platform/gmp-fake/id/ and
613 * $profileDir/gmp/$platform/gmp-fake/storage are removed.
614 */
TestClearRecentHistory2()615 void TestClearRecentHistory2() {
616 AssertIsOnGMPThread();
617 EXPECT_TRUE(IsCDMStorageIsEmpty());
618
619 // Generate storage data for some site.
620 nsCOMPtr<nsIRunnable> r =
621 NewRunnableMethod("CDMStorageTest::TestClearRecentHistory2_Clear", this,
622 &CDMStorageTest::TestClearRecentHistory2_Clear);
623 Expect(NS_LITERAL_CSTRING("test-storage complete"), r.forget());
624
625 CreateDecryptor(NS_LITERAL_STRING("http://example1.com"),
626 NS_LITERAL_STRING("http://example2.com"), false,
627 NS_LITERAL_CSTRING("test-storage"));
628 }
629
630 /**
631 * 1. Generate some storage data.
632 * 2. Find the max mtime |t| in $profileDir/gmp/$platform/gmp-fake/storage/.
633 * 3. Pass |t+1| to clear recent history.
634 * 4. Check if all directories in $profileDir/gmp/$platform/gmp-fake/id/ and
635 * $profileDir/gmp/$platform/gmp-fake/storage remain unchanged.
636 */
TestClearRecentHistory3()637 void TestClearRecentHistory3() {
638 AssertIsOnGMPThread();
639 EXPECT_TRUE(IsCDMStorageIsEmpty());
640
641 // Generate storage data for some site.
642 nsCOMPtr<nsIRunnable> r =
643 NewRunnableMethod("CDMStorageTest::TestClearRecentHistory3_Clear", this,
644 &CDMStorageTest::TestClearRecentHistory3_Clear);
645 Expect(NS_LITERAL_CSTRING("test-storage complete"), r.forget());
646
647 CreateDecryptor(NS_LITERAL_STRING("http://example1.com"),
648 NS_LITERAL_STRING("http://example2.com"), false,
649 NS_LITERAL_CSTRING("test-storage"));
650 }
651
652 class MaxMTimeFinder {
653 public:
MaxMTimeFinder()654 MaxMTimeFinder() : mMaxTime(0) {}
operator ()(nsIFile * aFile)655 void operator()(nsIFile* aFile) {
656 PRTime lastModified;
657 nsresult rv = aFile->GetLastModifiedTime(&lastModified);
658 if (NS_SUCCEEDED(rv) && lastModified > mMaxTime) {
659 mMaxTime = lastModified;
660 }
661 EnumerateDir(aFile, *this);
662 }
GetResult() const663 PRTime GetResult() const { return mMaxTime; }
664
665 private:
666 PRTime mMaxTime;
667 };
668
TestClearRecentHistory1_Clear()669 void TestClearRecentHistory1_Clear() {
670 MaxMTimeFinder f;
671 nsresult rv = EnumerateCDMStorageDir(NS_LITERAL_CSTRING("id"), f);
672 EXPECT_TRUE(NS_SUCCEEDED(rv));
673
674 nsCOMPtr<nsIRunnable> r = NewRunnableMethod(
675 "CDMStorageTest::TestClearRecentHistory_CheckEmpty", this,
676 &CDMStorageTest::TestClearRecentHistory_CheckEmpty);
677 nsCOMPtr<nsIThread> t(GetGMPThread());
678 ClearCDMStorage(r.forget(), t, f.GetResult());
679 }
680
TestClearRecentHistory2_Clear()681 void TestClearRecentHistory2_Clear() {
682 MaxMTimeFinder f;
683 nsresult rv = EnumerateCDMStorageDir(NS_LITERAL_CSTRING("storage"), f);
684 EXPECT_TRUE(NS_SUCCEEDED(rv));
685
686 nsCOMPtr<nsIRunnable> r = NewRunnableMethod(
687 "CDMStorageTest::TestClearRecentHistory_CheckEmpty", this,
688 &CDMStorageTest::TestClearRecentHistory_CheckEmpty);
689 nsCOMPtr<nsIThread> t(GetGMPThread());
690 ClearCDMStorage(r.forget(), t, f.GetResult());
691 }
692
TestClearRecentHistory3_Clear()693 void TestClearRecentHistory3_Clear() {
694 MaxMTimeFinder f;
695 nsresult rv = EnumerateCDMStorageDir(NS_LITERAL_CSTRING("storage"), f);
696 EXPECT_TRUE(NS_SUCCEEDED(rv));
697
698 nsCOMPtr<nsIRunnable> r = NewRunnableMethod(
699 "CDMStorageTest::TestClearRecentHistory_CheckNonEmpty", this,
700 &CDMStorageTest::TestClearRecentHistory_CheckNonEmpty);
701 nsCOMPtr<nsIThread> t(GetGMPThread());
702 ClearCDMStorage(r.forget(), t, f.GetResult() + 1);
703 }
704
705 class FileCounter {
706 public:
FileCounter()707 FileCounter() : mCount(0) {}
operator ()(nsIFile * aFile)708 void operator()(nsIFile* aFile) { ++mCount; }
GetCount() const709 int GetCount() const { return mCount; }
710
711 private:
712 int mCount;
713 };
714
TestClearRecentHistory_CheckEmpty()715 void TestClearRecentHistory_CheckEmpty() {
716 FileCounter c1;
717 nsresult rv = EnumerateCDMStorageDir(NS_LITERAL_CSTRING("id"), c1);
718 EXPECT_TRUE(NS_SUCCEEDED(rv));
719 // There should be no files under $profileDir/gmp/$platform/gmp-fake/id/
720 EXPECT_EQ(c1.GetCount(), 0);
721
722 FileCounter c2;
723 rv = EnumerateCDMStorageDir(NS_LITERAL_CSTRING("storage"), c2);
724 EXPECT_TRUE(NS_SUCCEEDED(rv));
725 // There should be no files under
726 // $profileDir/gmp/$platform/gmp-fake/storage/
727 EXPECT_EQ(c2.GetCount(), 0);
728
729 SetFinished();
730 }
731
TestClearRecentHistory_CheckNonEmpty()732 void TestClearRecentHistory_CheckNonEmpty() {
733 FileCounter c1;
734 nsresult rv = EnumerateCDMStorageDir(NS_LITERAL_CSTRING("id"), c1);
735 EXPECT_TRUE(NS_SUCCEEDED(rv));
736 // There should be one directory under
737 // $profileDir/gmp/$platform/gmp-fake/id/
738 EXPECT_EQ(c1.GetCount(), 1);
739
740 FileCounter c2;
741 rv = EnumerateCDMStorageDir(NS_LITERAL_CSTRING("storage"), c2);
742 EXPECT_TRUE(NS_SUCCEEDED(rv));
743 // There should be one directory under
744 // $profileDir/gmp/$platform/gmp-fake/storage/
745 EXPECT_EQ(c2.GetCount(), 1);
746
747 SetFinished();
748 }
749
TestCrossOriginStorage()750 void TestCrossOriginStorage() {
751 EXPECT_TRUE(!mCDM);
752
753 // Send the decryptor the message "store recordid $time"
754 // Wait for the decrytor to send us "stored recordid $time"
755 auto t = time(0);
756 nsCString response("stored crossOriginTestRecordId ");
757 response.AppendInt((int64_t)t);
758 Expect(
759 response,
760 NewRunnableMethod(
761 "CDMStorageTest::TestCrossOriginStorage_RecordStoredContinuation",
762 this,
763 &CDMStorageTest::TestCrossOriginStorage_RecordStoredContinuation));
764
765 nsCString update("store crossOriginTestRecordId ");
766 update.AppendInt((int64_t)t);
767
768 // Open decryptor on one, origin, write a record, and test that that
769 // record can't be read on another origin.
770 CreateDecryptor(NS_LITERAL_STRING("http://example3.com"),
771 NS_LITERAL_STRING("http://example4.com"), false, update);
772 }
773
TestCrossOriginStorage_RecordStoredContinuation()774 void TestCrossOriginStorage_RecordStoredContinuation() {
775 // Close the old decryptor, and create a new one on a different origin,
776 // and try to read the record.
777 Shutdown();
778
779 Expect(NS_LITERAL_CSTRING(
780 "retrieve crossOriginTestRecordId succeeded (length 0 bytes)"),
781 NewRunnableMethod("CDMStorageTest::SetFinished", this,
782 &CDMStorageTest::SetFinished));
783
784 CreateDecryptor(NS_LITERAL_STRING("http://example5.com"),
785 NS_LITERAL_STRING("http://example6.com"), false,
786 NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId"));
787 }
788
TestPBStorage()789 void TestPBStorage() {
790 // Send the decryptor the message "store recordid $time"
791 // Wait for the decrytor to send us "stored recordid $time"
792 nsCString response("stored pbdata test-pb-data");
793 Expect(response,
794 NewRunnableMethod(
795 "CDMStorageTest::TestPBStorage_RecordStoredContinuation", this,
796 &CDMStorageTest::TestPBStorage_RecordStoredContinuation));
797
798 // Open decryptor on one, origin, write a record, close decryptor,
799 // open another, and test that record can be read, close decryptor,
800 // then send pb-last-context-closed notification, then open decryptor
801 // and check that it can't read that data; it should have been purged.
802 CreateDecryptor(NS_LITERAL_STRING("http://pb1.com"),
803 NS_LITERAL_STRING("http://pb2.com"), true,
804 NS_LITERAL_CSTRING("store pbdata test-pb-data"));
805 }
806
TestPBStorage_RecordStoredContinuation()807 void TestPBStorage_RecordStoredContinuation() {
808 Shutdown();
809
810 Expect(
811 NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 12 bytes)"),
812 NewRunnableMethod(
813 "CDMStorageTest::TestPBStorage_RecordRetrievedContinuation", this,
814 &CDMStorageTest::TestPBStorage_RecordRetrievedContinuation));
815
816 CreateDecryptor(NS_LITERAL_STRING("http://pb1.com"),
817 NS_LITERAL_STRING("http://pb2.com"), true,
818 NS_LITERAL_CSTRING("retrieve pbdata"));
819 }
820
TestPBStorage_RecordRetrievedContinuation()821 void TestPBStorage_RecordRetrievedContinuation() {
822 Shutdown();
823 SimulatePBModeExit();
824
825 Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 0 bytes)"),
826 NewRunnableMethod("CDMStorageTest::SetFinished", this,
827 &CDMStorageTest::SetFinished));
828
829 CreateDecryptor(NS_LITERAL_STRING("http://pb1.com"),
830 NS_LITERAL_STRING("http://pb2.com"), true,
831 NS_LITERAL_CSTRING("retrieve pbdata"));
832 }
833
834 #if defined(XP_WIN)
TestOutputProtection()835 void TestOutputProtection() {
836 Shutdown();
837
838 Expect(NS_LITERAL_CSTRING("OP tests completed"),
839 NewRunnableMethod("CDMStorageTest::SetFinished", this,
840 &CDMStorageTest::SetFinished));
841
842 CreateDecryptor(NS_LITERAL_STRING("http://example15.com"),
843 NS_LITERAL_STRING("http://example16.com"), false,
844 NS_LITERAL_CSTRING("test-op-apis"));
845 }
846 #endif
847
TestLongRecordNames()848 void TestLongRecordNames() {
849 NS_NAMED_LITERAL_CSTRING(longRecordName,
850 "A_"
851 "very_very_very_very_very_very_very_very_very_"
852 "very_very_very_very_very_very_"
853 "very_very_very_very_very_very_very_very_very_"
854 "very_very_very_very_very_very_"
855 "very_very_very_very_very_very_very_very_very_"
856 "very_very_very_very_very_very_"
857 "very_very_very_very_very_very_very_very_very_"
858 "very_very_very_very_very_very_"
859 "very_very_very_very_very_very_very_very_very_"
860 "very_very_very_very_very_very_"
861 "very_very_very_very_very_very_very_very_very_"
862 "very_very_very_very_very_very_"
863 "very_very_very_very_very_very_very_very_very_"
864 "very_very_very_very_very_very_"
865 "very_very_very_very_very_very_very_very_very_"
866 "very_very_very_very_very_very_"
867 "very_very_very_very_very_very_very_very_very_"
868 "very_very_very_very_very_very_"
869 "very_very_very_very_very_very_very_very_very_"
870 "very_very_very_very_very_very_"
871 "very_very_very_very_very_very_very_very_very_"
872 "very_very_very_very_very_very_"
873 "very_very_very_very_very_very_very_very_very_"
874 "very_very_very_very_very_very_"
875 "very_very_very_very_very_very_very_very_very_"
876 "very_very_very_very_very_very_"
877 "very_very_very_very_very_very_very_very_very_"
878 "very_very_very_very_very_very_"
879 "very_very_very_very_very_very_very_very_very_"
880 "very_very_very_very_very_very_"
881 "long_record_name");
882
883 NS_NAMED_LITERAL_CSTRING(data, "Just_some_arbitrary_data.");
884
885 MOZ_ASSERT(longRecordName.Length() < GMP_MAX_RECORD_NAME_SIZE);
886 MOZ_ASSERT(longRecordName.Length() > 260); // Windows MAX_PATH
887
888 nsCString response("stored ");
889 response.Append(longRecordName);
890 response.AppendLiteral(" ");
891 response.Append(data);
892 Expect(response, NewRunnableMethod("CDMStorageTest::SetFinished", this,
893 &CDMStorageTest::SetFinished));
894
895 nsCString update("store ");
896 update.Append(longRecordName);
897 update.AppendLiteral(" ");
898 update.Append(data);
899 CreateDecryptor(NS_LITERAL_STRING("http://fuz.com"),
900 NS_LITERAL_STRING("http://baz.com"), false, update);
901 }
902
Expect(const nsCString & aMessage,already_AddRefed<nsIRunnable> aContinuation)903 void Expect(const nsCString& aMessage,
904 already_AddRefed<nsIRunnable> aContinuation) {
905 mExpected.AppendElement(
906 ExpectedMessage(aMessage, std::move(aContinuation)));
907 }
908
AwaitFinished()909 void AwaitFinished() {
910 mozilla::SpinEventLoopUntil([&]() -> bool { return mFinished; });
911 mFinished = false;
912 }
913
ShutdownThen(already_AddRefed<nsIRunnable> aContinuation)914 void ShutdownThen(already_AddRefed<nsIRunnable> aContinuation) {
915 EXPECT_TRUE(!!mCDM);
916 if (!mCDM) {
917 return;
918 }
919 EXPECT_FALSE(mNodeId.IsEmpty());
920 RefPtr<GMPShutdownObserver> task(new GMPShutdownObserver(
921 NewRunnableMethod("CDMStorageTest::Shutdown", this,
922 &CDMStorageTest::Shutdown),
923 std::move(aContinuation), mNodeId));
924 SchedulerGroup::Dispatch(TaskCategory::Other, task.forget());
925 }
926
Shutdown()927 void Shutdown() {
928 if (mCDM) {
929 mCDM->Shutdown();
930 mCDM = nullptr;
931 mNodeId = EmptyCString();
932 }
933 }
934
Dummy()935 void Dummy() {}
936
SetFinished()937 void SetFinished() {
938 mFinished = true;
939 Shutdown();
940 nsCOMPtr<nsIRunnable> task = NewRunnableMethod(
941 "CDMStorageTest::Dummy", this, &CDMStorageTest::Dummy);
942 SchedulerGroup::Dispatch(TaskCategory::Other, task.forget());
943 }
944
SessionMessage(const nsACString & aSessionId,uint32_t aMessageType,const nsTArray<uint8_t> & aMessage)945 void SessionMessage(const nsACString& aSessionId, uint32_t aMessageType,
946 const nsTArray<uint8_t>& aMessage) {
947 MonitorAutoLock mon(mMonitor);
948
949 nsCString msg((const char*)aMessage.Elements(), aMessage.Length());
950 EXPECT_TRUE(mExpected.Length() > 0);
951 bool matches = mExpected[0].mMessage.Equals(msg);
952 EXPECT_STREQ(mExpected[0].mMessage.get(), msg.get());
953 if (mExpected.Length() > 0 && matches) {
954 nsCOMPtr<nsIRunnable> continuation = mExpected[0].mContinuation;
955 mExpected.RemoveElementAt(0);
956 if (continuation) {
957 NS_DispatchToCurrentThread(continuation);
958 }
959 }
960 }
961
Terminated()962 void Terminated() {
963 if (mCDM) {
964 mCDM->Shutdown();
965 mCDM = nullptr;
966 }
967 }
968
969 private:
970 ~CDMStorageTest() = default;
971
972 struct ExpectedMessage {
ExpectedMessageCDMStorageTest::ExpectedMessage973 ExpectedMessage(const nsCString& aMessage,
974 already_AddRefed<nsIRunnable> aContinuation)
975 : mMessage(aMessage), mContinuation(aContinuation) {}
976 nsCString mMessage;
977 nsCOMPtr<nsIRunnable> mContinuation;
978 };
979
980 nsTArray<ExpectedMessage> mExpected;
981
982 RefPtr<nsIRunnable> mSetDecryptorIdContinuation;
983
984 RefPtr<gmp::ChromiumCDMParent> mCDM;
985 Monitor mMonitor;
986 Atomic<bool> mFinished;
987 nsCString mNodeId;
988
989 class CallbackProxy : public ChromiumCDMCallback {
990 public:
CallbackProxy(CDMStorageTest * aRunner)991 explicit CallbackProxy(CDMStorageTest* aRunner) : mRunner(aRunner) {}
992
SetSessionId(uint32_t aPromiseId,const nsCString & aSessionId)993 void SetSessionId(uint32_t aPromiseId,
994 const nsCString& aSessionId) override {}
995
ResolveLoadSessionPromise(uint32_t aPromiseId,bool aSuccessful)996 void ResolveLoadSessionPromise(uint32_t aPromiseId,
997 bool aSuccessful) override {}
998
ResolvePromiseWithKeyStatus(uint32_t aPromiseId,uint32_t aKeyStatus)999 void ResolvePromiseWithKeyStatus(uint32_t aPromiseId,
1000 uint32_t aKeyStatus) override {}
1001
ResolvePromise(uint32_t aPromiseId)1002 void ResolvePromise(uint32_t aPromiseId) override {}
1003
RejectPromise(uint32_t aPromiseId,ErrorResult && aError,const nsCString & aErrorMessage)1004 void RejectPromise(uint32_t aPromiseId, ErrorResult&& aError,
1005 const nsCString& aErrorMessage) override {}
1006
SessionMessage(const nsACString & aSessionId,uint32_t aMessageType,nsTArray<uint8_t> && aMessage)1007 void SessionMessage(const nsACString& aSessionId, uint32_t aMessageType,
1008 nsTArray<uint8_t>&& aMessage) override {
1009 mRunner->SessionMessage(aSessionId, aMessageType, std::move(aMessage));
1010 }
1011
SessionKeysChange(const nsCString & aSessionId,nsTArray<mozilla::gmp::CDMKeyInformation> && aKeysInfo)1012 void SessionKeysChange(
1013 const nsCString& aSessionId,
1014 nsTArray<mozilla::gmp::CDMKeyInformation>&& aKeysInfo) override {}
1015
ExpirationChange(const nsCString & aSessionId,double aSecondsSinceEpoch)1016 void ExpirationChange(const nsCString& aSessionId,
1017 double aSecondsSinceEpoch) override {}
1018
SessionClosed(const nsCString & aSessionId)1019 void SessionClosed(const nsCString& aSessionId) override {}
1020
Terminated()1021 void Terminated() override { mRunner->Terminated(); }
1022
Shutdown()1023 void Shutdown() override { mRunner->Shutdown(); }
1024
1025 private:
1026 // Warning: Weak ref.
1027 CDMStorageTest* mRunner;
1028 };
1029
1030 UniquePtr<CallbackProxy> mCallback;
1031 }; // class CDMStorageTest
1032
TEST(GeckoMediaPlugins,CDMStorageGetNodeId)1033 TEST(GeckoMediaPlugins, CDMStorageGetNodeId)
1034 {
1035 RefPtr<CDMStorageTest> runner = new CDMStorageTest();
1036 runner->DoTest(&CDMStorageTest::TestGetNodeId);
1037 }
1038
TEST(GeckoMediaPlugins,CDMStorageBasic)1039 TEST(GeckoMediaPlugins, CDMStorageBasic)
1040 {
1041 RefPtr<CDMStorageTest> runner = new CDMStorageTest();
1042 runner->DoTest(&CDMStorageTest::TestBasicStorage);
1043 }
1044
TEST(GeckoMediaPlugins,CDMStorageForgetThisSite)1045 TEST(GeckoMediaPlugins, CDMStorageForgetThisSite)
1046 {
1047 RefPtr<CDMStorageTest> runner = new CDMStorageTest();
1048 runner->DoTest(&CDMStorageTest::TestForgetThisSite);
1049 }
1050
TEST(GeckoMediaPlugins,CDMStorageClearRecentHistory1)1051 TEST(GeckoMediaPlugins, CDMStorageClearRecentHistory1)
1052 {
1053 RefPtr<CDMStorageTest> runner = new CDMStorageTest();
1054 runner->DoTest(&CDMStorageTest::TestClearRecentHistory1);
1055 }
1056
TEST(GeckoMediaPlugins,CDMStorageClearRecentHistory2)1057 TEST(GeckoMediaPlugins, CDMStorageClearRecentHistory2)
1058 {
1059 RefPtr<CDMStorageTest> runner = new CDMStorageTest();
1060 runner->DoTest(&CDMStorageTest::TestClearRecentHistory2);
1061 }
1062
TEST(GeckoMediaPlugins,CDMStorageClearRecentHistory3)1063 TEST(GeckoMediaPlugins, CDMStorageClearRecentHistory3)
1064 {
1065 RefPtr<CDMStorageTest> runner = new CDMStorageTest();
1066 runner->DoTest(&CDMStorageTest::TestClearRecentHistory3);
1067 }
1068
TEST(GeckoMediaPlugins,CDMStorageCrossOrigin)1069 TEST(GeckoMediaPlugins, CDMStorageCrossOrigin)
1070 {
1071 RefPtr<CDMStorageTest> runner = new CDMStorageTest();
1072 runner->DoTest(&CDMStorageTest::TestCrossOriginStorage);
1073 }
1074
TEST(GeckoMediaPlugins,CDMStoragePrivateBrowsing)1075 TEST(GeckoMediaPlugins, CDMStoragePrivateBrowsing)
1076 {
1077 RefPtr<CDMStorageTest> runner = new CDMStorageTest();
1078 runner->DoTest(&CDMStorageTest::TestPBStorage);
1079 }
1080
1081 #if defined(XP_WIN)
TEST(GeckoMediaPlugins,GMPOutputProtection)1082 TEST(GeckoMediaPlugins, GMPOutputProtection)
1083 {
1084 RefPtr<CDMStorageTest> runner = new CDMStorageTest();
1085 runner->DoTest(&CDMStorageTest::TestOutputProtection);
1086 }
1087 #endif
1088
TEST(GeckoMediaPlugins,CDMStorageLongRecordNames)1089 TEST(GeckoMediaPlugins, CDMStorageLongRecordNames)
1090 {
1091 RefPtr<CDMStorageTest> runner = new CDMStorageTest();
1092 runner->DoTest(&CDMStorageTest::TestLongRecordNames);
1093 }
1094