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 #include "chrome/browser/media/router/presentation_service_delegate_impl.h"
9 #include "base/containers/scoped_ptr_hash_map.h"
10 #include "base/containers/small_map.h"
11 #include "base/guid.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "chrome/browser/media/router/create_presentation_session_request.h"
15 #include "chrome/browser/media/router/media_route.h"
16 #include "chrome/browser/media/router/media_router.h"
17 #include "chrome/browser/media/router/media_router_dialog_controller.h"
18 #include "chrome/browser/media/router/media_router_factory.h"
19 #include "chrome/browser/media/router/media_sink.h"
20 #include "chrome/browser/media/router/media_source_helper.h"
21 #include "chrome/browser/media/router/presentation_media_sinks_observer.h"
22 #include "chrome/browser/media/router/presentation_session_messages_observer.h"
23 #include "chrome/browser/media/router/presentation_session_state_observer.h"
24 #include "chrome/browser/sessions/session_tab_helper.h"
25 #include "content/public/browser/presentation_screen_availability_listener.h"
26 #include "content/public/browser/presentation_session.h"
27 #include "content/public/browser/render_frame_host.h"
28 #include "content/public/browser/render_process_host.h"
30 DEFINE_WEB_CONTENTS_USER_DATA_KEY(
31 media_router::PresentationServiceDelegateImpl
);
33 using content::RenderFrameHost
;
35 namespace media_router
{
39 using DelegateObserver
= content::PresentationServiceDelegate::Observer
;
40 using PresentationSessionErrorCallback
=
41 content::PresentationServiceDelegate::PresentationSessionErrorCallback
;
42 using PresentationSessionSuccessCallback
=
43 content::PresentationServiceDelegate::PresentationSessionSuccessCallback
;
45 using RenderFrameHostId
= std::pair
<int, int>;
47 // Returns the unique identifier for the supplied RenderFrameHost.
48 RenderFrameHostId
GetRenderFrameHostId(RenderFrameHost
* render_frame_host
) {
49 int render_process_id
= render_frame_host
->GetProcess()->GetID();
50 int render_frame_id
= render_frame_host
->GetRoutingID();
51 return RenderFrameHostId(render_process_id
, render_frame_id
);
54 // Gets the last committed URL for the render frame specified by
55 // |render_frame_host_id|.
56 GURL
GetLastCommittedURLForFrame(RenderFrameHostId render_frame_host_id
) {
57 RenderFrameHost
* render_frame_host
= RenderFrameHost::FromID(
58 render_frame_host_id
.first
, render_frame_host_id
.second
);
59 DCHECK(render_frame_host
);
60 return render_frame_host
->GetLastCommittedURL();
65 // Used by PresentationServiceDelegateImpl to manage
66 // listeners and default presentation info in a render frame.
68 // * PresentationFrameManager AddDelegateObserver
70 // * PresentationFrameManager.RemoveDelegateObserver.
71 class PresentationFrame
{
73 PresentationFrame(content::WebContents
* web_contents
, MediaRouter
* router
);
76 // Mirror corresponding APIs in PresentationServiceDelegateImpl.
77 bool SetScreenAvailabilityListener(
78 content::PresentationScreenAvailabilityListener
* listener
);
79 bool RemoveScreenAvailabilityListener(
80 content::PresentationScreenAvailabilityListener
* listener
);
81 bool HasScreenAvailabilityListenerForTest(
82 const MediaSource::Id
& source_id
) const;
83 std::string
GetDefaultPresentationId() const;
84 void ListenForSessionStateChange(
85 const content::SessionStateChangedCallback
& state_changed_cb
);
86 void ListenForSessionMessages(
87 const content::PresentationSessionInfo
& session
,
88 const content::PresentationSessionMessageCallback
& message_cb
);
91 const MediaRoute::Id
GetRouteId(const std::string
& presentation_id
) const;
92 const std::vector
<MediaRoute::Id
> GetRouteIds() const;
93 void OnPresentationSessionClosed(const std::string
& presentation_id
);
95 void OnPresentationSessionStarted(
96 bool is_default_presentation
,
97 const content::PresentationSessionInfo
& session
,
98 const MediaRoute::Id
& route_id
);
99 void OnPresentationServiceDelegateDestroyed() const;
101 void set_delegate_observer(DelegateObserver
* observer
) {
102 delegate_observer_
= observer
;
105 void set_default_presentation_url(const std::string
& url
) {
106 default_presentation_url_
= url
;
110 MediaSource
GetMediaSourceFromListener(
111 content::PresentationScreenAvailabilityListener
* listener
) const;
112 MediaRouteIdToPresentationSessionMapping route_id_to_presentation_
;
113 base::SmallMap
<std::map
<std::string
, MediaRoute::Id
>>
114 presentation_id_to_route_id_
;
115 std::string default_presentation_url_
;
116 scoped_ptr
<PresentationMediaSinksObserver
> sinks_observer_
;
117 scoped_ptr
<PresentationSessionStateObserver
> session_state_observer_
;
118 ScopedVector
<PresentationSessionMessagesObserver
> session_messages_observers_
;
120 // References to the owning WebContents, and the corresponding MediaRouter.
121 const content::WebContents
* web_contents_
;
122 MediaRouter
* router_
;
124 DelegateObserver
* delegate_observer_
;
127 PresentationFrame::PresentationFrame(content::WebContents
* web_contents
,
129 : web_contents_(web_contents
),
131 delegate_observer_(nullptr) {
132 DCHECK(web_contents_
);
136 PresentationFrame::~PresentationFrame() {
139 void PresentationFrame::OnPresentationServiceDelegateDestroyed() const {
140 if (delegate_observer_
)
141 delegate_observer_
->OnDelegateDestroyed();
144 void PresentationFrame::OnPresentationSessionStarted(
145 bool is_default_presentation
,
146 const content::PresentationSessionInfo
& session
,
147 const MediaRoute::Id
& route_id
) {
148 presentation_id_to_route_id_
[session
.presentation_id
] = route_id
;
149 route_id_to_presentation_
.Add(route_id
, session
);
150 if (session_state_observer_
)
151 session_state_observer_
->OnPresentationSessionConnected(route_id
);
152 if (is_default_presentation
&& delegate_observer_
)
153 delegate_observer_
->OnDefaultPresentationStarted(session
);
156 void PresentationFrame::OnPresentationSessionClosed(
157 const std::string
& presentation_id
) {
158 auto it
= presentation_id_to_route_id_
.find(presentation_id
);
159 if (it
!= presentation_id_to_route_id_
.end()) {
160 route_id_to_presentation_
.Remove(it
->second
);
161 presentation_id_to_route_id_
.erase(it
);
163 // TODO(imcheng): Notify |session_state_observer_|?
166 const MediaRoute::Id
PresentationFrame::GetRouteId(
167 const std::string
& presentation_id
) const {
168 auto it
= presentation_id_to_route_id_
.find(presentation_id
);
169 return it
!= presentation_id_to_route_id_
.end() ? it
->second
: "";
172 const std::vector
<MediaRoute::Id
> PresentationFrame::GetRouteIds() const {
173 std::vector
<MediaRoute::Id
> route_ids
;
174 for (const auto& e
: presentation_id_to_route_id_
)
175 route_ids
.push_back(e
.second
);
179 bool PresentationFrame::SetScreenAvailabilityListener(
180 content::PresentationScreenAvailabilityListener
* listener
) {
181 if (sinks_observer_
&& sinks_observer_
->listener() == listener
) {
184 MediaSource
source(GetMediaSourceFromListener(listener
));
185 sinks_observer_
.reset(
186 new PresentationMediaSinksObserver(router_
, listener
, source
));
190 bool PresentationFrame::RemoveScreenAvailabilityListener(
191 content::PresentationScreenAvailabilityListener
* listener
) {
192 if (sinks_observer_
&& sinks_observer_
->listener() == listener
) {
193 sinks_observer_
.reset();
199 bool PresentationFrame::HasScreenAvailabilityListenerForTest(
200 const MediaSource::Id
& source_id
) const {
201 return sinks_observer_
&& sinks_observer_
->source().id() == source_id
;
204 void PresentationFrame::Reset() {
205 route_id_to_presentation_
.Clear();
207 for (const auto& pid_route_id
: presentation_id_to_route_id_
)
208 router_
->OnPresentationSessionDetached(pid_route_id
.second
);
210 presentation_id_to_route_id_
.clear();
211 sinks_observer_
.reset();
212 default_presentation_url_
.clear();
213 if (session_state_observer_
)
214 session_state_observer_
->Reset();
215 session_messages_observers_
.clear();
218 void PresentationFrame::ListenForSessionStateChange(
219 const content::SessionStateChangedCallback
& state_changed_cb
) {
220 CHECK(!session_state_observer_
.get());
221 session_state_observer_
.reset(new PresentationSessionStateObserver(
222 state_changed_cb
, &route_id_to_presentation_
, router_
));
225 void PresentationFrame::ListenForSessionMessages(
226 const content::PresentationSessionInfo
& session
,
227 const content::PresentationSessionMessageCallback
& message_cb
) {
228 auto it
= presentation_id_to_route_id_
.find(session
.presentation_id
);
229 if (it
== presentation_id_to_route_id_
.end()) {
230 DVLOG(2) << "ListenForSessionMessages: no route for "
231 << session
.presentation_id
;
235 session_messages_observers_
.push_back(
236 new PresentationSessionMessagesObserver(message_cb
, it
->second
, router_
));
239 MediaSource
PresentationFrame::GetMediaSourceFromListener(
240 content::PresentationScreenAvailabilityListener
* listener
) const {
241 // If the default presentation URL is empty then fall back to tab mirroring.
242 std::string
availability_url(listener
->GetAvailabilityUrl());
243 return availability_url
.empty()
244 ? MediaSourceForTab(SessionTabHelper::IdForTab(web_contents_
))
245 : MediaSourceForPresentationUrl(availability_url
);
248 // Used by PresentationServiceDelegateImpl to manage PresentationFrames.
249 class PresentationFrameManager
{
251 PresentationFrameManager(content::WebContents
* web_contents
,
252 MediaRouter
* router
);
253 ~PresentationFrameManager();
255 // Mirror corresponding APIs in PresentationServiceDelegateImpl.
256 bool SetScreenAvailabilityListener(
257 const RenderFrameHostId
& render_frame_host_id
,
258 content::PresentationScreenAvailabilityListener
* listener
);
259 bool RemoveScreenAvailabilityListener(
260 const RenderFrameHostId
& render_frame_host_id
,
261 content::PresentationScreenAvailabilityListener
* listener
);
262 void SetDefaultPresentationUrl(const RenderFrameHostId
& render_frame_host_id
,
263 const std::string
& default_presentation_url
);
264 void ListenForSessionStateChange(
265 const RenderFrameHostId
& render_frame_host_id
,
266 const content::SessionStateChangedCallback
& state_changed_cb
);
267 void ListenForSessionMessages(
268 const RenderFrameHostId
& render_frame_host_id
,
269 const content::PresentationSessionInfo
& session
,
270 const content::PresentationSessionMessageCallback
& message_cb
);
271 void AddDelegateObserver(const RenderFrameHostId
& render_frame_host_id
,
272 DelegateObserver
* observer
);
273 void RemoveDelegateObserver(const RenderFrameHostId
& render_frame_host_id
);
274 void Reset(const RenderFrameHostId
& render_frame_host_id
);
275 bool HasScreenAvailabilityListenerForTest(
276 const RenderFrameHostId
& render_frame_host_id
,
277 const MediaSource::Id
& source_id
) const;
278 void SetMediaRouterForTest(MediaRouter
* router
);
280 void OnPresentationSessionStarted(
281 const RenderFrameHostId
& render_frame_host_id
,
282 bool is_default_presentation
,
283 const content::PresentationSessionInfo
& session
,
284 const MediaRoute::Id
& route_id
);
286 void OnPresentationSessionClosed(
287 const RenderFrameHostId
& render_frame_host_id
,
288 const std::string
& presentation_id
);
289 const MediaRoute::Id
GetRouteId(const RenderFrameHostId
& render_frame_host_id
,
290 const std::string
& presentation_id
) const;
291 const std::vector
<MediaRoute::Id
> GetRouteIds(
292 const RenderFrameHostId
& render_frame_host_id
) const;
295 PresentationFrame
* GetOrAddPresentationFrame(
296 const RenderFrameHostId
& render_frame_host_id
);
298 // Maps a frame identifier to a PresentationFrame object for frames
299 // that are using presentation API.
300 base::ScopedPtrHashMap
<RenderFrameHostId
, scoped_ptr
<PresentationFrame
>>
301 presentation_frames_
;
303 // References to the owning WebContents, and the corresponding MediaRouter.
304 MediaRouter
* router_
;
305 content::WebContents
* web_contents_
;
308 PresentationFrameManager::PresentationFrameManager(
309 content::WebContents
* web_contents
,
311 : router_(router
), web_contents_(web_contents
) {
312 DCHECK(web_contents_
);
316 PresentationFrameManager::~PresentationFrameManager() {
317 for (auto& frame
: presentation_frames_
)
318 frame
.second
->OnPresentationServiceDelegateDestroyed();
321 void PresentationFrameManager::OnPresentationSessionStarted(
322 const RenderFrameHostId
& render_frame_host_id
,
323 bool is_default_presentation
,
324 const content::PresentationSessionInfo
& session
,
325 const MediaRoute::Id
& route_id
) {
326 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
327 if (presentation_frame
)
328 presentation_frame
->OnPresentationSessionStarted(is_default_presentation
,
332 void PresentationFrameManager::OnPresentationSessionClosed(
333 const RenderFrameHostId
& render_frame_host_id
,
334 const std::string
& presentation_id
) {
335 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
336 if (presentation_frame
)
337 presentation_frame
->OnPresentationSessionClosed(presentation_id
);
340 const MediaRoute::Id
PresentationFrameManager::GetRouteId(
341 const RenderFrameHostId
& render_frame_host_id
,
342 const std::string
& presentation_id
) const {
343 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
344 return presentation_frame
? presentation_frame
->GetRouteId(presentation_id
)
348 const std::vector
<MediaRoute::Id
> PresentationFrameManager::GetRouteIds(
349 const RenderFrameHostId
& render_frame_host_id
) const {
350 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
351 return presentation_frame
? presentation_frame
->GetRouteIds()
352 : std::vector
<MediaRoute::Id
>();
355 bool PresentationFrameManager::SetScreenAvailabilityListener(
356 const RenderFrameHostId
& render_frame_host_id
,
357 content::PresentationScreenAvailabilityListener
* listener
) {
359 auto presentation_frame
= GetOrAddPresentationFrame(render_frame_host_id
);
360 return presentation_frame
->SetScreenAvailabilityListener(listener
);
363 bool PresentationFrameManager::RemoveScreenAvailabilityListener(
364 const RenderFrameHostId
& render_frame_host_id
,
365 content::PresentationScreenAvailabilityListener
* listener
) {
367 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
368 return presentation_frame
&&
369 presentation_frame
->RemoveScreenAvailabilityListener(listener
);
372 bool PresentationFrameManager::HasScreenAvailabilityListenerForTest(
373 const RenderFrameHostId
& render_frame_host_id
,
374 const MediaSource::Id
& source_id
) const {
375 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
376 return presentation_frame
&&
377 presentation_frame
->HasScreenAvailabilityListenerForTest(source_id
);
380 void PresentationFrameManager::SetDefaultPresentationUrl(
381 const RenderFrameHostId
& render_frame_host_id
,
382 const std::string
& default_presentation_url
) {
383 auto presentation_frame
= GetOrAddPresentationFrame(render_frame_host_id
);
384 presentation_frame
->set_default_presentation_url(default_presentation_url
);
387 void PresentationFrameManager::ListenForSessionStateChange(
388 const RenderFrameHostId
& render_frame_host_id
,
389 const content::SessionStateChangedCallback
& state_changed_cb
) {
390 PresentationFrame
* presentation_frame
=
391 GetOrAddPresentationFrame(render_frame_host_id
);
392 presentation_frame
->ListenForSessionStateChange(state_changed_cb
);
395 void PresentationFrameManager::ListenForSessionMessages(
396 const RenderFrameHostId
& render_frame_host_id
,
397 const content::PresentationSessionInfo
& session
,
398 const content::PresentationSessionMessageCallback
& message_cb
) {
399 PresentationFrame
* presentation_frame
=
400 presentation_frames_
.get(render_frame_host_id
);
401 if (!presentation_frame
) {
402 DVLOG(2) << "ListenForSessionMessages: PresentationFrame does not exist "
403 << "for: (" << render_frame_host_id
.first
<< ", "
404 << render_frame_host_id
.second
<< ")";
407 presentation_frame
->ListenForSessionMessages(session
, message_cb
);
410 void PresentationFrameManager::AddDelegateObserver(
411 const RenderFrameHostId
& render_frame_host_id
,
412 DelegateObserver
* observer
) {
413 auto presentation_frame
= GetOrAddPresentationFrame(render_frame_host_id
);
414 presentation_frame
->set_delegate_observer(observer
);
417 void PresentationFrameManager::RemoveDelegateObserver(
418 const RenderFrameHostId
& render_frame_host_id
) {
419 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
420 if (presentation_frame
) {
421 presentation_frame
->set_delegate_observer(nullptr);
422 presentation_frames_
.erase(render_frame_host_id
);
426 void PresentationFrameManager::Reset(
427 const RenderFrameHostId
& render_frame_host_id
) {
428 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
429 if (presentation_frame
)
430 presentation_frame
->Reset();
433 PresentationFrame
* PresentationFrameManager::GetOrAddPresentationFrame(
434 const RenderFrameHostId
& render_frame_host_id
) {
435 if (!presentation_frames_
.contains(render_frame_host_id
)) {
436 presentation_frames_
.add(
437 render_frame_host_id
,
438 scoped_ptr
<PresentationFrame
>(
439 new PresentationFrame(web_contents_
, router_
)));
441 return presentation_frames_
.get(render_frame_host_id
);
444 void PresentationFrameManager::SetMediaRouterForTest(MediaRouter
* router
) {
448 PresentationServiceDelegateImpl
*
449 PresentationServiceDelegateImpl::GetOrCreateForWebContents(
450 content::WebContents
* web_contents
) {
451 DCHECK(web_contents
);
452 // CreateForWebContents does nothing if the delegate instance already exists.
453 PresentationServiceDelegateImpl::CreateForWebContents(web_contents
);
454 return PresentationServiceDelegateImpl::FromWebContents(web_contents
);
457 PresentationServiceDelegateImpl::PresentationServiceDelegateImpl(
458 content::WebContents
* web_contents
)
459 : web_contents_(web_contents
),
460 router_(MediaRouterFactory::GetApiForBrowserContext(
461 web_contents_
->GetBrowserContext())),
462 frame_manager_(new PresentationFrameManager(web_contents
, router_
)),
463 weak_factory_(this) {
464 DCHECK(web_contents_
);
468 PresentationServiceDelegateImpl::~PresentationServiceDelegateImpl() {
471 void PresentationServiceDelegateImpl::AddObserver(int render_process_id
,
473 DelegateObserver
* observer
) {
475 frame_manager_
->AddDelegateObserver(
476 RenderFrameHostId(render_process_id
, render_frame_id
), observer
);
479 void PresentationServiceDelegateImpl::RemoveObserver(int render_process_id
,
480 int render_frame_id
) {
481 frame_manager_
->RemoveDelegateObserver(
482 RenderFrameHostId(render_process_id
, render_frame_id
));
485 bool PresentationServiceDelegateImpl::AddScreenAvailabilityListener(
486 int render_process_id
,
488 content::PresentationScreenAvailabilityListener
* listener
) {
490 return frame_manager_
->SetScreenAvailabilityListener(
491 RenderFrameHostId(render_process_id
, render_frame_id
), listener
);
494 void PresentationServiceDelegateImpl::RemoveScreenAvailabilityListener(
495 int render_process_id
,
497 content::PresentationScreenAvailabilityListener
* listener
) {
499 frame_manager_
->RemoveScreenAvailabilityListener(
500 RenderFrameHostId(render_process_id
, render_frame_id
), listener
);
503 void PresentationServiceDelegateImpl::Reset(int render_process_id
,
504 int render_frame_id
) {
505 RenderFrameHostId
render_frame_host_id(render_process_id
, render_frame_id
);
506 frame_manager_
->Reset(render_frame_host_id
);
507 if (IsMainFrame(render_process_id
, render_frame_id
))
508 UpdateDefaultMediaSourceAndNotifyObservers(MediaSource(), GURL());
511 void PresentationServiceDelegateImpl::SetDefaultPresentationUrl(
512 int render_process_id
,
514 const std::string
& default_presentation_url
) {
515 RenderFrameHostId
render_frame_host_id(render_process_id
, render_frame_id
);
516 frame_manager_
->SetDefaultPresentationUrl(render_frame_host_id
,
517 default_presentation_url
);
518 if (IsMainFrame(render_process_id
, render_frame_id
)) {
519 // This is the main frame, which means tab-level default presentation
520 // might have been updated.
521 MediaSource default_source
;
522 if (!default_presentation_url
.empty())
523 default_source
= MediaSourceForPresentationUrl(default_presentation_url
);
525 GURL default_frame_url
= GetLastCommittedURLForFrame(render_frame_host_id
);
526 UpdateDefaultMediaSourceAndNotifyObservers(default_source
,
531 bool PresentationServiceDelegateImpl::IsMainFrame(int render_process_id
,
532 int render_frame_id
) const {
533 RenderFrameHost
* main_frame
= web_contents_
->GetMainFrame();
535 GetRenderFrameHostId(main_frame
) ==
536 RenderFrameHostId(render_process_id
, render_frame_id
);
539 void PresentationServiceDelegateImpl::
540 UpdateDefaultMediaSourceAndNotifyObservers(
541 const MediaSource
& new_default_source
,
542 const GURL
& new_default_frame_url
) {
543 if (!new_default_source
.Equals(default_source_
) ||
544 new_default_frame_url
!= default_frame_url_
) {
545 default_source_
= new_default_source
;
546 default_frame_url_
= new_default_frame_url
;
548 DefaultMediaSourceObserver
, default_media_source_observers_
,
549 OnDefaultMediaSourceChanged(default_source_
, default_frame_url_
));
553 void PresentationServiceDelegateImpl::OnJoinRouteResponse(
554 int render_process_id
,
556 const content::PresentationSessionInfo
& session
,
557 const PresentationSessionSuccessCallback
& success_cb
,
558 const PresentationSessionErrorCallback
& error_cb
,
559 const MediaRoute
* route
,
560 const std::string
& presentation_id
,
561 const std::string
& error_text
) {
563 error_cb
.Run(content::PresentationError(
564 content::PRESENTATION_ERROR_NO_PRESENTATION_FOUND
, error_text
));
566 DVLOG(1) << "OnJoinRouteResponse: "
567 << "route_id: " << route
->media_route_id()
568 << ", presentation URL: " << session
.presentation_url
569 << ", presentation ID: " << session
.presentation_id
;
570 DCHECK_EQ(session
.presentation_id
, presentation_id
);
571 frame_manager_
->OnPresentationSessionStarted(
572 RenderFrameHostId(render_process_id
, render_frame_id
), false, session
,
573 route
->media_route_id());
574 success_cb
.Run(session
);
578 void PresentationServiceDelegateImpl::OnStartSessionSucceeded(
579 int render_process_id
,
581 const PresentationSessionSuccessCallback
& success_cb
,
582 const content::PresentationSessionInfo
& new_session
,
583 const MediaRoute::Id
& route_id
) {
584 DVLOG(1) << "OnStartSessionSucceeded: "
585 << "route_id: " << route_id
586 << ", presentation URL: " << new_session
.presentation_url
587 << ", presentation ID: " << new_session
.presentation_id
;
588 frame_manager_
->OnPresentationSessionStarted(
589 RenderFrameHostId(render_process_id
, render_frame_id
), false, new_session
,
591 success_cb
.Run(new_session
);
594 void PresentationServiceDelegateImpl::StartSession(
595 int render_process_id
,
597 const std::string
& presentation_url
,
598 const PresentationSessionSuccessCallback
& success_cb
,
599 const PresentationSessionErrorCallback
& error_cb
) {
600 if (presentation_url
.empty() || !IsValidPresentationUrl(presentation_url
)) {
601 error_cb
.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN
,
602 "Invalid presentation arguments."));
605 RenderFrameHostId
render_frame_host_id(render_process_id
, render_frame_id
);
607 scoped_ptr
<CreatePresentationSessionRequest
> context(
608 new CreatePresentationSessionRequest(
609 presentation_url
, GetLastCommittedURLForFrame(render_frame_host_id
),
610 base::Bind(&PresentationServiceDelegateImpl::OnStartSessionSucceeded
,
611 weak_factory_
.GetWeakPtr(), render_process_id
,
612 render_frame_id
, success_cb
),
614 MediaRouterDialogController
* controller
=
615 MediaRouterDialogController::GetOrCreateForWebContents(web_contents_
);
616 if (!controller
->ShowMediaRouterDialogForPresentation(context
.Pass())) {
617 LOG(ERROR
) << "Media router dialog already exists. Ignoring StartSession.";
618 error_cb
.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN
,
619 "Unable to create dialog."));
624 void PresentationServiceDelegateImpl::JoinSession(
625 int render_process_id
,
627 const std::string
& presentation_url
,
628 const std::string
& presentation_id
,
629 const PresentationSessionSuccessCallback
& success_cb
,
630 const PresentationSessionErrorCallback
& error_cb
) {
631 std::vector
<MediaRouteResponseCallback
> route_response_callbacks
;
632 route_response_callbacks
.push_back(base::Bind(
633 &PresentationServiceDelegateImpl::OnJoinRouteResponse
,
634 weak_factory_
.GetWeakPtr(), render_process_id
, render_frame_id
,
635 content::PresentationSessionInfo(presentation_url
, presentation_id
),
636 success_cb
, error_cb
));
638 MediaSourceForPresentationUrl(presentation_url
).id(), presentation_id
,
639 GetLastCommittedURLForFrame(
640 RenderFrameHostId(render_process_id
, render_frame_id
))
642 SessionTabHelper::IdForTab(web_contents_
), route_response_callbacks
);
645 void PresentationServiceDelegateImpl::CloseSession(
646 int render_process_id
,
648 const std::string
& presentation_id
) {
649 const MediaRoute::Id
& route_id
= frame_manager_
->GetRouteId(
650 RenderFrameHostId(render_process_id
, render_frame_id
), presentation_id
);
651 if (route_id
.empty()) {
652 DVLOG(1) << "No active route for: " << presentation_id
;
655 router_
->CloseRoute(route_id
);
658 void PresentationServiceDelegateImpl::ListenForSessionMessages(
659 int render_process_id
,
661 const content::PresentationSessionInfo
& session
,
662 const content::PresentationSessionMessageCallback
& message_cb
) {
663 frame_manager_
->ListenForSessionMessages(
664 RenderFrameHostId(render_process_id
, render_frame_id
), session
,
668 void PresentationServiceDelegateImpl::SendMessage(
669 int render_process_id
,
671 const content::PresentationSessionInfo
& session
,
672 scoped_ptr
<content::PresentationSessionMessage
> message
,
673 const SendMessageCallback
& send_message_cb
) {
674 const MediaRoute::Id
& route_id
= frame_manager_
->GetRouteId(
675 RenderFrameHostId(render_process_id
, render_frame_id
),
676 session
.presentation_id
);
677 if (route_id
.empty()) {
678 DVLOG(1) << "No active route for " << session
.presentation_id
;
679 send_message_cb
.Run(false);
683 if (message
->is_binary()) {
684 router_
->SendRouteBinaryMessage(route_id
, message
->data
.Pass(),
687 router_
->SendRouteMessage(route_id
, message
->message
, send_message_cb
);
691 void PresentationServiceDelegateImpl::ListenForSessionStateChange(
692 int render_process_id
,
694 const content::SessionStateChangedCallback
& state_changed_cb
) {
695 frame_manager_
->ListenForSessionStateChange(
696 RenderFrameHostId(render_process_id
, render_frame_id
), state_changed_cb
);
699 void PresentationServiceDelegateImpl::OnRouteResponse(
700 const MediaRoute
* route
,
701 const std::string
& presentation_id
,
702 const std::string
& error
) {
705 const MediaSource
& source
= route
->media_source();
706 DCHECK(!source
.Empty());
707 if (!default_source_
.Equals(source
))
709 RenderFrameHost
* main_frame
= web_contents_
->GetMainFrame();
712 RenderFrameHostId
render_frame_host_id(GetRenderFrameHostId(main_frame
));
713 frame_manager_
->OnPresentationSessionStarted(
714 render_frame_host_id
, true,
715 content::PresentationSessionInfo(PresentationUrlFromMediaSource(source
),
717 route
->media_route_id());
720 void PresentationServiceDelegateImpl::AddDefaultMediaSourceObserver(
721 DefaultMediaSourceObserver
* observer
) {
722 default_media_source_observers_
.AddObserver(observer
);
725 void PresentationServiceDelegateImpl::RemoveDefaultMediaSourceObserver(
726 DefaultMediaSourceObserver
* observer
) {
727 default_media_source_observers_
.RemoveObserver(observer
);
730 base::WeakPtr
<PresentationServiceDelegateImpl
>
731 PresentationServiceDelegateImpl::GetWeakPtr() {
732 return weak_factory_
.GetWeakPtr();
735 void PresentationServiceDelegateImpl::SetMediaRouterForTest(
736 MediaRouter
* router
) {
738 frame_manager_
->SetMediaRouterForTest(router
);
741 bool PresentationServiceDelegateImpl::HasScreenAvailabilityListenerForTest(
742 int render_process_id
,
744 const MediaSource::Id
& source_id
) const {
745 RenderFrameHostId
render_frame_host_id(render_process_id
, render_frame_id
);
746 return frame_manager_
->HasScreenAvailabilityListenerForTest(
747 render_frame_host_id
, source_id
);
750 } // namespace media_router