| 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
|
|
|