cast_content_client.cc 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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 "chromecast/common/cast_content_client.h"
  5. #include <stdint.h>
  6. #include <memory>
  7. #include <utility>
  8. #include "base/command_line.h"
  9. #include "base/files/file_util.h"
  10. #include "base/native_library.h"
  11. #include "base/path_service.h"
  12. #include "base/strings/string_piece.h"
  13. #include "build/build_config.h"
  14. #include "chromecast/base/cast_constants.h"
  15. #include "chromecast/base/cast_paths.h"
  16. #include "chromecast/base/version.h"
  17. #include "chromecast/chromecast_buildflags.h"
  18. #include "components/cast/common/constants.h"
  19. #include "content/public/common/cdm_info.h"
  20. #include "media/base/media_switches.h"
  21. #include "media/media_buildflags.h"
  22. #include "mojo/public/cpp/bindings/binder_map.h"
  23. #include "third_party/widevine/cdm/buildflags.h"
  24. #include "ui/base/l10n/l10n_util.h"
  25. #include "ui/base/resource/resource_bundle.h"
  26. #include "url/url_util.h"
  27. #if BUILDFLAG(IS_ANDROID)
  28. #include "chromecast/common/media/cast_media_drm_bridge_client.h"
  29. #endif
  30. #if !BUILDFLAG(IS_FUCHSIA)
  31. #include "base/no_destructor.h"
  32. #include "components/services/heap_profiling/public/cpp/profiling_client.h" // nogncheck
  33. #include "mojo/public/cpp/bindings/pending_receiver.h"
  34. #endif
  35. #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
  36. #include "media/cdm/cdm_paths.h" // nogncheck
  37. #endif
  38. #if BUILDFLAG(BUNDLE_WIDEVINE_CDM) && BUILDFLAG(IS_LINUX)
  39. #include "base/no_destructor.h"
  40. #include "components/cdm/common/cdm_manifest.h"
  41. #include "media/cdm/cdm_capability.h"
  42. #include "third_party/widevine/cdm/widevine_cdm_common.h" // nogncheck
  43. // component updated CDM on all desktop platforms and remove this.
  44. // This file is In SHARED_INTERMEDIATE_DIR.
  45. #include "widevine_cdm_version.h" // nogncheck
  46. #endif
  47. namespace chromecast {
  48. namespace shell {
  49. namespace {
  50. #if BUILDFLAG(BUNDLE_WIDEVINE_CDM) && BUILDFLAG(IS_LINUX)
  51. // Copied from chrome_content_client.cc
  52. std::unique_ptr<content::CdmInfo> CreateWidevineCdmInfo(
  53. const base::Version& version,
  54. const base::FilePath& cdm_library_path,
  55. media::CdmCapability capability) {
  56. return std::make_unique<content::CdmInfo>(
  57. kWidevineKeySystem, content::CdmInfo::Robustness::kSoftwareSecure,
  58. std::move(capability), /*supports_sub_key_systems=*/false,
  59. kWidevineCdmDisplayName, kWidevineCdmType, version, cdm_library_path);
  60. }
  61. // On desktop Linux, given |cdm_base_path| that points to a folder containing
  62. // the Widevine CDM and associated files, read the manifest included in that
  63. // directory and create a CdmInfo. If that is successful, return the CdmInfo. If
  64. // not, return nullptr.
  65. // Copied from chrome_content_client.cc
  66. // TODO(crbug.com/1174571): move the functions to a common file.
  67. std::unique_ptr<content::CdmInfo> CreateCdmInfoFromWidevineDirectory(
  68. const base::FilePath& cdm_base_path) {
  69. // Library should be inside a platform specific directory.
  70. auto cdm_library_path =
  71. media::GetPlatformSpecificDirectory(cdm_base_path)
  72. .Append(base::GetNativeLibraryName(kWidevineCdmLibraryName));
  73. if (!base::PathExists(cdm_library_path)) {
  74. LOG(ERROR) << "cdm library path doesn't exist";
  75. return nullptr;
  76. }
  77. // Manifest should be at the top level.
  78. auto manifest_path = cdm_base_path.Append(FILE_PATH_LITERAL("manifest.json"));
  79. base::Version version;
  80. media::CdmCapability capability;
  81. if (!ParseCdmManifestFromPath(manifest_path, &version, &capability))
  82. return nullptr;
  83. return CreateWidevineCdmInfo(version, cdm_library_path,
  84. std::move(capability));
  85. }
  86. // This code checks to see if the Widevine CDM was bundled with Chrome. If one
  87. // can be found and looks valid, it returns the CdmInfo for the CDM. Otherwise
  88. // it returns nullptr.
  89. // Copied from chrome_content_client.cc
  90. content::CdmInfo* GetBundledWidevine() {
  91. // We only want to do this on the first call, as if Widevine wasn't bundled
  92. // with Chrome (or it was deleted/removed) it won't be loaded into the zygote.
  93. static base::NoDestructor<std::unique_ptr<content::CdmInfo>> s_cdm_info(
  94. []() -> std::unique_ptr<content::CdmInfo> {
  95. base::FilePath install_dir;
  96. CHECK(base::PathService::Get(chromecast::DIR_BUNDLED_WIDEVINE_CDM,
  97. &install_dir));
  98. // On desktop Linux the MANIFEST is bundled with the CDM.
  99. return CreateCdmInfoFromWidevineDirectory(install_dir);
  100. }());
  101. return s_cdm_info->get();
  102. }
  103. #endif // BUILDFLAG(BUNDLE_WIDEVINE_CDM) && BUILDFLAG(IS_LINUX)
  104. } // namespace
  105. CastContentClient::~CastContentClient() {
  106. }
  107. void CastContentClient::SetActiveURL(const GURL& url, std::string top_origin) {
  108. if (url.is_empty() || url == last_active_url_)
  109. return;
  110. LOG(INFO) << "Active URL: " << url.possibly_invalid_spec() << " for origin '"
  111. << top_origin << "'";
  112. last_active_url_ = url;
  113. }
  114. void CastContentClient::AddAdditionalSchemes(Schemes* schemes) {
  115. schemes->standard_schemes.push_back(kChromeResourceScheme);
  116. }
  117. std::u16string CastContentClient::GetLocalizedString(int message_id) {
  118. return l10n_util::GetStringUTF16(message_id);
  119. }
  120. base::StringPiece CastContentClient::GetDataResource(
  121. int resource_id,
  122. ui::ResourceScaleFactor scale_factor) {
  123. return ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
  124. resource_id, scale_factor);
  125. }
  126. base::RefCountedMemory* CastContentClient::GetDataResourceBytes(
  127. int resource_id) {
  128. // Chromecast loads localized resources for the home screen via this code
  129. // path. See crbug.com/643886 for details.
  130. return ui::ResourceBundle::GetSharedInstance().LoadLocalizedResourceBytes(
  131. resource_id);
  132. }
  133. std::string CastContentClient::GetDataResourceString(int resource_id) {
  134. return ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
  135. resource_id);
  136. }
  137. gfx::Image& CastContentClient::GetNativeImageNamed(int resource_id) {
  138. return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
  139. resource_id);
  140. }
  141. #if BUILDFLAG(IS_ANDROID)
  142. ::media::MediaDrmBridgeClient* CastContentClient::GetMediaDrmBridgeClient() {
  143. return new media::CastMediaDrmBridgeClient();
  144. }
  145. #endif // BUILDFLAG(IS_ANDROID)
  146. void CastContentClient::ExposeInterfacesToBrowser(
  147. scoped_refptr<base::SequencedTaskRunner> io_task_runner,
  148. mojo::BinderMap* binders) {
  149. #if !BUILDFLAG(IS_FUCHSIA)
  150. binders->Add<heap_profiling::mojom::ProfilingClient>(
  151. base::BindRepeating(
  152. [](mojo::PendingReceiver<heap_profiling::mojom::ProfilingClient>
  153. receiver) {
  154. static base::NoDestructor<heap_profiling::ProfilingClient>
  155. profiling_client;
  156. profiling_client->BindToInterface(std::move(receiver));
  157. }),
  158. io_task_runner);
  159. #endif // !BUILDFLAG(IS_FUCHSIA)
  160. }
  161. void CastContentClient::AddContentDecryptionModules(
  162. std::vector<content::CdmInfo>* cdms,
  163. std::vector<::media::CdmHostFilePath>* cdm_host_file_paths) {
  164. if (cdms) {
  165. #if BUILDFLAG(BUNDLE_WIDEVINE_CDM) && BUILDFLAG(IS_LINUX)
  166. // The Widevine CDM on Linux needs to be registered (and loaded) before the
  167. // zygote is locked down. The CDM can be found from the version bundled with
  168. // Chrome (if BUNDLE_WIDEVINE_CDM = true).
  169. content::CdmInfo* bundled_widevine = GetBundledWidevine();
  170. if (bundled_widevine) {
  171. DVLOG(1) << "Registering bundled Widevine " << bundled_widevine->version;
  172. cdms->push_back(*bundled_widevine);
  173. } else {
  174. DVLOG(1) << "Widevine enabled but no library found";
  175. }
  176. #endif // BUILDFLAG(BUNDLE_WIDEVINE_CDM) && BUILDFLAG(IS_LINUX)
  177. }
  178. }
  179. } // namespace shell
  180. } // namespace chromecast