File: extension_message_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 (229 lines) | stat: -rw-r--r-- 9,771 bytes parent folder | download | duplicates (3)
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// Copyright 2012 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_BROWSER_API_MESSAGING_EXTENSION_MESSAGE_PORT_H_
#define EXTENSIONS_BROWSER_API_MESSAGING_EXTENSION_MESSAGE_PORT_H_

#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/types/pass_key.h"
#include "base/uuid.h"
#include "content/public/browser/global_routing_id.h"
#include "extensions/browser/api/messaging/message_port.h"
#include "extensions/browser/message_tracker.h"
#include "extensions/browser/service_worker/worker_id.h"
#include "extensions/common/api/messaging/port_id.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/mojom/message_port.mojom.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "url/origin.h"

class GURL;

namespace content {
class BrowserContext;
class RenderFrameHost;
}  // namespace content

namespace IPC {
class Message;
}  // namespace IPC

namespace extensions {
class ExtensionHost;
class ChannelEndpoint;
struct PortContext;

// A port that manages communication with an extension.
// The port's lifetime will end when either all receivers close the port, or
// when the opener / receiver explicitly closes the channel.
class ExtensionMessagePort : public MessagePort {
 public:
  // Create a port that is tied to frame(s) in a single tab.
  static std::unique_ptr<ExtensionMessagePort> CreateForTab(
      base::WeakPtr<ChannelDelegate> channel_delegate,
      const PortId& port_id,
      const ExtensionId& extension_id,
      content::RenderFrameHost* render_frame_host,
      bool include_child_frames);

  // Create a port that is tied to all frames and service workers of an
  // extension. Should only be used for a receiver port.
  static std::unique_ptr<ExtensionMessagePort> CreateForExtension(
      base::WeakPtr<ChannelDelegate> channel_delegate,
      const PortId& port_id,
      const ExtensionId& extension_id,
      content::BrowserContext* browser_context);

  // Creates a port for any ChannelEndpoint which can be for a render frame or
  // Service Worker.
  static std::unique_ptr<ExtensionMessagePort> CreateForEndpoint(
      base::WeakPtr<ChannelDelegate> channel_delegate,
      const PortId& port_id,
      const ExtensionId& extension_id,
      const ChannelEndpoint& endpoint,
      mojo::PendingAssociatedRemote<extensions::mojom::MessagePort> port,
      mojo::PendingAssociatedReceiver<extensions::mojom::MessagePortHost>
          port_host);

  ExtensionMessagePort(base::WeakPtr<ChannelDelegate> channel_delegate,
                       const PortId& port_id,
                       const ExtensionId& extension_id,
                       content::BrowserContext* browser_context,
                       base::PassKey<ExtensionMessagePort>);

  ExtensionMessagePort(const ExtensionMessagePort&) = delete;
  ~ExtensionMessagePort() override;

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

  // MessagePort:
  void RemoveCommonFrames(const MessagePort& port) override;
  bool HasFrame(
      const content::GlobalRenderFrameHostToken& frame_token) const override;
  bool IsValidPort() override;
  void RevalidatePort() override;
  void DispatchOnConnect(mojom::ChannelType channel_type,
                         const std::string& channel_name,
                         std::optional<base::Value::Dict> source_tab,
                         const ExtensionApiFrameIdMap::FrameData& source_frame,
                         int guest_process_id,
                         int guest_render_frame_routing_id,
                         const MessagingEndpoint& source_endpoint,
                         const std::string& target_extension_id,
                         const GURL& source_url,
                         std::optional<url::Origin> source_origin,
                         const std::set<base::UnguessableToken>&
                             open_channel_tracking_ids) override;
  void DispatchOnDisconnect(const std::string& error_message) override;
  void DispatchOnMessage(const Message& message) override;
  void IncrementLazyKeepaliveCount(Activity::Type activity_type) override;
  void DecrementLazyKeepaliveCount(Activity::Type activity_type) override;
  void OpenPort(int process_id, const PortContext& port_context) override;
  void ClosePort(int process_id, int routing_id, int worker_thread_id) override;
  void NotifyResponsePending() override;

 private:
  class ContextTracker;
  struct IPCTarget;

  // Registers a frame as a receiver / sender.
  void RegisterFrame(content::RenderFrameHost* render_frame_host);

  // Unregisters a frame as a receiver / sender. When there are no registered
  // frames any more, the port closes via CloseChannel().
  bool UnregisterFrame(content::RenderFrameHost* render_frame_host);
  bool UnregisterFrame(const content::GlobalRenderFrameHostToken& frame_token);

  // Unregisters all the frames whose outermost main frame is `main_frame`. When
  // there are no registered frames any more, the port closes via
  // CloseChannel().
  // It returns if the port and the associated channel is closed.
  bool UnregisterFramesUnderMainFrame(
      content::RenderFrameHost* main_frame,
      std::optional<std::string> error_message = std::nullopt);

  // Methods to register/unregister a Service Worker endpoint for this port.
  void RegisterWorker(const WorkerId& worker_id);
  bool UnregisterWorker(const WorkerId& worker_id);
  void UnregisterWorker(int render_process_id, int worker_thread_id);

  // Immediately close the port and its associated channel.
  void CloseChannel(std::optional<std::string> error_message = std::nullopt);

  using SendCallback = base::RepeatingCallback<void(mojom::MessagePort*)>;
  void SendToPort(SendCallback send_callback);

  // Check if this activity of this type on this port would keep servicer worker
  // alive.
  bool IsServiceWorkerActivity(Activity::Type activity_type);

  bool ShouldSkipFrameForBFCache(content::RenderFrameHost* render_frame_host);

  void OnConnectResponse(
      const PortContext& port_context,
      const base::UnguessableToken& connect_dispatch_tracking_id,
      bool success);
  void Prune(const PortContext& port_context,
             const base::UnguessableToken& connect_dispatch_tracking_id);

  void ReportOpenChannelResult(
      MessageTracker::OpenChannelMessagePipelineResult emit_value);

  void ReportOpenChannelConnectDispatchResult(
      const base::UnguessableToken& tracking_id,
      MessageTracker::OpenChannelMessagePipelineResult emit_value);

  ExtensionId extension_id_;
  raw_ptr<content::BrowserContext> browser_context_ = nullptr;

  // Whether this port corresponds to *all* extension contexts. Should only be
  // true for a receiver port.
  bool for_all_extension_contexts_ = false;

  // When the port is used as a sender, this map contains only one element.
  // If used as a receiver, it may contain any number of frames.
  // This map is populated before the first message is sent to the destination,
  // and shrinks over time when the port is rejected by the recipient frame, or
  // when the frame is removed or unloaded.
  std::map<content::GlobalRenderFrameHostToken,
           mojo::AssociatedRemote<mojom::MessagePort>>
      frames_;

  // Service Worker endpoints for this port.
  std::map<WorkerId, mojo::AssociatedRemote<mojom::MessagePort>>
      service_workers_;

  // The set of frames and workers that have not been connected yet. These
  // should only have items during connection setup time.
  std::set<content::GlobalRenderFrameHostToken> pending_frames_;
  std::set<WorkerId> pending_service_workers_;

  // GUIDs of Service Workers that have pending keepalive requests inflight.
  std::map<WorkerId, std::vector<base::Uuid>> pending_keepalive_uuids_;

  // Whether the renderer acknowledged creation of the port. This is used to
  // distinguish abnormal port closure (e.g. no receivers) from explicit port
  // closure (e.g. by the port.disconnect() JavaScript method in the renderer).
  bool port_was_created_ = false;

  // Whether one of the receivers has indicated that it will respond later and
  // the opener should be expecting that response. Used to determine if we
  // should notify the opener of a message port being closed before an expected
  // response was received. By default this is assumed to be false until one of
  // the receivers notifies us otherwise.
  // Note: this is currently only relevant for messaging using
  // OneTimeMessageHandlers, where the receivers are able to indicate they are
  // going to respond asynchronously.
  bool asynchronous_reply_pending_ = false;

  // Used in IncrementLazyKeepaliveCount
  raw_ptr<ExtensionHost, DanglingUntriaged> background_host_ptr_ = nullptr;
  std::unique_ptr<ContextTracker> context_tracker_;

  // The set of PortContexts for which we're waiting on a response to
  // OnConnectResponse().
  std::set<PortContext> pending_contexts_to_respond_;
  // Tracking ID to every metric to emit once the result of the channel opening
  // is determined.
  std::set<base::UnguessableToken> pending_open_channel_tracking_ids_;
  // Tracking ID to every metric to emit if the channel (this class) closes
  // (destructs) before each port has responded to DispatchOnConnect IPC.
  std::set<base::UnguessableToken>
      pending_open_channel_connect_dispatch_tracking_ids_;

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

}  // namespace extensions

#endif  // EXTENSIONS_BROWSER_API_MESSAGING_EXTENSION_MESSAGE_PORT_H_