chromium/fuchsia_web/runners/cast/api_bindings_client.h

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FUCHSIA_WEB_RUNNERS_CAST_API_BINDINGS_CLIENT_H_
#define FUCHSIA_WEB_RUNNERS_CAST_API_BINDINGS_CLIENT_H_

#include <chromium/cast/cpp/fidl.h>
#include <fuchsia/web/cpp/fidl.h>

#include <optional>
#include <string_view>
#include <vector>

#include "base/memory/weak_ptr.h"
#include "components/cast/message_port/message_port.h"
#include "components/cast/named_message_port_connector/named_message_port_connector.h"

// Injects scripts received from the ApiBindings service, and provides connected
// ports to the Agent.
class ApiBindingsClient {
 public:
  // Reads bindings definitions from |bindings_service_| at construction time.
  // |on_initialization_complete| is invoked when either the initial bindings
  // have been received, or on failure. The caller should use HasBindings()
  // to verify that bindings were received, and may then use AttachToFrame().
  ApiBindingsClient(
      fidl::InterfaceHandle<chromium::cast::ApiBindings> bindings_service,
      base::OnceClosure on_initialization_complete);

  ApiBindingsClient(const ApiBindingsClient&) = delete;
  ApiBindingsClient& operator=(const ApiBindingsClient&) = delete;

  ~ApiBindingsClient();

  // Injects APIs and handles channel connections on |frame|.
  // |on_error_callback| is invoked asynchronusly in the event of an
  // unrecoverable error (e.g. lost connection to the Agent). The callback must
  // remain valid for the entire lifetime of |this|.
  void AttachToFrame(fuchsia::web::Frame* frame,
                     cast_api_bindings::NamedMessagePortConnector* connector,
                     base::OnceClosure on_error_callback);

  // Indicates that the Frame is no longer live, preventing the API bindings
  // client from attempting to remove injected bindings from it.
  void DetachFromFrame(fuchsia::web::Frame* frame);

  // Indicates that bindings were successfully received from
  // |bindings_service_|.
  bool HasBindings() const;

  // TODO(crbug.com/40131115): Move this method back to private once the Cast
  // Streaming Receiver component has been implemented.
  // Called when |connector_| has connected a port.
  bool OnPortConnected(std::string_view port_name,
                       std::unique_ptr<cast_api_bindings::MessagePort> port);

 private:
  // Called when ApiBindings::GetAll() has responded.
  void OnBindingsReceived(std::vector<chromium::cast::ApiBinding> bindings);

  // Used by AttachToFrame() to invoke `on_error_callback` asynchronously.
  void CallOnErrorCallback(base::OnceClosure on_error_callback);

  std::optional<std::vector<chromium::cast::ApiBinding>> bindings_;
  fuchsia::web::Frame* frame_ = nullptr;
  cast_api_bindings::NamedMessagePortConnector* connector_ = nullptr;
  chromium::cast::ApiBindingsPtr bindings_service_;
  base::OnceClosure on_initialization_complete_;

  base::WeakPtrFactory<ApiBindingsClient> weak_ptr_factory_{this};
};

#endif  // FUCHSIA_WEB_RUNNERS_CAST_API_BINDINGS_CLIENT_H_