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..73ce1e8ab198da9ca09cf54545039f191f96a246 |
--- /dev/null |
+++ b/chrome/browser/media/router/presentation_service_delegate_impl.cc |
@@ -0,0 +1,320 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
mark a. foltz
2015/05/11 07:36:21
Copyright
haibinlu
2015/05/13 01:40:19
Done.
|
+// 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/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_impl.h" |
mark a. foltz
2015/05/11 07:36:21
Why does this class need to know about the MR impl
haibinlu
2015/05/13 01:40:19
removed.
|
+#include "chrome/browser/media/router/media_router_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_helper.h" |
+#include "chrome/browser/media/router/presentation_media_sinks_observer.h" |
+#include "chrome/browser/sessions/session_tab_helper.h" |
+#include "chrome/browser/ui/webui/media_router/media_router_dialog_controller.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 { |
+ |
+PresentationServiceDelegateImpl::PresentationServiceDelegateImpl( |
+ content::WebContents* web_contents) |
+ : num_observers_(0u), |
+ web_contents_(web_contents), |
+ router_(MediaRouterImplFactory::GetMediaRouterForBrowserContext( |
+ web_contents_->GetBrowserContext())), |
+ weak_factory_(this) { |
+ DCHECK(router_); |
+} |
+ |
+PresentationServiceDelegateImpl::~PresentationServiceDelegateImpl() { |
+ DCHECK(observers_.empty()); |
+ DCHECK_EQ(0u, num_observers_); |
+ |
+ for (const auto& delegate_observer_entry : delegate_observers_) |
+ delegate_observer_entry.second->OnDelegateDestroyed(); |
+} |
+ |
+void PresentationServiceDelegateImpl::AddObserver( |
+ int render_process_id, |
+ int render_frame_id, |
+ content::PresentationServiceDelegate::Observer* observer) { |
+ DCHECK(observer); |
+ |
+ RenderFrameHostId rfh_id(render_process_id, render_frame_id); |
+ DCHECK(!ContainsKey(delegate_observers_, rfh_id)); |
+ |
+ delegate_observers_[rfh_id] = observer; |
+} |
+ |
+void PresentationServiceDelegateImpl::RemoveObserver(int render_process_id, |
+ int render_frame_id) { |
+ delegate_observers_.erase( |
+ RenderFrameHostId(render_process_id, render_frame_id)); |
+} |
+ |
+MediaSource PresentationServiceDelegateImpl::GetMediaSourceFromListener( |
+ content::PresentationScreenAvailabilityListener* listener) { |
+ // If the default presentation URL is empty then fall back to 1-UA mode, |
+ // i.e. offscreeen tab rendering. |
+ std::string presentation_url(listener->GetPresentationUrl()); |
+ return presentation_url.empty() |
+ ? ForTabMediaSource(SessionTabHelper::IdForTab(web_contents_)) |
+ : ForPresentationUrl(presentation_url); |
+} |
+ |
+bool PresentationServiceDelegateImpl::AddScreenAvailabilityListener( |
+ int render_process_id, |
+ int routing_id, |
+ content::PresentationScreenAvailabilityListener* listener) { |
+ DCHECK(listener); |
+ |
+ if (num_observers_ >= kMaxNumSources) { |
+ return false; |
+ } |
+ |
+ RenderFrameHostId rfh_id(render_process_id, routing_id); |
+ MediaSource source(GetMediaSourceFromListener(listener)); |
+ auto& observers_for_frame = observers_[rfh_id]; |
+ // Already exists. |
+ if (ContainsKey(observers_for_frame, source.id())) |
+ return false; |
+ |
+ linked_ptr<PresentationMediaSinksObserver> observer( |
+ new PresentationMediaSinksObserver(router_, listener, source)); |
+ observers_for_frame.insert(std::make_pair(source.id(), observer)); |
+ num_observers_++; |
+ return true; |
+} |
+ |
+void PresentationServiceDelegateImpl::RemoveScreenAvailabilityListener( |
+ int render_process_id, |
+ int routing_id, |
+ content::PresentationScreenAvailabilityListener* listener) { |
+ DCHECK(listener); |
+ |
+ RenderFrameHostId rfh_id(render_process_id, routing_id); |
+ MediaSource source(GetMediaSourceFromListener(listener)); |
+ auto it = observers_.find(rfh_id); |
+ if (it != observers_.end()) { |
+ auto& observers_by_id = it->second; |
+ auto observer_it = observers_by_id.find(source.id()); |
+ if (observer_it != observers_by_id.end()) { |
+ observers_by_id.erase(observer_it); |
+ num_observers_--; |
+ |
+ if (observers_by_id.empty()) |
+ observers_.erase(it); |
+ } |
+ } |
+} |
+ |
+void PresentationServiceDelegateImpl::Reset(int render_process_id, |
+ int routing_id) { |
+ RenderFrameHostId rfh_id(render_process_id, routing_id); |
+ UnregisterAllObserversFromFrame(rfh_id); |
+ default_presentation_infos_.erase(rfh_id); |
+ if (IsMainFrame(rfh_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 rfh_id(render_process_id, render_frame_id); |
+ if (default_presentation_url.empty() && default_presentation_id.empty()) { |
+ default_presentation_infos_.erase(rfh_id); |
+ } else { |
+ default_presentation_infos_[rfh_id].reset( |
+ new content::PresentationSessionInfo(default_presentation_url, |
+ default_presentation_id)); |
+ } |
+ |
+ if (IsMainFrame(rfh_id)) { |
+ // This is the main frame, that means tab-level default presentation |
+ // might have been updated. |
+ MediaSource new_default_source; |
+ if (!default_presentation_url.empty()) |
+ new_default_source = ForPresentationUrl(default_presentation_url); |
+ std::string new_default_source_host(GetSourceHostForFrame(rfh_id)); |
+ UpdateDefaultMediaSourceAndNotifyObservers(new_default_source, |
+ new_default_source_host); |
+ } |
+} |
+ |
+bool PresentationServiceDelegateImpl::IsMainFrame( |
+ RenderFrameHostId rfh_id) const { |
+ RenderFrameHost* main_frame = web_contents_->GetMainFrame(); |
+ return main_frame && GetRenderFrameHostId(main_frame) == rfh_id; |
+} |
+ |
+void PresentationServiceDelegateImpl:: |
+ UpdateDefaultMediaSourceAndNotifyObservers( |
+ const MediaSource& new_default_source, |
+ const std::string& new_default_source_host) { |
+ if (!new_default_source.Equals(default_source_) || |
+ new_default_source_host != default_source_host_) { |
+ default_source_ = new_default_source; |
+ default_source_host_ = new_default_source_host; |
+ FOR_EACH_OBSERVER( |
+ DefaultMediaSourceObserver, default_media_source_observers_, |
+ OnDefaultMediaSourceChanged(default_source_, default_source_host_)); |
+ } |
+} |
+ |
+std::string PresentationServiceDelegateImpl::GetOrGeneratePresentationId( |
+ RenderFrameHostId rfh_id, |
+ const std::string& presentation_id) const { |
+ if (!presentation_id.empty()) |
+ return presentation_id; |
+ |
+ auto it = default_presentation_infos_.find(rfh_id); |
+ if (it != default_presentation_infos_.end()) { |
+ const std::string& default_presentation_id = it->second->presentation_id; |
+ if (!default_presentation_id.empty()) |
+ return default_presentation_id; |
+ } |
+ |
+ return base::GenerateGUID(); |
+} |
+ |
+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) { |
+ if (presentation_url.empty() || !IsValidPresentationUrl(presentation_url)) { |
+ error_cb.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN, |
+ "Invalid presentation arguments.")); |
+ return; |
+ } |
+ |
+ RenderFrameHostId rfh_id(render_process_id, render_frame_id); |
+ scoped_ptr<CreateSessionRequest> context(new CreateSessionRequest( |
+ presentation_url, GetOrGeneratePresentationId(rfh_id, presentation_id), |
+ GURL(GetSourceHostForFrame(rfh_id)), success_cb, error_cb)); |
+ |
+ // NOTE: Currently this request is ignored if a dialog is already open, e.g. |
+ // via browser action. In practice, this should rarely happen, but log |
+ // an error message in case it does. |
+ MediaRouterDialogController* controller = |
+ MediaRouterDialogController::GetInstance(); |
+ DCHECK(controller); |
+ bool created = controller->ShowMediaRouterDialogForPresentation( |
+ web_contents_, context.Pass()); |
+ if (!created) { |
+ LOG(ERROR) << "Media router dialog already exists. Ignoring StartSession."; |
+ error_cb.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN, |
+ "Unable to create dialog.")); |
+ return; |
+ } |
+} |
+ |
+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) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void PresentationServiceDelegateImpl::ListenForSessionMessages( |
+ int render_process_id, |
+ int render_frame_id, |
+ const PresentationSessionMessageCallback& message_cb) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void PresentationServiceDelegateImpl::OnRouteCreated(const MediaRoute& route) { |
+ const MediaSource& source = route.media_source(); |
+ DCHECK(!source.Empty()); |
+ if (default_source_.Equals(source)) { |
+ RenderFrameHost* main_frame = web_contents_->GetMainFrame(); |
+ if (main_frame) { |
+ RenderFrameHostId rfh_id(GetRenderFrameHostId(main_frame)); |
+ auto it = delegate_observers_.find(rfh_id); |
+ if (it != delegate_observers_.end()) { |
+ // TODO(imcheng): Pass in valid default presentation ID once it is |
+ // available from MediaRoute URN. |
+ it->second->OnDefaultPresentationStarted( |
+ content::PresentationSessionInfo(GetPresentationUrl(source), |
+ std::string())); |
+ } |
+ } |
+ } |
+} |
+ |
+MediaSource PresentationServiceDelegateImpl::GetDefaultMediaSource() const { |
+ return default_source_; |
+} |
+ |
+std::string PresentationServiceDelegateImpl::GetSourceHostForFrame( |
+ RenderFrameHostId rfh_id) const { |
+ RenderFrameHost* rfh = RenderFrameHost::FromID(rfh_id.first, rfh_id.second); |
+ DCHECK(rfh); |
+ std::string host = rfh->GetLastCommittedURL().host(); |
+ if (StartsWithASCII(host, "www.", false)) |
+ host = host.substr(4); |
+ return host; |
+} |
+ |
+void PresentationServiceDelegateImpl::UnregisterAllObserversFromFrame( |
+ RenderFrameHostId rfh_id) { |
+ auto it = observers_.find(rfh_id); |
+ if (it != observers_.end()) { |
+ auto& observers_by_id = it->second; |
+ num_observers_ -= observers_by_id.size(); |
+ observers_.erase(it); |
+ } |
+} |
+ |
+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; |
+} |
+ |
+// static |
+PresentationServiceDelegateImpl::RenderFrameHostId |
+PresentationServiceDelegateImpl::GetRenderFrameHostId(RenderFrameHost* rfh) { |
+ int render_process_id = rfh->GetProcess()->GetID(); |
+ int routing_id = rfh->GetRoutingID(); |
+ return RenderFrameHostId(render_process_id, routing_id); |
+} |
+ |
+base::WeakPtr<PresentationServiceDelegateImpl> |
+PresentationServiceDelegateImpl::GetWeakPtr() { |
+ return weak_factory_.GetWeakPtr(); |
+} |
+ |
+} // namespace media_router |