File: cast_remoting_connector.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 (262 lines) | stat: -rw-r--r-- 11,827 bytes parent folder | download | duplicates (6)
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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_H_
#define CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_H_

#include <optional>
#include <set>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/sessions/core/session_id.h"
#include "media/mojo/mojom/remoting.mojom.h"
#include "media/mojo/mojom/remoting_common.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"

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

class MediaRemotingDialogCoordinator {
 public:
  using PermissionCallback = base::OnceCallback<void(bool)>;

  MediaRemotingDialogCoordinator() = default;
  MediaRemotingDialogCoordinator(const MediaRemotingDialogCoordinator&) =
      delete;
  MediaRemotingDialogCoordinator& operator=(
      const MediaRemotingDialogCoordinator&) = delete;
  virtual ~MediaRemotingDialogCoordinator() = default;

  virtual bool Show(PermissionCallback permission_callback);
  virtual void Hide();
  virtual bool IsShowing() const;
};

// CastRemotingConnector connects a single source (a media element in a render
// frame) with a single sink (a media player in a remote device). There is one
// instance of a CastRemotingConnector per source WebContents (representing a
// collection of render frames), and it is created on-demand. The source in the
// render process represents itself by providing a media::mojom::RemotingSource
// service instance. The sink is represented by a MediaRemoter in the Cast Media
// Route Provider that handles the communication with the remote device. The
// CastRemotingConnector and the MediaRemoter can communicate with each other
// through the media::mojom::Remoter and media::mojom::RemotingSource interfaces
// when a sink that is capable of remoting is available.
//
// Whenever a candidate media source is created in a render frame,
// ChromeContentBrowserClient will call CreateMediaRemoter() to instantiate a
// media::mojom::Remoter associated with the connector. A corresponding
// media::mojom::RemotingSource is provided by the caller for communications
// back to the media source in the render frame: The connector uses this to
// notify when a sink becomes available for remoting, and to pass binary
// messages from the sink back to the source.
//
// When a mirroring route is created and available for remoting, the Cast MRP
// will create a MediaRemoter and notify MediaRouter, which notifies the
// CastRemotingConnector registered under the tab ID being remoted. At this
// point, the CastRemotingConnector can communicate with the MediaRemoter. When
// CastRemotingConnector gets notified that a sink is available, it notifies all
// RemotingSources, and some time later a RemotingSource can request the start
// of a remoting session.
//
// Note that only one RemotingSource can remote media at a time. Therefore,
// CastRemotingConnector must mediate among simultaneous requests for media
// remoting, and only allow one at a time. Currently, the policy is "first come,
// first served."
//
// When starting a remoting session, the Cast MRP will also set up a Cast
// Streaming session to provide a bitstream transport for the media. Once this
// is done, the MediaRemoter notifies the CastRemotingConnector. Then,
// CastRemotingConnector knows it can look-up and pass the mojo data pipe
// handles to CastRemotingSenders, and the remoting session will be fully active
// The CastRemotingConnector is responsible for passing small binary messages
// between the source and sink, while the CastRemotingSender handles the
// high-volume media data transfer.
//
// Please see the unit tests in cast_remoting_connector_unittest.cc as a
// reference for how CastRemotingConnector and a MediaRemoter interact to
// start/execute/stop remoting sessions.
class CastRemotingConnector final : public base::SupportsUserData::Data,
                                    public media::mojom::RemotingSource {
 public:
  CastRemotingConnector(const CastRemotingConnector&) = delete;
  CastRemotingConnector& operator=(const CastRemotingConnector&) = delete;

  ~CastRemotingConnector() final;

  // Returns the instance of the CastRemotingConnector associated with
  // |source_contents|, creating a new instance if needed. Returns nullptr if
  // |source_contents| doesn't have a valid tab ID.
  static CastRemotingConnector* Get(content::WebContents* source_contents);

  // Used by ChromeContentBrowserClient to request a binding to a new
  // Remoter for each new source in a render frame.
  static void CreateMediaRemoter(
      content::RenderFrameHost* render_frame_host,
      mojo::PendingRemote<media::mojom::RemotingSource> source,
      mojo::PendingReceiver<media::mojom::Remoter> receiver);

  // Called at the start of mirroring to reset the permission.
  void ResetRemotingPermission();

  // Used by Mirroring Service to connect the media remoter with this source.
  void ConnectWithMediaRemoter(
      mojo::PendingRemote<media::mojom::Remoter> remoter,
      mojo::PendingReceiver<media::mojom::RemotingSource> receiver);

 private:
  // Allow unit tests access to the private constructor and CreateBridge()
  // method, since unit tests don't have a complete browser (i.e., with a
  // WebContents and RenderFrameHost) to work with.
  friend class CastRemotingConnectorTest;

  // Implementation of the media::mojom::Remoter service for a single source in
  // a render frame. This is just a "lightweight bridge" that delegates calls
  // back-and-forth between a CastRemotingConnector and a
  // media::mojom::RemotingSource. An instance of this class is owned by its
  // mojo message pipe.
  class RemotingBridge;

  // Main constructor. |tab_id| refers to any remoted content managed
  // by this instance (i.e., any remoted content from one tab/WebContents).
  CastRemotingConnector(
      PrefService* pref_service,
      SessionID tab_id,
      std::unique_ptr<MediaRemotingDialogCoordinator> dialog_coordinator);

  // Creates a RemotingBridge that implements the requested Remoter service, and
  // binds it to the interface |receiver|.
  void CreateBridge(mojo::PendingRemote<media::mojom::RemotingSource> source,
                    mojo::PendingReceiver<media::mojom::Remoter> receiver);

  // Called by the RemotingBridge constructor/destructor to register/deregister
  // an instance. This allows this connector to broadcast notifications to all
  // active sources.
  void RegisterBridge(RemotingBridge* bridge);
  void DeregisterBridge(RemotingBridge* bridge,
                        media::mojom::RemotingStopReason reason);

  // media::mojom::MirrorServiceRemotingSource implementation.
  // media::mojom::RemotingSource implementation.
  void OnSinkAvailable(media::mojom::RemotingSinkMetadataPtr metadata) override;
  void OnMessageFromSink(const std::vector<uint8_t>& message) override;
  void OnStopped(media::mojom::RemotingStopReason reason) override;

  // media::mojom::RemotingSource implementation.
  void OnSinkGone() override;
  void OnStarted() override;
  void OnStartFailed(media::mojom::RemotingStartFailReason reason) override;

  // These methods are called by RemotingBridge to forward media::mojom::Remoter
  // calls from a source through to this connector. They ensure that only one
  // source is allowed to be in a remoting session at a time, and that no source
  // may interfere with any other.
  void StartRemoting(RemotingBridge* bridge);
  void StartWithPermissionAlreadyGranted(RemotingBridge* bridge);
  bool StartRemotingCommon(RemotingBridge* bridge);
  void StartRemotingDataStreams(
      RemotingBridge* bridge,
      mojo::ScopedDataPipeConsumerHandle audio_pipe,
      mojo::ScopedDataPipeConsumerHandle video_pipe,
      mojo::PendingReceiver<media::mojom::RemotingDataStreamSender>
          audio_sender,
      mojo::PendingReceiver<media::mojom::RemotingDataStreamSender>
          video_sender);
  void StopRemoting(RemotingBridge* bridge,
                    media::mojom::RemotingStopReason reason,
                    bool is_initiated_by_source);
  void SendMessageToSink(RemotingBridge* bridge,
                         const std::vector<uint8_t>& message);
  void EstimateTransmissionCapacity(
      media::mojom::Remoter::EstimateTransmissionCapacityCallback callback);

  // Called by the permission dialog when it closes, to signal whether
  // permission is allowed.
  void OnDialogClosed(bool remoting_allowed);

  // Called after permission check. Either call |remoter_| to start remoting or
  // notify the source that start fails due to no permission.
  void StartRemotingIfPermitted();

  // Called when RTP streams are started.
  void OnDataStreamsStarted(
      mojo::ScopedDataPipeConsumerHandle audio_pipe,
      mojo::ScopedDataPipeConsumerHandle video_pipe,
      mojo::PendingReceiver<media::mojom::RemotingDataStreamSender>
          audio_sender,
      mojo::PendingReceiver<media::mojom::RemotingDataStreamSender>
          video_sender,
      int32_t audio_stream_id,
      int32_t video_stream_id);

  // Error handlers for message sending during an active remoting session. When
  // a failure occurs, these immediately force-stop remoting.
  void OnDataSendFailed();

  // Called when any connection error/lost occurs with the MediaRemoter.
  void OnMirrorServiceStopped();

  // Starts observing for changes to the user preference to enable/disable
  // remoting.
  void StartObservingPref();

  // Called when the user preference to enable/disable remoting changes. Stops
  // remoting if necessary.
  void OnPrefChanged();

  // Returns the user's remoting preference, or nullopt if it isn't set.
  std::optional<bool> GetRemotingAllowedUserPref() const;

  void set_remoting_allowed_for_testing(bool remoting_allowed) {
    remoting_allowed_ = remoting_allowed;
  }

  const raw_ptr<PrefService> pref_service_;
  const SessionID tab_id_;

  std::unique_ptr<MediaRemotingDialogCoordinator> dialog_coordinator_;

  // Describes the remoting sink's metadata and its enabled features. The sink's
  // metadata is updated by the mirror service calling OnSinkAvailable() and
  // cleared when remoting stops.
  media::mojom::RemotingSinkMetadata sink_metadata_;

  // Set of registered RemotingBridges, maintained by RegisterBridge() and
  // DeregisterBridge(). These pointers are always valid while they are in this
  // set.
  std::set<raw_ptr<RemotingBridge, SetExperimental>> bridges_;

  // When non-null, an active remoting session is taking place, with this
  // pointing to the RemotingBridge being used to communicate with the source.
  raw_ptr<RemotingBridge> active_bridge_ = nullptr;

  mojo::Receiver<media::mojom::RemotingSource> receiver_{this};
  mojo::Remote<media::mojom::Remoter> remoter_;

  // Permission is checked the first time remoting requested to start for each
  // casting session.
  std::optional<bool> remoting_allowed_;

  PrefChangeRegistrar pref_change_registrar_;

  // Produces weak pointers that are only valid for the current remoting
  // session. This is used to cancel any outstanding callbacks when a remoting
  // session is stopped.
  base::WeakPtrFactory<CastRemotingConnector> weak_factory_{this};

  // Key used with the base::SupportsUserData interface to search for an
  // instance of CastRemotingConnector owned by a WebContents.
  static const void* const kUserDataKey;
};

#endif  // CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_H_