| Index: chrome/browser/media/router/offscreen_presentation_manager.cc
|
| diff --git a/chrome/browser/media/router/offscreen_presentation_manager.cc b/chrome/browser/media/router/offscreen_presentation_manager.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..598c5e5c8517285b6331c36dfaaf6f2816528b4e
|
| --- /dev/null
|
| +++ b/chrome/browser/media/router/offscreen_presentation_manager.cc
|
| @@ -0,0 +1,236 @@
|
| +// 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/offscreen_presentation_manager.h"
|
| +
|
| +#include "content/public/browser/presentation_session_state_listener.h"
|
| +#include "content/public/browser/render_frame_host.h"
|
| +#include "content/public/browser/render_process_host.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +
|
| +namespace media_router {
|
| +
|
| +OffscreenPresentationManager::OffscreenPresentationSession::
|
| + OffscreenPresentationSession(
|
| + bool is_controller,
|
| + OffscreenPresentationManager::OffscreenPresentationConnection*
|
| + connection)
|
| + : is_controller_(is_controller),
|
| + state_change_listener_(nullptr),
|
| + connection_(connection) {
|
| + DCHECK(connection_);
|
| +}
|
| +
|
| +OffscreenPresentationManager::OffscreenPresentationSession::
|
| + ~OffscreenPresentationSession() {
|
| + if (connection_) {
|
| + if (is_controller_)
|
| + connection_->RemoveControllerSession();
|
| + else
|
| + connection_->RemoveReceiverSession();
|
| + }
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationSession::SendMessage(
|
| + scoped_ptr<content::PresentationSessionMessage> message,
|
| + const content::SendMessageCallback& callback) {
|
| + if (!connection_) {
|
| + callback.Run(false);
|
| + return;
|
| + }
|
| + if (is_controller_)
|
| + connection_->SendMessageToReceiver(message.Pass(), callback);
|
| + else
|
| + connection_->SendMessageToController(message.Pass(), callback);
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationSession::
|
| + ListenForMessages(
|
| + const content::PresentationSessionMessageCallback& callback) {
|
| + messages_callback_ = callback;
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationSession::
|
| + ListenForStateChanges(content::PresentationSessionStateListener* listener) {
|
| + state_change_listener_ = listener;
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationSession::
|
| + OnSessionStateChanged(content::PresentationSessionState state) {
|
| + if (state_change_listener_)
|
| + state_change_listener_->OnSessionStateChanged(state);
|
| +
|
| + if (state == content::PRESENTATION_SESSION_STATE_DISCONNECTED)
|
| + connection_ = nullptr;
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationSession::
|
| + OnMessageReceived(scoped_ptr<content::PresentationSessionMessage> message) {
|
| + if (!messages_callback_.is_null()) {
|
| + ScopedVector<content::PresentationSessionMessage> messages;
|
| + messages.push_back(message.release());
|
| + messages_callback_.Run(messages.Pass(), true);
|
| + }
|
| +}
|
| +
|
| +OffscreenPresentationManager::~OffscreenPresentationManager() {}
|
| +
|
| +void OffscreenPresentationManager::RegisterOffscreenPresentationReceiver(
|
| + const std::string& presentation_id,
|
| + const ReceiverSessionAvailableCallback& receiver_available_callback) {
|
| + DCHECK(!ContainsKey(offscreen_presentations_, presentation_id));
|
| +
|
| + offscreen_presentations_.insert(
|
| + presentation_id,
|
| + make_scoped_ptr(new OffscreenPresentation(
|
| + presentation_id, receiver_available_callback, this)));
|
| +}
|
| +
|
| +void OffscreenPresentationManager::UnregisterOffscreenPresentationReceiver(
|
| + const std::string& presentation_id) {
|
| + DCHECK(ContainsKey(offscreen_presentations_, presentation_id));
|
| + offscreen_presentations_.erase(presentation_id);
|
| +}
|
| +
|
| +scoped_ptr<OffscreenPresentationManager::OffscreenPresentationSession>
|
| +OffscreenPresentationManager::ConnectToOffscreenPresentation(
|
| + const std::string& presentation_id,
|
| + const RenderFrameHostId& controller_frame_id) {
|
| + auto it = offscreen_presentations_.find(presentation_id);
|
| + if (it == offscreen_presentations_.end())
|
| + return scoped_ptr<
|
| + OffscreenPresentationManager::OffscreenPresentationSession>();
|
| +
|
| + return it->second->AddConnection(controller_frame_id);
|
| +}
|
| +
|
| +OffscreenPresentationManager::OffscreenPresentationManager() {}
|
| +
|
| +OffscreenPresentationManager::OffscreenPresentationConnection::
|
| + OffscreenPresentationConnection(
|
| + const RenderFrameHostId& controller_frame_id,
|
| + OffscreenPresentation* presentation)
|
| + : presentation_(presentation),
|
| + controller_frame_id_(controller_frame_id),
|
| + controller_(nullptr),
|
| + receiver_(nullptr) {
|
| + DCHECK(presentation_);
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationConnection::Init(
|
| + OffscreenPresentationManager::OffscreenPresentationSession* controller,
|
| + OffscreenPresentationManager::OffscreenPresentationSession* receiver) {
|
| + DCHECK(!controller_);
|
| + DCHECK(!receiver_);
|
| + DCHECK(controller);
|
| + DCHECK(receiver);
|
| + controller_ = controller;
|
| + receiver_ = receiver;
|
| +}
|
| +
|
| +OffscreenPresentationManager::OffscreenPresentationConnection::
|
| + ~OffscreenPresentationConnection() {
|
| + DCHECK(!controller_ || !receiver_);
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationConnection::
|
| + RemoveControllerSession() {
|
| + RemoveSession(controller_);
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationConnection::
|
| + RemoveReceiverSession() {
|
| + RemoveSession(receiver_);
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationConnection::
|
| + RemoveSession(OffscreenPresentationSession* session) {
|
| + DCHECK(session);
|
| + OffscreenPresentationManager::OffscreenPresentationSession* other_session =
|
| + nullptr;
|
| + if (session == controller_) {
|
| + controller_ = nullptr;
|
| + other_session = receiver_;
|
| + } else {
|
| + DCHECK(session == receiver_);
|
| + receiver_ = nullptr;
|
| + other_session = controller_;
|
| + }
|
| +
|
| + DCHECK(other_session);
|
| + other_session->OnSessionStateChanged(
|
| + content::PRESENTATION_SESSION_STATE_DISCONNECTED);
|
| + presentation_->RemoveConnection(controller_frame_id_);
|
| + // |this| is deleted beyond this point.
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationConnection::
|
| + SendMessageToController(
|
| + scoped_ptr<content::PresentationSessionMessage> message,
|
| + const content::SendMessageCallback& callback) {
|
| + SendMessage(controller_, message.Pass(), callback);
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationConnection::
|
| + SendMessageToReceiver(
|
| + scoped_ptr<content::PresentationSessionMessage> message,
|
| + const content::SendMessageCallback& callback) {
|
| + SendMessage(receiver_, message.Pass(), callback);
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentationConnection::SendMessage(
|
| + OffscreenPresentationSession* session,
|
| + scoped_ptr<content::PresentationSessionMessage> message,
|
| + const content::SendMessageCallback& callback) {
|
| + // TODO(imcheng): Implement message batching.
|
| + session->OnMessageReceived(message.Pass());
|
| + callback.Run(true);
|
| +}
|
| +
|
| +OffscreenPresentationManager::OffscreenPresentation::OffscreenPresentation(
|
| + const std::string& presentation_id,
|
| + const ReceiverSessionAvailableCallback& receiver_available_callback,
|
| + OffscreenPresentationManager* manager)
|
| + : presentation_id_(presentation_id),
|
| + receiver_available_callback_(receiver_available_callback),
|
| + manager_(manager) {
|
| + DCHECK(!receiver_available_callback_.is_null());
|
| + DCHECK(manager_);
|
| +}
|
| +
|
| +OffscreenPresentationManager::OffscreenPresentation::~OffscreenPresentation() {
|
| + // The receiver must have destroyed all connections before unregistration.
|
| + DCHECK(connections_.empty());
|
| +}
|
| +
|
| +scoped_ptr<OffscreenPresentationManager::OffscreenPresentationSession>
|
| +OffscreenPresentationManager::OffscreenPresentation::AddConnection(
|
| + const RenderFrameHostId& controller_frame_id) {
|
| + DCHECK(!ContainsKey(connections_, controller_frame_id));
|
| +
|
| + scoped_ptr<OffscreenPresentationConnection> connection(
|
| + new OffscreenPresentationManager::OffscreenPresentationConnection(
|
| + controller_frame_id, this));
|
| + scoped_ptr<OffscreenPresentationManager::OffscreenPresentationSession>
|
| + controller_session(
|
| + new OffscreenPresentationManager::OffscreenPresentationSession(
|
| + true, connection.get()));
|
| + scoped_ptr<OffscreenPresentationManager::OffscreenPresentationSession>
|
| + receiver_session(
|
| + new OffscreenPresentationManager::OffscreenPresentationSession(
|
| + false, connection.get()));
|
| +
|
| + connection->Init(controller_session.get(), receiver_session.get());
|
| + connections_.insert(controller_frame_id, connection.Pass());
|
| + receiver_available_callback_.Run(receiver_session.Pass());
|
| + return controller_session.Pass();
|
| +}
|
| +
|
| +void OffscreenPresentationManager::OffscreenPresentation::RemoveConnection(
|
| + const RenderFrameHostId& controller_frame_id) {
|
| + DCHECK(ContainsKey(connections_, controller_frame_id));
|
| + connections_.erase(controller_frame_id);
|
| +}
|
| +
|
| +} // namespace media_router
|
|
|