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();
206 presentation_id_to_route_id_
.clear();
207 sinks_observer_
.reset();
208 default_presentation_url_
.clear();
209 if (session_state_observer_
)
210 session_state_observer_
->Reset();
211 session_messages_observers_
.clear();
214 void PresentationFrame::ListenForSessionStateChange(
215 const content::SessionStateChangedCallback
& state_changed_cb
) {
216 CHECK(!session_state_observer_
.get());
217 session_state_observer_
.reset(new PresentationSessionStateObserver(
218 state_changed_cb
, &route_id_to_presentation_
, router_
));
221 void PresentationFrame::ListenForSessionMessages(
222 const content::PresentationSessionInfo
& session
,
223 const content::PresentationSessionMessageCallback
& message_cb
) {
224 auto it
= presentation_id_to_route_id_
.find(session
.presentation_id
);
225 if (it
== presentation_id_to_route_id_
.end()) {
226 DVLOG(2) << "ListenForSessionMessages: no route for "
227 << session
.presentation_id
;
231 session_messages_observers_
.push_back(
232 new PresentationSessionMessagesObserver(message_cb
, it
->second
, router_
));
235 MediaSource
PresentationFrame::GetMediaSourceFromListener(
236 content::PresentationScreenAvailabilityListener
* listener
) const {
237 // If the default presentation URL is empty then fall back to tab mirroring.
238 std::string
presentation_url(listener
->GetPresentationUrl());
239 return presentation_url
.empty()
240 ? MediaSourceForTab(SessionTabHelper::IdForTab(web_contents_
))
241 : MediaSourceForPresentationUrl(presentation_url
);
244 // Used by PresentationServiceDelegateImpl to manage PresentationFrames.
245 class PresentationFrameManager
{
247 PresentationFrameManager(content::WebContents
* web_contents
,
248 MediaRouter
* router
);
249 ~PresentationFrameManager();
251 // Mirror corresponding APIs in PresentationServiceDelegateImpl.
252 bool SetScreenAvailabilityListener(
253 const RenderFrameHostId
& render_frame_host_id
,
254 content::PresentationScreenAvailabilityListener
* listener
);
255 bool RemoveScreenAvailabilityListener(
256 const RenderFrameHostId
& render_frame_host_id
,
257 content::PresentationScreenAvailabilityListener
* listener
);
258 void SetDefaultPresentationUrl(const RenderFrameHostId
& render_frame_host_id
,
259 const std::string
& default_presentation_url
);
260 void ListenForSessionStateChange(
261 const RenderFrameHostId
& render_frame_host_id
,
262 const content::SessionStateChangedCallback
& state_changed_cb
);
263 void ListenForSessionMessages(
264 const RenderFrameHostId
& render_frame_host_id
,
265 const content::PresentationSessionInfo
& session
,
266 const content::PresentationSessionMessageCallback
& message_cb
);
267 void AddDelegateObserver(const RenderFrameHostId
& render_frame_host_id
,
268 DelegateObserver
* observer
);
269 void RemoveDelegateObserver(const RenderFrameHostId
& render_frame_host_id
);
270 void Reset(const RenderFrameHostId
& render_frame_host_id
);
271 bool HasScreenAvailabilityListenerForTest(
272 const RenderFrameHostId
& render_frame_host_id
,
273 const MediaSource::Id
& source_id
) const;
274 void SetMediaRouterForTest(MediaRouter
* router
);
276 void OnPresentationSessionStarted(
277 const RenderFrameHostId
& render_frame_host_id
,
278 bool is_default_presentation
,
279 const content::PresentationSessionInfo
& session
,
280 const MediaRoute::Id
& route_id
);
282 void OnPresentationSessionClosed(
283 const RenderFrameHostId
& render_frame_host_id
,
284 const std::string
& presentation_id
);
285 const MediaRoute::Id
GetRouteId(const RenderFrameHostId
& render_frame_host_id
,
286 const std::string
& presentation_id
) const;
287 const std::vector
<MediaRoute::Id
> GetRouteIds(
288 const RenderFrameHostId
& render_frame_host_id
) const;
291 PresentationFrame
* GetOrAddPresentationFrame(
292 const RenderFrameHostId
& render_frame_host_id
);
294 // Maps a frame identifier to a PresentationFrame object for frames
295 // that are using presentation API.
296 base::ScopedPtrHashMap
<RenderFrameHostId
, scoped_ptr
<PresentationFrame
>>
297 presentation_frames_
;
299 // References to the owning WebContents, and the corresponding MediaRouter.
300 MediaRouter
* router_
;
301 content::WebContents
* web_contents_
;
304 PresentationFrameManager::PresentationFrameManager(
305 content::WebContents
* web_contents
,
307 : router_(router
), web_contents_(web_contents
) {
308 DCHECK(web_contents_
);
312 PresentationFrameManager::~PresentationFrameManager() {
313 for (auto& frame
: presentation_frames_
)
314 frame
.second
->OnPresentationServiceDelegateDestroyed();
317 void PresentationFrameManager::OnPresentationSessionStarted(
318 const RenderFrameHostId
& render_frame_host_id
,
319 bool is_default_presentation
,
320 const content::PresentationSessionInfo
& session
,
321 const MediaRoute::Id
& route_id
) {
322 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
323 if (presentation_frame
)
324 presentation_frame
->OnPresentationSessionStarted(is_default_presentation
,
328 void PresentationFrameManager::OnPresentationSessionClosed(
329 const RenderFrameHostId
& render_frame_host_id
,
330 const std::string
& presentation_id
) {
331 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
332 if (presentation_frame
)
333 presentation_frame
->OnPresentationSessionClosed(presentation_id
);
336 const MediaRoute::Id
PresentationFrameManager::GetRouteId(
337 const RenderFrameHostId
& render_frame_host_id
,
338 const std::string
& presentation_id
) const {
339 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
340 return presentation_frame
? presentation_frame
->GetRouteId(presentation_id
)
344 const std::vector
<MediaRoute::Id
> PresentationFrameManager::GetRouteIds(
345 const RenderFrameHostId
& render_frame_host_id
) const {
346 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
347 return presentation_frame
? presentation_frame
->GetRouteIds()
348 : std::vector
<MediaRoute::Id
>();
351 bool PresentationFrameManager::SetScreenAvailabilityListener(
352 const RenderFrameHostId
& render_frame_host_id
,
353 content::PresentationScreenAvailabilityListener
* listener
) {
355 auto presentation_frame
= GetOrAddPresentationFrame(render_frame_host_id
);
356 return presentation_frame
->SetScreenAvailabilityListener(listener
);
359 bool PresentationFrameManager::RemoveScreenAvailabilityListener(
360 const RenderFrameHostId
& render_frame_host_id
,
361 content::PresentationScreenAvailabilityListener
* listener
) {
363 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
364 return presentation_frame
&&
365 presentation_frame
->RemoveScreenAvailabilityListener(listener
);
368 bool PresentationFrameManager::HasScreenAvailabilityListenerForTest(
369 const RenderFrameHostId
& render_frame_host_id
,
370 const MediaSource::Id
& source_id
) const {
371 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
372 return presentation_frame
&&
373 presentation_frame
->HasScreenAvailabilityListenerForTest(source_id
);
376 void PresentationFrameManager::SetDefaultPresentationUrl(
377 const RenderFrameHostId
& render_frame_host_id
,
378 const std::string
& default_presentation_url
) {
379 auto presentation_frame
= GetOrAddPresentationFrame(render_frame_host_id
);
380 presentation_frame
->set_default_presentation_url(default_presentation_url
);
383 void PresentationFrameManager::ListenForSessionStateChange(
384 const RenderFrameHostId
& render_frame_host_id
,
385 const content::SessionStateChangedCallback
& state_changed_cb
) {
386 PresentationFrame
* presentation_frame
=
387 GetOrAddPresentationFrame(render_frame_host_id
);
388 presentation_frame
->ListenForSessionStateChange(state_changed_cb
);
391 void PresentationFrameManager::ListenForSessionMessages(
392 const RenderFrameHostId
& render_frame_host_id
,
393 const content::PresentationSessionInfo
& session
,
394 const content::PresentationSessionMessageCallback
& message_cb
) {
395 PresentationFrame
* presentation_frame
=
396 presentation_frames_
.get(render_frame_host_id
);
397 if (!presentation_frame
) {
398 DVLOG(2) << "ListenForSessionMessages: PresentationFrame does not exist "
399 << "for: (" << render_frame_host_id
.first
<< ", "
400 << render_frame_host_id
.second
<< ")";
403 presentation_frame
->ListenForSessionMessages(session
, message_cb
);
406 void PresentationFrameManager::AddDelegateObserver(
407 const RenderFrameHostId
& render_frame_host_id
,
408 DelegateObserver
* observer
) {
409 auto presentation_frame
= GetOrAddPresentationFrame(render_frame_host_id
);
410 presentation_frame
->set_delegate_observer(observer
);
413 void PresentationFrameManager::RemoveDelegateObserver(
414 const RenderFrameHostId
& render_frame_host_id
) {
415 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
416 if (presentation_frame
) {
417 presentation_frame
->set_delegate_observer(nullptr);
418 presentation_frames_
.erase(render_frame_host_id
);
422 void PresentationFrameManager::Reset(
423 const RenderFrameHostId
& render_frame_host_id
) {
424 auto presentation_frame
= presentation_frames_
.get(render_frame_host_id
);
425 if (presentation_frame
)
426 presentation_frame
->Reset();
429 PresentationFrame
* PresentationFrameManager::GetOrAddPresentationFrame(
430 const RenderFrameHostId
& render_frame_host_id
) {
431 if (!presentation_frames_
.contains(render_frame_host_id
)) {
432 presentation_frames_
.add(
433 render_frame_host_id
,
434 scoped_ptr
<PresentationFrame
>(
435 new PresentationFrame(web_contents_
, router_
)));
437 return presentation_frames_
.get(render_frame_host_id
);
440 void PresentationFrameManager::SetMediaRouterForTest(MediaRouter
* router
) {
444 PresentationServiceDelegateImpl
*
445 PresentationServiceDelegateImpl::GetOrCreateForWebContents(
446 content::WebContents
* web_contents
) {
447 DCHECK(web_contents
);
448 // CreateForWebContents does nothing if the delegate instance already exists.
449 PresentationServiceDelegateImpl::CreateForWebContents(web_contents
);
450 return PresentationServiceDelegateImpl::FromWebContents(web_contents
);
453 PresentationServiceDelegateImpl::PresentationServiceDelegateImpl(
454 content::WebContents
* web_contents
)
455 : web_contents_(web_contents
),
456 router_(MediaRouterFactory::GetApiForBrowserContext(
457 web_contents_
->GetBrowserContext())),
458 frame_manager_(new PresentationFrameManager(web_contents
, router_
)),
459 weak_factory_(this) {
460 DCHECK(web_contents_
);
464 PresentationServiceDelegateImpl::~PresentationServiceDelegateImpl() {
467 void PresentationServiceDelegateImpl::AddObserver(int render_process_id
,
469 DelegateObserver
* observer
) {
471 frame_manager_
->AddDelegateObserver(
472 RenderFrameHostId(render_process_id
, render_frame_id
), observer
);
475 void PresentationServiceDelegateImpl::RemoveObserver(int render_process_id
,
476 int render_frame_id
) {
477 frame_manager_
->RemoveDelegateObserver(
478 RenderFrameHostId(render_process_id
, render_frame_id
));
481 bool PresentationServiceDelegateImpl::AddScreenAvailabilityListener(
482 int render_process_id
,
484 content::PresentationScreenAvailabilityListener
* listener
) {
486 return frame_manager_
->SetScreenAvailabilityListener(
487 RenderFrameHostId(render_process_id
, render_frame_id
), listener
);
490 void PresentationServiceDelegateImpl::RemoveScreenAvailabilityListener(
491 int render_process_id
,
493 content::PresentationScreenAvailabilityListener
* listener
) {
495 frame_manager_
->RemoveScreenAvailabilityListener(
496 RenderFrameHostId(render_process_id
, render_frame_id
), listener
);
499 void PresentationServiceDelegateImpl::Reset(int render_process_id
,
500 int render_frame_id
) {
501 RenderFrameHostId
render_frame_host_id(render_process_id
, render_frame_id
);
502 frame_manager_
->Reset(render_frame_host_id
);
503 if (IsMainFrame(render_process_id
, render_frame_id
))
504 UpdateDefaultMediaSourceAndNotifyObservers(MediaSource(), GURL());
507 void PresentationServiceDelegateImpl::SetDefaultPresentationUrl(
508 int render_process_id
,
510 const std::string
& default_presentation_url
) {
511 RenderFrameHostId
render_frame_host_id(render_process_id
, render_frame_id
);
512 frame_manager_
->SetDefaultPresentationUrl(render_frame_host_id
,
513 default_presentation_url
);
514 if (IsMainFrame(render_process_id
, render_frame_id
)) {
515 // This is the main frame, which means tab-level default presentation
516 // might have been updated.
517 MediaSource default_source
;
518 if (!default_presentation_url
.empty())
519 default_source
= MediaSourceForPresentationUrl(default_presentation_url
);
521 GURL default_frame_url
= GetLastCommittedURLForFrame(render_frame_host_id
);
522 UpdateDefaultMediaSourceAndNotifyObservers(default_source
,
527 bool PresentationServiceDelegateImpl::IsMainFrame(int render_process_id
,
528 int render_frame_id
) const {
529 RenderFrameHost
* main_frame
= web_contents_
->GetMainFrame();
531 GetRenderFrameHostId(main_frame
) ==
532 RenderFrameHostId(render_process_id
, render_frame_id
);
535 void PresentationServiceDelegateImpl::
536 UpdateDefaultMediaSourceAndNotifyObservers(
537 const MediaSource
& new_default_source
,
538 const GURL
& new_default_frame_url
) {
539 if (!new_default_source
.Equals(default_source_
) ||
540 new_default_frame_url
!= default_frame_url_
) {
541 default_source_
= new_default_source
;
542 default_frame_url_
= new_default_frame_url
;
544 DefaultMediaSourceObserver
, default_media_source_observers_
,
545 OnDefaultMediaSourceChanged(default_source_
, default_frame_url_
));
549 void PresentationServiceDelegateImpl::OnJoinRouteResponse(
550 int render_process_id
,
552 const content::PresentationSessionInfo
& session
,
553 const PresentationSessionSuccessCallback
& success_cb
,
554 const PresentationSessionErrorCallback
& error_cb
,
555 const MediaRoute
* route
,
556 const std::string
& presentation_id
,
557 const std::string
& error_text
) {
559 error_cb
.Run(content::PresentationError(
560 content::PRESENTATION_ERROR_NO_PRESENTATION_FOUND
, error_text
));
562 DVLOG(1) << "OnJoinRouteResponse: "
563 << "route_id: " << route
->media_route_id()
564 << ", presentation URL: " << session
.presentation_url
565 << ", presentation ID: " << session
.presentation_id
;
566 DCHECK_EQ(session
.presentation_id
, presentation_id
);
567 frame_manager_
->OnPresentationSessionStarted(
568 RenderFrameHostId(render_process_id
, render_frame_id
), false, session
,
569 route
->media_route_id());
570 success_cb
.Run(session
);
574 void PresentationServiceDelegateImpl::OnStartSessionSucceeded(
575 int render_process_id
,
577 const PresentationSessionSuccessCallback
& success_cb
,
578 const content::PresentationSessionInfo
& new_session
,
579 const MediaRoute::Id
& route_id
) {
580 DVLOG(1) << "OnStartSessionSucceeded: "
581 << "route_id: " << route_id
582 << ", presentation URL: " << new_session
.presentation_url
583 << ", presentation ID: " << new_session
.presentation_id
;
584 frame_manager_
->OnPresentationSessionStarted(
585 RenderFrameHostId(render_process_id
, render_frame_id
), false, new_session
,
587 success_cb
.Run(new_session
);
590 void PresentationServiceDelegateImpl::StartSession(
591 int render_process_id
,
593 const std::string
& presentation_url
,
594 const PresentationSessionSuccessCallback
& success_cb
,
595 const PresentationSessionErrorCallback
& error_cb
) {
596 if (presentation_url
.empty() || !IsValidPresentationUrl(presentation_url
)) {
597 error_cb
.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN
,
598 "Invalid presentation arguments."));
601 RenderFrameHostId
render_frame_host_id(render_process_id
, render_frame_id
);
602 const std::string presentation_id
= base::GenerateGUID();
604 scoped_ptr
<CreatePresentationSessionRequest
> context(
605 new CreatePresentationSessionRequest(
606 presentation_url
, presentation_id
,
607 GetLastCommittedURLForFrame(render_frame_host_id
),
608 base::Bind(&PresentationServiceDelegateImpl::OnStartSessionSucceeded
,
609 weak_factory_
.GetWeakPtr(), render_process_id
,
610 render_frame_id
, success_cb
),
612 MediaRouterDialogController
* controller
=
613 MediaRouterDialogController::GetOrCreateForWebContents(web_contents_
);
614 if (!controller
->ShowMediaRouterDialogForPresentation(context
.Pass())) {
615 LOG(ERROR
) << "Media router dialog already exists. Ignoring StartSession.";
616 error_cb
.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN
,
617 "Unable to create dialog."));
622 void PresentationServiceDelegateImpl::JoinSession(
623 int render_process_id
,
625 const std::string
& presentation_url
,
626 const std::string
& presentation_id
,
627 const PresentationSessionSuccessCallback
& success_cb
,
628 const PresentationSessionErrorCallback
& error_cb
) {
629 std::vector
<MediaRouteResponseCallback
> route_response_callbacks
;
630 route_response_callbacks
.push_back(base::Bind(
631 &PresentationServiceDelegateImpl::OnJoinRouteResponse
,
632 weak_factory_
.GetWeakPtr(), render_process_id
, render_frame_id
,
633 content::PresentationSessionInfo(presentation_url
, presentation_id
),
634 success_cb
, error_cb
));
636 MediaSourceForPresentationUrl(presentation_url
).id(), presentation_id
,
637 GetLastCommittedURLForFrame(
638 RenderFrameHostId(render_process_id
, render_frame_id
))
640 SessionTabHelper::IdForTab(web_contents_
), route_response_callbacks
);
643 void PresentationServiceDelegateImpl::CloseSession(
644 int render_process_id
,
646 const std::string
& presentation_id
) {
647 const MediaRoute::Id
& route_id
= frame_manager_
->GetRouteId(
648 RenderFrameHostId(render_process_id
, render_frame_id
), presentation_id
);
649 if (route_id
.empty()) {
650 DVLOG(1) << "No active route for: " << presentation_id
;
653 router_
->CloseRoute(route_id
);
656 void PresentationServiceDelegateImpl::ListenForSessionMessages(
657 int render_process_id
,
659 const content::PresentationSessionInfo
& session
,
660 const content::PresentationSessionMessageCallback
& message_cb
) {
661 frame_manager_
->ListenForSessionMessages(
662 RenderFrameHostId(render_process_id
, render_frame_id
), session
,
666 void PresentationServiceDelegateImpl::SendMessage(
667 int render_process_id
,
669 const content::PresentationSessionInfo
& session
,
670 scoped_ptr
<content::PresentationSessionMessage
> message
,
671 const SendMessageCallback
& send_message_cb
) {
672 const MediaRoute::Id
& route_id
= frame_manager_
->GetRouteId(
673 RenderFrameHostId(render_process_id
, render_frame_id
),
674 session
.presentation_id
);
675 if (route_id
.empty()) {
676 DVLOG(1) << "No active route for " << session
.presentation_id
;
677 send_message_cb
.Run(false);
681 if (message
->is_binary()) {
682 router_
->SendRouteBinaryMessage(route_id
, message
->data
.Pass(),
685 router_
->SendRouteMessage(route_id
, message
->message
, send_message_cb
);
689 void PresentationServiceDelegateImpl::ListenForSessionStateChange(
690 int render_process_id
,
692 const content::SessionStateChangedCallback
& state_changed_cb
) {
693 frame_manager_
->ListenForSessionStateChange(
694 RenderFrameHostId(render_process_id
, render_frame_id
), state_changed_cb
);
697 void PresentationServiceDelegateImpl::OnRouteResponse(
698 const MediaRoute
* route
,
699 const std::string
& presentation_id
,
700 const std::string
& error
) {
703 const MediaSource
& source
= route
->media_source();
704 DCHECK(!source
.Empty());
705 if (!default_source_
.Equals(source
))
707 RenderFrameHost
* main_frame
= web_contents_
->GetMainFrame();
710 RenderFrameHostId
render_frame_host_id(GetRenderFrameHostId(main_frame
));
711 frame_manager_
->OnPresentationSessionStarted(
712 render_frame_host_id
, true,
713 content::PresentationSessionInfo(PresentationUrlFromMediaSource(source
),
715 route
->media_route_id());
718 void PresentationServiceDelegateImpl::AddDefaultMediaSourceObserver(
719 DefaultMediaSourceObserver
* observer
) {
720 default_media_source_observers_
.AddObserver(observer
);
723 void PresentationServiceDelegateImpl::RemoveDefaultMediaSourceObserver(
724 DefaultMediaSourceObserver
* observer
) {
725 default_media_source_observers_
.RemoveObserver(observer
);
728 base::WeakPtr
<PresentationServiceDelegateImpl
>
729 PresentationServiceDelegateImpl::GetWeakPtr() {
730 return weak_factory_
.GetWeakPtr();
733 void PresentationServiceDelegateImpl::SetMediaRouterForTest(
734 MediaRouter
* router
) {
736 frame_manager_
->SetMediaRouterForTest(router
);
739 bool PresentationServiceDelegateImpl::HasScreenAvailabilityListenerForTest(
740 int render_process_id
,
742 const MediaSource::Id
& source_id
) const {
743 RenderFrameHostId
render_frame_host_id(render_process_id
, render_frame_id
);
744 return frame_manager_
->HasScreenAvailabilityListenerForTest(
745 render_frame_host_id
, source_id
);
748 } // namespace media_router