[Cast MRP] Remove null fields for Cast-protocol messages.
(cherry picked from commit 6b9eac03845eb0fc0f6471a2b93bdb04f4caf841)
Bug: 1129217
Change-Id: Ic9300541ba56cddcb75524af07dd8afe9a4f35c2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2427124
Auto-Submit: John Williams <[email protected]>
Reviewed-by: mark a. foltz <[email protected]>
Reviewed-by: Takumi Fujimoto <[email protected]>
Commit-Queue: John Williams <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#813328}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2463845
Cr-Commit-Position: refs/branch-heads/4280@{#252}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/chrome/browser/media/router/providers/cast/cast_session_client_impl.cc b/chrome/browser/media/router/providers/cast/cast_session_client_impl.cc
index 49ede49..698eff0 100644
--- a/chrome/browser/media/router/providers/cast/cast_session_client_impl.cc
+++ b/chrome/browser/media/router/providers/cast/cast_session_client_impl.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/media/router/providers/cast/cast_session_client_impl.h"
+#include <vector>
+
#include "chrome/browser/media/router/data_decoder_util.h"
#include "chrome/browser/media/router/providers/cast/app_activity.h"
#include "components/cast_channel/enum_table.h"
@@ -23,6 +25,28 @@
<< error;
}
+// Traverses a JSON value, recursively removing any dict entries whose value is
+// null.
+void RemoveNullFields(base::Value& value) {
+ if (value.is_list()) {
+ for (auto& item : value.GetList()) {
+ RemoveNullFields(item);
+ }
+ } else if (value.is_dict()) {
+ std::vector<std::string> to_remove;
+ for (auto pair : value.DictItems()) {
+ if (pair.second.is_none()) {
+ to_remove.push_back(pair.first);
+ } else {
+ RemoveNullFields(pair.second);
+ }
+ }
+ for (const auto& key : to_remove) {
+ value.RemoveKey(key);
+ }
+ }
+}
+
} // namespace
CastSessionClientImpl::CastSessionClientImpl(const std::string& client_id,
@@ -127,6 +151,11 @@
return;
}
+ // NOTE(jrw): This step isn't part of the Cast protocol per se, but it's
+ // required for backward compatibility. There is one known case
+ // (crbug.com/1129217) where not doing it breaks the Cast SDK.
+ RemoveNullFields(*result.value);
+
std::unique_ptr<CastInternalMessage> cast_message =
CastInternalMessage::From(std::move(*result.value));
if (!cast_message) {
diff --git a/chrome/browser/media/router/providers/cast/cast_session_client_unittest.cc b/chrome/browser/media/router/providers/cast/cast_session_client_unittest.cc
index e5c5844..e31ea47 100644
--- a/chrome/browser/media/router/providers/cast/cast_session_client_unittest.cc
+++ b/chrome/browser/media/router/providers/cast/cast_session_client_unittest.cc
@@ -159,6 +159,39 @@
})"));
}
+TEST_F(CastSessionClientImplTest, NullFieldsAreRemoved) {
+ EXPECT_CALL(activity_, SendMediaRequestToReceiver)
+ .WillOnce([](const auto& message) {
+ // TODO(crbug.com/961081): Use IsCastInternalMessage as argument to
+ // SendMediaRequestToReceiver when bug is fixed.
+ EXPECT_THAT(message, IsCastInternalMessage(R"({
+ "type": "v2_message",
+ "clientId": "theClientId",
+ "sequenceNumber": 123,
+ "message": {
+ "sessionId": "theSessionId",
+ "type": "MEDIA_GET_STATUS",
+ "array": [{"in_array": true}]
+ }
+ })"));
+ return 0;
+ });
+
+ client_->OnMessage(
+ blink::mojom::PresentationConnectionMessage::NewMessage(R"({
+ "type": "v2_message",
+ "clientId": "theClientId",
+ "sequenceNumber": 123,
+ "message": {
+ "sessionId": "theSessionId",
+ "type": "MEDIA_GET_STATUS",
+ "array": [{"in_array": true, "is_null": null}],
+ "dummy": null
+ }
+ })"));
+ RunUntilIdle();
+}
+
TEST_F(CastSessionClientImplTest, AppMessageFromClient) {
EXPECT_CALL(activity_, SendAppMessageToReceiver)
.WillOnce(Return(cast_channel::Result::kOk));