summaryrefslogtreecommitdiff
path: root/chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.h
blob: 84e8d861820abf39441e7b27e2fb72b720d23d80 (plain)
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
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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_PRESENTATION_SERVICE_DELEGATE_IMPL_H_
#define COMPONENTS_MEDIA_ROUTER_BROWSER_PRESENTATION_PRESENTATION_SERVICE_DELEGATE_IMPL_H_

#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "build/build_config.h"
#include "components/media_router/browser/media_router.h"
#include "components/media_router/browser/presentation/presentation_service_delegate_observers.h"
#include "components/media_router/browser/presentation/start_presentation_context.h"
#include "components/media_router/browser/presentation/web_contents_presentation_manager.h"
#include "components/media_router/common/media_source.h"
#include "components/media_router/common/mojom/media_router.mojom.h"
#include "content/public/browser/presentation_request.h"
#include "content/public/browser/presentation_service_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

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

namespace url {
class Origin;
}  // namespace url

namespace media_router {

class MediaRoute;
class PresentationFrame;
class RouteRequestResult;

// Implementation of PresentationServiceDelegate that interfaces an instance of
// WebContents with the Chrome Media Router. It uses the Media Router to handle
// presentation API calls forwarded from PresentationServiceImpl. In addition,
// it also provides default presentation URL that is required for creating
// browser-initiated presentations.  It is scoped to the lifetime of a
// WebContents, and is managed by the associated WebContents.
// It is accessed through the WebContentsPresentationManager interface by
// clients (e.g. the UI code) that is interested in the presentation status of
// the WebContents, but not in other aspects such as the render frame.
class PresentationServiceDelegateImpl
    : public content::WebContentsUserData<PresentationServiceDelegateImpl>,
      public content::ControllerPresentationServiceDelegate,
      public WebContentsPresentationManager {
 public:
  // Retrieves the instance of PresentationServiceDelegateImpl that was attached
  // to the specified WebContents.  If no instance was attached, creates one,
  // and attaches it to the specified WebContents.
  static PresentationServiceDelegateImpl* GetOrCreateForWebContents(
      content::WebContents* web_contents);

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

  ~PresentationServiceDelegateImpl() override;

  // content::PresentationServiceDelegate implementation.
  void AddObserver(
      int render_process_id,
      int render_frame_id,
      content::PresentationServiceDelegate::Observer* observer) override;
  void RemoveObserver(int render_process_id, int render_frame_id) override;
  bool AddScreenAvailabilityListener(
      int render_process_id,
      int render_frame_id,
      content::PresentationScreenAvailabilityListener* listener) override;
  void RemoveScreenAvailabilityListener(
      int render_process_id,
      int render_frame_id,
      content::PresentationScreenAvailabilityListener* listener) override;
  void Reset(int render_process_id, int render_frame_id) override;
  void SetDefaultPresentationUrls(
      const content::PresentationRequest& request,
      content::DefaultPresentationConnectionCallback callback) override;
  void StartPresentation(
      const content::PresentationRequest& request,
      content::PresentationConnectionCallback success_cb,
      content::PresentationConnectionErrorCallback error_cb) override;
  void ReconnectPresentation(
      const content::PresentationRequest& request,
      const std::string& presentation_id,
      content::PresentationConnectionCallback success_cb,
      content::PresentationConnectionErrorCallback error_cb) override;
  void CloseConnection(int render_process_id,
                       int render_frame_id,
                       const std::string& presentation_id) override;
  void Terminate(int render_process_id,
                 int render_frame_id,
                 const std::string& presentation_id) override;
  std::unique_ptr<media::FlingingController> GetFlingingController(
      int render_process_id,
      int render_frame_id,
      const std::string& presentation_id) override;
  void ListenForConnectionStateChange(
      int render_process_id,
      int render_frame_id,
      const blink::mojom::PresentationInfo& connection,
      const content::PresentationConnectionStateChangedCallback&
          state_changed_cb) override;

  // WebContentsPresentationManager implementation.
  void AddObserver(content::PresentationObserver* observer) override;
  void RemoveObserver(content::PresentationObserver* observer) override;
  bool HasDefaultPresentationRequest() const override;
  const content::PresentationRequest& GetDefaultPresentationRequest()
      const override;
  void OnPresentationResponse(const content::PresentationRequest& request,
                              mojom::RoutePresentationConnectionPtr connection,
                              const RouteRequestResult& result) override;
  std::vector<MediaRoute> GetMediaRoutes() override;
  base::WeakPtr<WebContentsPresentationManager> GetWeakPtr() override;

  // Returns the WebContents that owns this instance.
  content::WebContents* web_contents() { return &GetWebContents(); }

  bool HasScreenAvailabilityListenerForTest(
      int render_process_id,
      int render_frame_id,
      const MediaSource::Id& source_id) const;

  void set_start_presentation_cb(
      base::RepeatingCallback<void(std::unique_ptr<StartPresentationContext>)>
          callback) {
    start_presentation_cb_ = std::move(callback);
  }

 private:
  friend class content::WebContentsUserData<PresentationServiceDelegateImpl>;
  FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
                           DelegateObservers);
  FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
                           SetDefaultPresentationUrl);
  FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
                           DefaultPresentationRequestObserver);
  FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
                           DefaultPresentationUrlCallback);
  FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
                           TestCloseConnectionForLocalPresentation);
  FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
                           ConnectToLocalPresentation);
  FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
                           ConnectToPresentation);

  explicit PresentationServiceDelegateImpl(content::WebContents* web_contents);

  PresentationFrame* GetOrAddPresentationFrame(
      const content::GlobalRenderFrameHostId& render_frame_host_id);

  void OnJoinRouteResponse(
      const content::GlobalRenderFrameHostId& render_frame_host_id,
      const GURL& presentation_url,
      const std::string& presentation_id,
      content::PresentationConnectionCallback success_cb,
      content::PresentationConnectionErrorCallback error_cb,
      mojom::RoutePresentationConnectionPtr connection,
      const RouteRequestResult& result);

  void OnStartPresentationSucceeded(
      const content::GlobalRenderFrameHostId& render_frame_host_id,
      content::PresentationConnectionCallback success_cb,
      const blink::mojom::PresentationInfo& new_presentation_info,
      mojom::RoutePresentationConnectionPtr connection,
      const MediaRoute& route);

  // Notifies the PresentationFrame of |render_frame_host_id| that a
  // presentation and its corresponding MediaRoute has been created.
  // The PresentationFrame will be created if it does not already exist.
  void AddPresentation(
      const content::GlobalRenderFrameHostId& render_frame_host_id,
      const blink::mojom::PresentationInfo& presentation_info,
      const MediaRoute& route);

  // Notifies the PresentationFrame of |render_frame_host_id| that a
  // presentation and its corresponding MediaRoute has been removed.
  void RemovePresentation(
      const content::GlobalRenderFrameHostId& render_frame_host_id,
      const std::string& presentation_id);

  // Clears the default presentation request for the owning WebContents and
  // notifies observers of changes. Also resets
  // |default_presentation_started_callback_|.
  void ClearDefaultPresentationRequest();

  // Returns the ID of the route corresponding to |presentation_id| in the given
  // frame, or empty if no such route exist.
  MediaRoute::Id GetRouteId(
      const content::GlobalRenderFrameHostId& render_frame_host_id,
      const std::string& presentation_id) const;

#if !BUILDFLAG(IS_ANDROID)
  // Returns true if auto-join requests should be cancelled for |origin|.
  bool ShouldCancelAutoJoinForOrigin(const url::Origin& origin);
#endif

  // Ensures that |connection| contains a valid pair of
  // blink::mojom::PresentationConnection{PtrInfo,Request} objects which will be
  // used for all Presentation API communication in a newly-connected
  // presentation.
  void EnsurePresentationConnection(
      const content::GlobalRenderFrameHostId& render_frame_host_id,
      const blink::mojom::PresentationInfo& presentation_info,
      mojom::RoutePresentationConnectionPtr* connection);

  void NotifyDefaultPresentationChanged(
      const content::PresentationRequest* request);
  void NotifyMediaRoutesChanged();

  // Invoked by the MR when a Presentation Connection state changes in a frame.
  // It calls |RemovePresentation()| when the connection is closed/terminated.
  void OnConnectionStateChanged(
      const content::GlobalRenderFrameHostId& render_frame_host_id,
      const blink::mojom::PresentationInfo& connection,
      const content::PresentationConnectionStateChangedCallback&
          state_changed_cb,
      const content::PresentationConnectionStateChangeInfo& info);

  // Reference to the associated browser profile's MediaRouter instance.
  raw_ptr<MediaRouter> router_;

  // References to the observers listening for changes to the default
  // presentation and presentation MediaRoutes associated with the
  // WebContents.
  base::ObserverList<content::PresentationObserver> presentation_observers_;

  // Default presentation request for the owning WebContents.
  absl::optional<content::PresentationRequest> default_presentation_request_;

  // Callback to invoke when the default presentation has started.
  content::DefaultPresentationConnectionCallback
      default_presentation_started_callback_;

  // If this callback is set when a request to start a presentation is made,
  // it is called instead of showing the Media Router dialog.
  base::RepeatingCallback<void(std::unique_ptr<StartPresentationContext>)>
      start_presentation_cb_;

  // Maps a frame identifier to a PresentationFrame object for frames
  // that are using Presentation API.
  std::unordered_map<content::GlobalRenderFrameHostId,
                     std::unique_ptr<PresentationFrame>,
                     content::GlobalRenderFrameHostIdHasher>
      presentation_frames_;

  PresentationServiceDelegateObservers observers_;

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

  WEB_CONTENTS_USER_DATA_KEY_DECL();
};

}  // namespace media_router

#endif  // COMPONENTS_MEDIA_ROUTER_BROWSER_PRESENTATION_PRESENTATION_SERVICE_DELEGATE_IMPL_H_