blob: 935b08770f93b287723f361d0c10818f7bb50dea [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "extensions/common/api/messaging/port_id.h"
#include "extensions/renderer/bindings/api_binding_util.h"
#include "gin/wrappable.h"
#include "v8/include/v8.h"
namespace gin {
class Arguments;
namespace extensions {
class APIEventHandler;
struct Message;
// A gin::Wrappable implementation of runtime.Port exposed to extensions. This
// provides a means for extensions to communicate with themselves and each
// other. This message-passing usually involves IPCs to the browser; we delegate
// out this responsibility. This class only handles the JS interface (both calls
// from JS and forward events to JS).
class GinPort final : public gin::Wrappable<GinPort> {
class Delegate {
virtual ~Delegate() {}
// Posts a message to the port.
virtual void PostMessageToPort(v8::Local<v8::Context> context,
const PortId& port_id,
int routing_id,
std::unique_ptr<Message> message) = 0;
// Closes the port.
virtual void ClosePort(v8::Local<v8::Context> context,
const PortId& port_id,
int routing_id) = 0;
GinPort(v8::Local<v8::Context> context,
const PortId& port_id,
int routing_id,
const std::string& name,
APIEventHandler* event_handler,
Delegate* delegate);
~GinPort() override;
static gin::WrapperInfo kWrapperInfo;
// gin::Wrappable:
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
const char* GetTypeName() override;
// Dispatches an event to any listeners of the onMessage event.
void DispatchOnMessage(v8::Local<v8::Context> context,
const Message& message);
// Dispatches an event to any listeners of the onDisconnect event and closes
// the port.
void DispatchOnDisconnect(v8::Local<v8::Context> context);
// Sets the |sender| property on the port.
void SetSender(v8::Local<v8::Context> context, v8::Local<v8::Value> sender);
const PortId& port_id() const { return port_id_; }
int routing_id() const { return routing_id_; }
const std::string& name() const { return name_; }
bool is_closed_for_testing() const { return state_ == kDisconnected; }
enum State {
kActive, // The port is currently active.
kDisconnected, // The port was disconnected by calling port.disconnect().
kInvalidated, // The associated v8::Context has been invalidated.
// Handlers for the gin::Wrappable.
// Port.disconnect()
void DisconnectHandler(gin::Arguments* arguments);
// Port.postMessage()
void PostMessageHandler(gin::Arguments* arguments,
v8::Local<v8::Value> v8_message);
std::string GetName();
// Port.onDisconnect
v8::Local<v8::Value> GetOnDisconnectEvent(gin::Arguments* arguments);
// Port.onMessage
v8::Local<v8::Value> GetOnMessageEvent(gin::Arguments* arguments);
// Port.sender
v8::Local<v8::Value> GetSender(gin::Arguments* arguments);
// Helper method to return the event with the given |name| (either
// onDisconnect or onMessage).
v8::Local<v8::Object> GetEvent(v8::Local<v8::Context> context,
base::StringPiece event_name);
// Helper method to dispatch an event.
void DispatchEvent(v8::Local<v8::Context> context,
std::vector<v8::Local<v8::Value>>* args,
base::StringPiece event_name);
// Invalidates the port (due to the context being removed). Any further calls
// to postMessage() or instantiating new events will fail.
void OnContextInvalidated();
// Invalidates the port's events after the port has been disconnected.
void InvalidateEvents(v8::Local<v8::Context> context);
// Throws the given |error|.
void ThrowError(v8::Isolate* isolate, base::StringPiece error);
// The current state of the port.
State state_ = kActive;
// The associated port id.
PortId port_id_;
// The routing id associated with the port's context's render frame.
// TODO(devlin/lazyboy): This won't work with service workers.
int routing_id_;
// The port's name.
std::string name_;
// The associated APIEventHandler. Guaranteed to outlive this object.
APIEventHandler* const event_handler_;
// The delegate for handling the message passing between ports. Guaranteed to
// outlive this object.
Delegate* const delegate_;
// A listener for context invalidation. Note: this isn't actually optional;
// it just needs to be created after |weak_factory_|, which needs to be the
// final member.
base::WeakPtrFactory<GinPort> weak_factory_;
} // namespace extensions