summaryrefslogtreecommitdiffstats
path: root/remoting/jingle_glue
diff options
context:
space:
mode:
Diffstat (limited to 'remoting/jingle_glue')
-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
5 files changed, 412 insertions, 189 deletions
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();