Commit f64aa5bd authored by John Williams's avatar John Williams Committed by Commit Bot

[Cast MRP] Split cast_activity_manager.{cc,h} apart.

Bug: 954797
Change-Id: Idec1306428c4efa4500534ad970da1606e132003
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1575435
Commit-Queue: John Williams <jrw@chromium.org>
Reviewed-by: default avatarTakumi Fujimoto <takumif@chromium.org>
Cr-Commit-Position: refs/heads/master@{#653361}
parent 18766e6b
...@@ -93,6 +93,8 @@ static_library("router") { ...@@ -93,6 +93,8 @@ static_library("router") {
"presentation/presentation_navigation_policy.h", "presentation/presentation_navigation_policy.h",
"providers/cast/cast_activity_manager.cc", "providers/cast/cast_activity_manager.cc",
"providers/cast/cast_activity_manager.h", "providers/cast/cast_activity_manager.h",
"providers/cast/cast_activity_record.cc",
"providers/cast/cast_activity_record.h",
"providers/cast/cast_app_availability_tracker.cc", "providers/cast/cast_app_availability_tracker.cc",
"providers/cast/cast_app_availability_tracker.h", "providers/cast/cast_app_availability_tracker.h",
"providers/cast/cast_app_discovery_service.cc", "providers/cast/cast_app_discovery_service.cc",
...@@ -103,6 +105,8 @@ static_library("router") { ...@@ -103,6 +105,8 @@ static_library("router") {
"providers/cast/cast_media_route_provider.h", "providers/cast/cast_media_route_provider.h",
"providers/cast/cast_media_route_provider_metrics.cc", "providers/cast/cast_media_route_provider_metrics.cc",
"providers/cast/cast_media_route_provider_metrics.h", "providers/cast/cast_media_route_provider_metrics.h",
"providers/cast/cast_session_client.cc",
"providers/cast/cast_session_client.h",
"providers/cast/cast_session_tracker.cc", "providers/cast/cast_session_tracker.cc",
"providers/cast/cast_session_tracker.h", "providers/cast/cast_session_tracker.h",
"providers/cast/chrome_cast_message_handler.cc", "providers/cast/chrome_cast_message_handler.cc",
......
// Copyright 2019 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/providers/cast/cast_activity_record.h"
#include <memory>
#include <vector>
#include "base/bind.h"
#include "base/optional.h"
#include "chrome/browser/media/router/providers/cast/cast_activity_manager.h"
#include "chrome/browser/media/router/providers/cast/cast_session_client.h"
#include "url/origin.h"
using blink::mojom::PresentationConnectionCloseReason;
using blink::mojom::PresentationConnectionMessagePtr;
namespace media_router {
CastActivityRecord::~CastActivityRecord() {}
mojom::RoutePresentationConnectionPtr CastActivityRecord::AddClient(
const CastMediaSource& source,
const url::Origin& origin,
int tab_id) {
const std::string& client_id = source.client_id();
auto client = std::make_unique<CastSessionClient>(client_id, origin, tab_id,
source.auto_join_policy(),
data_decoder_, this);
auto presentation_connection = client->Init();
connected_clients_.emplace(client_id, std::move(client));
// Route is now local due to connected client.
route_.set_local(true);
return presentation_connection;
}
void CastActivityRecord::RemoveClient(const std::string& client_id) {
// Don't erase by key here as the |client_id| may be referring to the
// client being deleted.
auto it = connected_clients_.find(client_id);
if (it != connected_clients_.end())
connected_clients_.erase(it);
}
void CastActivityRecord::SetOrUpdateSession(const CastSession& session,
const MediaSinkInternal& sink,
const std::string& hash_token) {
DVLOG(2) << "CastActivityRecord::SetOrUpdateSession old session_id = "
<< session_id_.value_or("<missing>")
<< ", new session_id = " << session.session_id();
if (!session_id_) {
session_id_ = session.session_id();
} else {
DCHECK_EQ(*session_id_, session.session_id());
for (auto& client : connected_clients_)
client.second->SendMessageToClient(
CreateUpdateSessionMessage(session, client.first, sink, hash_token));
}
route_.set_description(session.GetRouteDescription());
}
cast_channel::Result CastActivityRecord::SendAppMessageToReceiver(
const CastInternalMessage& cast_message) {
const CastSession* session = GetSession();
if (!session)
return cast_channel::Result::kFailed; // TODO(jrw): Send error code
// back to SDK client.
const std::string& message_namespace = cast_message.app_message_namespace();
if (!base::ContainsKey(session->message_namespaces(), message_namespace)) {
DLOG(ERROR) << "Disallowed message namespace: " << message_namespace;
// TODO(jrw): Send error code back to SDK client.
return cast_channel::Result::kFailed;
}
return message_handler_->SendAppMessage(
GetCastChannelId(),
cast_channel::CreateCastMessage(
message_namespace, cast_message.app_message_body(),
cast_message.client_id, session->transport_id()));
}
base::Optional<int> CastActivityRecord::SendMediaRequestToReceiver(
const CastInternalMessage& cast_message) {
CastSession* session = GetSession();
if (!session)
return base::nullopt;
return message_handler_->SendMediaRequest(
GetCastChannelId(), cast_message.v2_message_body(),
cast_message.client_id, session->transport_id());
}
void CastActivityRecord::SendSetVolumeRequestToReceiver(
const CastInternalMessage& cast_message,
cast_channel::ResultCallback callback) {
message_handler_->SendSetVolumeRequest(
GetCastChannelId(), cast_message.v2_message_body(),
cast_message.client_id, std::move(callback));
}
void CastActivityRecord::SendStopSessionMessageToReceiver(
const base::Optional<std::string>& client_id,
mojom::MediaRouteProvider::TerminateRouteCallback callback) {
const std::string& sink_id = route_.media_sink_id();
const MediaSinkInternal* sink = media_sink_service_->GetSinkById(sink_id);
DCHECK(sink);
DCHECK(session_id_);
message_handler_->StopSession(
sink->cast_data().cast_channel_id, *session_id_, client_id,
base::BindOnce(&CastActivityManager::HandleStopSessionResponse,
activity_manager_->GetWeakPtr(), route_.media_route_id(),
std::move(callback)));
}
void CastActivityRecord::HandleLeaveSession(const std::string& client_id) {
auto client_it = connected_clients_.find(client_id);
CHECK(client_it != connected_clients_.end());
CastSessionClient& client = *client_it->second;
std::vector<std::string> leaving_client_ids;
for (const auto& pair : connected_clients_) {
if (pair.second->MatchesAutoJoinPolicy(client.origin(), client.tab_id()))
leaving_client_ids.push_back(pair.first);
}
for (const auto& client_id : leaving_client_ids) {
auto leaving_client_it = connected_clients_.find(client_id);
CHECK(leaving_client_it != connected_clients_.end());
leaving_client_it->second->CloseConnection(
PresentationConnectionCloseReason::CLOSED);
connected_clients_.erase(leaving_client_it);
}
}
void CastActivityRecord::SendMessageToClient(
const std::string& client_id,
PresentationConnectionMessagePtr message) {
auto it = connected_clients_.find(client_id);
if (it == connected_clients_.end()) {
DLOG(ERROR) << "Attempting to send message to nonexistent client: "
<< client_id;
return;
}
it->second->SendMessageToClient(std::move(message));
}
void CastActivityRecord::ClosePresentationConnections(
PresentationConnectionCloseReason close_reason) {
for (auto& client : connected_clients_)
client.second->CloseConnection(close_reason);
}
void CastActivityRecord::TerminatePresentationConnections() {
for (auto& client : connected_clients_)
client.second->TerminateConnection();
}
CastActivityRecord::CastActivityRecord(
const MediaRoute& route,
const std::string& app_id,
MediaSinkServiceBase* media_sink_service,
cast_channel::CastMessageHandler* message_handler,
CastSessionTracker* session_tracker,
DataDecoder* data_decoder,
CastActivityManager* owner)
: route_(route),
app_id_(app_id),
media_sink_service_(media_sink_service),
message_handler_(message_handler),
session_tracker_(session_tracker),
data_decoder_(data_decoder),
activity_manager_(owner) {}
CastSession* CastActivityRecord::GetSession() {
DCHECK(session_id_);
CastSession* session = session_tracker_->GetSessionById(*session_id_);
if (!session) {
// TODO(crbug.com/905002): Add UMA metrics for this and other error
// conditions.
LOG(ERROR) << "Session not found: " << session_id_.value_or("<missing>");
}
return session;
}
int CastActivityRecord::GetCastChannelId() {
const MediaSinkInternal* sink = media_sink_service_->GetSinkByRoute(route_);
if (!sink) {
// TODO(crbug.com/905002): Add UMA metrics for this and other error
// conditions.
LOG(ERROR) << "Sink not found for route: " << route_;
return -1;
}
return sink->cast_data().cast_channel_id;
}
} // namespace media_router
// Copyright 2019 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.
#ifndef CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_ACTIVITY_RECORD_H_
#define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_ACTIVITY_RECORD_H_
#include <memory>
#include <string>
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/optional.h"
#include "chrome/common/media_router/mojo/media_router.mojom.h"
#include "chrome/common/media_router/providers/cast/cast_media_source.h"
#include "components/cast_channel/cast_message_handler.h"
#include "url/origin.h"
namespace media_router {
class CastActivityManager;
struct CastInternalMessage;
class CastSession;
class CastSessionClient;
class CastSessionTracker;
class DataDecoder;
class MediaSinkServiceBase;
// Represents an ongoing or launching Cast application on a Cast receiver.
// It keeps track of the set of Cast SDK clients connected to the application.
// Note that we do not keep track of 1-UA mode presentations here. Instead, they
// are handled by LocalPresentationManager.
//
// Instances of this class are associated with a specific session and app.
class CastActivityRecord {
public:
~CastActivityRecord();
const MediaRoute& route() const { return route_; }
const std::string& app_id() const { return app_id_; }
const base::flat_map<std::string, std::unique_ptr<CastSessionClient>>&
connected_clients() const {
return connected_clients_;
}
const base::Optional<std::string>& session_id() const { return session_id_; }
// Sends app message |cast_message|, which came from the SDK client, to the
// receiver hosting this session. Returns true if the message is sent
// successfully.
cast_channel::Result SendAppMessageToReceiver(
const CastInternalMessage& cast_message);
// Sends media command |cast_message|, which came from the SDK client, to the
// receiver hosting this session. Returns the locally-assigned request ID of
// the message sent to the receiver.
base::Optional<int> SendMediaRequestToReceiver(
const CastInternalMessage& cast_message);
// Sends a SET_VOLUME request to the receiver and calls |callback| when a
// response indicating whether the request succeeded is received.
void SendSetVolumeRequestToReceiver(const CastInternalMessage& cast_message,
cast_channel::ResultCallback callback);
void SendStopSessionMessageToReceiver(
const base::Optional<std::string>& client_id,
mojom::MediaRouteProvider::TerminateRouteCallback callback);
// Called when the client given by |client_id| requests to leave the session.
// This will also cause all clients within the session with matching origin
// and/or tab ID to leave (i.e., their presentation connections will be
// closed).
void HandleLeaveSession(const std::string& client_id);
// Adds a new client specified by |source| to this session and returns the
// handles of the two pipes to be held by Blink. It is invalid to call this
// method if the client already exists.
mojom::RoutePresentationConnectionPtr AddClient(const CastMediaSource& source,
const url::Origin& origin,
int tab_id);
void RemoveClient(const std::string& client_id);
// On the first call, saves the ID of |session|. On subsequent calls,
// notifies all connected clients that the session has been updated. In both
// cases, the stored route description is updated to match the session
// description.
//
// The |hash_token| parameter is used for hashing receiver IDs in messages
// sent to the Cast SDK, and |sink| is the sink associated with |session|.
void SetOrUpdateSession(const CastSession& session,
const MediaSinkInternal& sink,
const std::string& hash_token);
// Sends |message| to the client given by |client_id|.
void SendMessageToClient(
const std::string& client_id,
blink::mojom::PresentationConnectionMessagePtr message);
// Closes / Terminates the PresentationConnections of all clients connected
// to this activity.
void ClosePresentationConnections(
blink::mojom::PresentationConnectionCloseReason close_reason);
void TerminatePresentationConnections();
private:
friend class CastSessionClient;
friend class CastActivityManager;
// Creates a new record owned by |owner|.
CastActivityRecord(const MediaRoute& route,
const std::string& app_id,
MediaSinkServiceBase* media_sink_service,
cast_channel::CastMessageHandler* message_handler,
CastSessionTracker* session_tracker,
DataDecoder* data_decoder,
CastActivityManager* owner);
CastSession* GetSession();
int GetCastChannelId();
MediaRoute route_;
const std::string app_id_;
base::flat_map<std::string, std::unique_ptr<CastSessionClient>>
connected_clients_;
// Set by CastActivityManager after the session is launched successfully.
base::Optional<std::string> session_id_;
MediaSinkServiceBase* const media_sink_service_;
// TODO(https://crbug.com/809249): Consider wrapping CastMessageHandler with
// known parameters (sink, client ID, session transport ID) and passing them
// to objects that need to send messages to the receiver.
cast_channel::CastMessageHandler* const message_handler_;
CastSessionTracker* const session_tracker_;
DataDecoder* const data_decoder_;
CastActivityManager* const activity_manager_;
DISALLOW_COPY_AND_ASSIGN(CastActivityRecord);
};
} // namespace media_router
#endif // CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_ACTIVITY_RECORD_H_
// Copyright 2018 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/providers/cast/cast_session_client.h"
#include "base/bind.h"
#include "chrome/browser/media/router/data_decoder_util.h"
#include "chrome/browser/media/router/providers/cast/cast_activity_record.h"
using blink::mojom::PresentationConnectionCloseReason;
using blink::mojom::PresentationConnectionMessagePtr;
using blink::mojom::PresentationConnectionPtrInfo;
using blink::mojom::PresentationConnectionState;
namespace media_router {
namespace {
void ReportClientMessageParseError(const MediaRoute::Id& route_id,
const std::string& error) {
// TODO(crbug.com/808720): Record UMA metric for parse result.
DVLOG(2) << "Failed to parse Cast client message for " << route_id << ": "
<< error;
}
} // namespace
CastSessionClient::CastSessionClient(const std::string& client_id,
const url::Origin& origin,
int tab_id,
AutoJoinPolicy auto_join_policy,
DataDecoder* data_decoder,
CastActivityRecord* activity)
: client_id_(client_id),
origin_(origin),
tab_id_(tab_id),
auto_join_policy_(auto_join_policy),
data_decoder_(data_decoder),
activity_(activity),
connection_binding_(this),
weak_ptr_factory_(this) {}
CastSessionClient::~CastSessionClient() = default;
mojom::RoutePresentationConnectionPtr CastSessionClient::Init() {
PresentationConnectionPtrInfo renderer_connection;
connection_binding_.Bind(mojo::MakeRequest(&renderer_connection));
auto connection_request = mojo::MakeRequest(&connection_);
connection_->DidChangeState(PresentationConnectionState::CONNECTED);
return mojom::RoutePresentationConnection::New(std::move(renderer_connection),
std::move(connection_request));
}
void CastSessionClient::SendMessageToClient(
PresentationConnectionMessagePtr message) {
connection_->OnMessage(std::move(message));
}
void CastSessionClient::SendMediaStatusToClient(
const base::Value& media_status,
base::Optional<int> request_id) {
// Look up if there is a pending request from this client associated with this
// message. If so, send the media status message as a response by setting the
// sequence number.
base::Optional<int> sequence_number;
if (request_id) {
auto it = pending_media_requests_.find(*request_id);
if (it != pending_media_requests_.end()) {
DVLOG(2) << "Found matching request id: " << *request_id << " -> "
<< it->second;
sequence_number = it->second;
pending_media_requests_.erase(it);
}
}
SendMessageToClient(
CreateV2Message(client_id_, media_status, sequence_number));
}
void CastSessionClient::OnMessage(PresentationConnectionMessagePtr message) {
if (!message->is_message())
return;
data_decoder_->ParseJson(
message->get_message(),
base::BindRepeating(&CastSessionClient::HandleParsedClientMessage,
weak_ptr_factory_.GetWeakPtr()),
base::BindRepeating(&ReportClientMessageParseError,
activity_->route().media_route_id()));
}
void CastSessionClient::DidClose(PresentationConnectionCloseReason reason) {
// TODO(https://crbug.com/809249): Implement close connection with this
// method once we make sure Blink calls this on navigation and on
// PresentationConnection::close().
}
bool CastSessionClient::MatchesAutoJoinPolicy(url::Origin origin,
int tab_id) const {
switch (auto_join_policy_) {
case AutoJoinPolicy::kTabAndOriginScoped:
return origin == origin_ && tab_id == tab_id_;
case AutoJoinPolicy::kOriginScoped:
return origin == origin_;
default:
return false;
}
}
void CastSessionClient::HandleParsedClientMessage(
std::unique_ptr<base::Value> message) {
std::unique_ptr<CastInternalMessage> cast_message =
CastInternalMessage::From(std::move(*message));
if (!cast_message) {
ReportClientMessageParseError(activity_->route().media_route_id(),
"Not a Cast message");
DLOG(ERROR) << "Received non-Cast message from client";
return;
}
if (cast_message->client_id != client_id_) {
DLOG(ERROR) << "Client ID mismatch: expected: " << client_id_
<< ", got: " << cast_message->client_id;
return;
}
if (cast_message->has_session_id() &&
cast_message->session_id() != activity_->session_id()) {
DLOG(ERROR) << "Session ID mismatch: expected: "
<< activity_->session_id().value_or("<missing>")
<< ", got: " << cast_message->session_id();
return;
}
switch (cast_message->type) {
case CastInternalMessage::Type::kAppMessage:
// Send an ACK message back to SDK client to indicate it is handled.
if (activity_->SendAppMessageToReceiver(*cast_message) ==
cast_channel::Result::kOk) {
DCHECK(cast_message->sequence_number);
SendMessageToClient(CreateAppMessageAck(
cast_message->client_id, *cast_message->sequence_number));
}
break;
case CastInternalMessage::Type::kV2Message:
HandleV2ProtocolMessage(*cast_message);
break;
case CastInternalMessage::Type::kLeaveSession:
SendMessageToClient(CreateLeaveSessionAckMessage(
client_id_, cast_message->sequence_number));
activity_->HandleLeaveSession(client_id_);
break;
default:
DLOG(ERROR) << "Unhandled message type: "
<< static_cast<int>(cast_message->type);
}
}
void CastSessionClient::HandleV2ProtocolMessage(
const CastInternalMessage& cast_message) {
const std::string& type_str = cast_message.v2_message_type();
cast_channel::V2MessageType type =
cast_channel::V2MessageTypeFromString(type_str);
if (cast_channel::IsMediaRequestMessageType(type)) {
DVLOG(2) << "Got media command from client: " << type_str;
base::Optional<int> request_id =
activity_->SendMediaRequestToReceiver(cast_message);
if (request_id) {
DCHECK(cast_message.sequence_number);
if (pending_media_requests_.size() >= kMaxPendingMediaRequests) {
// Delete old pending requests. Request IDs are generated sequentially,
// so this should always delete the oldest requests. Deleting requests
// is O(n) in the size of the table, so we delete half the outstanding
// requests at once so the amortized deletion cost is O(1).
pending_media_requests_.erase(pending_media_requests_.begin(),
pending_media_requests_.begin() +
pending_media_requests_.size() / 2);
}
pending_media_requests_.emplace(*request_id,
*cast_message.sequence_number);
}
} else if (type == cast_channel::V2MessageType::kSetVolume) {
DVLOG(2) << "Got volume command from client";
DCHECK(cast_message.sequence_number);
activity_->SendSetVolumeRequestToReceiver(
cast_message, base::BindOnce(&CastSessionClient::SendResultResponse,
weak_ptr_factory_.GetWeakPtr(),
*cast_message.sequence_number));
} else if (type == cast_channel::V2MessageType::kStop) {
// TODO(jrw): implement STOP_SESSION.
DVLOG(2) << "Ignoring stop-session (" << type_str << ") message";
} else {
DLOG(ERROR) << "Unknown v2 message type: " << type_str;
}
}
void CastSessionClient::SendResultResponse(int sequence_number,
cast_channel::Result result) {
// TODO(jrw): Send error message on failure.
if (result == cast_channel::Result::kOk) {
// Send an empty message to let the client know the request succeeded.
SendMessageToClient(
CreateV2Message(client_id_, base::Value(), sequence_number));
}
}
void CastSessionClient::CloseConnection(
PresentationConnectionCloseReason close_reason) {
if (connection_)
connection_->DidClose(close_reason);
TearDownPresentationConnection();
}
void CastSessionClient::TerminateConnection() {
if (connection_) {
connection_->DidChangeState(PresentationConnectionState::TERMINATED);
}
TearDownPresentationConnection();
}
void CastSessionClient::TearDownPresentationConnection() {
connection_.reset();
connection_binding_.Close();
}
} // namespace media_router
// Copyright 2019 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.
#ifndef CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_SESSION_CLIENT_H_
#define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_SESSION_CLIENT_H_
#include <memory>
#include <string>
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "chrome/browser/media/router/providers/cast/cast_session_tracker.h"
#include "chrome/common/media_router/mojo/media_router.mojom.h"
#include "chrome/common/media_router/providers/cast/cast_media_source.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "url/origin.h"
namespace media_router {
class CastActivityRecord;
class DataDecoder;
// Represents a Cast SDK client connection to a Cast session. This class
// contains PresentationConnection Mojo pipes to send and receive messages
// from/to the corresponding SDK client hosted in a presentation controlling
// frame in Blink.
class CastSessionClient : public blink::mojom::PresentationConnection {
public:
CastSessionClient(const std::string& client_id,
const url::Origin& origin,
int tab_id,
AutoJoinPolicy auto_join_policy,
DataDecoder* data_decoder,
CastActivityRecord* activity);
~CastSessionClient() override;
const std::string& client_id() const { return client_id_; }
const base::Optional<std::string>& session_id() const { return session_id_; }
const url::Origin& origin() const { return origin_; }
int tab_id() { return tab_id_; }
// Initializes the PresentationConnection Mojo message pipes and returns the
// handles of the two pipes to be held by Blink. Also transitions the
// connection state to CONNECTED. This method can only be called once, and
// must be called before |SendMessageToClient()|.
mojom::RoutePresentationConnectionPtr Init();
// Sends |message| to the Cast SDK client in Blink.
void SendMessageToClient(
blink::mojom::PresentationConnectionMessagePtr message);
// Sends a media status message to the client. If |request_id| is given, it
// is used to look up the sequence number of a previous request, which is
// included in the outgoing message.
void SendMediaStatusToClient(const base::Value& media_status,
base::Optional<int> request_id);
// Changes the PresentationConnection state to CLOSED/TERMINATED and resets
// PresentationConnection message pipes.
void CloseConnection(
blink::mojom::PresentationConnectionCloseReason close_reason);
void TerminateConnection();
// blink::mojom::PresentationConnection implementation
void OnMessage(
blink::mojom::PresentationConnectionMessagePtr message) override;
// Blink does not initiate state change or close using PresentationConnection.
// Instead, |PresentationService::Close/TerminateConnection| is used.
void DidChangeState(
blink::mojom::PresentationConnectionState state) override {}
void DidClose(
blink::mojom::PresentationConnectionCloseReason reason) override;
// Tests whether the specified origin and tab ID match this session's origin
// and tab ID to the extent required by this sesssion's auto-join policy.
// Depending on the value of |auto_join_policy_|, |origin|, |tab_id|, or both
// may be ignored.
//
// TODO(jrw): It appears the real purpose of this method is to detect whether
// this session was created by an auto-join request, but auto-joining isn't
// implemented yet. This comment should probably be updated once auto-join is
// implemented and I've verified this method does what I think it does.
// Alternatively, it might make more sense to record at session creation time
// whether a particular session was created by an auto-join request, in which
// case I believe this method would no longer be needed.
bool MatchesAutoJoinPolicy(url::Origin origin, int tab_id) const;
private:
void HandleParsedClientMessage(std::unique_ptr<base::Value> message);
void HandleV2ProtocolMessage(const CastInternalMessage& cast_message);
// Resets the PresentationConnection Mojo message pipes.
void TearDownPresentationConnection();
// Sends a response to the client indicating that a particular request
// succeeded or failed.
void SendResultResponse(int sequence_number, cast_channel::Result result);
std::string client_id_;
base::Optional<std::string> session_id_;
// The origin and tab ID parameters originally passed to the CreateRoute
// method of the MediaRouteProvider Mojo interface.
url::Origin origin_;
int tab_id_;
const AutoJoinPolicy auto_join_policy_;
DataDecoder* const data_decoder_;
CastActivityRecord* const activity_;
// The maximum number of pending media requests, used to prevent memory leaks.
// Normally the number of pending requests should be fairly small, but each
// entry only consumes 2*sizeof(int) bytes, so the upper limit is set fairly
// high.
static constexpr std::size_t kMaxPendingMediaRequests = 1024;
// Maps internal, locally-generated request IDs to sequence numbers from cast
// messages received from the client. Used to set an appropriate
// sequenceNumber field in outgoing messages so a client can associate a media
// status message with a previous request.
//
// TODO(jrw): Investigate whether this mapping is really necessary, or if
// sequence numbers can be used directly without generating request IDs.
base::flat_map<int, int> pending_media_requests_;
// Binding for the PresentationConnection in Blink to receive incoming
// messages and respond to state changes.
mojo::Binding<blink::mojom::PresentationConnection> connection_binding_;
// Mojo message pipe to PresentationConnection in Blink to send messages and
// initiate state changes.
blink::mojom::PresentationConnectionPtr connection_;
base::WeakPtrFactory<CastSessionClient> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CastSessionClient);
};
} // namespace media_router
#endif // CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_SESSION_CLIENT_H_
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_SESSION_TRACKER_H_ #ifndef CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_SESSION_TRACKER_H_
#define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_SESSION_TRACKER_H_ #define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_SESSION_TRACKER_H_
#include "base/containers/flat_map.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment