Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / media / router / presentation_service_delegate_impl.cc
blob16e7e5aaf497af2b28a96ec2f4b9bad88a160f03
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"
7 #include <string>
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 {
37 namespace {
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();
63 } // namespace
65 // Used by PresentationServiceDelegateImpl to manage
66 // listeners and default presentation info in a render frame.
67 // Its lifetime:
68 // * PresentationFrameManager AddDelegateObserver
69 // * Reset 0+ times.
70 // * PresentationFrameManager.RemoveDelegateObserver.
71 class PresentationFrame {
72 public:
73 PresentationFrame(content::WebContents* web_contents, MediaRouter* router);
74 ~PresentationFrame();
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);
89 void Reset();
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;
109 private:
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,
128 MediaRouter* router)
129 : web_contents_(web_contents),
130 router_(router),
131 delegate_observer_(nullptr) {
132 DCHECK(web_contents_);
133 DCHECK(router_);
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);
176 return route_ids;
179 bool PresentationFrame::SetScreenAvailabilityListener(
180 content::PresentationScreenAvailabilityListener* listener) {
181 if (sinks_observer_ && sinks_observer_->listener() == listener) {
182 return false;
184 MediaSource source(GetMediaSourceFromListener(listener));
185 sinks_observer_.reset(
186 new PresentationMediaSinksObserver(router_, listener, source));
187 return true;
190 bool PresentationFrame::RemoveScreenAvailabilityListener(
191 content::PresentationScreenAvailabilityListener* listener) {
192 if (sinks_observer_ && sinks_observer_->listener() == listener) {
193 sinks_observer_.reset();
194 return true;
196 return false;
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;
228 return;
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 {
246 public:
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;
290 private:
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,
306 MediaRouter* router)
307 : router_(router), web_contents_(web_contents) {
308 DCHECK(web_contents_);
309 DCHECK(router_);
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,
325 session, route_id);
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)
341 : "";
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) {
354 DCHECK(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) {
362 DCHECK(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 << ")";
401 return;
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) {
441 router_ = 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_);
461 DCHECK(router_);
464 PresentationServiceDelegateImpl::~PresentationServiceDelegateImpl() {
467 void PresentationServiceDelegateImpl::AddObserver(int render_process_id,
468 int render_frame_id,
469 DelegateObserver* observer) {
470 DCHECK(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,
483 int render_frame_id,
484 content::PresentationScreenAvailabilityListener* listener) {
485 DCHECK(listener);
486 return frame_manager_->SetScreenAvailabilityListener(
487 RenderFrameHostId(render_process_id, render_frame_id), listener);
490 void PresentationServiceDelegateImpl::RemoveScreenAvailabilityListener(
491 int render_process_id,
492 int render_frame_id,
493 content::PresentationScreenAvailabilityListener* listener) {
494 DCHECK(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,
509 int render_frame_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,
523 default_frame_url);
527 bool PresentationServiceDelegateImpl::IsMainFrame(int render_process_id,
528 int render_frame_id) const {
529 RenderFrameHost* main_frame = web_contents_->GetMainFrame();
530 return main_frame &&
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;
543 FOR_EACH_OBSERVER(
544 DefaultMediaSourceObserver, default_media_source_observers_,
545 OnDefaultMediaSourceChanged(default_source_, default_frame_url_));
549 void PresentationServiceDelegateImpl::OnJoinRouteResponse(
550 int render_process_id,
551 int render_frame_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) {
558 if (!route) {
559 error_cb.Run(content::PresentationError(
560 content::PRESENTATION_ERROR_NO_PRESENTATION_FOUND, error_text));
561 } else {
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,
576 int render_frame_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,
586 route_id);
587 success_cb.Run(new_session);
590 void PresentationServiceDelegateImpl::StartSession(
591 int render_process_id,
592 int render_frame_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."));
599 return;
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),
611 error_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."));
618 return;
622 void PresentationServiceDelegateImpl::JoinSession(
623 int render_process_id,
624 int render_frame_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));
635 router_->JoinRoute(
636 MediaSourceForPresentationUrl(presentation_url).id(), presentation_id,
637 GetLastCommittedURLForFrame(
638 RenderFrameHostId(render_process_id, render_frame_id))
639 .GetOrigin(),
640 SessionTabHelper::IdForTab(web_contents_), route_response_callbacks);
643 void PresentationServiceDelegateImpl::CloseSession(
644 int render_process_id,
645 int render_frame_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;
651 return;
653 router_->CloseRoute(route_id);
656 void PresentationServiceDelegateImpl::ListenForSessionMessages(
657 int render_process_id,
658 int render_frame_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,
663 message_cb);
666 void PresentationServiceDelegateImpl::SendMessage(
667 int render_process_id,
668 int render_frame_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);
678 return;
681 if (message->is_binary()) {
682 router_->SendRouteBinaryMessage(route_id, message->data.Pass(),
683 send_message_cb);
684 } else {
685 router_->SendRouteMessage(route_id, message->message, send_message_cb);
689 void PresentationServiceDelegateImpl::ListenForSessionStateChange(
690 int render_process_id,
691 int render_frame_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) {
701 if (!route)
702 return;
703 const MediaSource& source = route->media_source();
704 DCHECK(!source.Empty());
705 if (!default_source_.Equals(source))
706 return;
707 RenderFrameHost* main_frame = web_contents_->GetMainFrame();
708 if (!main_frame)
709 return;
710 RenderFrameHostId render_frame_host_id(GetRenderFrameHostId(main_frame));
711 frame_manager_->OnPresentationSessionStarted(
712 render_frame_host_id, true,
713 content::PresentationSessionInfo(PresentationUrlFromMediaSource(source),
714 presentation_id),
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) {
735 router_ = router;
736 frame_manager_->SetMediaRouterForTest(router);
739 bool PresentationServiceDelegateImpl::HasScreenAvailabilityListenerForTest(
740 int render_process_id,
741 int render_frame_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