// Copyright (c) 2011 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/invalidation_notifier.h"
#include "base/logging.h"
#include "base/message_loop_proxy.h"
#include "chrome/browser/sync/notifier/sync_notifier_observer.h"
#include "chrome/browser/sync/protocol/service_constants.h"
#include "chrome/browser/sync/syncable/model_type_payload_map.h"
#include "jingle/notifier/base/const_communicator.h"
#include "jingle/notifier/base/notifier_options_util.h"
#include "jingle/notifier/communicator/connection_options.h"
#include "net/base/host_port_pair.h"
#include "net/url_request/url_request_context.h"
#include "talk/xmpp/jid.h"
#include "talk/xmpp/xmppclientsettings.h"
namespace sync_notifier {
InvalidationNotifier::InvalidationNotifier(
const notifier::NotifierOptions& notifier_options,
const std::string& client_info)
: state_(STOPPED),
notifier_options_(notifier_options),
client_info_(client_info) {
DCHECK_EQ(notifier::NOTIFICATION_SERVER,
notifier_options.notification_method);
DCHECK(notifier_options_.request_context_getter);
// TODO(akalin): Replace NonThreadSafe checks with IO thread checks.
DCHECK(notifier_options_.request_context_getter->GetIOMessageLoopProxy()->
BelongsToCurrentThread());
}
InvalidationNotifier::~InvalidationNotifier() {
DCHECK(non_thread_safe_.CalledOnValidThread());
}
void InvalidationNotifier::AddObserver(SyncNotifierObserver* observer) {
DCHECK(non_thread_safe_.CalledOnValidThread());
observers_.AddObserver(observer);
}
void InvalidationNotifier::RemoveObserver(SyncNotifierObserver* observer) {
DCHECK(non_thread_safe_.CalledOnValidThread());
observers_.RemoveObserver(observer);
}
void InvalidationNotifier::SetState(const std::string& state) {
DCHECK(non_thread_safe_.CalledOnValidThread());
invalidation_state_ = state;
}
void InvalidationNotifier::UpdateCredentials(
const std::string& email, const std::string& token) {
DCHECK(non_thread_safe_.CalledOnValidThread());
VLOG(1) << "Updating credentials for " << email;
buzz::XmppClientSettings xmpp_client_settings =
notifier::MakeXmppClientSettings(notifier_options_,
email, token, SYNC_SERVICE_NAME);
if (state_ >= CONNECTING) {
login_->UpdateXmppSettings(xmpp_client_settings);
} else {
notifier::ConnectionOptions options;
VLOG(1) << "First time updating credentials: connecting";
login_.reset(
new notifier::Login(this,
xmpp_client_settings,
notifier::ConnectionOptions(),
notifier_options_.request_context_getter,
notifier::GetServerList(notifier_options_),
notifier_options_.try_ssltcp_first,
notifier_options_.auth_mechanism));
login_->StartConnection();
state_ = CONNECTING;
}
}
void InvalidationNotifier::UpdateEnabledTypes(
const syncable::ModelTypeSet& types) {
DCHECK(non_thread_safe_.CalledOnValidThread());
invalidation_client_.RegisterTypes(types);
}
void InvalidationNotifier::SendNotification() {
DCHECK(non_thread_safe_.CalledOnValidThread());
}
void InvalidationNotifier::OnConnect(
base::WeakPtr<talk_base::Task> base_task) {
DCHECK(non_thread_safe_.CalledOnValidThread());
VLOG(1) << "OnConnect";
if (state_ >= STARTED) {
invalidation_client_.ChangeBaseTask(base_task);
} else {
VLOG(1) << "First time connecting: starting invalidation client";
// TODO(akalin): Make cache_guid() part of the client ID. If we
// do so and we somehow propagate it up to the server somehow, we
// can make it so that we won't receive any notifications that
// were generated from our own changes.
const std::string kClientId = "invalidation_notifier";
invalidation_client_.Start(
kClientId, client_info_, invalidation_state_, this, this, base_task);
invalidation_state_.clear();
state_ = STARTED;
}
}
void InvalidationNotifier::OnDisconnect() {
DCHECK(non_thread_safe_.CalledOnValidThread());
VLOG(1) << "OnDisconnect";
}
void InvalidationNotifier::OnInvalidate(
const syncable::ModelTypePayloadMap& type_payloads) {
DCHECK(non_thread_safe_.CalledOnValidThread());
FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
OnIncomingNotification(type_payloads));
}
void InvalidationNotifier::OnSessionStatusChanged(bool has_session) {
FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
OnNotificationStateChange(has_session));
}
void InvalidationNotifier::WriteState(const std::string& state) {
DCHECK(non_thread_safe_.CalledOnValidThread());
VLOG(1) << "WriteState";
FOR_EACH_OBSERVER(SyncNotifierObserver, observers_, StoreState(state));
}
} // namespace sync_notifier