summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-11 20:08:35 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-11 20:08:35 +0000
commitd8efb9909c2b7b3c9d43eaaf0fcc6c609e3d06cb (patch)
tree4b021d847052309f3ad4cde574cdfdac8f41daf8 /chrome/browser
parent9b056baffd0aa88a4c6e41b0ca450f56feff78e2 (diff)
downloadchromium_src-d8efb9909c2b7b3c9d43eaaf0fcc6c609e3d06cb.zip
chromium_src-d8efb9909c2b7b3c9d43eaaf0fcc6c609e3d06cb.tar.gz
chromium_src-d8efb9909c2b7b3c9d43eaaf0fcc6c609e3d06cb.tar.bz2
Made GaiaAuth use Chrome threads instead of libjingle threads.
This partially solves the issue in 30721, as it makes sure that there is a Chrome message loop for the SSL socket adapter on OS X/Linux. However, although it has stopped crashing, gaia authentication still times out. Renamed GaiaAuth::WorkerThread to GaiaAuth::WorkerTask and cleaned it up. BUG=30721 TEST=manual Review URL: http://codereview.chromium.org/542003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35932 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc162
-rw-r--r--chrome/browser/sync/notifier/gaia_auth/gaiaauth.h15
2 files changed, 106 insertions, 71 deletions
diff --git a/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc b/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc
index 0afae73..6a65032 100644
--- a/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc
+++ b/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc
@@ -5,13 +5,15 @@
#include <string>
#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "base/thread.h"
#include "chrome/browser/sync/notifier/base/ssl_adapter.h"
#include "chrome/browser/sync/notifier/gaia_auth/gaiaauth.h"
#include "talk/base/asynchttprequest.h"
#include "talk/base/firewallsocketserver.h"
#include "talk/base/httpclient.h"
#include "talk/base/physicalsocketserver.h"
-#include "talk/base/signalthread.h"
#include "talk/base/socketadapters.h"
#include "talk/base/socketpool.h"
#include "talk/base/stringutils.h"
@@ -27,7 +29,7 @@ static const int kGaiaAuthTimeoutMs = 30 * 1000; // 30 sec
GaiaServer g_gaia_server;
///////////////////////////////////////////////////////////////////////////////
-// GaiaAuth::WorkerThread
+// GaiaAuth::WorkerTask
///////////////////////////////////////////////////////////////////////////////
// GaiaAuth is NOT invoked during SASL authentication, but it is invoked even
@@ -38,42 +40,42 @@ GaiaServer g_gaia_server;
// It is used by XmppClient. It grabs a SaslAuthenticator which knows how to
// play the cookie login.
-class GaiaAuth::WorkerThread : public talk_base::SignalThread {
+class GaiaAuth::WorkerTask {
public:
- WorkerThread(const std::string& username,
- const talk_base::CryptString& pass,
- const std::string& token,
- const std::string& service,
- const std::string& user_agent,
- const std::string& signature,
- bool obtain_auth,
- const std::string& token_service) :
+ WorkerTask(const std::string& username,
+ const talk_base::CryptString& pass,
+ const std::string& service,
+ const talk_base::ProxyInfo& proxy,
+ talk_base::FirewallManager* firewall,
+ const std::string& token,
+ const CaptchaAnswer& captcha_answer,
+ bool obtain_auth,
+ const std::string& user_agent,
+ const std::string& signature,
+ const std::string& token_service) :
username_(username),
pass_(pass),
service_(service),
- firewall_(0),
- done_(false),
+ proxy_(proxy),
+ firewall_(firewall),
success_(false),
error_(true),
error_code_(0),
proxy_auth_required_(false),
certificate_expired_(false),
auth_token_(token),
+ captcha_answer_(captcha_answer),
fresh_auth_token_(false),
obtain_auth_(obtain_auth),
agent_(user_agent),
signature_(signature),
token_service_(token_service) {}
- void set_proxy(const talk_base::ProxyInfo& proxy) { proxy_ = proxy; }
- void set_firewall(talk_base::FirewallManager * firewall) {
- firewall_ = firewall;
- }
- void set_captcha_answer(const CaptchaAnswer& captcha_answer) {
- captcha_answer_ = captcha_answer;
- }
+ ~WorkerTask() {}
- virtual void DoWork() {
+ void DoWork(MessageLoop* parent_message_loop, Task* on_work_done_task) {
+ DCHECK(parent_message_loop);
+ DCHECK(on_work_done_task);
LOG(INFO) << "GaiaAuth Begin";
// Maybe we already have an auth token, then there is nothing to do.
if (!auth_token_.empty()) {
@@ -122,6 +124,10 @@ class GaiaAuth::WorkerThread : public talk_base::SignalThread {
GaiaRequestSid(&http, username_, pass_, signature_,
obtain_auth_ ? service_ : "", captcha_answer_,
g_gaia_server);
+ // TODO(akalin): handle timeouts better; this can cause jank,
+ // e.g. when we're waiting on this and the user stops syncing,
+ // which causes the GaiaAuth object to be destroyed, which
+ // waits on this. (bug: http://crbug.com/31981 )
ss->Wait(kGaiaAuthTimeoutMs, true);
error_code_ = monitor.error(); // Save off the error code.
@@ -201,10 +207,10 @@ class GaiaAuth::WorkerThread : public talk_base::SignalThread {
// Done authenticating.
Cleanup:
- done_ = true;
+ LOG(INFO) << "GaiaAuth done";
+ parent_message_loop->PostTask(FROM_HERE, on_work_done_task);
}
- bool IsDone() const { return done_; }
bool Succeeded() const { return success_; }
bool HadError() const { return error_; }
int GetError() const { return error_code_; }
@@ -247,20 +253,36 @@ class GaiaAuth::WorkerThread : public talk_base::SignalThread {
std::string token_service_;
};
+} // namespace buzz
+
+// We outlive any runnable methods we create, so stub out
+// RunnableMethodTraits for GaiaAuth and WorkerTask.
+
+template <>
+struct RunnableMethodTraits<buzz::GaiaAuth> {
+ void RetainCallee(buzz::GaiaAuth* gaia_auth) {}
+ void ReleaseCallee(buzz::GaiaAuth* gaia_auth) {}
+};
+
+template <>
+struct RunnableMethodTraits<buzz::GaiaAuth::WorkerTask> {
+ void RetainCallee(buzz::GaiaAuth::WorkerTask* gaia_auth) {}
+ void ReleaseCallee(buzz::GaiaAuth::WorkerTask* gaia_auth) {}
+};
+
+namespace buzz {
+
///////////////////////////////////////////////////////////////////////////////
// GaiaAuth
///////////////////////////////////////////////////////////////////////////////
GaiaAuth::GaiaAuth(const std::string &user_agent, const std::string &sig)
- : agent_(user_agent), signature_(sig), firewall_(0), worker_(NULL),
+ : agent_(user_agent), signature_(sig), firewall_(0),
+ worker_thread_("GaiaAuth worker thread"), worker_task_(NULL),
done_(false) {
}
GaiaAuth::~GaiaAuth() {
- if (worker_) {
- worker_->Release();
- worker_ = NULL;
- }
}
void GaiaAuth::StartPreXmppAuth(const buzz::Jid& jid,
@@ -297,27 +319,34 @@ void GaiaAuth::InternalStartGaiaAuth(const buzz::Jid& jid,
const std::string& token,
const std::string& service,
bool obtain_auth) {
- worker_ = new WorkerThread(jid.Str(), pass, token, service, agent_,
- signature_, obtain_auth, token_service_);
- worker_->set_proxy(proxy_);
- worker_->set_firewall(firewall_);
- worker_->set_captcha_answer(captcha_answer_);
- worker_->SignalWorkDone.connect(this, &GaiaAuth::OnAuthDone);
- worker_->Start();
+ worker_task_.reset(
+ new WorkerTask(jid.Str(), pass, service, proxy_, firewall_,
+ token, captcha_answer_, obtain_auth, agent_,
+ signature_, token_service_));
+ MessageLoop* current_message_loop = MessageLoop::current();
+ DCHECK(current_message_loop);
+ Task* on_work_done_task = NewRunnableMethod(this, &GaiaAuth::OnAuthDone);
+ LOG(INFO) << "GaiaAuth begin (async)";
+ worker_thread_.Start();
+ worker_thread_.message_loop()->PostTask(
+ FROM_HERE, NewRunnableMethod(worker_task_.get(),
+ &WorkerTask::DoWork,
+ current_message_loop,
+ on_work_done_task));
}
-void GaiaAuth::OnAuthDone(talk_base::SignalThread* worker) {
- if (!worker_->IsDone())
- return;
+void GaiaAuth::OnAuthDone() {
+ LOG(INFO) << "GaiaAuth done (async)";
+ worker_thread_.Stop();
done_ = true;
- if (worker_->fresh_auth_token()) {
- SignalFreshAuthCookie(worker_->GetToken());
+ if (worker_task_->fresh_auth_token()) {
+ SignalFreshAuthCookie(worker_task_->GetToken());
}
- if (worker_->ProxyAuthRequired()) {
+ if (worker_task_->ProxyAuthRequired()) {
SignalAuthenticationError();
}
- if (worker_->CertificateExpired()) {
+ if (worker_task_->CertificateExpired()) {
SignalCertificateExpired();
}
SignalAuthDone();
@@ -342,12 +371,12 @@ std::string GaiaAuth::ChooseBestSaslMechanism(
// Never pass @google.com passwords without encryption!!
if (!encrypted &&
- buzz::Jid(worker_->GetUsername()).domain() == "google.com") {
+ buzz::Jid(worker_task_->GetUsername()).domain() == "google.com") {
return "";
}
// As a last resort, use plain authentication.
- if (buzz::Jid(worker_->GetUsername()).domain() != "google.com") {
+ if (buzz::Jid(worker_task_->GetUsername()).domain() != "google.com") {
it = std::find(mechanisms.begin(), mechanisms.end(), "PLAIN");
if (it != mechanisms.end())
return "PLAIN";
@@ -366,22 +395,22 @@ buzz::SaslMechanism* GaiaAuth::CreateSaslMechanism(
if (mechanism == "X-GOOGLE-TOKEN") {
return new buzz::SaslCookieMechanism(
mechanism,
- worker_->GetUsername(),
- worker_->GetToken(),
- worker_->GetTokenService());
+ worker_task_->GetUsername(),
+ worker_task_->GetToken(),
+ worker_task_->GetTokenService());
}
if (mechanism == "X-GOOGLE-COOKIE") {
return new buzz::SaslCookieMechanism(
"X-GOOGLE-COOKIE",
- worker_->GetUsername(),
- worker_->GetSID(),
- worker_->GetTokenService());
+ worker_task_->GetUsername(),
+ worker_task_->GetSID(),
+ worker_task_->GetTokenService());
}
if (mechanism == "PLAIN") {
- return new buzz::SaslPlainMechanism(buzz::Jid(worker_->GetUsername()),
- worker_->GetPassword());
+ return new buzz::SaslPlainMechanism(buzz::Jid(worker_task_->GetUsername()),
+ worker_task_->GetPassword());
}
// Oh well - none of the above.
@@ -390,14 +419,15 @@ buzz::SaslMechanism* GaiaAuth::CreateSaslMechanism(
std::string GaiaAuth::CreateAuthenticatedUrl(
const std::string & continue_url, const std::string & service) {
- if (!done_ || worker_->GetToken().empty())
+ if (!done_ || worker_task_->GetToken().empty())
return "";
std::string url;
// Note that http_prefix always ends with a "/".
url += g_gaia_server.http_prefix()
+ "accounts/TokenAuth?auth="
- + worker_->GetToken(); // Do not URL encode - GAIA doesn't like that.
+ // Do not URL encode - GAIA doesn't like that.
+ + worker_task_->GetToken();
url += "&service=" + service;
url += "&continue=" + UrlEncodeString(continue_url);
url += "&source=" + signature_;
@@ -406,26 +436,26 @@ std::string GaiaAuth::CreateAuthenticatedUrl(
std::string GaiaAuth::GetAuthCookie() {
assert(IsAuthDone() && IsAuthorized());
- if (!done_ || !worker_->Succeeded()) {
+ if (!done_ || !worker_task_->Succeeded()) {
return "";
}
- return worker_->GetToken();
+ return worker_task_->GetToken();
}
std::string GaiaAuth::GetAuth() {
assert(IsAuthDone() && IsAuthorized());
- if (!done_ || !worker_->Succeeded()) {
+ if (!done_ || !worker_task_->Succeeded()) {
return "";
}
- return worker_->GetAuth();
+ return worker_task_->GetAuth();
}
std::string GaiaAuth::GetSID() {
assert(IsAuthDone() && IsAuthorized());
- if (!done_ || !worker_->Succeeded()) {
+ if (!done_ || !worker_task_->Succeeded()) {
return "";
}
- return worker_->GetSID();
+ return worker_task_->GetSID();
}
bool GaiaAuth::IsAuthDone() {
@@ -433,25 +463,25 @@ bool GaiaAuth::IsAuthDone() {
}
bool GaiaAuth::IsAuthorized() {
- return done_ && worker_ != NULL && worker_->Succeeded();
+ return done_ && worker_task_ != NULL && worker_task_->Succeeded();
}
bool GaiaAuth::HadError() {
- return done_ && worker_ != NULL && worker_->HadError();
+ return done_ && worker_task_ != NULL && worker_task_->HadError();
}
int GaiaAuth::GetError() {
- if (done_ && worker_ != NULL) {
- return worker_->GetError();
+ if (done_ && worker_task_ != NULL) {
+ return worker_task_->GetError();
}
return 0;
}
buzz::CaptchaChallenge GaiaAuth::GetCaptchaChallenge() {
- if (!done_ || worker_->Succeeded()) {
+ if (!done_ || worker_task_->Succeeded()) {
return buzz::CaptchaChallenge();
}
- return worker_->GetCaptchaChallenge();
+ return worker_task_->GetCaptchaChallenge();
}
} // namespace buzz
diff --git a/chrome/browser/sync/notifier/gaia_auth/gaiaauth.h b/chrome/browser/sync/notifier/gaia_auth/gaiaauth.h
index e2f3a6e..06b6383 100644
--- a/chrome/browser/sync/notifier/gaia_auth/gaiaauth.h
+++ b/chrome/browser/sync/notifier/gaia_auth/gaiaauth.h
@@ -11,6 +11,8 @@
#include <string>
#include <vector>
+#include "base/scoped_ptr.h"
+#include "base/thread.h"
#include "chrome/browser/sync/notifier/gaia_auth/gaiahelper.h"
#include "talk/base/cryptstring.h"
#include "talk/base/messagequeue.h"
@@ -19,7 +21,6 @@
namespace talk_base {
class FirewallManager;
-class SignalThread;
}
namespace buzz {
@@ -28,7 +29,7 @@ namespace buzz {
// GaiaAuth
///////////////////////////////////////////////////////////////////////////////
-class GaiaAuth : public PreXmppAuth, public sigslot::has_slots<> {
+class GaiaAuth : public PreXmppAuth {
public:
GaiaAuth(const std::string& user_agent, const std::string& signature);
virtual ~GaiaAuth();
@@ -94,8 +95,12 @@ class GaiaAuth : public PreXmppAuth, public sigslot::has_slots<> {
sigslot::signal0<> SignalCertificateExpired;
sigslot::signal1<const std::string&> SignalFreshAuthCookie;
+ // Needs to be public for the RunnableMethodTraits specialization in
+ // gaiaauth.cc.
+ class WorkerTask;
+
private:
- void OnAuthDone(talk_base::SignalThread* worker);
+ void OnAuthDone();
void InternalStartGaiaAuth(const buzz::Jid& jid,
const talk_base::SocketAddress& server,
@@ -108,8 +113,8 @@ class GaiaAuth : public PreXmppAuth, public sigslot::has_slots<> {
std::string signature_;
talk_base::ProxyInfo proxy_;
talk_base::FirewallManager* firewall_;
- class WorkerThread;
- WorkerThread* worker_;
+ base::Thread worker_thread_;
+ scoped_ptr<WorkerTask> worker_task_;
bool done_;
CaptchaAnswer captcha_answer_;