media_foundation_cdm_unittest.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/cdm/win/media_foundation_cdm.h"
  5. #include <wchar.h>
  6. #include "base/bind.h"
  7. #include "base/strings/utf_string_conversions.h"
  8. #include "base/test/mock_callback.h"
  9. #include "base/test/task_environment.h"
  10. #include "media/base/mock_filters.h"
  11. #include "media/base/test_helpers.h"
  12. #include "media/base/win/media_foundation_cdm_proxy.h"
  13. #include "media/base/win/mf_helpers.h"
  14. #include "media/base/win/mf_mocks.h"
  15. #include "testing/gmock/include/gmock/gmock.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. using ::testing::_;
  18. using ::testing::DoAll;
  19. using ::testing::InSequence;
  20. using ::testing::IsEmpty;
  21. using ::testing::NotNull;
  22. using ::testing::Return;
  23. using ::testing::SetArgPointee;
  24. using ::testing::SetArgReferee;
  25. using ::testing::StrEq;
  26. using ::testing::StrictMock;
  27. using ::testing::WithoutArgs;
  28. namespace media {
  29. namespace {
  30. const char kSessionId[] = "session_id";
  31. const double kExpirationMs = 123456789.0;
  32. const auto kExpirationTime = base::Time::FromJsTime(kExpirationMs);
  33. const char kTestUmaPrefix[] = "Media.EME.TestUmaPrefix.";
  34. std::vector<uint8_t> StringToVector(const std::string& str) {
  35. return std::vector<uint8_t>(str.begin(), str.end());
  36. }
  37. // testing::InvokeArgument<N> does not work with base::OnceCallback. Use this
  38. // gmock action template to invoke base::OnceCallback. `k` is the k-th argument
  39. // and `T` is the callback's type.
  40. ACTION_TEMPLATE(InvokeCallbackArgument,
  41. HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
  42. AND_1_VALUE_PARAMS(p0)) {
  43. std::move(const_cast<T&>(std::get<k>(args))).Run(p0);
  44. }
  45. } // namespace
  46. using Microsoft::WRL::ComPtr;
  47. class MediaFoundationCdmTest : public testing::Test {
  48. public:
  49. MediaFoundationCdmTest()
  50. : mf_cdm_(MakeComPtr<MockMFCdm>()),
  51. mf_cdm_session_(MakeComPtr<MockMFCdmSession>()),
  52. cdm_(base::MakeRefCounted<MediaFoundationCdm>(
  53. kTestUmaPrefix,
  54. base::BindRepeating(&MediaFoundationCdmTest::CreateMFCdm,
  55. base::Unretained(this)),
  56. is_type_supported_cb_.Get(),
  57. store_client_token_cb_.Get(),
  58. cdm_event_cb_.Get(),
  59. base::BindRepeating(&MockCdmClient::OnSessionMessage,
  60. base::Unretained(&cdm_client_)),
  61. base::BindRepeating(&MockCdmClient::OnSessionClosed,
  62. base::Unretained(&cdm_client_)),
  63. base::BindRepeating(&MockCdmClient::OnSessionKeysChange,
  64. base::Unretained(&cdm_client_)),
  65. base::BindRepeating(&MockCdmClient::OnSessionExpirationUpdate,
  66. base::Unretained(&cdm_client_)))) {}
  67. ~MediaFoundationCdmTest() override = default;
  68. void CreateMFCdm(HRESULT& hresult,
  69. Microsoft::WRL::ComPtr<IMFContentDecryptionModule>& mf_cdm) {
  70. if (can_initialize_) {
  71. hresult = S_OK;
  72. mf_cdm = mf_cdm_;
  73. } else {
  74. hresult = E_FAIL;
  75. mf_cdm.Reset();
  76. }
  77. }
  78. void Initialize() { ASSERT_SUCCESS(cdm_->Initialize()); }
  79. void InitializeAndExpectFailure() {
  80. can_initialize_ = false;
  81. EXPECT_CALL(cdm_event_cb_, Run(CdmEvent::kCdmError));
  82. ASSERT_FAILED(cdm_->Initialize());
  83. }
  84. void SetGenerateRequestExpectations(
  85. ComPtr<MockMFCdmSession> mf_cdm_session,
  86. const char* session_id,
  87. IMFContentDecryptionModuleSessionCallbacks** mf_cdm_session_callbacks,
  88. bool expect_message = true) {
  89. std::vector<uint8_t> license_request = StringToVector("request");
  90. // Session ID to return. Will be released by |mf_cdm_session_|.
  91. std::wstring wide_session_id = base::UTF8ToWide(session_id);
  92. LPWSTR mf_session_id = nullptr;
  93. ASSERT_SUCCESS(
  94. CopyCoTaskMemWideString(wide_session_id.data(), &mf_session_id));
  95. COM_EXPECT_CALL(mf_cdm_session,
  96. GenerateRequest(StrEq(L"webm"), NotNull(), _))
  97. .WillOnce(WithoutArgs([=] { // Capture local variables by value.
  98. (*mf_cdm_session_callbacks)
  99. ->KeyMessage(MF_MEDIAKEYSESSION_MESSAGETYPE_LICENSE_REQUEST,
  100. license_request.data(), license_request.size(),
  101. nullptr);
  102. return S_OK;
  103. }));
  104. COM_EXPECT_CALL(mf_cdm_session, GetSessionId(_))
  105. .WillOnce(DoAll(SetArgPointee<0>(mf_session_id), Return(S_OK)));
  106. if (expect_message) {
  107. EXPECT_CALL(cdm_client_,
  108. OnSessionMessage(session_id, CdmMessageType::LICENSE_REQUEST,
  109. license_request));
  110. }
  111. }
  112. void CreateSessionAndGenerateRequest() {
  113. std::vector<uint8_t> init_data = StringToVector("init_data");
  114. COM_EXPECT_CALL(mf_cdm_,
  115. CreateSession(MF_MEDIAKEYSESSION_TYPE_TEMPORARY, _, _))
  116. .WillOnce(DoAll(SaveComPtr<1>(&mf_cdm_session_callbacks_),
  117. SetComPointee<2>(mf_cdm_session_.Get()), Return(S_OK)));
  118. SetGenerateRequestExpectations(mf_cdm_session_, kSessionId,
  119. &mf_cdm_session_callbacks_);
  120. cdm_->CreateSessionAndGenerateRequest(
  121. CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
  122. std::make_unique<MockCdmSessionPromise>(/*expect_success=*/true,
  123. &session_id_));
  124. task_environment_.RunUntilIdle();
  125. EXPECT_EQ(session_id_, kSessionId);
  126. }
  127. protected:
  128. base::test::TaskEnvironment task_environment_;
  129. StrictMock<MockCdmClient> cdm_client_;
  130. StrictMock<base::MockCallback<MediaFoundationCdm::IsTypeSupportedCB>>
  131. is_type_supported_cb_;
  132. base::MockCallback<MediaFoundationCdm::StoreClientTokenCB>
  133. store_client_token_cb_;
  134. StrictMock<base::MockCallback<MediaFoundationCdm::CdmEventCB>> cdm_event_cb_;
  135. ComPtr<MockMFCdm> mf_cdm_;
  136. ComPtr<MockMFCdmSession> mf_cdm_session_;
  137. ComPtr<IMFContentDecryptionModuleSessionCallbacks> mf_cdm_session_callbacks_;
  138. scoped_refptr<MediaFoundationCdm> cdm_;
  139. bool can_initialize_ = true;
  140. std::string session_id_;
  141. scoped_refptr<MediaFoundationCdmProxy> mf_cdm_proxy_;
  142. };
  143. TEST_F(MediaFoundationCdmTest, SetServerCertificate) {
  144. Initialize();
  145. std::vector<uint8_t> certificate = StringToVector("certificate");
  146. COM_EXPECT_CALL(mf_cdm_,
  147. SetServerCertificate(certificate.data(), certificate.size()))
  148. .WillOnce(Return(S_OK));
  149. cdm_->SetServerCertificate(
  150. certificate, std::make_unique<MockCdmPromise>(/*expect_success=*/true));
  151. }
  152. TEST_F(MediaFoundationCdmTest, SetServerCertificate_Failure) {
  153. Initialize();
  154. std::vector<uint8_t> certificate = StringToVector("certificate");
  155. COM_EXPECT_CALL(mf_cdm_,
  156. SetServerCertificate(certificate.data(), certificate.size()))
  157. .WillOnce(Return(E_FAIL));
  158. cdm_->SetServerCertificate(
  159. certificate, std::make_unique<MockCdmPromise>(/*expect_success=*/false));
  160. }
  161. TEST_F(MediaFoundationCdmTest, GetStatusForPolicy_HdcpNone_KeyStatusUsable) {
  162. Initialize();
  163. CdmKeyInformation::KeyStatus key_status;
  164. cdm_->GetStatusForPolicy(HdcpVersion::kHdcpVersionNone,
  165. std::make_unique<MockCdmKeyStatusPromise>(
  166. /*expect_success=*/true, &key_status));
  167. EXPECT_EQ(CdmKeyInformation::KeyStatus::USABLE, key_status);
  168. }
  169. TEST_F(MediaFoundationCdmTest, GetStatusForPolicy_HdcpV1_1_KeyStatusUsable) {
  170. Initialize();
  171. EXPECT_CALL(is_type_supported_cb_,
  172. Run("video/mp4;codecs=\"avc1\";features=\"hdcp=1\"", _))
  173. .WillOnce(
  174. InvokeCallbackArgument<1,
  175. MediaFoundationCdm::IsTypeSupportedResultCB>(
  176. /*is_supported=*/true));
  177. CdmKeyInformation::KeyStatus key_status;
  178. cdm_->GetStatusForPolicy(HdcpVersion::kHdcpVersion1_1,
  179. std::make_unique<MockCdmKeyStatusPromise>(
  180. /*expect_success=*/true, &key_status));
  181. EXPECT_EQ(CdmKeyInformation::KeyStatus::USABLE, key_status);
  182. }
  183. TEST_F(MediaFoundationCdmTest,
  184. GetStatusForPolicy_HdcpV2_3_KeyStatusOutputRestricted) {
  185. Initialize();
  186. EXPECT_CALL(is_type_supported_cb_,
  187. Run("video/mp4;codecs=\"avc1\";features=\"hdcp=2\"", _))
  188. .WillOnce(
  189. InvokeCallbackArgument<1,
  190. MediaFoundationCdm::IsTypeSupportedResultCB>(
  191. /*is_supported=*/false));
  192. CdmKeyInformation::KeyStatus key_status;
  193. cdm_->GetStatusForPolicy(HdcpVersion::kHdcpVersion2_3,
  194. std::make_unique<MockCdmKeyStatusPromise>(
  195. /*expect_success=*/true, &key_status));
  196. EXPECT_EQ(CdmKeyInformation::KeyStatus::OUTPUT_RESTRICTED, key_status);
  197. }
  198. TEST_F(MediaFoundationCdmTest, CreateSessionAndGenerateRequest) {
  199. Initialize();
  200. CreateSessionAndGenerateRequest();
  201. }
  202. // Tests the case where two sessions are being created in parallel.
  203. TEST_F(MediaFoundationCdmTest, CreateSessionAndGenerateRequest_Parallel) {
  204. Initialize();
  205. std::vector<uint8_t> init_data = StringToVector("init_data");
  206. const char kSessionId1[] = "session_id_1";
  207. const char kSessionId2[] = "session_id_2";
  208. auto mf_cdm_session_1 = MakeComPtr<MockMFCdmSession>();
  209. auto mf_cdm_session_2 = MakeComPtr<MockMFCdmSession>();
  210. ComPtr<IMFContentDecryptionModuleSessionCallbacks> mf_cdm_session_callbacks_1;
  211. ComPtr<IMFContentDecryptionModuleSessionCallbacks> mf_cdm_session_callbacks_2;
  212. COM_EXPECT_CALL(mf_cdm_,
  213. CreateSession(MF_MEDIAKEYSESSION_TYPE_TEMPORARY, _, _))
  214. .WillOnce(DoAll(SaveComPtr<1>(&mf_cdm_session_callbacks_1),
  215. SetComPointee<2>(mf_cdm_session_1.Get()), Return(S_OK)))
  216. .WillOnce(DoAll(SaveComPtr<1>(&mf_cdm_session_callbacks_2),
  217. SetComPointee<2>(mf_cdm_session_2.Get()), Return(S_OK)));
  218. SetGenerateRequestExpectations(mf_cdm_session_1, kSessionId1,
  219. &mf_cdm_session_callbacks_1);
  220. SetGenerateRequestExpectations(mf_cdm_session_2, kSessionId2,
  221. &mf_cdm_session_callbacks_2);
  222. std::string session_id_1;
  223. std::string session_id_2;
  224. cdm_->CreateSessionAndGenerateRequest(
  225. CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
  226. std::make_unique<MockCdmSessionPromise>(/*expect_success=*/true,
  227. &session_id_1));
  228. cdm_->CreateSessionAndGenerateRequest(
  229. CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
  230. std::make_unique<MockCdmSessionPromise>(/*expect_success=*/true,
  231. &session_id_2));
  232. task_environment_.RunUntilIdle();
  233. EXPECT_EQ(session_id_1, kSessionId1);
  234. EXPECT_EQ(session_id_2, kSessionId2);
  235. }
  236. TEST_F(MediaFoundationCdmTest, InitializeFailure) {
  237. InitializeAndExpectFailure();
  238. std::vector<uint8_t> init_data = StringToVector("init_data");
  239. cdm_->CreateSessionAndGenerateRequest(
  240. CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
  241. std::make_unique<MockCdmSessionPromise>(/*expect_success=*/false,
  242. &session_id_));
  243. task_environment_.RunUntilIdle();
  244. EXPECT_TRUE(session_id_.empty());
  245. }
  246. TEST_F(MediaFoundationCdmTest,
  247. CreateSessionAndGenerateRequest_CreateSessionFailure) {
  248. Initialize();
  249. COM_EXPECT_CALL(mf_cdm_,
  250. CreateSession(MF_MEDIAKEYSESSION_TYPE_TEMPORARY, _, _))
  251. .WillOnce(Return(E_FAIL));
  252. std::vector<uint8_t> init_data = StringToVector("init_data");
  253. cdm_->CreateSessionAndGenerateRequest(
  254. CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
  255. std::make_unique<MockCdmSessionPromise>(/*expect_success=*/false,
  256. &session_id_));
  257. task_environment_.RunUntilIdle();
  258. EXPECT_TRUE(session_id_.empty());
  259. }
  260. TEST_F(MediaFoundationCdmTest,
  261. CreateSessionAndGenerateRequest_GenerateRequestFailure) {
  262. Initialize();
  263. COM_EXPECT_CALL(mf_cdm_,
  264. CreateSession(MF_MEDIAKEYSESSION_TYPE_TEMPORARY, _, _))
  265. .WillOnce(DoAll(SaveComPtr<1>(&mf_cdm_session_callbacks_),
  266. SetComPointee<2>(mf_cdm_session_.Get()), Return(S_OK)));
  267. std::vector<uint8_t> init_data = StringToVector("init_data");
  268. COM_EXPECT_CALL(mf_cdm_session_,
  269. GenerateRequest(StrEq(L"webm"), NotNull(), init_data.size()))
  270. .WillOnce(Return(E_FAIL));
  271. cdm_->CreateSessionAndGenerateRequest(
  272. CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
  273. std::make_unique<MockCdmSessionPromise>(/*expect_success=*/false,
  274. &session_id_));
  275. task_environment_.RunUntilIdle();
  276. EXPECT_TRUE(session_id_.empty());
  277. }
  278. // Duplicate session IDs cause session creation failure.
  279. TEST_F(MediaFoundationCdmTest,
  280. CreateSessionAndGenerateRequest_DuplicateSessionId) {
  281. Initialize();
  282. auto mf_cdm_session_1 = MakeComPtr<MockMFCdmSession>();
  283. auto mf_cdm_session_2 = MakeComPtr<MockMFCdmSession>();
  284. ComPtr<IMFContentDecryptionModuleSessionCallbacks> mf_cdm_session_callbacks_1;
  285. ComPtr<IMFContentDecryptionModuleSessionCallbacks> mf_cdm_session_callbacks_2;
  286. COM_EXPECT_CALL(mf_cdm_,
  287. CreateSession(MF_MEDIAKEYSESSION_TYPE_TEMPORARY, _, _))
  288. .WillOnce(DoAll(SaveComPtr<1>(&mf_cdm_session_callbacks_1),
  289. SetComPointee<2>(mf_cdm_session_1.Get()), Return(S_OK)))
  290. .WillOnce(DoAll(SaveComPtr<1>(&mf_cdm_session_callbacks_2),
  291. SetComPointee<2>(mf_cdm_session_2.Get()), Return(S_OK)));
  292. // In both sessions we return kSessionId. Session 1 succeeds. Session 2 fails
  293. // because of duplicate session ID.
  294. SetGenerateRequestExpectations(mf_cdm_session_1, kSessionId,
  295. &mf_cdm_session_callbacks_1);
  296. SetGenerateRequestExpectations(mf_cdm_session_2, kSessionId,
  297. &mf_cdm_session_callbacks_2,
  298. /*expect_message=*/false);
  299. std::string session_id_1;
  300. std::string session_id_2;
  301. std::vector<uint8_t> init_data = StringToVector("init_data");
  302. cdm_->CreateSessionAndGenerateRequest(
  303. CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
  304. std::make_unique<MockCdmSessionPromise>(/*expect_success=*/true,
  305. &session_id_1));
  306. cdm_->CreateSessionAndGenerateRequest(
  307. CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
  308. std::make_unique<MockCdmSessionPromise>(/*expect_success=*/false,
  309. &session_id_2));
  310. task_environment_.RunUntilIdle();
  311. EXPECT_EQ(session_id_1, kSessionId);
  312. EXPECT_TRUE(session_id_2.empty());
  313. }
  314. // LoadSession() is not implemented.
  315. TEST_F(MediaFoundationCdmTest, LoadSession) {
  316. Initialize();
  317. cdm_->LoadSession(CdmSessionType::kPersistentLicense, kSessionId,
  318. std::make_unique<MockCdmSessionPromise>(
  319. /*expect_success=*/false, &session_id_));
  320. task_environment_.RunUntilIdle();
  321. EXPECT_TRUE(session_id_.empty());
  322. }
  323. TEST_F(MediaFoundationCdmTest, UpdateSession) {
  324. Initialize();
  325. CreateSessionAndGenerateRequest();
  326. std::vector<uint8_t> response = StringToVector("response");
  327. COM_EXPECT_CALL(mf_cdm_session_, Update(NotNull(), response.size()))
  328. .WillOnce(DoAll([&] { mf_cdm_session_callbacks_->KeyStatusChanged(); },
  329. Return(S_OK)));
  330. COM_EXPECT_CALL(mf_cdm_session_, GetKeyStatuses(_, _)).WillOnce(Return(S_OK));
  331. COM_EXPECT_CALL(mf_cdm_session_, GetExpiration(_))
  332. .WillOnce(DoAll(SetArgPointee<0>(kExpirationMs), Return(S_OK)));
  333. EXPECT_CALL(cdm_client_, OnSessionKeysChangeCalled(_, true));
  334. EXPECT_CALL(cdm_client_, OnSessionExpirationUpdate(_, kExpirationTime));
  335. cdm_->UpdateSession(
  336. session_id_, response,
  337. std::make_unique<MockCdmPromise>(/*expect_success=*/true));
  338. task_environment_.RunUntilIdle();
  339. }
  340. TEST_F(MediaFoundationCdmTest, UpdateSession_InvalidSessionId) {
  341. Initialize();
  342. CreateSessionAndGenerateRequest();
  343. std::vector<uint8_t> response = StringToVector("response");
  344. cdm_->UpdateSession(
  345. "invalid_session_id", response,
  346. std::make_unique<MockCdmPromise>(/*expect_success=*/false));
  347. task_environment_.RunUntilIdle();
  348. }
  349. TEST_F(MediaFoundationCdmTest, UpdateSession_Failure) {
  350. Initialize();
  351. CreateSessionAndGenerateRequest();
  352. std::vector<uint8_t> response = StringToVector("response");
  353. COM_EXPECT_CALL(mf_cdm_session_, Update(NotNull(), response.size()))
  354. .WillOnce(Return(E_FAIL));
  355. cdm_->UpdateSession(
  356. session_id_, response,
  357. std::make_unique<MockCdmPromise>(/*expect_success=*/false));
  358. task_environment_.RunUntilIdle();
  359. }
  360. TEST_F(MediaFoundationCdmTest, CloseSession) {
  361. Initialize();
  362. CreateSessionAndGenerateRequest();
  363. COM_EXPECT_CALL(mf_cdm_session_, Close()).WillOnce(Return(S_OK));
  364. EXPECT_CALL(cdm_client_,
  365. OnSessionClosed(kSessionId, CdmSessionClosedReason::kClose));
  366. cdm_->CloseSession(session_id_,
  367. std::make_unique<MockCdmPromise>(/*expect_success=*/true));
  368. task_environment_.RunUntilIdle();
  369. }
  370. TEST_F(MediaFoundationCdmTest, CloseSession_Failure) {
  371. Initialize();
  372. CreateSessionAndGenerateRequest();
  373. COM_EXPECT_CALL(mf_cdm_session_, Close()).WillOnce(Return(E_FAIL));
  374. cdm_->CloseSession(
  375. session_id_, std::make_unique<MockCdmPromise>(/*expect_success=*/false));
  376. task_environment_.RunUntilIdle();
  377. }
  378. TEST_F(MediaFoundationCdmTest, RemoveSession) {
  379. Initialize();
  380. CreateSessionAndGenerateRequest();
  381. COM_EXPECT_CALL(mf_cdm_session_, Remove()).WillOnce(Return(S_OK));
  382. COM_EXPECT_CALL(mf_cdm_session_, GetExpiration(_))
  383. .WillOnce(DoAll(SetArgPointee<0>(kExpirationMs), Return(S_OK)));
  384. EXPECT_CALL(cdm_client_, OnSessionExpirationUpdate(_, kExpirationTime));
  385. cdm_->RemoveSession(
  386. session_id_, std::make_unique<MockCdmPromise>(/*expect_success=*/true));
  387. task_environment_.RunUntilIdle();
  388. }
  389. TEST_F(MediaFoundationCdmTest, RemoveSession_Failure) {
  390. Initialize();
  391. CreateSessionAndGenerateRequest();
  392. COM_EXPECT_CALL(mf_cdm_session_, Remove()).WillOnce(Return(E_FAIL));
  393. cdm_->RemoveSession(
  394. session_id_, std::make_unique<MockCdmPromise>(/*expect_success=*/false));
  395. task_environment_.RunUntilIdle();
  396. }
  397. TEST_F(MediaFoundationCdmTest, HardwareContextReset) {
  398. Initialize();
  399. CreateSessionAndGenerateRequest();
  400. CdmContext* cdm_context = cdm_->GetCdmContext();
  401. mf_cdm_proxy_ = cdm_context->GetMediaFoundationCdmProxy();
  402. task_environment_.RunUntilIdle();
  403. ASSERT_TRUE(mf_cdm_proxy_);
  404. COM_EXPECT_CALL(mf_cdm_session_, Close()).WillOnce(Return(S_OK));
  405. EXPECT_CALL(cdm_client_,
  406. OnSessionClosed(kSessionId,
  407. CdmSessionClosedReason::kHardwareContextReset));
  408. mf_cdm_proxy_->OnHardwareContextReset();
  409. // Create a new session and expect success.
  410. CreateSessionAndGenerateRequest();
  411. }
  412. TEST_F(MediaFoundationCdmTest, HardwareContextReset_InitializeFailure) {
  413. Initialize();
  414. CreateSessionAndGenerateRequest();
  415. CdmContext* cdm_context = cdm_->GetCdmContext();
  416. mf_cdm_proxy_ = cdm_context->GetMediaFoundationCdmProxy();
  417. task_environment_.RunUntilIdle();
  418. ASSERT_TRUE(mf_cdm_proxy_);
  419. // Make the next `Initialize()` fail.
  420. can_initialize_ = false;
  421. EXPECT_CALL(cdm_event_cb_, Run(CdmEvent::kCdmError));
  422. COM_EXPECT_CALL(mf_cdm_session_, Close()).WillOnce(Return(S_OK));
  423. EXPECT_CALL(cdm_client_,
  424. OnSessionClosed(kSessionId,
  425. CdmSessionClosedReason::kHardwareContextReset));
  426. mf_cdm_proxy_->OnHardwareContextReset();
  427. std::vector<uint8_t> init_data = StringToVector("init_data");
  428. cdm_->CreateSessionAndGenerateRequest(
  429. CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
  430. std::make_unique<MockCdmSessionPromise>(/*expect_success=*/false,
  431. &session_id_));
  432. task_environment_.RunUntilIdle();
  433. }
  434. } // namespace media