/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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 "gtest/gtest.h" #include "mozilla/gtest/MozAssertions.h" #include "mozilla/StaticPtr.h" #include "GMPTestMonitor.h" #include "GMPVideoDecoderProxy.h" #include "GMPVideoEncoderProxy.h" #include "GMPServiceParent.h" #include "nsAppDirectoryServiceDefs.h" #include "mozilla/Atomics.h" #include "mozilla/DebugOnly.h" #include "nsThreadUtils.h" using namespace mozilla; using namespace mozilla::gmp; struct GMPTestRunner { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPTestRunner) GMPTestRunner() = default; void DoTest(void (GMPTestRunner::*aTestMethod)(GMPTestMonitor&)); void RunTestGMPTestCodec1(GMPTestMonitor& aMonitor); void RunTestGMPTestCodec2(GMPTestMonitor& aMonitor); void RunTestGMPTestCodec3(GMPTestMonitor& aMonitor); void RunTestGMPCrossOrigin1(GMPTestMonitor& aMonitor); void RunTestGMPCrossOrigin2(GMPTestMonitor& aMonitor); void RunTestGMPCrossOrigin3(GMPTestMonitor& aMonitor); void RunTestGMPCrossOrigin4(GMPTestMonitor& aMonitor); private: ~GMPTestRunner() = default; }; template *, const nsACString&, UniquePtr&&)> class RunTestGMPVideoCodec : public Base { public: void Done(T* aGMP, GMPVideoHost* aHost) override { EXPECT_TRUE(aGMP); EXPECT_TRUE(aHost); if (aGMP) { aGMP->Close(); } mMonitor.SetFinished(); } static void Run(GMPTestMonitor& aMonitor, const nsCString& aOrigin) { UniquePtr callback(new RunTestGMPVideoCodec(aMonitor)); Get(aOrigin, std::move(callback)); } protected: typedef T GMPCodecType; typedef Base GMPCallbackType; explicit RunTestGMPVideoCodec(GMPTestMonitor& aMonitor) : mMonitor(aMonitor) {} static nsresult Get(const nsACString& aNodeId, UniquePtr&& aCallback) { nsTArray tags; tags.AppendElement("h264"_ns); tags.AppendElement("fake"_ns); RefPtr service = GeckoMediaPluginService::GetGeckoMediaPluginService(); return ((*service).*Getter)(nullptr, &tags, aNodeId, std::move(aCallback)); } GMPTestMonitor& mMonitor; }; typedef RunTestGMPVideoCodec RunTestGMPVideoDecoder; typedef RunTestGMPVideoCodec RunTestGMPVideoEncoder; void GMPTestRunner::RunTestGMPTestCodec1(GMPTestMonitor& aMonitor) { RunTestGMPVideoDecoder::Run(aMonitor, "o"_ns); } void GMPTestRunner::RunTestGMPTestCodec2(GMPTestMonitor& aMonitor) { RunTestGMPVideoDecoder::Run(aMonitor, ""_ns); } void GMPTestRunner::RunTestGMPTestCodec3(GMPTestMonitor& aMonitor) { RunTestGMPVideoEncoder::Run(aMonitor, ""_ns); } template class RunTestGMPCrossOrigin : public Base { public: void Done(typename Base::GMPCodecType* aGMP, GMPVideoHost* aHost) override { EXPECT_TRUE(aGMP); UniquePtr callback( new Step2(Base::mMonitor, aGMP, mShouldBeEqual)); nsresult rv = Base::Get(mOrigin2, std::move(callback)); EXPECT_NS_SUCCEEDED(rv); if (NS_FAILED(rv)) { Base::mMonitor.SetFinished(); } } static void Run(GMPTestMonitor& aMonitor, const nsCString& aOrigin1, const nsCString& aOrigin2) { UniquePtr callback( new RunTestGMPCrossOrigin(aMonitor, aOrigin1, aOrigin2)); nsresult rv = Base::Get(aOrigin1, std::move(callback)); EXPECT_NS_SUCCEEDED(rv); if (NS_FAILED(rv)) { aMonitor.SetFinished(); } } private: RunTestGMPCrossOrigin(GMPTestMonitor& aMonitor, const nsCString& aOrigin1, const nsCString& aOrigin2) : Base(aMonitor), mGMP(nullptr), mOrigin2(aOrigin2), mShouldBeEqual(aOrigin1.Equals(aOrigin2)) {} class Step2 : public Base { public: Step2(GMPTestMonitor& aMonitor, typename Base::GMPCodecType* aGMP, bool aShouldBeEqual) : Base(aMonitor), mGMP(aGMP), mShouldBeEqual(aShouldBeEqual) {} void Done(typename Base::GMPCodecType* aGMP, GMPVideoHost* aHost) override { EXPECT_TRUE(aGMP); if (aGMP) { EXPECT_TRUE(mGMP && (mGMP->GetPluginId() == aGMP->GetPluginId()) == mShouldBeEqual); } if (mGMP) { mGMP->Close(); } Base::Done(aGMP, aHost); } private: typename Base::GMPCodecType* mGMP; bool mShouldBeEqual; }; typename Base::GMPCodecType* mGMP; nsCString mOrigin2; bool mShouldBeEqual; }; typedef RunTestGMPCrossOrigin RunTestGMPVideoDecoderCrossOrigin; typedef RunTestGMPCrossOrigin RunTestGMPVideoEncoderCrossOrigin; void GMPTestRunner::RunTestGMPCrossOrigin1(GMPTestMonitor& aMonitor) { RunTestGMPVideoDecoderCrossOrigin::Run(aMonitor, "origin1"_ns, "origin2"_ns); } void GMPTestRunner::RunTestGMPCrossOrigin2(GMPTestMonitor& aMonitor) { RunTestGMPVideoEncoderCrossOrigin::Run(aMonitor, "origin1"_ns, "origin2"_ns); } void GMPTestRunner::RunTestGMPCrossOrigin3(GMPTestMonitor& aMonitor) { RunTestGMPVideoDecoderCrossOrigin::Run(aMonitor, "origin1"_ns, "origin1"_ns); } void GMPTestRunner::RunTestGMPCrossOrigin4(GMPTestMonitor& aMonitor) { RunTestGMPVideoEncoderCrossOrigin::Run(aMonitor, "origin1"_ns, "origin1"_ns); } void GMPTestRunner::DoTest( void (GMPTestRunner::*aTestMethod)(GMPTestMonitor&)) { RefPtr service = GeckoMediaPluginService::GetGeckoMediaPluginService(); nsCOMPtr thread; EXPECT_NS_SUCCEEDED(service->GetThread(getter_AddRefs(thread))); GMPTestMonitor monitor; thread->Dispatch(NewRunnableMethod( "GMPTestRunner::DoTest", this, aTestMethod, monitor), NS_DISPATCH_NORMAL); monitor.AwaitFinished(); } // Bug 1776767 - Skip all GMP tests on Windows ASAN #if !(defined(XP_WIN) && defined(MOZ_ASAN)) TEST(GeckoMediaPlugins, GMPTestCodec) { RefPtr runner = new GMPTestRunner(); runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec1); runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec2); runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec3); } TEST(GeckoMediaPlugins, GMPCrossOrigin) { RefPtr runner = new GMPTestRunner(); runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin1); runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin2); runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin3); runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin4); } #endif // !(defined(XP_WIN) && defined(MOZ_ASAN))