File: gin_port.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (164 lines) | stat: -rw-r--r-- 5,625 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#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/wrappable.h"
#include "v8/include/v8-forward.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> {
 public:
  class Delegate {
   public:
    virtual ~Delegate() {}

    // Posts a message to the port.
    virtual void PostMessageToPort(v8::Local<v8::Context> context,
                                   const PortId& port_id,
                                   std::unique_ptr<Message> message) = 0;

    // Closes the port.
    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 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. Note: this can only be called
  // before the `sender` property is accessed on the JS object, since it is
  // lazily set as a data property in first access.
  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:
  enum class 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);

  // Port.name
  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,
                                 std::string_view event_name);

  // Helper method to dispatch an event.
  void DispatchEvent(v8::Local<v8::Context> context,
                     v8::LocalVector<v8::Value>* args,
                     std::string_view 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, std::string_view error);

  // The current state of the port.
  State state_ = State::kActive;

  // The associated port id.
  const PortId port_id_;

  // The port's name.
  const std::string name_;

  // The type of the associated channel.
  const mojom::ChannelType channel_type_;

  // The associated APIEventHandler. Guaranteed to outlive this object.
  const raw_ptr<APIEventHandler> event_handler_;

  // The delegate for handling the message passing between ports. Guaranteed to
  // outlive this object.
  const raw_ptr<Delegate, DanglingUntriaged> delegate_;

  // Whether the `sender` property has been accessed, and thus set on the
  // port JS object.
  bool accessed_sender_;

  // 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.
  std::optional<binding::ContextInvalidationListener>
      context_invalidation_listener_;

  base::WeakPtrFactory<GinPort> weak_factory_{this};
};

}  // namespace extensions

#endif  // EXTENSIONS_RENDERER_API_MESSAGING_GIN_PORT_H_