File: dial_media_route_provider.h

package info (click to toggle)
chromium 139.0.7258.127-1~deb13u1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,096 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 (207 lines) | stat: -rw-r--r-- 9,533 bytes parent folder | download | duplicates (8)
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
// Copyright 2018 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_ROUTER_PROVIDERS_DIAL_DIAL_MEDIA_ROUTE_PROVIDER_H_
#define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_DIAL_DIAL_MEDIA_ROUTE_PROVIDER_H_

#include <memory>
#include <string>
#include <vector>

#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl.h"
#include "chrome/browser/media/router/providers/dial/dial_activity_manager.h"
#include "chrome/browser/media/router/providers/dial/dial_internal_message_util.h"
#include "components/media_router/common/mojom/media_router.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"
#include "services/data_decoder/public/cpp/data_decoder.h"

namespace url {
class Origin;
}

namespace media_router {

// MediaRouteProvider for DIAL sinks.
// DialMediaRouteProvider supports custom DIAL launch, which is a
// way for websites that uses Cast SDK to launch apps on DIAL devices.
// The life of a custom DIAL launch workflow is as follows:
// 1) The user initiates a custom DIAL launch by selecting a DIAL device
//    to cast to. This becomes a CreateRoute request to the
//    DialMediaRouteProvider.
// 2) The DialMediaRouteProvider sends NEW_SESSION / RECEIVER_ACTION messages to
//    the Cast SDK to inform of a new Cast session. In addition, a
//    CUSTOM_DIAL_LAUNCH request is sent to the Cast SDK.
// 3) The Cast SDK sends back a CUSTOM_DIAL_LAUNCH response. Depending on the
//    response, either the page have already handled the app launch, or the
//    DialMediaRouteProvider will initiate the app launch on the device.
// 4) Once the app is launched, the workflow is complete. The webpage will then
//    communicate with the app on the device via its own mechanism.
class DialMediaRouteProvider : public mojom::MediaRouteProvider,
                               public MediaSinkServiceBase::Observer {
 public:
  // |receiver|: Mojo receiver to bind to |this|.
  // |media_router|: Pending remote to MediaRouter.
  // |media_sink_service|: DIAL MediaSinkService providing information on sinks.
  // |hash_token|: A per-profile value used to hash sink IDs.
  // |task_runner|: The task runner on which |this| runs.
  DialMediaRouteProvider(
      mojo::PendingReceiver<mojom::MediaRouteProvider> receiver,
      mojo::PendingRemote<mojom::MediaRouter> media_router,
      DialMediaSinkServiceImpl* media_sink_service,
      const std::string& hash_token,
      const scoped_refptr<base::SequencedTaskRunner>& task_runner);

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

  ~DialMediaRouteProvider() override;

  // mojom::MediaRouteProvider:
  void CreateRoute(const std::string& media_source,
                   const std::string& sink_id,
                   const std::string& presentation_id,
                   const url::Origin& origin,
                   int32_t frame_tree_node_id,
                   base::TimeDelta timeout,
                   CreateRouteCallback callback) override;
  void JoinRoute(const std::string& media_source,
                 const std::string& presentation_id,
                 const url::Origin& origin,
                 int32_t frame_tree_node_id,
                 base::TimeDelta timeout,
                 JoinRouteCallback callback) override;
  void TerminateRoute(const std::string& route_id,
                      TerminateRouteCallback callback) override;
  void SendRouteMessage(const std::string& media_route_id,
                        const std::string& message) override;
  void SendRouteBinaryMessage(const std::string& media_route_id,
                              const std::vector<uint8_t>& data) override;
  void StartObservingMediaSinks(const std::string& media_source) override;
  void StopObservingMediaSinks(const std::string& media_source) override;
  void StartObservingMediaRoutes() override;
  void DetachRoute(const std::string& route_id) override;
  void DiscoverSinksNow() override;
  void BindMediaController(
      const std::string& route_id,
      mojo::PendingReceiver<mojom::MediaController> media_controller,
      mojo::PendingRemote<mojom::MediaStatusObserver> observer,
      BindMediaControllerCallback callback) override;
  void GetState(GetStateCallback callback) override;

  void SetActivityManagerForTest(
      std::unique_ptr<DialActivityManager> activity_manager);

 private:
  FRIEND_TEST_ALL_PREFIXES(DialMediaRouteProviderTest, AddRemoveSinkQuery);
  FRIEND_TEST_ALL_PREFIXES(DialMediaRouteProviderTest,
                           AddSinkQuerySameMediaSource);
  FRIEND_TEST_ALL_PREFIXES(DialMediaRouteProviderTest,
                           AddSinkQuerySameAppDifferentMediaSources);
  FRIEND_TEST_ALL_PREFIXES(DialMediaRouteProviderTest,
                           AddSinkQueryDifferentApps);
  FRIEND_TEST_ALL_PREFIXES(DialMediaRouteProviderTest, ListenForRouteMessages);

  struct MediaSinkQuery {
    MediaSinkQuery();

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

    ~MediaSinkQuery();

    // Set of registered media sources for current sink query.
    base::flat_set<MediaSource> media_sources;
    base::CallbackListSubscription subscription;
  };

  // MediaSinkServiceBase::Observer:
  void OnSinksDiscovered(const std::vector<MediaSinkInternal>& sinks) override;

  // Binds the message pipes |receiver| and |media_router| to |this|.
  void Init(mojo::PendingReceiver<mojom::MediaRouteProvider> receiver,
            mojo::PendingRemote<mojom::MediaRouter> media_router);

  void OnAvailableSinksUpdated(const std::string& app_name);

  void NotifyOnSinksReceived(const MediaSource::Id& source_id,
                             const std::vector<MediaSinkInternal>& sinks,
                             const std::vector<url::Origin>& origins);

  void HandleParsedRouteMessage(const MediaRoute::Id& route_id,
                                data_decoder::DataDecoder::ValueOrError result);
  void HandleClientConnect(const DialActivity& activity,
                           const MediaSinkInternal& sink);
  void SendCustomDialLaunchMessage(const MediaRoute::Id& route_id,
                                   const MediaSink::Id& sink_id,
                                   const std::string& app_name,
                                   DialAppInfoResult result);
  void SendDialAppInfoResponse(const MediaRoute::Id& route_id,
                               int sequence_number,
                               const MediaSink::Id& sink_id,
                               const std::string& app_name,
                               DialAppInfoResult result);
  void HandleCustomDialLaunchResponse(const DialActivity& activity,
                                      const DialInternalMessage& message);
  void HandleDiapAppInfoRequest(const DialActivity& activity,
                                const DialInternalMessage& message,
                                const MediaSinkInternal& sink);
  void HandleAppLaunchResult(const MediaRoute::Id& route_id, bool success);
  void DoTerminateRoute(const DialActivity& activity,
                        const MediaSinkInternal& sink,
                        TerminateRouteCallback callback);
  void HandleStopAppResult(const MediaRoute::Id& route_id,
                           TerminateRouteCallback callback,
                           const std::optional<std::string>& message,
                           mojom::RouteRequestResultCode result_code);
  void NotifyAllOnRoutesUpdated();
  void NotifyOnRoutesUpdated(const std::vector<MediaRoute>& routes);

  // Returns a list of valid origins for |app_name|. Returns an empty list if
  // all origins are valid.
  std::vector<url::Origin> GetOrigins(const std::string& app_name);

  // Binds |this| to the Mojo receiver passed into the ctor.
  mojo::Receiver<mojom::MediaRouteProvider> receiver_{this};

  // Mojo remote to the Media Router.
  mojo::Remote<mojom::MediaRouter> media_router_;

  // Non-owned pointer to the DialMediaSinkServiceImpl instance.
  const raw_ptr<DialMediaSinkServiceImpl> media_sink_service_;

  // Map of media sink queries, keyed by app name.
  base::flat_map<std::string, std::unique_ptr<MediaSinkQuery>>
      media_sink_queries_;

  // Set of route queries by MediaSource ID.
  base::flat_set<MediaSource::Id> media_route_queries_;

  // Set of pending DIAL launches by sequence number. The max number of pending
  // launches is capped, and oldest entries (smallest number) will be evicted.
  base::flat_set<int> pending_dial_launches_;

  std::unique_ptr<DialActivityManager> activity_manager_;

  DialInternalMessageUtil internal_message_util_;

  // Mojo remote to the logger owned by the Media Router.
  mojo::Remote<mojom::Logger> logger_;

  SEQUENCE_CHECKER(sequence_checker_);
  base::WeakPtrFactory<DialMediaRouteProvider> weak_ptr_factory_{this};
};

}  // namespace media_router

#endif  // CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_DIAL_DIAL_MEDIA_ROUTE_PROVIDER_H_