Commit 5443b73b authored by zijiehe's avatar zijiehe Committed by Commit bot

[Chromoting] Plugin message in JingleMessage

This change adds plugin message in JingleMessage, which is an action indepenent
xml node, placed before or after other messages.

The plugin message will be used to send and receive host attributes and
experiment configuration.

This is part of host experiment framework.

BUG=650926

Review-Url: https://codereview.chromium.org/2567953002
Cr-Commit-Position: refs/heads/master@{#438945}
parent 8cb43c2a
per-file *_messages.cc=set noparent
per-file *_messages.cc=file://ipc/SECURITY_OWNERS
per-file *_messages*.h=set noparent
per-file *_messages*.h=file://ipc/SECURITY_OWNERS
per-file jingle_messages.h=file://remoting/OWNERS
per-file jingle_messages.cc=file://remoting/OWNERS
......@@ -342,15 +342,28 @@ bool JingleMessage::ParseXml(const buzz::XmlElement* stanza,
return false;
}
const XmlElement* attachments_tag =
jingle_tag->FirstNamed(QName(kChromotingXmlNamespace, "attachments"));
if (attachments_tag) {
attachments.reset(new XmlElement(*attachments_tag));
} else {
attachments.reset();
}
if (action == SESSION_INFO) {
// session-info messages may contain arbitrary information not
// defined by the Jingle protocol. We don't need to parse it.
const XmlElement* child = jingle_tag->FirstElement();
// Plugin messages are action independent, which should not be considered as
// session-info.
if (child == attachments_tag) {
child = child->NextElement();
}
if (child) {
// session-info is allowed to be empty.
info.reset(new XmlElement(*child));
} else {
info.reset(nullptr);
info.reset();
}
return true;
}
......@@ -374,8 +387,9 @@ bool JingleMessage::ParseXml(const buzz::XmlElement* stanza,
}
}
if (action == SESSION_TERMINATE)
if (action == SESSION_TERMINATE) {
return true;
}
const XmlElement* content_tag =
jingle_tag->FirstNamed(QName(kJingleNamespace, "content"));
......@@ -396,7 +410,7 @@ bool JingleMessage::ParseXml(const buzz::XmlElement* stanza,
transport_info.reset(new buzz::XmlElement(*webrtc_transport_tag));
}
description.reset(nullptr);
description.reset();
if (action == SESSION_INITIATE || action == SESSION_ACCEPT) {
const XmlElement* description_tag = content_tag->FirstNamed(
QName(kChromotingXmlNamespace, "description"));
......@@ -439,18 +453,25 @@ std::unique_ptr<buzz::XmlElement> JingleMessage::ToXml() const {
SetAddress(root.get(), jingle_tag, from, true);
const char* action_attr = ValueToName(kActionTypes, action);
if (!action_attr)
if (!action_attr) {
LOG(FATAL) << "Invalid action value " << action;
}
jingle_tag->AddAttr(QName(kEmptyNamespace, "action"), action_attr);
if (attachments) {
jingle_tag->AddElement(new XmlElement(*attachments));
}
if (action == SESSION_INFO) {
if (info.get())
if (info.get()) {
jingle_tag->AddElement(new XmlElement(*info.get()));
}
return root;
}
if (action == SESSION_INITIATE)
if (action == SESSION_INITIATE) {
jingle_tag->AddAttr(QName(kEmptyNamespace, "initiator"), initiator);
}
if (reason != UNKNOWN_REASON) {
XmlElement* reason_tag = new XmlElement(QName(kJingleNamespace, "reason"));
......@@ -475,8 +496,9 @@ std::unique_ptr<buzz::XmlElement> JingleMessage::ToXml() const {
ContentDescription::kChromotingContentName);
content_tag->AddAttr(QName(kEmptyNamespace, "creator"), "initiator");
if (description)
if (description) {
content_tag->AddElement(description->ToXml());
}
if (transport_info) {
content_tag->AddElement(new XmlElement(*transport_info));
......@@ -573,8 +595,9 @@ std::unique_ptr<buzz::XmlElement> JingleMessageReply::ToXml(
NOTREACHED();
}
if (!text.empty())
if (!text.empty()) {
error_text = text;
}
error->SetAttr(QName(kEmptyNamespace, "type"), type);
......@@ -604,8 +627,9 @@ IceTransportInfo::~IceTransportInfo() {}
bool IceTransportInfo::ParseXml(
const buzz::XmlElement* element) {
if (element->Name() != QName(kIceTransportNamespace, "transport"))
if (element->Name() != QName(kIceTransportNamespace, "transport")) {
return false;
}
ice_credentials.clear();
candidates.clear();
......@@ -615,8 +639,9 @@ bool IceTransportInfo::ParseXml(
credentials_tag;
credentials_tag = credentials_tag->NextNamed(qn_credentials)) {
IceTransportInfo::IceCredentials credentials;
if (!ParseIceCredentials(credentials_tag, &credentials))
if (!ParseIceCredentials(credentials_tag, &credentials)) {
return false;
}
ice_credentials.push_back(credentials);
}
......@@ -624,8 +649,9 @@ bool IceTransportInfo::ParseXml(
for (const XmlElement* candidate_tag = element->FirstNamed(qn_candidate);
candidate_tag; candidate_tag = candidate_tag->NextNamed(qn_candidate)) {
IceTransportInfo::NamedCandidate candidate;
if (!ParseIceCandidate(candidate_tag, &candidate))
if (!ParseIceCandidate(candidate_tag, &candidate)) {
return false;
}
candidates.push_back(candidate);
}
......
......@@ -101,6 +101,10 @@ struct JingleMessage {
// Content of session-info messages.
std::unique_ptr<buzz::XmlElement> info;
// Content of plugin message. The node is read or written by all plugins, and
// ActionType independent.
std::unique_ptr<buzz::XmlElement> attachments;
// Value from the <reason> tag if it is present in the
// message. Useful mainly for session-terminate messages, but Jingle
// spec allows it in any message.
......
......@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_util.h"
#include "remoting/protocol/content_description.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -600,5 +601,70 @@ TEST(JingleMessageTest, RemotingErrorCode) {
}
}
TEST(JingleMessageTest, AttachmentsMessage) {
// Ordering of the "attachments" tag and other tags are irrelevent. But the
// JingleMessage implementation always puts it before other tags, so we do the
// same thing in test cases.
const char* kMessageWithPluginTag =
"<cli:iq from='user@gmail.com/chromoting016DBB07' "
"to='user@gmail.com/chromiumsy5C6A652D' type='set' "
"xmlns:cli='jabber:client'><jingle action='$1' "
"sid='2227053353' xmlns='urn:xmpp:jingle:1'>"
"<gr:attachments xmlns:gr='google:remoting'>"
"<gr:sometag>some-message</gr:sometag>"
"</gr:attachments>$2</jingle></cli:iq>";
for (int i = JingleMessage::SESSION_INITIATE;
i <= JingleMessage::TRANSPORT_INFO; i++) {
JingleMessage::ActionType action_type =
static_cast<JingleMessage::ActionType>(i);
std::vector<std::string> substitutes = {
JingleMessage::GetActionName(action_type)
};
if (action_type == JingleMessage::SESSION_INFO) {
substitutes.push_back("<test-info>test-message</test-info>");
} else if (action_type == JingleMessage::SESSION_TERMINATE) {
substitutes.emplace_back();
} else if (action_type == JingleMessage::TRANSPORT_INFO) {
substitutes.push_back(
"<content name='chromoting' creator='initiator'>"
"<transport xmlns='google:remoting:webrtc'>"
"<credentials channel='event' ufrag='tPUyEAmQrEw3y7hi' "
"password='2iRdhLfawKZC5ydJ'/>"
"<credentials channel='video' ufrag='EPK3CXo5sTLJSez0' "
"password='eM0VUfUkZ+1Pyi0M'/>"
"<candidate name='event' foundation='725747215' "
"address='172.23.164.186' port='59089' type='local' "
"protocol='udp' priority='2122194688' generation='0'/>"
"<candidate name='video' foundation='3623806809' "
"address='172.23.164.186' port='57040' type='local' "
"protocol='udp' priority='2122194688' generation='0'/>"
"</transport>"
"</content>");
} else {
substitutes.push_back("<content name='chromoting' creator='initiator'>"
"<description xmlns='google:remoting'>"
"<authentication><auth-token>"
"j7whCMii0Z0AAPwj7whCM/j7whCMii0Z0AAPw="
"</auth-token></authentication>"
"</description>"
"<transport xmlns='google:remoting:webrtc' />"
"</content>");
}
std::string message_str = base::ReplaceStringPlaceholders(
kMessageWithPluginTag, substitutes, nullptr);
JingleMessage message;
ParseFormatAndCompare(message_str.c_str(), &message);
EXPECT_TRUE(message.attachments);
XmlElement expected(QName("google:remoting", "attachments"));
expected.AddElement(new XmlElement(QName("google:remoting", "sometag")));
expected.FirstElement()->SetBodyText("some-message");
std::string error;
EXPECT_TRUE(VerifyXml(&expected, message.attachments.get(), &error))
<< error;
}
}
} // namespace protocol
} // namespace remoting
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