| Index: chrome/browser/sync/notifier/communicator/login.cc
|
| ===================================================================
|
| --- chrome/browser/sync/notifier/communicator/login.cc (revision 46353)
|
| +++ chrome/browser/sync/notifier/communicator/login.cc (working copy)
|
| @@ -1,358 +0,0 @@
|
| -// 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 "chrome/browser/sync/notifier/communicator/login.h"
|
| -
|
| -#include "chrome/browser/sync/notifier/base/network_status_detector_task.h"
|
| -#include "chrome/browser/sync/notifier/base/time.h"
|
| -#include "chrome/browser/sync/notifier/base/timer.h"
|
| -#include "chrome/browser/sync/notifier/communicator/auto_reconnect.h"
|
| -#include "chrome/browser/sync/notifier/communicator/connection_options.h"
|
| -#include "chrome/browser/sync/notifier/communicator/login_settings.h"
|
| -#include "chrome/browser/sync/notifier/communicator/product_info.h"
|
| -#include "chrome/browser/sync/notifier/communicator/single_login_attempt.h"
|
| -#include "talk/base/common.h"
|
| -#include "talk/base/firewallsocketserver.h"
|
| -#include "talk/base/logging.h"
|
| -#include "talk/base/taskrunner.h"
|
| -#include "talk/xmllite/xmlelement.h"
|
| -#include "talk/xmpp/asyncsocket.h"
|
| -#include "talk/xmpp/prexmppauth.h"
|
| -#include "talk/xmpp/xmppclient.h"
|
| -#include "talk/xmpp/xmppclientsettings.h"
|
| -#include "talk/xmpp/xmppengine.h"
|
| -
|
| -namespace notifier {
|
| -
|
| -// Redirect valid for 5 minutes.
|
| -static const time64 kRedirectTimeoutNs = 5 * kMinsTo100ns;
|
| -
|
| -// Disconnect if network stays down for more than 10 seconds.
|
| -static const int kDisconnectionDelaySecs = 10;
|
| -
|
| -Login::Login(talk_base::Task* parent,
|
| - const buzz::XmppClientSettings& user_settings,
|
| - const ConnectionOptions& options,
|
| - std::string lang,
|
| - ServerInformation* server_list,
|
| - int server_count,
|
| - NetworkStatusDetectorTask* network_status,
|
| - talk_base::FirewallManager* firewall,
|
| - bool proxy_only,
|
| - bool previous_login_successful)
|
| - : login_settings_(new LoginSettings(user_settings,
|
| - options,
|
| - lang,
|
| - server_list,
|
| - server_count,
|
| - firewall,
|
| - proxy_only)),
|
| - single_attempt_(NULL),
|
| - successful_connection_(previous_login_successful),
|
| - parent_(parent),
|
| - state_(STATE_OPENING),
|
| - redirect_time_ns_(0),
|
| - redirect_port_(0),
|
| - unexpected_disconnect_occurred_(false),
|
| - reset_unexpected_timer_(NULL),
|
| - google_host_(user_settings.host()),
|
| - google_user_(user_settings.user()),
|
| - disconnect_timer_(NULL) {
|
| - if (!network_status) {
|
| - network_status = NetworkStatusDetectorTask::Create(parent_);
|
| - if (network_status) {
|
| - // On linux we don't have an implementation of NetworkStatusDetectorTask.
|
| - network_status->Start();
|
| - }
|
| - }
|
| -
|
| - if (network_status) {
|
| - network_status->SignalNetworkStateDetected.connect(
|
| - this, &Login::OnNetworkStateDetected);
|
| - auto_reconnect_.reset(new AutoReconnect(parent_, network_status));
|
| - auto_reconnect_->SignalStartConnection.connect(this,
|
| - &Login::StartConnection);
|
| - auto_reconnect_->SignalTimerStartStop.connect(
|
| - this,
|
| - &Login::OnAutoReconnectTimerChange);
|
| - SignalClientStateChange.connect(auto_reconnect_.get(),
|
| - &AutoReconnect::OnClientStateChange);
|
| - SignalIdleChange.connect(auto_reconnect_.get(),
|
| - &AutoReconnect::set_idle);
|
| - SignalPowerSuspended.connect(auto_reconnect_.get(),
|
| - &AutoReconnect::OnPowerSuspend);
|
| - }
|
| -}
|
| -
|
| -// Defined so that the destructors are executed here (and the corresponding
|
| -// classes don't need to be included in the header file).
|
| -Login::~Login() {
|
| - if (single_attempt_) {
|
| - single_attempt_->Abort();
|
| - single_attempt_ = NULL;
|
| - }
|
| -}
|
| -
|
| -void Login::StartConnection() {
|
| - // If there is a server redirect, use it.
|
| - if (GetCurrent100NSTime() < redirect_time_ns_ + kRedirectTimeoutNs) {
|
| - // Override server/port with redirect values.
|
| - talk_base::SocketAddress server_override;
|
| - server_override.SetIP(redirect_server_, false);
|
| - ASSERT(redirect_port_ != 0);
|
| - server_override.SetPort(redirect_port_);
|
| - login_settings_->set_server_override(server_override);
|
| - } else {
|
| - login_settings_->clear_server_override();
|
| - }
|
| -
|
| - if (single_attempt_) {
|
| - single_attempt_->Abort();
|
| - single_attempt_ = NULL;
|
| - }
|
| - single_attempt_ = new SingleLoginAttempt(parent_,
|
| - login_settings_.get(),
|
| - successful_connection_);
|
| -
|
| - // Do the signaling hook-ups.
|
| - single_attempt_->SignalLoginFailure.connect(this, &Login::OnLoginFailure);
|
| - single_attempt_->SignalRedirect.connect(this, &Login::OnRedirect);
|
| - single_attempt_->SignalClientStateChange.connect(
|
| - this,
|
| - &Login::OnClientStateChange);
|
| - single_attempt_->SignalUnexpectedDisconnect.connect(
|
| - this,
|
| - &Login::OnUnexpectedDisconnect);
|
| - single_attempt_->SignalLogoff.connect(
|
| - this,
|
| - &Login::OnLogoff);
|
| - single_attempt_->SignalNeedAutoReconnect.connect(
|
| - this,
|
| - &Login::DoAutoReconnect);
|
| - SignalLogInput.repeat(single_attempt_->SignalLogInput);
|
| - SignalLogOutput.repeat(single_attempt_->SignalLogOutput);
|
| -
|
| - single_attempt_->Start();
|
| -}
|
| -
|
| -const std::string& Login::google_host() const {
|
| - return google_host_;
|
| -}
|
| -
|
| -const std::string& Login::google_user() const {
|
| - return google_user_;
|
| -}
|
| -
|
| -const talk_base::ProxyInfo& Login::proxy() const {
|
| - return proxy_info_;
|
| -}
|
| -
|
| -void Login::OnLoginFailure(const LoginFailure& failure) {
|
| - auto_reconnect_->StopReconnectTimer();
|
| - HandleClientStateChange(STATE_CLOSED);
|
| - SignalLoginFailure(failure);
|
| -}
|
| -
|
| -void Login::OnLogoff() {
|
| - HandleClientStateChange(STATE_CLOSED);
|
| -}
|
| -
|
| -void Login::OnClientStateChange(buzz::XmppEngine::State state) {
|
| - ConnectionState new_state = STATE_CLOSED;
|
| -
|
| - switch (state) {
|
| - case buzz::XmppEngine::STATE_NONE:
|
| - case buzz::XmppEngine::STATE_CLOSED:
|
| - // Ignore the closed state (because we may be trying the next dns entry).
|
| - //
|
| - // But we go to this state for other signals when there is no retry
|
| - // happening.
|
| - new_state = state_;
|
| - break;
|
| -
|
| - case buzz::XmppEngine::STATE_START:
|
| - case buzz::XmppEngine::STATE_OPENING:
|
| - new_state = STATE_OPENING;
|
| - break;
|
| -
|
| - case buzz::XmppEngine::STATE_OPEN:
|
| - new_state = STATE_OPENED;
|
| - break;
|
| -
|
| - default:
|
| - ASSERT(false);
|
| - break;
|
| - }
|
| - HandleClientStateChange(new_state);
|
| -}
|
| -
|
| -void Login::HandleClientStateChange(ConnectionState new_state) {
|
| - // Do we need to transition between the retrying and closed states?
|
| - if (auto_reconnect_.get() && auto_reconnect_->is_retrying()) {
|
| - if (new_state == STATE_CLOSED) {
|
| - new_state = STATE_RETRYING;
|
| - }
|
| - } else {
|
| - if (new_state == STATE_RETRYING) {
|
| - new_state = STATE_CLOSED;
|
| - }
|
| - }
|
| -
|
| - if (new_state != state_) {
|
| - state_ = new_state;
|
| - if (reset_unexpected_timer_) {
|
| - reset_unexpected_timer_->Abort();
|
| - reset_unexpected_timer_ = NULL;
|
| - }
|
| -
|
| - if (state_ == STATE_OPENED) {
|
| - successful_connection_ = true;
|
| -
|
| - google_host_ = single_attempt_->xmpp_client()->jid().domain();
|
| - google_user_ = single_attempt_->xmpp_client()->jid().node();
|
| - proxy_info_ = single_attempt_->proxy();
|
| -
|
| - reset_unexpected_timer_ = new Timer(parent_,
|
| - kResetReconnectInfoDelaySec,
|
| - false); // Repeat.
|
| - reset_unexpected_timer_->SignalTimeout.connect(
|
| - this,
|
| - &Login::ResetUnexpectedDisconnect);
|
| - }
|
| - SignalClientStateChange(state_);
|
| - }
|
| -}
|
| -
|
| -void Login::OnAutoReconnectTimerChange() {
|
| - if (!single_attempt_ || !single_attempt_->xmpp_client()) {
|
| - HandleClientStateChange(STATE_CLOSED);
|
| - return;
|
| - }
|
| - OnClientStateChange(single_attempt_->xmpp_client()->GetState());
|
| -}
|
| -
|
| -buzz::XmppClient* Login::xmpp_client() {
|
| - if (!single_attempt_) {
|
| - return NULL;
|
| - }
|
| - return single_attempt_->xmpp_client();
|
| -}
|
| -
|
| -int Login::seconds_until_reconnect() const {
|
| - return auto_reconnect_->seconds_until();
|
| -}
|
| -
|
| -void Login::UseNextConnection() {
|
| - if (!single_attempt_) {
|
| - // Just in case, there is an obscure case that causes this to get called
|
| - // when there is no single_attempt_.
|
| - return;
|
| - }
|
| - single_attempt_->UseNextConnection();
|
| -}
|
| -
|
| -void Login::UseCurrentConnection() {
|
| - if (!single_attempt_) {
|
| - // Just in case, there is an obscure case that causes this to get called
|
| - // when there is no single_attempt_.
|
| - return;
|
| - }
|
| - single_attempt_->UseCurrentConnection();
|
| -}
|
| -
|
| -void Login::OnRedirect(const std::string& redirect_server, int redirect_port) {
|
| - ASSERT(redirect_port_ != 0);
|
| -
|
| - redirect_time_ns_ = GetCurrent100NSTime();
|
| - redirect_server_ = redirect_server;
|
| - redirect_port_ = redirect_port;
|
| -
|
| - // Drop the current connection, and start the login process again.
|
| - StartConnection();
|
| -}
|
| -
|
| -void Login::OnUnexpectedDisconnect() {
|
| - if (reset_unexpected_timer_) {
|
| - reset_unexpected_timer_->Abort();
|
| - reset_unexpected_timer_ = NULL;
|
| - }
|
| -
|
| - // Start the login process again.
|
| - if (unexpected_disconnect_occurred_) {
|
| - // If we already have received an unexpected disconnect recently, then our
|
| - // account may have be jailed due to abuse, so we shouldn't make the
|
| - // situation worse by trying really hard to reconnect. Instead, we'll do
|
| - // the autoreconnect route, which has exponential back-off.
|
| - DoAutoReconnect();
|
| - return;
|
| - }
|
| - StartConnection();
|
| - unexpected_disconnect_occurred_ = true;
|
| -}
|
| -
|
| -void Login::ResetUnexpectedDisconnect() {
|
| - reset_unexpected_timer_ = NULL;
|
| - unexpected_disconnect_occurred_ = false;
|
| -}
|
| -
|
| -void Login::DoAutoReconnect() {
|
| - bool allow_auto_reconnect =
|
| - login_settings_->connection_options().auto_reconnect();
|
| - // Start the reconnect time before aborting the connection to ensure that
|
| - // AutoReconnect::is_retrying() is true, so that the Login doesn't
|
| - // transition to the CLOSED state (which would cause the reconnection timer
|
| - // to reset and not double).
|
| - if (allow_auto_reconnect) {
|
| - auto_reconnect_->StartReconnectTimer();
|
| - }
|
| -
|
| - if (single_attempt_) {
|
| - single_attempt_->Abort();
|
| - single_attempt_ = NULL;
|
| - }
|
| -
|
| - if (!allow_auto_reconnect) {
|
| - HandleClientStateChange(STATE_CLOSED);
|
| - return;
|
| - }
|
| -}
|
| -
|
| -void Login::OnNetworkStateDetected(bool was_alive, bool is_alive) {
|
| - if (was_alive && !is_alive) {
|
| - // Our network connection just went down. Setup a timer to disconnect.
|
| - // Don't disconnect immediately to avoid constant
|
| - // connection/disconnection due to flaky network interfaces.
|
| - ASSERT(disconnect_timer_ == NULL);
|
| - disconnect_timer_ = new Timer(parent_, kDisconnectionDelaySecs, false);
|
| - disconnect_timer_->SignalTimeout.connect(this,
|
| - &Login::OnDisconnectTimeout);
|
| - } else if (!was_alive && is_alive) {
|
| - // Our connection has come back up. If we have a disconnect timer going,
|
| - // abort it so we don't disconnect.
|
| - if (disconnect_timer_) {
|
| - disconnect_timer_->Abort();
|
| - // It will free itself.
|
| - disconnect_timer_ = NULL;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void Login::OnDisconnectTimeout() {
|
| - disconnect_timer_ = NULL;
|
| -
|
| - if (state_ != STATE_OPENED) {
|
| - return;
|
| - }
|
| -
|
| - if (single_attempt_) {
|
| - single_attempt_->Abort();
|
| - single_attempt_ = NULL;
|
| - }
|
| -
|
| - StartConnection();
|
| -}
|
| -
|
| -} // namespace notifier
|
|
|