Index: chrome/browser/media/router/one_ua_presentation_router.cc |
diff --git a/chrome/browser/media/router/one_ua_presentation_router.cc b/chrome/browser/media/router/one_ua_presentation_router.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..168c92ac1d6b97ed9645139c661fa918c2871818 |
--- /dev/null |
+++ b/chrome/browser/media/router/one_ua_presentation_router.cc |
@@ -0,0 +1,346 @@ |
+// 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/one_ua_presentation_router.h" |
+ |
+using content::PresentationSessionInfo; |
+using content::PresenterSessionAvailableCallback; |
+ |
+namespace media_router { |
+ |
+OneUAPresentationRouter::~OneUAPresentationRouter() {} |
+ |
+void OneUAPresentationRouter::RegisterPresenter( |
+ const std::string& presentation_id, |
+ const RenderFrameHostId& presenter_frame_id) { |
+ DCHECK(!ContainsKey(presenter_frames_, presenter_frame_id)); |
+ presenter_frames_[presenter_frame_id] = presentation_id; |
+ |
+ auto* presentation_info = GetOrCreateOneUAPresentationInfo(presentation_id); |
+ presentation_info->presenter_frame_id = presenter_frame_id; |
+ // We wait until the controller side has registered before setting up the |
+ // route. |
+} |
+ |
+void OneUAPresentationRouter::UnregisterPresenter( |
+ const RenderFrameHostId& presenter_frame_id) { |
+ DCHECK(ContainsKey(presenter_frames_, presenter_frame_id)); |
+ auto it = presenter_frames_.find(presenter_frame_id); |
+ std::string presentation_id = it->second; |
+ presenter_frames_.erase(it); |
+ |
+ auto* presentation_info = GetOneUAPresentationInfo(presentation_id); |
+ DCHECK(presentation_info); |
+ DCHECK(presenter_frame_id == presentation_info->presenter_frame_id); |
+ RemovePresenterAndNotifyStateChange(presentation_info); |
+ if (presentation_info->IsEmpty()) |
+ one_ua_presentations_.erase(presentation_id); |
+} |
+ |
+void OneUAPresentationRouter::RegisterController( |
+ const content::PresentationSessionInfo& session, |
+ const RenderFrameHostId& controller_frame_id) { |
+ const std::string& presentation_id = session.presentation_id; |
+ auto* presentation_info = GetOrCreateOneUAPresentationInfo(presentation_id); |
+ |
+ auto& route = presentation_info->route; |
+ |
+ // Check that this (presentation, controller) is not already registered. |
+ DCHECK(!route.controller); |
+ DCHECK(!route.presenter); |
+ |
+ route.controller.reset( |
+ new OneUAPresentationSession(controller_frame_id, session)); |
+ content::PresentationSessionInfo presenter_session(std::string(), |
+ presentation_id); |
+ route.presenter.reset( |
+ new OneUAPresentationSession(controller_frame_id, presenter_session)); |
+ |
+ // Resolve pending getSession() request. |
+ // Note: session objects for presenters do not contain presentation URLs. |
+ if (!presentation_info->session_callback.is_null()) { |
+ presentation_info->session_callback.Run(presenter_session); |
+ presentation_info->session_callback.Reset(); |
+ } |
+} |
+ |
+void OneUAPresentationRouter::UnregisterController( |
+ const std::string& presentation_id, |
+ const RenderFrameHostId& controller_frame_id) { |
+ auto* presentation_info = GetOneUAPresentationInfo(presentation_id); |
+ DCHECK(presentation_info); |
+ DCHECK(controller_frame_id == |
+ presentation_info->route.controller->controller_frame_id); |
+ RemoveControllerAndNotifyStateChange(presentation_info); |
+ |
+ if (presentation_info->IsEmpty()) |
+ one_ua_presentations_.erase(presentation_id); |
+} |
+ |
+bool OneUAPresentationRouter::IsPresenter( |
+ const RenderFrameHostId& frame_id) const { |
+ return ContainsKey(presenter_frames_, frame_id); |
+} |
+ |
+bool OneUAPresentationRouter::IsController( |
+ const std::string& presentation_id, |
+ const RenderFrameHostId& frame_id) const { |
+ auto* presentation_info = GetOneUAPresentationInfo(presentation_id); |
+ if (!presentation_info) |
+ return false; |
+ |
+ const auto& route = presentation_info->route; |
+ if (!route.controller) |
+ return false; |
+ return frame_id == route.controller->controller_frame_id; |
+} |
+ |
+void OneUAPresentationRouter::GetSinglePresenterSession( |
+ const RenderFrameHostId& presenter_frame_id, |
+ const PresenterSessionAvailableCallback& callback) { |
+ DCHECK(!callback.is_null()); |
+ DCHECK(IsPresenter(presenter_frame_id)); |
+ |
+ const std::string& presentation_id = presenter_frames_[presenter_frame_id]; |
+ auto* presentation_info = GetOneUAPresentationInfo(presentation_id); |
+ DCHECK(presentation_info); |
+ DCHECK(presenter_frame_id == presentation_info->presenter_frame_id); |
+ |
+ // Resolve with the first route. |
+ const auto& route = presentation_info->route; |
+ if (route.presenter) { |
+ callback.Run(route.presenter->session); |
+ return; |
+ } else { |
+ presentation_info->session_callback = callback; |
+ } |
+} |
+ |
+std::vector<content::PresentationSessionInfo> |
+OneUAPresentationRouter::GetPresenterSessions( |
+ const RenderFrameHostId& presenter_frame_id) const { |
+ DCHECK(IsPresenter(presenter_frame_id)); |
+ |
+ auto it = presenter_frames_.find(presenter_frame_id); |
+ DCHECK(it != presenter_frames_.end()); |
+ const std::string& presentation_id = it->second; |
+ auto* presentation_info = GetOneUAPresentationInfo(presentation_id); |
+ DCHECK(presentation_info); |
+ |
+ std::vector<content::PresentationSessionInfo> sessions; |
+ // TODO(imcheng): Support multiple controllers. |
+ if (presentation_info->route.presenter) |
+ sessions.push_back(presentation_info->route.presenter->session); |
+ return sessions; |
+} |
+ |
+void OneUAPresentationRouter::SendMessage( |
+ const PresentationSessionInfo& session, |
+ scoped_ptr<content::PresentationSessionMessage> message, |
+ const content::SendMessageCallback& callback) { |
+ const std::string& presentation_id = session.presentation_id; |
+ auto* presentation_info = GetOneUAPresentationInfo(presentation_id); |
+ if (!presentation_info) { |
+ LOG(ERROR) << "SendMessage: Unknown 1UA presentation " << presentation_id; |
+ callback.Run(false); |
+ return; |
+ } |
+ |
+ bool from_presenter = session.presentation_url.empty(); |
+ auto& route = presentation_info->route; |
+ // From presenter to controller. |
+ if (from_presenter) { |
+ auto* controller = route.controller.get(); |
+ if (controller && !controller->message_callback.is_null()) { |
+ ScopedVector<content::PresentationSessionMessage> messages; |
+ messages.push_back(message.release()); |
+ controller->message_callback.Run(messages.Pass(), true); |
+ } |
+ } else { |
+ auto* presenter = route.presenter.get(); |
+ // From controller to presenter. |
+ if (presenter && !presenter->message_callback.is_null()) { |
+ ScopedVector<content::PresentationSessionMessage> messages; |
+ messages.push_back(message.release()); |
+ presenter->message_callback.Run(messages.Pass(), true); |
+ } |
+ } |
+ |
+ callback.Run(true); |
+} |
+ |
+void OneUAPresentationRouter::ListenForMessages( |
+ const PresentationSessionInfo& session, |
+ const content::PresentationSessionMessageCallback& callback) { |
+ const std::string& presentation_id = session.presentation_id; |
+ auto* presentation_info = GetOneUAPresentationInfo(presentation_id); |
+ if (!presentation_info) { |
+ LOG(ERROR) << "ListenForMessages: Unknown 1UA presentation " |
+ << presentation_id; |
+ return; |
+ } |
+ |
+ bool from_presenter = session.presentation_url.empty(); |
+ auto& route = presentation_info->route; |
+ if (from_presenter) { |
+ auto* presenter = route.presenter.get(); |
+ if (!presenter) { |
+ LOG(ERROR) << "ListenForMessages: presenter frame not found for " |
+ << presentation_id; |
+ return; |
+ } |
+ DVLOG_IF(2, !presenter->message_callback.is_null()) |
+ << "Overwriting presenter frame message callback for " |
+ << presentation_id; |
+ presenter->message_callback = callback; |
+ } else { |
+ auto* controller = route.controller.get(); |
+ if (!controller) { |
+ LOG(ERROR) << "ListenForMessages: controller frame not found for " |
+ << presentation_id; |
+ return; |
+ } |
+ DVLOG_IF(2, !controller->message_callback.is_null()) |
+ << "Overwriting controller frame message callback for " |
+ << presentation_id; |
+ controller->message_callback = callback; |
+ } |
+} |
+ |
+void OneUAPresentationRouter::ListenForStateChanges( |
+ const PresentationSessionInfo& session, |
+ const content::SessionStateChangedCallback& callback) { |
+ const std::string& presentation_id = session.presentation_id; |
+ auto* presentation_info = GetOneUAPresentationInfo(presentation_id); |
+ if (!presentation_info) { |
+ LOG(ERROR) << "ListenForMessages: Unknown 1UA presentation " |
+ << presentation_id; |
+ return; |
+ } |
+ |
+ bool from_presenter = session.presentation_url.empty(); |
+ auto& route = presentation_info->route; |
+ if (from_presenter) { |
+ auto* presenter = route.presenter.get(); |
+ if (!presenter) { |
+ LOG(ERROR) << "ListenForMessages: presenter frame not found for " |
+ << presentation_id; |
+ return; |
+ } |
+ DVLOG_IF(2, !presenter->state_change_callback.is_null()) |
+ << "Overwriting presenter frame state change callback for " |
+ << presentation_id; |
+ presenter->state_change_callback = callback; |
+ } else { |
+ auto* controller = route.controller.get(); |
+ if (!controller) { |
+ LOG(ERROR) << "ListenForMessages: controller frame not found for " |
+ << presentation_id; |
+ return; |
+ } |
+ DVLOG_IF(2, !controller->state_change_callback.is_null()) |
+ << "Overwriting controller frame state change callback for " |
+ << presentation_id; |
+ controller->state_change_callback = callback; |
+ } |
+} |
+ |
+void OneUAPresentationRouter::Reset(const RenderFrameHostId& frame_id) { |
+ if (IsPresenter(frame_id)) |
+ UnregisterPresenter(frame_id); |
+ |
+ for (auto it = one_ua_presentations_.begin(); |
+ it != one_ua_presentations_.end(); |
+ /* no-op */) { |
+ auto* presentation_info = it->second; |
+ auto* controller = presentation_info->route.controller.get(); |
+ if (controller && controller->controller_frame_id == frame_id) { |
+ RemovePresenterAndNotifyStateChange(presentation_info); |
+ if (presentation_info->IsEmpty()) |
+ one_ua_presentations_.erase(it++); |
+ else |
+ ++it; |
+ } else { |
+ ++it; |
+ } |
+ } |
+} |
+ |
+OneUAPresentationRouter::OneUAPresentationRouter() {} |
+ |
+void OneUAPresentationRouter::RemovePresenterAndNotifyStateChange( |
+ OneUAPresentationInfo* presentation_info) { |
+ presentation_info->presenter_frame_id = RenderFrameHostId(); |
+ presentation_info->session_callback.Reset(); |
+ |
+ auto& route = presentation_info->route; |
+ if (route.presenter) { |
+ route.presenter.reset(); |
+ auto& controller = route.controller; |
+ if (controller && !controller->state_change_callback.is_null()) { |
+ controller->state_change_callback.Run( |
+ controller->session, |
+ content::PRESENTATION_SESSION_STATE_DISCONNECTED); |
+ } |
+ } |
+} |
+ |
+void OneUAPresentationRouter::RemoveControllerAndNotifyStateChange( |
+ OneUAPresentationInfo* presentation_info) { |
+ auto& route = presentation_info->route; |
+ route.controller.reset(); |
+ |
+ auto& presenter = route.presenter; |
+ if (presenter && !presenter->state_change_callback.is_null()) { |
+ presenter->state_change_callback.Run( |
+ presenter->session, content::PRESENTATION_SESSION_STATE_DISCONNECTED); |
+ } |
+} |
+ |
+OneUAPresentationRouter::OneUAPresentationInfo* |
+OneUAPresentationRouter::GetOrCreateOneUAPresentationInfo( |
+ const std::string& presentation_id) { |
+ OneUAPresentationInfo* info = nullptr; |
+ auto presentation_info_it = one_ua_presentations_.find(presentation_id); |
+ if (presentation_info_it == one_ua_presentations_.end()) { |
+ info = new OneUAPresentationInfo; |
+ one_ua_presentations_.insert(presentation_id, make_scoped_ptr(info)); |
+ } else { |
+ info = presentation_info_it->second; |
+ } |
+ DCHECK(info); |
+ return info; |
+} |
+ |
+OneUAPresentationRouter::OneUAPresentationInfo* |
+OneUAPresentationRouter::GetOneUAPresentationInfo( |
+ const std::string& presentation_id) const { |
+ OneUAPresentationInfo* info = nullptr; |
+ auto presentation_info_it = one_ua_presentations_.find(presentation_id); |
+ return presentation_info_it == one_ua_presentations_.end() |
+ ? nullptr |
+ : presentation_info_it->second; |
+} |
+ |
+OneUAPresentationRouter::OneUAPresentationSession::OneUAPresentationSession( |
+ const RenderFrameHostId& controller_frame_id, |
+ const content::PresentationSessionInfo& session) |
+ : controller_frame_id(controller_frame_id), session(session) {} |
+ |
+OneUAPresentationRouter::OneUAPresentationSession::~OneUAPresentationSession() { |
+} |
+ |
+OneUAPresentationRouter::OneUAPresentationRoute::OneUAPresentationRoute() {} |
+ |
+OneUAPresentationRouter::OneUAPresentationRoute::~OneUAPresentationRoute() {} |
+ |
+OneUAPresentationRouter::OneUAPresentationInfo::OneUAPresentationInfo() {} |
+ |
+OneUAPresentationRouter::OneUAPresentationInfo::~OneUAPresentationInfo() {} |
+ |
+bool OneUAPresentationRouter::OneUAPresentationInfo::IsEmpty() const { |
+ return !route.presenter && !route.controller; |
+} |
+ |
+} // namespace media_router |