summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrmsousa@chromium.org <rmsousa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-01 07:59:40 +0000
committerrmsousa@chromium.org <rmsousa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-01 07:59:40 +0000
commitc22db290a238599efa63f1c4b7ae6459b860c93f (patch)
treec0b9b3382b05cde77ea6fa68200a05fa68459117
parent66471276ecae9f474476e410203efefb17ae3024 (diff)
downloadchromium_src-c22db290a238599efa63f1c4b7ae6459b860c93f.zip
chromium_src-c22db290a238599efa63f1c4b7ae6459b860c93f.tar.gz
chromium_src-c22db290a238599efa63f1c4b7ae6459b860c93f.tar.bz2
Refactor of Authenticator to allow it to ProcessMessage asynchronously and then call a callback
This is so that ProcessMessage can potentially require user input (or use the result of a network operation) without blocking the network thread on JingleSession. BUG=115899 Review URL: https://chromiumcodereview.appspot.com/12389010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@185492 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/host/pam_authorization_factory_posix.cc20
-rw-r--r--remoting/protocol/authenticator.h16
-rw-r--r--remoting/protocol/authenticator_test_base.cc51
-rw-r--r--remoting/protocol/authenticator_test_base.h2
-rw-r--r--remoting/protocol/connection_to_client.cc1
-rw-r--r--remoting/protocol/connection_to_host.cc1
-rw-r--r--remoting/protocol/fake_authenticator.cc6
-rw-r--r--remoting/protocol/fake_authenticator.h3
-rw-r--r--remoting/protocol/jingle_session.cc35
-rw-r--r--remoting/protocol/jingle_session.h3
-rw-r--r--remoting/protocol/me2me_host_authenticator_factory.cc4
-rw-r--r--remoting/protocol/negotiating_authenticator.cc29
-rw-r--r--remoting/protocol/negotiating_authenticator.h5
-rw-r--r--remoting/protocol/session.h7
-rw-r--r--remoting/protocol/v2_authenticator.cc8
-rw-r--r--remoting/protocol/v2_authenticator.h5
-rw-r--r--remoting/protocol/v2_authenticator_unittest.cc3
17 files changed, 130 insertions, 69 deletions
diff --git a/remoting/host/pam_authorization_factory_posix.cc b/remoting/host/pam_authorization_factory_posix.cc
index 6d1bf58..1a5b0b3 100644
--- a/remoting/host/pam_authorization_factory_posix.cc
+++ b/remoting/host/pam_authorization_factory_posix.cc
@@ -6,6 +6,8 @@
#include <security/pam_appl.h>
+#include "base/bind.h"
+#include "base/callback.h"
#include "base/environment.h"
#include "base/logging.h"
#include "remoting/protocol/channel_authenticator.h"
@@ -22,7 +24,8 @@ class PamAuthorizer : public protocol::Authenticator {
// protocol::Authenticator interface.
virtual State state() const OVERRIDE;
virtual RejectionReason rejection_reason() const OVERRIDE;
- virtual void ProcessMessage(const buzz::XmlElement* message) OVERRIDE;
+ virtual void ProcessMessage(const buzz::XmlElement* message,
+ const base::Closure& resume_callback) OVERRIDE;
virtual scoped_ptr<buzz::XmlElement> GetNextMessage() OVERRIDE;
virtual scoped_ptr<protocol::ChannelAuthenticator>
CreateChannelAuthenticator() const OVERRIDE;
@@ -30,6 +33,7 @@ class PamAuthorizer : public protocol::Authenticator {
private:
void MaybeCheckLocalLogin();
bool IsLocalLoginAllowed();
+ void OnMessageProcessed(const base::Closure& resume_callback);
static int PamConversation(int num_messages,
const struct pam_message** messages,
@@ -66,13 +70,21 @@ PamAuthorizer::rejection_reason() const {
}
}
-void PamAuthorizer::ProcessMessage(const buzz::XmlElement* message) {
- underlying_->ProcessMessage(message);
+void PamAuthorizer::ProcessMessage(const buzz::XmlElement* message,
+ const base::Closure& resume_callback) {
+ // |underlying_| is owned, so Unretained() is safe here.
+ underlying_->ProcessMessage(message, base::Bind(
+ &PamAuthorizer::OnMessageProcessed,
+ base::Unretained(this), resume_callback));
+}
+
+void PamAuthorizer::OnMessageProcessed(const base::Closure& resume_callback) {
MaybeCheckLocalLogin();
+ resume_callback.Run();
}
scoped_ptr<buzz::XmlElement> PamAuthorizer::GetNextMessage() {
- scoped_ptr<buzz::XmlElement> result (underlying_->GetNextMessage());
+ scoped_ptr<buzz::XmlElement> result(underlying_->GetNextMessage());
MaybeCheckLocalLogin();
return result.Pass();
}
diff --git a/remoting/protocol/authenticator.h b/remoting/protocol/authenticator.h
index b8aa37d..53e0d26 100644
--- a/remoting/protocol/authenticator.h
+++ b/remoting/protocol/authenticator.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
namespace buzz {
@@ -38,6 +39,9 @@ class Authenticator {
// WAITING_MESSAGE -> MESSAGE_READY
// WAITING_MESSAGE -> ACCEPTED
// WAITING_MESSAGE -> REJECTED
+ // WAITING_MESSAGE -> PROCESSING_MESSAGE
+ // After asynchronous message processing finishes:
+ /// PROCESSING_MESSAGE -> MESSAGE_READY
// When GetNextMessage() is called:
// MESSAGE_READY -> WAITING_MESSAGE
// MESSAGE_READY -> ACCEPTED
@@ -53,6 +57,9 @@ class Authenticator {
// Session is rejected.
REJECTED,
+
+ // Asynchronously processing the last message from the peer.
+ PROCESSING_MESSAGE,
};
enum RejectionReason {
@@ -81,9 +88,12 @@ class Authenticator {
virtual RejectionReason rejection_reason() const = 0;
// Called in response to incoming message received from the peer.
- // Should only be called when in WAITING_MESSAGE state. Caller
- // retains ownership of |message|.
- virtual void ProcessMessage(const buzz::XmlElement* message) = 0;
+ // Should only be called when in WAITING_MESSAGE state. Caller retains
+ // ownership of |message|. |resume_callback| will be called when processing is
+ // finished. The implementation must guarantee that |resume_callback| is not
+ // called after the Authenticator is destroyed.
+ virtual void ProcessMessage(const buzz::XmlElement* message,
+ const base::Closure& resume_callback) = 0;
// Must be called when in MESSAGE_READY state. Returns next
// authentication message that needs to be sent to the peer.
diff --git a/remoting/protocol/authenticator_test_base.cc b/remoting/protocol/authenticator_test_base.cc
index 18de95d..d79c227 100644
--- a/remoting/protocol/authenticator_test_base.cc
+++ b/remoting/protocol/authenticator_test_base.cc
@@ -60,36 +60,27 @@ void AuthenticatorTestBase::SetUp() {
}
void AuthenticatorTestBase::RunAuthExchange() {
- do {
- scoped_ptr<buzz::XmlElement> message;
-
- // Pass message from client to host.
- ASSERT_EQ(Authenticator::MESSAGE_READY, client_->state());
- message = client_->GetNextMessage();
- ASSERT_TRUE(message.get());
- ASSERT_NE(Authenticator::MESSAGE_READY, client_->state());
-
- ASSERT_EQ(Authenticator::WAITING_MESSAGE, host_->state());
- host_->ProcessMessage(message.get());
- ASSERT_NE(Authenticator::WAITING_MESSAGE, host_->state());
-
- // Are we done yet?
- if (host_->state() == Authenticator::ACCEPTED ||
- host_->state() == Authenticator::REJECTED) {
- break;
- }
-
- // Pass message from host to client.
- ASSERT_EQ(Authenticator::MESSAGE_READY, host_->state());
- message = host_->GetNextMessage();
- ASSERT_TRUE(message.get());
- ASSERT_NE(Authenticator::MESSAGE_READY, host_->state());
-
- ASSERT_EQ(Authenticator::WAITING_MESSAGE, client_->state());
- client_->ProcessMessage(message.get());
- ASSERT_NE(Authenticator::WAITING_MESSAGE, client_->state());
- } while (client_->state() != Authenticator::ACCEPTED &&
- client_->state() != Authenticator::REJECTED);
+ ContinueAuthExchangeWith(client_.get(), host_.get());
+}
+
+// static
+void AuthenticatorTestBase::ContinueAuthExchangeWith(Authenticator* sender,
+ Authenticator* receiver) {
+ scoped_ptr<buzz::XmlElement> message;
+ ASSERT_NE(Authenticator::WAITING_MESSAGE, sender->state());
+ if (sender->state() == Authenticator::ACCEPTED ||
+ sender->state() == Authenticator::REJECTED)
+ return;
+ // Pass message from client to host.
+ ASSERT_EQ(Authenticator::MESSAGE_READY, sender->state());
+ message = sender->GetNextMessage();
+ ASSERT_TRUE(message.get());
+ ASSERT_NE(Authenticator::MESSAGE_READY, sender->state());
+
+ ASSERT_EQ(Authenticator::WAITING_MESSAGE, receiver->state());
+ receiver->ProcessMessage(message.get(), base::Bind(
+ &AuthenticatorTestBase::ContinueAuthExchangeWith,
+ base::Unretained(receiver), base::Unretained(sender)));
}
void AuthenticatorTestBase::RunChannelAuth(bool expected_fail) {
diff --git a/remoting/protocol/authenticator_test_base.h b/remoting/protocol/authenticator_test_base.h
index fc4856c..4a43347 100644
--- a/remoting/protocol/authenticator_test_base.h
+++ b/remoting/protocol/authenticator_test_base.h
@@ -40,6 +40,8 @@ class AuthenticatorTestBase : public testing::Test {
MOCK_METHOD1(OnDone, void(net::Error error));
};
+ static void ContinueAuthExchangeWith(Authenticator* sender,
+ Authenticator* receiver);
virtual void SetUp() OVERRIDE;
void RunAuthExchange();
void RunChannelAuth(bool expected_fail);
diff --git a/remoting/protocol/connection_to_client.cc b/remoting/protocol/connection_to_client.cc
index d3814ba..c3a7816 100644
--- a/remoting/protocol/connection_to_client.cc
+++ b/remoting/protocol/connection_to_client.cc
@@ -108,6 +108,7 @@ void ConnectionToClient::OnSessionStateChange(Session::State state) {
switch(state) {
case Session::INITIALIZING:
case Session::CONNECTING:
+ case Session::ACCEPTING:
case Session::CONNECTED:
// Don't care about these events.
break;
diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host.cc
index dd21220..105ccba 100644
--- a/remoting/protocol/connection_to_host.cc
+++ b/remoting/protocol/connection_to_host.cc
@@ -160,6 +160,7 @@ void ConnectionToHost::OnSessionStateChange(
switch (state) {
case Session::INITIALIZING:
case Session::CONNECTING:
+ case Session::ACCEPTING:
case Session::CONNECTED:
// Don't care about these events.
break;
diff --git a/remoting/protocol/fake_authenticator.cc b/remoting/protocol/fake_authenticator.cc
index 681f2a9..26d89de 100644
--- a/remoting/protocol/fake_authenticator.cc
+++ b/remoting/protocol/fake_authenticator.cc
@@ -86,7 +86,7 @@ FakeAuthenticator::FakeAuthenticator(
FakeAuthenticator::~FakeAuthenticator() {
}
-Authenticator::State FakeAuthenticator::state() const{
+Authenticator::State FakeAuthenticator::state() const {
EXPECT_LE(messages_, round_trips_ * 2);
if (messages_ >= round_trips_ * 2) {
if (action_ == REJECT) {
@@ -117,12 +117,14 @@ Authenticator::RejectionReason FakeAuthenticator::rejection_reason() const {
return INVALID_CREDENTIALS;
}
-void FakeAuthenticator::ProcessMessage(const buzz::XmlElement* message) {
+void FakeAuthenticator::ProcessMessage(const buzz::XmlElement* message,
+ const base::Closure& resume_callback) {
EXPECT_EQ(WAITING_MESSAGE, state());
std::string id =
message->TextNamed(buzz::QName(kChromotingXmlNamespace, "id"));
EXPECT_EQ(id, base::IntToString(messages_));
++messages_;
+ resume_callback.Run();
}
scoped_ptr<buzz::XmlElement> FakeAuthenticator::GetNextMessage() {
diff --git a/remoting/protocol/fake_authenticator.h b/remoting/protocol/fake_authenticator.h
index a6ab85e..a5a2de8 100644
--- a/remoting/protocol/fake_authenticator.h
+++ b/remoting/protocol/fake_authenticator.h
@@ -64,7 +64,8 @@ class FakeAuthenticator : public Authenticator {
// Authenticator interface.
virtual State state() const OVERRIDE;
virtual RejectionReason rejection_reason() const OVERRIDE;
- virtual void ProcessMessage(const buzz::XmlElement* message) OVERRIDE;
+ virtual void ProcessMessage(const buzz::XmlElement* message,
+ const base::Closure& resume_callback) OVERRIDE;
virtual scoped_ptr<buzz::XmlElement> GetNextMessage() OVERRIDE;
virtual scoped_ptr<ChannelAuthenticator>
CreateChannelAuthenticator() const OVERRIDE;
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
index bfab845..c6a4f22 100644
--- a/remoting/protocol/jingle_session.cc
+++ b/remoting/protocol/jingle_session.cc
@@ -130,7 +130,7 @@ void JingleSession::InitializeIncomingConnection(
session_id_ = initiate_message.sid;
candidate_config_ = initiate_message.description->config()->Clone();
- SetState(CONNECTING);
+ SetState(ACCEPTING);
}
void JingleSession::AcceptIncomingConnection(
@@ -147,7 +147,14 @@ void JingleSession::AcceptIncomingConnection(
}
DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE);
- authenticator_->ProcessMessage(first_auth_message);
+ // |authenticator_| is owned, so Unretained() is safe here.
+ authenticator_->ProcessMessage(first_auth_message, base::Bind(
+ &JingleSession::ContinueAcceptIncomingConnection,
+ base::Unretained(this)));
+}
+
+void JingleSession::ContinueAcceptIncomingConnection() {
+ DCHECK_NE(authenticator_->state(), Authenticator::PROCESSING_MESSAGE);
if (authenticator_->state() == Authenticator::REJECTED) {
CloseInternal(AuthRejectionReasonToErrorCode(
authenticator_->rejection_reason()));
@@ -435,9 +442,6 @@ void JingleSession::OnAccept(const JingleMessage& message,
return;
}
- DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
- authenticator_->ProcessMessage(auth_message);
-
if (!InitializeConfigFromDescription(message.description.get())) {
CloseInternal(INCOMPATIBLE_PROTOCOL);
return;
@@ -448,12 +452,9 @@ void JingleSession::OnAccept(const JingleMessage& message,
SetState(CONNECTED);
- // Process authentication.
- if (authenticator_->state() == Authenticator::ACCEPTED) {
- SetState(AUTHENTICATED);
- } else {
- ProcessAuthenticationStep();
- }
+ DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
+ authenticator_->ProcessMessage(auth_message, base::Bind(
+ &JingleSession::ProcessAuthenticationStep,base::Unretained(this)));
}
void JingleSession::OnSessionInfo(const JingleMessage& message,
@@ -475,8 +476,8 @@ void JingleSession::OnSessionInfo(const JingleMessage& message,
reply_callback.Run(JingleMessageReply::NONE);
- authenticator_->ProcessMessage(message.info.get());
- ProcessAuthenticationStep();
+ authenticator_->ProcessMessage(message.info.get(), base::Bind(
+ &JingleSession::ProcessAuthenticationStep, base::Unretained(this)));
}
void JingleSession::ProcessTransportInfo(const JingleMessage& message) {
@@ -494,7 +495,8 @@ void JingleSession::ProcessTransportInfo(const JingleMessage& message) {
void JingleSession::OnTerminate(const JingleMessage& message,
const ReplyCallback& reply_callback) {
- if (state_ != CONNECTING && state_ != CONNECTED && state_ != AUTHENTICATED) {
+ if (state_ != CONNECTING && state_ != ACCEPTING && state_ != CONNECTED &&
+ state_ != AUTHENTICATED) {
LOG(WARNING) << "Received unexpected session-terminate message.";
reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST);
return;
@@ -550,7 +552,9 @@ bool JingleSession::InitializeConfigFromDescription(
}
void JingleSession::ProcessAuthenticationStep() {
+ DCHECK(CalledOnValidThread());
DCHECK_EQ(state_, CONNECTED);
+ DCHECK_NE(authenticator_->state(), Authenticator::PROCESSING_MESSAGE);
if (authenticator_->state() == Authenticator::MESSAGE_READY) {
JingleMessage message(peer_jid_, JingleMessage::SESSION_INFO, session_id_);
@@ -571,7 +575,8 @@ void JingleSession::ProcessAuthenticationStep() {
void JingleSession::CloseInternal(ErrorCode error) {
DCHECK(CalledOnValidThread());
- if (state_ == CONNECTING || state_ == CONNECTED || state_ == AUTHENTICATED) {
+ if (state_ == CONNECTING || state_ == ACCEPTING || state_ == CONNECTED ||
+ state_ == AUTHENTICATED) {
// Send session-terminate message with the appropriate error code.
JingleMessage::Reason reason;
switch (error) {
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h
index dfe817c..1b7f17e 100644
--- a/remoting/protocol/jingle_session.h
+++ b/remoting/protocol/jingle_session.h
@@ -126,6 +126,9 @@ class JingleSession : public Session,
// Called from OnAccept() to initialize session config.
bool InitializeConfigFromDescription(const ContentDescription* description);
+ // Called after the initial incoming authenticator message is processed.
+ void ContinueAcceptIncomingConnection();
+ // Called after subsequent authenticator messages are processed.
void ProcessAuthenticationStep();
// Terminates the session and sends session-terminate if it is
diff --git a/remoting/protocol/me2me_host_authenticator_factory.cc b/remoting/protocol/me2me_host_authenticator_factory.cc
index ad813f7..c871b6c 100644
--- a/remoting/protocol/me2me_host_authenticator_factory.cc
+++ b/remoting/protocol/me2me_host_authenticator_factory.cc
@@ -34,9 +34,11 @@ class RejectingAuthenticator : public Authenticator {
return INVALID_CREDENTIALS;
}
- virtual void ProcessMessage(const buzz::XmlElement* message) OVERRIDE {
+ virtual void ProcessMessage(const buzz::XmlElement* message,
+ const base::Closure& resume_callback) OVERRIDE {
DCHECK_EQ(state_, WAITING_MESSAGE);
state_ = REJECTED;
+ resume_callback.Run();
}
virtual scoped_ptr<buzz::XmlElement> GetNextMessage() OVERRIDE {
diff --git a/remoting/protocol/negotiating_authenticator.cc b/remoting/protocol/negotiating_authenticator.cc
index efdbb32..a8ed3fe 100644
--- a/remoting/protocol/negotiating_authenticator.cc
+++ b/remoting/protocol/negotiating_authenticator.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <sstream>
+#include "base/bind.h"
#include "base/logging.h"
#include "base/string_split.h"
#include "crypto/rsa_private_key.h"
@@ -90,7 +91,9 @@ NegotiatingAuthenticator::rejection_reason() const {
return rejection_reason_;
}
-void NegotiatingAuthenticator::ProcessMessage(const buzz::XmlElement* message) {
+void NegotiatingAuthenticator::ProcessMessage(
+ const buzz::XmlElement* message,
+ const base::Closure& resume_callback) {
DCHECK_EQ(state(), WAITING_MESSAGE);
std::string method_attr = message->Attr(kMethodAttributeQName);
@@ -112,6 +115,7 @@ void NegotiatingAuthenticator::ProcessMessage(const buzz::XmlElement* message) {
// Message contains neither method nor supported-methods attributes.
state_ = REJECTED;
rejection_reason_ = PROTOCOL_ERROR;
+ resume_callback.Run();
return;
}
@@ -136,6 +140,7 @@ void NegotiatingAuthenticator::ProcessMessage(const buzz::XmlElement* message) {
// Failed to find a common auth method.
state_ = REJECTED;
rejection_reason_ = PROTOCOL_ERROR;
+ resume_callback.Run();
return;
}
@@ -151,15 +156,27 @@ void NegotiatingAuthenticator::ProcessMessage(const buzz::XmlElement* message) {
current_method_ = method;
CreateAuthenticator(state_);
}
-
if (state_ == WAITING_MESSAGE) {
- current_authenticator_->ProcessMessage(message);
- state_ = current_authenticator_->state();
- if (state_ == REJECTED)
- rejection_reason_ = current_authenticator_->rejection_reason();
+ // |current_authenticator_| is owned, so Unretained() is safe here.
+ current_authenticator_->ProcessMessage(message, base::Bind(
+ &NegotiatingAuthenticator::UpdateState,
+ base::Unretained(this), resume_callback));
+ } else {
+ UpdateState(resume_callback);
}
}
+void NegotiatingAuthenticator::UpdateState(
+ const base::Closure& resume_callback) {
+ // After the underlying authenticator finishes processing the message, the
+ // NegotiatingAuthenticator must update its own state before running the
+ // |resume_callback| to resume the session negotiation.
+ state_ = current_authenticator_->state();
+ if (state_ == REJECTED)
+ rejection_reason_ = current_authenticator_->rejection_reason();
+ resume_callback.Run();
+}
+
scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() {
DCHECK_EQ(state(), MESSAGE_READY);
diff --git a/remoting/protocol/negotiating_authenticator.h b/remoting/protocol/negotiating_authenticator.h
index aabbf88..61b471b 100644
--- a/remoting/protocol/negotiating_authenticator.h
+++ b/remoting/protocol/negotiating_authenticator.h
@@ -40,7 +40,8 @@ class NegotiatingAuthenticator : public Authenticator {
// Authenticator interface.
virtual State state() const OVERRIDE;
virtual RejectionReason rejection_reason() const OVERRIDE;
- virtual void ProcessMessage(const buzz::XmlElement* message) OVERRIDE;
+ virtual void ProcessMessage(const buzz::XmlElement* message,
+ const base::Closure& resume_callback) OVERRIDE;
virtual scoped_ptr<buzz::XmlElement> GetNextMessage() OVERRIDE;
virtual scoped_ptr<ChannelAuthenticator>
CreateChannelAuthenticator() const OVERRIDE;
@@ -50,6 +51,8 @@ class NegotiatingAuthenticator : public Authenticator {
void AddMethod(const AuthenticationMethod& method);
void CreateAuthenticator(State initial_state);
+ void UpdateState(const base::Closure& resume_callback);
+
bool is_host_side() const;
// Used only for host authenticators.
diff --git a/remoting/protocol/session.h b/remoting/protocol/session.h
index daa12e4..a542283 100644
--- a/remoting/protocol/session.h
+++ b/remoting/protocol/session.h
@@ -29,11 +29,12 @@ class Session {
// Created, but not connecting yet.
INITIALIZING,
- // Sent or received session-initiate, but haven't sent or received
- // session-accept.
- // TODO(sergeyu): Do we really need this state?
+ // Sent session-initiate, but haven't received session-accept.
CONNECTING,
+ // Received session-initiate, but haven't sent session-accept.
+ ACCEPTING,
+
// Session has been accepted and is pending authentication.
CONNECTED,
diff --git a/remoting/protocol/v2_authenticator.cc b/remoting/protocol/v2_authenticator.cc
index 95b42d5..3728a6a 100644
--- a/remoting/protocol/v2_authenticator.cc
+++ b/remoting/protocol/v2_authenticator.cc
@@ -80,7 +80,13 @@ Authenticator::RejectionReason V2Authenticator::rejection_reason() const {
return rejection_reason_;
}
-void V2Authenticator::ProcessMessage(const buzz::XmlElement* message) {
+void V2Authenticator::ProcessMessage(const buzz::XmlElement* message,
+ const base::Closure& resume_callback) {
+ ProcessMessageInternal(message);
+ resume_callback.Run();
+}
+
+void V2Authenticator::ProcessMessageInternal(const buzz::XmlElement* message) {
DCHECK_EQ(state(), WAITING_MESSAGE);
// Parse the certificate.
diff --git a/remoting/protocol/v2_authenticator.h b/remoting/protocol/v2_authenticator.h
index ef6503c..fdc86be 100644
--- a/remoting/protocol/v2_authenticator.h
+++ b/remoting/protocol/v2_authenticator.h
@@ -40,7 +40,8 @@ class V2Authenticator : public Authenticator {
// Authenticator interface.
virtual State state() const OVERRIDE;
virtual RejectionReason rejection_reason() const OVERRIDE;
- virtual void ProcessMessage(const buzz::XmlElement* message) OVERRIDE;
+ virtual void ProcessMessage(const buzz::XmlElement* message,
+ const base::Closure& resume_callback) OVERRIDE;
virtual scoped_ptr<buzz::XmlElement> GetNextMessage() OVERRIDE;
virtual scoped_ptr<ChannelAuthenticator>
CreateChannelAuthenticator() const OVERRIDE;
@@ -52,6 +53,8 @@ class V2Authenticator : public Authenticator {
const std::string& shared_secret,
State initial_state);
+ virtual void ProcessMessageInternal(const buzz::XmlElement* message);
+
bool is_host_side() const;
// Used only for host authenticators.
diff --git a/remoting/protocol/v2_authenticator_unittest.cc b/remoting/protocol/v2_authenticator_unittest.cc
index dc95318..da3512e 100644
--- a/remoting/protocol/v2_authenticator_unittest.cc
+++ b/remoting/protocol/v2_authenticator_unittest.cc
@@ -85,7 +85,8 @@ TEST_F(V2AuthenticatorTest, InvalidSecret) {
ASSERT_TRUE(message.get());
ASSERT_EQ(Authenticator::WAITING_MESSAGE, client_->state());
- host_->ProcessMessage(message.get());
+ host_->ProcessMessage(message.get(), base::Bind(&base::DoNothing));
+ // This assumes that V2Authenticator::ProcessMessage runs synchronously.
ASSERT_EQ(Authenticator::REJECTED, host_->state());
}