cast_message_handler_unittest.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/cast_channel/cast_message_handler.h"
  5. #include <string>
  6. #include "base/bind.h"
  7. #include "base/callback_helpers.h"
  8. #include "base/json/json_reader.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/run_loop.h"
  11. #include "base/strings/string_number_conversions.h"
  12. #include "base/strings/stringprintf.h"
  13. #include "base/test/mock_callback.h"
  14. #include "base/test/task_environment.h"
  15. #include "base/test/test_simple_task_runner.h"
  16. #include "base/test/values_test_util.h"
  17. #include "components/cast_channel/cast_message_util.h"
  18. #include "components/cast_channel/cast_test_util.h"
  19. #include "content/public/test/browser_task_environment.h"
  20. #include "services/data_decoder/public/cpp/data_decoder.h"
  21. #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
  22. #include "testing/gmock/include/gmock/gmock.h"
  23. #include "testing/gtest/include/gtest/gtest.h"
  24. using base::test::IsJson;
  25. using base::test::ParseJson;
  26. using testing::_;
  27. using testing::AnyNumber;
  28. using testing::InSequence;
  29. using testing::Return;
  30. using testing::SaveArg;
  31. using testing::WithArg;
  32. namespace cast_channel {
  33. namespace {
  34. constexpr char kAppId1[] = "0F5096E8";
  35. constexpr char kAppId2[] = "85CDB22F";
  36. constexpr char kTestUserAgentString[] =
  37. "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) "
  38. "Chrome/66.0.3331.0 Safari/537.36";
  39. constexpr char kSessionId[] = "theSessionId";
  40. constexpr char kSourceId[] = "theSourceId";
  41. constexpr char kDestinationId[] = "theDestinationId";
  42. constexpr char kAppParams[] = R"(
  43. {
  44. "requiredFeatures" : ["STREAM_TRANSFER"],
  45. "launchCheckerParams" : {
  46. "credentialsData" : {
  47. "credentialsType" : "mobile",
  48. "credentials" : "99843n2idsguyhga"
  49. }
  50. }
  51. }
  52. )";
  53. constexpr int kMaxProtocolMessageSize = 64 * 1024;
  54. data_decoder::DataDecoder::ValueOrError ParseJsonLikeDataDecoder(
  55. base::StringPiece json) {
  56. return ParseJson(json);
  57. }
  58. absl::optional<base::Value::Dict> GetDictionaryFromCastMessage(
  59. const CastMessage& message) {
  60. if (!message.has_payload_utf8())
  61. return absl::nullopt;
  62. absl::optional<base::Value> value =
  63. base::JSONReader::Read(message.payload_utf8());
  64. if (!value || !value->is_dict())
  65. return absl::nullopt;
  66. return std::move(value->GetDict());
  67. }
  68. CastMessageType GetMessageType(const CastMessage& message) {
  69. absl::optional<base::Value::Dict> dict =
  70. GetDictionaryFromCastMessage(message);
  71. if (!dict)
  72. return CastMessageType::kOther;
  73. const std::string* message_type = dict->FindString("type");
  74. if (!message_type)
  75. return CastMessageType::kOther;
  76. return CastMessageTypeFromString(*message_type);
  77. }
  78. MATCHER_P(HasMessageType, type, "") {
  79. return GetMessageType(arg) == type;
  80. }
  81. MATCHER_P(HasPayloadUtf8, payload, "") {
  82. return arg.payload_utf8() == payload;
  83. }
  84. } // namespace
  85. class CastMessageHandlerTest : public testing::Test {
  86. public:
  87. CastMessageHandlerTest()
  88. : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
  89. cast_socket_service_(new base::TestSimpleTaskRunner()),
  90. handler_(
  91. &cast_socket_service_,
  92. base::BindRepeating(&data_decoder::DataDecoder::ParseJsonIsolated),
  93. kTestUserAgentString,
  94. "66.0.3331.0",
  95. "en-US") {
  96. ON_CALL(cast_socket_service_, GetSocket(testing::Matcher<int>(_)))
  97. .WillByDefault(testing::Return(&cast_socket_));
  98. }
  99. CastMessageHandlerTest(const CastMessageHandlerTest&) = delete;
  100. CastMessageHandlerTest& operator=(const CastMessageHandlerTest&) = delete;
  101. ~CastMessageHandlerTest() override = default;
  102. void OnMessage(const CastMessage& message) {
  103. handler_.OnMessage(cast_socket_, message);
  104. }
  105. void OnError(ChannelError error) { handler_.OnError(cast_socket_, error); }
  106. void OnAppAvailability(const std::string& app_id,
  107. GetAppAvailabilityResult result) {
  108. if (run_loop_)
  109. run_loop_->Quit();
  110. DoOnAppAvailability(app_id, result);
  111. }
  112. MOCK_METHOD2(DoOnAppAvailability,
  113. void(const std::string& app_id,
  114. GetAppAvailabilityResult result));
  115. void ExpectSessionLaunchResult(LaunchSessionResponse::Result expected_result,
  116. LaunchSessionResponse response) {
  117. if (run_loop_)
  118. run_loop_->Quit();
  119. ++session_launch_response_count_;
  120. EXPECT_EQ(expected_result, response.result);
  121. if (response.result == LaunchSessionResponse::Result::kOk)
  122. EXPECT_TRUE(response.receiver_status);
  123. }
  124. void ExpectEnsureConnection() {
  125. EXPECT_CALL(*transport_,
  126. SendMessage_(HasMessageType(CastMessageType::kConnect), _));
  127. }
  128. void ExpectEnsureConnectionThen(CastMessageType next_type,
  129. int request_count = 1) {
  130. InSequence dummy;
  131. ExpectEnsureConnection();
  132. EXPECT_CALL(*transport_, SendMessage_(HasMessageType(next_type), _))
  133. .Times(request_count)
  134. .WillRepeatedly(SaveArg<0>(&last_request_));
  135. }
  136. void CreatePendingRequests() {
  137. EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(AnyNumber());
  138. handler_.LaunchSession(channel_id_, kAppId1, base::TimeDelta::Max(),
  139. {"WEB"}, /* appParams */ absl::nullopt,
  140. launch_session_callback_.Get());
  141. for (int i = 0; i < 2; i++) {
  142. handler_.RequestAppAvailability(&cast_socket_, kAppId1,
  143. get_app_availability_callback_.Get());
  144. handler_.SendSetVolumeRequest(
  145. channel_id_,
  146. ParseJson(R"({"sessionId": "theSessionId", "type": "SET_VOLUME"})"),
  147. kSourceId, set_volume_callback_.Get());
  148. }
  149. handler_.StopSession(channel_id_, kSessionId, kSourceId,
  150. stop_session_callback_.Get());
  151. }
  152. void SendMessageAndExpectConnection(const std::string& destination_id,
  153. VirtualConnectionType connection_type) {
  154. CastMessage message = CreateCastMessage(
  155. "namespace", base::Value(base::Value::Type::DICTIONARY), kSourceId,
  156. destination_id);
  157. {
  158. InSequence dummy;
  159. // We should first send a CONNECT request to ensure a connection.
  160. EXPECT_CALL(*transport_,
  161. SendMessage_(HasMessageType(CastMessageType::kConnect), _))
  162. .WillOnce(WithArg<0>([&](const CastMessage& message) {
  163. absl::optional<base::Value::Dict> dict =
  164. GetDictionaryFromCastMessage(message);
  165. EXPECT_EQ(connection_type, dict->FindInt("connType").value());
  166. }));
  167. // Then we send the actual message.
  168. EXPECT_CALL(*transport_, SendMessage_(_, _));
  169. }
  170. EXPECT_EQ(Result::kOk, handler_.SendAppMessage(channel_id_, message));
  171. }
  172. void HandlePendingLaunchSessionRequest(int request_id) {
  173. handler_.HandleCastInternalMessage(channel_id_, kSourceId, kDestinationId,
  174. "theNamespace",
  175. ParseJsonLikeDataDecoder(R"(
  176. {
  177. "requestId": )" + base::NumberToString(request_id) + R"(,
  178. "type": "RECEIVER_STATUS",
  179. "status": {"foo": "bar"},
  180. })"));
  181. }
  182. void HandlePendingGeneralRequest(int request_id) {
  183. handler_.HandleCastInternalMessage(channel_id_, kSourceId, kDestinationId,
  184. "theNamespace",
  185. ParseJsonLikeDataDecoder(R"(
  186. {
  187. "requestId": )" + base::NumberToString(request_id) + R"(
  188. })"));
  189. }
  190. void HandleAppAvailabilityRequest(int request_id) {
  191. handler_.HandleCastInternalMessage(channel_id_, kSourceId, kDestinationId,
  192. "theNamespace",
  193. ParseJsonLikeDataDecoder(R"(
  194. {
  195. "requestId": )" + base::NumberToString(request_id) + R"(,
  196. "availability": {")" + kAppId1 + R"(": "APP_AVAILABLE"},
  197. })"));
  198. }
  199. protected:
  200. content::BrowserTaskEnvironment task_environment_;
  201. std::unique_ptr<base::RunLoop> run_loop_;
  202. testing::NiceMock<MockCastSocketService> cast_socket_service_;
  203. data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
  204. CastMessageHandler handler_;
  205. MockCastSocket cast_socket_;
  206. const int channel_id_ = cast_socket_.id();
  207. const raw_ptr<MockCastTransport> transport_ = cast_socket_.mock_transport();
  208. int session_launch_response_count_ = 0;
  209. CastMessage last_request_;
  210. base::MockCallback<LaunchSessionCallback> launch_session_callback_;
  211. base::MockCallback<GetAppAvailabilityCallback> get_app_availability_callback_;
  212. base::MockCallback<ResultCallback> set_volume_callback_;
  213. base::MockCallback<ResultCallback> stop_session_callback_;
  214. };
  215. TEST_F(CastMessageHandlerTest, VirtualConnectionCreatedOnlyOnce) {
  216. ExpectEnsureConnectionThen(CastMessageType::kGetAppAvailability, 2);
  217. handler_.RequestAppAvailability(
  218. &cast_socket_, kAppId1,
  219. base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
  220. base::Unretained(this)));
  221. handler_.RequestAppAvailability(
  222. &cast_socket_, kAppId2,
  223. base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
  224. base::Unretained(this)));
  225. }
  226. TEST_F(CastMessageHandlerTest, RecreateVirtualConnectionAfterError) {
  227. ExpectEnsureConnectionThen(CastMessageType::kGetAppAvailability);
  228. handler_.RequestAppAvailability(
  229. &cast_socket_, kAppId1,
  230. base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
  231. base::Unretained(this)));
  232. EXPECT_CALL(*this,
  233. DoOnAppAvailability(kAppId1, GetAppAvailabilityResult::kUnknown));
  234. OnError(ChannelError::TRANSPORT_ERROR);
  235. ExpectEnsureConnectionThen(CastMessageType::kGetAppAvailability);
  236. handler_.RequestAppAvailability(
  237. &cast_socket_, kAppId2,
  238. base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
  239. base::Unretained(this)));
  240. // The callback is invoked with kUnknown before the PendingRequests is
  241. // destroyed.
  242. EXPECT_CALL(*this,
  243. DoOnAppAvailability(kAppId2, GetAppAvailabilityResult::kUnknown));
  244. }
  245. TEST_F(CastMessageHandlerTest, RequestAppAvailability) {
  246. ExpectEnsureConnectionThen(CastMessageType::kGetAppAvailability);
  247. handler_.RequestAppAvailability(
  248. &cast_socket_, "ABCDEFAB",
  249. base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
  250. base::Unretained(this)));
  251. absl::optional<base::Value::Dict> dict =
  252. GetDictionaryFromCastMessage(last_request_);
  253. ASSERT_TRUE(dict);
  254. const absl::optional<int> request_id_value = dict->FindInt("requestId");
  255. ASSERT_TRUE(request_id_value);
  256. int request_id = *request_id_value;
  257. EXPECT_GT(request_id, 0);
  258. CastMessage response;
  259. response.set_namespace_("urn:x-cast:com.google.cast.receiver");
  260. response.set_source_id("receiver-0");
  261. response.set_destination_id(handler_.sender_id());
  262. response.set_payload_type(
  263. CastMessage::PayloadType::CastMessage_PayloadType_STRING);
  264. response.set_payload_utf8(
  265. base::StringPrintf("{\"requestId\": %d, \"availability\": {\"ABCDEFAB\": "
  266. "\"APP_AVAILABLE\"}}",
  267. request_id));
  268. run_loop_ = std::make_unique<base::RunLoop>();
  269. EXPECT_CALL(*this, DoOnAppAvailability("ABCDEFAB",
  270. GetAppAvailabilityResult::kAvailable));
  271. OnMessage(response);
  272. run_loop_->Run();
  273. }
  274. TEST_F(CastMessageHandlerTest, RequestAppAvailabilityTimesOut) {
  275. EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(2);
  276. handler_.RequestAppAvailability(
  277. &cast_socket_, "ABCDEFAB",
  278. base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
  279. base::Unretained(this)));
  280. EXPECT_CALL(*this, DoOnAppAvailability("ABCDEFAB",
  281. GetAppAvailabilityResult::kUnknown));
  282. task_environment_.FastForwardBy(base::Seconds(5));
  283. }
  284. TEST_F(CastMessageHandlerTest, AppAvailabilitySentOnlyOnceWhilePending) {
  285. EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(2);
  286. handler_.RequestAppAvailability(
  287. &cast_socket_, "ABCDEFAB",
  288. base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
  289. base::Unretained(this)));
  290. EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(0);
  291. handler_.RequestAppAvailability(
  292. &cast_socket_, "ABCDEFAB",
  293. base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
  294. base::Unretained(this)));
  295. }
  296. TEST_F(CastMessageHandlerTest, EnsureConnection) {
  297. ExpectEnsureConnection();
  298. handler_.EnsureConnection(channel_id_, kSourceId, kDestinationId,
  299. VirtualConnectionType::kStrong);
  300. // No-op because connection is already created the first time.
  301. EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(0);
  302. handler_.EnsureConnection(channel_id_, kSourceId, kDestinationId,
  303. VirtualConnectionType::kStrong);
  304. }
  305. TEST_F(CastMessageHandlerTest, CloseConnection) {
  306. ExpectEnsureConnection();
  307. handler_.EnsureConnection(channel_id_, kSourceId, kDestinationId,
  308. VirtualConnectionType::kStrong);
  309. EXPECT_CALL(
  310. *transport_,
  311. SendMessage_(HasMessageType(CastMessageType::kCloseConnection), _));
  312. handler_.CloseConnection(channel_id_, kSourceId, kDestinationId);
  313. // Re-open virtual connection should cause CONNECT message to be sent.
  314. ExpectEnsureConnection();
  315. handler_.EnsureConnection(channel_id_, kSourceId, kDestinationId,
  316. VirtualConnectionType::kStrong);
  317. }
  318. TEST_F(CastMessageHandlerTest, CloseConnectionFromReceiver) {
  319. ExpectEnsureConnection();
  320. handler_.EnsureConnection(channel_id_, kSourceId, kDestinationId,
  321. VirtualConnectionType::kStrong);
  322. CastMessage response;
  323. response.set_namespace_("urn:x-cast:com.google.cast.tp.connection");
  324. response.set_source_id(kDestinationId);
  325. response.set_destination_id(kSourceId);
  326. response.set_payload_type(
  327. CastMessage::PayloadType::CastMessage_PayloadType_STRING);
  328. response.set_payload_utf8(R"({
  329. "type": "CLOSE"
  330. })");
  331. OnMessage(response);
  332. // Wait for message to be parsed and handled.
  333. task_environment_.RunUntilIdle();
  334. // Re-open virtual connection should cause message to be sent.
  335. EXPECT_CALL(*transport_, SendMessage_(_, _));
  336. handler_.EnsureConnection(channel_id_, kSourceId, kDestinationId,
  337. VirtualConnectionType::kStrong);
  338. }
  339. TEST_F(CastMessageHandlerTest, LaunchSession) {
  340. ExpectEnsureConnectionThen(CastMessageType::kLaunch);
  341. const absl::optional<base::Value> json = base::JSONReader::Read(kAppParams);
  342. handler_.LaunchSession(
  343. channel_id_, kAppId1, base::Seconds(30), {"WEB"}, json,
  344. base::BindOnce(&CastMessageHandlerTest::ExpectSessionLaunchResult,
  345. base::Unretained(this),
  346. LaunchSessionResponse::Result::kOk));
  347. absl::optional<base::Value::Dict> dict =
  348. GetDictionaryFromCastMessage(last_request_);
  349. ASSERT_TRUE(dict);
  350. const absl::optional<int> request_id_value = dict->FindInt("requestId");
  351. ASSERT_TRUE(request_id_value);
  352. int request_id = *request_id_value;
  353. EXPECT_GT(request_id, 0);
  354. const base::Value* app_params = dict->Find("appParams");
  355. EXPECT_EQ(json.value(), *app_params);
  356. CastMessage response;
  357. response.set_namespace_("urn:x-cast:com.google.cast.receiver");
  358. response.set_source_id("receiver-0");
  359. response.set_destination_id(handler_.sender_id());
  360. response.set_payload_type(
  361. CastMessage::PayloadType::CastMessage_PayloadType_STRING);
  362. response.set_payload_utf8(
  363. base::StringPrintf("{"
  364. "\"type\": \"RECEIVER_STATUS\","
  365. "\"requestId\": %d,"
  366. "\"status\": {}"
  367. "}",
  368. request_id));
  369. run_loop_ = std::make_unique<base::RunLoop>();
  370. OnMessage(response);
  371. run_loop_->Run();
  372. EXPECT_EQ(1, session_launch_response_count_);
  373. }
  374. TEST_F(CastMessageHandlerTest, LaunchSessionTimedOut) {
  375. ExpectEnsureConnectionThen(CastMessageType::kLaunch);
  376. handler_.LaunchSession(
  377. channel_id_, kAppId1, base::Seconds(30), {"WEB"},
  378. /* appParams */ absl::nullopt,
  379. base::BindOnce(&CastMessageHandlerTest::ExpectSessionLaunchResult,
  380. base::Unretained(this),
  381. LaunchSessionResponse::Result::kTimedOut));
  382. task_environment_.FastForwardBy(base::Seconds(30));
  383. EXPECT_EQ(1, session_launch_response_count_);
  384. }
  385. TEST_F(CastMessageHandlerTest, LaunchSessionMessageExceedsSizeLimit) {
  386. std::string invalid_url(kMaxProtocolMessageSize, 'a');
  387. base::Value::Dict json;
  388. json.Set("key", invalid_url);
  389. handler_.LaunchSession(
  390. channel_id_, kAppId1, base::Seconds(30), {"WEB"},
  391. absl::make_optional<base::Value>(std::move(json)),
  392. base::BindOnce(&CastMessageHandlerTest::ExpectSessionLaunchResult,
  393. base::Unretained(this),
  394. LaunchSessionResponse::Result::kError));
  395. EXPECT_EQ(1, session_launch_response_count_);
  396. }
  397. TEST_F(CastMessageHandlerTest, SendAppMessage) {
  398. base::Value::Dict body;
  399. body.Set("foo", "bar");
  400. CastMessage message = CreateCastMessage(
  401. "namespace", base::Value(std::move(body)), kSourceId, kDestinationId);
  402. {
  403. InSequence dummy;
  404. ExpectEnsureConnection();
  405. EXPECT_CALL(*transport_,
  406. SendMessage_(HasPayloadUtf8(message.payload_utf8()), _));
  407. }
  408. EXPECT_EQ(Result::kOk, handler_.SendAppMessage(channel_id_, message));
  409. }
  410. TEST_F(CastMessageHandlerTest, SendMessageOnInvisibleConnection) {
  411. // For destinations other than receiver-0, we should default to an invisible
  412. // connection.
  413. SendMessageAndExpectConnection("non-platform-receiver-id",
  414. VirtualConnectionType::kInvisible);
  415. }
  416. TEST_F(CastMessageHandlerTest, SendMessageToPlatformReceiver) {
  417. // For receiver-0, we should default to a strong connection because some
  418. // commands (e.g. LAUNCH) are not accepted from invisible connections.
  419. SendMessageAndExpectConnection("receiver-0", VirtualConnectionType::kStrong);
  420. }
  421. TEST_F(CastMessageHandlerTest, SendAppMessageExceedsSizeLimit) {
  422. std::string invalid_msg(kMaxProtocolMessageSize, 'a');
  423. base::Value::Dict body;
  424. body.Set("foo", invalid_msg);
  425. CastMessage message = CreateCastMessage(
  426. "namespace", base::Value(std::move(body)), kSourceId, kDestinationId);
  427. EXPECT_EQ(Result::kFailed, handler_.SendAppMessage(channel_id_, message));
  428. }
  429. // Check that SendMediaRequest sends a message created by CreateMediaRequest and
  430. // returns a request ID.
  431. TEST_F(CastMessageHandlerTest, SendMediaRequest) {
  432. {
  433. InSequence dummy;
  434. ExpectEnsureConnection();
  435. EXPECT_CALL(*transport_, SendMessage_(_, _))
  436. .WillOnce(WithArg<0>([&](const auto& message) {
  437. std::string expected_body = R"({
  438. "requestId": 1,
  439. "type": "PLAY",
  440. })";
  441. auto expected = CreateMediaRequest(ParseJson(expected_body), 1,
  442. "theSourceId", kDestinationId);
  443. EXPECT_EQ(expected.namespace_(), message.namespace_());
  444. EXPECT_EQ(expected.source_id(), message.source_id());
  445. EXPECT_EQ(expected.destination_id(), message.destination_id());
  446. EXPECT_EQ(expected.payload_utf8(), message.payload_utf8());
  447. // Future-proofing. This matcher gives terrible error messages but it
  448. // might catch errors the above matchers miss.
  449. EXPECT_THAT(message, EqualsProto(expected));
  450. }));
  451. }
  452. std::string message_str = R"({
  453. "type": "PLAY",
  454. })";
  455. absl::optional<int> request_id = handler_.SendMediaRequest(
  456. channel_id_, ParseJson(message_str), "theSourceId", kDestinationId);
  457. EXPECT_EQ(1, request_id);
  458. }
  459. TEST_F(CastMessageHandlerTest, SendBroadcastMessage) {
  460. BroadcastRequest request = BroadcastRequest("namespace", "message");
  461. CastMessage message = CreateBroadcastRequest(
  462. "theSourceId", /* request_id */ 1, {kAppId1}, request);
  463. {
  464. InSequence dummy;
  465. ExpectEnsureConnection();
  466. EXPECT_CALL(*transport_,
  467. SendMessage_(HasPayloadUtf8(message.payload_utf8()), _));
  468. }
  469. EXPECT_EQ(Result::kOk,
  470. handler_.SendBroadcastMessage(channel_id_, {kAppId1}, request));
  471. }
  472. TEST_F(CastMessageHandlerTest, SendBroadcastMessageExceedsSizeLimit) {
  473. BroadcastRequest request =
  474. BroadcastRequest("namespace", std::string(kMaxProtocolMessageSize, 'a'));
  475. CastMessage message = CreateBroadcastRequest(
  476. "theSourceId", /* request_id */ 1, {kAppId1}, request);
  477. EXPECT_EQ(Result::kFailed,
  478. handler_.SendBroadcastMessage(channel_id_, {kAppId1}, request));
  479. }
  480. // Check that SendVolumeCommand sends a message created by CreateVolumeRequest
  481. // and registers a pending request.
  482. TEST_F(CastMessageHandlerTest, SendVolumeCommand) {
  483. {
  484. InSequence dummy;
  485. ExpectEnsureConnection();
  486. EXPECT_CALL(*transport_, SendMessage_(_, _))
  487. .WillOnce(WithArg<0>([&](const auto& message) {
  488. std::string expected_body = R"({
  489. "requestId": 1,
  490. "type": "SET_VOLUME",
  491. })";
  492. auto expected = CreateSetVolumeRequest(ParseJson(expected_body), 1,
  493. "theSourceId");
  494. EXPECT_EQ(expected.namespace_(), message.namespace_());
  495. EXPECT_EQ(expected.source_id(), message.source_id());
  496. EXPECT_EQ(expected.destination_id(), message.destination_id());
  497. EXPECT_EQ(expected.payload_utf8(), message.payload_utf8());
  498. // Future-proofing. This matcher gives terrible error messages but it
  499. // might catch errors the above matchers miss.
  500. EXPECT_THAT(message, EqualsProto(expected));
  501. }));
  502. }
  503. std::string message_str = R"({
  504. "sessionId": "theSessionId",
  505. "type": "SET_VOLUME",
  506. })";
  507. handler_.SendSetVolumeRequest(channel_id_, ParseJson(message_str),
  508. "theSourceId", base::DoNothing());
  509. }
  510. // Check that closing a socket removes pending requests, and that the pending
  511. // request callbacks are called appropriately.
  512. TEST_F(CastMessageHandlerTest, PendingRequestsDestructor) {
  513. CreatePendingRequests();
  514. // Set up expanctions for pending request callbacks.
  515. EXPECT_CALL(launch_session_callback_, Run(_))
  516. .WillOnce([&](LaunchSessionResponse response) {
  517. EXPECT_EQ(LaunchSessionResponse::kError, response.result);
  518. EXPECT_EQ(absl::nullopt, response.receiver_status);
  519. });
  520. EXPECT_CALL(get_app_availability_callback_,
  521. Run(kAppId1, GetAppAvailabilityResult::kUnknown))
  522. .Times(2);
  523. EXPECT_CALL(set_volume_callback_, Run(Result::kFailed)).Times(2);
  524. EXPECT_CALL(stop_session_callback_, Run(Result::kFailed));
  525. // Force callbacks to be called through PendingRequests destructor by
  526. // simulating a socket closing.
  527. EXPECT_CALL(cast_socket_, ready_state()).WillOnce(Return(ReadyState::CLOSED));
  528. handler_.OnReadyStateChanged(cast_socket_);
  529. }
  530. TEST_F(CastMessageHandlerTest, HandlePendingRequest) {
  531. int next_request_id = 1;
  532. CreatePendingRequests();
  533. // Set up expanctions for pending request callbacks.
  534. EXPECT_CALL(launch_session_callback_, Run(_))
  535. .WillOnce([&](LaunchSessionResponse response) {
  536. EXPECT_EQ(LaunchSessionResponse::kOk, response.result);
  537. EXPECT_THAT(response.receiver_status,
  538. testing::Optional(IsJson(R"({"foo": "bar"})")));
  539. });
  540. EXPECT_CALL(get_app_availability_callback_,
  541. Run(kAppId1, GetAppAvailabilityResult::kAvailable))
  542. .Times(2);
  543. EXPECT_CALL(set_volume_callback_, Run(Result::kOk)).Times(2);
  544. EXPECT_CALL(stop_session_callback_, Run(Result::kOk));
  545. HandlePendingLaunchSessionRequest(next_request_id++);
  546. // Handle both pending get app availability requests.
  547. HandleAppAvailabilityRequest(next_request_id++);
  548. // Handle pending set volume request (1 of 2).
  549. HandlePendingGeneralRequest(next_request_id++);
  550. // Skip request_id == 4, since it was used by the second get app availability
  551. // request.
  552. next_request_id++;
  553. // Handle pending set volume request (2 of 2).
  554. HandlePendingGeneralRequest(next_request_id++);
  555. // Handle pending stop session request.
  556. HandlePendingGeneralRequest(next_request_id++);
  557. }
  558. // Check that set volume requests time out correctly.
  559. TEST_F(CastMessageHandlerTest, SetVolumeTimedOut) {
  560. EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(AnyNumber());
  561. std::string message_str = R"({
  562. "sessionId": "theSessionId",
  563. "type": "SET_VOLUME",
  564. })";
  565. base::MockCallback<ResultCallback> callback;
  566. handler_.SendSetVolumeRequest(channel_id_, ParseJson(message_str),
  567. "theSourceId", callback.Get());
  568. EXPECT_CALL(callback, Run(Result::kFailed));
  569. task_environment_.FastForwardBy(kRequestTimeout);
  570. }
  571. TEST_F(CastMessageHandlerTest, SendMultipleLaunchRequests) {
  572. int next_request_id = 1;
  573. base::MockCallback<LaunchSessionCallback> expect_success_callback;
  574. base::MockCallback<LaunchSessionCallback> expect_failure_callback;
  575. EXPECT_CALL(expect_success_callback, Run(_))
  576. .WillOnce(WithArg<0>([](LaunchSessionResponse response) {
  577. EXPECT_EQ(LaunchSessionResponse::Result::kOk, response.result);
  578. }));
  579. EXPECT_CALL(expect_failure_callback, Run(_))
  580. .WillOnce(WithArg<0>([](LaunchSessionResponse response) {
  581. EXPECT_EQ(LaunchSessionResponse::Result::kError, response.result);
  582. }));
  583. EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(AnyNumber());
  584. handler_.LaunchSession(channel_id_, kAppId1, base::TimeDelta::Max(), {"WEB"},
  585. /* appParams */ absl::nullopt,
  586. expect_success_callback.Get());
  587. // When there already is a launch request queued, we expect subsequent
  588. // requests to fail.
  589. handler_.LaunchSession(channel_id_, kAppId1, base::TimeDelta::Max(), {"WEB"},
  590. /* appParams */ absl::nullopt,
  591. expect_failure_callback.Get());
  592. // This resolves the first launch request.
  593. HandlePendingLaunchSessionRequest(next_request_id++);
  594. }
  595. TEST_F(CastMessageHandlerTest, SendMultipleStopRequests) {
  596. int next_request_id = 1;
  597. base::MockCallback<ResultCallback> expect_success_callback;
  598. base::MockCallback<ResultCallback> expect_failure_callback;
  599. EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(AnyNumber());
  600. handler_.LaunchSession(channel_id_, kAppId1, base::TimeDelta::Max(), {"WEB"},
  601. /* appParams */ absl::nullopt,
  602. launch_session_callback_.Get());
  603. HandlePendingLaunchSessionRequest(next_request_id++);
  604. EXPECT_CALL(expect_success_callback, Run(Result::kOk));
  605. EXPECT_CALL(expect_failure_callback, Run(Result::kFailed));
  606. handler_.StopSession(channel_id_, kSessionId, kSourceId,
  607. expect_success_callback.Get());
  608. // When there already is a stop request queued, we expect subsequent requests
  609. // to fail.
  610. handler_.StopSession(channel_id_, kSessionId, kSourceId,
  611. expect_failure_callback.Get());
  612. // This resolves the first stop request.
  613. HandlePendingGeneralRequest(next_request_id++);
  614. }
  615. } // namespace cast_channel