#ifndef EXTENSIONS_RENDERER_API_MESSAGING_GIN_PORT_H_
#define EXTENSIONS_RENDERER_API_MESSAGING_GIN_PORT_H_
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "extensions/common/api/messaging/port_id.h"
#include "extensions/common/mojom/message_port.mojom.h"
#include "extensions/renderer/bindings/api_binding_util.h"
#include "gin/public/wrappable_pointer_tags.h"
#include "gin/wrappable.h"
#include "v8/include/v8-forward.h"
namespace gin {
class Arguments;
}
namespace extensions {
class APIEventHandler;
class Message;
class GinPort final : public gin::Wrappable<GinPort> {
public:
class Delegate {
public:
virtual ~Delegate() {}
virtual void PostMessageToPort(v8::Local<v8::Context> context,
const PortId& port_id,
std::unique_ptr<Message> message) = 0;
virtual void ClosePort(v8::Local<v8::Context> context,
const PortId& port_id) = 0;
};
GinPort(v8::Local<v8::Context> context,
const PortId& port_id,
const std::string& name,
const mojom::ChannelType channel_type,
APIEventHandler* event_handler,
Delegate* delegate);
GinPort(const GinPort&) = delete;
GinPort& operator=(const GinPort&) = delete;
~GinPort() override;
static constexpr gin::WrapperInfo kWrapperInfo = {
{gin::kEmbedderNativeGin}, gin::kGinPort};
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
const char* GetHumanReadableName() const override;
void DispatchOnMessage(v8::Local<v8::Context> context,
const Message& message);
void DispatchOnDisconnect(v8::Local<v8::Context> context);
void SetSender(v8::Local<v8::Context> context, v8::Local<v8::Value> sender);
const PortId& port_id() const { return port_id_; }
const std::string& name() const { return name_; }
bool is_closed_for_testing() const { return state_ == State::kDisconnected; }
private:
const gin::WrapperInfo* wrapper_info() const override;
enum class State {
kActive,
kDisconnected,
kInvalidated,
};
void DisconnectHandler(gin::Arguments* arguments);
void PostMessageHandler(gin::Arguments* arguments,
v8::Local<v8::Value> v8_message);
std::string GetName();
v8::Local<v8::Value> GetOnDisconnectEvent(gin::Arguments* arguments);
v8::Local<v8::Value> GetOnMessageEvent(gin::Arguments* arguments);
v8::Local<v8::Value> GetSender(gin::Arguments* arguments);
v8::Local<v8::Object> GetEvent(v8::Local<v8::Context> context,
std::string_view event_name);
void DispatchEvent(v8::Local<v8::Context> context,
v8::LocalVector<v8::Value>* args,
std::string_view event_name);
void OnContextInvalidated();
void InvalidateEvents(v8::Local<v8::Context> context);
void ThrowError(v8::Isolate* isolate, std::string_view error);
State state_ = State::kActive;
const PortId port_id_;
const std::string name_;
const mojom::ChannelType channel_type_;
const raw_ptr<APIEventHandler> event_handler_;
const raw_ptr<Delegate, DanglingUntriaged> delegate_;
bool accessed_sender_;
std::optional<binding::ContextInvalidationListener>
context_invalidation_listener_;
base::WeakPtrFactory<GinPort> weak_factory_{this};
};
}
#endif