File: local_presentation_manager.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 (277 lines) | stat: -rw-r--r-- 12,154 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
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
// 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 COMPONENTS_MEDIA_ROUTER_BROWSER_PRESENTATION_LOCAL_PRESENTATION_MANAGER_H_
#define COMPONENTS_MEDIA_ROUTER_BROWSER_PRESENTATION_LOCAL_PRESENTATION_MANAGER_H_

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>

#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/threading/thread_checker.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/media_router/common/media_route.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/presentation_service_delegate.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/mojom/presentation/presentation.mojom.h"

namespace content {
class WebContents;
}

namespace media_router {
// Manages all local presentations started in the associated Profile and
// facilitates communication between the controllers and the receiver of a
// local presentation. A local presentation may be an offscreen presentation for
// Presentation API 1-UA mode, or a presentation to a wired display.
//
// Design doc:
// https://docs.google.com/document/d/1XM3jhMJTQyhEC5PDAAJFNIaKh6UUEihqZDz_ztEe4Co/edit#heading=h.hadpx5oi0gml
//
// Example usage:
//
// Receiver is created to host the local presentation and registers itself
// so that controller frames can connect to it:
//
//   LocalPresentationManager* manager =
//       LocalPresentationManagerFactory::GetOrCreateForBrowserContext(
//           web_contents_->GetBrowserContext());
//   manager->OnLocalPresentationReceiverCreated(presentation_info,
//       base::BindRepeating(
//           &PresentationServiceImpl::OnReceiverConnectionAvailable));
//
// Controlling frame establishes connection with the receiver side, resulting
// in a connection with the two endpoints being the controller
// PresentationConnectionRemote and receiver PresentationConnectionReceiver.
// Note calling this will trigger receiver frame's
// PresentationServiceImpl::OnReceiverConnectionAvailable.
//
//   manager->RegisterLocalPresentationController(
//       presentation_info,
//       std::move(controller_connection_remote),
//       std::move(receiver_connection_receiver));
//
// Invoked on receiver's PresentationServiceImpl when controller connection is
// established.
//
//   |presentation_receiver_remote_|: mojo::Remote<T> for the implementation of
//   the blink::mojom::PresentationService interface in the renderer process.
//   |controller_connection_remote|: mojo::PendingRemote<T> for
//   blink::PresentationConnection object in controlling frame's render process.
//   |receiver_connection_receiver|: mojo::PendingReceiver<T> to be bind to
//   blink::PresentationConnection object in receiver frame's render process.
//   void PresentationServiceImpl::OnReceiverConnectionAvailable(
//       const blink::mojom::PresentationInfo& presentation_info,
//       PresentationConnectionRemote controller_connection_remote,
//       PresentationConnectionReceiver receiver_connection_receiver) {
//     presentation_receiver_remote_->OnReceiverConnectionAvailable(
//         blink::mojom::PresentationInfo::From(presentation_info),
//         std::move(controller_connection_remote),
//         std::move(receiver_connection_receiver));
//   }
//
// Send message from controlling/receiver frame to receiver/controlling frame:
//
//   |target_connection_|: member variable of mojo::PendingRemote<T> for
//                         blink::PresentationConnection type, referring to
//                         remote PresentationConnectionProxy object on
//                         receiver/controlling frame.
//   |message|: Text message to be sent.
//   PresentationConnctionPtr::SendString(
//       const blink::WebString& message) {
//     target_connection_->OnMessage(
//         blink::mojom::PresentationConnectionMessage::NewMessage(
//             message.Utf8()),
//         base::BindOnce(&OnMessageReceived));
//   }
//
// A controller or receiver leaves the local presentation (e.g., due to
// navigation) by unregistering themselves from LocalPresentation object.
//
// When the receiver is no longer associated with a local presentation, it
// shall unregister itself with LocalPresentationManager. Unregistration
// will prevent additional controllers from establishing a connection with the
// receiver:
//
//   In receiver's PSImpl::Reset() {
//     local_presentation_manager->
//         OnLocalPresentationReceiverTerminated(presentation_id);
//   }
//
// This class is not thread safe. All functions must be invoked on the UI
// thread. All callbacks passed into this class will also be invoked on UI
// thread.
class LocalPresentationManager : public KeyedService {
 public:
  // Used by
  // LocalPresentationManagerFactory::BuildServiceInstanceForBrowserContext.
  LocalPresentationManager();
  LocalPresentationManager(const LocalPresentationManager&) = delete;
  LocalPresentationManager& operator=(const LocalPresentationManager&) = delete;

  ~LocalPresentationManager() override;

  // Registers controller PresentationConnectionPtr to presentation with
  // |presentation_id| and |render_frame_id|.
  // Creates a new presentation if no presentation with |presentation_id|
  // exists.
  // |controller_connection_remote|, |receiver_connection_receiver|: Not owned
  // by this class. Ownership is transferred to presentation receiver via
  // |receiver_callback| passed below.
  virtual void RegisterLocalPresentationController(
      const blink::mojom::PresentationInfo& presentation_info,
      const content::GlobalRenderFrameHostId& render_frame_id,
      mojo::PendingRemote<blink::mojom::PresentationConnection>
          controller_connection_remote,
      mojo::PendingReceiver<blink::mojom::PresentationConnection>
          receiver_connection_receiver,
      const MediaRoute& route);

  // Unregisters controller PresentationConnectionPtr to presentation with
  // |presentation_id|, |render_frame_id|. It does nothing if there is no
  // controller that matches the provided arguments. It removes presentation
  // that matches the arguments if the presentation has no |receiver_callback|
  // and any other pending controller.
  virtual void UnregisterLocalPresentationController(
      const std::string& presentation_id,
      const content::GlobalRenderFrameHostId& render_frame_id);

  // Registers |receiver_callback| and set |receiver_web_contents| to
  // presentation with |presentation_info|.
  virtual void OnLocalPresentationReceiverCreated(
      const blink::mojom::PresentationInfo& presentation_info,
      const content::ReceiverConnectionAvailableCallback& receiver_callback,
      content::WebContents* receiver_web_contents);

  // Unregisters ReceiverConnectionAvailableCallback associated with
  // |presentation_id|.
  virtual void OnLocalPresentationReceiverTerminated(
      const std::string& presentation_id);

  // Returns true if this class has a local presentation with
  // |presentation_id|.
  virtual bool IsLocalPresentation(const std::string& presentation_id);

  // Returns true if this class has a local presentation with |web_contents|.
  virtual bool IsLocalPresentation(content::WebContents* web_contents);

  // Returns nullptr if |presentation_id| is not associated with a local
  // presentation.
  virtual const MediaRoute* GetRoute(const std::string& presentation_id);

 private:
  // Represents a local presentation registered with
  // LocalPresentationManager. Contains callback to the receiver to inform
  // it of new connections established from a controller. Contains set of
  // controllers registered to LocalPresentationManager before corresponding
  // receiver.
  class LocalPresentation {
   public:
    explicit LocalPresentation(
        const blink::mojom::PresentationInfo& presentation_info);

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

    ~LocalPresentation();

    // Register controller with |render_frame_id|. If |receiver_callback_| has
    // been set, invoke |receiver_callback_| with |controller_connection_remote|
    // and |receiver_connection_receiver| as parameter, else creates a
    // ControllerConnection object with |controller_connection_remote| and
    // |receiver_connection_receiver|, and store it in |pending_controllers_|
    // map.
    void RegisterController(
        const content::GlobalRenderFrameHostId& render_frame_id,
        mojo::PendingRemote<blink::mojom::PresentationConnection>
            controller_connection_remote,
        mojo::PendingReceiver<blink::mojom::PresentationConnection>
            receiver_connection_receiver,
        const MediaRoute& route);

    // Unregister controller with |render_frame_id|. Do nothing if there is no
    // pending controller with |render_frame_id|.
    void UnregisterController(
        const content::GlobalRenderFrameHostId& render_frame_id);

    // Register |receiver_callback| and set |receiver_web_contents| to current
    // local_presentation object. For each controller in |pending_controllers_|
    // map, invoke |receiver_callback| with controller as parameter. Clear
    // |pending_controllers_| map afterwards.
    void RegisterReceiver(
        const content::ReceiverConnectionAvailableCallback& receiver_callback,
        content::WebContents* receiver_web_contents);

   private:
    friend class LocalPresentationManagerTest;
    friend class LocalPresentationManager;

    // Returns false if receiver_callback_ is null and there are no pending
    // controllers.
    bool IsValid() const;

    const blink::mojom::PresentationInfo presentation_info_;
    std::optional<MediaRoute> route_;
    raw_ptr<content::WebContents, DanglingUntriaged> receiver_web_contents_ =
        nullptr;

    // Callback to invoke whenever a receiver connection is available.
    content::ReceiverConnectionAvailableCallback receiver_callback_;

    // Stores controller information.
    // |controller_connection_remote|: mojo::PendingRemote<T> to
    // blink::PresentationConnection object in controlling frame;
    // |receiver_connection_receiver|: mojo::PendingReceiver<T> to be bind to
    // blink::PresentationConnection object in receiver frame.
    struct ControllerConnection {
     public:
      ControllerConnection(
          mojo::PendingRemote<blink::mojom::PresentationConnection>
              controller_connection_remote,
          mojo::PendingReceiver<blink::mojom::PresentationConnection>
              receiver_connection_receiver);
      ~ControllerConnection();

      mojo::PendingRemote<blink::mojom::PresentationConnection>
          controller_connection_remote;
      mojo::PendingReceiver<blink::mojom::PresentationConnection>
          receiver_connection_receiver;
    };

    // Contains ControllerConnection objects registered via
    // |RegisterController()| before |receiver_callback_| is set.
    std::unordered_map<content::GlobalRenderFrameHostId,
                       std::unique_ptr<ControllerConnection>,
                       content::GlobalRenderFrameHostIdHasher>
        pending_controllers_;
  };

 private:
  friend class LocalPresentationManagerTest;
  friend class MockLocalPresentationManager;
  FRIEND_TEST_ALL_PREFIXES(ControllerPresentationServiceDelegateImplTest,
                           ConnectToLocalPresentation);

  using LocalPresentationMap =
      std::map<std::string, std::unique_ptr<LocalPresentation>>;

  // Creates a local presentation with |presentation_info|.
  LocalPresentation* GetOrCreateLocalPresentation(
      const blink::mojom::PresentationInfo& presentation_info);

  // Maps from presentation ID to LocalPresentation.
  LocalPresentationMap local_presentations_;

  THREAD_CHECKER(thread_checker_);
};

}  // namespace media_router

#endif  // COMPONENTS_MEDIA_ROUTER_BROWSER_PRESENTATION_LOCAL_PRESENTATION_MANAGER_H_