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_
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/containers/hash_tables.h"
15 #include "base/containers/scoped_ptr_map.h"
16 #include "base/gtest_prod_util.h"
17 #include "base/macros.h"
18 #include "base/memory/linked_ptr.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/memory/scoped_vector.h"
21 #include "base/memory/weak_ptr.h"
22 #include "content/common/content_export.h"
23 #include "content/common/presentation/presentation_service.mojom.h"
24 #include "content/public/browser/navigation_details.h"
25 #include "content/public/browser/presentation_screen_availability_listener.h"
26 #include "content/public/browser/presentation_service_delegate.h"
27 #include "content/public/browser/web_contents_observer.h"
28 #include "content/public/common/frame_navigate_params.h"
29 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
33 struct FrameNavigateParams
;
34 struct LoadCommittedDetails
;
35 struct PresentationSessionMessage
;
36 class RenderFrameHost
;
38 using NewSessionMojoCallback
= mojo::Callback
<
39 void(presentation::PresentationSessionInfoPtr
,
40 presentation::PresentationErrorPtr
)>;
42 // Implementation of Mojo PresentationService.
43 // It handles Presentation API requests coming from Blink / renderer process
44 // and delegates the requests to the embedder's media router via
45 // PresentationServiceDelegate.
46 // An instance of this class tied to a RenderFrameHost and listens to events
47 // related to the RFH via implementing WebContentsObserver.
48 // This class is instantiated on-demand via Mojo's ConnectToRemoteService
49 // from the renderer when the first presentation API request is handled.
50 class CONTENT_EXPORT PresentationServiceImpl
51 : public NON_EXPORTED_BASE(presentation::PresentationService
),
52 public WebContentsObserver
,
53 public PresentationServiceDelegate::Observer
{
55 ~PresentationServiceImpl() override
;
57 // Static factory method to create an instance of PresentationServiceImpl.
58 // |render_frame_host|: The RFH the instance is associated with.
59 // |request|: The instance will be bound to this request. Used for Mojo setup.
60 static void CreateMojoService(
61 RenderFrameHost
* render_frame_host
,
62 mojo::InterfaceRequest
<presentation::PresentationService
> request
);
65 friend class PresentationServiceImplTest
;
66 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
, Reset
);
67 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
, DidNavigateThisFrame
);
68 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
69 DidNavigateOtherFrame
);
70 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
, ThisRenderFrameDeleted
);
71 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
72 OtherRenderFrameDeleted
);
73 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
, DelegateFails
);
74 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
75 SetDefaultPresentationUrl
);
76 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
77 SetSameDefaultPresentationUrl
);
78 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
79 ClearDefaultPresentationUrl
);
80 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
81 ListenForDefaultSessionStart
);
82 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
83 ListenForDefaultSessionStartAfterSet
);
84 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
85 DefaultSessionStartReset
);
86 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
87 ReceiveSessionMessagesAfterReset
);
88 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
89 MaxPendingStartSessionRequests
);
90 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
91 MaxPendingJoinSessionRequests
);
92 FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest
,
93 ListenForSessionStateChange
);
94 // Maximum number of pending JoinSession requests at any given time.
95 static const int kMaxNumQueuedSessionRequests
= 10;
97 using DefaultSessionMojoCallback
=
98 mojo::Callback
<void(presentation::PresentationSessionInfoPtr
)>;
99 using SessionStateCallback
=
100 mojo::Callback
<void(presentation::PresentationSessionInfoPtr
,
101 presentation::PresentationSessionState
)>;
102 using SessionMessagesCallback
=
103 mojo::Callback
<void(mojo::Array
<presentation::SessionMessagePtr
>)>;
104 using SendMessageMojoCallback
= mojo::Callback
<void(bool)>;
106 // Listener implementation owned by PresentationServiceImpl. An instance of
107 // this is created when PresentationRequest.getAvailability() is resolved.
108 // The instance receives screen availability results from the embedder and
109 // propagates results back to PresentationServiceImpl.
110 class CONTENT_EXPORT ScreenAvailabilityListenerImpl
111 : public PresentationScreenAvailabilityListener
{
113 ScreenAvailabilityListenerImpl(
114 const std::string
& availability_url
,
115 PresentationServiceImpl
* service
);
116 ~ScreenAvailabilityListenerImpl() override
;
118 // PresentationScreenAvailabilityListener implementation.
119 std::string
GetAvailabilityUrl() const override
;
120 void OnScreenAvailabilityChanged(bool available
) override
;
123 const std::string availability_url_
;
124 PresentationServiceImpl
* const service_
;
127 class CONTENT_EXPORT DefaultSessionStartContext
{
129 DefaultSessionStartContext();
130 ~DefaultSessionStartContext();
132 // Adds a callback. May invoke the callback immediately if |session| using
133 // default presentation URL was already started.
134 void AddCallback(const DefaultSessionMojoCallback
& callback
);
136 // Sets the session info. Maybe invoke callbacks queued with AddCallback().
137 void set_session(const PresentationSessionInfo
& session
);
140 // Flush all queued callbacks by invoking them with null
141 // PresentationSessionInfoPtr.
144 ScopedVector
<DefaultSessionMojoCallback
> callbacks_
;
145 scoped_ptr
<PresentationSessionInfo
> session_
;
148 // Ensures the provided NewSessionMojoCallback is invoked exactly once
149 // before it goes out of scope.
150 class NewSessionMojoCallbackWrapper
{
152 explicit NewSessionMojoCallbackWrapper(
153 const NewSessionMojoCallback
& callback
);
154 ~NewSessionMojoCallbackWrapper();
156 void Run(presentation::PresentationSessionInfoPtr session
,
157 presentation::PresentationErrorPtr error
);
160 NewSessionMojoCallback callback_
;
162 DISALLOW_COPY_AND_ASSIGN(NewSessionMojoCallbackWrapper
);
165 // |render_frame_host|: The RFH this instance is associated with.
166 // |web_contents|: The WebContents to observe.
167 // |delegate|: Where Presentation API requests are delegated to. Not owned
169 PresentationServiceImpl(
170 RenderFrameHost
* render_frame_host
,
171 WebContents
* web_contents
,
172 PresentationServiceDelegate
* delegate
);
174 // PresentationService implementation.
175 void SetDefaultPresentationURL(const mojo::String
& url
) override
;
176 void SetClient(presentation::PresentationServiceClientPtr client
) override
;
177 void ListenForScreenAvailability(const mojo::String
& url
) override
;
178 void StopListeningForScreenAvailability(const mojo::String
& url
) override
;
179 void ListenForDefaultSessionStart(
180 const DefaultSessionMojoCallback
& callback
) override
;
182 const mojo::String
& presentation_url
,
183 const NewSessionMojoCallback
& callback
) override
;
185 const mojo::String
& presentation_url
,
186 const mojo::String
& presentation_id
,
187 const NewSessionMojoCallback
& callback
) override
;
188 void SendSessionMessage(presentation::PresentationSessionInfoPtr session_info
,
189 presentation::SessionMessagePtr session_message
,
190 const SendMessageMojoCallback
& callback
) override
;
192 const mojo::String
& presentation_url
,
193 const mojo::String
& presentation_id
) override
;
194 void ListenForSessionStateChange() override
;
195 void ListenForSessionMessages(
196 presentation::PresentationSessionInfoPtr session
) override
;
198 // Creates a binding between this object and |request|.
199 void Bind(mojo::InterfaceRequest
<presentation::PresentationService
> request
);
201 // WebContentsObserver override.
202 void DidNavigateAnyFrame(
203 content::RenderFrameHost
* render_frame_host
,
204 const content::LoadCommittedDetails
& details
,
205 const content::FrameNavigateParams
& params
) override
;
206 void RenderFrameDeleted(content::RenderFrameHost
* render_frame_host
) override
;
208 // PresentationServiceDelegate::Observer
209 void OnDelegateDestroyed() override
;
210 void OnDefaultPresentationStarted(const PresentationSessionInfo
& session
)
213 // Finds the callback from |pending_join_session_cbs_| using
214 // |request_session_id|.
215 // If it exists, invoke it with |session| and |error|, then erase it from
216 // |pending_join_session_cbs_|.
217 void RunAndEraseJoinSessionMojoCallback(
218 int request_session_id
,
219 presentation::PresentationSessionInfoPtr session
,
220 presentation::PresentationErrorPtr error
);
222 // Removes all listeners and resets default presentation URL on this instance
223 // and informs the PresentationServiceDelegate of such.
226 // These functions are bound as base::Callbacks and passed to
227 // embedder's implementation of PresentationServiceDelegate for later
229 void OnStartSessionSucceeded(
230 int request_session_id
,
231 const PresentationSessionInfo
& session_info
);
232 void OnStartSessionError(
233 int request_session_id
,
234 const PresentationError
& error
);
235 void OnJoinSessionSucceeded(
236 int request_session_id
,
237 const PresentationSessionInfo
& session_info
);
238 void OnJoinSessionError(
239 int request_session_id
,
240 const PresentationError
& error
);
241 void OnSendMessageCallback(bool sent
);
243 // Passed to embedder's implementation of PresentationServiceDelegate for
244 // later invocation when session messages arrive.
245 void OnSessionMessages(
246 const content::PresentationSessionInfo
& session
,
247 const ScopedVector
<PresentationSessionMessage
>& messages
,
248 bool pass_ownership
);
250 // Associates a JoinSession |callback| with a unique request ID and
251 // stores it in a map.
252 // Returns a positive value on success.
253 int RegisterJoinSessionCallback(const NewSessionMojoCallback
& callback
);
255 // Invoked by the embedder's PresentationServiceDelegate when a
256 // presentation session's state has changed.
257 void OnSessionStateChanged(const PresentationSessionInfo
& session_info
,
258 PresentationSessionState session_state
);
260 // Returns true if this object is associated with |render_frame_host|.
261 bool FrameMatches(content::RenderFrameHost
* render_frame_host
) const;
263 // Embedder-specific delegate to forward Presentation requests to.
264 // May be null if embedder does not support Presentation API.
265 PresentationServiceDelegate
* delegate_
;
267 // Proxy to the PresentationServiceClient to send results (e.g., screen
269 presentation::PresentationServiceClientPtr client_
;
271 std::string default_presentation_url_
;
273 using ScreenAvailabilityListenerMap
=
274 base::ScopedPtrMap
<std::string
, scoped_ptr
<ScreenAvailabilityListenerImpl
>>;
275 ScreenAvailabilityListenerMap screen_availability_listeners_
;
277 // For StartSession requests.
278 // Set to a positive value when a StartSession request is being processed.
279 int start_session_request_id_
;
280 scoped_ptr
<NewSessionMojoCallbackWrapper
> pending_start_session_cb_
;
282 // For JoinSession requests.
283 base::hash_map
<int, linked_ptr
<NewSessionMojoCallbackWrapper
>>
284 pending_join_session_cbs_
;
286 scoped_ptr
<DefaultSessionStartContext
> default_session_start_context_
;
288 // RAII binding of |this| to an Presentation interface request.
289 // The binding is removed when binding_ is cleared or goes out of scope.
290 scoped_ptr
<mojo::Binding
<presentation::PresentationService
>> binding_
;
292 // There can be only one send message request at a time.
293 scoped_ptr
<SendMessageMojoCallback
> send_message_callback_
;
295 scoped_ptr
<SessionMessagesCallback
> on_session_messages_callback_
;
297 // ID of the RenderFrameHost this object is associated with.
298 int render_process_id_
;
299 int render_frame_id_
;
301 // NOTE: Weak pointers must be invalidated before all other member variables.
302 base::WeakPtrFactory
<PresentationServiceImpl
> weak_factory_
;
304 DISALLOW_COPY_AND_ASSIGN(PresentationServiceImpl
);
307 } // namespace content
309 #endif // CONTENT_BROWSER_PRESENTATION_PRESENTATION_SERVICE_IMPL_H_