summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--remoting/client/plugin/chromoting_scriptable_object.cc14
-rw-r--r--remoting/client/plugin/chromoting_scriptable_object.h15
-rw-r--r--remoting/client/plugin/pepper_xmpp_proxy.cc57
-rw-r--r--remoting/client/plugin/pepper_xmpp_proxy.h42
-rw-r--r--remoting/host/chromoting_host.cc19
-rw-r--r--remoting/host/chromoting_host.h2
-rw-r--r--remoting/host/heartbeat_sender.cc33
-rw-r--r--remoting/host/heartbeat_sender.h15
-rw-r--r--remoting/host/heartbeat_sender_unittest.cc36
-rw-r--r--remoting/jingle_glue/iq_request.cc90
-rw-r--r--remoting/jingle_glue/iq_request.h98
-rw-r--r--remoting/jingle_glue/jingle_client.cc245
-rw-r--r--remoting/jingle_glue/jingle_client.h153
-rw-r--r--remoting/jingle_glue/jingle_client_unittest.cc15
-rw-r--r--remoting/protocol/connection_to_host.cc13
-rw-r--r--remoting/protocol/connection_to_host.h1
-rw-r--r--remoting/protocol/protocol_test_client.cc8
17 files changed, 619 insertions, 237 deletions
diff --git a/remoting/client/plugin/chromoting_scriptable_object.cc b/remoting/client/plugin/chromoting_scriptable_object.cc
index 497e803..b45b822 100644
--- a/remoting/client/plugin/chromoting_scriptable_object.cc
+++ b/remoting/client/plugin/chromoting_scriptable_object.cc
@@ -9,6 +9,7 @@
#include "ppapi/cpp/var.h"
#include "remoting/client/client_config.h"
#include "remoting/client/plugin/chromoting_instance.h"
+#include "remoting/client/plugin/pepper_xmpp_proxy.h"
using pp::Var;
@@ -250,6 +251,19 @@ void ChromotingScriptableObject::SignalLoginChallenge() {
LogDebugInfo("Exception when invoking loginChallenge JS callback.");
}
+void ChromotingScriptableObject::AttachXmppProxy(XmppProxy* xmpp_proxy) {
+ xmpp_proxy_ = xmpp_proxy;
+}
+
+void ChromotingScriptableObject::SendIq(const std::string& iq_request_xml) {
+ // TODO(ajwong): Do something smart here.
+ NOTIMPLEMENTED();
+}
+
+void ChromotingScriptableObject::ReceiveIq(const std::string& iq_response_xml) {
+ xmpp_proxy_->ReceiveIq(iq_response_xml);
+}
+
Var ChromotingScriptableObject::DoConnect(const std::vector<Var>& args,
Var* exception) {
if (args.size() != 3) {
diff --git a/remoting/client/plugin/chromoting_scriptable_object.h b/remoting/client/plugin/chromoting_scriptable_object.h
index aec9c23..b8b848e62 100644
--- a/remoting/client/plugin/chromoting_scriptable_object.h
+++ b/remoting/client/plugin/chromoting_scriptable_object.h
@@ -65,12 +65,15 @@
#include <string>
#include <vector>
+#include "base/weak_ptr.h"
+
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"
#include "ppapi/cpp/var.h"
namespace remoting {
class ChromotingInstance;
+class XmppProxy;
extern const char kStatusAttribute[];
@@ -91,7 +94,9 @@ enum ConnectionQuality {
QUALITY_BAD,
};
-class ChromotingScriptableObject : public pp::deprecated::ScriptableObject {
+class ChromotingScriptableObject
+ : public pp::deprecated::ScriptableObject,
+ public base::SupportsWeakPtr<ChromotingScriptableObject> {
public:
explicit ChromotingScriptableObject(ChromotingInstance* instance);
virtual ~ChromotingScriptableObject();
@@ -118,6 +123,12 @@ class ChromotingScriptableObject : public pp::deprecated::ScriptableObject {
// This should be called to signal JS code to provide login information.
void SignalLoginChallenge();
+ // Handles a Request/Response for a Javascript IQ stanza used to initiate a
+ // jingle connection.
+ void AttachXmppProxy(XmppProxy* xmpp_proxy);
+ void SendIq(const std::string& iq_request_xml);
+ void ReceiveIq(const std::string& iq_response_xml);
+
private:
typedef std::map<std::string, int> PropertyNameMap;
typedef pp::Var (ChromotingScriptableObject::*MethodHandler)(
@@ -141,7 +152,6 @@ class ChromotingScriptableObject : public pp::deprecated::ScriptableObject {
MethodHandler method;
};
-
// Routines to add new attribute, method properties.
void AddAttribute(const std::string& name, pp::Var attribute);
void AddMethod(const std::string& name, MethodHandler handler);
@@ -158,6 +168,7 @@ class ChromotingScriptableObject : public pp::deprecated::ScriptableObject {
PropertyNameMap property_names_;
std::vector<PropertyDescriptor> properties_;
+ scoped_refptr<XmppProxy> xmpp_proxy_;
ChromotingInstance* instance_;
};
diff --git a/remoting/client/plugin/pepper_xmpp_proxy.cc b/remoting/client/plugin/pepper_xmpp_proxy.cc
new file mode 100644
index 0000000..7e4c26c
--- /dev/null
+++ b/remoting/client/plugin/pepper_xmpp_proxy.cc
@@ -0,0 +1,57 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/client/plugin/pepper_xmpp_proxy.h"
+
+namespace remoting {
+
+PepperXmppProxy::PepperXmppProxy(MessageLoop* jingle_message_loop,
+ MessageLoop* pepper_message_loop)
+ : jingle_message_loop_(jingle_message_loop),
+ pepper_message_loop_(pepper_message_loop) {
+}
+
+void PepperXmppProxy::AttachScriptableObject(
+ ChromotingScriptableObject* scriptable_object,
+ Task* done) {
+ DCHECK_EQ(jingle_message_loop_, MessageLoop::Current());
+ scriptable_object_ = scriptable_object;
+ scriptable_object_->AttachXmppProxy(this);
+}
+
+void PepperXmppProxy::AttachJavascriptIqRequest(
+ JavascriptIqRequest* javascript_iq_request) {
+ DCHECK_EQ(pepper_message_loop_, MessageLoop::Current());
+ javascript_iq_request_ = javascript_iq_request;
+}
+
+void PepperXmppProxy::SendIq(const std::string& iq_request_xml) {
+ if (MessageLoop::Current() != pepper_message_loop_) {
+ pepper_message_loop_->PostTask(
+ NewRunnableMethod(this,
+ &PepperXmppProxy::SendIq,
+ iq_request_xml));
+ return;
+ }
+
+ if (scriptable_object_) {
+ scriptable_object_->SendIq(iq_request_xml, this);
+ }
+}
+
+void PepperXmppProxy::ReceiveIq(const std::string& iq_response_xml) {
+ if (MessageLoop::Current() != jingle_message_loop_) {
+ jingle_message_loop_->PostTask(
+ NewRunnableMethod(this,
+ &PepperXmppProxy::ReceiveIq,
+ iq_response_xml));
+ return;
+ }
+
+ if (javascript_iq_request_) {
+ javascript_iq_request_->handleIqResponse(iq_response_xml);
+ }
+}
+
+} // namespace remoting
diff --git a/remoting/client/plugin/pepper_xmpp_proxy.h b/remoting/client/plugin/pepper_xmpp_proxy.h
new file mode 100644
index 0000000..6c6c553
--- /dev/null
+++ b/remoting/client/plugin/pepper_xmpp_proxy.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_CLIENT_PLUGIN_PEPPER_XMPP_PROXY_H_
+#define REMOTING_CLIENT_PLUGIN_PEPPER_XMPP_PROXY_H_
+
+#include "base/weak_ptr.h"
+#include "remoting/jingle_glue/iq_request.h"
+
+namespace remoting {
+
+class PepperXmppProxy : public XmppProxy {
+ public:
+ PepperXmppProxy(MessageLoop* jingle_message_loop,
+ MessageLoop* pepper_message_loop);
+
+ // Must be run on pepper thread.
+ void AttachScriptableObject(ChromotingScriptableObject* scriptable_object);
+
+ // Must be run on jingle thread.
+ void AttachJavascriptIqRequest(JavascriptIqRequest* javascript_iq_request);
+
+ void SendIq(const std::string& iq_request_xml);
+ void ReceiveIq(const std::string& iq_response_xml);
+
+ private:
+ ~PepperXmppProxy();
+
+ MessageLoop* jingle_message_loop_;
+ MessageLoop* pepper_message_loop_;
+
+ base::WeakPtr<ChromotingScriptableObject> scriptable_object_;
+ base::WeakPtr<JavascriptIqRequest> javascript_iq_request_;
+ std::string iq_response_xml_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperXmppProxy);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_CLIENT_PLUGIN_PEPPER_XMPP_PROXY_H_
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc
index 38437e8..9522b5c 100644
--- a/remoting/host/chromoting_host.cc
+++ b/remoting/host/chromoting_host.cc
@@ -97,12 +97,19 @@ void ChromotingHost::Start(Task* shutdown_task) {
return;
// Connect to the talk network with a JingleClient.
- jingle_client_ = new JingleClient(context_->jingle_thread());
- jingle_client_->Init(xmpp_login, xmpp_auth_token,
- kChromotingTokenServiceName, this);
-
- heartbeat_sender_ = new HeartbeatSender();
- if (!heartbeat_sender_->Init(config_, jingle_client_.get())) {
+ signal_strategy_.reset(
+ new XmppSignalStrategy(context_->jingle_thread(), xmpp_login,
+ xmpp_auth_token,
+ kChromotingTokenServiceName));
+ jingle_client_ = new JingleClient(context_->jingle_thread(),
+ signal_strategy_.get(),
+ this);
+ jingle_client_->Init();
+
+ heartbeat_sender_ =
+ new HeartbeatSender(context_->jingle_thread()->message_loop(),
+ jingle_client_.get(), config_);
+ if (!heartbeat_sender_->Init()) {
LOG(ERROR) << "Failed to initialize HeartbeatSender.";
return;
}
diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h
index 5a5959f..fc6daaf 100644
--- a/remoting/host/chromoting_host.h
+++ b/remoting/host/chromoting_host.h
@@ -154,6 +154,8 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>,
scoped_ptr<DesktopEnvironment> desktop_environment_;
+ scoped_ptr<SignalStrategy> signal_strategy_;
+
// The libjingle client. This is used to connect to the talk network to
// receive connection requests from chromoting client.
scoped_refptr<JingleClient> jingle_client_;
diff --git a/remoting/host/heartbeat_sender.cc b/remoting/host/heartbeat_sender.cc
index 74c08c3..56ec751 100644
--- a/remoting/host/heartbeat_sender.cc
+++ b/remoting/host/heartbeat_sender.cc
@@ -33,29 +33,32 @@ const char kSetIntervalTag[] = "set-interval";
const int64 kDefaultHeartbeatIntervalMs = 5 * 60 * 1000; // 5 minutes.
}
-HeartbeatSender::HeartbeatSender()
+HeartbeatSender::HeartbeatSender(MessageLoop* message_loop,
+ JingleClient* jingle_client,
+ MutableHostConfig* config)
+
: state_(CREATED),
+ message_loop_(message_loop),
+ jingle_client_(jingle_client),
+ config_(config),
interval_ms_(kDefaultHeartbeatIntervalMs) {
+ DCHECK(jingle_client_);
+ DCHECK(config_);
}
HeartbeatSender::~HeartbeatSender() {
DCHECK(state_ == CREATED || state_ == INITIALIZED || state_ == STOPPED);
}
-bool HeartbeatSender::Init(MutableHostConfig* config,
- JingleClient* jingle_client) {
- DCHECK(jingle_client);
+bool HeartbeatSender::Init() {
DCHECK(state_ == CREATED);
- jingle_client_ = jingle_client;
- config_ = config;
-
if (!config_->GetString(kHostIdConfigPath, &host_id_)) {
LOG(ERROR) << "host_id is not defined in the config.";
return false;
}
- if (!key_pair_.Load(config)) {
+ if (!key_pair_.Load(config_)) {
return false;
}
@@ -65,8 +68,8 @@ bool HeartbeatSender::Init(MutableHostConfig* config,
}
void HeartbeatSender::Start() {
- if (MessageLoop::current() != jingle_client_->message_loop()) {
- jingle_client_->message_loop()->PostTask(
+ if (MessageLoop::current() != message_loop_) {
+ message_loop_->PostTask(
FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::Start));
return;
}
@@ -77,13 +80,13 @@ void HeartbeatSender::Start() {
request_.reset(jingle_client_->CreateIqRequest());
request_->set_callback(NewCallback(this, &HeartbeatSender::ProcessResponse));
- jingle_client_->message_loop()->PostTask(
+ message_loop_->PostTask(
FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::DoSendStanza));
}
void HeartbeatSender::Stop() {
- if (MessageLoop::current() != jingle_client_->message_loop()) {
- jingle_client_->message_loop()->PostTask(
+ if (MessageLoop::current() != message_loop_) {
+ message_loop_->PostTask(
FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::Stop));
return;
}
@@ -99,7 +102,7 @@ void HeartbeatSender::DoSendStanza() {
if (state_ == STARTED) {
// |jingle_client_| may be already destroyed if |state_| is set to
// |STOPPED|, so don't touch it here unless we are in |STARTED| state.
- DCHECK(MessageLoop::current() == jingle_client_->message_loop());
+ DCHECK(MessageLoop::current() == message_loop_);
VLOG(1) << "Sending heartbeat stanza to " << kChromotingBotJid;
@@ -107,7 +110,7 @@ void HeartbeatSender::DoSendStanza() {
CreateHeartbeatMessage());
// Schedule next heartbeat.
- jingle_client_->message_loop()->PostDelayedTask(
+ message_loop_->PostDelayedTask(
FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::DoSendStanza),
interval_ms_);
}
diff --git a/remoting/host/heartbeat_sender.h b/remoting/host/heartbeat_sender.h
index ef310b4..089e040 100644
--- a/remoting/host/heartbeat_sender.h
+++ b/remoting/host/heartbeat_sender.h
@@ -18,6 +18,7 @@ namespace remoting {
class IqRequest;
class HostKeyPair;
class JingleClient;
+class JingleThread;
class MutableHostConfig;
// HeartbeatSender periodically sends heartbeat stanzas to the Chromoting Bot.
@@ -56,13 +57,14 @@ class MutableHostConfig;
// TODO(sergeyu): Is it enough to sign JID and nothing else?
class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
public:
- HeartbeatSender();
+ HeartbeatSender(MessageLoop* main_loop,
+ JingleClient* jingle_client,
+ MutableHostConfig* config);
virtual ~HeartbeatSender();
- // Initializes heart-beating for |jingle_client| with the specified
- // config. Returns false if the config is invalid (e.g. private key
- // cannot be parsed).
- bool Init(MutableHostConfig* config, JingleClient* jingle_client);
+ // Initializes heart-beating for |jingle_client_| with |config_|. Returns
+ // false if the config is invalid (e.g. private key cannot be parsed).
+ bool Init();
// Starts heart-beating. Must be called after init.
void Start();
@@ -96,8 +98,9 @@ class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
void ProcessResponse(const buzz::XmlElement* response);
State state_;
- scoped_refptr<MutableHostConfig> config_;
+ MessageLoop* message_loop_;
JingleClient* jingle_client_;
+ scoped_refptr<MutableHostConfig> config_;
scoped_ptr<IqRequest> request_;
std::string host_id_;
HostKeyPair key_pair_;
diff --git a/remoting/host/heartbeat_sender_unittest.cc b/remoting/host/heartbeat_sender_unittest.cc
index 6e1f4fe..fc59c33 100644
--- a/remoting/host/heartbeat_sender_unittest.cc
+++ b/remoting/host/heartbeat_sender_unittest.cc
@@ -36,20 +36,21 @@ const char kTestJid[] = "user@gmail.com/chromoting123";
const int64 kTestTime = 123123123;
} // namespace
-class MockJingleClient : public JingleClient {
+class MockSignalStrategy : public SignalStrategy {
public:
- explicit MockJingleClient(JingleThread* thread) : JingleClient(thread) { }
+ MOCK_METHOD1(Init, void(StatusObserver* observer));
+ MOCK_METHOD0(port_allocator, cricket::BasicPortAllocator*());
+ MOCK_METHOD1(StartSession, void(cricket::SessionManager* session_manager));
+ MOCK_METHOD0(EndSession, void());
MOCK_METHOD0(CreateIqRequest, IqRequest*());
};
class MockIqRequest : public IqRequest {
public:
- explicit MockIqRequest(JingleClient* jingle_client)
- : IqRequest(jingle_client) {
- }
MOCK_METHOD3(SendIq, void(const std::string& type,
const std::string& addressee,
XmlElement* iq_body));
+ MOCK_METHOD1(set_callback, void(IqRequest::ReplyCallback*));
};
class HeartbeatSenderTest : public testing::Test {
@@ -61,12 +62,15 @@ class HeartbeatSenderTest : public testing::Test {
jingle_thread_.message_loop_ = &message_loop_;
- jingle_client_ = new MockJingleClient(&jingle_thread_);
+ signal_strategy_.reset(new MockSignalStrategy());
+ jingle_client_ =
+ new JingleClient(&jingle_thread_, signal_strategy_.get(), NULL);
jingle_client_->full_jid_ = kTestJid;
}
JingleThread jingle_thread_;
- scoped_refptr<MockJingleClient> jingle_client_;
+ scoped_ptr<MockSignalStrategy> signal_strategy_;
+ scoped_refptr<JingleClient> jingle_client_;
MessageLoop message_loop_;
scoped_refptr<InMemoryHostConfig> config_;
};
@@ -75,12 +79,14 @@ class HeartbeatSenderTest : public testing::Test {
// being send.
TEST_F(HeartbeatSenderTest, DoSendStanza) {
// |iq_request| is freed by HeartbeatSender.
- MockIqRequest* iq_request = new MockIqRequest(jingle_client_);
+ MockIqRequest* iq_request = new MockIqRequest();
+ EXPECT_CALL(*iq_request, set_callback(_)).Times(1);
- scoped_refptr<HeartbeatSender> heartbeat_sender(new HeartbeatSender());
- ASSERT_TRUE(heartbeat_sender->Init(config_, jingle_client_));
+ scoped_refptr<HeartbeatSender> heartbeat_sender(
+ new HeartbeatSender(&message_loop_, jingle_client_.get(), config_));
+ ASSERT_TRUE(heartbeat_sender->Init());
- EXPECT_CALL(*jingle_client_, CreateIqRequest())
+ EXPECT_CALL(*signal_strategy_, CreateIqRequest())
.WillOnce(Return(iq_request));
EXPECT_CALL(*iq_request, SendIq(buzz::STR_SET, kChromotingBotJid, NotNull()))
@@ -95,8 +101,9 @@ TEST_F(HeartbeatSenderTest, DoSendStanza) {
// Validate format of the heartbeat stanza.
TEST_F(HeartbeatSenderTest, CreateHeartbeatMessage) {
- scoped_refptr<HeartbeatSender> heartbeat_sender(new HeartbeatSender());
- ASSERT_TRUE(heartbeat_sender->Init(config_, jingle_client_));
+ scoped_refptr<HeartbeatSender> heartbeat_sender(
+ new HeartbeatSender(&message_loop_, jingle_client_.get(), config_));
+ ASSERT_TRUE(heartbeat_sender->Init());
int64 start_time = static_cast<int64>(base::Time::Now().ToDoubleT());
@@ -145,7 +152,8 @@ TEST_F(HeartbeatSenderTest, ProcessResponse) {
const int kTestInterval = 123;
set_interval->AddText(base::IntToString(kTestInterval));
- scoped_refptr<HeartbeatSender> heartbeat_sender(new HeartbeatSender());
+ scoped_refptr<HeartbeatSender> heartbeat_sender(
+ new HeartbeatSender(&message_loop_, jingle_client_.get(), config_));
heartbeat_sender->ProcessResponse(response.get());
EXPECT_EQ(kTestInterval * 1000, heartbeat_sender->interval_ms_);
diff --git a/remoting/jingle_glue/iq_request.cc b/remoting/jingle_glue/iq_request.cc
index c56ef4c..8d53b40 100644
--- a/remoting/jingle_glue/iq_request.cc
+++ b/remoting/jingle_glue/iq_request.cc
@@ -7,28 +7,42 @@
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/scoped_ptr.h"
-#include "remoting/jingle_glue/jingle_client.h"
#include "third_party/libjingle/source/talk/xmpp/constants.h"
-#include "third_party/libjingle/source/talk/xmpp/xmppengine.h"
+#include "third_party/libjingle/source/talk/xmpp/xmppclient.h"
namespace remoting {
-IqRequest::IqRequest(JingleClient* jingle_client)
- : jingle_client_(jingle_client),
+// static
+buzz::XmlElement* IqRequest::MakeIqStanza(const std::string& type,
+ const std::string& addressee,
+ buzz::XmlElement* iq_body,
+ const std::string& id) {
+ buzz::XmlElement* stanza = new buzz::XmlElement(buzz::QN_IQ);
+ stanza->AddAttr(buzz::QN_TYPE, type);
+ stanza->AddAttr(buzz::QN_TO, addressee);
+ stanza->AddAttr(buzz::QN_ID, id);
+ stanza->AddElement(iq_body);
+ return stanza;
+}
+
+XmppIqRequest::XmppIqRequest(MessageLoop* message_loop,
+ buzz::XmppClient* xmpp_client)
+ : message_loop_(message_loop),
+ xmpp_client_(xmpp_client),
cookie_(NULL) {
- DCHECK(jingle_client_ != NULL);
- DCHECK(MessageLoop::current() == jingle_client_->message_loop());
+ DCHECK(xmpp_client_);
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
}
-IqRequest::~IqRequest() {
- DCHECK(MessageLoop::current() == jingle_client_->message_loop());
+XmppIqRequest::~XmppIqRequest() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
Unregister();
}
-void IqRequest::SendIq(const std::string& type,
+void XmppIqRequest::SendIq(const std::string& type,
const std::string& addressee,
buzz::XmlElement* iq_body) {
- DCHECK(MessageLoop::current() == jingle_client_->message_loop());
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
// Unregister the handler if it is already registered.
Unregister();
@@ -36,44 +50,54 @@ void IqRequest::SendIq(const std::string& type,
DCHECK_GT(type.length(), 0U);
DCHECK_GT(addressee.length(), 0U);
- buzz::XmppClient* xmpp_client = jingle_client_->xmpp_client();
- DCHECK(xmpp_client); // Expect that connection is active.
-
scoped_ptr<buzz::XmlElement> stanza(MakeIqStanza(type, addressee, iq_body,
- xmpp_client->NextId()));
+ xmpp_client_->NextId()));
- xmpp_client->engine()->SendIq(stanza.get(), this, &cookie_);
-}
-
-// static
-buzz::XmlElement* IqRequest::MakeIqStanza(const std::string& type,
- const std::string& addressee,
- buzz::XmlElement* iq_body,
- const std::string& id) {
- buzz::XmlElement* stanza = new buzz::XmlElement(buzz::QN_IQ);
- stanza->AddAttr(buzz::QN_TYPE, type);
- stanza->AddAttr(buzz::QN_TO, addressee);
- stanza->AddAttr(buzz::QN_ID, id);
- stanza->AddElement(iq_body);
- return stanza;
+ xmpp_client_->engine()->SendIq(stanza.get(), this, &cookie_);
}
-void IqRequest::Unregister() {
+void XmppIqRequest::Unregister() {
if (cookie_) {
- buzz::XmppClient* xmpp_client = jingle_client_->xmpp_client();
// No need to unregister the handler if the client has been destroyed.
- if (xmpp_client) {
- xmpp_client->engine()->RemoveIqHandler(cookie_, NULL);
+ if (xmpp_client_) {
+ xmpp_client_->engine()->RemoveIqHandler(cookie_, NULL);
}
cookie_ = NULL;
}
}
-void IqRequest::IqResponse(buzz::XmppIqCookie cookie,
+void XmppIqRequest::IqResponse(buzz::XmppIqCookie cookie,
const buzz::XmlElement* stanza) {
if (callback_.get() != NULL) {
callback_->Run(stanza);
}
}
+JavascriptIqRequest::JavascriptIqRequest() {
+}
+
+JavascriptIqRequest::~JavascriptIqRequest() {
+}
+
+void JavascriptIqRequest::SendIq(const std::string& type,
+ const std::string& addressee,
+ buzz::XmlElement* iq_body) {
+ NOTIMPLEMENTED();
+ // TODO(ajwong): The "1" below is completely wrong. Need to change to use a
+ // sequence that just increments or something.
+ scoped_ptr<buzz::XmlElement> stanza(
+ MakeIqStanza(type, addressee, iq_body, "1"));
+
+ xmpp_proxy_->SendIq(stanza->Str());
+}
+
+void JavascriptIqRequest::ReceiveIq(const std::string& iq_response) {
+ // TODO(ajwong): Somehow send this to callback_ here.
+ LOG(ERROR) << "Got IQ!!!!!!\n" << iq_response;
+}
+
+void JavascriptIqRequest::set_callback(ReplyCallback* callback) {
+ callback_.reset(callback);
+}
+
} // namespace remoting
diff --git a/remoting/jingle_glue/iq_request.h b/remoting/jingle_glue/iq_request.h
index 6933b17..3d11034 100644
--- a/remoting/jingle_glue/iq_request.h
+++ b/remoting/jingle_glue/iq_request.h
@@ -9,11 +9,42 @@
#include "base/callback.h"
#include "base/gtest_prod_util.h"
+#include "base/weak_ptr.h"
#include "third_party/libjingle/source/talk/xmpp/xmppengine.h"
+class MessageLoop;
+
+namespace buzz {
+class XmppClient;
+} // namespace buzz
+
namespace remoting {
-class JingleClient;
+class JavascriptIqRequest;
+class ChromotingScriptableObject;
+
+class XmppProxy : public base::RefCountedThreadSafe<XmppProxy> {
+ public:
+ XmppProxy() {}
+
+ // Must be run on pepper thread.
+ virtual void AttachScriptableObject(
+ ChromotingScriptableObject* scriptable_object) = 0;
+
+ // Must be run on jingle thread.
+ virtual void AttachJavascriptIqRequest(
+ JavascriptIqRequest* javascript_iq_request) = 0;
+
+ virtual void SendIq(const std::string& iq_request_xml) = 0;
+ virtual void ReceiveIq(const std::string& iq_response_xml) = 0;
+
+ protected:
+ friend class base::RefCountedThreadSafe<XmppProxy>;
+ virtual ~XmppProxy() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(XmppProxy);
+};
// IqRequest class can be used to send an IQ stanza and then receive reply
// stanza for that request. It sends outgoing stanza when SendIq() is called,
@@ -21,22 +52,67 @@ class JingleClient;
// set_callback(). If multiple IQ stanzas are send with SendIq() then only reply
// to the last one will be received.
// The class must be used on the jingle thread only.
-class IqRequest : private buzz::XmppIqHandler {
+class IqRequest {
public:
typedef Callback1<const buzz::XmlElement*>::Type ReplyCallback;
- explicit IqRequest(JingleClient* jingle_client);
- virtual ~IqRequest();
+ IqRequest() {}
+ virtual ~IqRequest() {}
// Sends stanza of type |type| to |addressee|. |iq_body| contains body of
// the stanza. Ownership of |iq_body| is transfered to IqRequest. Must
// be called on the jingle thread.
virtual void SendIq(const std::string& type, const std::string& addressee,
- buzz::XmlElement* iq_body);
+ buzz::XmlElement* iq_body) = 0;
// Sets callback that is called when reply stanza is received. Callback
// is called on the jingle thread.
- void set_callback(ReplyCallback* callback) {
+ virtual void set_callback(ReplyCallback* callback) = 0;
+
+ protected:
+ static buzz::XmlElement* MakeIqStanza(const std::string& type,
+ const std::string& addressee,
+ buzz::XmlElement* iq_body,
+ const std::string& id);
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(IqRequestTest, MakeIqStanza);
+
+ DISALLOW_COPY_AND_ASSIGN(IqRequest);
+};
+
+// TODO(ajwong): Is this class even used? The client side may never use
+// IqRequests in the JingleClient.
+class JavascriptIqRequest : public IqRequest,
+ public base::SupportsWeakPtr<JavascriptIqRequest> {
+ public:
+ JavascriptIqRequest();
+ virtual ~JavascriptIqRequest();
+
+ virtual void SendIq(const std::string& type, const std::string& addressee,
+ buzz::XmlElement* iq_body);
+
+ virtual void ReceiveIq(const std::string& iq_response);
+
+ virtual void set_callback(ReplyCallback* callback);
+
+ private:
+ scoped_ptr<ReplyCallback> callback_;
+ scoped_refptr<XmppProxy> xmpp_proxy_;
+
+ FRIEND_TEST_ALL_PREFIXES(IqRequestTest, MakeIqStanza);
+};
+
+class XmppIqRequest : public IqRequest, private buzz::XmppIqHandler {
+ public:
+ typedef Callback1<const buzz::XmlElement*>::Type ReplyCallback;
+
+ XmppIqRequest(MessageLoop* message_loop, buzz::XmppClient* xmpp_client);
+ virtual ~XmppIqRequest();
+
+ virtual void SendIq(const std::string& type, const std::string& addressee,
+ buzz::XmlElement* iq_body);
+ virtual void set_callback(ReplyCallback* callback) {
callback_.reset(callback);
}
@@ -47,14 +123,12 @@ class IqRequest : private buzz::XmppIqHandler {
virtual void IqResponse(buzz::XmppIqCookie cookie,
const buzz::XmlElement* stanza);
- static buzz::XmlElement* MakeIqStanza(const std::string& type,
- const std::string& addressee,
- buzz::XmlElement* iq_body,
- const std::string& id);
-
void Unregister();
- scoped_refptr<JingleClient> jingle_client_;
+ // TODO(ajwong): This used to hold a reference to the jingle client...make
+ // sure the lifetime names sense now.
+ MessageLoop* message_loop_;
+ buzz::XmppClient* xmpp_client_;
buzz::XmppIqCookie cookie_;
scoped_ptr<ReplyCallback> callback_;
};
diff --git a/remoting/jingle_glue/jingle_client.cc b/remoting/jingle_glue/jingle_client.cc
index 7b00d79..02593ed 100644
--- a/remoting/jingle_glue/jingle_client.cc
+++ b/remoting/jingle_glue/jingle_client.cc
@@ -22,79 +22,178 @@
namespace remoting {
-JingleClient::JingleClient(JingleThread* thread)
- : thread_(thread),
- callback_(NULL),
- client_(NULL),
- state_(START),
- initialized_(false),
- closed_(false) {
-}
-
-JingleClient::~JingleClient() {
- base::AutoLock auto_lock(state_lock_);
- DCHECK(!initialized_ || closed_);
+// The XmppSignalStrategy encapsulates all the logic to perform the signaling
+// STUN/ICE for jingle via a direct XMPP connection.
+//
+// This class is not threadsafe.
+XmppSignalStrategy::XmppSignalStrategy(JingleThread* jingle_thread,
+ const std::string& username,
+ const std::string& auth_token,
+ const std::string& auth_token_service)
+ : thread_(jingle_thread),
+ username_(username),
+ auth_token_(auth_token),
+ auth_token_service_(auth_token_service),
+ xmpp_client_(NULL),
+ observer_(NULL) {
}
-void JingleClient::Init(
- const std::string& username, const std::string& auth_token,
- const std::string& auth_token_service, Callback* callback) {
- DCHECK_NE(username, "");
-
- {
- base::AutoLock auto_lock(state_lock_);
- DCHECK(!initialized_ && !closed_);
- initialized_ = true;
-
- DCHECK(callback != NULL);
- callback_ = callback;
- }
-
- message_loop()->PostTask(
- FROM_HERE, NewRunnableMethod(this, &JingleClient::DoInitialize,
- username, auth_token, auth_token_service));
+XmppSignalStrategy::~XmppSignalStrategy() {
}
-void JingleClient::DoInitialize(const std::string& username,
- const std::string& auth_token,
- const std::string& auth_token_service) {
- DCHECK_EQ(message_loop(), MessageLoop::current());
+void XmppSignalStrategy::Init(StatusObserver* observer) {
+ observer_ = observer;
- buzz::Jid login_jid(username);
+ buzz::Jid login_jid(username_);
buzz::XmppClientSettings settings;
settings.set_user(login_jid.node());
settings.set_host(login_jid.domain());
settings.set_resource("chromoting");
settings.set_use_tls(true);
- settings.set_token_service(auth_token_service);
- settings.set_auth_cookie(auth_token);
+ settings.set_token_service(auth_token_service_);
+ settings.set_auth_cookie(auth_token_);
settings.set_server(talk_base::SocketAddress("talk.google.com", 5222));
- client_ = new buzz::XmppClient(thread_->task_pump());
- client_->SignalStateChange.connect(
- this, &JingleClient::OnConnectionStateChanged);
-
buzz::AsyncSocket* socket = new XmppSocketAdapter(settings, false);
- client_->Connect(settings, "", socket, CreatePreXmppAuth(settings));
- client_->Start();
+ xmpp_client_ = new buzz::XmppClient(thread_->task_pump());
+ xmpp_client_->Connect(settings, "", socket, CreatePreXmppAuth(settings));
+ xmpp_client_->SignalStateChange.connect(
+ this, &XmppSignalStrategy::OnConnectionStateChanged);
+ xmpp_client_->Start();
+ // Setup the port allocation based on jingle connections.
network_manager_.reset(new talk_base::NetworkManager());
-
RelayPortAllocator* port_allocator =
new RelayPortAllocator(network_manager_.get(), "transp2");
+ port_allocator->SetJingleInfo(xmpp_client_);
port_allocator_.reset(port_allocator);
- port_allocator->SetJingleInfo(client_);
+}
- session_manager_.reset(new cricket::SessionManager(port_allocator_.get()));
+cricket::BasicPortAllocator* XmppSignalStrategy::port_allocator() {
+ return port_allocator_.get();
+}
+void XmppSignalStrategy::StartSession(
+ cricket::SessionManager* session_manager) {
cricket::SessionManagerTask* receiver =
- new cricket::SessionManagerTask(client_, session_manager_.get());
+ new cricket::SessionManagerTask(xmpp_client_, session_manager);
receiver->EnableOutgoingMessages();
receiver->Start();
}
+void XmppSignalStrategy::EndSession() {
+ if (xmpp_client_) {
+ xmpp_client_->Disconnect();
+ // Client is deleted by TaskRunner.
+ xmpp_client_ = NULL;
+ }
+}
+
+IqRequest* XmppSignalStrategy::CreateIqRequest() {
+ return new XmppIqRequest(thread_->message_loop(), xmpp_client_);
+}
+
+void XmppSignalStrategy::OnConnectionStateChanged(
+ buzz::XmppEngine::State state) {
+ switch (state) {
+ case buzz::XmppEngine::STATE_START:
+ observer_->OnStateChange(StatusObserver::START);
+ break;
+ case buzz::XmppEngine::STATE_OPENING:
+ observer_->OnStateChange(StatusObserver::CONNECTING);
+ break;
+ case buzz::XmppEngine::STATE_OPEN:
+ observer_->OnJidChange(xmpp_client_->jid().Str());
+ observer_->OnStateChange(StatusObserver::CONNECTED);
+ break;
+ case buzz::XmppEngine::STATE_CLOSED:
+ observer_->OnStateChange(StatusObserver::CLOSED);
+ // Client is destroyed by the TaskRunner after the client is
+ // closed. Reset the pointer so we don't try to use it later.
+ xmpp_client_ = NULL;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+buzz::PreXmppAuth* XmppSignalStrategy::CreatePreXmppAuth(
+ const buzz::XmppClientSettings& settings) {
+ buzz::Jid jid(settings.user(), settings.host(), buzz::STR_EMPTY);
+ return new notifier::GaiaTokenPreXmppAuth(jid.Str(), settings.auth_cookie(),
+ settings.token_service());
+}
+
+
+JavascriptSignalStrategy::JavascriptSignalStrategy() {
+}
+
+JavascriptSignalStrategy::~JavascriptSignalStrategy() {
+}
+
+void JavascriptSignalStrategy::Init(StatusObserver* observer) {
+ NOTIMPLEMENTED();
+}
+
+cricket::BasicPortAllocator* JavascriptSignalStrategy::port_allocator() {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+void JavascriptSignalStrategy::StartSession(
+ cricket::SessionManager* session_manager) {
+ NOTIMPLEMENTED();
+}
+
+void JavascriptSignalStrategy::EndSession() {
+ NOTIMPLEMENTED();
+}
+
+IqRequest* JavascriptSignalStrategy::CreateIqRequest() {
+ return new JavascriptIqRequest();
+}
+
+JingleClient::JingleClient(JingleThread* thread,
+ SignalStrategy* signal_strategy,
+ Callback* callback)
+ : thread_(thread),
+ state_(START),
+ initialized_(false),
+ closed_(false),
+ callback_(callback),
+ signal_strategy_(signal_strategy) {
+}
+
+JingleClient::~JingleClient() {
+ base::AutoLock auto_lock(state_lock_);
+ DCHECK(!initialized_ || closed_);
+}
+
+void JingleClient::Init() {
+ {
+ base::AutoLock auto_lock(state_lock_);
+ DCHECK(!initialized_ && !closed_);
+ initialized_ = true;
+ }
+
+ message_loop()->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &JingleClient::DoInitialize));
+}
+
+void JingleClient::DoInitialize() {
+ DCHECK_EQ(message_loop(), MessageLoop::current());
+
+ signal_strategy_->Init(this);
+
+ session_manager_.reset(
+ new cricket::SessionManager(signal_strategy_->port_allocator()));
+
+ signal_strategy_->StartSession(session_manager_.get());
+}
+
void JingleClient::Close() {
Close(NULL);
}
@@ -121,14 +220,9 @@ void JingleClient::DoClose() {
DCHECK(closed_);
session_manager_.reset();
- port_allocator_.reset();
- network_manager_.reset();
-
- if (client_) {
- client_->Disconnect();
- // Client is deleted by TaskRunner.
- client_ = NULL;
- }
+ signal_strategy_->EndSession();
+ // TODO(ajwong): SignalStrategy should drop all resources at EndSession().
+ signal_strategy_ = NULL;
if (closed_task_.get()) {
closed_task_->Run();
@@ -137,12 +231,12 @@ void JingleClient::DoClose() {
}
std::string JingleClient::GetFullJid() {
- base::AutoLock auto_lock(full_jid_lock_);
+ base::AutoLock auto_lock(jid_lock_);
return full_jid_;
}
IqRequest* JingleClient::CreateIqRequest() {
- return new IqRequest(this);
+ return signal_strategy_->CreateIqRequest();
}
MessageLoop* JingleClient::message_loop() {
@@ -154,36 +248,7 @@ cricket::SessionManager* JingleClient::session_manager() {
return session_manager_.get();
}
-void JingleClient::OnConnectionStateChanged(buzz::XmppEngine::State state) {
- switch (state) {
- case buzz::XmppEngine::STATE_START:
- UpdateState(START);
- break;
- case buzz::XmppEngine::STATE_OPENING:
- UpdateState(CONNECTING);
- break;
- case buzz::XmppEngine::STATE_OPEN:
- SetFullJid(client_->jid().Str());
- UpdateState(CONNECTED);
- break;
- case buzz::XmppEngine::STATE_CLOSED:
- UpdateState(CLOSED);
- // Client is destroyed by the TaskRunner after the client is
- // closed. Reset the pointer so we don't try to use it later.
- client_ = NULL;
- break;
- default:
- NOTREACHED();
- break;
- }
-}
-
-void JingleClient::SetFullJid(const std::string& full_jid) {
- base::AutoLock auto_lock(full_jid_lock_);
- full_jid_ = full_jid;
-}
-
-void JingleClient::UpdateState(State new_state) {
+void JingleClient::OnStateChange(State new_state) {
if (new_state != state_) {
state_ = new_state;
{
@@ -196,11 +261,9 @@ void JingleClient::UpdateState(State new_state) {
}
}
-buzz::PreXmppAuth* JingleClient::CreatePreXmppAuth(
- const buzz::XmppClientSettings& settings) {
- buzz::Jid jid(settings.user(), settings.host(), buzz::STR_EMPTY);
- return new notifier::GaiaTokenPreXmppAuth(jid.Str(), settings.auth_cookie(),
- settings.token_service());
+void JingleClient::OnJidChange(const std::string& full_jid) {
+ base::AutoLock auto_lock(jid_lock_);
+ full_jid_ = full_jid;
}
} // namespace remoting
diff --git a/remoting/jingle_glue/jingle_client.h b/remoting/jingle_glue/jingle_client.h
index 173e90e..f60e029 100644
--- a/remoting/jingle_glue/jingle_client.h
+++ b/remoting/jingle_glue/jingle_client.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/gtest_prod_util.h"
#include "base/ref_counted.h"
#include "base/synchronization/lock.h"
#include "third_party/libjingle/source/talk/xmpp/xmppclient.h"
@@ -35,16 +36,90 @@ namespace remoting {
class IqRequest;
class JingleThread;
-class JingleClient : public base::RefCountedThreadSafe<JingleClient>,
- public sigslot::has_slots<> {
+// TODO(ajwong): The SignalStrategy stuff needs to be separated out to separate
+// files.
+class SignalStrategy {
public:
- enum State {
- START, // Initial state.
- CONNECTING,
- CONNECTED,
- CLOSED,
+ class StatusObserver {
+ public:
+ enum State {
+ START,
+ CONNECTING,
+ CONNECTED,
+ CLOSED,
+ };
+
+ // Called when state of the connection is changed.
+ virtual void OnStateChange(State state) = 0;
+ virtual void OnJidChange(const std::string& full_jid) = 0;
};
+ SignalStrategy() {}
+ virtual ~SignalStrategy() {}
+ virtual void Init(StatusObserver* observer) = 0;
+ virtual cricket::BasicPortAllocator* port_allocator() = 0;
+ virtual void StartSession(cricket::SessionManager* session_manager) = 0;
+ virtual void EndSession() = 0;
+ virtual IqRequest* CreateIqRequest() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SignalStrategy);
+};
+
+class XmppSignalStrategy : public SignalStrategy, public sigslot::has_slots<> {
+ public:
+ XmppSignalStrategy(JingleThread* thread,
+ const std::string& username,
+ const std::string& auth_token,
+ const std::string& auth_token_service);
+ virtual ~XmppSignalStrategy();
+
+ virtual void Init(StatusObserver* observer);
+ virtual cricket::BasicPortAllocator* port_allocator();
+ virtual void StartSession(cricket::SessionManager* session_manager);
+ virtual void EndSession();
+ virtual IqRequest* CreateIqRequest();
+
+ private:
+ void OnConnectionStateChanged(buzz::XmppEngine::State state);
+ static buzz::PreXmppAuth* CreatePreXmppAuth(
+ const buzz::XmppClientSettings& settings);
+
+ JingleThread* thread_;
+
+ std::string username_;
+ std::string auth_token_;
+ std::string auth_token_service_;
+ buzz::XmppClient* xmpp_client_;
+ StatusObserver* observer_;
+ scoped_ptr<talk_base::NetworkManager> network_manager_;
+ scoped_ptr<cricket::BasicPortAllocator> port_allocator_;
+
+ private:
+ friend class JingleClientTest;
+
+ DISALLOW_COPY_AND_ASSIGN(XmppSignalStrategy);
+};
+
+class JavascriptSignalStrategy : public SignalStrategy {
+ public:
+ JavascriptSignalStrategy();
+ virtual ~JavascriptSignalStrategy();
+
+ virtual void Init(StatusObserver* observer);
+ virtual cricket::BasicPortAllocator* port_allocator();
+ virtual void StartSession(cricket::SessionManager* session_manager);
+ virtual void EndSession();
+ virtual IqRequest* CreateIqRequest();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(JavascriptSignalStrategy);
+};
+
+
+class JingleClient : public base::RefCountedThreadSafe<JingleClient>,
+ public SignalStrategy::StatusObserver {
+ public:
class Callback {
public:
virtual ~Callback() {}
@@ -53,17 +128,13 @@ class JingleClient : public base::RefCountedThreadSafe<JingleClient>,
virtual void OnStateChange(JingleClient* client, State state) = 0;
};
- // Creates a JingleClient object that executes on |thread|. This does not
- // take ownership of |thread| and expects that the thread is started before
- // the constructor is called, and only stopped after the JingleClient object
- // has been destructed.
- explicit JingleClient(JingleThread* thread);
- virtual ~JingleClient();
+ JingleClient(JingleThread* thread, SignalStrategy* signal_strategy,
+ Callback* callback);
+ ~JingleClient();
// Starts the XMPP connection initialization. Must be called only once.
// |callback| specifies callback object for the client and must not be NULL.
- void Init(const std::string& username, const std::string& auth_token,
- const std::string& auth_token_service, Callback* callback);
+ void Init();
// Closes XMPP connection and stops the thread. Must be called before the
// object is destroyed. If specified, |closed_task| is executed after the
@@ -77,64 +148,52 @@ class JingleClient : public base::RefCountedThreadSafe<JingleClient>,
// Creates new IqRequest for this client. Ownership for of the created object
// is transfered to the caller.
- virtual IqRequest* CreateIqRequest();
-
- // Current connection state of the client.
- State state() { return state_; }
-
- // Returns XmppClient object for the xmpp connection or NULL if not connected.
- buzz::XmppClient* xmpp_client() { return client_; }
-
- // Message loop used by this object to execute tasks.
- MessageLoop* message_loop();
+ IqRequest* CreateIqRequest();
// The session manager used by this client. Must be called from the
// jingle thread only. Returns NULL if the client is not active.
cricket::SessionManager* session_manager();
+ // Message loop used by this object to execute tasks.
+ MessageLoop* message_loop();
+
private:
friend class HeartbeatSenderTest;
friend class JingleClientTest;
- void OnConnectionStateChanged(buzz::XmppEngine::State state);
-
- void DoInitialize(const std::string& username,
- const std::string& auth_token,
- const std::string& auth_token_service);
-
- // Used by Close().
+ void DoInitialize();
void DoClose();
- void SetFullJid(const std::string& full_jid);
-
// Updates current state of the connection. Must be called only in
// the jingle thread.
void UpdateState(State new_state);
- buzz::PreXmppAuth* CreatePreXmppAuth(
- const buzz::XmppClientSettings& settings);
+ virtual void OnStateChange(State state);
+ virtual void OnJidChange(const std::string& full_jid);
// JingleThread used for the connection. Set in the constructor.
JingleThread* thread_;
- // Callback for this object. Callback must not be called if closed_ == true.
- Callback* callback_;
-
- // The XmppClient and its state and jid.
- buzz::XmppClient* client_;
- State state_;
- base::Lock full_jid_lock_;
- std::string full_jid_;
-
// Current state of the object.
// Must be locked when accessing initialized_ or closed_.
base::Lock state_lock_;
+ State state_;
bool initialized_;
bool closed_;
scoped_ptr<Task> closed_task_;
- scoped_ptr<talk_base::NetworkManager> network_manager_;
- scoped_ptr<cricket::BasicPortAllocator> port_allocator_;
+ // We need a separate lock for the jid since the |state_lock_| may be held
+ // over a callback which can end up having a double lock.
+ //
+ // TODO(ajwong): Can we avoid holding the |state_lock_| over a callback and
+ // remove this extra lock?
+ base::Lock jid_lock_;
+ std::string full_jid_;
+
+ // Callback for this object. Callback must not be called if closed_ == true.
+ Callback* callback_;
+
+ SignalStrategy* signal_strategy_;
scoped_ptr<cricket::SessionManager> session_manager_;
DISALLOW_COPY_AND_ASSIGN(JingleClient);
diff --git a/remoting/jingle_glue/jingle_client_unittest.cc b/remoting/jingle_glue/jingle_client_unittest.cc
index 807f061..3d9f574 100644
--- a/remoting/jingle_glue/jingle_client_unittest.cc
+++ b/remoting/jingle_glue/jingle_client_unittest.cc
@@ -29,22 +29,25 @@ class JingleClientTest : public testing::Test {
// A helper that calls OnConnectionStateChanged(). Need this because we want
// to call it on the jingle thread.
- static void ChangeState(JingleClient* client, buzz::XmppEngine::State state,
+ static void ChangeState(XmppSignalStrategy* strategy,
+ buzz::XmppEngine::State state,
base::WaitableEvent* done_event) {
- client->OnConnectionStateChanged(state);
+ strategy->OnConnectionStateChanged(state);
if (done_event)
done_event->Signal();
}
protected:
virtual void SetUp() {
- client_ = new JingleClient(&thread_);
+ signal_strategy_.reset(new XmppSignalStrategy(&thread_, "", "", ""));
+ client_ = new JingleClient(&thread_, signal_strategy_.get(), &callback_);
// Fake initialization
client_->initialized_ = true;
- client_->callback_ = &callback_;
+ signal_strategy_->observer_ = client_;
}
JingleThread thread_;
+ scoped_ptr<XmppSignalStrategy> signal_strategy_;
scoped_refptr<JingleClient> client_;
MockJingleClientCallback callback_;
};
@@ -57,7 +60,7 @@ TEST_F(JingleClientTest, OnStateChanged) {
base::WaitableEvent state_changed_event(true, false);
thread_.message_loop()->PostTask(FROM_HERE, NewRunnableFunction(
- &JingleClientTest::ChangeState, client_,
+ &JingleClientTest::ChangeState, signal_strategy_.get(),
buzz::XmppEngine::STATE_OPENING, &state_changed_event));
state_changed_event.Wait();
@@ -73,7 +76,7 @@ TEST_F(JingleClientTest, Close) {
client_->Close();
// Verify that the channel doesn't call callback anymore.
thread_.message_loop()->PostTask(FROM_HERE, NewRunnableFunction(
- &JingleClientTest::ChangeState, client_,
+ &JingleClientTest::ChangeState, signal_strategy_.get(),
buzz::XmppEngine::STATE_OPENING,
static_cast<base::WaitableEvent*>(NULL)));
thread_.Stop();
diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host.cc
index 67719f4..27d2da1 100644
--- a/remoting/protocol/connection_to_host.cc
+++ b/remoting/protocol/connection_to_host.cc
@@ -53,9 +53,16 @@ void ConnectionToHost::Connect(const std::string& username,
video_stub_ = video_stub;
// Initialize |jingle_client_|.
- jingle_client_ = new JingleClient(thread_);
- jingle_client_->Init(username, auth_token,
- kChromotingTokenServiceName, this);
+ if (1 == 0) {
+ signal_strategy_.reset(new JavascriptSignalStrategy());
+ } else {
+ signal_strategy_.reset(
+ new XmppSignalStrategy(thread_, username, auth_token,
+ kChromotingTokenServiceName));
+ }
+
+ jingle_client_ = new JingleClient(thread_, signal_strategy_.get(), this);
+ jingle_client_->Init();
// Save jid of the host. The actual connection is created later after
// |jingle_client_| is connected.
diff --git a/remoting/protocol/connection_to_host.h b/remoting/protocol/connection_to_host.h
index 515b89a..0869a7b 100644
--- a/remoting/protocol/connection_to_host.h
+++ b/remoting/protocol/connection_to_host.h
@@ -98,6 +98,7 @@ class ConnectionToHost : public JingleClient::Callback {
JingleThread* thread_;
+ scoped_ptr<SignalStrategy> signal_strategy_;
scoped_refptr<JingleClient> jingle_client_;
scoped_refptr<SessionManager> session_manager_;
scoped_refptr<Session> session_;
diff --git a/remoting/protocol/protocol_test_client.cc b/remoting/protocol/protocol_test_client.cc
index 849bbd7..f95b93e 100644
--- a/remoting/protocol/protocol_test_client.cc
+++ b/remoting/protocol/protocol_test_client.cc
@@ -112,6 +112,7 @@ class ProtocolTestClient
void DestroyConnection(scoped_refptr<ProtocolTestConnection> connection);
std::string host_jid_;
+ scoped_ptr<SignalStrategy> signal_strategy_;
scoped_refptr<JingleClient> client_;
scoped_refptr<JingleSessionManager> session_manager_;
ConnectionsList connections_;
@@ -225,8 +226,11 @@ void ProtocolTestClient::Run(const std::string& username,
const std::string& host_jid) {
remoting::JingleThread jingle_thread;
jingle_thread.Start();
- client_ = new JingleClient(&jingle_thread);
- client_->Init(username, auth_token, kChromotingTokenServiceName, this);
+ signal_strategy_.reset(
+ new XmppSignalStrategy(&jingle_thread, username, auth_token,
+ kChromotingTokenServiceName));
+ client_ = new JingleClient(&jingle_thread, signal_strategy_.get(), this);
+ client_->Init();
session_manager_ = new JingleSessionManager(&jingle_thread);