Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / media / router / presentation_service_delegate_impl.cc
blobe03063d83228cd22368d63c42e78bebb6675992a
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();
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;
232 return;
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 {
250 public:
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;
294 private:
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,
310 MediaRouter* router)
311 : router_(router), web_contents_(web_contents) {
312 DCHECK(web_contents_);
313 DCHECK(router_);
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,
329 session, route_id);
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)
345 : "";
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) {
358 DCHECK(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) {
366 DCHECK(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 << ")";
405 return;
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) {
445 router_ = 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_);
465 DCHECK(router_);
468 PresentationServiceDelegateImpl::~PresentationServiceDelegateImpl() {
471 void PresentationServiceDelegateImpl::AddObserver(int render_process_id,
472 int render_frame_id,
473 DelegateObserver* observer) {
474 DCHECK(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,
487 int render_frame_id,
488 content::PresentationScreenAvailabilityListener* listener) {
489 DCHECK(listener);
490 return frame_manager_->SetScreenAvailabilityListener(
491 RenderFrameHostId(render_process_id, render_frame_id), listener);
494 void PresentationServiceDelegateImpl::RemoveScreenAvailabilityListener(
495 int render_process_id,
496 int render_frame_id,
497 content::PresentationScreenAvailabilityListener* listener) {
498 DCHECK(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,
513 int render_frame_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,
527 default_frame_url);
531 bool PresentationServiceDelegateImpl::IsMainFrame(int render_process_id,
532 int render_frame_id) const {
533 RenderFrameHost* main_frame = web_contents_->GetMainFrame();
534 return main_frame &&
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;
547 FOR_EACH_OBSERVER(
548 DefaultMediaSourceObserver, default_media_source_observers_,
549 OnDefaultMediaSourceChanged(default_source_, default_frame_url_));
553 void PresentationServiceDelegateImpl::OnJoinRouteResponse(
554 int render_process_id,
555 int render_frame_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) {
562 if (!route) {
563 error_cb.Run(content::PresentationError(
564 content::PRESENTATION_ERROR_NO_PRESENTATION_FOUND, error_text));
565 } else {
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,
580 int render_frame_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,
590 route_id);
591 success_cb.Run(new_session);
594 void PresentationServiceDelegateImpl::StartSession(
595 int render_process_id,
596 int render_frame_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."));
603 return;
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),
613 error_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."));
620 return;
624 void PresentationServiceDelegateImpl::JoinSession(
625 int render_process_id,
626 int render_frame_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));
637 router_->JoinRoute(
638 MediaSourceForPresentationUrl(presentation_url).id(), presentation_id,
639 GetLastCommittedURLForFrame(
640 RenderFrameHostId(render_process_id, render_frame_id))
641 .GetOrigin(),
642 SessionTabHelper::IdForTab(web_contents_), route_response_callbacks);
645 void PresentationServiceDelegateImpl::CloseSession(
646 int render_process_id,
647 int render_frame_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;
653 return;
655 router_->CloseRoute(route_id);
658 void PresentationServiceDelegateImpl::ListenForSessionMessages(
659 int render_process_id,
660 int render_frame_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,
665 message_cb);
668 void PresentationServiceDelegateImpl::SendMessage(
669 int render_process_id,
670 int render_frame_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);
680 return;
683 if (message->is_binary()) {
684 router_->SendRouteBinaryMessage(route_id, message->data.Pass(),
685 send_message_cb);
686 } else {
687 router_->SendRouteMessage(route_id, message->message, send_message_cb);
691 void PresentationServiceDelegateImpl::ListenForSessionStateChange(
692 int render_process_id,
693 int render_frame_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) {
703 if (!route)
704 return;
705 const MediaSource& source = route->media_source();
706 DCHECK(!source.Empty());
707 if (!default_source_.Equals(source))
708 return;
709 RenderFrameHost* main_frame = web_contents_->GetMainFrame();
710 if (!main_frame)
711 return;
712 RenderFrameHostId render_frame_host_id(GetRenderFrameHostId(main_frame));
713 frame_manager_->OnPresentationSessionStarted(
714 render_frame_host_id, true,
715 content::PresentationSessionInfo(PresentationUrlFromMediaSource(source),
716 presentation_id),
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) {
737 router_ = router;
738 frame_manager_->SetMediaRouterForTest(router);
741 bool PresentationServiceDelegateImpl::HasScreenAvailabilityListenerForTest(
742 int render_process_id,
743 int render_frame_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