fuchsia_web_debug_proxy.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright 2022 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/webinstance_host/fuchsia_web_debug_proxy.h"
  5. #include <lib/fidl/cpp/binding.h>
  6. #include "base/check.h"
  7. #include "base/containers/flat_set.h"
  8. #include "base/containers/unique_ptr_adapters.h"
  9. #include "base/fuchsia/fuchsia_logging.h"
  10. #include "base/logging.h"
  11. namespace {
  12. // Proxies notifications from a DevToolsPerContextListener channel connected
  13. // to a web container, to the specified set of DevToolsListeners.
  14. class PerContextListenerProxy final
  15. : public fuchsia::web::DevToolsPerContextListener {
  16. public:
  17. PerContextListenerProxy(
  18. fidl::InterfaceRequest<fuchsia::web::DevToolsPerContextListener> request,
  19. const fidl::InterfacePtrSet<fuchsia::web::DevToolsListener>& clients)
  20. : binding_(this, std::move(request)) {
  21. // Notify clients of the newly-available per-Context DevTools.
  22. for (const auto& client : clients.ptrs()) {
  23. fidl::InterfaceHandle<fuchsia::web::DevToolsPerContextListener> handle;
  24. (*client)->OnContextDevToolsAvailable(handle.NewRequest());
  25. auto ptr = std::make_unique<
  26. fidl::InterfacePtr<fuchsia::web::DevToolsPerContextListener>>(
  27. handle.Bind());
  28. // If the client disconnects then remove it. If no clients remain then
  29. // delete this proxy.
  30. ptr->set_error_handler([this, client = ptr.get()](zx_status_t status) {
  31. ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status);
  32. clients_.erase(client);
  33. if (clients_.empty())
  34. delete this;
  35. });
  36. clients_.insert(std::move(ptr));
  37. }
  38. // Delete this proxy if the instance goes-away.
  39. binding_.set_error_handler([this](zx_status_t status) {
  40. ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status);
  41. delete this;
  42. });
  43. }
  44. ~PerContextListenerProxy() override = default;
  45. // fuchsia::web::DevToolsPerContextListener implementation.
  46. void OnHttpPortOpen(uint16_t port) override {
  47. for (const auto& client : clients_) {
  48. (*client)->OnHttpPortOpen(port);
  49. }
  50. }
  51. private:
  52. fidl::Binding<fuchsia::web::DevToolsPerContextListener> binding_;
  53. // Connections to clients to which to propagate updates.
  54. base::flat_set<std::unique_ptr<fidl::InterfacePtr<
  55. fuchsia::web::DevToolsPerContextListener>>,
  56. base::UniquePtrComparator>
  57. clients_;
  58. };
  59. } // namespace
  60. FuchsiaWebDebugProxy::FuchsiaWebDebugProxy() = default;
  61. FuchsiaWebDebugProxy::~FuchsiaWebDebugProxy() = default;
  62. void FuchsiaWebDebugProxy::EnableDevTools(
  63. fidl::InterfaceHandle<fuchsia::web::DevToolsListener> listener,
  64. EnableDevToolsCallback callback) {
  65. // Add the listener to the active set, but do not inform it of any debuggable
  66. // instances that already exist, since callers are expected to only start
  67. // creating new instances after the callback has returned.
  68. devtools_listeners_.AddInterfacePtr(listener.Bind());
  69. // If there were statically-configured fuchsia.web.Debug instances configured
  70. // then they should be connected-to here, and |callback()| invoked only
  71. // when each static instance' |EnableDevTools()| call had completed, or
  72. // failed.
  73. callback();
  74. }
  75. void FuchsiaWebDebugProxy::RegisterInstance(
  76. fidl::InterfaceHandle<fuchsia::web::Debug> debug) {
  77. DCHECK(has_clients());
  78. // Create a new DevToolsListener binding, and connect it to the instance.
  79. fidl::InterfaceHandle<fuchsia::web::DevToolsListener> handle;
  80. instance_bindings_.AddBinding(this, handle.NewRequest());
  81. debug.Bind()->EnableDevTools(std::move(handle), {});
  82. }
  83. void FuchsiaWebDebugProxy::OnContextDevToolsAvailable(
  84. fidl::InterfaceRequest<fuchsia::web::DevToolsPerContextListener> request) {
  85. // Create a proxy to propagate notifications for this new per-Context
  86. // listener out to each of the clients.
  87. new PerContextListenerProxy(std::move(request), devtools_listeners_);
  88. }