Commit 698d3431 authored by John Williams's avatar John Williams Committed by Commit Bot

[Cast MRP] Refactored to streamline unit tests.

This patch as a number of changes to streamline unit tests; the main
on is that it names ActivityRecord::SetOrUpdateSession() a nonvirtual
method and delegates subclass-specific functionality to the new
OnSessionSet() and OnSessionUpdated() methods.

Change-Id: I3ce0c0ced968d3e3945ecd215dfe9a25959a49a1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2278138
Commit-Queue: John Williams <jrw@chromium.org>
Reviewed-by: default avatarTakumi Fujimoto <takumif@chromium.org>
Cr-Commit-Position: refs/heads/master@{#786504}
parent 8dfe34d4
...@@ -73,10 +73,10 @@ void ActivityRecord::SetOrUpdateSession(const CastSession& session, ...@@ -73,10 +73,10 @@ void ActivityRecord::SetOrUpdateSession(const CastSession& session,
sink_ = sink; sink_ = sink;
if (session_id_) { if (session_id_) {
DCHECK_EQ(*session_id_, session.session_id()); DCHECK_EQ(*session_id_, session.session_id());
OnSessionUpdated(session, hash_token);
} else { } else {
session_id_ = session.session_id(); session_id_ = session.session_id();
if (on_session_set_) OnSessionSet(session);
std::move(on_session_set_).Run();
} }
} }
...@@ -175,6 +175,9 @@ void ActivityRecord::HandleLeaveSession(const std::string& client_id) { ...@@ -175,6 +175,9 @@ void ActivityRecord::HandleLeaveSession(const std::string& client_id) {
} }
} }
void ActivityRecord::OnSessionUpdated(const CastSession& session,
const std::string& hash_token) {}
CastSessionClientFactoryForTest* ActivityRecord::client_factory_for_test_ = CastSessionClientFactoryForTest* ActivityRecord::client_factory_for_test_ =
nullptr; nullptr;
......
...@@ -74,9 +74,9 @@ class ActivityRecord { ...@@ -74,9 +74,9 @@ class ActivityRecord {
// //
// The |hash_token| parameter is used for hashing receiver IDs in messages // 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|. // sent to the Cast SDK, and |sink| is the sink associated with |session|.
virtual void SetOrUpdateSession(const CastSession& session, void SetOrUpdateSession(const CastSession& session,
const MediaSinkInternal& sink, const MediaSinkInternal& sink,
const std::string& hash_token); const std::string& hash_token);
virtual void SendStopSessionMessageToClients(const std::string& hash_token); virtual void SendStopSessionMessageToClients(const std::string& hash_token);
...@@ -144,20 +144,25 @@ class ActivityRecord { ...@@ -144,20 +144,25 @@ class ActivityRecord {
client_factory_for_test_ = factory; client_factory_for_test_ = factory;
} }
void SetSessionAndSinkForTest(const CastSession& session, void SetSessionIdForTest(const std::string& session_id) {
const MediaSinkInternal& sink, session_id_ = session_id;
const std::string& hash_code) {
session_id_ = session.session_id();
sink_ = sink;
} }
protected: protected:
using ClientMap = using ClientMap =
base::flat_map<std::string, std::unique_ptr<CastSessionClient>>; base::flat_map<std::string, std::unique_ptr<CastSessionClient>>;
// Gets the session associated with this activity. May return nullptr. // Gets the session based on its ID. May return null.
CastSession* GetSession() const; CastSession* GetSession() const;
// Called after the session has been set by SetOrUpdateSession. The |session|
// parameters are somewhat redundant because the same information is available
// using the GetSession() method, but passing the parameter avoids some
// unnecessary lookups and eliminates the need to a null check.
virtual void OnSessionSet(const CastSession& session) = 0;
virtual void OnSessionUpdated(const CastSession& session,
const std::string& hash_token);
CastSessionClient* GetClient(const std::string& client_id) { CastSessionClient* GetClient(const std::string& client_id) {
auto it = connected_clients_.find(client_id); auto it = connected_clients_.find(client_id);
return it == connected_clients_.end() ? nullptr : it->second.get(); return it == connected_clients_.end() ? nullptr : it->second.get();
...@@ -169,9 +174,6 @@ class ActivityRecord { ...@@ -169,9 +174,6 @@ class ActivityRecord {
std::string app_id_; std::string app_id_;
base::Optional<int> mirroring_tab_id_; base::Optional<int> mirroring_tab_id_;
// Called when a session is initially set from SetOrUpdateSession().
base::OnceCallback<void()> on_session_set_;
// TODO(https://crbug.com/809249): Consider wrapping CastMessageHandler with // TODO(https://crbug.com/809249): Consider wrapping CastMessageHandler with
// known parameters (sink, client ID, session transport ID) and passing them // known parameters (sink, client ID, session transport ID) and passing them
// to objects that need to send messages to the receiver. // to objects that need to send messages to the receiver.
......
...@@ -161,8 +161,8 @@ void CastActivityManager::LaunchSessionParsed( ...@@ -161,8 +161,8 @@ void CastActivityManager::LaunchSessionParsed(
activity_it->second->route().media_route_id(); activity_it->second->route().media_route_id();
// We cannot launch the new session in the TerminateSession() callback // We cannot launch the new session in the TerminateSession() callback
// because if we create a session there, then it may get deleted when // because if we create a session there, then it may get deleted when
// OnSessionRemoved() is called to notify that the previous session was // OnSessionRemoved() is called to notify that the previous session
// removed on the receiver. // was removed on the receiver.
TerminateSession(existing_route_id, base::DoNothing()); TerminateSession(existing_route_id, base::DoNothing());
// The new session will be launched when OnSessionRemoved() is called for // The new session will be launched when OnSessionRemoved() is called for
// the old session. // the old session.
...@@ -487,8 +487,7 @@ ActivityRecord* CastActivityManager::AddMirroringActivityRecord( ...@@ -487,8 +487,7 @@ ActivityRecord* CastActivityManager::AddMirroringActivityRecord(
: std::make_unique<MirroringActivityRecord>( : std::make_unique<MirroringActivityRecord>(
route, app_id, message_handler_, session_tracker_, tab_id, route, app_id, message_handler_, session_tracker_, tab_id,
cast_data, std::move(on_stop)); cast_data, std::move(on_stop));
if (route.is_local()) activity->CreateMojoBindings(media_router_);
activity->CreateMojoBindings(media_router_);
auto* const activity_ptr = activity.get(); auto* const activity_ptr = activity.get();
activities_.emplace(route.media_route_id(), std::move(activity)); activities_.emplace(route.media_route_id(), std::move(activity));
return activity_ptr; return activity_ptr;
......
...@@ -72,6 +72,8 @@ constexpr char kAppParams[] = R"( ...@@ -72,6 +72,8 @@ constexpr char kAppParams[] = R"(
} }
} }
)"; )";
constexpr char kPresentationId[] = "presentationId";
constexpr char kPresentationId2[] = "presentationId2";
std::string MakeSourceId(const std::string& app_id = kAppId1, std::string MakeSourceId(const std::string& app_id = kAppId1,
const std::string& app_params = "") { const std::string& app_params = "") {
...@@ -115,17 +117,8 @@ class MockMirroringActivityRecord : public MirroringActivityRecord { ...@@ -115,17 +117,8 @@ class MockMirroringActivityRecord : public MirroringActivityRecord {
CastSinkExtraData(), CastSinkExtraData(),
std::move(on_stop)) {} std::move(on_stop)) {}
void set_session_id(const std::string& new_id) { MOCK_METHOD(void, CreateMojoBindings, (mojom::MediaRouter * media_router));
if (!session_id_) MOCK_METHOD(void, OnSessionSet, (const CastSession& session));
session_id_ = new_id;
ASSERT_EQ(session_id_, new_id);
}
MOCK_METHOD1(CreateMojoBindings, void(mojom::MediaRouter* media_router));
MOCK_METHOD3(SetOrUpdateSession,
void(const CastSession& session,
const MediaSinkInternal& sink,
const std::string& hash_token));
}; };
} // namespace } // namespace
...@@ -183,12 +176,8 @@ class CastActivityManagerTest : public testing::Test, ...@@ -183,12 +176,8 @@ class CastActivityManagerTest : public testing::Test,
const MediaRoute& route, const MediaRoute& route,
const std::string& app_id) override { const std::string& app_id) override {
auto activity = std::make_unique<MockCastActivityRecord>(route, app_id); auto activity = std::make_unique<MockCastActivityRecord>(route, app_id);
ON_CALL(*activity, SetOrUpdateSession) cast_activity_ = activity.get();
.WillByDefault( activity_record_callback_.Run(activity.get());
Invoke(activity.get(), &ActivityRecord::SetSessionAndSinkForTest));
auto* activity_ptr = activity.get();
cast_activities_.push_back(activity_ptr);
activity_record_callback_.Run(activity_ptr);
return activity; return activity;
} }
...@@ -199,9 +188,6 @@ class CastActivityManagerTest : public testing::Test, ...@@ -199,9 +188,6 @@ class CastActivityManagerTest : public testing::Test,
MirroringActivityRecord::OnStopCallback on_stop) override { MirroringActivityRecord::OnStopCallback on_stop) override {
auto activity = std::make_unique<MockMirroringActivityRecord>( auto activity = std::make_unique<MockMirroringActivityRecord>(
route, app_id, std::move(on_stop)); route, app_id, std::move(on_stop));
ON_CALL(*activity, SetOrUpdateSession)
.WillByDefault(
Invoke(activity.get(), &ActivityRecord::SetSessionAndSinkForTest));
mirroring_activity_ = activity.get(); mirroring_activity_ = activity.get();
return activity; return activity;
} }
...@@ -263,7 +249,7 @@ class CastActivityManagerTest : public testing::Test, ...@@ -263,7 +249,7 @@ class CastActivityManagerTest : public testing::Test,
// Callback will be invoked synchronously. // Callback will be invoked synchronously.
manager_->LaunchSession( manager_->LaunchSession(
*source, sink_, "presentationId", origin_, kTabId, *source, sink_, kPresentationId, origin_, kTabId,
/*incognito*/ false, /*incognito*/ false,
base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess, base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess,
base::Unretained(this))); base::Unretained(this)));
...@@ -288,8 +274,10 @@ class CastActivityManagerTest : public testing::Test, ...@@ -288,8 +274,10 @@ class CastActivityManagerTest : public testing::Test,
// (3) Route list will be updated. // (3) Route list will be updated.
// TODO(jrw): Check more params. // TODO(jrw): Check more params.
EXPECT_CALL(*cast_activities_[0], SendMessageToClient("theClientId", _)); EXPECT_CALL(*cast_activity_, SendMessageToClient("theClientId", _));
EXPECT_CALL(*cast_activities_[0], SetOrUpdateSession(_, sink_, _)); EXPECT_CALL(*cast_activity_, OnSessionSet).WillOnce([this]() {
EXPECT_EQ(sink_, cast_activity_->sink());
});
EXPECT_CALL(message_handler_, EXPECT_CALL(message_handler_,
EnsureConnection(kChannelId, "theClientId", "theTransportId")); EnsureConnection(kChannelId, "theClientId", "theTransportId"));
...@@ -303,11 +291,20 @@ class CastActivityManagerTest : public testing::Test, ...@@ -303,11 +291,20 @@ class CastActivityManagerTest : public testing::Test,
RunUntilIdle(); RunUntilIdle();
} }
void TerminateSession(bool expect_success) { void ExpectCastActivityStopped(int times = 1) {
EXPECT_CALL(*cast_activities_[0], SendStopSessionMessageToClients); EXPECT_CALL(*cast_activity_, SendStopSessionMessageToClients).Times(times);
if (times == 0) {
EXPECT_CALL(message_handler_, StopSession).Times(0);
} else {
// TODO(jrw): Check other parameters
EXPECT_CALL(message_handler_, StopSession(kChannelId, _, _, _))
.Times(times);
}
}
// TODO(jrw): Check parameters void TerminateSession(bool expect_success) {
EXPECT_CALL(message_handler_, StopSession(kChannelId, _, _, _)); ExpectCastActivityStopped();
if (expect_success) { if (expect_success) {
ExpectEmptyRouteUpdate(); ExpectEmptyRouteUpdate();
...@@ -323,8 +320,7 @@ class CastActivityManagerTest : public testing::Test, ...@@ -323,8 +320,7 @@ class CastActivityManagerTest : public testing::Test,
void TerminateNoSession() { void TerminateNoSession() {
// Stop session message not sent because session has not launched yet. // Stop session message not sent because session has not launched yet.
EXPECT_CALL(*cast_activities_[0], SendStopSessionMessageToClients).Times(0); ExpectCastActivityStopped(0);
EXPECT_CALL(message_handler_, StopSession).Times(0);
ExpectNoRouteUpdate(); ExpectNoRouteUpdate();
manager_->TerminateSession(route_->media_route_id(), manager_->TerminateSession(route_->media_route_id(),
MakeTerminateRouteCallback(true)); MakeTerminateRouteCallback(true));
...@@ -394,13 +390,13 @@ class CastActivityManagerTest : public testing::Test, ...@@ -394,13 +390,13 @@ class CastActivityManagerTest : public testing::Test,
cast_channel::MockCastMessageHandler message_handler_; cast_channel::MockCastMessageHandler message_handler_;
MediaSinkInternal sink_ = CreateCastSink(kChannelId); MediaSinkInternal sink_ = CreateCastSink(kChannelId);
MediaSinkInternal sink2_ = CreateCastSink(kChannelId2); MediaSinkInternal sink2_ = CreateCastSink(kChannelId2);
std::unique_ptr<MediaRoute> route_; // TODO(jrw): Is this needed? std::unique_ptr<MediaRoute> route_;
cast_channel::LaunchSessionCallback launch_session_callback_; cast_channel::LaunchSessionCallback launch_session_callback_;
TestMediaSinkService media_sink_service_; TestMediaSinkService media_sink_service_;
MockCastAppDiscoveryService app_discovery_service_; MockCastAppDiscoveryService app_discovery_service_;
std::unique_ptr<CastActivityManager> manager_; std::unique_ptr<CastActivityManager> manager_;
std::unique_ptr<CastSessionTracker> session_tracker_; std::unique_ptr<CastSessionTracker> session_tracker_;
std::vector<MockCastActivityRecord*> cast_activities_; MockCastActivityRecord* cast_activity_ = nullptr;
MockMirroringActivityRecord* mirroring_activity_ = nullptr; MockMirroringActivityRecord* mirroring_activity_ = nullptr;
MockCastActivityRecordCallback activity_record_callback_ = base::DoNothing(); MockCastActivityRecordCallback activity_record_callback_ = base::DoNothing();
const url::Origin origin_ = url::Origin::Create(GURL(kOrigin)); const url::Origin origin_ = url::Origin::Create(GURL(kOrigin));
...@@ -449,7 +445,7 @@ TEST_F(CastActivityManagerTest, LaunchSessionFails) { ...@@ -449,7 +445,7 @@ TEST_F(CastActivityManagerTest, LaunchSessionFails) {
CallLaunchSession(); CallLaunchSession();
EXPECT_CALL( EXPECT_CALL(
*cast_activities_[0], *cast_activity_,
ClosePresentationConnections( ClosePresentationConnections(
blink::mojom::PresentationConnectionCloseReason::CONNECTION_ERROR)); blink::mojom::PresentationConnectionCloseReason::CONNECTION_ERROR));
...@@ -469,7 +465,7 @@ TEST_F(CastActivityManagerTest, LaunchCastAppSessionFailsWithAppParams) { ...@@ -469,7 +465,7 @@ TEST_F(CastActivityManagerTest, LaunchCastAppSessionFailsWithAppParams) {
// Callback will be invoked synchronously. // Callback will be invoked synchronously.
manager_->LaunchSession( manager_->LaunchSession(
*source, sink_, "presentationId", origin_, kTabId, *source, sink_, kPresentationId, origin_, kTabId,
/*incognito*/ false, /*incognito*/ false,
base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionFailure, base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionFailure,
base::Unretained(this))); base::Unretained(this)));
...@@ -479,8 +475,7 @@ TEST_F(CastActivityManagerTest, LaunchCastAppSessionFailsWithAppParams) { ...@@ -479,8 +475,7 @@ TEST_F(CastActivityManagerTest, LaunchCastAppSessionFailsWithAppParams) {
TEST_F(CastActivityManagerTest, LaunchSessionTerminatesExistingSessionOnSink) { TEST_F(CastActivityManagerTest, LaunchSessionTerminatesExistingSessionOnSink) {
LaunchCastAppSession(); LaunchCastAppSession();
ExpectCastActivityStopped();
EXPECT_CALL(*cast_activities_[0], SendStopSessionMessageToClients);
{ {
testing::InSequence dummy; testing::InSequence dummy;
...@@ -500,7 +495,7 @@ TEST_F(CastActivityManagerTest, LaunchSessionTerminatesExistingSessionOnSink) { ...@@ -500,7 +495,7 @@ TEST_F(CastActivityManagerTest, LaunchSessionTerminatesExistingSessionOnSink) {
// LaunchSessionParsed() is called asynchronously and will fail the test. // LaunchSessionParsed() is called asynchronously and will fail the test.
manager_->LaunchSessionParsed( manager_->LaunchSessionParsed(
// TODO(jrw): Verify that presentation ID is used correctly. // TODO(jrw): Verify that presentation ID is used correctly.
*source, sink_, "presentationId2", origin_, kTabId2, /*incognito*/ *source, sink_, kPresentationId2, origin_, kTabId2, /*incognito*/
false, false,
base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess, base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess,
base::Unretained(this)), base::Unretained(this)),
...@@ -520,15 +515,14 @@ TEST_F(CastActivityManagerTest, LaunchSessionTerminatesExistingSessionOnSink) { ...@@ -520,15 +515,14 @@ TEST_F(CastActivityManagerTest, LaunchSessionTerminatesExistingSessionOnSink) {
TEST_F(CastActivityManagerTest, LaunchSessionTerminatesExistingSessionFromTab) { TEST_F(CastActivityManagerTest, LaunchSessionTerminatesExistingSessionFromTab) {
LaunchCastAppSession(); LaunchCastAppSession();
ExpectCastActivityStopped();
EXPECT_CALL(*cast_activities_[0], SendStopSessionMessageToClients);
// Launch a new session on the same sink. // Launch a new session on the same sink.
auto source = CastMediaSource::FromMediaSourceId(MakeSourceId(kAppId2)); auto source = CastMediaSource::FromMediaSourceId(MakeSourceId(kAppId2));
// Use LaunchSessionParsed() instead of LaunchSession() here because // Use LaunchSessionParsed() instead of LaunchSession() here because
// LaunchSessionParsed() is called asynchronously and will fail the test. // LaunchSessionParsed() is called asynchronously and will fail the test.
manager_->LaunchSessionParsed( manager_->LaunchSessionParsed(
*source, sink2_, "presentationId2", origin_, kTabId, /*incognito*/ *source, sink2_, kPresentationId2, origin_, kTabId, /*incognito*/
false, false,
base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess, base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess,
base::Unretained(this)), base::Unretained(this)),
...@@ -550,7 +544,9 @@ TEST_F(CastActivityManagerTest, AddRemoveNonLocalActivity) { ...@@ -550,7 +544,9 @@ TEST_F(CastActivityManagerTest, AddRemoveNonLocalActivity) {
TEST_F(CastActivityManagerTest, UpdateNewlyCreatedSession) { TEST_F(CastActivityManagerTest, UpdateNewlyCreatedSession) {
LaunchCastAppSession(); LaunchCastAppSession();
EXPECT_CALL(*cast_activities_[0], SetOrUpdateSession(_, sink_, _)); EXPECT_CALL(*cast_activity_, OnSessionUpdated).WillOnce([this]() {
EXPECT_EQ(sink_, cast_activity_->sink());
});
auto session = MakeSession(kAppId1); auto session = MakeSession(kAppId1);
ExpectSingleRouteUpdate(); ExpectSingleRouteUpdate();
manager_->OnSessionAddedOrUpdated(sink_, *session); manager_->OnSessionAddedOrUpdated(sink_, *session);
...@@ -564,6 +560,9 @@ TEST_F(CastActivityManagerTest, UpdateNewlyCreatedSession) { ...@@ -564,6 +560,9 @@ TEST_F(CastActivityManagerTest, UpdateNewlyCreatedSession) {
// would have failed. // would have failed.
TEST_F(CastActivityManagerTest, UpdateNewlyCreatedMirroringSession) { TEST_F(CastActivityManagerTest, UpdateNewlyCreatedMirroringSession) {
CallLaunchSession(kCastStreamingAppId); CallLaunchSession(kCastStreamingAppId);
EXPECT_CALL(*mirroring_activity_, OnSessionSet).WillOnce([this]() {
EXPECT_EQ(sink_, mirroring_activity_->sink());
});
auto response = GetSuccessLaunchResponse(); auto response = GetSuccessLaunchResponse();
SetSessionForTest(route_->media_sink_id(), SetSessionForTest(route_->media_sink_id(),
CastSession::From(sink_, *response.receiver_status)); CastSession::From(sink_, *response.receiver_status));
...@@ -571,7 +570,6 @@ TEST_F(CastActivityManagerTest, UpdateNewlyCreatedMirroringSession) { ...@@ -571,7 +570,6 @@ TEST_F(CastActivityManagerTest, UpdateNewlyCreatedMirroringSession) {
RunUntilIdle(); RunUntilIdle();
ASSERT_TRUE(mirroring_activity_); ASSERT_TRUE(mirroring_activity_);
EXPECT_CALL(*mirroring_activity_, SetOrUpdateSession(_, sink_, _));
auto session = MakeSession(kCastStreamingAppId); auto session = MakeSession(kCastStreamingAppId);
ExpectSingleRouteUpdate(); ExpectSingleRouteUpdate();
manager_->OnSessionAddedOrUpdated(sink_, *session); manager_->OnSessionAddedOrUpdated(sink_, *session);
...@@ -584,7 +582,7 @@ TEST_F(CastActivityManagerTest, OnSessionAddedOrUpdated) { ...@@ -584,7 +582,7 @@ TEST_F(CastActivityManagerTest, OnSessionAddedOrUpdated) {
LaunchCastAppSession(); LaunchCastAppSession();
auto session = MakeSession(kAppId1); auto session = MakeSession(kAppId1);
ExpectSingleRouteUpdate(); ExpectSingleRouteUpdate();
EXPECT_CALL(*cast_activities_[0], SetOrUpdateSession(_, _, "theHashToken")); EXPECT_CALL(*cast_activity_, OnSessionUpdated(_, "theHashToken"));
manager_->OnSessionAddedOrUpdated(sink_, *session); manager_->OnSessionAddedOrUpdated(sink_, *session);
} }
...@@ -614,8 +612,7 @@ TEST_F(CastActivityManagerTest, AppMessageFromReceiver) { ...@@ -614,8 +612,7 @@ TEST_F(CastActivityManagerTest, AppMessageFromReceiver) {
"urn:x-cast:com.google.foo", base::Value(base::Value::Type::DICTIONARY), "urn:x-cast:com.google.foo", base::Value(base::Value::Type::DICTIONARY),
"sourceId", "theClientId"); "sourceId", "theClientId");
EXPECT_CALL(*cast_activities_[0], EXPECT_CALL(*cast_activity_, OnAppMessage(IsCastChannelMessage(message)));
OnAppMessage(IsCastChannelMessage(message)));
manager_->OnAppMessage(kChannelId, message); manager_->OnAppMessage(kChannelId, message);
} }
...@@ -625,7 +622,7 @@ TEST_F(CastActivityManagerTest, OnMediaStatusUpdated) { ...@@ -625,7 +622,7 @@ TEST_F(CastActivityManagerTest, OnMediaStatusUpdated) {
const char status[] = R"({"foo": "bar"})"; const char status[] = R"({"foo": "bar"})";
base::Optional<int> request_id(345); base::Optional<int> request_id(345);
EXPECT_CALL(*cast_activities_[0], EXPECT_CALL(*cast_activity_,
SendMediaStatusToClients(IsJson(status), request_id)); SendMediaStatusToClients(IsJson(status), request_id));
manager_->OnMediaStatusUpdated(sink_, ParseJson(status), request_id); manager_->OnMediaStatusUpdated(sink_, ParseJson(status), request_id);
} }
......
...@@ -29,15 +29,16 @@ CastActivityRecord::CastActivityRecord( ...@@ -29,15 +29,16 @@ CastActivityRecord::CastActivityRecord(
CastActivityRecord::~CastActivityRecord() = default; CastActivityRecord::~CastActivityRecord() = default;
void CastActivityRecord::SetOrUpdateSession(const CastSession& session, void CastActivityRecord::OnSessionSet(const CastSession& session) {
const MediaSinkInternal& sink, if (media_controller_)
const std::string& hash_token) { media_controller_->SetSession(session);
bool had_session_id = session_id_.has_value(); }
ActivityRecord::SetOrUpdateSession(session, sink, hash_token);
if (had_session_id) { void CastActivityRecord::OnSessionUpdated(const CastSession& session,
for (auto& client : connected_clients_) const std::string& hash_token) {
client.second->SendMessageToClient( for (auto& client : connected_clients_) {
CreateUpdateSessionMessage(session, client.first, sink, hash_token)); client.second->SendMessageToClient(
CreateUpdateSessionMessage(session, client.first, sink_, hash_token));
} }
if (media_controller_) if (media_controller_)
media_controller_->SetSession(session); media_controller_->SetSession(session);
......
...@@ -40,10 +40,6 @@ class CastActivityRecord : public ActivityRecord { ...@@ -40,10 +40,6 @@ class CastActivityRecord : public ActivityRecord {
CastSessionTracker* session_tracker); CastSessionTracker* session_tracker);
~CastActivityRecord() override; ~CastActivityRecord() override;
// ActivityRecord implementation
void SetOrUpdateSession(const CastSession& session,
const MediaSinkInternal& sink,
const std::string& hash_token) override;
void SendMediaStatusToClients(const base::Value& media_status, void SendMediaStatusToClients(const base::Value& media_status,
base::Optional<int> request_id) override; base::Optional<int> request_id) override;
void OnAppMessage(const cast::channel::CastMessage& message) override; void OnAppMessage(const cast::channel::CastMessage& message) override;
...@@ -64,6 +60,9 @@ class CastActivityRecord : public ActivityRecord { ...@@ -64,6 +60,9 @@ class CastActivityRecord : public ActivityRecord {
bool HasJoinableClient(AutoJoinPolicy policy, bool HasJoinableClient(AutoJoinPolicy policy,
const url::Origin& origin, const url::Origin& origin,
int tab_id) const; int tab_id) const;
void OnSessionSet(const CastSession& session) override;
void OnSessionUpdated(const CastSession& session,
const std::string& hash_token) override;
private: private:
friend class CastSessionClientImpl; friend class CastSessionClientImpl;
......
...@@ -71,24 +71,21 @@ class MockPresentationConnection : public blink::mojom::PresentationConnection { ...@@ -71,24 +71,21 @@ class MockPresentationConnection : public blink::mojom::PresentationConnection {
} // namespace } // namespace
#define EXPECT_ERROR_LOG(matcher) \
if (DLOG_IS_ON(ERROR)) { \
EXPECT_CALL(log_, Log(logging::LOG_ERROR, _, _, _, matcher)) \
.WillOnce(Return(true)); /* suppress logging */ \
}
class CastSessionClientImplTest : public testing::Test { class CastSessionClientImplTest : public testing::Test {
public: public:
CastSessionClientImplTest() { activity_.set_session_id("theSessionId"); } CastSessionClientImplTest() { activity_.SetSessionIdForTest("theSessionId"); }
~CastSessionClientImplTest() override { RunUntilIdle(); } ~CastSessionClientImplTest() override { RunUntilIdle(); }
protected: protected:
void RunUntilIdle() { task_environment_.RunUntilIdle(); } void RunUntilIdle() { task_environment_.RunUntilIdle(); }
template <typename T>
void ExpectErrorLog(const T& matcher) {
if (DLOG_IS_ON(ERROR)) {
EXPECT_CALL(log_, Log(logging::LOG_ERROR, _, _, _,
matcher))
.WillOnce(Return(true)); // suppress logging
}
}
content::BrowserTaskEnvironment task_environment_; content::BrowserTaskEnvironment task_environment_;
data_decoder::test::InProcessDataDecoder in_process_data_decoder_; data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
cast_channel::MockCastSocketService socket_service_{ cast_channel::MockCastSocketService socket_service_{
...@@ -111,7 +108,7 @@ class CastSessionClientImplTest : public testing::Test { ...@@ -111,7 +108,7 @@ class CastSessionClientImplTest : public testing::Test {
TEST_F(CastSessionClientImplTest, OnInvalidJson) { TEST_F(CastSessionClientImplTest, OnInvalidJson) {
// TODO(crbug.com/905002): Check UMA calls instead of logging (here and // TODO(crbug.com/905002): Check UMA calls instead of logging (here and
// below). // below).
ExpectErrorLog(HasSubstr("Failed to parse Cast client message")); EXPECT_ERROR_LOG(HasSubstr("Failed to parse Cast client message"));
log_.StartCapturingLogs(); log_.StartCapturingLogs();
client_->OnMessage( client_->OnMessage(
...@@ -119,8 +116,8 @@ TEST_F(CastSessionClientImplTest, OnInvalidJson) { ...@@ -119,8 +116,8 @@ TEST_F(CastSessionClientImplTest, OnInvalidJson) {
} }
TEST_F(CastSessionClientImplTest, OnInvalidMessage) { TEST_F(CastSessionClientImplTest, OnInvalidMessage) {
ExpectErrorLog(AllOf(HasSubstr("Failed to parse Cast client message"), EXPECT_ERROR_LOG(AllOf(HasSubstr("Failed to parse Cast client message"),
HasSubstr("Not a Cast message"))); HasSubstr("Not a Cast message")));
log_.StartCapturingLogs(); log_.StartCapturingLogs();
client_->OnMessage( client_->OnMessage(
...@@ -128,9 +125,9 @@ TEST_F(CastSessionClientImplTest, OnInvalidMessage) { ...@@ -128,9 +125,9 @@ TEST_F(CastSessionClientImplTest, OnInvalidMessage) {
} }
TEST_F(CastSessionClientImplTest, OnMessageWrongClientId) { TEST_F(CastSessionClientImplTest, OnMessageWrongClientId) {
ExpectErrorLog(AllOf(HasSubstr("Client ID mismatch"), EXPECT_ERROR_LOG(AllOf(HasSubstr("Client ID mismatch"),
HasSubstr("theClientId"), HasSubstr("theClientId"),
HasSubstr("theWrongClientId"))); HasSubstr("theWrongClientId")));
log_.StartCapturingLogs(); log_.StartCapturingLogs();
client_->OnMessage( client_->OnMessage(
...@@ -145,9 +142,9 @@ TEST_F(CastSessionClientImplTest, OnMessageWrongClientId) { ...@@ -145,9 +142,9 @@ TEST_F(CastSessionClientImplTest, OnMessageWrongClientId) {
} }
TEST_F(CastSessionClientImplTest, OnMessageWrongSessionId) { TEST_F(CastSessionClientImplTest, OnMessageWrongSessionId) {
ExpectErrorLog(AllOf(HasSubstr("Session ID mismatch"), EXPECT_ERROR_LOG(AllOf(HasSubstr("Session ID mismatch"),
HasSubstr("theSessionId"), HasSubstr("theSessionId"),
HasSubstr("theWrongSessionId"))); HasSubstr("theWrongSessionId")));
log_.StartCapturingLogs(); log_.StartCapturingLogs();
client_->OnMessage( client_->OnMessage(
......
...@@ -142,7 +142,8 @@ MirroringActivityRecord::~MirroringActivityRecord() { ...@@ -142,7 +142,8 @@ MirroringActivityRecord::~MirroringActivityRecord() {
void MirroringActivityRecord::CreateMojoBindings( void MirroringActivityRecord::CreateMojoBindings(
mojom::MediaRouter* media_router) { mojom::MediaRouter* media_router) {
DCHECK(mirroring_type_); if (!mirroring_type_)
return;
// Get a reference to the mirroring service host. // Get a reference to the mirroring service host.
switch (*mirroring_type_) { switch (*mirroring_type_) {
...@@ -165,28 +166,9 @@ void MirroringActivityRecord::CreateMojoBindings( ...@@ -165,28 +166,9 @@ void MirroringActivityRecord::CreateMojoBindings(
break; break;
} }
auto cast_source = CastMediaSource::FromMediaSource(route_.media_source()); DCHECK(!channel_to_service_receiver_);
DCHECK(cast_source); channel_to_service_receiver_ =
channel_to_service_.BindNewPipeAndPassReceiver();
// Derive session type from capabilities and media source.
const bool has_audio = (cast_data_.capabilities &
static_cast<uint8_t>(cast_channel::AUDIO_OUT)) != 0 &&
cast_source->allow_audio_capture();
const bool has_video = (cast_data_.capabilities &
static_cast<uint8_t>(cast_channel::VIDEO_OUT)) != 0;
DCHECK(has_audio || has_video);
const SessionType session_type =
has_audio && has_video
? SessionType::AUDIO_AND_VIDEO
: has_audio ? SessionType::AUDIO_ONLY : SessionType::VIDEO_ONLY;
// Arrange to start mirroring once the session is set.
on_session_set_ = base::BindOnce(
&MirroringActivityRecord::StartMirroring, base::Unretained(this),
SessionParameters::New(session_type, cast_data_.ip_endpoint.address(),
cast_data_.model_name,
cast_source->target_playout_delay()),
channel_to_service_.BindNewPipeAndPassReceiver());
} }
void MirroringActivityRecord::OnError(SessionError error) { void MirroringActivityRecord::OnError(SessionError error) {
...@@ -293,9 +275,25 @@ void MirroringActivityRecord::HandleParseJsonResult( ...@@ -293,9 +275,25 @@ void MirroringActivityRecord::HandleParseJsonResult(
message_handler_->SendCastMessage(cast_data_.cast_channel_id, cast_message); message_handler_->SendCastMessage(cast_data_.cast_channel_id, cast_message);
} }
void MirroringActivityRecord::StartMirroring( void MirroringActivityRecord::OnSessionSet(const CastSession& session) {
mirroring::mojom::SessionParametersPtr session_params, if (!mirroring_type_)
mojo::PendingReceiver<CastMessageChannel> channel_to_service) { return;
auto cast_source = CastMediaSource::FromMediaSource(route_.media_source());
DCHECK(cast_source);
// Derive session type from capabilities and media source.
const bool has_audio = (cast_data_.capabilities &
static_cast<uint8_t>(cast_channel::AUDIO_OUT)) != 0 &&
cast_source->allow_audio_capture();
const bool has_video = (cast_data_.capabilities &
static_cast<uint8_t>(cast_channel::VIDEO_OUT)) != 0;
DCHECK(has_audio || has_video);
const SessionType session_type =
has_audio && has_video
? SessionType::AUDIO_AND_VIDEO
: has_audio ? SessionType::AUDIO_ONLY : SessionType::VIDEO_ONLY;
will_start_mirroring_timestamp_ = base::Time::Now(); will_start_mirroring_timestamp_ = base::Time::Now();
// Bind Mojo receivers for the interfaces this object implements. // Bind Mojo receivers for the interfaces this object implements.
...@@ -304,8 +302,15 @@ void MirroringActivityRecord::StartMirroring( ...@@ -304,8 +302,15 @@ void MirroringActivityRecord::StartMirroring(
mojo::PendingRemote<mirroring::mojom::CastMessageChannel> channel_remote; mojo::PendingRemote<mirroring::mojom::CastMessageChannel> channel_remote;
channel_receiver_.Bind(channel_remote.InitWithNewPipeAndPassReceiver()); channel_receiver_.Bind(channel_remote.InitWithNewPipeAndPassReceiver());
host_->Start(std::move(session_params), std::move(observer_remote), // If this fails, it's probably because CreateMojoBindings() hasn't been
std::move(channel_remote), std::move(channel_to_service)); // called.
DCHECK(channel_to_service_receiver_);
host_->Start(SessionParameters::New(
session_type, cast_data_.ip_endpoint.address(),
cast_data_.model_name, cast_source->target_playout_delay()),
std::move(observer_remote), std::move(channel_remote),
std::move(channel_to_service_receiver_));
} }
void MirroringActivityRecord::StopMirroring() { void MirroringActivityRecord::StopMirroring() {
......
...@@ -66,6 +66,7 @@ class MirroringActivityRecord : public ActivityRecord, ...@@ -66,6 +66,7 @@ class MirroringActivityRecord : public ActivityRecord,
void OnInternalMessage(const cast_channel::InternalMessage& message) override; void OnInternalMessage(const cast_channel::InternalMessage& message) override;
protected: protected:
void OnSessionSet(const CastSession& session) override;
void CreateMediaController( void CreateMediaController(
mojo::PendingReceiver<mojom::MediaController> media_controller, mojo::PendingReceiver<mojom::MediaController> media_controller,
mojo::PendingRemote<mojom::MediaStatusObserver> observer) override; mojo::PendingRemote<mojom::MediaStatusObserver> observer) override;
...@@ -74,9 +75,6 @@ class MirroringActivityRecord : public ActivityRecord, ...@@ -74,9 +75,6 @@ class MirroringActivityRecord : public ActivityRecord,
void HandleParseJsonResult(const std::string& route_id, void HandleParseJsonResult(const std::string& route_id,
data_decoder::DataDecoder::ValueOrError result); data_decoder::DataDecoder::ValueOrError result);
void StartMirroring(
mirroring::mojom::SessionParametersPtr session_params,
mojo::PendingReceiver<CastMessageChannel> channel_to_service);
void StopMirroring(); void StopMirroring();
mojo::Remote<mirroring::mojom::MirroringServiceHost> host_; mojo::Remote<mirroring::mojom::MirroringServiceHost> host_;
...@@ -84,6 +82,11 @@ class MirroringActivityRecord : public ActivityRecord, ...@@ -84,6 +82,11 @@ class MirroringActivityRecord : public ActivityRecord,
// Sends Cast messages from the mirroring receiver to the mirroring service. // Sends Cast messages from the mirroring receiver to the mirroring service.
mojo::Remote<mirroring::mojom::CastMessageChannel> channel_to_service_; mojo::Remote<mirroring::mojom::CastMessageChannel> channel_to_service_;
// Only used to store pending CastMessageChannel receiver while waiting for
// OnSessionSet() to be called.
mojo::PendingReceiver<mirroring::mojom::CastMessageChannel>
channel_to_service_receiver_;
mojo::Receiver<mirroring::mojom::SessionObserver> observer_receiver_{this}; mojo::Receiver<mirroring::mojom::SessionObserver> observer_receiver_{this};
// To handle Cast messages from the mirroring service to the mirroring // To handle Cast messages from the mirroring service to the mirroring
......
...@@ -21,12 +21,6 @@ class MockCastActivityRecord : public CastActivityRecord { ...@@ -21,12 +21,6 @@ class MockCastActivityRecord : public CastActivityRecord {
MockCastActivityRecord(const MediaRoute& route, const std::string& app_id); MockCastActivityRecord(const MediaRoute& route, const std::string& app_id);
~MockCastActivityRecord() override; ~MockCastActivityRecord() override;
void set_session_id(const std::string& new_id) {
if (!session_id_)
session_id_ = new_id;
ASSERT_EQ(session_id_, new_id);
}
MOCK_METHOD1(SendAppMessageToReceiver, MOCK_METHOD1(SendAppMessageToReceiver,
cast_channel::Result(const CastInternalMessage& cast_message)); cast_channel::Result(const CastInternalMessage& cast_message));
MOCK_METHOD1(SendMediaRequestToReceiver, MOCK_METHOD1(SendMediaRequestToReceiver,
...@@ -47,10 +41,9 @@ class MockCastActivityRecord : public CastActivityRecord { ...@@ -47,10 +41,9 @@ class MockCastActivityRecord : public CastActivityRecord {
const url::Origin& origin, const url::Origin& origin,
int tab_id)); int tab_id));
MOCK_METHOD1(RemoveClient, void(const std::string& client_id)); MOCK_METHOD1(RemoveClient, void(const std::string& client_id));
MOCK_METHOD3(SetOrUpdateSession, MOCK_METHOD1(OnSessionSet, void(const CastSession& session));
void(const CastSession& session, MOCK_METHOD2(OnSessionUpdated,
const MediaSinkInternal& sink, void(const CastSession& session, const std::string& hash_token));
const std::string& hash_token));
MOCK_METHOD2(SendMessageToClient, MOCK_METHOD2(SendMessageToClient,
void(const std::string& client_id, void(const std::string& client_id,
blink::mojom::PresentationConnectionMessagePtr message)); blink::mojom::PresentationConnectionMessagePtr message));
......
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