diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-03 15:56:57 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-03 15:56:57 +0000 |
commit | e05eb1d621ca0a26e0b33c650d4dbf456dba6863 (patch) | |
tree | 97322432de7e2381eb065cc3af19d53abba6e2f3 /remoting | |
parent | fbc94a82c898c17dffbb7bad4f2ed70ffc15b133 (diff) | |
download | chromium_src-e05eb1d621ca0a26e0b33c650d4dbf456dba6863.zip chromium_src-e05eb1d621ca0a26e0b33c650d4dbf456dba6863.tar.gz chromium_src-e05eb1d621ca0a26e0b33c650d4dbf456dba6863.tar.bz2 |
Refactor JingleClient to support thunking the xmpp signaling into Javascript.
We do this so that we may make HTTP requests using the javascript libraries available to Google Talk. This is required to allow us to sandbox.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/6597092
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76746 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/client/plugin/chromoting_scriptable_object.cc | 14 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_scriptable_object.h | 15 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_xmpp_proxy.cc | 57 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_xmpp_proxy.h | 42 | ||||
-rw-r--r-- | remoting/host/chromoting_host.cc | 19 | ||||
-rw-r--r-- | remoting/host/chromoting_host.h | 2 | ||||
-rw-r--r-- | remoting/host/heartbeat_sender.cc | 33 | ||||
-rw-r--r-- | remoting/host/heartbeat_sender.h | 15 | ||||
-rw-r--r-- | remoting/host/heartbeat_sender_unittest.cc | 36 | ||||
-rw-r--r-- | remoting/jingle_glue/iq_request.cc | 90 | ||||
-rw-r--r-- | remoting/jingle_glue/iq_request.h | 98 | ||||
-rw-r--r-- | remoting/jingle_glue/jingle_client.cc | 245 | ||||
-rw-r--r-- | remoting/jingle_glue/jingle_client.h | 153 | ||||
-rw-r--r-- | remoting/jingle_glue/jingle_client_unittest.cc | 15 | ||||
-rw-r--r-- | remoting/protocol/connection_to_host.cc | 13 | ||||
-rw-r--r-- | remoting/protocol/connection_to_host.h | 1 | ||||
-rw-r--r-- | remoting/protocol/protocol_test_client.cc | 8 |
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); |