Directly include Skia headers where needed.
[chromium-blink-merge.git] / remoting / host / register_support_host_request.cc
blob30a5bc9005da4c1181492e81b757c89cf6d8e31e
1 // Copyright (c) 2012 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/host/register_support_host_request.h"
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/time/time.h"
13 #include "remoting/base/constants.h"
14 #include "remoting/host/host_config.h"
15 #include "remoting/signaling/iq_sender.h"
16 #include "remoting/signaling/jid_util.h"
17 #include "remoting/signaling/signal_strategy.h"
18 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
19 #include "third_party/webrtc/libjingle/xmpp/constants.h"
21 using buzz::QName;
22 using buzz::XmlElement;
24 namespace remoting {
26 namespace {
27 // Strings used in the request message we send to the bot.
28 const char kRegisterQueryTag[] = "register-support-host";
29 const char kPublicKeyTag[] = "public-key";
30 const char kSignatureTag[] = "signature";
31 const char kSignatureTimeAttr[] = "time";
33 // Strings used to parse responses received from the bot.
34 const char kRegisterQueryResultTag[] = "register-support-host-result";
35 const char kSupportIdTag[] = "support-id";
36 const char kSupportIdLifetimeTag[] = "support-id-lifetime";
39 RegisterSupportHostRequest::RegisterSupportHostRequest(
40 SignalStrategy* signal_strategy,
41 scoped_refptr<RsaKeyPair> key_pair,
42 const std::string& directory_bot_jid,
43 const RegisterCallback& callback)
44 : signal_strategy_(signal_strategy),
45 key_pair_(key_pair),
46 directory_bot_jid_(directory_bot_jid),
47 callback_(callback) {
48 DCHECK(signal_strategy_);
49 DCHECK(key_pair_.get());
50 signal_strategy_->AddListener(this);
51 iq_sender_.reset(new IqSender(signal_strategy_));
54 RegisterSupportHostRequest::~RegisterSupportHostRequest() {
55 if (signal_strategy_)
56 signal_strategy_->RemoveListener(this);
59 void RegisterSupportHostRequest::OnSignalStrategyStateChange(
60 SignalStrategy::State state) {
61 if (state == SignalStrategy::CONNECTED) {
62 DCHECK(!callback_.is_null());
64 request_ = iq_sender_->SendIq(
65 buzz::STR_SET, directory_bot_jid_,
66 CreateRegistrationRequest(signal_strategy_->GetLocalJid()).Pass(),
67 base::Bind(&RegisterSupportHostRequest::ProcessResponse,
68 base::Unretained(this)));
69 } else if (state == SignalStrategy::DISCONNECTED) {
70 // We will reach here if signaling fails to connect.
71 std::string error_message = "Signal strategy disconnected.";
72 LOG(ERROR) << error_message;
73 CallCallback(std::string(), base::TimeDelta(), error_message);
77 bool RegisterSupportHostRequest::OnSignalStrategyIncomingStanza(
78 const buzz::XmlElement* stanza) {
79 return false;
82 scoped_ptr<XmlElement> RegisterSupportHostRequest::CreateRegistrationRequest(
83 const std::string& jid) {
84 scoped_ptr<XmlElement> query(new XmlElement(
85 QName(kChromotingXmlNamespace, kRegisterQueryTag)));
86 XmlElement* public_key = new XmlElement(
87 QName(kChromotingXmlNamespace, kPublicKeyTag));
88 public_key->AddText(key_pair_->GetPublicKey());
89 query->AddElement(public_key);
90 query->AddElement(CreateSignature(jid).release());
91 return query.Pass();
94 scoped_ptr<XmlElement> RegisterSupportHostRequest::CreateSignature(
95 const std::string& jid) {
96 scoped_ptr<XmlElement> signature_tag(new XmlElement(
97 QName(kChromotingXmlNamespace, kSignatureTag)));
99 int64 time = static_cast<int64>(base::Time::Now().ToDoubleT());
100 std::string time_str(base::Int64ToString(time));
101 signature_tag->AddAttr(
102 QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str);
104 std::string message = NormalizeJid(jid) + ' ' + time_str;
105 std::string signature(key_pair_->SignMessage(message));
106 signature_tag->AddText(signature);
108 return signature_tag.Pass();
111 void RegisterSupportHostRequest::ParseResponse(const XmlElement* response,
112 std::string* support_id,
113 base::TimeDelta* lifetime,
114 std::string* error_message) {
115 std::ostringstream error;
117 std::string type = response->Attr(buzz::QN_TYPE);
118 if (type == buzz::STR_ERROR) {
119 error << "Received error in response to heartbeat: " << response->Str();
120 *error_message = error.str();
121 LOG(ERROR) << *error_message;
122 return;
125 // This method must only be called for error or result stanzas.
126 if (type != buzz::STR_RESULT) {
127 error << "Received unexpect stanza of type \"" << type << "\"";
128 *error_message = error.str();
129 LOG(ERROR) << *error_message;
130 return;
133 const XmlElement* result_element = response->FirstNamed(QName(
134 kChromotingXmlNamespace, kRegisterQueryResultTag));
135 if (!result_element) {
136 error << "<" << kRegisterQueryResultTag
137 << "> is missing in the host registration response: "
138 << response->Str();
139 *error_message = error.str();
140 LOG(ERROR) << *error_message;
141 return;
144 const XmlElement* support_id_element =
145 result_element->FirstNamed(QName(kChromotingXmlNamespace, kSupportIdTag));
146 if (!support_id_element) {
147 error << "<" << kSupportIdTag
148 << "> is missing in the host registration response: "
149 << response->Str();
150 *error_message = error.str();
151 LOG(ERROR) << *error_message;
152 return;
155 const XmlElement* lifetime_element =
156 result_element->FirstNamed(QName(kChromotingXmlNamespace,
157 kSupportIdLifetimeTag));
158 if (!lifetime_element) {
159 error << "<" << kSupportIdLifetimeTag
160 << "> is missing in the host registration response: "
161 << response->Str();
162 *error_message = error.str();
163 LOG(ERROR) << *error_message;
164 return;
167 int lifetime_int;
168 if (!base::StringToInt(lifetime_element->BodyText().c_str(), &lifetime_int) ||
169 lifetime_int <= 0) {
170 error << "<" << kSupportIdLifetimeTag
171 << "> is malformed in the host registration response: "
172 << response->Str();
173 *error_message = error.str();
174 LOG(ERROR) << *error_message;
175 return;
178 *support_id = support_id_element->BodyText();
179 *lifetime = base::TimeDelta::FromSeconds(lifetime_int);
180 return;
183 void RegisterSupportHostRequest::ProcessResponse(IqRequest* request,
184 const XmlElement* response) {
185 std::string support_id;
186 base::TimeDelta lifetime;
187 std::string error_message;
188 ParseResponse(response, &support_id, &lifetime, &error_message);
189 CallCallback(support_id, lifetime, error_message);
192 void RegisterSupportHostRequest::CallCallback(
193 const std::string& support_id,
194 base::TimeDelta lifetime,
195 const std::string& error_message) {
196 // Cleanup state before calling the callback.
197 request_.reset();
198 iq_sender_.reset();
199 signal_strategy_->RemoveListener(this);
200 signal_strategy_ = nullptr;
202 base::ResetAndReturn(&callback_).Run(support_id, lifetime, error_message);
205 } // namespace remoting