cdm_service.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Copyright 2014 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/mojo/services/cdm_service.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/logging.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/memory/weak_ptr.h"
  10. #include "media/base/cdm_factory.h"
  11. #include "media/mojo/services/mojo_cdm_service.h"
  12. #include "media/mojo/services/mojo_cdm_service_context.h"
  13. #include "mojo/public/cpp/bindings/remote.h"
  14. #include "mojo/public/cpp/bindings/unique_receiver_set.h"
  15. namespace media {
  16. namespace {
  17. // Implementation of mojom::CdmFactory that creates and hosts MojoCdmServices
  18. // which then host CDMs created by the media::CdmFactory provided by the
  19. // CdmService::Client.
  20. //
  21. // Lifetime Note:
  22. // 1. CdmFactoryImpl instances are owned by a DeferredDestroyUniqueReceiverSet
  23. // directly, which is owned by CdmService.
  24. // 2. CdmFactoryImpl is destroyed in any of the following two cases:
  25. // - CdmService is destroyed. Because of (2) this should not happen except for
  26. // during browser shutdown, when the Cdservice could be destroyed directly,
  27. // ignoring any outstanding interface connections.
  28. // - mojo::CdmFactory disconnection happens, AND CdmFactoryImpl doesn't own
  29. // any CDMs (|cdm_receivers_| is empty). This is to prevent destroying the
  30. // CDMs too early (e.g. during page navigation) which could cause errors
  31. // (session closed) on the client side. See https://crbug.com/821171 for
  32. // details.
  33. class CdmFactoryImpl final : public DeferredDestroy<mojom::CdmFactory> {
  34. public:
  35. CdmFactoryImpl(CdmService::Client* client,
  36. mojo::PendingRemote<mojom::FrameInterfaceFactory> interfaces)
  37. : client_(client), interfaces_(std::move(interfaces)) {
  38. DVLOG(1) << __func__;
  39. // base::Unretained is safe because |cdm_receivers_| is owned by |this|. If
  40. // |this| is destructed, |cdm_receivers_| will be destructed as well and the
  41. // error handler should never be called.
  42. cdm_receivers_.set_disconnect_handler(base::BindRepeating(
  43. &CdmFactoryImpl::OnReceiverDisconnect, base::Unretained(this)));
  44. }
  45. CdmFactoryImpl(const CdmFactoryImpl&) = delete;
  46. CdmFactoryImpl operator=(const CdmFactoryImpl&) = delete;
  47. ~CdmFactoryImpl() final { DVLOG(1) << __func__; }
  48. // mojom::CdmFactory implementation.
  49. void CreateCdm(const CdmConfig& cdm_config,
  50. CreateCdmCallback callback) final {
  51. DVLOG(2) << __func__;
  52. auto* cdm_factory = GetCdmFactory();
  53. if (!cdm_factory) {
  54. std::move(callback).Run(mojo::NullRemote(), nullptr,
  55. "CDM Factory creation failed");
  56. return;
  57. }
  58. auto mojo_cdm_service =
  59. std::make_unique<MojoCdmService>(&cdm_service_context_);
  60. auto* raw_mojo_cdm_service = mojo_cdm_service.get();
  61. DCHECK(!pending_mojo_cdm_services_.count(raw_mojo_cdm_service));
  62. pending_mojo_cdm_services_[raw_mojo_cdm_service] =
  63. std::move(mojo_cdm_service);
  64. raw_mojo_cdm_service->Initialize(
  65. cdm_factory, cdm_config,
  66. base::BindOnce(&CdmFactoryImpl::OnCdmServiceInitialized,
  67. weak_ptr_factory_.GetWeakPtr(), raw_mojo_cdm_service,
  68. std::move(callback)));
  69. }
  70. // DeferredDestroy<mojom::CdmFactory> implemenation.
  71. void OnDestroyPending(base::OnceClosure destroy_cb) final {
  72. destroy_cb_ = std::move(destroy_cb);
  73. if (cdm_receivers_.empty())
  74. std::move(destroy_cb_).Run();
  75. // else the callback will be called when |cdm_receivers_| become empty.
  76. }
  77. private:
  78. media::CdmFactory* GetCdmFactory() {
  79. if (!cdm_factory_) {
  80. cdm_factory_ = client_->CreateCdmFactory(interfaces_.get());
  81. DLOG_IF(ERROR, !cdm_factory_) << "CdmFactory not available.";
  82. }
  83. return cdm_factory_.get();
  84. }
  85. void OnReceiverDisconnect() {
  86. if (destroy_cb_ && cdm_receivers_.empty())
  87. std::move(destroy_cb_).Run();
  88. }
  89. void OnCdmServiceInitialized(MojoCdmService* raw_mojo_cdm_service,
  90. CreateCdmCallback callback,
  91. mojom::CdmContextPtr cdm_context,
  92. const std::string& error_message) {
  93. DCHECK(raw_mojo_cdm_service);
  94. // Remove pending MojoCdmService from the mapping in all cases.
  95. DCHECK(pending_mojo_cdm_services_.count(raw_mojo_cdm_service));
  96. auto mojo_cdm_service =
  97. std::move(pending_mojo_cdm_services_[raw_mojo_cdm_service]);
  98. pending_mojo_cdm_services_.erase(raw_mojo_cdm_service);
  99. if (!cdm_context) {
  100. std::move(callback).Run(mojo::NullRemote(), nullptr, error_message);
  101. return;
  102. }
  103. mojo::PendingRemote<mojom::ContentDecryptionModule> remote;
  104. cdm_receivers_.Add(std::move(mojo_cdm_service),
  105. remote.InitWithNewPipeAndPassReceiver());
  106. std::move(callback).Run(std::move(remote), std::move(cdm_context), "");
  107. }
  108. // Must be declared before the receivers below because the bound objects might
  109. // take a raw pointer of |cdm_service_context_| and assume it's always
  110. // available.
  111. MojoCdmServiceContext cdm_service_context_;
  112. raw_ptr<CdmService::Client> client_;
  113. mojo::Remote<mojom::FrameInterfaceFactory> interfaces_;
  114. mojo::UniqueReceiverSet<mojom::ContentDecryptionModule> cdm_receivers_;
  115. std::unique_ptr<media::CdmFactory> cdm_factory_;
  116. base::OnceClosure destroy_cb_;
  117. // MojoCdmServices pending initialization.
  118. std::map<MojoCdmService*, std::unique_ptr<MojoCdmService>>
  119. pending_mojo_cdm_services_;
  120. // NOTE: Weak pointers must be invalidated before all other member variables.
  121. base::WeakPtrFactory<CdmFactoryImpl> weak_ptr_factory_{this};
  122. };
  123. } // namespace
  124. CdmService::CdmService(std::unique_ptr<Client> client,
  125. mojo::PendingReceiver<mojom::CdmService> receiver)
  126. : receiver_(this, std::move(receiver)), client_(std::move(client)) {
  127. DVLOG(1) << __func__;
  128. DCHECK(client_);
  129. }
  130. CdmService::~CdmService() {
  131. DVLOG(1) << __func__;
  132. }
  133. void CdmService::CreateCdmFactory(
  134. mojo::PendingReceiver<mojom::CdmFactory> receiver,
  135. mojo::PendingRemote<mojom::FrameInterfaceFactory> frame_interfaces) {
  136. // Ignore receiver if service has already stopped.
  137. if (!client_)
  138. return;
  139. cdm_factory_receivers_.Add(std::make_unique<CdmFactoryImpl>(
  140. client_.get(), std::move(frame_interfaces)),
  141. std::move(receiver));
  142. }
  143. } // namespace media