1 // Copyright 2015 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.
5 #include "remoting/signaling/xmpp_stream_parser.h"
7 #include "base/location.h"
8 #include "base/logging.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "third_party/webrtc/libjingle/xmllite/xmlbuilder.h"
12 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
13 #include "third_party/webrtc/libjingle/xmllite/xmlparser.h"
17 class XmppStreamParser::Core
: public buzz::XmlParseHandler
{
19 typedef base::Callback
<void(scoped_ptr
<buzz::XmlElement
> stanza
)>
25 void SetCallbacks(const OnStanzaCallback
& on_stanza_callback
,
26 const base::Closure
& on_error_callback
);
28 void AppendData(const std::string
& data
);
31 // buzz::XmlParseHandler interface.
32 void StartElement(buzz::XmlParseContext
* context
,
34 const char** atts
) override
;
35 void EndElement(buzz::XmlParseContext
* context
, const char* name
) override
;
36 void CharacterData(buzz::XmlParseContext
* context
,
39 void Error(buzz::XmlParseContext
* context
, XML_Error error_code
) override
;
43 OnStanzaCallback on_stanza_callback_
;
44 base::Closure on_error_callback_
;
46 buzz::XmlParser parser_
;
48 buzz::XmlBuilder builder_
;
52 DISALLOW_COPY_AND_ASSIGN(Core
);
55 XmppStreamParser::Core::Core()
61 XmppStreamParser::Core::~Core() {
64 void XmppStreamParser::Core::SetCallbacks(
65 const OnStanzaCallback
& on_stanza_callback
,
66 const base::Closure
& on_error_callback
) {
67 on_stanza_callback_
= on_stanza_callback
;
68 on_error_callback_
= on_error_callback
;
71 void XmppStreamParser::Core::AppendData(const std::string
& data
) {
74 parser_
.Parse(data
.data(), data
.size(), false);
77 void XmppStreamParser::Core::StartElement(buzz::XmlParseContext
* context
,
84 scoped_ptr
<buzz::XmlElement
> header(
85 buzz::XmlBuilder::BuildElement(context
, name
, atts
));
87 LOG(ERROR
) << "Failed to parse XMPP stream header.";
93 builder_
.StartElement(context
, name
, atts
);
96 void XmppStreamParser::Core::EndElement(buzz::XmlParseContext
* context
,
102 LOG(ERROR
) << "XMPP stream ended unexpectedly.";
107 builder_
.EndElement(context
, name
);
110 if (!on_stanza_callback_
.is_null())
111 on_stanza_callback_
.Run(make_scoped_ptr(builder_
.CreateElement()));
115 void XmppStreamParser::Core::CharacterData(buzz::XmlParseContext
* context
,
120 // Ignore data between stanzas.
122 // Only whitespace is allowed outside of the stanzas.
123 bool all_spaces
= true;
124 for (char c
: std::string(text
, len
)) {
131 LOG(ERROR
) << "Received unexpected string: " << std::string(text
,
135 } else if (depth_
> 1) {
136 builder_
.CharacterData(context
, text
, len
);
140 void XmppStreamParser::Core::Error(buzz::XmlParseContext
* context
,
141 XML_Error error_code
) {
142 LOG(ERROR
) << "XMPP parser error: " << error_code
;
146 void XmppStreamParser::Core::ProcessError() {
148 if (!on_error_callback_
.is_null())
149 on_error_callback_
.Run();
152 XmppStreamParser::XmppStreamParser() : core_(new Core()) {
155 XmppStreamParser::~XmppStreamParser() {
156 // Set null callbacks and delete |core_| asynchronously to make sure it's not
157 // deleted from a callback.
158 core_
->SetCallbacks(OnStanzaCallback(), base::Closure());
159 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE
, core_
.release());
162 void XmppStreamParser::SetCallbacks(const OnStanzaCallback
& on_stanza_callback
,
163 const base::Closure
& on_error_callback
) {
164 core_
->SetCallbacks(on_stanza_callback
, on_error_callback
);
167 void XmppStreamParser::AppendData(const std::string
& data
) {
168 core_
->AppendData(data
);
171 } // namespace remoting