pending_cast_component.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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 "fuchsia_web/runners/cast/pending_cast_component.h"
  5. #include "base/bind.h"
  6. #include "base/check.h"
  7. #include "base/fuchsia/fuchsia_logging.h"
  8. #include "base/strings/string_piece.h"
  9. #include "fuchsia_web/runners/common/modular/agent_manager.h"
  10. PendingCastComponent::PendingCastComponent(
  11. Delegate* delegate,
  12. std::unique_ptr<base::StartupContext> startup_context,
  13. fidl::InterfaceRequest<fuchsia::sys::ComponentController>
  14. controller_request,
  15. base::StringPiece app_id)
  16. : delegate_(delegate), app_id_(app_id) {
  17. DCHECK(startup_context);
  18. DCHECK(controller_request);
  19. // Store the supplied CastComponent parameters in |params_|.
  20. params_.startup_context = std::move(startup_context);
  21. params_.controller_request = std::move(controller_request);
  22. // Request the application's configuration, including the identity of the
  23. // Agent that should provide component-specific resources, e.g. API bindings.
  24. // TODO(https://crbug.com/1065707): Access the ApplicationConfigManager via
  25. // the Runner's incoming service directory once it is available there.
  26. params_.startup_context->svc()->Connect(
  27. application_config_manager_.NewRequest());
  28. application_config_manager_.set_error_handler([this](zx_status_t status) {
  29. ZX_LOG(ERROR, status) << "ApplicationConfigManager disconnected.";
  30. delegate_->CancelPendingComponent(this);
  31. });
  32. application_config_manager_->GetConfig(
  33. std::string(app_id),
  34. fit::bind_member(this,
  35. &PendingCastComponent::OnApplicationConfigReceived));
  36. // Create the AgentManager through which component-specific Agent services
  37. // will be connected.
  38. // TODO(https://crbug.com/1065709): Migrate off the ConnectToAgentService()
  39. // API and remove the cr_fuchsia::AgentManager.
  40. params_.agent_manager = std::make_unique<cr_fuchsia::AgentManager>(
  41. params_.startup_context->component_context()->svc().get());
  42. }
  43. PendingCastComponent::~PendingCastComponent() = default;
  44. void PendingCastComponent::OnApplicationConfigReceived(
  45. chromium::cast::ApplicationConfig application_config) {
  46. if (application_config.IsEmpty()) {
  47. DLOG(WARNING) << "No application config was found.";
  48. delegate_->CancelPendingComponent(this);
  49. return;
  50. }
  51. if (!application_config.has_web_url()) {
  52. DLOG(WARNING) << "Only web-based applications are supported.";
  53. delegate_->CancelPendingComponent(this);
  54. return;
  55. }
  56. if (!application_config.has_agent_url()) {
  57. DLOG(WARNING) << "No agent has been associated with this app.";
  58. delegate_->CancelPendingComponent(this);
  59. return;
  60. }
  61. params_.application_config = std::move(application_config);
  62. // Request custom API bindings from the component's Agent.
  63. params_.api_bindings_client = std::make_unique<ApiBindingsClient>(
  64. params_.agent_manager->ConnectToAgentService<chromium::cast::ApiBindings>(
  65. params_.application_config.agent_url()),
  66. base::BindOnce(&PendingCastComponent::OnApiBindingsInitialized,
  67. base::Unretained(this)));
  68. // Request UrlRequestRewriteRulesProvider from the Agent.
  69. params_.agent_manager->ConnectToAgentService(
  70. params_.application_config.agent_url(),
  71. params_.url_rewrite_rules_provider.NewRequest());
  72. params_.url_rewrite_rules_provider.set_error_handler([this](
  73. zx_status_t status) {
  74. if (status != ZX_ERR_PEER_CLOSED) {
  75. ZX_LOG(ERROR, status) << "UrlRequestRewriteRulesProvider disconnected.";
  76. delegate_->CancelPendingComponent(this);
  77. return;
  78. }
  79. ZX_DLOG(WARNING, status) << "UrlRequestRewriteRulesProvider unsupported.";
  80. params_.initial_url_rewrite_rules =
  81. std::vector<fuchsia::web::UrlRequestRewriteRule>();
  82. MaybeLaunchComponent();
  83. });
  84. params_.url_rewrite_rules_provider->GetUrlRequestRewriteRules(
  85. [this](std::vector<fuchsia::web::UrlRequestRewriteRule> rewrite_rules) {
  86. params_.initial_url_rewrite_rules.emplace(std::move(rewrite_rules));
  87. MaybeLaunchComponent();
  88. });
  89. // Connect to the component-specific ApplicationContext to retrieve the
  90. // media-session identifier assigned to this instance.
  91. application_context_ =
  92. params_.agent_manager
  93. ->ConnectToAgentService<chromium::cast::ApplicationContext>(
  94. params_.application_config.agent_url());
  95. application_context_.set_error_handler([this](zx_status_t status) {
  96. ZX_LOG(ERROR, status) << "ApplicationContext disconnected.";
  97. delegate_->CancelPendingComponent(this);
  98. });
  99. if (params_.application_config.has_audio_renderer_usage()) {
  100. DCHECK(!params_.media_settings);
  101. params_.media_settings = fuchsia::web::FrameMediaSettings{};
  102. params_.media_settings->set_renderer_usage(
  103. params_.application_config.audio_renderer_usage());
  104. } else {
  105. // If `audio_renderer_usage` is not specified then `AudioConsumer` is used
  106. // for that app. We need to fetch `session_id` in that case.
  107. application_context_->GetMediaSessionId([this](uint64_t session_id) {
  108. DCHECK(!params_.media_settings);
  109. params_.media_settings = fuchsia::web::FrameMediaSettings{};
  110. if (session_id > 0)
  111. params_.media_settings->set_audio_consumer_session_id(session_id);
  112. MaybeLaunchComponent();
  113. });
  114. }
  115. }
  116. void PendingCastComponent::OnApiBindingsInitialized() {
  117. if (params_.api_bindings_client->HasBindings())
  118. MaybeLaunchComponent();
  119. else
  120. delegate_->CancelPendingComponent(this);
  121. }
  122. void PendingCastComponent::MaybeLaunchComponent() {
  123. if (!params_.AreComplete())
  124. return;
  125. // Clear the error handlers on InterfacePtr<>s before passing them, to avoid
  126. // user-after-free of |this|.
  127. params_.url_rewrite_rules_provider.set_error_handler(nullptr);
  128. params_.application_context = application_context_.Unbind();
  129. delegate_->LaunchPendingComponent(this, std::move(params_));
  130. }