1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CONTENT_BROWSER_PRESENTATION_PRESENTATION_SERVICE_IMPL_H_
6 #define CONTENT_BROWSER_PRESENTATION_PRESENTATION_SERVICE_IMPL_H_
10 #include "base/basictypes.h"
11 #include "base/compiler_specific.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/macros.h"
15 #include "base/memory/linked_ptr.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/scoped_vector.h"
18 #include "base/memory/weak_ptr.h"
19 #include "content/common/content_export.h"
20 #include "content/common/presentation/presentation_service.mojom.h"
21 #include "content/public/browser/navigation_details.h"
22 #include "content/public/browser/presentation_screen_availability_listener.h"
23 #include "content/public/browser/presentation_service_delegate.h"
24 #include "content/public/browser/web_contents_observer.h"
25 #include "content/public/common/frame_navigate_params.h"
29 struct FrameNavigateParams
;
30 struct LoadCommittedDetails
;
31 struct PresentationSessionMessage
;
32 class RenderFrameHost
;
34 using NewSessionMojoCallback
= mojo::Callback
<
35 void(presentation::PresentationSessionInfoPtr
,
36 presentation::PresentationErrorPtr
)>;
38 // Implementation of Mojo PresentationService.
39 // It handles Presentation API requests coming from Blink / renderer process
40 // and delegates the requests to the embedder's media router via
41 // PresentationServiceDelegate.
42 // An instance of this class tied to a RenderFrameHost and listens to events
43 // related to the RFH via implementing WebContentsObserver.
44 // This class is instantiated on-demand via Mojo's ConnectToRemoteService
45 // from the renderer when the first presentation API request is handled.
46 class CONTENT_EXPORT PresentationServiceImpl
47 : public NON_EXPORTED_BASE(presentation::PresentationService
),
48 public mojo::ErrorHandler
,
49 public WebContentsObserver
,
50 public PresentationServiceDelegate::Observer
{
52 ~PresentationServiceImpl() override
;
54 // Static factory method to create an instance of PresentationServiceImpl.
55 // |render_frame_host|: The RFH the instance is associated with.
56 // |request|: The instance will be bound to this request. Used for Mojo setup.
57 static void CreateMojoService(
58 RenderFrameHost
* render_frame_host
,
59 mojo::InterfaceRequest
<presentation::PresentationService
> request
);
62 friend class PresentationServiceImplTest
;
63 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
, Reset
);
64 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
, DidNavigateThisFrame
);
65 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
66 DidNavigateOtherFrame
);
67 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
, ThisRenderFrameDeleted
);
68 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
69 OtherRenderFrameDeleted
);
70 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
, DelegateFails
);
71 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
72 SetDefaultPresentationUrl
);
73 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
74 SetSameDefaultPresentationUrl
);
75 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
76 ClearDefaultPresentationUrl
);
77 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
78 ListenForDefaultSessionStart
);
79 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
80 ListenForDefaultSessionStartAfterSet
);
81 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
82 DefaultSessionStartReset
);
83 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
84 ReceiveSessionMessagesAfterReset
);
85 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
86 MaxPendingStartSessionRequests
);
87 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
88 MaxPendingJoinSessionRequests
);
89 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
90 ListenForSessionStateChange
);
91 // Maximum number of pending JoinSession requests at any given time.
92 static const int kMaxNumQueuedSessionRequests
= 10;
94 using DefaultSessionMojoCallback
=
95 mojo::Callback
<void(presentation::PresentationSessionInfoPtr
)>;
96 using SessionStateCallback
=
97 mojo::Callback
<void(presentation::PresentationSessionInfoPtr
,
98 presentation::PresentationSessionState
)>;
99 using SessionMessagesCallback
=
100 mojo::Callback
<void(mojo::Array
<presentation::SessionMessagePtr
>)>;
101 using SendMessageMojoCallback
= mojo::Callback
<void(bool)>;
103 // Listener implementation owned by PresentationServiceImpl. An instance of
104 // this is created when an |onavailablechange| handler is added.
105 // The instance receives screen availability results from the embedder and
106 // propagates results back to PresentationServiceImpl.
107 class CONTENT_EXPORT ScreenAvailabilityListenerImpl
108 : public PresentationScreenAvailabilityListener
{
110 ScreenAvailabilityListenerImpl(
111 const std::string
& presentation_url
,
112 PresentationServiceImpl
* service
);
113 ~ScreenAvailabilityListenerImpl() override
;
115 // PresentationScreenAvailabilityListener implementation.
116 std::string
GetPresentationUrl() const override
;
117 void OnScreenAvailabilityChanged(bool available
) override
;
120 const std::string presentation_url_
;
121 PresentationServiceImpl
* const service_
;
124 class CONTENT_EXPORT DefaultSessionStartContext
{
126 DefaultSessionStartContext();
127 ~DefaultSessionStartContext();
129 // Adds a callback. May invoke the callback immediately if |session| using
130 // default presentation URL was already started.
131 void AddCallback(const DefaultSessionMojoCallback
& callback
);
133 // Sets the session info. Maybe invoke callbacks queued with AddCallback().
134 void set_session(const PresentationSessionInfo
& session
);
137 // Flush all queued callbacks by invoking them with null
138 // PresentationSessionInfoPtr.
141 ScopedVector
<DefaultSessionMojoCallback
> callbacks_
;
142 scoped_ptr
<PresentationSessionInfo
> session_
;
145 // Ensures the provided NewSessionMojoCallback is invoked exactly once
146 // before it goes out of scope.
147 class NewSessionMojoCallbackWrapper
{
149 explicit NewSessionMojoCallbackWrapper(
150 const NewSessionMojoCallback
& callback
);
151 ~NewSessionMojoCallbackWrapper();
153 void Run(presentation::PresentationSessionInfoPtr session
,
154 presentation::PresentationErrorPtr error
);
157 NewSessionMojoCallback callback_
;
159 DISALLOW_COPY_AND_ASSIGN(NewSessionMojoCallbackWrapper
);
162 // |render_frame_host|: The RFH this instance is associated with.
163 // |web_contents|: The WebContents to observe.
164 // |delegate|: Where Presentation API requests are delegated to. Not owned
166 PresentationServiceImpl(
167 RenderFrameHost
* render_frame_host
,
168 WebContents
* web_contents
,
169 PresentationServiceDelegate
* delegate
);
171 // PresentationService implementation.
172 void SetDefaultPresentationURL(const mojo::String
& url
) override
;
173 void SetClient(presentation::PresentationServiceClientPtr client
) override
;
174 void ListenForScreenAvailability() override
;
175 void StopListeningForScreenAvailability() override
;
176 void ListenForDefaultSessionStart(
177 const DefaultSessionMojoCallback
& callback
) override
;
179 const mojo::String
& presentation_url
,
180 const NewSessionMojoCallback
& callback
) override
;
182 const mojo::String
& presentation_url
,
183 const mojo::String
& presentation_id
,
184 const NewSessionMojoCallback
& callback
) override
;
185 void SendSessionMessage(presentation::PresentationSessionInfoPtr session_info
,
186 presentation::SessionMessagePtr session_message
,
187 const SendMessageMojoCallback
& callback
) override
;
189 const mojo::String
& presentation_url
,
190 const mojo::String
& presentation_id
) override
;
191 void ListenForSessionStateChange() override
;
192 void ListenForSessionMessages(
193 presentation::PresentationSessionInfoPtr session
) override
;
195 // Creates a binding between this object and |request|.
196 void Bind(mojo::InterfaceRequest
<presentation::PresentationService
> request
);
198 // mojo::ErrorHandler override.
199 // Note that this is called when the RenderFrameHost is deleted.
200 void OnConnectionError() override
;
202 // WebContentsObserver override.
203 void DidNavigateAnyFrame(
204 content::RenderFrameHost
* render_frame_host
,
205 const content::LoadCommittedDetails
& details
,
206 const content::FrameNavigateParams
& params
) override
;
207 void RenderFrameDeleted(content::RenderFrameHost
* render_frame_host
) override
;
209 // PresentationServiceDelegate::Observer
210 void OnDelegateDestroyed() override
;
211 void OnDefaultPresentationStarted(const PresentationSessionInfo
& session
)
214 // Finds the callback from |pending_join_session_cbs_| using
215 // |request_session_id|.
216 // If it exists, invoke it with |session| and |error|, then erase it from
217 // |pending_join_session_cbs_|.
218 void RunAndEraseJoinSessionMojoCallback(
219 int request_session_id
,
220 presentation::PresentationSessionInfoPtr session
,
221 presentation::PresentationErrorPtr error
);
223 // Creates a new screen availability listener for |presentation_url| and
224 // registers it with |delegate_|. Replaces the existing listener if any.
225 void ResetScreenAvailabilityListener(const std::string
& presentation_url
);
227 // Removes all listeners and resets default presentation URL on this instance
228 // and informs the PresentationServiceDelegate of such.
231 // These functions are bound as base::Callbacks and passed to
232 // embedder's implementation of PresentationServiceDelegate for later
234 void OnStartSessionSucceeded(
235 int request_session_id
,
236 const PresentationSessionInfo
& session_info
);
237 void OnStartSessionError(
238 int request_session_id
,
239 const PresentationError
& error
);
240 void OnJoinSessionSucceeded(
241 int request_session_id
,
242 const PresentationSessionInfo
& session_info
);
243 void OnJoinSessionError(
244 int request_session_id
,
245 const PresentationError
& error
);
246 void OnSendMessageCallback(bool sent
);
248 // Passed to embedder's implementation of PresentationServiceDelegate for
249 // later invocation when session messages arrive.
250 void OnSessionMessages(
251 const content::PresentationSessionInfo
& session
,
252 const ScopedVector
<PresentationSessionMessage
>& messages
);
254 // Associates a JoinSession |callback| with a unique request ID and
255 // stores it in a map.
256 // Returns a positive value on success.
257 int RegisterJoinSessionCallback(const NewSessionMojoCallback
& callback
);
259 // Invoked by the embedder's PresentationServiceDelegate when a
260 // presentation session's state has changed.
261 void OnSessionStateChanged(const PresentationSessionInfo
& session_info
,
262 PresentationSessionState session_state
);
264 // Returns true if this object is associated with |render_frame_host|.
265 bool FrameMatches(content::RenderFrameHost
* render_frame_host
) const;
267 // Embedder-specific delegate to forward Presentation requests to.
268 // May be null if embedder does not support Presentation API.
269 PresentationServiceDelegate
* delegate_
;
271 // Proxy to the PresentationServiceClient to send results (e.g., screen
273 presentation::PresentationServiceClientPtr client_
;
275 std::string default_presentation_url_
;
277 scoped_ptr
<ScreenAvailabilityListenerImpl
> screen_availability_listener_
;
279 // For StartSession requests.
280 // Set to a positive value when a StartSession request is being processed.
281 int start_session_request_id_
;
282 scoped_ptr
<NewSessionMojoCallbackWrapper
> pending_start_session_cb_
;
284 // For JoinSession requests.
285 base::hash_map
<int, linked_ptr
<NewSessionMojoCallbackWrapper
>>
286 pending_join_session_cbs_
;
288 scoped_ptr
<DefaultSessionStartContext
> default_session_start_context_
;
290 // RAII binding of |this| to an Presentation interface request.
291 // The binding is removed when binding_ is cleared or goes out of scope.
292 scoped_ptr
<mojo::Binding
<presentation::PresentationService
>> binding_
;
294 // There can be only one send message request at a time.
295 scoped_ptr
<SendMessageMojoCallback
> send_message_callback_
;
297 scoped_ptr
<SessionMessagesCallback
> on_session_messages_callback_
;
299 // ID of the RenderFrameHost this object is associated with.
300 int render_process_id_
;
301 int render_frame_id_
;
303 // NOTE: Weak pointers must be invalidated before all other member variables.
304 base::WeakPtrFactory
<PresentationServiceImpl
> weak_factory_
;
306 DISALLOW_COPY_AND_ASSIGN(PresentationServiceImpl
);
309 } // namespace content
311 #endif // CONTENT_BROWSER_PRESENTATION_PRESENTATION_SERVICE_IMPL_H_