Index: chrome/browser/media/router/presentation_service_delegate_impl.cc |
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation_service_delegate_impl.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..21252920bee36e97f5978523227e932a089e7101 |
--- /dev/null |
+++ b/chrome/browser/media/router/presentation_service_delegate_impl.cc |
@@ -0,0 +1,516 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/media/router/presentation_service_delegate_impl.h" |
+ |
+#include <string> |
+ |
+#include "base/containers/scoped_ptr_hash_map.h" |
+#include "base/guid.h" |
+#include "base/strings/string_util.h" |
+#include "base/strings/stringprintf.h" |
+#include "chrome/browser/media/router/create_session_request.h" |
+#include "chrome/browser/media/router/media_route.h" |
+#include "chrome/browser/media/router/media_router.h" |
+#include "chrome/browser/media/router/media_router_mojo_impl.h" |
+#include "chrome/browser/media/router/media_router_mojo_impl_factory.h" |
+#include "chrome/browser/media/router/media_sink.h" |
+#include "chrome/browser/media/router/media_source_helper.h" |
+#include "chrome/browser/media/router/presentation_media_sinks_observer.h" |
+#include "chrome/browser/sessions/session_tab_helper.h" |
+#include "content/public/browser/presentation_screen_availability_listener.h" |
+#include "content/public/browser/presentation_session.h" |
+#include "content/public/browser/render_frame_host.h" |
+#include "content/public/browser/render_process_host.h" |
+ |
+DEFINE_WEB_CONTENTS_USER_DATA_KEY( |
+ media_router::PresentationServiceDelegateImpl); |
+ |
+using content::RenderFrameHost; |
+ |
+namespace media_router { |
+ |
+using RenderFrameHostId = std::pair<int, int>; |
+ |
+namespace { |
+ |
+using DelegateObserver = content::PresentationServiceDelegate::Observer; |
+ |
+// Returns the unique identifier for the supplied RenderViewHost. |
+RenderFrameHostId GetRenderFrameHostId(RenderFrameHost* render_view_host) { |
+ int render_process_id = render_view_host->GetProcess()->GetID(); |
+ int render_frame_id = render_view_host->GetRoutingID(); |
+ return RenderFrameHostId(render_process_id, render_frame_id); |
+} |
+ |
+std::string GetDisplayNameForFrame(RenderFrameHostId render_frame_host_id) { |
+ RenderFrameHost* render_view_host = RenderFrameHost::FromID( |
+ render_frame_host_id.first, render_frame_host_id.second); |
+ std::string host = render_view_host->GetLastCommittedURL().host(); |
+ if (StartsWithASCII(host, "www.", false)) |
+ host = host.substr(4); |
+ return host; |
+} |
+ |
+} // namespace |
+ |
+// Used by PresentationServiceDelegateImpl to manage |
+// listeners and default presentation info in a render frame. |
+// Its lifetime: |
+// * PresentationFrameManager AddDelegateObserver |
+// * Reset 0+ times. |
+// * PresentationFrameManager.RemoveDelegateObserver. |
+class PresentationFrame { |
+ public: |
+ PresentationFrame(content::WebContents* web_contents, MediaRouter* router); |
+ ~PresentationFrame(); |
+ |
+ // Mirror corresponding APIs in PresentationServiceDelegateImpl. |
+ bool SetScreenAvailabilityListener( |
+ content::PresentationScreenAvailabilityListener* listener); |
+ bool RemoveScreenAvailabilityListener( |
+ content::PresentationScreenAvailabilityListener* listener); |
+ bool HasScreenAvailabilityListenerForTest( |
+ const MediaSourceId& source_id) const; |
+ void SetDefaultPresentationInfo(const std::string& default_presentation_url, |
+ const std::string& default_presentation_id); |
+ std::string GetDefaultPresentationId() const; |
+ void Reset(); |
+ |
+ void OnDefaultPresentationStarted( |
+ const content::PresentationSessionInfo& session) const; |
+ void OnPresentationServiceDelegateDestroyed() const; |
+ |
+ void set_delegate_observer(DelegateObserver* observer) { |
+ delegate_observer_ = observer; |
+ } |
+ |
+ private: |
+ MediaSource GetMediaSourceFromListener( |
+ content::PresentationScreenAvailabilityListener* listener) const; |
+ |
+ scoped_ptr<content::PresentationSessionInfo> default_presentation_info_; |
+ scoped_ptr<PresentationMediaSinksObserver> sinks_observer_; |
+ |
+ // References to the owning WebContents, and the corresponding MediaRouter. |
+ const content::WebContents* web_contents_; |
+ MediaRouter* router_; |
+ |
+ DelegateObserver* delegate_observer_; |
+}; |
+ |
+PresentationFrame::PresentationFrame(content::WebContents* web_contents, |
+ MediaRouter* router) |
+ : web_contents_(web_contents), |
+ router_(router), |
+ delegate_observer_(nullptr) { |
+ DCHECK(web_contents_); |
+ DCHECK(router_); |
+} |
+ |
+PresentationFrame::~PresentationFrame() { |
+} |
+ |
+void PresentationFrame::OnPresentationServiceDelegateDestroyed() const { |
+ if (delegate_observer_) |
+ delegate_observer_->OnDelegateDestroyed(); |
+} |
+ |
+void PresentationFrame::OnDefaultPresentationStarted( |
+ const content::PresentationSessionInfo& session) const { |
+ if (delegate_observer_) |
+ delegate_observer_->OnDefaultPresentationStarted(session); |
+} |
+ |
+bool PresentationFrame::SetScreenAvailabilityListener( |
+ content::PresentationScreenAvailabilityListener* listener) { |
+ if (sinks_observer_ && sinks_observer_->listener() == listener) { |
+ return false; |
+ } |
+ MediaSource source(GetMediaSourceFromListener(listener)); |
+ sinks_observer_.reset( |
+ new PresentationMediaSinksObserver(router_, listener, source)); |
+ return true; |
+} |
+ |
+bool PresentationFrame::RemoveScreenAvailabilityListener( |
+ content::PresentationScreenAvailabilityListener* listener) { |
+ if (sinks_observer_ && sinks_observer_->listener() == listener) { |
+ sinks_observer_.reset(); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+bool PresentationFrame::HasScreenAvailabilityListenerForTest( |
+ const MediaSourceId& source_id) const { |
+ return sinks_observer_ && sinks_observer_->source().id() == source_id; |
+} |
+ |
+void PresentationFrame::Reset() { |
+ sinks_observer_.reset(); |
+ default_presentation_info_.reset(); |
+} |
+ |
+void PresentationFrame::SetDefaultPresentationInfo( |
+ const std::string& default_presentation_url, |
+ const std::string& default_presentation_id) { |
+ if (default_presentation_url.empty() && default_presentation_id.empty()) { |
+ default_presentation_info_.reset(); |
+ } else { |
+ default_presentation_info_.reset(new content::PresentationSessionInfo( |
+ default_presentation_url, default_presentation_id)); |
+ } |
+} |
+ |
+std::string PresentationFrame::GetDefaultPresentationId() const { |
+ return default_presentation_info_ |
+ ? default_presentation_info_->presentation_id |
+ : ""; |
+} |
+ |
+MediaSource PresentationFrame::GetMediaSourceFromListener( |
+ content::PresentationScreenAvailabilityListener* listener) const { |
+ // If the default presentation URL is empty then fall back to tab mirroring. |
+ std::string presentation_url(listener->GetPresentationUrl()); |
+ return presentation_url.empty() |
+ ? MediaSourceForTab(SessionTabHelper::IdForTab(web_contents_)) |
+ : MediaSourceForPresentationUrl(presentation_url); |
+} |
+ |
+// Used by PresentationServiceDelegateImpl to manage PresentationFrames. |
+class PresentationFrameManager { |
+ public: |
+ PresentationFrameManager(content::WebContents* web_contents, |
+ MediaRouter* router); |
+ ~PresentationFrameManager(); |
+ |
+ // Mirror corresponding APIs in PresentationServiceDelegateImpl. |
+ bool SetScreenAvailabilityListener( |
+ const RenderFrameHostId& render_frame_host_id, |
+ content::PresentationScreenAvailabilityListener* listener); |
+ bool RemoveScreenAvailabilityListener( |
+ const RenderFrameHostId& render_frame_host_id, |
+ content::PresentationScreenAvailabilityListener* listener); |
+ void SetDefaultPresentationInfo(const RenderFrameHostId& render_frame_host_id, |
+ const std::string& default_presentation_url, |
+ const std::string& default_presentation_id); |
+ void AddDelegateObserver(const RenderFrameHostId& render_frame_host_id, |
+ DelegateObserver* observer); |
+ void RemoveDelegateObserver(const RenderFrameHostId& render_frame_host_id); |
+ void Reset(const RenderFrameHostId& render_frame_host_id); |
+ bool HasScreenAvailabilityListenerForTest( |
+ const RenderFrameHostId& render_frame_host_id, |
+ const MediaSourceId& source_id) const; |
+ void SetMediaRouterForTest(MediaRouter* router); |
+ |
+ // Returns default presentation ID, or empty string if no default |
+ // presentation ID is set in the frame. |
+ std::string GetDefaultPresentationId( |
+ const RenderFrameHostId& render_frame_host_id) const; |
+ |
+ void OnDefaultPresentationStarted( |
+ const RenderFrameHostId& render_frame_host_id, |
+ const content::PresentationSessionInfo& session) const; |
+ |
+ private: |
+ PresentationFrame* GetOrAddPresentationFrame( |
+ const RenderFrameHostId& render_frame_host_id); |
+ |
+ // Maps a frame identifier to a PresentationFrame object for frames |
+ // that are using presentation API. |
+ base::ScopedPtrHashMap<RenderFrameHostId, scoped_ptr<PresentationFrame>> |
+ presentation_frames_; |
+ |
+ // References to the owning WebContents, and the corresponding MediaRouter. |
+ MediaRouter* router_; |
+ content::WebContents* web_contents_; |
+}; |
+ |
+PresentationFrameManager::PresentationFrameManager( |
+ content::WebContents* web_contents, |
+ MediaRouter* router) |
+ : router_(router), web_contents_(web_contents) { |
+ DCHECK(web_contents_); |
+ DCHECK(router_); |
+} |
+ |
+PresentationFrameManager::~PresentationFrameManager() { |
+ for (auto& frame : presentation_frames_) |
+ frame.second->OnPresentationServiceDelegateDestroyed(); |
+} |
+ |
+void PresentationFrameManager::OnDefaultPresentationStarted( |
+ const RenderFrameHostId& render_frame_host_id, |
+ const content::PresentationSessionInfo& session) const { |
+ auto presentation_frame = presentation_frames_.get(render_frame_host_id); |
+ if (presentation_frame) |
+ presentation_frame->OnDefaultPresentationStarted(session); |
+} |
+ |
+bool PresentationFrameManager::SetScreenAvailabilityListener( |
+ const RenderFrameHostId& render_frame_host_id, |
+ content::PresentationScreenAvailabilityListener* listener) { |
+ DCHECK(listener); |
+ auto presentation_frame = GetOrAddPresentationFrame(render_frame_host_id); |
+ return presentation_frame->SetScreenAvailabilityListener(listener); |
+} |
+ |
+bool PresentationFrameManager::RemoveScreenAvailabilityListener( |
+ const RenderFrameHostId& render_frame_host_id, |
+ content::PresentationScreenAvailabilityListener* listener) { |
+ DCHECK(listener); |
+ auto presentation_frame = presentation_frames_.get(render_frame_host_id); |
+ return presentation_frame && |
+ presentation_frame->RemoveScreenAvailabilityListener(listener); |
+} |
+ |
+bool PresentationFrameManager::HasScreenAvailabilityListenerForTest( |
+ const RenderFrameHostId& render_frame_host_id, |
+ const MediaSourceId& source_id) const { |
+ auto presentation_frame = presentation_frames_.get(render_frame_host_id); |
+ return presentation_frame && |
+ presentation_frame->HasScreenAvailabilityListenerForTest(source_id); |
+} |
+ |
+void PresentationFrameManager::SetDefaultPresentationInfo( |
+ const RenderFrameHostId& render_frame_host_id, |
+ const std::string& default_presentation_url, |
+ const std::string& default_presentation_id) { |
+ auto presentation_frame = GetOrAddPresentationFrame(render_frame_host_id); |
+ presentation_frame->SetDefaultPresentationInfo(default_presentation_url, |
+ default_presentation_id); |
+} |
+ |
+std::string PresentationFrameManager::GetDefaultPresentationId( |
+ const RenderFrameHostId& render_frame_host_id) const { |
+ auto presentation_frame = presentation_frames_.get(render_frame_host_id); |
+ return presentation_frame ? presentation_frame->GetDefaultPresentationId() |
+ : ""; |
+} |
+ |
+void PresentationFrameManager::AddDelegateObserver( |
+ const RenderFrameHostId& render_frame_host_id, |
+ DelegateObserver* observer) { |
+ auto presentation_frame = GetOrAddPresentationFrame(render_frame_host_id); |
+ presentation_frame->set_delegate_observer(observer); |
+} |
+ |
+void PresentationFrameManager::RemoveDelegateObserver( |
+ const RenderFrameHostId& render_frame_host_id) { |
+ auto presentation_frame = presentation_frames_.get(render_frame_host_id); |
+ if (presentation_frame) { |
+ presentation_frame->set_delegate_observer(nullptr); |
+ presentation_frames_.erase(render_frame_host_id); |
+ } |
+} |
+ |
+void PresentationFrameManager::Reset( |
+ const RenderFrameHostId& render_frame_host_id) { |
+ auto presentation_frame = presentation_frames_.get(render_frame_host_id); |
+ if (presentation_frame) |
+ presentation_frame->Reset(); |
+} |
+ |
+PresentationFrame* PresentationFrameManager::GetOrAddPresentationFrame( |
+ const RenderFrameHostId& render_frame_host_id) { |
+ if (!presentation_frames_.contains(render_frame_host_id)) { |
+ presentation_frames_.add( |
+ render_frame_host_id, |
+ scoped_ptr<PresentationFrame>( |
+ new PresentationFrame(web_contents_, router_))); |
+ } |
+ return presentation_frames_.get(render_frame_host_id); |
+} |
+ |
+void PresentationFrameManager::SetMediaRouterForTest(MediaRouter* router) { |
+ router_ = router; |
+} |
+ |
+PresentationServiceDelegateImpl::PresentationServiceDelegateImpl( |
+ content::WebContents* web_contents) |
+ : web_contents_(web_contents), |
+ router_(MediaRouterMojoImplFactory::GetApiForBrowserContext( |
+ web_contents_->GetBrowserContext())), |
+ frame_manager_(new PresentationFrameManager(web_contents, router_)), |
+ weak_factory_(this) { |
+ DCHECK(web_contents_); |
+ DCHECK(router_); |
+} |
+ |
+PresentationServiceDelegateImpl::~PresentationServiceDelegateImpl() { |
+} |
+ |
+void PresentationServiceDelegateImpl::AddObserver(int render_process_id, |
+ int render_frame_id, |
+ DelegateObserver* observer) { |
+ DCHECK(observer); |
+ frame_manager_->AddDelegateObserver( |
+ RenderFrameHostId(render_process_id, render_frame_id), observer); |
+} |
+ |
+void PresentationServiceDelegateImpl::RemoveObserver(int render_process_id, |
+ int render_frame_id) { |
+ frame_manager_->RemoveDelegateObserver( |
+ RenderFrameHostId(render_process_id, render_frame_id)); |
+} |
+ |
+bool PresentationServiceDelegateImpl::AddScreenAvailabilityListener( |
+ int render_process_id, |
+ int render_frame_id, |
+ content::PresentationScreenAvailabilityListener* listener) { |
+ DCHECK(listener); |
+ return frame_manager_->SetScreenAvailabilityListener( |
+ RenderFrameHostId(render_process_id, render_frame_id), listener); |
+} |
+ |
+void PresentationServiceDelegateImpl::RemoveScreenAvailabilityListener( |
+ int render_process_id, |
+ int render_frame_id, |
+ content::PresentationScreenAvailabilityListener* listener) { |
+ DCHECK(listener); |
+ frame_manager_->RemoveScreenAvailabilityListener( |
+ RenderFrameHostId(render_process_id, render_frame_id), listener); |
+} |
+ |
+void PresentationServiceDelegateImpl::Reset(int render_process_id, |
+ int render_frame_id) { |
+ RenderFrameHostId render_frame_host_id(render_process_id, render_frame_id); |
+ frame_manager_->Reset(render_frame_host_id); |
+ if (IsMainFrame(render_process_id, render_frame_id)) |
+ UpdateDefaultMediaSourceAndNotifyObservers(MediaSource(), std::string()); |
+} |
+ |
+void PresentationServiceDelegateImpl::SetDefaultPresentationUrl( |
+ int render_process_id, |
+ int render_frame_id, |
+ const std::string& default_presentation_url, |
+ const std::string& default_presentation_id) { |
+ RenderFrameHostId render_frame_host_id(render_process_id, render_frame_id); |
+ frame_manager_->SetDefaultPresentationInfo( |
+ render_frame_host_id, default_presentation_url, default_presentation_id); |
+ if (IsMainFrame(render_process_id, render_frame_id)) { |
+ // This is the main frame, which means tab-level default presentation |
+ // might have been updated. |
+ MediaSource default_source; |
+ if (!default_presentation_url.empty()) |
+ default_source = MediaSourceForPresentationUrl(default_presentation_url); |
+ |
+ std::string default_frame_display_name( |
+ GetDisplayNameForFrame(render_frame_host_id)); |
+ UpdateDefaultMediaSourceAndNotifyObservers(default_source, |
+ default_frame_display_name); |
+ } |
+} |
+ |
+bool PresentationServiceDelegateImpl::IsMainFrame(int render_process_id, |
+ int render_frame_id) const { |
+ RenderFrameHost* main_frame = web_contents_->GetMainFrame(); |
+ return main_frame && |
+ GetRenderFrameHostId(main_frame) == |
+ RenderFrameHostId(render_process_id, render_frame_id); |
+} |
+ |
+void PresentationServiceDelegateImpl:: |
+ UpdateDefaultMediaSourceAndNotifyObservers( |
+ const MediaSource& default_source, |
+ const std::string& default_frame_display_name) { |
+ if (!default_source.Equals(default_source_) || |
+ default_frame_display_name != default_frame_display_name_) { |
+ default_source_ = default_source; |
+ default_frame_display_name_ = default_frame_display_name; |
+ FOR_EACH_OBSERVER(DefaultMediaSourceObserver, |
+ default_media_source_observers_, |
+ OnDefaultMediaSourceChanged(default_source_, |
+ default_frame_display_name_)); |
+ } |
+} |
+ |
+void PresentationServiceDelegateImpl::StartSession( |
+ int render_process_id, |
+ int render_frame_id, |
+ const std::string& presentation_url, |
+ const std::string& presentation_id, |
+ const PresentationSessionSuccessCallback& success_cb, |
+ const PresentationSessionErrorCallback& error_cb) { |
+ // BUG=464205 |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void PresentationServiceDelegateImpl::JoinSession( |
+ int render_process_id, |
+ int render_frame_id, |
+ const std::string& presentation_url, |
+ const std::string& presentation_id, |
+ const PresentationSessionSuccessCallback& success_cb, |
+ const PresentationSessionErrorCallback& error_cb) { |
+ // BUG=464205 |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void PresentationServiceDelegateImpl::ListenForSessionMessages( |
+ int render_process_id, |
+ int render_frame_id, |
+ const PresentationSessionMessageCallback& message_cb) { |
+ // BUG=464205 |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void PresentationServiceDelegateImpl::SendMessage( |
+ int render_process_id, |
+ int render_frame_id, |
+ scoped_ptr<content::PresentationSessionMessage> message_request, |
+ const SendMessageCallback& send_message_cb) { |
+ // BUG=464205 |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void PresentationServiceDelegateImpl::OnRouteCreated(const MediaRoute& route) { |
+ const MediaSource& source = route.media_source(); |
+ DCHECK(!source.Empty()); |
+ if (!default_source_.Equals(source)) |
+ return; |
+ RenderFrameHost* main_frame = web_contents_->GetMainFrame(); |
+ if (!main_frame) |
+ return; |
+ RenderFrameHostId render_frame_host_id(GetRenderFrameHostId(main_frame)); |
+ // TODO(imcheng): Pass in valid default presentation ID once it is |
+ // available from MediaRoute URN. BUG=493365 |
+ frame_manager_->OnDefaultPresentationStarted( |
+ render_frame_host_id, |
+ content::PresentationSessionInfo(PresentationUrlFromMediaSource(source), |
+ std::string())); |
+} |
+ |
+void PresentationServiceDelegateImpl::AddDefaultMediaSourceObserver( |
+ DefaultMediaSourceObserver* observer) { |
+ default_media_source_observers_.AddObserver(observer); |
+} |
+ |
+void PresentationServiceDelegateImpl::RemoveDefaultMediaSourceObserver( |
+ DefaultMediaSourceObserver* observer) { |
+ default_media_source_observers_.RemoveObserver(observer); |
+} |
+ |
+void PresentationServiceDelegateImpl::SetMediaRouterForTest( |
+ MediaRouter* router) { |
+ router_ = router; |
+ frame_manager_->SetMediaRouterForTest(router); |
+} |
+ |
+base::WeakPtr<PresentationServiceDelegateImpl> |
+PresentationServiceDelegateImpl::GetWeakPtr() { |
+ return weak_factory_.GetWeakPtr(); |
+} |
+ |
+bool PresentationServiceDelegateImpl::HasScreenAvailabilityListenerForTest( |
+ int render_process_id, |
+ int render_frame_id, |
+ const MediaSourceId& source_id) const { |
+ RenderFrameHostId render_frame_host_id(render_process_id, render_frame_id); |
+ return frame_manager_->HasScreenAvailabilityListenerForTest( |
+ render_frame_host_id, source_id); |
+} |
+ |
+} // namespace media_router |