summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhbono@google.com <hbono@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-17 04:17:53 +0000
committerhbono@google.com <hbono@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-17 04:17:53 +0000
commitec880bbf40a7e7e837aaf0ef7be8bd827a24b8be (patch)
tree05431f361c4b73b337e1488d59cd35e341960cf8
parent8814427f49396271ee260e44de0a8482f4ae2b76 (diff)
downloadchromium_src-ec880bbf40a7e7e837aaf0ef7be8bd827a24b8be.zip
chromium_src-ec880bbf40a7e7e837aaf0ef7be8bd827a24b8be.tar.gz
chromium_src-ec880bbf40a7e7e837aaf0ef7be8bd827a24b8be.tar.bz2
Revert 41790 - Removed auth_task.* and talk_auth_task.* (dead code) because Windows XP doesn't have inet_pton and it crashes XP bots.
Removed GaiaAuth class. Gtalk login will now fail immediately instead of trying (in vain) to gaiaauth. Removed nowunneeded parameters. BUG=38034 TEST=manual with and without invalidatesyncxmpplogin Review URL: http://codereview.chromium.org/885008 TBR=akalin@chromium.org Review URL: http://codereview.chromium.org/983005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41808 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/sync/notifier/base/async_dns_lookup.cc5
-rw-r--r--chrome/browser/sync/notifier/communicator/auth_task.cc68
-rw-r--r--chrome/browser/sync/notifier/communicator/auth_task.h77
-rw-r--r--chrome/browser/sync/notifier/communicator/login.cc2
-rw-r--r--chrome/browser/sync/notifier/communicator/login.h4
-rw-r--r--chrome/browser/sync/notifier/communicator/login_failure.cc18
-rw-r--r--chrome/browser/sync/notifier/communicator/login_failure.h18
-rw-r--r--chrome/browser/sync/notifier/communicator/login_settings.cc2
-rw-r--r--chrome/browser/sync/notifier/communicator/login_settings.h6
-rw-r--r--chrome/browser/sync/notifier/communicator/single_login_attempt.cc78
-rw-r--r--chrome/browser/sync/notifier/communicator/single_login_attempt.h9
-rw-r--r--chrome/browser/sync/notifier/communicator/talk_auth_task.cc74
-rw-r--r--chrome/browser/sync/notifier/communicator/talk_auth_task.h64
-rw-r--r--chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc435
-rw-r--r--chrome/browser/sync/notifier/gaia_auth/gaiaauth.h133
-rw-r--r--chrome/browser/sync/notifier/gaia_auth/gaiahelper.cc237
-rw-r--r--chrome/browser/sync/notifier/gaia_auth/gaiahelper.h87
-rw-r--r--chrome/browser/sync/notifier/gaia_auth/inet_aton.h14
-rw-r--r--chrome/browser/sync/notifier/gaia_auth/sigslotrepeater.h (renamed from chrome/browser/sync/notifier/base/sigslotrepeater.h)6
-rw-r--r--chrome/browser/sync/notifier/gaia_auth/win/win32window.cc (renamed from third_party/libjingle/files/talk/base/win32window.cc)37
-rw-r--r--chrome/browser/sync/notifier/listener/mediator_thread_impl.cc1
-rw-r--r--chrome/chrome.gyp12
-rw-r--r--third_party/libjingle/libjingle.gyp1
-rw-r--r--third_party/libjingle/mods-since-v0_4_0.diff1
24 files changed, 1339 insertions, 50 deletions
diff --git a/chrome/browser/sync/notifier/base/async_dns_lookup.cc b/chrome/browser/sync/notifier/base/async_dns_lookup.cc
index 267dd50..a8fee43 100644
--- a/chrome/browser/sync/notifier/base/async_dns_lookup.cc
+++ b/chrome/browser/sync/notifier/base/async_dns_lookup.cc
@@ -14,8 +14,6 @@
#include <netinet/ip.h>
#include <sys/socket.h>
#include <sys/types.h>
-#else
-#include <Ws2tcpip.h>
#endif // defined(OS_POSIX)
#include <vector>
@@ -23,6 +21,7 @@
#include "base/basictypes.h"
#include "base/logging.h"
#include "chrome/browser/sync/notifier/base/nethelpers.h"
+#include "chrome/browser/sync/notifier/gaia_auth/inet_aton.h"
#include "talk/base/byteorder.h"
#include "talk/base/common.h"
#include "talk/base/socketaddress.h"
@@ -50,7 +49,7 @@ void AsyncDNSLookup::DoWork() {
std::string hostname(server_->IPAsString());
in_addr addr;
- if (inet_pton(AF_INET, hostname.c_str(), &addr)) {
+ if (inet_aton(hostname.c_str(), &addr)) {
talk_base::CritScope scope(&cs_);
ip_list_.push_back(talk_base::NetworkToHost32(addr.s_addr));
} else {
diff --git a/chrome/browser/sync/notifier/communicator/auth_task.cc b/chrome/browser/sync/notifier/communicator/auth_task.cc
new file mode 100644
index 0000000..ba98fe3
--- /dev/null
+++ b/chrome/browser/sync/notifier/communicator/auth_task.cc
@@ -0,0 +1,68 @@
+// Copyright (c) 2009 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 "chrome/browser/sync/notifier/communicator/auth_task.h"
+
+#include "chrome/browser/sync/notifier/gaia_auth/gaiaauth.h"
+#include "chrome/browser/sync/notifier/communicator/login.h"
+#include "chrome/browser/sync/notifier/communicator/login_settings.h"
+#include "chrome/browser/sync/notifier/communicator/product_info.h"
+#include "talk/base/common.h"
+#include "talk/base/urlencode.h"
+#include "talk/xmpp/xmppclient.h"
+
+namespace notifier {
+const char kTalkGadgetAuthPath[] = "/auth";
+
+AuthTask::AuthTask(talk_base::Task* parent, Login* login, const char* url)
+ : talk_base::Task(parent),
+ login_(login),
+ url_(url),
+ use_gaia_redirect_(true) {
+ ASSERT(login && !url_.empty());
+}
+
+int AuthTask::ProcessStart() {
+ auth_.reset(new buzz::GaiaAuth(GetUserAgentString(),
+ GetProductSignature()));
+ auth_->SignalAuthDone.connect(this, &AuthTask::OnAuthDone);
+ auth_->StartTokenAuth(login_->xmpp_client()->jid().BareJid(),
+ login_->login_settings().user_settings().pass(),
+ use_gaia_redirect_ ? "gaia" : service_);
+ return STATE_RESPONSE;
+}
+
+int AuthTask::ProcessResponse() {
+ ASSERT(auth_.get());
+ if (!auth_->IsAuthDone()) {
+ return STATE_BLOCKED;
+ }
+ if (!auth_->IsAuthorized()) {
+ SignalAuthError(!auth_->HadError());
+ return STATE_ERROR;
+ }
+
+ std::string uber_url;
+ if (use_gaia_redirect_) {
+ uber_url = auth_->CreateAuthenticatedUrl(url_, service_);
+ } else {
+ uber_url = redir_auth_prefix_ + auth_->GetAuthCookie();
+ uber_url += redir_continue_;
+ uber_url += UrlEncodeString(url_);
+ }
+
+ if (uber_url == "") {
+ SignalAuthError(true);
+ return STATE_ERROR;
+ }
+
+ SignalAuthDone(uber_url);
+ return STATE_DONE;
+}
+
+void AuthTask::OnAuthDone() {
+ Wake();
+}
+
+} // namespace notifier
diff --git a/chrome/browser/sync/notifier/communicator/auth_task.h b/chrome/browser/sync/notifier/communicator/auth_task.h
new file mode 100644
index 0000000..b71bd92
--- /dev/null
+++ b/chrome/browser/sync/notifier/communicator/auth_task.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2009 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 CHROME_BROWSER_SYNC_NOTIFIER_COMMUNICATOR_AUTH_TASK_H_
+#define CHROME_BROWSER_SYNC_NOTIFIER_COMMUNICATOR_AUTH_TASK_H_
+
+#include <string>
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/task.h"
+
+namespace buzz {
+class GaiaAuth;
+}
+
+namespace notifier {
+
+class Login;
+
+// Create an authenticated talk url from an unauthenticated url.
+class AuthTask : public talk_base::Task, public sigslot::has_slots<> {
+ public:
+ AuthTask(talk_base::Task* parent, Login* login, const char* url);
+
+ // An abort method which doesn't take any parameters.
+ // (talk_base::Task::Abort() has a default parameter).
+ //
+ // The primary purpose of this method is to allow a signal to be hooked up to
+ // abort this task.
+ void Abort() {
+ talk_base::Task::Abort();
+ }
+
+ void set_service(const char* service) {
+ service_ = service;
+ }
+
+ void set_use_gaia_redirect(bool use_gaia_redirect) {
+ use_gaia_redirect_ = use_gaia_redirect;
+ }
+
+ void set_redir_auth_prefix(const char* redir_auth_prefix) {
+ redir_auth_prefix_ = redir_auth_prefix;
+ }
+
+ void set_redir_continue(const char* redir_continue) {
+ redir_continue_ = redir_continue;
+ }
+
+ sigslot::signal1<const std::string&> SignalAuthDone;
+ sigslot::signal1<bool> SignalAuthError;
+
+ protected:
+ virtual int ProcessStart();
+ virtual int ProcessResponse();
+
+ private:
+ void OnAuthDone();
+
+ scoped_ptr<buzz::GaiaAuth> auth_;
+ Login* login_;
+ std::string service_;
+ std::string url_;
+
+ // The following members are used for cases where we don't want to redirect
+ // through gaia, but rather via the end-site's mechanism.
+ bool use_gaia_redirect_;
+ std::string redir_auth_prefix_;
+ std::string redir_continue_;
+
+ DISALLOW_COPY_AND_ASSIGN(AuthTask);
+};
+
+} // namespace notifier
+
+#endif // CHROME_BROWSER_SYNC_NOTIFIER_COMMUNICATOR_AUTH_TASK_H_
diff --git a/chrome/browser/sync/notifier/communicator/login.cc b/chrome/browser/sync/notifier/communicator/login.cc
index 9da7f56..de7fd3a 100644
--- a/chrome/browser/sync/notifier/communicator/login.cc
+++ b/chrome/browser/sync/notifier/communicator/login.cc
@@ -41,6 +41,7 @@ Login::Login(talk_base::Task* parent,
int server_count,
NetworkStatusDetectorTask* network_status,
talk_base::FirewallManager* firewall,
+ bool no_gaia_auth,
bool proxy_only,
bool previous_login_successful)
: login_settings_(new LoginSettings(user_settings,
@@ -49,6 +50,7 @@ Login::Login(talk_base::Task* parent,
server_list,
server_count,
firewall,
+ no_gaia_auth,
proxy_only)),
single_attempt_(NULL),
successful_connection_(previous_login_successful),
diff --git a/chrome/browser/sync/notifier/communicator/login.h b/chrome/browser/sync/notifier/communicator/login.h
index de90a1b..284435b 100644
--- a/chrome/browser/sync/notifier/communicator/login.h
+++ b/chrome/browser/sync/notifier/communicator/login.h
@@ -7,14 +7,15 @@
#include <string>
-#include "chrome/browser/sync/notifier/base/sigslotrepeater.h"
#include "chrome/browser/sync/notifier/base/time.h"
+#include "chrome/browser/sync/notifier/gaia_auth/sigslotrepeater.h"
#include "talk/base/proxyinfo.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/sigslot.h"
#include "talk/xmpp/xmppengine.h"
namespace buzz {
+class CaptchaChallenge;
class XmppClient;
class XmppEngine;
class XmppClientSettings;
@@ -51,6 +52,7 @@ class Login : public sigslot::has_slots<> {
int server_count,
NetworkStatusDetectorTask* network_status,
talk_base::FirewallManager* firewall,
+ bool no_gaia_auth,
bool proxy_only,
bool previous_login_successful);
~Login();
diff --git a/chrome/browser/sync/notifier/communicator/login_failure.cc b/chrome/browser/sync/notifier/communicator/login_failure.cc
index c10a35b..80d2f74 100644
--- a/chrome/browser/sync/notifier/communicator/login_failure.cc
+++ b/chrome/browser/sync/notifier/communicator/login_failure.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/sync/notifier/communicator/login_failure.h"
+#include "talk/xmpp/prexmppauth.h"
+
namespace notifier {
LoginFailure::LoginFailure(LoginError error)
@@ -20,9 +22,25 @@ LoginFailure::LoginFailure(LoginError error,
subcode_(subcode) {
}
+LoginFailure::LoginFailure(LoginError error,
+ buzz::XmppEngine::Error xmpp_error,
+ int subcode,
+ const buzz::CaptchaChallenge& captcha)
+ : error_(error),
+ xmpp_error_(xmpp_error),
+ subcode_(subcode),
+ captcha_(new buzz::CaptchaChallenge(captcha)) {
+}
+
buzz::XmppEngine::Error LoginFailure::xmpp_error() const {
ASSERT(error_ == XMPP_ERROR);
return xmpp_error_;
}
+const buzz::CaptchaChallenge& LoginFailure::captcha() const {
+ ASSERT(xmpp_error_ == buzz::XmppEngine::ERROR_UNAUTHORIZED ||
+ xmpp_error_ == buzz::XmppEngine::ERROR_MISSING_USERNAME);
+ return *captcha_.get();
+}
+
} // namespace notifier
diff --git a/chrome/browser/sync/notifier/communicator/login_failure.h b/chrome/browser/sync/notifier/communicator/login_failure.h
index 886f8da..21d7d36 100644
--- a/chrome/browser/sync/notifier/communicator/login_failure.h
+++ b/chrome/browser/sync/notifier/communicator/login_failure.h
@@ -8,6 +8,10 @@
#include "talk/base/common.h"
#include "talk/xmpp/xmppengine.h"
+namespace buzz {
+class CaptchaChallenge;
+}
+
namespace notifier {
class LoginFailure {
@@ -28,6 +32,10 @@ class LoginFailure {
LoginFailure(LoginError error,
buzz::XmppEngine::Error xmpp_error,
int subcode);
+ LoginFailure(LoginError error,
+ buzz::XmppEngine::Error xmpp_error,
+ int subcode,
+ const buzz::CaptchaChallenge& captcha);
// Used as the first level of error information.
LoginError error() const {
@@ -40,10 +48,20 @@ class LoginFailure {
// (except that the DiagnoseConnectionError has already been done).
buzz::XmppEngine::Error xmpp_error() const;
+ // Returns the captcha challenge. Valid if and only if
+ // xmpp_error is buzz::XmppEngine::ERROR_UNAUTHORIZED or
+ // buzz::XmppEngine::ERROR_MISSING_USERNAME
+ //
+ // See PhoneWindow::HandleConnectionPasswordError for how to handle this
+ // (after the if (..) { LoginAccountAndConnectionSetting(); ...} because
+ // that is done by SingleLoginAttempt.
+ const buzz::CaptchaChallenge& captcha() const;
+
private:
LoginError error_;
buzz::XmppEngine::Error xmpp_error_;
int subcode_;
+ scoped_ptr<buzz::CaptchaChallenge> captcha_;
DISALLOW_COPY_AND_ASSIGN(LoginFailure);
};
diff --git a/chrome/browser/sync/notifier/communicator/login_settings.cc b/chrome/browser/sync/notifier/communicator/login_settings.cc
index 085bf31..bf450bc 100644
--- a/chrome/browser/sync/notifier/communicator/login_settings.cc
+++ b/chrome/browser/sync/notifier/communicator/login_settings.cc
@@ -20,8 +20,10 @@ LoginSettings::LoginSettings(const buzz::XmppClientSettings& user_settings,
ServerInformation* server_list,
int server_count,
talk_base::FirewallManager* firewall,
+ bool no_gaia_auth,
bool proxy_only)
: proxy_only_(proxy_only),
+ no_gaia_auth_(no_gaia_auth),
firewall_(firewall),
lang_(lang),
server_list_(new ServerInformation[server_count]),
diff --git a/chrome/browser/sync/notifier/communicator/login_settings.h b/chrome/browser/sync/notifier/communicator/login_settings.h
index 331d341..3e9b971 100644
--- a/chrome/browser/sync/notifier/communicator/login_settings.h
+++ b/chrome/browser/sync/notifier/communicator/login_settings.h
@@ -30,6 +30,7 @@ class LoginSettings {
ServerInformation* server_list,
int server_count,
talk_base::FirewallManager* firewall,
+ bool no_gaia_auth,
bool proxy_only);
~LoginSettings();
@@ -42,6 +43,10 @@ class LoginSettings {
return firewall_;
}
+ bool no_gaia_auth() const {
+ return no_gaia_auth_;
+ }
+
bool proxy_only() const {
return proxy_only_;
}
@@ -75,6 +80,7 @@ class LoginSettings {
private:
bool proxy_only_;
+ bool no_gaia_auth_;
talk_base::FirewallManager* firewall_;
std::string lang_;
diff --git a/chrome/browser/sync/notifier/communicator/single_login_attempt.cc b/chrome/browser/sync/notifier/communicator/single_login_attempt.cc
index de759a6..80c438b 100644
--- a/chrome/browser/sync/notifier/communicator/single_login_attempt.cc
+++ b/chrome/browser/sync/notifier/communicator/single_login_attempt.cc
@@ -17,12 +17,14 @@
#include "chrome/browser/sync/notifier/communicator/product_info.h"
#include "chrome/browser/sync/notifier/communicator/xmpp_connection_generator.h"
#include "chrome/browser/sync/notifier/communicator/xmpp_socket_adapter.h"
+#include "chrome/browser/sync/notifier/gaia_auth/gaiaauth.h"
#include "talk/base/asynchttprequest.h"
#include "talk/base/firewallsocketserver.h"
#include "talk/base/signalthread.h"
#include "talk/base/taskrunner.h"
#include "talk/base/winsock_initializer.h"
#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/prexmppauth.h"
#include "talk/xmpp/saslcookiemechanism.h"
#include "talk/xmpp/saslhandler.h"
#include "talk/xmpp/xmppclient.h"
@@ -31,15 +33,29 @@
namespace notifier {
+static void FillProxyInfo(const buzz::XmppClientSettings& xcs,
+ talk_base::ProxyInfo* proxy) {
+ ASSERT(proxy != NULL);
+ proxy->type = xcs.proxy();
+ proxy->address.SetIP(xcs.proxy_host());
+ proxy->address.SetPort(xcs.proxy_port());
+ if (xcs.use_proxy_auth()) {
+ proxy->username = xcs.proxy_user();
+ proxy->password = xcs.proxy_pass();
+ }
+}
+
static void GetClientErrorInformation(
buzz::XmppClient* client,
buzz::XmppEngine::Error* error,
int* subcode,
- buzz::XmlElement** stream_error) {
+ buzz::XmlElement** stream_error,
+ buzz::CaptchaChallenge* captcha_challenge) {
ASSERT(client != NULL);
- ASSERT(error && subcode && stream_error);
+ ASSERT(error && subcode && stream_error && captcha_challenge);
*error = client->GetError(subcode);
+ *captcha_challenge = client->GetCaptchaChallenge();
*stream_error = NULL;
if (*error == buzz::XmppEngine::ERROR_STREAM) {
@@ -230,7 +246,7 @@ void SingleLoginAttempt::DoLogin(
// Start connecting.
client_->Connect(client_settings, login_settings_->lang(),
CreateSocket(client_settings),
- NULL,
+ CreatePreXmppAuth(client_settings),
CreateSaslHandler(client_settings));
client_->Start();
}
@@ -260,6 +276,32 @@ buzz::AsyncSocket* SingleLoginAttempt::CreateSocket(
return adapter;
}
+buzz::PreXmppAuth* SingleLoginAttempt::CreatePreXmppAuth(
+ const buzz::XmppClientSettings& xcs) {
+ if (login_settings_->no_gaia_auth())
+ return NULL;
+
+ // For GMail, use Gaia preauthentication over HTTP.
+ buzz::GaiaAuth* auth = new buzz::GaiaAuth(GetUserAgentString(),
+ GetProductSignature());
+ auth->SignalAuthenticationError.connect(
+ this,
+ &SingleLoginAttempt::OnAuthenticationError);
+ auth->SignalCertificateExpired.connect(
+ this,
+ &SingleLoginAttempt::OnCertificateExpired);
+ auth->SignalFreshAuthCookie.connect(
+ this,
+ &SingleLoginAttempt::OnFreshAuthCookie);
+ auth->set_token_service(xcs.token_service());
+
+ talk_base::ProxyInfo proxy;
+ FillProxyInfo(xcs, &proxy);
+ auth->set_proxy(proxy);
+ auth->set_firewall(login_settings_->firewall());
+ return auth;
+}
+
buzz::SaslHandler* SingleLoginAttempt::CreateSaslHandler(
const buzz::XmppClientSettings& xcs) {
buzz::Jid jid(xcs.user(), xcs.host(), buzz::STR_EMPTY);
@@ -449,11 +491,13 @@ void SingleLoginAttempt::OnClientStateChangeClosed(
buzz::XmppEngine::State previous_state) {
buzz::XmppEngine::Error error = buzz::XmppEngine::ERROR_NONE;
int error_subcode = 0;
+ buzz::CaptchaChallenge captcha_challenge;
buzz::XmlElement* stream_error_ptr;
GetClientErrorInformation(client_,
&error,
&error_subcode,
- &stream_error_ptr);
+ &stream_error_ptr,
+ &captcha_challenge);
scoped_ptr<buzz::XmlElement> stream_error(stream_error_ptr);
client_->SignalStateChange.disconnect(this);
@@ -467,20 +511,36 @@ void SingleLoginAttempt::OnClientStateChangeClosed(
SignalUnexpectedDisconnect();
return;
} else {
- HandleConnectionError(error, error_subcode, stream_error.get());
+ HandleConnectionError(error, error_subcode, stream_error.get(),
+ captcha_challenge);
}
}
-void SingleLoginAttempt::HandleConnectionPasswordError() {
+void SingleLoginAttempt::HandleConnectionPasswordError(
+ const buzz::CaptchaChallenge& captcha_challenge) {
LOG(INFO) << "SingleLoginAttempt::HandleConnectionPasswordError";
- LoginFailure failure(LoginFailure::XMPP_ERROR, code_, subcode_);
+
+ // Clear the auth cookie.
+ std::string current_auth_cookie =
+ login_settings_->user_settings().auth_cookie();
+ login_settings_->modifiable_user_settings()->set_auth_cookie("");
+ // If there was an auth cookie and it was the same as the last auth cookie,
+ // then it is a stale cookie. Retry login.
+ if (!current_auth_cookie.empty() && !cookie_refreshed_) {
+ UseCurrentConnection();
+ return;
+ }
+
+ LoginFailure failure(LoginFailure::XMPP_ERROR, code_, subcode_,
+ captcha_challenge);
SignalLoginFailure(failure);
}
void SingleLoginAttempt::HandleConnectionError(
buzz::XmppEngine::Error code,
int subcode,
- const buzz::XmlElement* stream_error) {
+ const buzz::XmlElement* stream_error,
+ const buzz::CaptchaChallenge& captcha_challenge) {
LOG(INFO) << "(" << code << ", " << subcode << ")";
// Save off the error code information, so we can use it to tell the user
@@ -490,7 +550,7 @@ void SingleLoginAttempt::HandleConnectionError(
if ((code_ == buzz::XmppEngine::ERROR_UNAUTHORIZED) ||
(code_ == buzz::XmppEngine::ERROR_MISSING_USERNAME)) {
// There was a problem with credentials (username/password).
- HandleConnectionPasswordError();
+ HandleConnectionPasswordError(captcha_challenge);
return;
}
diff --git a/chrome/browser/sync/notifier/communicator/single_login_attempt.h b/chrome/browser/sync/notifier/communicator/single_login_attempt.h
index 388260c..c798a27 100644
--- a/chrome/browser/sync/notifier/communicator/single_login_attempt.h
+++ b/chrome/browser/sync/notifier/communicator/single_login_attempt.h
@@ -15,6 +15,8 @@
namespace buzz {
class AsyncSocket;
+class CaptchaChallenge;
+class PreXmppAuth;
class SaslHandler;
class XmppClient;
class XmppClientSettings;
@@ -94,6 +96,7 @@ class SingleLoginAttempt : public talk_base::Task, public sigslot::has_slots<> {
private:
void DoLogin(const ConnectionSettings& connection_settings);
buzz::AsyncSocket* CreateSocket(const buzz::XmppClientSettings& xcs);
+ buzz::PreXmppAuth* CreatePreXmppAuth(const buzz::XmppClientSettings& xcs);
static buzz::SaslHandler* CreateSaslHandler(
const buzz::XmppClientSettings& xcs);
@@ -103,8 +106,10 @@ class SingleLoginAttempt : public talk_base::Task, public sigslot::has_slots<> {
void HandleConnectionError(
buzz::XmppEngine::Error code,
int subcode,
- const buzz::XmlElement* stream_error);
- void HandleConnectionPasswordError();
+ const buzz::XmlElement* stream_error,
+ const buzz::CaptchaChallenge& captcha_challenge);
+ void HandleConnectionPasswordError(
+ const buzz::CaptchaChallenge& captcha_challenge);
void DiagnoseConnectionError();
void OnHttpTestDone(talk_base::SignalThread* thread);
diff --git a/chrome/browser/sync/notifier/communicator/talk_auth_task.cc b/chrome/browser/sync/notifier/communicator/talk_auth_task.cc
new file mode 100644
index 0000000..f085b16
--- /dev/null
+++ b/chrome/browser/sync/notifier/communicator/talk_auth_task.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2009 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 "chrome/browser/sync/notifier/communicator/talk_auth_task.h"
+
+#include "chrome/browser/sync/notifier/communicator/login.h"
+#include "chrome/browser/sync/notifier/communicator/login_settings.h"
+#include "chrome/browser/sync/notifier/communicator/product_info.h"
+#include "chrome/browser/sync/notifier/gaia_auth/gaiaauth.h"
+#include "talk/base/common.h"
+#include "talk/base/urlencode.h"
+#include "talk/xmpp/xmppclient.h"
+
+namespace notifier {
+const char kTalkGadgetAuthPath[] = "/auth";
+
+TalkAuthTask::TalkAuthTask(talk_base::Task* parent,
+ Login* login,
+ const char* url)
+ : talk_base::Task(parent),
+ login_(login),
+ url_(url) {
+ ASSERT(login && !url_.empty());
+}
+
+int TalkAuthTask::ProcessStart() {
+ auth_.reset(new buzz::GaiaAuth(GetUserAgentString(),
+ GetProductSignature()));
+ auth_->SignalAuthDone.connect(
+ this,
+ &TalkAuthTask::OnAuthDone);
+ auth_->StartAuth(login_->xmpp_client()->jid().BareJid(),
+ login_->login_settings().user_settings().pass(),
+ "talk");
+ return STATE_RESPONSE;
+}
+
+int TalkAuthTask::ProcessResponse() {
+ ASSERT(auth_.get());
+ if (!auth_->IsAuthDone()) {
+ return STATE_BLOCKED;
+ }
+ SignalAuthDone(*this);
+ return STATE_DONE;
+}
+
+
+void TalkAuthTask::OnAuthDone() {
+ Wake();
+}
+
+bool TalkAuthTask::HadError() const {
+ return auth_->HadError();
+}
+
+std::string TalkAuthTask::GetAuthenticatedUrl(
+ const char* talk_base_url) const {
+ ASSERT(talk_base_url && *talk_base_url && !auth_->HadError());
+
+ std::string auth_url(talk_base_url);
+ auth_url.append(kTalkGadgetAuthPath);
+ auth_url.append("?silent=true&redirect=true&host=");
+ auth_url.append(UrlEncodeString(url_));
+ auth_url.append("&auth=");
+ auth_url.append(auth_->GetAuth());
+ return auth_url;
+}
+
+std::string TalkAuthTask::GetSID() const {
+ return auth_->GetSID();
+}
+
+} // namespace notifier
diff --git a/chrome/browser/sync/notifier/communicator/talk_auth_task.h b/chrome/browser/sync/notifier/communicator/talk_auth_task.h
new file mode 100644
index 0000000..da00f2a
--- /dev/null
+++ b/chrome/browser/sync/notifier/communicator/talk_auth_task.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2009 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 CHROME_BROWSER_SYNC_NOTIFIER_COMMUNICATOR_TALK_AUTH_TASK_H_
+#define CHROME_BROWSER_SYNC_NOTIFIER_COMMUNICATOR_TALK_AUTH_TASK_H_
+
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/task.h"
+
+namespace buzz {
+class GaiaAuth;
+}
+
+namespace notifier {
+
+class Login;
+
+// Create an authenticated talk url from an unauthenticated url.
+class TalkAuthTask : public talk_base::Task, public sigslot::has_slots<> {
+ public:
+ TalkAuthTask(talk_base::Task* parent,
+ Login* login,
+ const char* url);
+
+ // An abort method which doesn't take any parameters.
+ // (talk_base::Task::Abort() has a default parameter.)
+ //
+ // The primary purpose of this method is to allow a signal to be hooked up to
+ // abort this task.
+ void Abort() {
+ talk_base::Task::Abort();
+ }
+
+ const std::string& url() {
+ return url_;
+ }
+
+ std::string GetAuthenticatedUrl(const char* talk_base_url) const;
+ std::string GetSID() const;
+
+ sigslot::signal1<const TalkAuthTask&> SignalAuthDone;
+
+ bool HadError() const;
+
+ // TODO(sync): add captcha support.
+
+ protected:
+ virtual int ProcessStart();
+ virtual int ProcessResponse();
+
+ private:
+ void OnAuthDone();
+
+ scoped_ptr<buzz::GaiaAuth> auth_;
+ Login* login_;
+ std::string url_;
+ DISALLOW_COPY_AND_ASSIGN(TalkAuthTask);
+};
+
+} // namespace notifier
+
+#endif // CHROME_BROWSER_SYNC_NOTIFIER_COMMUNICATOR_TALK_AUTH_TASK_H_
diff --git a/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc b/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc
new file mode 100644
index 0000000..1558b06
--- /dev/null
+++ b/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc
@@ -0,0 +1,435 @@
+// Copyright (c) 2009 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 <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/socketadapters.h"
+#include "talk/base/socketpool.h"
+#include "talk/base/stringutils.h"
+#include "talk/base/urlencode.h"
+#include "talk/xmpp/saslcookiemechanism.h"
+#include "talk/xmpp/saslplainmechanism.h"
+
+namespace buzz {
+
+static const int kGaiaAuthTimeoutMs = 30 * 1000; // 30 sec
+
+// Warning, this is externed.
+GaiaServer g_gaia_server;
+
+///////////////////////////////////////////////////////////////////////////////
+// GaiaAuth::WorkerTask
+///////////////////////////////////////////////////////////////////////////////
+
+// GaiaAuth is NOT invoked during SASL authentication, but it is invoked even
+// before XMPP login begins. As a PreXmppAuth object, it is driven by
+// XmppClient before the XMPP socket is opened. The job of GaiaAuth is to goes
+// out using HTTPS POST to grab cookies from GAIA.
+//
+// It is used by XmppClient. It grabs a SaslAuthenticator which knows how to
+// play the cookie login.
+
+class GaiaAuth::WorkerTask {
+ public:
+ 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),
+ 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) {}
+
+ ~WorkerTask() {}
+
+ 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()) {
+ LOG(INFO) << "Reusing auth token:" << auth_token_;
+ success_ = true;
+ error_ = false;
+ } else {
+ // SocketFactory::CreateSSLAdapter() is called on the following
+ // object somewhere in the depths of libjingle so we wrap it
+ // with SSLAdapterSocketFactory to make sure it returns the
+ // right SSLAdapter (see http://crbug.com/30721 ).
+ notifier::SSLAdapterSocketFactory<talk_base::PhysicalSocketServer>
+ physical;
+ talk_base::SocketServer* ss = &physical;
+ if (firewall_) {
+ ss = new talk_base::FirewallSocketServer(ss, firewall_);
+ }
+
+ talk_base::SslSocketFactory factory(ss, agent_);
+ factory.SetProxy(proxy_);
+ if (g_gaia_server.use_ssl()) {
+ factory.SetIgnoreBadCert(true);
+ factory.UseSSL(g_gaia_server.hostname().c_str());
+ }
+ factory.SetLogging(talk_base::LS_VERBOSE, "GaiaAuth");
+
+#if defined(OS_WIN)
+ talk_base::ReuseSocketPool pool(&factory);
+#else
+ // On non-Windows platforms our SSL socket wrapper
+ // implementation does not support restartable SSL sockets, so
+ // we turn it off and use a NewSocketPool instead. This means
+ // that we create separate connections for each HTTP request but
+ // this is okay since we do only two (in GaiaRequestSid() and
+ // GaiaRequestAuthToken()).
+ factory.SetUseRestartableSSLSockets(false);
+ talk_base::NewSocketPool pool(&factory);
+#endif
+ talk_base::HttpClient http(agent_, &pool);
+
+ talk_base::HttpMonitor monitor(ss);
+ monitor.Connect(&http);
+
+ // If we do not already have a SID, let's get one using our password.
+ if (sid_.empty() || (auth_.empty() && obtain_auth_)) {
+ 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.
+
+ if (!monitor.done()) {
+ LOG(INFO) << "GaiaAuth request timed out";
+ goto Cleanup;
+ } else if (monitor.error()) {
+ LOG(INFO) << "GaiaAuth request error: " << monitor.error();
+ if (monitor.error() == talk_base::HE_AUTH) {
+ success_ = false;
+ proxy_auth_required_ = true;
+ } else if (monitor.error() == talk_base::HE_CERTIFICATE_EXPIRED) {
+ success_ = false;
+ certificate_expired_ = true;
+ }
+ goto Cleanup;
+ } else {
+ std::string captcha_token, captcha_url;
+ switch (GaiaParseSidResponse(http, g_gaia_server,
+ &captcha_token, &captcha_url,
+ &sid_, &lsid_, &auth_)) {
+ case GR_ERROR:
+ goto Cleanup;
+
+ case GR_UNAUTHORIZED:
+ if (!captcha_url.empty()) {
+ captcha_challenge_ = buzz::CaptchaChallenge(captcha_token,
+ captcha_url);
+ }
+ // We had no "error" - we were just unauthorized.
+ error_ = false;
+ error_code_ = 0;
+ goto Cleanup;
+
+ case GR_SUCCESS:
+ break;
+ }
+ }
+ }
+
+ // If all we need is a SID, then we are done now.
+ if (service_.empty() || obtain_auth_) {
+ success_ = true;
+ error_ = false;
+ error_code_ = 0;
+ goto Cleanup;
+ }
+
+ monitor.reset();
+ GaiaRequestAuthToken(&http, sid_, lsid_, service_, g_gaia_server);
+ ss->Wait(kGaiaAuthTimeoutMs, true);
+
+ error_code_ = monitor.error(); // Save off the error code.
+
+ if (!monitor.done()) {
+ LOG(INFO) << "GaiaAuth request timed out";
+ } else if (monitor.error()) {
+ LOG(INFO) << "GaiaAuth request error: " << monitor.error();
+ if (monitor.error() == talk_base::HE_AUTH) {
+ success_ = false;
+ proxy_auth_required_ = true;
+ } else if (monitor.error() == talk_base::HE_CERTIFICATE_EXPIRED) {
+ success_ = false;
+ certificate_expired_ = true;
+ }
+ } else {
+ if (GR_SUCCESS == GaiaParseAuthTokenResponse(http, &auth_token_)) {
+ fresh_auth_token_ = true;
+ success_ = true;
+ error_ = false;
+ error_code_ = 0;
+ }
+ }
+ }
+
+ // Done authenticating.
+
+ Cleanup:
+ LOG(INFO) << "GaiaAuth done";
+ parent_message_loop->PostTask(FROM_HERE, on_work_done_task);
+ }
+
+ bool Succeeded() const { return success_; }
+ bool HadError() const { return error_; }
+ int GetError() const { return error_code_; }
+ bool ProxyAuthRequired() const { return proxy_auth_required_; }
+ bool CertificateExpired() const { return certificate_expired_; }
+ const buzz::CaptchaChallenge& GetCaptchaChallenge() {
+ return captcha_challenge_;
+ }
+ bool fresh_auth_token() const { return fresh_auth_token_; }
+
+ talk_base::CryptString GetPassword() const { return pass_; }
+ std::string GetSID() const { return sid_; }
+ std::string GetAuth() const { return auth_; }
+ std::string GetToken() const { return auth_token_; }
+ std::string GetUsername() const { return username_; }
+ std::string GetTokenService() const { return token_service_; }
+
+ private:
+ std::string username_;
+ talk_base::CryptString pass_;
+ std::string service_;
+ talk_base::ProxyInfo proxy_;
+ talk_base::FirewallManager * firewall_;
+ bool done_;
+ bool success_;
+ bool error_;
+ int error_code_;
+ bool proxy_auth_required_;
+ bool certificate_expired_;
+ std::string sid_;
+ std::string lsid_;
+ std::string auth_;
+ std::string auth_token_;
+ buzz::CaptchaChallenge captcha_challenge_;
+ CaptchaAnswer captcha_answer_;
+ bool fresh_auth_token_;
+ bool obtain_auth_;
+ std::string agent_;
+ std::string signature_;
+ std::string token_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerTask);
+};
+
+} // 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_task_(NULL), on_work_done_task_(NULL),
+ worker_thread_("GaiaAuth worker thread"), done_(false),
+ current_message_loop_(MessageLoop::current()) {
+ DCHECK(current_message_loop_);
+}
+
+GaiaAuth::~GaiaAuth() {
+ DCHECK_EQ(MessageLoop::current(), current_message_loop_);
+ // Wait until worker thread stops running.
+ worker_thread_.Stop();
+ // Then, if the worker thread posted an OnAuthDone() task that is
+ // still pending, cancel it.
+ if (on_work_done_task_) {
+ on_work_done_task_->Cancel();
+ }
+}
+
+void GaiaAuth::StartPreXmppAuth(const buzz::Jid& jid,
+ const talk_base::SocketAddress& server,
+ const talk_base::CryptString& pass,
+ const std::string & auth_cookie) {
+ InternalStartGaiaAuth(jid, server, pass, auth_cookie, "mail", false);
+}
+
+void GaiaAuth::StartTokenAuth(const buzz::Jid& jid,
+ const talk_base::CryptString& pass,
+ const std::string& service) {
+ InternalStartGaiaAuth(jid, talk_base::SocketAddress(), pass, "", service,
+ false);
+}
+
+void GaiaAuth::StartAuth(const buzz::Jid& jid,
+ const talk_base::CryptString& pass,
+ const std::string & service) {
+ InternalStartGaiaAuth(jid, talk_base::SocketAddress(), pass, "", service,
+ true);
+}
+
+void GaiaAuth::StartAuthFromSid(const buzz::Jid& jid,
+ const std::string& sid,
+ const std::string& service) {
+ InternalStartGaiaAuth(jid, talk_base::SocketAddress(),
+ talk_base::CryptString(), sid, service, false);
+}
+
+void GaiaAuth::InternalStartGaiaAuth(const buzz::Jid& jid,
+ const talk_base::SocketAddress& server,
+ const talk_base::CryptString& pass,
+ const std::string& token,
+ const std::string& service,
+ bool obtain_auth) {
+ DCHECK_EQ(MessageLoop::current(), current_message_loop_);
+ worker_task_.reset(
+ new WorkerTask(jid.Str(), pass, service, proxy_, firewall_,
+ token, captcha_answer_, obtain_auth, agent_,
+ signature_, token_service_));
+ 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() {
+ DCHECK_EQ(MessageLoop::current(), current_message_loop_);
+ LOG(INFO) << "GaiaAuth done (async)";
+ worker_thread_.Stop();
+ on_work_done_task_ = NULL;
+ done_ = true;
+
+ if (worker_task_->fresh_auth_token()) {
+ SignalFreshAuthCookie(worker_task_->GetToken());
+ }
+ if (worker_task_->ProxyAuthRequired()) {
+ SignalAuthenticationError();
+ }
+ if (worker_task_->CertificateExpired()) {
+ SignalCertificateExpired();
+ }
+ SignalAuthDone();
+}
+
+std::string GaiaAuth::CreateAuthenticatedUrl(
+ const std::string & continue_url, const std::string & service) {
+ 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="
+ // Do not URL encode - GAIA doesn't like that.
+ + worker_task_->GetToken();
+ url += "&service=" + service;
+ url += "&continue=" + UrlEncodeString(continue_url);
+ url += "&source=" + signature_;
+ return url;
+}
+
+std::string GaiaAuth::GetAuthCookie() {
+ assert(IsAuthDone() && IsAuthorized());
+ if (!done_ || !worker_task_->Succeeded()) {
+ return "";
+ }
+ return worker_task_->GetToken();
+}
+
+std::string GaiaAuth::GetAuth() {
+ assert(IsAuthDone() && IsAuthorized());
+ if (!done_ || !worker_task_->Succeeded()) {
+ return "";
+ }
+ return worker_task_->GetAuth();
+}
+
+std::string GaiaAuth::GetSID() {
+ assert(IsAuthDone() && IsAuthorized());
+ if (!done_ || !worker_task_->Succeeded()) {
+ return "";
+ }
+ return worker_task_->GetSID();
+}
+
+bool GaiaAuth::IsAuthDone() {
+ return done_;
+}
+
+bool GaiaAuth::IsAuthorized() {
+ return done_ && worker_task_ != NULL && worker_task_->Succeeded();
+}
+
+bool GaiaAuth::HadError() {
+ return done_ && worker_task_ != NULL && worker_task_->HadError();
+}
+
+int GaiaAuth::GetError() {
+ if (done_ && worker_task_ != NULL) {
+ return worker_task_->GetError();
+ }
+ return 0;
+}
+
+buzz::CaptchaChallenge GaiaAuth::GetCaptchaChallenge() {
+ if (!done_ || worker_task_->Succeeded()) {
+ return buzz::CaptchaChallenge();
+ }
+ 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
new file mode 100644
index 0000000..0de7632
--- /dev/null
+++ b/chrome/browser/sync/notifier/gaia_auth/gaiaauth.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2009 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.
+//
+// Gaia auth code for XMPP notifier support. This should be merged with the
+// other gaia auth file when we have time.
+
+#ifndef CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_GAIAAUTH_H_
+#define CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_GAIAAUTH_H_
+
+#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"
+#include "talk/base/proxyinfo.h"
+#include "talk/xmpp/prexmppauth.h"
+
+class MessageLoop;
+
+namespace talk_base {
+class FirewallManager;
+}
+
+namespace buzz {
+
+///////////////////////////////////////////////////////////////////////////////
+// GaiaAuth
+///////////////////////////////////////////////////////////////////////////////
+
+class GaiaAuth : public PreXmppAuth {
+ public:
+ GaiaAuth(const std::string& user_agent, const std::string& signature);
+ virtual ~GaiaAuth();
+
+ 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;
+ }
+
+ // From inside XMPP login, this is called.
+ virtual void StartPreXmppAuth(const buzz::Jid& jid,
+ const talk_base::SocketAddress& server,
+ const talk_base::CryptString& pass,
+ const std::string& auth_cookie);
+
+ void StartTokenAuth(const buzz::Jid& jid,
+ const talk_base::CryptString& pass,
+ const std::string& service);
+
+ // This is used when calling GetAuth().
+ void StartAuth(const buzz::Jid& jid,
+ const talk_base::CryptString& pass,
+ const std::string& service);
+
+ // This is used when bootstrapping from a download page.
+ void StartAuthFromSid(const buzz::Jid& jid,
+ const std::string& sid,
+ const std::string& service);
+
+ virtual bool IsAuthDone();
+ virtual bool IsAuthorized();
+ virtual bool HadError();
+ virtual int GetError();
+ virtual buzz::CaptchaChallenge GetCaptchaChallenge();
+ // Returns the auth token that can be sent in an url param to gaia in order
+ // to generate an auth cookie.
+ virtual std::string GetAuthCookie();
+
+ // Returns the auth cookie for gaia.
+ std::string GetAuth();
+ std::string GetSID();
+
+ // Sets / gets the token service to use.
+ std::string token_service() const { return token_service_; }
+ void set_token_service(const std::string& token_service) {
+ token_service_ = token_service;
+ }
+
+ std::string CreateAuthenticatedUrl(const std::string& continue_url,
+ const std::string& service);
+
+ sigslot::signal0<> SignalAuthenticationError;
+ 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();
+
+ void InternalStartGaiaAuth(const buzz::Jid& jid,
+ const talk_base::SocketAddress& server,
+ const talk_base::CryptString& pass,
+ const std::string& sid,
+ const std::string& service,
+ bool obtain_auth);
+
+ std::string agent_;
+ std::string signature_;
+ talk_base::ProxyInfo proxy_;
+ talk_base::FirewallManager* firewall_;
+ scoped_ptr<WorkerTask> worker_task_;
+ CancelableTask* on_work_done_task_;
+ base::Thread worker_thread_;
+ bool done_;
+ MessageLoop* current_message_loop_;
+
+ CaptchaAnswer captcha_answer_;
+ std::string token_service_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Globals
+///////////////////////////////////////////////////////////////////////////////
+
+extern GaiaServer g_gaia_server;
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace buzz
+
+#endif // CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_GAIAAUTH_H_
diff --git a/chrome/browser/sync/notifier/gaia_auth/gaiahelper.cc b/chrome/browser/sync/notifier/gaia_auth/gaiahelper.cc
new file mode 100644
index 0000000..f20f3ed
--- /dev/null
+++ b/chrome/browser/sync/notifier/gaia_auth/gaiahelper.cc
@@ -0,0 +1,237 @@
+// Copyright (c) 2009 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 "chrome/browser/sync/notifier/gaia_auth/gaiahelper.h"
+#include "base/logging.h"
+#include "talk/base/common.h"
+#include "talk/base/cryptstring.h"
+#include "talk/base/httpclient.h"
+#include "talk/base/httpcommon-inl.h"
+#include "talk/base/stringutils.h"
+#include "talk/base/urlencode.h"
+#include "talk/xmpp/jid.h"
+#include "talk/xmpp/xmppconstants.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace {
+
+std::string GetValueForKey(const std::string& key, const std::string& nvp) {
+ size_t start_of_line = 0;
+ size_t end_of_line = 0;
+ for (;;) { // For each line.
+ start_of_line = nvp.find_first_not_of("\r\n", end_of_line);
+ if (start_of_line == std::string::npos)
+ break;
+ end_of_line = nvp.find_first_of("\r\n", start_of_line);
+ if (end_of_line == std::string::npos) {
+ end_of_line = nvp.length();
+ }
+ size_t equals = nvp.find('=', start_of_line);
+ if (equals >= end_of_line ||
+ equals == std::string::npos ||
+ equals - start_of_line != key.length()) {
+ continue;
+ }
+
+ if (nvp.find(key, start_of_line) == start_of_line) {
+ return std::string(nvp, equals + 1, end_of_line - equals - 1);
+ }
+ }
+ return "";
+}
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace buzz {
+
+GaiaServer::GaiaServer()
+ : hostname_("www.google.com"),
+ port_(443),
+ use_ssl_(true) {
+}
+
+bool GaiaServer::SetServer(const char* url) {
+ talk_base::Url<char> parsed(url);
+ hostname_ = parsed.server();
+ port_ = parsed.port();
+ use_ssl_ = parsed.secure();
+ return true;
+}
+
+bool GaiaServer::SetDebugServer(const char* server) {
+ const char* colon = strchr(server, ':');
+ if (colon) {
+ hostname_ = std::string(server, colon - server);
+ port_ = atoi(colon + 1);
+ use_ssl_ = false;
+ return true;
+ }
+ return false;
+}
+
+std::string GaiaServer::http_prefix() const {
+ talk_base::Url<char> parsed("", hostname_, port_);
+ parsed.set_secure(use_ssl_);
+ return parsed.url();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool GaiaRequestSid(talk_base::HttpClient* client,
+ const std::string& username,
+ const talk_base::CryptString& password,
+ const std::string& signature,
+ const std::string& service,
+ const CaptchaAnswer& captcha_answer,
+ const GaiaServer& gaia_server) {
+ buzz::Jid jid(username);
+ std::string usable_name = username;
+ if (jid.domain() == buzz::STR_DEFAULT_DOMAIN) {
+ // The default domain (default.talk.google.com) is not usable for Gaia
+ // auth. But both gmail.com and googlemain.com will work, because the gaia
+ // server doesn't check to make sure the appropriate one is being used. So
+ // we just slam on gmail.com
+ usable_name = jid.node() + "@" + buzz::STR_GMAIL_COM;
+ }
+
+ std::string post_data;
+ post_data += "Email=" + UrlEncodeString(usable_name);
+ post_data += "&Passwd=" + password.UrlEncode();
+ post_data += "&PersistentCookie=false";
+ post_data += "&source=" + signature;
+ // TODO(chron): This behavior is not the same as in the other gaia auth
+ // loader. We should make it the same. Probably GOOGLE is enough, we don't
+ // want to auth against hosted accounts.
+ post_data += "&accountType=HOSTED_OR_GOOGLE";
+ post_data += "&skipvpage=true";
+ if (!service.empty()) {
+ post_data += "&service=" + service;
+ }
+
+ if (!captcha_answer.captcha_token().empty()) {
+ post_data += "&logintoken=" + captcha_answer.captcha_token();
+ post_data += "&logincaptcha="
+ + UrlEncodeString(captcha_answer.captcha_answer());
+ }
+
+ client->reset();
+ client->set_server(talk_base::SocketAddress(gaia_server.hostname(),
+ gaia_server.port(), false));
+ client->request().verb = talk_base::HV_POST;
+ client->request().path = "/accounts/ClientAuth";
+ client->request().setContent("application/x-www-form-urlencoded",
+ new talk_base::MemoryStream(post_data.data(), post_data.size()));
+ client->response().document.reset(new talk_base::MemoryStream);
+ client->start();
+ return true;
+}
+
+GaiaResponse GaiaParseSidResponse(const talk_base::HttpClient& client,
+ const GaiaServer& gaia_server,
+ std::string* captcha_token,
+ std::string* captcha_url,
+ std::string* sid,
+ std::string* lsid,
+ std::string* auth) {
+ uint32 status_code = client.response().scode;
+ const talk_base::MemoryStream* stream =
+ static_cast<const talk_base::MemoryStream*>(
+ client.response().document.get());
+ size_t length;
+ stream->GetPosition(&length);
+ std::string response;
+ if (length > 0) {
+ response.assign(stream->GetBuffer(), length);
+ }
+
+ LOG(INFO) << "GaiaAuth request to " << client.request().path;
+ LOG(INFO) << "GaiaAuth Status Code: " << status_code;
+ LOG(INFO) << response;
+
+ if (status_code == talk_base::HC_FORBIDDEN) {
+ // The error URL may be the relative path to the captcha jpg.
+ std::string image_url = GetValueForKey("CaptchaUrl", response);
+ if (!image_url.empty()) {
+ // We should activate this "full url code" once we have a better ways
+ // to crack the URL for later download. Right now we are too dependent
+ // on what Gaia returns.
+#if 0
+ if (image_url.find("http://") != 0 &&
+ image_url.find("https://") != 0) {
+ if (image_url.find("/") == 0) {
+ *captcha_url = gaia_server.http_prefix() + image_url;
+ } else {
+ *captcha_url = Utf8(gaia_server.http_prefix()).AsString()
+ + "/accounts/" + image_url;
+ }
+ }
+#else
+ *captcha_url = "/accounts/" + image_url;
+#endif
+
+ *captcha_token = GetValueForKey("CaptchaToken", response);
+ }
+ return GR_UNAUTHORIZED;
+ }
+
+ if (status_code != talk_base::HC_OK) {
+ return GR_ERROR;
+ }
+
+ *sid = GetValueForKey("SID", response);
+ *lsid = GetValueForKey("LSID", response);
+ if (auth) {
+ *auth = GetValueForKey("Auth", response);
+ }
+ if (sid->empty() || lsid->empty()) {
+ return GR_ERROR;
+ }
+
+ return GR_SUCCESS;
+}
+
+bool GaiaRequestAuthToken(talk_base::HttpClient* client,
+ const std::string& sid,
+ const std::string& lsid,
+ const std::string& service,
+ const GaiaServer& gaia_server) {
+ std::string post_data;
+ post_data += "SID=" + UrlEncodeString(sid);
+ post_data += "&LSID=" + UrlEncodeString(lsid);
+ post_data += "&service=" + service;
+ post_data += "&Session=true"; // Creates two week cookie.
+
+ client->reset();
+ client->set_server(talk_base::SocketAddress(gaia_server.hostname(),
+ gaia_server.port(), false));
+ client->request().verb = talk_base::HV_POST;
+ client->request().path = "/accounts/IssueAuthToken";
+ client->request().setContent("application/x-www-form-urlencoded",
+ new talk_base::MemoryStream(post_data.data(), post_data.size()));
+ client->response().document.reset(new talk_base::MemoryStream);
+ client->start();
+ return true;
+}
+
+GaiaResponse GaiaParseAuthTokenResponse(const talk_base::HttpClient& client,
+ std::string* auth_token) {
+ if (client.response().scode != talk_base::HC_OK) {
+ return GR_ERROR;
+ }
+
+ const talk_base::MemoryStream* stream =
+ static_cast<const talk_base::MemoryStream*>(
+ client.response().document.get());
+ size_t length;
+ stream->GetPosition(&length);
+ while ((length > 0) && isspace(stream->GetBuffer()[length-1]))
+ --length;
+ auth_token->assign(stream->GetBuffer(), length);
+ return auth_token->empty() ? GR_ERROR : GR_SUCCESS;
+}
+
+} // namespace buzz
diff --git a/chrome/browser/sync/notifier/gaia_auth/gaiahelper.h b/chrome/browser/sync/notifier/gaia_auth/gaiahelper.h
new file mode 100644
index 0000000..933bc97
--- /dev/null
+++ b/chrome/browser/sync/notifier/gaia_auth/gaiahelper.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2009 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 CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_GAIAHELPER_H__
+#define CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_GAIAHELPER_H__
+
+#include <string>
+
+namespace talk_base {
+class CryptString;
+class HttpClient;
+}
+
+namespace buzz {
+
+///////////////////////////////////////////////////////////////////////////////
+
+class CaptchaAnswer {
+ public:
+ CaptchaAnswer() {}
+ CaptchaAnswer(const std::string& token, const std::string& answer)
+ : captcha_token_(token), captcha_answer_(answer) {
+ }
+ const std::string& captcha_token() const { return captcha_token_; }
+ const std::string& captcha_answer() const { return captcha_answer_; }
+
+ private:
+ std::string captcha_token_;
+ std::string captcha_answer_;
+};
+
+class GaiaServer {
+ public:
+ GaiaServer();
+
+ bool SetServer(const char* url); // protocol://server:port
+ bool SetDebugServer(const char* server); // server:port
+
+ const std::string& hostname() const { return hostname_; }
+ int port() const { return port_; }
+ bool use_ssl() const { return use_ssl_; }
+
+ std::string http_prefix() const;
+
+ private:
+ std::string hostname_;
+ int port_;
+ bool use_ssl_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Gaia Authentication Helper Functions
+///////////////////////////////////////////////////////////////////////////////
+
+enum GaiaResponse { GR_ERROR, GR_UNAUTHORIZED, GR_SUCCESS };
+
+bool GaiaRequestSid(talk_base::HttpClient* client,
+ const std::string& username,
+ const talk_base::CryptString& password,
+ const std::string& signature,
+ const std::string& service,
+ const CaptchaAnswer& captcha_answer,
+ const GaiaServer& gaia_server);
+
+GaiaResponse GaiaParseSidResponse(const talk_base::HttpClient& client,
+ const GaiaServer& gaia_server,
+ std::string* captcha_token,
+ std::string* captcha_url,
+ std::string* sid,
+ std::string* lsid,
+ std::string* auth);
+
+bool GaiaRequestAuthToken(talk_base::HttpClient* client,
+ const std::string& sid,
+ const std::string& lsid,
+ const std::string& service,
+ const GaiaServer& gaia_server);
+
+GaiaResponse GaiaParseAuthTokenResponse(const talk_base::HttpClient& client,
+ std::string* auth_token);
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace buzz
+
+#endif // CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_GAIAHELPER_H__
diff --git a/chrome/browser/sync/notifier/gaia_auth/inet_aton.h b/chrome/browser/sync/notifier/gaia_auth/inet_aton.h
new file mode 100644
index 0000000..29e4dcb
--- /dev/null
+++ b/chrome/browser/sync/notifier/gaia_auth/inet_aton.h
@@ -0,0 +1,14 @@
+// Copyright (c) 2009 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.
+//
+// Define inet_aton alone so it's easier to include.
+
+#ifndef CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_INET_ATON_H_
+#define CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_INET_ATON_H_
+
+#if defined(OS_WIN)
+int inet_aton(const char* cp, struct in_addr* inp);
+#endif
+
+#endif // CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_INET_ATON_H_
diff --git a/chrome/browser/sync/notifier/base/sigslotrepeater.h b/chrome/browser/sync/notifier/gaia_auth/sigslotrepeater.h
index 85ab3e6..3c0941e 100644
--- a/chrome/browser/sync/notifier/base/sigslotrepeater.h
+++ b/chrome/browser/sync/notifier/gaia_auth/sigslotrepeater.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_SYNC_NOTIFIER_BASE_SIGSLOTREPEATER_H_
-#define CHROME_BROWSER_SYNC_NOTIFIER_BASE_SIGSLOTREPEATER_H_
+#ifndef CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_INET_ATON_H_SIGSLOTREPEATER_H_
+#define CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_INET_ATON_H_SIGSLOTREPEATER_H_
// Repeaters are both signals and slots, which are designed as intermediate
// pass-throughs for signals and slots which don't know about each other (for
@@ -80,4 +80,4 @@ class repeater3 : public signal3<arg1_type, arg2_type, arg3_type, mt_policy>,
} // namespace sigslot
-#endif // CHROME_BROWSER_SYNC_NOTIFIER_BASE_SIGSLOTREPEATER_H_
+#endif // CHROME_BROWSER_SYNC_NOTIFIER_GAIA_AUTH_INET_ATON_H_SIGSLOTREPEATER_H_
diff --git a/third_party/libjingle/files/talk/base/win32window.cc b/chrome/browser/sync/notifier/gaia_auth/win/win32window.cc
index 05d639b..720838e 100644
--- a/third_party/libjingle/files/talk/base/win32window.cc
+++ b/chrome/browser/sync/notifier/gaia_auth/win/win32window.cc
@@ -1,33 +1,12 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+// Copyright (c) 2009 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.
+//
+// Originally from libjingle. Minor alterations to compile it in Chrome.
#include "talk/base/win32window.h"
-#include "talk/base/logging.h"
+#include "base/logging.h"
#include "talk/base/common.h"
namespace talk_base {
@@ -64,7 +43,7 @@ bool Win32Window::Create(HWND parent, const wchar_t* title, DWORD style,
wcex.lpszClassName = kWindowBaseClassName;
window_class_ = ::RegisterClassEx(&wcex);
if (!window_class_) {
- LOG(LS_ERROR) << "RegisterClassEx failed: " << GetLastError();
+ LOG(ERROR) << "RegisterClassEx failed: " << GetLastError();
return false;
}
}
@@ -119,7 +98,7 @@ LRESULT Win32Window::WndProc(HWND hwnd, UINT uMsg,
if (WM_DESTROY == uMsg) {
for (HWND child = ::GetWindow(hwnd, GW_CHILD); child;
child = ::GetWindow(child, GW_HWNDNEXT)) {
- LOG(LS_INFO) << "Child window: " << static_cast<void*>(child);
+ LOG(INFO) << "Child window: " << static_cast<void*>(child);
}
}
if (WM_NCDESTROY == uMsg) {
diff --git a/chrome/browser/sync/notifier/listener/mediator_thread_impl.cc b/chrome/browser/sync/notifier/listener/mediator_thread_impl.cc
index 4728268..11cf90a 100644
--- a/chrome/browser/sync/notifier/listener/mediator_thread_impl.cc
+++ b/chrome/browser/sync/notifier/listener/mediator_thread_impl.cc
@@ -190,6 +190,7 @@ void MediatorThreadImpl::DoLogin(LoginData* login_data) {
NULL,
// talk_base::FirewallManager* is NULL.
NULL,
+ false,
// Both the proxy and a non-proxy route
// will be attempted.
false,
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 2ae4173..98bce6c 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -772,6 +772,8 @@
'browser/sync/notifier/base/utils.h',
'browser/sync/notifier/base/win/async_network_alive_win32.cc',
'browser/sync/notifier/base/win/time_win32.cc',
+ 'browser/sync/notifier/communicator/auth_task.cc',
+ 'browser/sync/notifier/communicator/auth_task.h',
'browser/sync/notifier/communicator/auto_reconnect.cc',
'browser/sync/notifier/communicator/auto_reconnect.h',
'browser/sync/notifier/communicator/connection_options.cc',
@@ -791,12 +793,21 @@
'browser/sync/notifier/communicator/single_login_attempt.h',
'browser/sync/notifier/communicator/ssl_socket_adapter.cc',
'browser/sync/notifier/communicator/ssl_socket_adapter.h',
+ 'browser/sync/notifier/communicator/talk_auth_task.cc',
+ 'browser/sync/notifier/communicator/talk_auth_task.h',
'browser/sync/notifier/communicator/xmpp_connection_generator.cc',
'browser/sync/notifier/communicator/xmpp_connection_generator.h',
'browser/sync/notifier/communicator/xmpp_log.cc',
'browser/sync/notifier/communicator/xmpp_log.h',
'browser/sync/notifier/communicator/xmpp_socket_adapter.cc',
'browser/sync/notifier/communicator/xmpp_socket_adapter.h',
+ 'browser/sync/notifier/gaia_auth/gaiaauth.cc',
+ 'browser/sync/notifier/gaia_auth/gaiaauth.h',
+ 'browser/sync/notifier/gaia_auth/gaiahelper.cc',
+ 'browser/sync/notifier/gaia_auth/gaiahelper.h',
+ 'browser/sync/notifier/gaia_auth/inet_aton.h',
+ 'browser/sync/notifier/gaia_auth/sigslotrepeater.h',
+ 'browser/sync/notifier/gaia_auth/win/win32window.cc',
'browser/sync/notifier/listener/listen_task.cc',
'browser/sync/notifier/listener/listen_task.h',
'browser/sync/notifier/listener/mediator_thread.h',
@@ -807,7 +818,6 @@
'browser/sync/notifier/listener/notification_constants.h',
'browser/sync/notifier/listener/send_update_task.cc',
'browser/sync/notifier/listener/send_update_task.h',
- 'browser/sync/notifier/base/sigslotrepeater.h',
'browser/sync/notifier/listener/subscribe_task.cc',
'browser/sync/notifier/listener/subscribe_task.h',
'browser/sync/notifier/listener/talk_mediator.h',
diff --git a/third_party/libjingle/libjingle.gyp b/third_party/libjingle/libjingle.gyp
index 5b04c2b..180f8a3 100644
--- a/third_party/libjingle/libjingle.gyp
+++ b/third_party/libjingle/libjingle.gyp
@@ -219,7 +219,6 @@
'files/talk/base/win32socketserver.cc',
'files/talk/base/win32socketserver.h',
'files/talk/base/win32window.h',
- 'files/talk/base/win32window.cc',
'files/talk/base/winfirewall.cc',
'files/talk/base/winfirewall.h',
'files/talk/base/winping.cc',
diff --git a/third_party/libjingle/mods-since-v0_4_0.diff b/third_party/libjingle/mods-since-v0_4_0.diff
index 7403b4f..307439e4 100644
--- a/third_party/libjingle/mods-since-v0_4_0.diff
+++ b/third_party/libjingle/mods-since-v0_4_0.diff
@@ -1140,7 +1140,6 @@ diff -r libjingle-0.4.0/talk/base/win32socketserver.cc libjingle/files/talk/base
> #include "talk/base/winsock_initializer.h"
269a271
> talk_base::EnsureWinsockInit();
-Only in libjingle/files/talk/base: win32window.cc
diff -r libjingle-0.4.0/talk/base/winping.cc libjingle/files/talk/base/winping.cc
133c133
< return sizeof(ICMP_ECHO_REPLY) + max(8UL, data_size);