summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync
diff options
context:
space:
mode:
authorlipalani@chromium.org <lipalani@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 04:29:25 +0000
committerlipalani@chromium.org <lipalani@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 04:29:25 +0000
commitfd44ec78f94eca53ebf278fdaffea005d75fd4b1 (patch)
treeaf5ec3ec3a3f792edcf87c27bbda3c5e9b39d541 /chrome/browser/sync
parent48d701b12eeedd4c52bc507a3c250170ba137305 (diff)
downloadchromium_src-fd44ec78f94eca53ebf278fdaffea005d75fd4b1.zip
chromium_src-fd44ec78f94eca53ebf278fdaffea005d75fd4b1.tar.gz
chromium_src-fd44ec78f94eca53ebf278fdaffea005d75fd4b1.tar.bz2
make new syncer thread the default. Fixed all the test cases that failed.
BUG=26339 TEST=unit_tests.exe, sync_integration_tests.exe, sync_unit_tests.exe. manual testcases: 1. Set up a brand new profile to sync and make sure it syncs. 2. enable/disable a datatype and make sure it syncs. 3. Make change to a datatype locally and make sure it gets propagated. 4. make change to a datatype remotely and make sure it syncs down. Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=82026 Review URL: http://codereview.chromium.org/6874018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82067 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync')
-rw-r--r--chrome/browser/sync/engine/all_status.cc7
-rw-r--r--chrome/browser/sync/engine/net/server_connection_manager.cc14
-rw-r--r--chrome/browser/sync/engine/nudge_source.h5
-rw-r--r--chrome/browser/sync/engine/syncapi.cc96
-rw-r--r--chrome/browser/sync/engine/syncapi.h20
-rw-r--r--chrome/browser/sync/engine/syncapi_unittest.cc2
-rw-r--r--chrome/browser/sync/engine/syncer_end_command.cc4
-rw-r--r--chrome/browser/sync/engine/syncer_thread.cc1449
-rw-r--r--chrome/browser/sync/engine/syncer_thread.h575
-rw-r--r--chrome/browser/sync/engine/syncer_thread2.cc863
-rw-r--r--chrome/browser/sync/engine/syncer_thread2.h344
-rw-r--r--chrome/browser/sync/engine/syncer_thread2_unittest.cc7
-rw-r--r--chrome/browser/sync/engine/syncer_thread2_whitebox_unittest.cc8
-rw-r--r--chrome/browser/sync/engine/syncer_thread_adapter.cc148
-rw-r--r--chrome/browser/sync/engine/syncer_thread_adapter.h60
-rw-r--r--chrome/browser/sync/engine/syncer_thread_unittest.cc1242
-rw-r--r--chrome/browser/sync/engine/syncer_types.h29
-rw-r--r--chrome/browser/sync/glue/data_type_manager.h5
-rw-r--r--chrome/browser/sync/glue/data_type_manager_impl.cc250
-rw-r--r--chrome/browser/sync/glue/data_type_manager_impl.h34
-rw-r--r--chrome/browser/sync/glue/data_type_manager_impl2.cc363
-rw-r--r--chrome/browser/sync/glue/data_type_manager_impl2.h81
-rw-r--r--chrome/browser/sync/glue/data_type_manager_impl2_unittest.cc30
-rw-r--r--chrome/browser/sync/glue/data_type_manager_impl_unittest.cc685
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.cc116
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.h34
-rw-r--r--chrome/browser/sync/glue/sync_backend_host_mock.cc9
-rw-r--r--chrome/browser/sync/glue/sync_backend_host_mock.h2
-rw-r--r--chrome/browser/sync/js_sync_manager_observer.cc8
-rw-r--r--chrome/browser/sync/js_sync_manager_observer.h2
-rw-r--r--chrome/browser/sync/js_sync_manager_observer_unittest.cc9
-rw-r--r--chrome/browser/sync/profile_sync_factory_impl.cc7
-rw-r--r--chrome/browser/sync/profile_sync_service.cc7
-rw-r--r--chrome/browser/sync/profile_sync_service_password_unittest.cc5
-rw-r--r--chrome/browser/sync/sessions/sync_session_context.cc7
-rw-r--r--chrome/browser/sync/sessions/sync_session_context.h7
-rw-r--r--chrome/browser/sync/test_profile_sync_service.cc19
-rw-r--r--chrome/browser/sync/test_profile_sync_service.h2
38 files changed, 1137 insertions, 5418 deletions
diff --git a/chrome/browser/sync/engine/all_status.cc b/chrome/browser/sync/engine/all_status.cc
index 77d2f5f..0b454a3 100644
--- a/chrome/browser/sync/engine/all_status.cc
+++ b/chrome/browser/sync/engine/all_status.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// 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.
@@ -106,12 +106,7 @@ void AllStatus::OnSyncEngineEvent(const SyncEngineEvent& event) {
case SyncEngineEvent::STATUS_CHANGED:
status_ = CalcSyncing(event);
break;
- case SyncEngineEvent::SYNCER_THREAD_PAUSED:
- case SyncEngineEvent::SYNCER_THREAD_RESUMED:
- case SyncEngineEvent::SYNCER_THREAD_WAITING_FOR_CONNECTION:
- case SyncEngineEvent::SYNCER_THREAD_CONNECTED:
case SyncEngineEvent::STOP_SYNCING_PERMANENTLY:
- case SyncEngineEvent::SYNCER_THREAD_EXITING:
break;
default:
LOG(ERROR) << "Unrecognized Syncer Event: " << event.what_happened;
diff --git a/chrome/browser/sync/engine/net/server_connection_manager.cc b/chrome/browser/sync/engine/net/server_connection_manager.cc
index 4598588..f84b8b7 100644
--- a/chrome/browser/sync/engine/net/server_connection_manager.cc
+++ b/chrome/browser/sync/engine/net/server_connection_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -158,16 +158,8 @@ ServerConnectionManager::~ServerConnectionManager() {
}
void ServerConnectionManager::NotifyStatusChanged() {
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kNewSyncerThread)) {
- listeners_->Notify(&ServerConnectionEventListener::OnServerConnectionEvent,
- ServerConnectionEvent2(server_status_, server_reachable_));
- } else {
- ServerConnectionEvent event = { ServerConnectionEvent::STATUS_CHANGED,
- server_status_,
- server_reachable_ };
- channel_->NotifyListeners(event);
- }
+ listeners_->Notify(&ServerConnectionEventListener::OnServerConnectionEvent,
+ ServerConnectionEvent2(server_status_, server_reachable_));
}
bool ServerConnectionManager::PostBufferWithCachedAuth(
diff --git a/chrome/browser/sync/engine/nudge_source.h b/chrome/browser/sync/engine/nudge_source.h
index 3e3b3ae..fc9b02a 100644
--- a/chrome/browser/sync/engine/nudge_source.h
+++ b/chrome/browser/sync/engine/nudge_source.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -8,8 +8,6 @@
namespace browser_sync {
-namespace s3 {
-
enum NudgeSource {
NUDGE_SOURCE_UNKNOWN = 0,
// We received an invalidation message and are nudging to check for updates.
@@ -20,7 +18,6 @@ enum NudgeSource {
NUDGE_SOURCE_CONTINUATION,
};
-} // namespace s3
} // namespace browser_sync
#endif // CHROME_BROWSER_SYNC_ENGINE_NUDGE_SOURCE_H_
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc
index 7792dc6..41da3d7 100644
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -23,17 +23,17 @@
#include "base/string_util.h"
#include "base/synchronization/lock.h"
#include "base/task.h"
+#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/sync/engine/all_status.h"
#include "chrome/browser/sync/engine/change_reorder_buffer.h"
#include "chrome/browser/sync/engine/model_safe_worker.h"
+#include "chrome/browser/sync/engine/nudge_source.h"
#include "chrome/browser/sync/engine/net/server_connection_manager.h"
#include "chrome/browser/sync/engine/net/syncapi_server_connection_manager.h"
#include "chrome/browser/sync/engine/syncer.h"
#include "chrome/browser/sync/engine/syncer_thread.h"
-#include "chrome/browser/sync/engine/syncer_thread2.h"
-#include "chrome/browser/sync/engine/syncer_thread_adapter.h"
#include "chrome/browser/sync/engine/http_post_provider_factory.h"
#include "chrome/browser/sync/js_arg_list.h"
#include "chrome/browser/sync/js_backend.h"
@@ -57,6 +57,7 @@
#include "chrome/browser/sync/syncable/autofill_migration.h"
#include "chrome/browser/sync/syncable/directory_manager.h"
#include "chrome/browser/sync/syncable/model_type_payload_map.h"
+#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/syncable/nigori_util.h"
#include "chrome/browser/sync/syncable/syncable.h"
#include "chrome/browser/sync/util/crypto_helpers.h"
@@ -66,6 +67,7 @@
#include "content/browser/browser_thread.h"
#include "net/base/network_change_notifier.h"
+using base::TimeDelta;
using browser_sync::AllStatus;
using browser_sync::Cryptographer;
using browser_sync::KeyParams;
@@ -79,7 +81,6 @@ using browser_sync::SyncEngineEvent;
using browser_sync::SyncEngineEventListener;
using browser_sync::Syncer;
using browser_sync::SyncerThread;
-using browser_sync::SyncerThreadAdapter;
using browser_sync::kNigoriTag;
using browser_sync::sessions::SyncSessionContext;
using std::list;
@@ -89,6 +90,7 @@ using std::vector;
using syncable::Directory;
using syncable::DirectoryManager;
using syncable::Entry;
+using syncable::ModelTypeBitSet;
using syncable::SPECIFICS;
using sync_pb::AutofillProfileSpecifics;
@@ -1269,7 +1271,7 @@ class SyncManager::SyncInternal
SyncAPIServerConnectionManager* connection_manager() {
return connection_manager_.get();
}
- SyncerThreadAdapter* syncer_thread() { return syncer_thread_.get(); }
+ SyncerThread* syncer_thread() { return syncer_thread_.get(); }
UserShare* GetUserShare() { return &share_; }
// Return the currently active (validated) username for use with syncable
@@ -1516,7 +1518,7 @@ class SyncManager::SyncInternal
scoped_ptr<SyncAPIServerConnectionManager> connection_manager_;
// The thread that runs the Syncer. Needs to be explicitly Start()ed.
- scoped_ptr<SyncerThreadAdapter> syncer_thread_;
+ scoped_ptr<SyncerThread> syncer_thread_;
// The SyncNotifier which notifies us when updates need to be downloaded.
sync_notifier::SyncNotifier* sync_notifier_;
@@ -1664,44 +1666,30 @@ bool SyncManager::IsUsingExplicitPassphrase() {
return data_ && data_->IsUsingExplicitPassphrase();
}
-bool SyncManager::RequestPause() {
- if (data_->syncer_thread())
- return data_->syncer_thread()->RequestPause();
- return false;
-}
-
-bool SyncManager::RequestResume() {
- if (data_->syncer_thread())
- return data_->syncer_thread()->RequestResume();
- return false;
-}
-
void SyncManager::RequestNudge(const tracked_objects::Location& location) {
if (data_->syncer_thread())
- data_->syncer_thread()->NudgeSyncer(0, SyncerThread::kLocal, location);
+ data_->syncer_thread()->ScheduleNudge(
+ TimeDelta::FromMilliseconds(0), browser_sync::NUDGE_SOURCE_LOCAL,
+ ModelTypeBitSet(), location);
}
void SyncManager::RequestClearServerData() {
if (data_->syncer_thread())
- data_->syncer_thread()->NudgeSyncer(0, SyncerThread::kClearPrivateData,
- FROM_HERE);
+ data_->syncer_thread()->ScheduleClearUserData();
}
void SyncManager::RequestConfig(const syncable::ModelTypeBitSet& types) {
if (!data_->syncer_thread())
return;
- // It is an error for this to be called if new_impl is null.
StartConfigurationMode(NULL);
- data_->syncer_thread()->new_impl()->ScheduleConfig(types);
+ data_->syncer_thread()->ScheduleConfig(types);
}
void SyncManager::StartConfigurationMode(ModeChangeCallback* callback) {
if (!data_->syncer_thread())
return;
- if (!data_->syncer_thread()->new_impl())
- return;
- data_->syncer_thread()->new_impl()->Start(
- browser_sync::s3::SyncerThread::CONFIGURATION_MODE, callback);
+ data_->syncer_thread()->Start(
+ browser_sync::SyncerThread::CONFIGURATION_MODE, callback);
}
const std::string& SyncManager::GetAuthenticatedUsername() {
@@ -1739,16 +1727,7 @@ bool SyncManager::SyncInternal::Init(
net::NetworkChangeNotifier::AddIPAddressObserver(this);
- bool new_syncer_thread = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kNewSyncerThread);
-
- if (new_syncer_thread) {
- connection_manager()->AddListener(this);
- } else {
- connection_manager_hookup_.reset(
- NewEventListenerHookup(connection_manager()->channel(), this,
- &SyncManager::SyncInternal::HandleServerConnectionEvent));
- }
+ connection_manager()->AddListener(this);
// TODO(akalin): CheckServerReachable() can block, which may cause jank if we
// try to shut down sync. Fix this.
@@ -1769,8 +1748,7 @@ bool SyncManager::SyncInternal::Init(
listeners);
context->set_account_name(credentials.email);
// The SyncerThread takes ownership of |context|.
- syncer_thread_.reset(new SyncerThreadAdapter(context,
- new_syncer_thread));
+ syncer_thread_.reset(new SyncerThread(context, new Syncer()));
}
bool signed_in = SignIn(credentials);
@@ -1825,11 +1803,12 @@ void SyncManager::SyncInternal::BootstrapEncryption(
}
void SyncManager::SyncInternal::StartSyncing() {
+ // Start the syncer thread. This won't actually
+ // result in any syncing until at least the
+ // DirectoryManager broadcasts the OPENED event,
+ // and a valid server connection is detected.
if (syncer_thread()) // NULL during certain unittests.
- syncer_thread()->Start(); // Start the syncer thread. This won't actually
- // result in any syncing until at least the
- // DirectoryManager broadcasts the OPENED event,
- // and a valid server connection is detected.
+ syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
}
void SyncManager::SyncInternal::MarkAndNotifyInitializationComplete() {
@@ -1882,9 +1861,6 @@ bool SyncManager::SyncInternal::OpenDirectory() {
connection_manager()->set_client_id(lookup->cache_guid());
- if (syncer_thread())
- syncer_thread()->CreateSyncer(username_for_share());
-
MarkAndNotifyInitializationComplete();
dir_change_hookup_.reset(lookup->AddChangeObserver(this));
return true;
@@ -2210,9 +2186,7 @@ void SyncManager::SyncInternal::Shutdown() {
method_factory_.RevokeAll();
if (syncer_thread()) {
- if (!syncer_thread()->Stop(kThreadExitTimeoutMsec)) {
- LOG(FATAL) << "Unable to stop the syncer, it won't be happy...";
- }
+ syncer_thread()->Stop();
syncer_thread_.reset();
}
@@ -2417,9 +2391,9 @@ void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncApi(
if (exists_unsynced_items && syncer_thread()) {
int nudge_delay = only_preference_changes ?
kPreferencesNudgeDelayMilliseconds : kDefaultNudgeDelayMilliseconds;
- syncer_thread()->NudgeSyncerWithDataTypes(
- nudge_delay,
- SyncerThread::kLocal,
+ syncer_thread()->ScheduleNudge(
+ TimeDelta::FromMilliseconds(nudge_delay),
+ browser_sync::NUDGE_SOURCE_LOCAL,
model_types,
FROM_HERE);
}
@@ -2575,18 +2549,6 @@ void SyncManager::SyncInternal::OnSyncEngineEvent(
}
}
- if (event.what_happened == SyncEngineEvent::SYNCER_THREAD_PAUSED) {
- FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
- OnPaused());
- return;
- }
-
- if (event.what_happened == SyncEngineEvent::SYNCER_THREAD_RESUMED) {
- FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
- OnResumed());
- return;
- }
-
if (event.what_happened == SyncEngineEvent::STOP_SYNCING_PERMANENTLY) {
FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
OnStopSyncingPermanently());
@@ -2743,7 +2705,7 @@ void SyncManager::SyncInternal::OnNotificationStateChange(
<< (notifications_enabled ? "true" : "false");
allstatus_.SetNotificationsEnabled(notifications_enabled);
if (syncer_thread()) {
- syncer_thread()->SetNotificationsEnabled(notifications_enabled);
+ syncer_thread()->set_notifications_enabled(notifications_enabled);
}
if (parent_router_) {
ListValue args;
@@ -2768,9 +2730,9 @@ void SyncManager::SyncInternal::OnIncomingNotification(
const syncable::ModelTypePayloadMap& type_payloads) {
if (!type_payloads.empty()) {
if (syncer_thread()) {
- syncer_thread()->NudgeSyncerWithPayloads(
- kSyncerThreadDelayMsec,
- SyncerThread::kNotification,
+ syncer_thread()->ScheduleNudgeWithPayloads(
+ TimeDelta::FromMilliseconds(kSyncerThreadDelayMsec),
+ browser_sync::NUDGE_SOURCE_NOTIFICATION,
type_payloads, FROM_HERE);
}
allstatus_.IncrementNotificationsReceived();
diff --git a/chrome/browser/sync/engine/syncapi.h b/chrome/browser/sync/engine/syncapi.h
index 1718c71..1011a29 100644
--- a/chrome/browser/sync/engine/syncapi.h
+++ b/chrome/browser/sync/engine/syncapi.h
@@ -808,12 +808,6 @@ class SyncManager {
// message, unless otherwise specified, produces undefined behavior.
virtual void OnInitializationComplete() = 0;
- // The syncer thread has been paused.
- virtual void OnPaused() = 0;
-
- // The syncer thread has been resumed.
- virtual void OnResumed() = 0;
-
// We are no longer permitted to communicate with the server. Sync should
// be disabled and state cleaned up at once. This can happen for a number
// of reasons, e.g. swapping from a test instance to production, or a
@@ -917,20 +911,6 @@ class SyncManager {
// types, as we do not currently support decrypting datatypes.
void EncryptDataTypes(const syncable::ModelTypeSet& encrypted_types);
- // Requests the syncer thread to pause. The observer's OnPause
- // method will be called when the syncer thread is paused. Returns
- // false if the syncer thread can not be paused (e.g. if it is not
- // started).
- // TODO(tim): Deprecated.
- bool RequestPause();
-
- // Requests the syncer thread to resume. The observer's OnResume
- // method will be called when the syncer thread is resumed. Returns
- // false if the syncer thread can not be resumed (e.g. if it is not
- // paused).
- // TODO(tim): Deprecated.
- bool RequestResume();
-
// Puts the SyncerThread into a mode where no normal nudge or poll traffic
// will occur, but calls to RequestConfig will be supported. If |callback|
// is provided, it will be invoked (from the internal SyncerThread) when
diff --git a/chrome/browser/sync/engine/syncapi_unittest.cc b/chrome/browser/sync/engine/syncapi_unittest.cc
index 10d53a3..6c68735 100644
--- a/chrome/browser/sync/engine/syncapi_unittest.cc
+++ b/chrome/browser/sync/engine/syncapi_unittest.cc
@@ -617,8 +617,6 @@ class SyncManagerObserverMock : public SyncManager::Observer {
MOCK_METHOD1(OnPassphraseRequired, void(bool)); // NOLINT
MOCK_METHOD0(OnPassphraseFailed, void()); // NOLINT
MOCK_METHOD1(OnPassphraseAccepted, void(const std::string&)); // NOLINT
- MOCK_METHOD0(OnPaused, void()); // NOLINT
- MOCK_METHOD0(OnResumed, void()); // NOLINT
MOCK_METHOD0(OnStopSyncingPermanently, void()); // NOLINT
MOCK_METHOD1(OnUpdatedToken, void(const std::string&)); // NOLINT
MOCK_METHOD0(OnClearServerDataFailed, void()); // NOLINT
diff --git a/chrome/browser/sync/engine/syncer_end_command.cc b/chrome/browser/sync/engine/syncer_end_command.cc
index 8f67841..516bbd0 100644
--- a/chrome/browser/sync/engine/syncer_end_command.cc
+++ b/chrome/browser/sync/engine/syncer_end_command.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
@@ -21,7 +21,7 @@ void SyncerEndCommand::ExecuteImpl(sessions::SyncSession* session) {
sessions::SyncSessionSnapshot snapshot(session->TakeSnapshot());
event.snapshot = &snapshot;
session->context()->NotifyListeners(event);
- session->context()->set_last_snapshot(session->TakeSnapshot());
+ VLOG(1) << this << " sent sync end snapshot";
}
} // namespace browser_sync
diff --git a/chrome/browser/sync/engine/syncer_thread.cc b/chrome/browser/sync/engine/syncer_thread.cc
index 5851c45..5bf0d4d 100644
--- a/chrome/browser/sync/engine/syncer_thread.cc
+++ b/chrome/browser/sync/engine/syncer_thread.cc
@@ -5,27 +5,10 @@
#include "chrome/browser/sync/engine/syncer_thread.h"
#include <algorithm>
-#include <queue>
-#include <string>
-#include <vector>
#include "base/rand_util.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "build/build_config.h"
-#include "chrome/browser/sync/engine/model_safe_worker.h"
-#include "chrome/browser/sync/engine/net/server_connection_manager.h"
#include "chrome/browser/sync/engine/syncer.h"
-#include "chrome/browser/sync/sessions/sync_session.h"
-#if defined(OS_MACOSX)
-#include <CoreFoundation/CFNumber.h>
-#include <IOKit/IOTypes.h>
-#include <IOKit/IOKitLib.h>
-#endif
-
-using std::priority_queue;
-using std::min;
-using base::Time;
using base::TimeDelta;
using base::TimeTicks;
@@ -35,861 +18,843 @@ using sessions::SyncSession;
using sessions::SyncSessionSnapshot;
using sessions::SyncSourceInfo;
using syncable::ModelTypePayloadMap;
+using syncable::ModelTypeBitSet;
+using sync_pb::GetUpdatesCallerInfo;
-// We use high values here to ensure that failure to receive poll updates from
-// the server doesn't result in rapid-fire polling from the client due to low
-// local limits.
-const int SyncerThread::kDefaultShortPollIntervalSeconds = 3600 * 8;
-const int SyncerThread::kDefaultLongPollIntervalSeconds = 3600 * 12;
-
-// TODO(tim): This is used to regulate the short poll (when notifications are
-// disabled) based on user idle time. If it is set to a smaller value than
-// the short poll interval, it basically does nothing; for now, this is what
-// we want and allows stronger control over the poll rate from the server. We
-// should probably re-visit this code later and figure out if user idle time
-// is really something we want and make sure it works, if it is.
-const int SyncerThread::kDefaultMaxPollIntervalMs = 30 * 60 * 1000;
-
-// Backoff interval randomization factor.
-static const int kBackoffRandomizationFactor = 2;
-
-const int SyncerThread::kMaxBackoffSeconds = 60 * 60 * 4; // 4 hours.
-
-SyncerThread::ProtectedFields::ProtectedFields()
- : stop_syncer_thread_(false),
- pause_requested_(false),
- paused_(false),
- syncer_(NULL),
- connected_(false),
- pending_nudge_source_(kUnknown) {}
-
-SyncerThread::ProtectedFields::~ProtectedFields() {}
-
-void SyncerThread::NudgeSyncerWithPayloads(
- int milliseconds_from_now,
- NudgeSource source,
- const ModelTypePayloadMap& model_types_with_payloads) {
- base::AutoLock lock(lock_);
- if (vault_.syncer_ == NULL) {
- return;
- }
+SyncerThread::DelayProvider::DelayProvider() {}
+SyncerThread::DelayProvider::~DelayProvider() {}
- NudgeSyncImpl(milliseconds_from_now, source, model_types_with_payloads);
-}
+SyncerThread::WaitInterval::WaitInterval() {}
+SyncerThread::WaitInterval::~WaitInterval() {}
-void SyncerThread::NudgeSyncerWithDataTypes(
- int milliseconds_from_now,
- NudgeSource source,
- const syncable::ModelTypeBitSet& model_types) {
- base::AutoLock lock(lock_);
- if (vault_.syncer_ == NULL) {
- return;
- }
+SyncerThread::SyncSessionJob::SyncSessionJob() {}
+SyncerThread::SyncSessionJob::~SyncSessionJob() {}
- ModelTypePayloadMap model_types_with_payloads =
- syncable::ModelTypePayloadMapFromBitSet(model_types, std::string());
- NudgeSyncImpl(milliseconds_from_now, source, model_types_with_payloads);
+SyncerThread::SyncSessionJob::SyncSessionJob(SyncSessionJobPurpose purpose,
+ base::TimeTicks start,
+ linked_ptr<sessions::SyncSession> session, bool is_canary_job,
+ const tracked_objects::Location& nudge_location) : purpose(purpose),
+ scheduled_start(start),
+ session(session),
+ is_canary_job(is_canary_job),
+ nudge_location(nudge_location) {
}
-void SyncerThread::NudgeSyncer(
- int milliseconds_from_now,
+TimeDelta SyncerThread::DelayProvider::GetDelay(
+ const base::TimeDelta& last_delay) {
+ return SyncerThread::GetRecommendedDelay(last_delay);
+}
+
+GetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource(
NudgeSource source) {
- base::AutoLock lock(lock_);
- if (vault_.syncer_ == NULL) {
- return;
+ switch (source) {
+ case NUDGE_SOURCE_NOTIFICATION:
+ return GetUpdatesCallerInfo::NOTIFICATION;
+ case NUDGE_SOURCE_LOCAL:
+ return GetUpdatesCallerInfo::LOCAL;
+ case NUDGE_SOURCE_CONTINUATION:
+ return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION;
+ case NUDGE_SOURCE_UNKNOWN:
+ return GetUpdatesCallerInfo::UNKNOWN;
+ default:
+ NOTREACHED();
+ return GetUpdatesCallerInfo::UNKNOWN;
}
-
- // Set all enabled datatypes.
- ModelSafeRoutingInfo routes;
- session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
- ModelTypePayloadMap model_types_with_payloads =
- syncable::ModelTypePayloadMapFromRoutingInfo(routes, std::string());
- NudgeSyncImpl(milliseconds_from_now, source, model_types_with_payloads);
}
-SyncerThread::SyncerThread(sessions::SyncSessionContext* context)
- : thread_main_started_(false, false),
- thread_("SyncEngine_SyncerThread"),
- vault_field_changed_(&lock_),
- conn_mgr_hookup_(NULL),
- syncer_short_poll_interval_seconds_(kDefaultShortPollIntervalSeconds),
- syncer_long_poll_interval_seconds_(kDefaultLongPollIntervalSeconds),
- syncer_polling_interval_(kDefaultShortPollIntervalSeconds),
- syncer_max_interval_(kDefaultMaxPollIntervalMs),
- session_context_(context),
- disable_idle_detection_(false) {
- DCHECK(context);
+SyncerThread::WaitInterval::WaitInterval(Mode mode, TimeDelta length)
+ : mode(mode), had_nudge(false), length(length) { }
- if (context->connection_manager())
- WatchConnectionManager(context->connection_manager());
+SyncerThread::SyncerThread(sessions::SyncSessionContext* context,
+ Syncer* syncer)
+ : thread_("SyncEngine_SyncerThread"),
+ syncer_short_poll_interval_seconds_(
+ TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)),
+ syncer_long_poll_interval_seconds_(
+ TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)),
+ mode_(NORMAL_MODE),
+ server_connection_ok_(false),
+ delay_provider_(new DelayProvider()),
+ syncer_(syncer),
+ session_context_(context) {
}
SyncerThread::~SyncerThread() {
- conn_mgr_hookup_.reset();
- delete vault_.syncer_;
- CHECK(!thread_.IsRunning());
-}
-
-// Creates and starts a syncer thread.
-// Returns true if it creates a thread or if there's currently a thread running
-// and false otherwise.
-bool SyncerThread::Start() {
- {
- base::AutoLock lock(lock_);
- if (thread_.IsRunning()) {
- return true;
- }
+ DCHECK(!thread_.IsRunning());
+}
+
+void SyncerThread::CheckServerConnectionManagerStatus(
+ HttpResponse::ServerConnectionCode code) {
+
+ VLOG(1) << "SyncerThread(" << this << ")" << " Server connection changed."
+ << "Old mode: " << server_connection_ok_ << " Code: " << code;
+ // Note, be careful when adding cases here because if the SyncerThread
+ // thinks there is no valid connection as determined by this method, it
+ // will drop out of *all* forward progress sync loops (it won't poll and it
+ // will queue up Talk notifications but not actually call SyncShare) until
+ // some external action causes a ServerConnectionManager to broadcast that
+ // a valid connection has been re-established.
+ if (HttpResponse::CONNECTION_UNAVAILABLE == code ||
+ HttpResponse::SYNC_AUTH_ERROR == code) {
+ server_connection_ok_ = false;
+ VLOG(1) << "SyncerThread(" << this << ")" << " Server connection changed."
+ << " new mode:" << server_connection_ok_;
+ } else if (HttpResponse::SERVER_CONNECTION_OK == code) {
+ server_connection_ok_ = true;
+ VLOG(1) << "SyncerThread(" << this << ")" << " Server connection changed."
+ << " new mode:" << server_connection_ok_;
+ DoCanaryJob();
+ }
+}
+void SyncerThread::Start(Mode mode, ModeChangeCallback* callback) {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Start called from thread "
+ << MessageLoop::current()->thread_name();
+ if (!thread_.IsRunning()) {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Starting thread with mode "
+ << mode;
if (!thread_.Start()) {
- return false;
+ NOTREACHED() << "Unable to start SyncerThread.";
+ return;
}
+ WatchConnectionManager();
+ thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &SyncerThread::SendInitialSnapshot));
}
- thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this,
- &SyncerThread::ThreadMain));
+ VLOG(1) << "SyncerThread(" << this << ")" << " Entering start with mode = "
+ << mode;
- // Wait for notification that our task makes it safely onto the message
- // loop before returning, so the caller can't call Stop before we're
- // actually up and running. This is for consistency with the old pthread
- // impl because pthread_create would do this in one step.
- thread_main_started_.Wait();
- VLOG(1) << "SyncerThread started.";
- return true;
+ thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &SyncerThread::StartImpl, mode, make_linked_ptr(callback)));
}
-// Stop processing. A max wait of at least 2*server RTT time is recommended.
-// Returns true if we stopped, false otherwise.
-bool SyncerThread::Stop(int max_wait) {
- RequestSyncerExitAndSetThreadStopConditions();
-
- // This will join, and finish when ThreadMain terminates.
- thread_.Stop();
- return true;
+void SyncerThread::SendInitialSnapshot() {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ scoped_ptr<SyncSession> dummy(new SyncSession(session_context_.get(), this,
+ SyncSourceInfo(), ModelSafeRoutingInfo(),
+ std::vector<ModelSafeWorker*>()));
+ SyncEngineEvent event(SyncEngineEvent::STATUS_CHANGED);
+ sessions::SyncSessionSnapshot snapshot(dummy->TakeSnapshot());
+ event.snapshot = &snapshot;
+ session_context_->NotifyListeners(event);
}
-void SyncerThread::RequestSyncerExitAndSetThreadStopConditions() {
- {
- base::AutoLock lock(lock_);
- // If the thread has been started, then we either already have or are about
- // to enter ThreadMainLoop so we have to proceed with shutdown and wait for
- // it to finish. If the thread has not been started --and we now own the
- // lock-- then we can early out because the caller has not called Start().
- if (!thread_.IsRunning())
- return;
+void SyncerThread::WatchConnectionManager() {
+ ServerConnectionManager* scm = session_context_->connection_manager();
+ CheckServerConnectionManagerStatus(scm->server_status());
+ scm->AddListener(this);
+}
- VLOG(1) << "SyncerThread::Stop - setting ThreadMain exit condition to true "
- "(vault_.stop_syncer_thread_)";
- // Exit the ThreadMainLoop once the syncer finishes (we tell it to exit
- // below).
- vault_.stop_syncer_thread_ = true;
- if (NULL != vault_.syncer_) {
- // Try to early exit the syncer itself, which could be looping inside
- // SyncShare.
- vault_.syncer_->RequestEarlyExit();
- }
+void SyncerThread::StartImpl(Mode mode,
+ linked_ptr<ModeChangeCallback> callback) {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Doing StartImpl with mode "
+ << mode;
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ DCHECK(!session_context_->account_name().empty());
+ DCHECK(syncer_.get());
+ mode_ = mode;
+ AdjustPolling(NULL); // Will kick start poll timer if needed.
+ if (callback.get())
+ callback->Run();
- // stop_syncer_thread_ is now true and the Syncer has been told to exit.
- // We want to wake up all waiters so they can re-examine state. We signal,
- // causing all waiters to try to re-acquire the lock, and then we release
- // the lock, and join on our internal thread which should soon run off the
- // end of ThreadMain.
- vault_field_changed_.Broadcast();
- }
+ // We just changed our mode. See if there are any pending jobs that we could
+ // execute in the new mode.
+ DoPendingJobIfPossible(false);
}
-bool SyncerThread::RequestPause() {
- base::AutoLock lock(lock_);
- if (vault_.pause_requested_ || vault_.paused_)
- return false;
+SyncerThread::JobProcessDecision SyncerThread::DecideWhileInWaitInterval(
+ const SyncSessionJob& job) {
- if (thread_.IsRunning()) {
- // Set the pause request. The syncer thread will read this
- // request, enter the paused state, and send the PAUSED
- // notification.
- vault_.pause_requested_ = true;
- vault_field_changed_.Broadcast();
- VLOG(1) << "Pause requested.";
- } else {
- // If the thread is not running, go directly into the paused state
- // and notify.
- EnterPausedState();
- VLOG(1) << "Paused while not running.";
- }
- return true;
-}
+ DCHECK(wait_interval_.get());
+ DCHECK_NE(job.purpose, SyncSessionJob::CLEAR_USER_DATA);
-void SyncerThread::Notify(SyncEngineEvent::EventCause cause) {
- session_context_->NotifyListeners(SyncEngineEvent(cause));
-}
+ VLOG(1) << "SyncerThread(" << this << ")" << " Wait interval mode : "
+ << wait_interval_->mode << "Wait interval had nudge : "
+ << wait_interval_->had_nudge << "is canary job : "
+ << job.is_canary_job;
-bool SyncerThread::RequestResume() {
- base::AutoLock lock(lock_);
- // Only valid to request a resume when we are already paused or we
- // have a pause pending.
- if (!(vault_.paused_ || vault_.pause_requested_))
- return false;
-
- if (thread_.IsRunning()) {
- if (vault_.pause_requested_) {
- // If pause was requested we have not yet paused. In this case,
- // the resume cancels the pause request.
- vault_.pause_requested_ = false;
- vault_field_changed_.Broadcast();
- Notify(SyncEngineEvent::SYNCER_THREAD_RESUMED);
- VLOG(1) << "Pending pause canceled by resume.";
- } else {
- // Unpause and notify.
- vault_.paused_ = false;
- vault_field_changed_.Broadcast();
- }
- } else {
- ExitPausedState();
- VLOG(1) << "Resumed while not running.";
- }
- return true;
-}
+ if (job.purpose == SyncSessionJob::POLL)
+ return DROP;
-void SyncerThread::OnReceivedLongPollIntervalUpdate(
- const base::TimeDelta& new_interval) {
- syncer_long_poll_interval_seconds_ = static_cast<int>(
- new_interval.InSeconds());
-}
+ DCHECK(job.purpose == SyncSessionJob::NUDGE ||
+ job.purpose == SyncSessionJob::CONFIGURATION);
+ if (wait_interval_->mode == WaitInterval::THROTTLED)
+ return SAVE;
-void SyncerThread::OnReceivedShortPollIntervalUpdate(
- const base::TimeDelta& new_interval) {
- syncer_short_poll_interval_seconds_ = static_cast<int>(
- new_interval.InSeconds());
-}
+ DCHECK_EQ(wait_interval_->mode, WaitInterval::EXPONENTIAL_BACKOFF);
+ if (job.purpose == SyncSessionJob::NUDGE) {
+ if (mode_ == CONFIGURATION_MODE)
+ return SAVE;
-void SyncerThread::OnSilencedUntil(const base::TimeTicks& silenced_until) {
- silenced_until_ = silenced_until;
+ // If we already had one nudge then just drop this nudge. We will retry
+ // later when the timer runs out.
+ return wait_interval_->had_nudge ? DROP : CONTINUE;
+ }
+ // This is a config job.
+ return job.is_canary_job ? CONTINUE : SAVE;
}
-bool SyncerThread::IsSyncingCurrentlySilenced() {
- // We should ignore reads from silenced_until_ under ThreadSanitizer
- // since this is a benign race.
- ANNOTATE_IGNORE_READS_BEGIN();
- bool ret = (silenced_until_ - TimeTicks::Now()) >= TimeDelta::FromSeconds(0);
- ANNOTATE_IGNORE_READS_END();
- return ret;
-}
+SyncerThread::JobProcessDecision SyncerThread::DecideOnJob(
+ const SyncSessionJob& job) {
+ if (job.purpose == SyncSessionJob::CLEAR_USER_DATA)
+ return CONTINUE;
-void SyncerThread::OnShouldStopSyncingPermanently() {
- RequestSyncerExitAndSetThreadStopConditions();
- Notify(SyncEngineEvent::STOP_SYNCING_PERMANENTLY);
-}
+ if (wait_interval_.get())
+ return DecideWhileInWaitInterval(job);
-void SyncerThread::ThreadMainLoop() {
- // This is called with lock_ acquired.
- lock_.AssertAcquired();
- VLOG(1) << "In thread main loop.";
-
- // Use the short poll value by default.
- vault_.current_wait_interval_.poll_delta =
- TimeDelta::FromSeconds(syncer_short_poll_interval_seconds_);
- int user_idle_milliseconds = 0;
- TimeTicks last_sync_time;
- bool initial_sync_for_thread = true;
- bool continue_sync_cycle = false;
-
-#if defined(OS_LINUX)
- idle_query_.reset(new IdleQueryLinux());
-#endif
-
- if (vault_.syncer_ == NULL) {
- VLOG(1) << "Syncer thread waiting for database initialization.";
- while (vault_.syncer_ == NULL && !vault_.stop_syncer_thread_)
- vault_field_changed_.Wait();
- VLOG_IF(1, !(vault_.syncer_ == NULL)) << "Syncer was found after DB "
- "started.";
+ if (mode_ == CONFIGURATION_MODE) {
+ if (job.purpose == SyncSessionJob::NUDGE)
+ return SAVE;
+ else if (job.purpose == SyncSessionJob::CONFIGURATION)
+ return CONTINUE;
+ else
+ return DROP;
}
- while (!vault_.stop_syncer_thread_) {
- // The Wait()s in these conditionals using |vault_| are not TimedWait()s (as
- // below) because we cannot poll until these conditions are met, so we wait
- // indefinitely.
-
- // If we are not connected, enter WaitUntilConnectedOrQuit() which
- // will return only when the network is connected or a quit is
- // requested. Note that it is possible to exit
- // WaitUntilConnectedOrQuit() in the paused state which will be
- // handled by the next statement.
- if (!vault_.connected_ && !initial_sync_for_thread) {
- WaitUntilConnectedOrQuit();
- continue;
- }
+ // We are in normal mode.
+ DCHECK_EQ(mode_, NORMAL_MODE);
+ DCHECK_NE(job.purpose, SyncSessionJob::CONFIGURATION);
- // Check if we should be paused or if a pause was requested. Note
- // that we don't check initial_sync_for_thread here since we want
- // the pause to happen regardless if it is the initial sync or not.
- if (vault_.pause_requested_ || vault_.paused_) {
- PauseUntilResumedOrQuit();
- continue;
- }
+ // Freshness condition
+ if (job.scheduled_start < last_sync_session_end_time_) {
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " Dropping job because of freshness";
+ return DROP;
+ }
- const TimeTicks next_poll = last_sync_time +
- vault_.current_wait_interval_.poll_delta;
- bool throttled = vault_.current_wait_interval_.mode ==
- WaitInterval::THROTTLED;
- // If we are throttled, we must wait. Otherwise, wait until either the next
- // nudge (if one exists) or the poll interval.
- TimeTicks end_wait = next_poll;
- if (!throttled && !vault_.pending_nudge_time_.is_null()) {
- end_wait = std::min(end_wait, vault_.pending_nudge_time_);
- }
- VLOG(1) << "end_wait is " << end_wait.ToInternalValue()
- << "\nnext_poll is " << next_poll.ToInternalValue();
-
- // We block until the CV is signaled (e.g a control field changed, loss of
- // network connection, nudge, spurious, etc), or the poll interval elapses.
- TimeDelta sleep_time = end_wait - TimeTicks::Now();
- if (!initial_sync_for_thread && sleep_time > TimeDelta::FromSeconds(0)) {
- vault_field_changed_.TimedWait(sleep_time);
-
- if (TimeTicks::Now() < end_wait) {
- // Didn't timeout. Could be a spurious signal, or a signal corresponding
- // to an actual change in one of our control fields. By continuing here
- // we perform the typical "always recheck conditions when signaled",
- // (typically handled by a while(condition_not_met) cv.wait() construct)
- // because we jump to the top of the loop. The main difference is we
- // recalculate the wait interval, but last_sync_time won't have changed.
- // So if we were signaled by a nudge (for ex.) we'll grab the new nudge
- // off the queue and wait for that delta. If it was a spurious signal,
- // we'll keep waiting for the same moment in time as we just were.
- continue;
- }
- }
+ if (server_connection_ok_)
+ return CONTINUE;
- // Handle a nudge, caused by either a notification or a local bookmark
- // event. This will also update the source of the following SyncMain call.
- VLOG(1) << "Calling Sync Main at time " << Time::Now().ToInternalValue();
- bool nudged = false;
- scoped_ptr<SyncSession> session;
- session.reset(SyncMain(vault_.syncer_,
- throttled, continue_sync_cycle, &initial_sync_for_thread, &nudged));
-
- // Update timing information for how often these datatypes are triggering
- // nudges.
- base::TimeTicks now = TimeTicks::Now();
- if (!last_sync_time.is_null()) {
- ModelTypePayloadMap::const_iterator iter;
- for (iter = session->source().types.begin();
- iter != session->source().types.end();
- ++iter) {
- syncable::PostTimeToTypeHistogram(iter->first,
- now - last_sync_time);
- }
- }
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " Bad server connection. Using that to decide on job.";
+ return job.purpose == SyncSessionJob::NUDGE ? SAVE : DROP;
+}
+
+void SyncerThread::InitOrCoalescePendingJob(const SyncSessionJob& job) {
+ DCHECK(job.purpose != SyncSessionJob::CONFIGURATION);
+ if (pending_nudge_.get() == NULL) {
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " Creating a pending nudge job";
+ SyncSession* s = job.session.get();
+ scoped_ptr<SyncSession> session(new SyncSession(s->context(),
+ s->delegate(), s->source(), s->routing_info(), s->workers()));
- last_sync_time = now;
+ SyncSessionJob new_job(SyncSessionJob::NUDGE, job.scheduled_start,
+ make_linked_ptr(session.release()), false, job.nudge_location);
+ pending_nudge_.reset(new SyncSessionJob(new_job));
- VLOG(1) << "Updating the next polling time after SyncMain";
- vault_.current_wait_interval_ = CalculatePollingWaitTime(
- static_cast<int>(vault_.current_wait_interval_.poll_delta.InSeconds()),
- &user_idle_milliseconds, &continue_sync_cycle, nudged);
+ return;
}
-#if defined(OS_LINUX)
- idle_query_.reset();
-#endif
-}
-void SyncerThread::SetConnected(bool connected) {
- DCHECK(!thread_.IsRunning());
- vault_.connected_ = connected;
-}
+ VLOG(1) << "SyncerThread(" << this << ")" << " Coalescing a pending nudge";
+ pending_nudge_->session->Coalesce(*(job.session.get()));
+ pending_nudge_->scheduled_start = job.scheduled_start;
-void SyncerThread::SetSyncerPollingInterval(base::TimeDelta interval) {
- // TODO(timsteele): Use TimeDelta internally.
- syncer_polling_interval_ = static_cast<int>(interval.InSeconds());
+ // Unfortunately the nudge location cannot be modified. So it stores the
+ // location of the first caller.
}
-void SyncerThread::SetSyncerShortPollInterval(base::TimeDelta interval) {
- // TODO(timsteele): Use TimeDelta internally.
- syncer_short_poll_interval_seconds_ =
- static_cast<int>(interval.InSeconds());
-}
+bool SyncerThread::ShouldRunJob(const SyncSessionJob& job) {
+ JobProcessDecision decision = DecideOnJob(job);
+ VLOG(1) << "SyncerThread(" << this << ")" << " Should run job, decision: "
+ << decision << " Job purpose " << job.purpose << "mode " << mode_;
+ if (decision != SAVE)
+ return decision == CONTINUE;
-void SyncerThread::WaitUntilConnectedOrQuit() {
- VLOG(1) << "Syncer thread waiting for connection.";
- Notify(SyncEngineEvent::SYNCER_THREAD_WAITING_FOR_CONNECTION);
+ DCHECK(job.purpose == SyncSessionJob::NUDGE || job.purpose ==
+ SyncSessionJob::CONFIGURATION);
- bool is_paused = vault_.paused_;
+ SaveJob(job);
+ return false;
+}
- while (!vault_.connected_ && !vault_.stop_syncer_thread_) {
- if (!is_paused && vault_.pause_requested_) {
- // If we get a pause request while waiting for a connection,
- // enter the paused state.
- EnterPausedState();
- is_paused = true;
- VLOG(1) << "Syncer thread entering disconnected pause.";
- }
+void SyncerThread::SaveJob(const SyncSessionJob& job) {
+ DCHECK(job.purpose != SyncSessionJob::CLEAR_USER_DATA);
+ if (job.purpose == SyncSessionJob::NUDGE) {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Saving a nudge job";
+ InitOrCoalescePendingJob(job);
+ } else if (job.purpose == SyncSessionJob::CONFIGURATION){
+ VLOG(1) << "SyncerThread(" << this << ")" << " Saving a configuration job";
+ DCHECK(wait_interval_.get());
+ DCHECK(mode_ == CONFIGURATION_MODE);
- if (is_paused && !vault_.paused_) {
- ExitPausedState();
- is_paused = false;
- VLOG(1) << "Syncer thread exiting disconnected pause.";
- }
+ SyncSession* old = job.session.get();
+ SyncSession* s(new SyncSession(session_context_.get(), this,
+ old->source(), old->routing_info(), old->workers()));
+ SyncSessionJob new_job(job.purpose, TimeTicks::Now(),
+ make_linked_ptr(s), false, job.nudge_location);
+ wait_interval_->pending_configure_job.reset(new SyncSessionJob(new_job));
+ } // drop the rest.
+}
- vault_field_changed_.Wait();
+// Functor for std::find_if to search by ModelSafeGroup.
+struct ModelSafeWorkerGroupIs {
+ explicit ModelSafeWorkerGroupIs(ModelSafeGroup group) : group(group) {}
+ bool operator()(ModelSafeWorker* w) {
+ return group == w->GetModelSafeGroup();
}
+ ModelSafeGroup group;
+};
- if (!vault_.stop_syncer_thread_) {
- Notify(SyncEngineEvent::SYNCER_THREAD_CONNECTED);
- VLOG(1) << "Syncer thread found connection.";
+void SyncerThread::ScheduleClearUserData() {
+ if (!thread_.IsRunning()) {
+ NOTREACHED();
+ return;
}
+ thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &SyncerThread::ScheduleClearUserDataImpl));
}
-void SyncerThread::PauseUntilResumedOrQuit() {
- VLOG(1) << "Syncer thread entering pause.";
- // If pause was requested (rather than already being paused), send
- // the PAUSED notification.
- if (vault_.pause_requested_)
- EnterPausedState();
-
- // Thread will get stuck here until either a resume is requested
- // or shutdown is started.
- while (vault_.paused_ && !vault_.stop_syncer_thread_)
- vault_field_changed_.Wait();
+void SyncerThread::ScheduleNudge(const TimeDelta& delay,
+ NudgeSource source, const ModelTypeBitSet& types,
+ const tracked_objects::Location& nudge_location) {
+ if (!thread_.IsRunning()) {
+ NOTREACHED();
+ return;
+ }
- // Notify that we have resumed if we are not shutting down.
- if (!vault_.stop_syncer_thread_)
- ExitPausedState();
+ VLOG(1) << "SyncerThread(" << this << ")" << " Nudge scheduled";
- VLOG(1) << "Syncer thread exiting pause.";
+ ModelTypePayloadMap types_with_payloads =
+ syncable::ModelTypePayloadMapFromBitSet(types, std::string());
+ thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &SyncerThread::ScheduleNudgeImpl, delay,
+ GetUpdatesFromNudgeSource(source), types_with_payloads, false,
+ nudge_location));
}
-void SyncerThread::EnterPausedState() {
- lock_.AssertAcquired();
- vault_.pause_requested_ = false;
- vault_.paused_ = true;
- vault_field_changed_.Broadcast();
- Notify(SyncEngineEvent::SYNCER_THREAD_PAUSED);
-}
+void SyncerThread::ScheduleNudgeWithPayloads(const TimeDelta& delay,
+ NudgeSource source, const ModelTypePayloadMap& types_with_payloads,
+ const tracked_objects::Location& nudge_location) {
+ if (!thread_.IsRunning()) {
+ NOTREACHED();
+ return;
+ }
+
+ VLOG(1) << "SyncerThread(" << this << ")" << " Nudge scheduled with payloads";
-void SyncerThread::ExitPausedState() {
- lock_.AssertAcquired();
- vault_.paused_ = false;
- vault_field_changed_.Broadcast();
- Notify(SyncEngineEvent::SYNCER_THREAD_RESUMED);
+ thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &SyncerThread::ScheduleNudgeImpl, delay,
+ GetUpdatesFromNudgeSource(source), types_with_payloads, false,
+ nudge_location));
}
-void SyncerThread::DisableIdleDetection() {
- disable_idle_detection_ = true;
+void SyncerThread::ScheduleClearUserDataImpl() {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ SyncSession* session = new SyncSession(session_context_.get(), this,
+ SyncSourceInfo(), ModelSafeRoutingInfo(),
+ std::vector<ModelSafeWorker*>());
+ ScheduleSyncSessionJob(TimeDelta::FromSeconds(0),
+ SyncSessionJob::CLEAR_USER_DATA, session, FROM_HERE);
}
-// We check how long the user's been idle and sync less often if the machine is
-// not in use. The aim is to reduce server load.
-SyncerThread::WaitInterval SyncerThread::CalculatePollingWaitTime(
- int last_poll_wait, // Time in seconds.
- int* user_idle_milliseconds,
- bool* continue_sync_cycle,
- bool was_nudged) {
- lock_.AssertAcquired(); // We access 'vault' in here, so we need the lock.
- WaitInterval return_interval;
+void SyncerThread::ScheduleNudgeImpl(const TimeDelta& delay,
+ GetUpdatesCallerInfo::GetUpdatesSource source,
+ const ModelTypePayloadMap& types_with_payloads,
+ bool is_canary_job, const tracked_objects::Location& nudge_location) {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- // Server initiated throttling trumps everything.
- if (!silenced_until_.is_null()) {
- // We don't need to reset other state, it can continue where it left off.
- return_interval.mode = WaitInterval::THROTTLED;
- return_interval.poll_delta = silenced_until_ - TimeTicks::Now();
- return return_interval;
- }
+ VLOG(1) << "SyncerThread(" << this << ")" << " Running Schedule nudge impl";
+ // Note we currently nudge for all types regardless of the ones incurring
+ // the nudge. Doing different would throw off some syncer commands like
+ // CleanupDisabledTypes. We may want to change this in the future.
+ SyncSourceInfo info(source, types_with_payloads);
- bool is_continuing_sync_cyle = *continue_sync_cycle;
- *continue_sync_cycle = false;
+ SyncSession* session(CreateSyncSession(info));
+ SyncSessionJob job(SyncSessionJob::NUDGE, TimeTicks::Now() + delay,
+ make_linked_ptr(session), is_canary_job,
+ nudge_location);
- // Determine if the syncer has unfinished work to do.
- SyncSessionSnapshot* snapshot = session_context_->previous_session_snapshot();
- const bool syncer_has_work_to_do = snapshot &&
- (snapshot->num_server_changes_remaining > 0 ||
- snapshot->unsynced_count > 0);
- VLOG(1) << "syncer_has_work_to_do is " << syncer_has_work_to_do;
+ session = NULL;
+ if (!ShouldRunJob(job))
+ return;
- // First calculate the expected wait time, figuring in any backoff because of
- // user idle time. next_wait is in seconds
- syncer_polling_interval_ = (!session_context_->notifications_enabled()) ?
- syncer_short_poll_interval_seconds_ :
- syncer_long_poll_interval_seconds_;
- int default_next_wait = syncer_polling_interval_;
- return_interval.poll_delta = TimeDelta::FromSeconds(default_next_wait);
-
- if (syncer_has_work_to_do) {
- // Provide exponential backoff due to consecutive errors, else attempt to
- // complete the work as soon as possible.
- if (is_continuing_sync_cyle) {
- return_interval.mode = WaitInterval::EXPONENTIAL_BACKOFF;
- if (was_nudged && vault_.current_wait_interval_.mode ==
- WaitInterval::EXPONENTIAL_BACKOFF) {
- // We were nudged, it failed, and we were already in backoff.
- return_interval.had_nudge_during_backoff = true;
- // Keep exponent for exponential backoff the same in this case.
- return_interval.poll_delta = vault_.current_wait_interval_.poll_delta;
- } else {
- // We weren't nudged, or we were in a NORMAL wait interval until now.
- return_interval.poll_delta = TimeDelta::FromSeconds(
- GetRecommendedDelaySeconds(last_poll_wait));
- }
- } else {
- // No consecutive error.
- return_interval.poll_delta = TimeDelta::FromSeconds(
- GetRecommendedDelaySeconds(0));
+ if (pending_nudge_.get()) {
+ if (IsBackingOff() && delay > TimeDelta::FromSeconds(1)) {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Dropping the nudge because"
+ << "we are in backoff";
+ return;
}
- *continue_sync_cycle = true;
- } else if (!session_context_->notifications_enabled()) {
- // Ensure that we start exponential backoff from our base polling
- // interval when we are not continuing a sync cycle.
- last_poll_wait = std::max(last_poll_wait, syncer_polling_interval_);
-
- // Did the user start interacting with the computer again?
- // If so, revise our idle time (and probably next_sync_time) downwards
- int new_idle_time = disable_idle_detection_ ? 0 : UserIdleTime();
- if (new_idle_time < *user_idle_milliseconds) {
- *user_idle_milliseconds = new_idle_time;
+
+ VLOG(1) << "SyncerThread(" << this << ")" << " Coalescing pending nudge";
+ pending_nudge_->session->Coalesce(*(job.session.get()));
+
+ if (!IsBackingOff()) {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Dropping a nudge because"
+ << " we are not in backoff and the job was coalesced";
+ return;
+ } else {
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " Rescheduling pending nudge";
+ SyncSession* s = pending_nudge_->session.get();
+ job.session.reset(new SyncSession(s->context(), s->delegate(),
+ s->source(), s->routing_info(), s->workers()));
+ pending_nudge_.reset();
}
- return_interval.poll_delta = TimeDelta::FromMilliseconds(
- CalculateSyncWaitTime(last_poll_wait * 1000,
- *user_idle_milliseconds));
- DCHECK_GE(return_interval.poll_delta.InSeconds(), default_next_wait);
}
- VLOG(1) << "Sync wait: idle " << default_next_wait
- << " non-idle or backoff " << return_interval.poll_delta.InSeconds();
-
- return return_interval;
+ // TODO(lipalani) - pass the job itself to ScheduleSyncSessionJob.
+ ScheduleSyncSessionJob(delay, SyncSessionJob::NUDGE, job.session.release(),
+ nudge_location);
}
-void SyncerThread::ThreadMain() {
- base::AutoLock lock(lock_);
- // Signal Start() to let it know we've made it safely onto the message loop,
- // and unblock it's caller.
- thread_main_started_.Signal();
- ThreadMainLoop();
- VLOG(1) << "Syncer thread ThreadMain is done.";
- Notify(SyncEngineEvent::SYNCER_THREAD_EXITING);
-}
+// Helper to extract the routing info and workers corresponding to types in
+// |types| from |registrar|.
+void GetModelSafeParamsForTypes(const ModelTypeBitSet& types,
+ ModelSafeWorkerRegistrar* registrar, ModelSafeRoutingInfo* routes,
+ std::vector<ModelSafeWorker*>* workers) {
+ ModelSafeRoutingInfo r_tmp;
+ std::vector<ModelSafeWorker*> w_tmp;
+ registrar->GetModelSafeRoutingInfo(&r_tmp);
+ registrar->GetWorkers(&w_tmp);
-SyncSession* SyncerThread::SyncMain(Syncer* syncer, bool was_throttled,
- bool continue_sync_cycle, bool* initial_sync_for_thread,
- bool* was_nudged) {
- CHECK(syncer);
+ typedef std::vector<ModelSafeWorker*>::const_iterator iter;
+ for (size_t i = syncable::FIRST_REAL_MODEL_TYPE; i < types.size(); ++i) {
+ if (!types.test(i))
+ continue;
+ syncable::ModelType t = syncable::ModelTypeFromInt(i);
+ DCHECK_EQ(1U, r_tmp.count(t));
+ (*routes)[t] = r_tmp[t];
+ iter it = std::find_if(w_tmp.begin(), w_tmp.end(),
+ ModelSafeWorkerGroupIs(r_tmp[t]));
+ if (it != w_tmp.end())
+ workers->push_back(*it);
+ else
+ NOTREACHED();
+ }
+
+ iter it = std::find_if(w_tmp.begin(), w_tmp.end(),
+ ModelSafeWorkerGroupIs(GROUP_PASSIVE));
+ if (it != w_tmp.end())
+ workers->push_back(*it);
+ else
+ NOTREACHED();
+}
- // Since we are initiating a new session for which we are the delegate, we
- // are not currently silenced so reset this state for the next session which
- // may need to use it.
- silenced_until_ = base::TimeTicks();
+void SyncerThread::ScheduleConfig(const ModelTypeBitSet& types) {
+ if (!thread_.IsRunning()) {
+ NOTREACHED();
+ return;
+ }
+ VLOG(1) << "SyncerThread(" << this << ")" << " Scheduling a config";
ModelSafeRoutingInfo routes;
std::vector<ModelSafeWorker*> workers;
- session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
- session_context_->registrar()->GetWorkers(&workers);
- SyncSourceInfo info(GetAndResetNudgeSource(was_throttled,
- continue_sync_cycle, initial_sync_for_thread, was_nudged));
- scoped_ptr<SyncSession> session;
-
- base::AutoUnlock unlock(lock_);
- do {
- session.reset(new SyncSession(session_context_.get(), this,
- info, routes, workers));
- VLOG(1) << "Calling SyncShare.";
- syncer->SyncShare(session.get());
- } while (session->HasMoreToSync() && silenced_until_.is_null());
-
- VLOG(1) << "Done calling SyncShare.";
- return session.release();
-}
-
-SyncSourceInfo SyncerThread::GetAndResetNudgeSource(bool was_throttled,
- bool continue_sync_cycle,
- bool* initial_sync,
- bool* was_nudged) {
- bool nudged = false;
- NudgeSource nudge_source = kUnknown;
- ModelTypePayloadMap model_types_with_payloads;
- // Has the previous sync cycle completed?
- if (continue_sync_cycle)
- nudge_source = kContinuation;
- // Update the nudge source if a new nudge has come through during the
- // previous sync cycle.
- if (!vault_.pending_nudge_time_.is_null()) {
- if (!was_throttled) {
- nudge_source = vault_.pending_nudge_source_;
- model_types_with_payloads = vault_.pending_nudge_types_;
- nudged = true;
- }
- VLOG(1) << "Clearing pending nudge from " << vault_.pending_nudge_source_
- << " at tick " << vault_.pending_nudge_time_.ToInternalValue();
- vault_.pending_nudge_source_ = kUnknown;
- vault_.pending_nudge_types_.clear();
- vault_.pending_nudge_time_ = base::TimeTicks();
+ GetModelSafeParamsForTypes(types, session_context_->registrar(),
+ &routes, &workers);
+
+ thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &SyncerThread::ScheduleConfigImpl, routes, workers,
+ GetUpdatesCallerInfo::FIRST_UPDATE));
+}
+
+void SyncerThread::ScheduleConfigImpl(const ModelSafeRoutingInfo& routing_info,
+ const std::vector<ModelSafeWorker*>& workers,
+ const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source) {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+
+ VLOG(1) << "SyncerThread(" << this << ")" << " ScheduleConfigImpl...";
+ // TODO(tim): config-specific GetUpdatesCallerInfo value?
+ SyncSession* session = new SyncSession(session_context_.get(), this,
+ SyncSourceInfo(source,
+ syncable::ModelTypePayloadMapFromRoutingInfo(
+ routing_info, std::string())),
+ routing_info, workers);
+ ScheduleSyncSessionJob(TimeDelta::FromSeconds(0),
+ SyncSessionJob::CONFIGURATION, session, FROM_HERE);
+}
+
+void SyncerThread::ScheduleSyncSessionJob(const base::TimeDelta& delay,
+ SyncSessionJob::SyncSessionJobPurpose purpose,
+ sessions::SyncSession* session,
+ const tracked_objects::Location& nudge_location) {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+
+ SyncSessionJob job(purpose, TimeTicks::Now() + delay,
+ make_linked_ptr(session), false, nudge_location);
+ if (purpose == SyncSessionJob::NUDGE) {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Resetting pending_nudge in"
+ << " ScheduleSyncSessionJob";
+ DCHECK(!pending_nudge_.get() || pending_nudge_->session.get() == session);
+ pending_nudge_.reset(new SyncSessionJob(job));
+ }
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " Posting job to execute in DoSyncSessionJob. Job purpose "
+ << job.purpose;
+ MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(this,
+ &SyncerThread::DoSyncSessionJob, job),
+ delay.InMilliseconds());
+}
+
+void SyncerThread::SetSyncerStepsForPurpose(
+ SyncSessionJob::SyncSessionJobPurpose purpose,
+ SyncerStep* start, SyncerStep* end) {
+ *end = SYNCER_END;
+ switch (purpose) {
+ case SyncSessionJob::CONFIGURATION:
+ *start = DOWNLOAD_UPDATES;
+ *end = APPLY_UPDATES;
+ return;
+ case SyncSessionJob::CLEAR_USER_DATA:
+ *start = CLEAR_PRIVATE_DATA;
+ return;
+ case SyncSessionJob::NUDGE:
+ case SyncSessionJob::POLL:
+ *start = SYNCER_BEGIN;
+ return;
+ default:
+ NOTREACHED();
}
+}
- *was_nudged = nudged;
-
- // TODO(tim): Hack for bug 64136 to correctly tag continuations that result
- // from syncer having more work to do. This will be handled properly with
- // the message loop based syncer thread, bug 26339.
- return MakeSyncSourceInfo(nudged || nudge_source == kContinuation,
- nudge_source, model_types_with_payloads, initial_sync);
-}
-
-SyncSourceInfo SyncerThread::MakeSyncSourceInfo(bool nudged,
- NudgeSource nudge_source,
- const ModelTypePayloadMap& model_types_with_payloads,
- bool* initial_sync) {
- sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source =
- sync_pb::GetUpdatesCallerInfo::UNKNOWN;
- if (*initial_sync) {
- updates_source = sync_pb::GetUpdatesCallerInfo::FIRST_UPDATE;
- *initial_sync = false;
- } else if (!nudged) {
- updates_source = sync_pb::GetUpdatesCallerInfo::PERIODIC;
+void SyncerThread::DoSyncSessionJob(const SyncSessionJob& job) {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ if (!ShouldRunJob(job))
+ return;
+
+ if (job.purpose == SyncSessionJob::NUDGE) {
+ DCHECK(pending_nudge_.get());
+ if (pending_nudge_->session != job.session)
+ return; // Another nudge must have been scheduled in in the meantime.
+ pending_nudge_.reset();
+ }
+ VLOG(1) << "SyncerThread(" << this << ")" << " DoSyncSessionJob. job purpose "
+ << job.purpose;
+
+ SyncerStep begin(SYNCER_BEGIN);
+ SyncerStep end(SYNCER_END);
+ SetSyncerStepsForPurpose(job.purpose, &begin, &end);
+
+ bool has_more_to_sync = true;
+ while (ShouldRunJob(job) && has_more_to_sync) {
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " SyncerThread: Calling SyncShare.";
+ // Synchronously perform the sync session from this thread.
+ syncer_->SyncShare(job.session.get(), begin, end);
+ has_more_to_sync = job.session->HasMoreToSync();
+ if (has_more_to_sync)
+ job.session->ResetTransientState();
+ }
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " SyncerThread: Done SyncShare looping.";
+ FinishSyncSessionJob(job);
+}
+
+void SyncerThread::UpdateCarryoverSessionState(const SyncSessionJob& old_job) {
+ if (old_job.purpose == SyncSessionJob::CONFIGURATION) {
+ // Whatever types were part of a configuration task will have had updates
+ // downloaded. For that reason, we make sure they get recorded in the
+ // event that they get disabled at a later time.
+ ModelSafeRoutingInfo r(session_context_->previous_session_routing_info());
+ if (!r.empty()) {
+ ModelSafeRoutingInfo temp_r;
+ ModelSafeRoutingInfo old_info(old_job.session->routing_info());
+ std::set_union(r.begin(), r.end(), old_info.begin(), old_info.end(),
+ std::insert_iterator<ModelSafeRoutingInfo>(temp_r, temp_r.begin()));
+ session_context_->set_previous_session_routing_info(temp_r);
+ }
} else {
- switch (nudge_source) {
- case kNotification:
- updates_source = sync_pb::GetUpdatesCallerInfo::NOTIFICATION;
- break;
- case kLocal:
- updates_source = sync_pb::GetUpdatesCallerInfo::LOCAL;
- break;
- case kContinuation:
- updates_source = sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION;
- break;
- case kClearPrivateData:
- updates_source = sync_pb::GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA;
- break;
- case kUnknown:
- default:
- updates_source = sync_pb::GetUpdatesCallerInfo::UNKNOWN;
- break;
+ session_context_->set_previous_session_routing_info(
+ old_job.session->routing_info());
+ }
+}
+
+void SyncerThread::FinishSyncSessionJob(const SyncSessionJob& job) {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ // Update timing information for how often datatypes are triggering nudges.
+ base::TimeTicks now = TimeTicks::Now();
+ if (!last_sync_session_end_time_.is_null()) {
+ ModelTypePayloadMap::const_iterator iter;
+ for (iter = job.session->source().types.begin();
+ iter != job.session->source().types.end();
+ ++iter) {
+ syncable::PostTimeToTypeHistogram(iter->first,
+ now - last_sync_session_end_time_);
}
}
+ last_sync_session_end_time_ = now;
+ UpdateCarryoverSessionState(job);
+ if (IsSyncingCurrentlySilenced()) {
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " We are currently throttled. So not scheduling the next sync.";
+ SaveJob(job);
+ return; // Nothing to do.
+ }
- ModelTypePayloadMap sync_source_types;
- if (model_types_with_payloads.empty()) {
- // No datatypes requested. This must be a poll so set all enabled datatypes.
- ModelSafeRoutingInfo routes;
- session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
- sync_source_types = syncable::ModelTypePayloadMapFromRoutingInfo(routes,
- std::string());
- } else {
- sync_source_types = model_types_with_payloads;
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " Updating the next polling time after SyncMain";
+ ScheduleNextSync(job);
+}
+
+void SyncerThread::ScheduleNextSync(const SyncSessionJob& old_job) {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ DCHECK(!old_job.session->HasMoreToSync());
+ // Note: |num_server_changes_remaining| > 0 here implies that we received a
+ // broken response while trying to download all updates, because the Syncer
+ // will loop until this value is exhausted. Also, if unsynced_handles exist
+ // but HasMoreToSync is false, this implies that the Syncer determined no
+ // forward progress was possible at this time (an error, such as an HTTP
+ // 500, is likely to have occurred during commit).
+ const bool work_to_do =
+ old_job.session->status_controller()->num_server_changes_remaining() > 0
+ || old_job.session->status_controller()->unsynced_handles().size() > 0;
+ VLOG(1) << "SyncerThread(" << this << ")" << " syncer has work to do: "
+ << work_to_do;
+
+ AdjustPolling(&old_job);
+
+ // TODO(tim): Old impl had special code if notifications disabled. Needed?
+ if (!work_to_do) {
+ // Success implies backoff relief. Note that if this was a "one-off" job
+ // (i.e. purpose == SyncSessionJob::CLEAR_USER_DATA), if there was
+ // work_to_do before it ran this wont have changed, as jobs like this don't
+ // run a full sync cycle. So we don't need special code here.
+ wait_interval_.reset();
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " Job suceeded so not scheduling more jobs";
+ return;
}
- return SyncSourceInfo(updates_source, sync_source_types);
-}
-
-void SyncerThread::CreateSyncer(const std::string& dirname) {
- base::AutoLock lock(lock_);
- VLOG(1) << "Creating syncer up for: " << dirname;
- // The underlying database structure is ready, and we should create
- // the syncer.
- CHECK(vault_.syncer_ == NULL);
- vault_.syncer_ = new Syncer();
- vault_field_changed_.Broadcast();
-}
-
-// Sets |*connected| to false if it is currently true but |code| suggests that
-// the current network configuration and/or auth state cannot be used to make
-// forward progress, and user intervention (e.g changing server URL or auth
-// credentials) is likely necessary. If |*connected| is false, set it to true
-// if |code| suggests that we just recently made healthy contact with the
-// server.
-static inline void CheckConnected(bool* connected,
- HttpResponse::ServerConnectionCode code,
- base::ConditionVariable* condvar) {
- if (*connected) {
- // Note, be careful when adding cases here because if the SyncerThread
- // thinks there is no valid connection as determined by this method, it
- // will drop out of *all* forward progress sync loops (it won't poll and it
- // will queue up Talk notifications but not actually call SyncShare) until
- // some external action causes a ServerConnectionManager to broadcast that
- // a valid connection has been re-established.
- if (HttpResponse::CONNECTION_UNAVAILABLE == code ||
- HttpResponse::SYNC_AUTH_ERROR == code) {
- *connected = false;
- condvar->Broadcast();
- }
+ if (old_job.session->source().updates_source ==
+ GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION) {
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " Job failed with source continuation";
+ // We don't seem to have made forward progress. Start or extend backoff.
+ HandleConsecutiveContinuationError(old_job);
+ } else if (IsBackingOff()) {
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " A nudge during backoff failed";
+ // We weren't continuing but we're in backoff; must have been a nudge.
+ DCHECK_EQ(SyncSessionJob::NUDGE, old_job.purpose);
+ DCHECK(!wait_interval_->had_nudge);
+ wait_interval_->had_nudge = true;
+ wait_interval_->timer.Reset();
} else {
- if (HttpResponse::SERVER_CONNECTION_OK == code) {
- *connected = true;
- condvar->Broadcast();
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " Failed. Schedule a job with continuation as source";
+ // We weren't continuing and we aren't in backoff. Schedule a normal
+ // continuation.
+ if (old_job.purpose == SyncSessionJob::CONFIGURATION) {
+ ScheduleConfigImpl(old_job.session->routing_info(),
+ old_job.session->workers(),
+ GetUpdatesFromNudgeSource(NUDGE_SOURCE_CONTINUATION));
+ } else {
+ // For all other purposes(nudge and poll) we schedule a retry nudge.
+ ScheduleNudgeImpl(TimeDelta::FromSeconds(0),
+ GetUpdatesFromNudgeSource(NUDGE_SOURCE_CONTINUATION),
+ old_job.session->source().types, false, FROM_HERE);
}
}
}
-void SyncerThread::WatchConnectionManager(ServerConnectionManager* conn_mgr) {
- conn_mgr_hookup_.reset(NewEventListenerHookup(conn_mgr->channel(), this,
- &SyncerThread::HandleServerConnectionEvent));
- CheckConnected(&vault_.connected_, conn_mgr->server_status(),
- &vault_field_changed_);
+void SyncerThread::AdjustPolling(const SyncSessionJob* old_job) {
+ DCHECK(thread_.IsRunning());
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+
+ TimeDelta poll = (!session_context_->notifications_enabled()) ?
+ syncer_short_poll_interval_seconds_ :
+ syncer_long_poll_interval_seconds_;
+ bool rate_changed = !poll_timer_.IsRunning() ||
+ poll != poll_timer_.GetCurrentDelay();
+
+ if (old_job && old_job->purpose != SyncSessionJob::POLL && !rate_changed)
+ poll_timer_.Reset();
+
+ if (!rate_changed)
+ return;
+
+ // Adjust poll rate.
+ poll_timer_.Stop();
+ poll_timer_.Start(poll, this, &SyncerThread::PollTimerCallback);
}
-void SyncerThread::HandleServerConnectionEvent(
- const ServerConnectionEvent& event) {
- if (ServerConnectionEvent::STATUS_CHANGED == event.what_happened) {
- base::AutoLock lock(lock_);
- CheckConnected(&vault_.connected_, event.connection_code,
- &vault_field_changed_);
+void SyncerThread::HandleConsecutiveContinuationError(
+ const SyncSessionJob& old_job) {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ // This if conditions should be compiled out in retail builds.
+ if (IsBackingOff()) {
+ DCHECK(wait_interval_->timer.IsRunning() || old_job.is_canary_job);
}
+ SyncSession* old = old_job.session.get();
+ SyncSession* s(new SyncSession(session_context_.get(), this,
+ old->source(), old->routing_info(), old->workers()));
+ TimeDelta length = delay_provider_->GetDelay(
+ IsBackingOff() ? wait_interval_->length : TimeDelta::FromSeconds(1));
+
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " In handle continuation error. Old job purpose is "
+ << old_job.purpose;
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " In Handle continuation error. The time delta(ms) is: "
+ << length.InMilliseconds();
+
+ // This will reset the had_nudge variable as well.
+ wait_interval_.reset(new WaitInterval(WaitInterval::EXPONENTIAL_BACKOFF,
+ length));
+ if (old_job.purpose == SyncSessionJob::CONFIGURATION) {
+ SyncSessionJob job(old_job.purpose, TimeTicks::Now() + length,
+ make_linked_ptr(s), false, FROM_HERE);
+ wait_interval_->pending_configure_job.reset(new SyncSessionJob(job));
+ } else {
+ // We are not in configuration mode. So wait_interval's pending job
+ // should be null.
+ DCHECK(wait_interval_->pending_configure_job.get() == NULL);
+
+ // TODO(lipalani) - handle clear user data.
+ InitOrCoalescePendingJob(old_job);
+ }
+ wait_interval_->timer.Start(length, this, &SyncerThread::DoCanaryJob);
}
-int SyncerThread::GetRecommendedDelaySeconds(int base_delay_seconds) {
- if (base_delay_seconds >= kMaxBackoffSeconds)
- return kMaxBackoffSeconds;
+// static
+TimeDelta SyncerThread::GetRecommendedDelay(const TimeDelta& last_delay) {
+ if (last_delay.InSeconds() >= kMaxBackoffSeconds)
+ return TimeDelta::FromSeconds(kMaxBackoffSeconds);
// This calculates approx. base_delay_seconds * 2 +/- base_delay_seconds / 2
- int backoff_s =
- std::max(1, base_delay_seconds * kBackoffRandomizationFactor);
+ int64 backoff_s =
+ std::max(static_cast<int64>(1),
+ last_delay.InSeconds() * kBackoffRandomizationFactor);
// Flip a coin to randomize backoff interval by +/- 50%.
int rand_sign = base::RandInt(0, 1) * 2 - 1;
// Truncation is adequate for rounding here.
backoff_s = backoff_s +
- (rand_sign * (base_delay_seconds / kBackoffRandomizationFactor));
+ (rand_sign * (last_delay.InSeconds() / kBackoffRandomizationFactor));
// Cap the backoff interval.
- backoff_s = std::max(1, std::min(backoff_s, kMaxBackoffSeconds));
+ backoff_s = std::max(static_cast<int64>(1),
+ std::min(backoff_s, kMaxBackoffSeconds));
- return backoff_s;
+ return TimeDelta::FromSeconds(backoff_s);
}
-// Inputs and return value in milliseconds.
-int SyncerThread::CalculateSyncWaitTime(int last_interval, int user_idle_ms) {
- // syncer_polling_interval_ is in seconds
- int syncer_polling_interval_ms = syncer_polling_interval_ * 1000;
-
- // This is our default and lower bound.
- int next_wait = syncer_polling_interval_ms;
-
- // Get idle time, bounded by max wait.
- int idle = min(user_idle_ms, syncer_max_interval_);
+void SyncerThread::Stop() {
+ VLOG(1) << "SyncerThread(" << this << ")" << " stop called";
+ syncer_->RequestEarlyExit(); // Safe to call from any thread.
+ session_context_->connection_manager()->RemoveListener(this);
+ thread_.Stop();
+}
- // If the user has been idle for a while, we'll start decreasing the poll
- // rate.
- if (idle >= kPollBackoffThresholdMultiplier * syncer_polling_interval_ms) {
- next_wait = std::min(GetRecommendedDelaySeconds(
- last_interval / 1000), syncer_max_interval_ / 1000) * 1000;
+void SyncerThread::DoCanaryJob() {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Do canary job";
+ DoPendingJobIfPossible(true);
+}
+
+void SyncerThread::DoPendingJobIfPossible(bool is_canary_job) {
+ SyncSessionJob* job_to_execute = NULL;
+ if (mode_ == CONFIGURATION_MODE && wait_interval_.get()
+ && wait_interval_->pending_configure_job.get()) {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Found pending configure job";
+ job_to_execute = wait_interval_->pending_configure_job.get();
+ } else if (mode_ == NORMAL_MODE && pending_nudge_.get()) {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Found pending nudge job";
+ // Pending jobs mostly have time from the past. Reset it so this job
+ // will get executed.
+ if (pending_nudge_->scheduled_start < TimeTicks::Now())
+ pending_nudge_->scheduled_start = TimeTicks::Now();
+
+ scoped_ptr<SyncSession> session(CreateSyncSession(
+ pending_nudge_->session->source()));
+
+ // Also the routing info might have been changed since we cached the
+ // pending nudge. Update it by coalescing to the latest.
+ pending_nudge_->session->Coalesce(*(session.get()));
+ // The pending nudge would be cleared in the DoSyncSessionJob function.
+ job_to_execute = pending_nudge_.get();
}
- return next_wait;
-}
-
-// Called with mutex_ already locked.
-void SyncerThread::NudgeSyncImpl(
- int milliseconds_from_now,
- NudgeSource source,
- const ModelTypePayloadMap& model_types_with_payloads) {
- // TODO(sync): Add the option to reset the backoff state machine.
- // This is needed so nudges that are a result of the user's desire
- // to download updates for a new data type can be satisfied quickly.
- if (vault_.current_wait_interval_.mode == WaitInterval::THROTTLED ||
- vault_.current_wait_interval_.had_nudge_during_backoff) {
- // Drop nudges on the floor if we've already had one since starting this
- // stage of exponential backoff or we are throttled.
- return;
+ if (job_to_execute != NULL) {
+ VLOG(1) << "SyncerThread(" << this << ")" << " Executing pending job";
+ SyncSessionJob copy = *job_to_execute;
+ copy.is_canary_job = is_canary_job;
+ DoSyncSessionJob(copy);
}
+}
- // Union the current ModelTypePayloadMap with any from nudges that may have
- // already posted (coalesce the nudge datatype information).
- // TODO(tim): It seems weird to do this if the sources don't match up (e.g.
- // if pending_source is kLocal and |source| is kClearPrivateData).
- syncable::CoalescePayloads(&vault_.pending_nudge_types_,
- model_types_with_payloads);
-
- const TimeTicks nudge_time = TimeTicks::Now() +
- TimeDelta::FromMilliseconds(milliseconds_from_now);
- if (nudge_time <= vault_.pending_nudge_time_) {
- VLOG(1) << "Nudge for source " << source
- << " dropped due to existing later pending nudge";
- return;
- }
+SyncSession* SyncerThread::CreateSyncSession(const SyncSourceInfo& source) {
+ ModelSafeRoutingInfo routes;
+ std::vector<ModelSafeWorker*> workers;
+ session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
+ session_context_->registrar()->GetWorkers(&workers);
+ SyncSourceInfo info(source);
- VLOG(1) << "Replacing pending nudge for source " << source
- << " at " << nudge_time.ToInternalValue();
+ SyncSession* session(new SyncSession(session_context_.get(), this, info,
+ routes, workers));
- vault_.pending_nudge_source_ = source;
- vault_.pending_nudge_time_ = nudge_time;
- vault_field_changed_.Broadcast();
+ return session;
}
-void SyncerThread::SetNotificationsEnabled(bool notifications_enabled) {
- base::AutoLock lock(lock_);
- session_context_->set_notifications_enabled(notifications_enabled);
+void SyncerThread::PollTimerCallback() {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ ModelSafeRoutingInfo r;
+ ModelTypePayloadMap types_with_payloads =
+ syncable::ModelTypePayloadMapFromRoutingInfo(r, std::string());
+ SyncSourceInfo info(GetUpdatesCallerInfo::PERIODIC, types_with_payloads);
+ SyncSession* s = CreateSyncSession(info);
+ ScheduleSyncSessionJob(TimeDelta::FromSeconds(0), SyncSessionJob::POLL, s,
+ FROM_HERE);
}
-// Returns the amount of time since the user last interacted with the computer,
-// in milliseconds
-int SyncerThread::UserIdleTime() {
-#if defined(OS_WIN)
- LASTINPUTINFO last_input_info;
- last_input_info.cbSize = sizeof(LASTINPUTINFO);
-
- // Get time in windows ticks since system start of last activity.
- BOOL b = ::GetLastInputInfo(&last_input_info);
- if (b == TRUE)
- return ::GetTickCount() - last_input_info.dwTime;
-#elif defined(OS_MACOSX)
- // It would be great to do something like:
- //
- // return 1000 *
- // CGEventSourceSecondsSinceLastEventType(
- // kCGEventSourceStateCombinedSessionState,
- // kCGAnyInputEventType);
- //
- // Unfortunately, CGEvent* lives in ApplicationServices, and we're a daemon
- // and can't link that high up the food chain. Thus this mucking in IOKit.
-
- io_service_t hid_service =
- IOServiceGetMatchingService(kIOMasterPortDefault,
- IOServiceMatching("IOHIDSystem"));
- if (!hid_service) {
- LOG(WARNING) << "Could not obtain IOHIDSystem";
- return 0;
- }
+void SyncerThread::Unthrottle() {
+ DCHECK_EQ(WaitInterval::THROTTLED, wait_interval_->mode);
+ VLOG(1) << "SyncerThread(" << this << ")" << " Unthrottled..";
+ DoCanaryJob();
+ wait_interval_.reset();
+}
- CFTypeRef object = IORegistryEntryCreateCFProperty(hid_service,
- CFSTR("HIDIdleTime"),
- kCFAllocatorDefault,
- 0);
- if (!object) {
- LOG(WARNING) << "Could not get IOHIDSystem's HIDIdleTime property";
- IOObjectRelease(hid_service);
- return 0;
- }
+void SyncerThread::Notify(SyncEngineEvent::EventCause cause) {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ session_context_->NotifyListeners(SyncEngineEvent(cause));
+}
- int64 idle_time; // in nanoseconds
- Boolean success = false;
- if (CFGetTypeID(object) == CFNumberGetTypeID()) {
- success = CFNumberGetValue((CFNumberRef)object,
- kCFNumberSInt64Type,
- &idle_time);
- } else {
- LOG(WARNING) << "IOHIDSystem's HIDIdleTime property isn't a number!";
- }
+bool SyncerThread::IsBackingOff() const {
+ return wait_interval_.get() && wait_interval_->mode ==
+ WaitInterval::EXPONENTIAL_BACKOFF;
+}
+
+void SyncerThread::OnSilencedUntil(const base::TimeTicks& silenced_until) {
+ wait_interval_.reset(new WaitInterval(WaitInterval::THROTTLED,
+ silenced_until - TimeTicks::Now()));
+ wait_interval_->timer.Start(wait_interval_->length, this,
+ &SyncerThread::Unthrottle);
+}
- CFRelease(object);
- IOObjectRelease(hid_service);
+bool SyncerThread::IsSyncingCurrentlySilenced() {
+ return wait_interval_.get() && wait_interval_->mode ==
+ WaitInterval::THROTTLED;
+}
- if (!success) {
- LOG(WARNING) << "Could not get IOHIDSystem's HIDIdleTime property's value";
- return 0;
- }
- return idle_time / 1000000; // nano to milli
-#elif defined(OS_LINUX)
- if (idle_query_.get())
- return idle_query_->IdleTime();
- return 0;
-#else
- static bool was_logged = false;
- if (!was_logged) {
- was_logged = true;
- VLOG(1) << "UserIdleTime unimplemented on this platform, synchronization "
- "will not throttle when user idle";
- }
-#endif
+void SyncerThread::OnReceivedShortPollIntervalUpdate(
+ const base::TimeDelta& new_interval) {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ syncer_short_poll_interval_seconds_ = new_interval;
+}
- return 0;
+void SyncerThread::OnReceivedLongPollIntervalUpdate(
+ const base::TimeDelta& new_interval) {
+ DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
+ syncer_long_poll_interval_seconds_ = new_interval;
+}
+
+void SyncerThread::OnShouldStopSyncingPermanently() {
+ VLOG(1) << "SyncerThread(" << this << ")"
+ << " OnShouldStopSyncingPermanently";
+ syncer_->RequestEarlyExit(); // Thread-safe.
+ Notify(SyncEngineEvent::STOP_SYNCING_PERMANENTLY);
+}
+
+void SyncerThread::OnServerConnectionEvent(
+ const ServerConnectionEvent2& event) {
+ thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &SyncerThread::CheckServerConnectionManagerStatus,
+ event.connection_code));
+}
+
+void SyncerThread::set_notifications_enabled(bool notifications_enabled) {
+ session_context_->set_notifications_enabled(notifications_enabled);
}
-} // namespace browser_sync
+} // browser_sync
diff --git a/chrome/browser/sync/engine/syncer_thread.h b/chrome/browser/sync/engine/syncer_thread.h
index d270f14..11fee16 100644
--- a/chrome/browser/sync/engine/syncer_thread.h
+++ b/chrome/browser/sync/engine/syncer_thread.h
@@ -3,74 +3,175 @@
// found in the LICENSE file.
//
// A class to run the syncer on a thread.
-// This is the default implementation of SyncerThread whose Stop implementation
-// does not support a timeout, but is greatly simplified.
#ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
#define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
#pragma once
-#include <list>
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/ref_counted.h"
+#include "base/callback.h"
+#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/condition_variable.h"
+#include "base/observer_list.h"
+#include "base/task.h"
#include "base/threading/thread.h"
#include "base/time.h"
-#include "base/synchronization/waitable_event.h"
-#include "chrome/browser/sync/engine/syncer_types.h"
-#include "chrome/browser/sync/sessions/sync_session.h"
-#include "chrome/browser/sync/syncable/model_type.h"
+#include "base/timer.h"
+#include "chrome/browser/sync/engine/nudge_source.h"
+#include "chrome/browser/sync/engine/polling_constants.h"
+#include "chrome/browser/sync/engine/syncer.h"
#include "chrome/browser/sync/syncable/model_type_payload_map.h"
-#include "chrome/common/deprecated/event_sys-inl.h"
-
-#if defined(OS_LINUX)
-#include "chrome/browser/sync/engine/idle_query_linux.h"
-#endif
-
-class EventListenerHookup;
+#include "chrome/browser/sync/engine/net/server_connection_manager.h"
+#include "chrome/browser/sync/sessions/sync_session.h"
+#include "chrome/browser/sync/sessions/sync_session_context.h"
namespace browser_sync {
-class ModelSafeWorker;
-class ServerConnectionManager;
-class Syncer;
-class URLFactory;
struct ServerConnectionEvent;
-class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
- public sessions::SyncSession::Delegate {
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadTest, CalculateSyncWaitTime);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadTest, CalculatePollingWaitTime);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Polling);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Nudge);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, NudgeWithDataTypes);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest,
- NudgeWithDataTypesCoalesced);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, NudgeWithPayloads);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest,
- NudgeWithPayloadsCoalesced);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Throttling);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, AuthInvalid);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Pause);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, StartWhenNotConnected);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, PauseWhenNotConnected);
- FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, StopSyncPermanently);
- friend class SyncerThreadWithSyncerTest;
- friend class SyncerThreadFactory;
+class SyncerThread : public sessions::SyncSession::Delegate,
+ public ServerConnectionEventListener {
public:
- // Encapsulates the parameters that make up an interval on which the
- // syncer thread is sleeping.
+ enum Mode {
+ // In this mode, the thread only performs configuration tasks. This is
+ // designed to make the case where we want to download updates for a
+ // specific type only, and not continue syncing until we are moved into
+ // normal mode.
+ CONFIGURATION_MODE,
+ // Resumes polling and allows nudges, drops configuration tasks. Runs
+ // through entire sync cycle.
+ NORMAL_MODE,
+ };
+
+ // Takes ownership of both |context| and |syncer|.
+ SyncerThread(sessions::SyncSessionContext* context, Syncer* syncer);
+ virtual ~SyncerThread();
+
+ typedef Callback0::Type ModeChangeCallback;
+
+ // Change the mode of operation.
+ // We don't use a lock when changing modes, so we won't cause currently
+ // scheduled jobs to adhere to the new mode. We could protect it, but it
+ // doesn't buy very much as a) a session could already be in progress and it
+ // will continue no matter what, b) the scheduled sessions already contain
+ // all their required state and won't be affected by potential change at
+ // higher levels (i.e. the registrar), and c) we service tasks FIFO, so once
+ // the mode changes all future jobs will be run against the updated mode.
+ // If supplied, |callback| will be invoked when the mode has been
+ // changed to |mode| *from the SyncerThread*, and not from the caller
+ // thread.
+ void Start(Mode mode, ModeChangeCallback* callback);
+
+ // Joins on the thread as soon as possible (currently running session
+ // completes).
+ void Stop();
+
+ // The meat and potatoes.
+ void ScheduleNudge(const base::TimeDelta& delay, NudgeSource source,
+ const syncable::ModelTypeBitSet& types,
+ const tracked_objects::Location& nudge_location);
+ void ScheduleNudgeWithPayloads(
+ const base::TimeDelta& delay, NudgeSource source,
+ const syncable::ModelTypePayloadMap& types_with_payloads,
+ const tracked_objects::Location& nudge_location);
+ void ScheduleConfig(const syncable::ModelTypeBitSet& types);
+ void ScheduleClearUserData();
+
+ // Change status of notifications in the SyncSessionContext.
+ void set_notifications_enabled(bool notifications_enabled);
+
+ // DDOS avoidance function. Calculates how long we should wait before trying
+ // again after a failed sync attempt, where the last delay was |base_delay|.
+ // TODO(tim): Look at URLRequestThrottlerEntryInterface.
+ static base::TimeDelta GetRecommendedDelay(const base::TimeDelta& base_delay);
+
+ // SyncSession::Delegate implementation.
+ virtual void OnSilencedUntil(const base::TimeTicks& silenced_until);
+ virtual bool IsSyncingCurrentlySilenced();
+ virtual void OnReceivedShortPollIntervalUpdate(
+ const base::TimeDelta& new_interval);
+ virtual void OnReceivedLongPollIntervalUpdate(
+ const base::TimeDelta& new_interval);
+ virtual void OnShouldStopSyncingPermanently();
+
+ // ServerConnectionEventListener implementation.
+ // TODO(tim): schedule a nudge when valid connection detected? in 1 minute?
+ virtual void OnServerConnectionEvent(const ServerConnectionEvent2& event);
+
+ private:
+ enum JobProcessDecision {
+ // Indicates we should continue with the current job.
+ CONTINUE,
+ // Indicates that we should save it to be processed later.
+ SAVE,
+ // Indicates we should drop this job.
+ DROP,
+ };
+
+ struct SyncSessionJob {
+ // An enum used to describe jobs for scheduling purposes.
+ enum SyncSessionJobPurpose {
+ // Our poll timer schedules POLL jobs periodically based on a server
+ // assigned poll interval.
+ POLL,
+ // A nudge task can come from a variety of components needing to force
+ // a sync. The source is inferable from |session.source()|.
+ NUDGE,
+ // The user invoked a function in the UI to clear their entire account
+ // and stop syncing (globally).
+ CLEAR_USER_DATA,
+ // Typically used for fetching updates for a subset of the enabled types
+ // during initial sync or reconfiguration. We don't run all steps of
+ // the sync cycle for these (e.g. CleanupDisabledTypes is skipped).
+ CONFIGURATION,
+ };
+ SyncSessionJob();
+ SyncSessionJob(SyncSessionJobPurpose purpose, base::TimeTicks start,
+ linked_ptr<sessions::SyncSession> session, bool is_canary_job,
+ const tracked_objects::Location& nudge_location);
+ ~SyncSessionJob();
+ SyncSessionJobPurpose purpose;
+ base::TimeTicks scheduled_start;
+ linked_ptr<sessions::SyncSession> session;
+ bool is_canary_job;
+
+ // This is the location the nudge came from. used for debugging purpose.
+ // In case of multiple nudges getting coalesced this stores the first nudge
+ // that came in.
+ tracked_objects::Location nudge_location;
+ };
+ friend class SyncerThread2Test;
+ friend class SyncerThread2WhiteboxTest;
+
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
+ DropNudgeWhileExponentialBackOff);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, SaveNudge);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueNudge);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, DropPoll);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinuePoll);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueConfiguration);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
+ SaveConfigurationWhileThrottled);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
+ SaveNudgeWhileThrottled);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
+ ContinueClearUserDataUnderAllCircumstances);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
+ ContinueCanaryJobConfig);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
+ ContinueNudgeWhileExponentialBackOff);
+
+ // A component used to get time delays associated with exponential backoff.
+ // Encapsulated into a class to facilitate testing.
+ class DelayProvider {
+ public:
+ DelayProvider();
+ virtual base::TimeDelta GetDelay(const base::TimeDelta& last_delay);
+ virtual ~DelayProvider();
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DelayProvider);
+ };
+
struct WaitInterval {
enum Mode {
- // A wait interval whose duration has not been affected by exponential
- // backoff. The base case for exponential backoff falls in to this case
- // (e.g when the exponent is 1). So far, we don't need a separate case.
- // NORMAL intervals are not nudge-rate limited.
- NORMAL,
// A wait interval whose duration has been affected by exponential
// backoff.
// EXPONENTIAL_BACKOFF intervals are nudge-rate limited to 1 per interval.
@@ -79,286 +180,162 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
// during such an interval.
THROTTLED,
};
+ WaitInterval();
+ ~WaitInterval();
Mode mode;
- // This bool is set to true if we have observed a nudge during during this
- // interval and mode == EXPONENTIAL_BACKOFF.
- bool had_nudge_during_backoff;
- base::TimeDelta poll_delta; // The wait duration until the next poll.
- WaitInterval() : mode(NORMAL), had_nudge_during_backoff(false) { }
+ // This bool is set to true if we have observed a nudge during this
+ // interval and mode == EXPONENTIAL_BACKOFF.
+ bool had_nudge;
+ base::TimeDelta length;
+ base::OneShotTimer<SyncerThread> timer;
+
+ // Configure jobs are saved only when backing off or throttling. So we
+ // expose the pointer here.
+ scoped_ptr<SyncSessionJob> pending_configure_job;
+ WaitInterval(Mode mode, base::TimeDelta length);
};
- enum NudgeSource {
- kUnknown = 0,
- kNotification,
- kLocal,
- kContinuation,
- kClearPrivateData
- };
- // Server can overwrite these values via client commands.
- // Standard short poll. This is used when XMPP is off.
- static const int kDefaultShortPollIntervalSeconds;
- // Long poll is used when XMPP is on.
- static const int kDefaultLongPollIntervalSeconds;
- // 30 minutes by default. If exponential backoff kicks in, this is the
- // longest possible poll interval.
- static const int kDefaultMaxPollIntervalMs;
- // Maximum interval for exponential backoff.
- static const int kMaxBackoffSeconds;
-
- explicit SyncerThread(sessions::SyncSessionContext* context);
- virtual ~SyncerThread();
+ // Helper to assemble a job and post a delayed task to sync.
+ void ScheduleSyncSessionJob(
+ const base::TimeDelta& delay,
+ SyncSessionJob::SyncSessionJobPurpose purpose,
+ sessions::SyncSession* session,
+ const tracked_objects::Location& nudge_location);
- virtual void WatchConnectionManager(ServerConnectionManager* conn_mgr);
-
- // Starts a syncer thread.
- // Returns true if it creates a thread or if there's currently a thread
- // running and false otherwise.
- virtual bool Start();
-
- // Stop processing. |max_wait| doesn't do anything in this version.
- virtual bool Stop(int max_wait);
-
- // Request that the thread pauses. Returns false if the request can
- // not be completed (e.g. the thread is not running). When the
- // thread actually pauses, a SyncEngineEvent::PAUSED event notification
- // will be sent to the relay channel.
- virtual bool RequestPause();
-
- // Request that the thread resumes from pause. Returns false if the
- // request can not be completed (e.g. the thread is not running or
- // is not currently paused). When the thread actually resumes, a
- // SyncEngineEvent::RESUMED event notification will be sent to the relay
- // channel.
- virtual bool RequestResume();
-
- // Nudges the syncer to sync with a delay specified. This API is for access
- // from the SyncerThread's controller and will cause a mutex lock.
- virtual void NudgeSyncer(int milliseconds_from_now, NudgeSource source);
-
- // Same as |NudgeSyncer|, but supports tracking the datatypes that caused
- // the nudge to occur.
- virtual void NudgeSyncerWithDataTypes(
- int milliseconds_from_now,
- NudgeSource source,
- const syncable::ModelTypeBitSet& model_types);
-
- // Same as |NudgeSyncer|, but supports including a payload for passing on to
- // the download updates command. Datatypes with payloads are also considered
- // to have caused a nudged to occur and treated accordingly.
- virtual void NudgeSyncerWithPayloads(
- int milliseconds_from_now,
- NudgeSource source,
- const syncable::ModelTypePayloadMap& model_types_with_payloads);
-
- void SetNotificationsEnabled(bool notifications_enabled);
-
- // Call this when a directory is opened
- void CreateSyncer(const std::string& dirname);
-
- // DDOS avoidance function. The argument and return value is in seconds
- static int GetRecommendedDelaySeconds(int base_delay_seconds);
-
- protected:
- virtual void ThreadMain();
- void ThreadMainLoop();
-
- virtual void SetConnected(bool connected);
-
- virtual void SetSyncerPollingInterval(base::TimeDelta interval);
- virtual void SetSyncerShortPollInterval(base::TimeDelta interval);
-
- // Needed to emulate the behavior of pthread_create, which synchronously
- // started the thread and set the value of thread_running_ to true.
- // We can't quite match that because we asynchronously post the task,
- // which opens a window for Stop to get called before the task actually
- // makes it. To prevent this, we block Start() until we're sure it's ok.
- base::WaitableEvent thread_main_started_;
-
- // Handle of the running thread.
- base::Thread thread_;
+ // Invoke the Syncer to perform a sync.
+ void DoSyncSessionJob(const SyncSessionJob& job);
- // Fields that are modified / accessed by multiple threads go in this struct
- // for clarity and explicitness.
- struct ProtectedFields {
- ProtectedFields();
- ~ProtectedFields();
+ // Called after the Syncer has performed the sync represented by |job|, to
+ // reset our state.
+ void FinishSyncSessionJob(const SyncSessionJob& job);
- // False when we want to stop the thread.
- bool stop_syncer_thread_;
+ // Record important state that might be needed in future syncs, such as which
+ // data types may require cleanup.
+ void UpdateCarryoverSessionState(const SyncSessionJob& old_job);
- // True when a pause was requested.
- bool pause_requested_;
+ // Helper to FinishSyncSessionJob to schedule the next sync operation.
+ void ScheduleNextSync(const SyncSessionJob& old_job);
- // True when the thread is paused.
- bool paused_;
+ // Helper to configure polling intervals. Used by Start and ScheduleNextSync.
+ void AdjustPolling(const SyncSessionJob* old_job);
- Syncer* syncer_;
+ // Helper to ScheduleNextSync in case of consecutive sync errors.
+ void HandleConsecutiveContinuationError(const SyncSessionJob& old_job);
- // State of the server connection.
- bool connected_;
+ // Determines if it is legal to run |job| by checking current
+ // operational mode, backoff or throttling, freshness
+ // (so we don't make redundant syncs), and connection.
+ bool ShouldRunJob(const SyncSessionJob& job);
- // kUnknown if there is no pending nudge. (Theoretically, there
- // could be a pending nudge of type kUnknown, so it's better to
- // check pending_nudge_time_.)
- NudgeSource pending_nudge_source_;
+ // Decide whether we should CONTINUE, SAVE or DROP the job.
+ JobProcessDecision DecideOnJob(const SyncSessionJob& job);
- // Map of all datatypes that are requesting a nudge. Can be union
- // from multiple nudges that are coalesced. In addition, we
- // optionally track a payload associated with each datatype (most recent
- // payload overwrites old ones). These payloads are used by the download
- // updates command and can contain datatype specific information the server
- // might use.
- syncable::ModelTypePayloadMap pending_nudge_types_;
+ // Decide on whether to CONTINUE, SAVE or DROP the job when we are in
+ // backoff mode.
+ JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job);
- // null iff there is no pending nudge.
- base::TimeTicks pending_nudge_time_;
+ // Saves the job for future execution. Note: It drops all the poll jobs.
+ void SaveJob(const SyncSessionJob& job);
- // The wait interval for to the current iteration of our main loop. This is
- // only written to by the syncer thread, and since the only reader from a
- // different thread (NudgeSync) is called at totally random times, we don't
- // really need to access mutually exclusively as the data races that exist
- // are intrinsic, but do so anyway and avoid using 'volatile'.
- WaitInterval current_wait_interval_;
- } vault_;
+ // Coalesces the current job with the pending nudge.
+ void InitOrCoalescePendingJob(const SyncSessionJob& job);
- // Gets signaled whenever a thread outside of the syncer thread changes a
- // protected field in the vault_.
- base::ConditionVariable vault_field_changed_;
+ // 'Impl' here refers to real implementation of public functions, running on
+ // |thread_|.
+ void StartImpl(Mode mode, linked_ptr<ModeChangeCallback> callback);
+ void ScheduleNudgeImpl(
+ const base::TimeDelta& delay,
+ sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+ const syncable::ModelTypePayloadMap& types_with_payloads,
+ bool is_canary_job, const tracked_objects::Location& nudge_location);
+ void ScheduleConfigImpl(const ModelSafeRoutingInfo& routing_info,
+ const std::vector<ModelSafeWorker*>& workers,
+ const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source);
+ void ScheduleClearUserDataImpl();
- // Used to lock everything in |vault_|.
- base::Lock lock_;
+ // Returns true if the client is currently in exponential backoff.
+ bool IsBackingOff() const;
- private:
- // Threshold multipler for how long before user should be considered idle.
- static const int kPollBackoffThresholdMultiplier = 10;
+ // Helper to signal all listeners registered with |session_context_|.
+ void Notify(SyncEngineEvent::EventCause cause);
- // SyncSession::Delegate implementation.
- virtual void OnSilencedUntil(const base::TimeTicks& silenced_until);
- virtual bool IsSyncingCurrentlySilenced();
- virtual void OnReceivedShortPollIntervalUpdate(
- const base::TimeDelta& new_interval);
- virtual void OnReceivedLongPollIntervalUpdate(
- const base::TimeDelta& new_interval);
- virtual void OnShouldStopSyncingPermanently();
+ // Callback to change backoff state.
+ void DoCanaryJob();
+ void Unthrottle();
- void HandleServerConnectionEvent(const ServerConnectionEvent& event);
-
- // Collect all local state required for a sync and build a SyncSession out of
- // it, reset state for the next time, and performs the sync cycle.
- // See |GetAndResetNudgeSource| for details on what 'reset' means.
- // |was_nudged| is set to true if the session returned is fulfilling a nudge.
- // Returns once the session is finished (HasMoreToSync returns false). The
- // caller owns the returned SyncSession.
- sessions::SyncSession* SyncMain(Syncer* syncer,
- bool was_throttled,
- bool continue_sync_cycle,
- bool* initial_sync_for_thread,
- bool* was_nudged);
-
- // Calculates the next sync wait time and exponential backoff state.
- // last_poll_wait is the time duration of the previous polling timeout which
- // was used. user_idle_milliseconds is updated by this method, and is a report
- // of the full amount of time since the last period of activity for the user.
- // The continue_sync_cycle parameter is used to determine whether or not we
- // are calculating a polling wait time that is a continuation of an sync cycle
- // which terminated while the syncer still had work to do. was_nudged is used
- // in case of exponential backoff so we only allow one nudge per backoff
- // interval.
- WaitInterval CalculatePollingWaitTime(
- int last_poll_wait, // in s
- int* user_idle_milliseconds,
- bool* continue_sync_cycle,
- bool was_nudged);
-
- // Helper to above function, considers effect of user idle time.
- virtual int CalculateSyncWaitTime(int last_wait, int user_idle_ms);
-
- // Resets the source tracking state to a clean slate and returns the current
- // state in a SyncSourceInfo.
- // The initial sync boolean is updated if read as a sentinel. The following
- // two methods work in concert to achieve this goal.
- // If |was_throttled| was true, this still discards elapsed nudges, but we
- // treat the request as a periodic poll rather than a nudge from a source.
- // Builds a SyncSourceInfo and returns whether a nudge occurred in the
- // |was_nudged| parameter.
- sessions::SyncSourceInfo GetAndResetNudgeSource(bool was_throttled,
- bool continue_sync_cycle,
- bool* initial_sync,
- bool* was_nudged);
-
- sessions::SyncSourceInfo MakeSyncSourceInfo(
- bool nudged,
- NudgeSource nudge_source,
- const syncable::ModelTypePayloadMap& model_types_with_payloads,
- bool* initial_sync);
-
- int UserIdleTime();
-
- void WaitUntilConnectedOrQuit();
-
- // The thread will remain in this method until a resume is requested
- // or shutdown is started.
- void PauseUntilResumedOrQuit();
-
- void EnterPausedState();
-
- void ExitPausedState();
-
- // For unit tests only.
- virtual void DisableIdleDetection();
-
- // This sets all conditions for syncer thread termination but does not
- // actually join threads. It is expected that Stop will be called at some
- // time after to fully stop and clean up.
- void RequestSyncerExitAndSetThreadStopConditions();
+ // Executes the pending job. Called whenever an event occurs that may
+ // change conditions permitting a job to run. Like when network connection is
+ // re-established, mode changes etc.
+ void DoPendingJobIfPossible(bool is_canary_job);
- void Notify(SyncEngineEvent::EventCause cause);
+ // The pointer is owned by the caller.
+ browser_sync::sessions::SyncSession* CreateSyncSession(
+ const browser_sync::sessions::SyncSourceInfo& info);
+
+ // Creates a session for a poll and performs the sync.
+ void PollTimerCallback();
+
+ // Assign |start| and |end| to appropriate SyncerStep values for the
+ // specified |purpose|.
+ void SetSyncerStepsForPurpose(SyncSessionJob::SyncSessionJobPurpose purpose,
+ SyncerStep* start,
+ SyncerStep* end);
- scoped_ptr<EventListenerHookup> conn_mgr_hookup_;
+ // Initializes the hookup between the ServerConnectionManager and us.
+ void WatchConnectionManager();
+
+ // Used to update |server_connection_ok_|, see below.
+ void CheckServerConnectionManagerStatus(
+ HttpResponse::ServerConnectionCode code);
+
+ // Called once the first time thread_ is started to broadcast an initial
+ // session snapshot containing data like initial_sync_ended. Important when
+ // the client starts up and does not need to perform an initial sync.
+ void SendInitialSnapshot();
+
+ base::Thread thread_;
// Modifiable versions of kDefaultLongPollIntervalSeconds which can be
// updated by the server.
- int syncer_short_poll_interval_seconds_;
- int syncer_long_poll_interval_seconds_;
-
- // The time we wait between polls in seconds. This is used as lower bound on
- // our wait time. Updated once per loop from the command line flag.
- int syncer_polling_interval_;
-
- // The upper bound on the nominal wait between polls in seconds. Note that
- // this bounds the "nominal" poll interval, while the the actual interval
- // also takes previous failures into account.
- int syncer_max_interval_;
-
- // This causes syncer to start syncing ASAP. If the rate of requests is too
- // high the request will be silently dropped. mutex_ should be held when
- // this is called.
- void NudgeSyncImpl(
- int milliseconds_from_now,
- NudgeSource source,
- const syncable::ModelTypePayloadMap& model_types_with_payloads);
-
-#if defined(OS_LINUX)
- // On Linux, we need this information in order to query idle time.
- scoped_ptr<IdleQueryLinux> idle_query_;
-#endif
+ base::TimeDelta syncer_short_poll_interval_seconds_;
+ base::TimeDelta syncer_long_poll_interval_seconds_;
- scoped_ptr<sessions::SyncSessionContext> session_context_;
+ // Periodic timer for polling. See AdjustPolling.
+ base::RepeatingTimer<SyncerThread> poll_timer_;
+
+ // The mode of operation. We don't use a lock, see Start(...) comment.
+ Mode mode_;
+
+ // TODO(tim): Bug 26339. This needs to track more than just time I think,
+ // since the nudges could be for different types. Current impl doesn't care.
+ base::TimeTicks last_sync_session_end_time_;
- // Set whenever the server instructs us to stop sending it requests until
- // a specified time, and reset for each call to SyncShare. (Note that the
- // WaitInterval::THROTTLED contract is such that we don't call SyncShare at
- // all until the "silenced until" embargo expires.)
- base::TimeTicks silenced_until_;
+ // Have we observed a valid server connection?
+ bool server_connection_ok_;
- // Useful for unit tests
- bool disable_idle_detection_;
+ // Tracks in-flight nudges so we can coalesce.
+ scoped_ptr<SyncSessionJob> pending_nudge_;
+
+ // Current wait state. Null if we're not in backoff and not throttled.
+ scoped_ptr<WaitInterval> wait_interval_;
+
+ scoped_ptr<DelayProvider> delay_provider_;
+
+ // Invoked to run through the sync cycle.
+ scoped_ptr<Syncer> syncer_;
+
+ scoped_ptr<sessions::SyncSessionContext> session_context_;
DISALLOW_COPY_AND_ASSIGN(SyncerThread);
};
+
} // namespace browser_sync
+// The SyncerThread manages its own internal thread and thus outlives it. We
+// don't need refcounting for posting tasks to this internal thread.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::SyncerThread);
+
#endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
diff --git a/chrome/browser/sync/engine/syncer_thread2.cc b/chrome/browser/sync/engine/syncer_thread2.cc
deleted file mode 100644
index b8bd9a9..0000000
--- a/chrome/browser/sync/engine/syncer_thread2.cc
+++ /dev/null
@@ -1,863 +0,0 @@
-// 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/engine/syncer_thread2.h"
-
-#include <algorithm>
-
-#include "base/rand_util.h"
-#include "chrome/browser/sync/engine/syncer.h"
-
-using base::TimeDelta;
-using base::TimeTicks;
-
-namespace browser_sync {
-
-using sessions::SyncSession;
-using sessions::SyncSessionSnapshot;
-using sessions::SyncSourceInfo;
-using syncable::ModelTypePayloadMap;
-using syncable::ModelTypeBitSet;
-using sync_pb::GetUpdatesCallerInfo;
-
-namespace s3 {
-
-SyncerThread::DelayProvider::DelayProvider() {}
-SyncerThread::DelayProvider::~DelayProvider() {}
-
-SyncerThread::WaitInterval::WaitInterval() {}
-SyncerThread::WaitInterval::~WaitInterval() {}
-
-SyncerThread::SyncSessionJob::SyncSessionJob() {}
-SyncerThread::SyncSessionJob::~SyncSessionJob() {}
-
-SyncerThread::SyncSessionJob::SyncSessionJob(SyncSessionJobPurpose purpose,
- base::TimeTicks start,
- linked_ptr<sessions::SyncSession> session, bool is_canary_job,
- const tracked_objects::Location& nudge_location) : purpose(purpose),
- scheduled_start(start),
- session(session),
- is_canary_job(is_canary_job),
- nudge_location(nudge_location) {
-}
-
-TimeDelta SyncerThread::DelayProvider::GetDelay(
- const base::TimeDelta& last_delay) {
- return SyncerThread::GetRecommendedDelay(last_delay);
-}
-
-GetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource(
- NudgeSource source) {
- switch (source) {
- case NUDGE_SOURCE_NOTIFICATION:
- return GetUpdatesCallerInfo::NOTIFICATION;
- case NUDGE_SOURCE_LOCAL:
- return GetUpdatesCallerInfo::LOCAL;
- case NUDGE_SOURCE_CONTINUATION:
- return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION;
- case NUDGE_SOURCE_UNKNOWN:
- return GetUpdatesCallerInfo::UNKNOWN;
- default:
- NOTREACHED();
- return GetUpdatesCallerInfo::UNKNOWN;
- }
-}
-
-SyncerThread::WaitInterval::WaitInterval(Mode mode, TimeDelta length)
- : mode(mode), had_nudge(false), length(length) { }
-
-SyncerThread::SyncerThread(sessions::SyncSessionContext* context,
- Syncer* syncer)
- : thread_("SyncEngine_SyncerThread"),
- syncer_short_poll_interval_seconds_(
- TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)),
- syncer_long_poll_interval_seconds_(
- TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)),
- mode_(NORMAL_MODE),
- server_connection_ok_(false),
- delay_provider_(new DelayProvider()),
- syncer_(syncer),
- session_context_(context) {
-}
-
-SyncerThread::~SyncerThread() {
- DCHECK(!thread_.IsRunning());
-}
-
-void SyncerThread::CheckServerConnectionManagerStatus(
- HttpResponse::ServerConnectionCode code) {
-
- VLOG(2) << "SyncerThread(" << this << ")" << " Server connection changed."
- << "Old mode: " << server_connection_ok_ << " Code: " << code;
- // Note, be careful when adding cases here because if the SyncerThread
- // thinks there is no valid connection as determined by this method, it
- // will drop out of *all* forward progress sync loops (it won't poll and it
- // will queue up Talk notifications but not actually call SyncShare) until
- // some external action causes a ServerConnectionManager to broadcast that
- // a valid connection has been re-established.
- if (HttpResponse::CONNECTION_UNAVAILABLE == code ||
- HttpResponse::SYNC_AUTH_ERROR == code) {
- server_connection_ok_ = false;
- VLOG(2) << "SyncerThread(" << this << ")" << " Server connection changed."
- << " new mode:" << server_connection_ok_;
- } else if (HttpResponse::SERVER_CONNECTION_OK == code) {
- server_connection_ok_ = true;
- VLOG(2) << "SyncerThread(" << this << ")" << " Server connection changed."
- << " new mode:" << server_connection_ok_;
- DoCanaryJob();
- }
-}
-
-void SyncerThread::Start(Mode mode, ModeChangeCallback* callback) {
- VLOG(2) << "SyncerThread(" << this << ")" << " Start called from thread "
- << MessageLoop::current()->thread_name();
- if (!thread_.IsRunning()) {
- VLOG(2) << "SyncerThread(" << this << ")" << " Starting thread with mode "
- << mode;
- if (!thread_.Start()) {
- NOTREACHED() << "Unable to start SyncerThread.";
- return;
- }
- WatchConnectionManager();
- thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &SyncerThread::SendInitialSnapshot));
- }
-
- VLOG(2) << "SyncerThread(" << this << ")" << " Entering start with mode = "
- << mode;
-
- thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &SyncerThread::StartImpl, mode, make_linked_ptr(callback)));
-}
-
-void SyncerThread::SendInitialSnapshot() {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- scoped_ptr<SyncSession> dummy(new SyncSession(session_context_.get(), this,
- SyncSourceInfo(), ModelSafeRoutingInfo(),
- std::vector<ModelSafeWorker*>()));
- SyncEngineEvent event(SyncEngineEvent::STATUS_CHANGED);
- sessions::SyncSessionSnapshot snapshot(dummy->TakeSnapshot());
- event.snapshot = &snapshot;
- session_context_->NotifyListeners(event);
-}
-
-void SyncerThread::WatchConnectionManager() {
- ServerConnectionManager* scm = session_context_->connection_manager();
- CheckServerConnectionManagerStatus(scm->server_status());
- scm->AddListener(this);
-}
-
-void SyncerThread::StartImpl(Mode mode,
- linked_ptr<ModeChangeCallback> callback) {
- VLOG(2) << "SyncerThread(" << this << ")" << " Doing StartImpl with mode "
- << mode;
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- DCHECK(!session_context_->account_name().empty());
- DCHECK(syncer_.get());
- mode_ = mode;
- AdjustPolling(NULL); // Will kick start poll timer if needed.
- if (callback.get())
- callback->Run();
-
- // We just changed our mode. See if there are any pending jobs that we could
- // execute in the new mode.
- DoPendingJobIfPossible(false);
-}
-
-SyncerThread::JobProcessDecision SyncerThread::DecideWhileInWaitInterval(
- const SyncSessionJob& job) {
-
- DCHECK(wait_interval_.get());
- DCHECK_NE(job.purpose, SyncSessionJob::CLEAR_USER_DATA);
-
- VLOG(2) << "SyncerThread(" << this << ")" << " Wait interval mode : "
- << wait_interval_->mode << "Wait interval had nudge : "
- << wait_interval_->had_nudge << "is canary job : "
- << job.is_canary_job;
-
- if (job.purpose == SyncSessionJob::POLL)
- return DROP;
-
- DCHECK(job.purpose == SyncSessionJob::NUDGE ||
- job.purpose == SyncSessionJob::CONFIGURATION);
- if (wait_interval_->mode == WaitInterval::THROTTLED)
- return SAVE;
-
- DCHECK_EQ(wait_interval_->mode, WaitInterval::EXPONENTIAL_BACKOFF);
- if (job.purpose == SyncSessionJob::NUDGE) {
- if (mode_ == CONFIGURATION_MODE)
- return SAVE;
-
- // If we already had one nudge then just drop this nudge. We will retry
- // later when the timer runs out.
- return wait_interval_->had_nudge ? DROP : CONTINUE;
- }
- // This is a config job.
- return job.is_canary_job ? CONTINUE : SAVE;
-}
-
-SyncerThread::JobProcessDecision SyncerThread::DecideOnJob(
- const SyncSessionJob& job) {
- if (job.purpose == SyncSessionJob::CLEAR_USER_DATA)
- return CONTINUE;
-
- if (wait_interval_.get())
- return DecideWhileInWaitInterval(job);
-
- if (mode_ == CONFIGURATION_MODE) {
- if (job.purpose == SyncSessionJob::NUDGE)
- return SAVE;
- else if (job.purpose == SyncSessionJob::CONFIGURATION)
- return CONTINUE;
- else
- return DROP;
- }
-
- // We are in normal mode.
- DCHECK_EQ(mode_, NORMAL_MODE);
- DCHECK_NE(job.purpose, SyncSessionJob::CONFIGURATION);
-
- // Freshness condition
- if (job.scheduled_start < last_sync_session_end_time_) {
- VLOG(2) << "SyncerThread(" << this << ")"
- << " Dropping job because of freshness";
- return DROP;
- }
-
- if (server_connection_ok_)
- return CONTINUE;
-
- VLOG(2) << "SyncerThread(" << this << ")"
- << " Bad server connection. Using that to decide on job.";
- return job.purpose == SyncSessionJob::NUDGE ? SAVE : DROP;
-}
-
-void SyncerThread::InitOrCoalescePendingJob(const SyncSessionJob& job) {
- DCHECK(job.purpose != SyncSessionJob::CONFIGURATION);
- if (pending_nudge_.get() == NULL) {
- VLOG(2) << "SyncerThread(" << this << ")"
- << " Creating a pending nudge job";
- SyncSession* s = job.session.get();
- scoped_ptr<SyncSession> session(new SyncSession(s->context(),
- s->delegate(), s->source(), s->routing_info(), s->workers()));
-
- SyncSessionJob new_job(SyncSessionJob::NUDGE, job.scheduled_start,
- make_linked_ptr(session.release()), false, job.nudge_location);
- pending_nudge_.reset(new SyncSessionJob(new_job));
-
- return;
- }
-
- VLOG(2) << "SyncerThread(" << this << ")" << " Coalescing a pending nudge";
- pending_nudge_->session->Coalesce(*(job.session.get()));
- pending_nudge_->scheduled_start = job.scheduled_start;
-
- // Unfortunately the nudge location cannot be modified. So it stores the
- // location of the first caller.
-}
-
-bool SyncerThread::ShouldRunJob(const SyncSessionJob& job) {
- JobProcessDecision decision = DecideOnJob(job);
- VLOG(2) << "SyncerThread(" << this << ")" << " Should run job, decision: "
- << decision << " Job purpose " << job.purpose << "mode " << mode_;
- if (decision != SAVE)
- return decision == CONTINUE;
-
- DCHECK(job.purpose == SyncSessionJob::NUDGE || job.purpose ==
- SyncSessionJob::CONFIGURATION);
-
- SaveJob(job);
- return false;
-}
-
-void SyncerThread::SaveJob(const SyncSessionJob& job) {
- DCHECK(job.purpose != SyncSessionJob::CLEAR_USER_DATA);
- if (job.purpose == SyncSessionJob::NUDGE) {
- VLOG(2) << "SyncerThread(" << this << ")" << " Saving a nudge job";
- InitOrCoalescePendingJob(job);
- } else if (job.purpose == SyncSessionJob::CONFIGURATION){
- VLOG(2) << "SyncerThread(" << this << ")" << " Saving a configuration job";
- DCHECK(wait_interval_.get());
- DCHECK(mode_ == CONFIGURATION_MODE);
-
- SyncSession* old = job.session.get();
- SyncSession* s(new SyncSession(session_context_.get(), this,
- old->source(), old->routing_info(), old->workers()));
- SyncSessionJob new_job(job.purpose, TimeTicks::Now(),
- make_linked_ptr(s), false, job.nudge_location);
- wait_interval_->pending_configure_job.reset(new SyncSessionJob(new_job));
- } // drop the rest.
-}
-
-// Functor for std::find_if to search by ModelSafeGroup.
-struct ModelSafeWorkerGroupIs {
- explicit ModelSafeWorkerGroupIs(ModelSafeGroup group) : group(group) {}
- bool operator()(ModelSafeWorker* w) {
- return group == w->GetModelSafeGroup();
- }
- ModelSafeGroup group;
-};
-
-void SyncerThread::ScheduleClearUserData() {
- if (!thread_.IsRunning()) {
- NOTREACHED();
- return;
- }
- thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &SyncerThread::ScheduleClearUserDataImpl));
-}
-
-void SyncerThread::ScheduleNudge(const TimeDelta& delay,
- NudgeSource source, const ModelTypeBitSet& types,
- const tracked_objects::Location& nudge_location) {
- if (!thread_.IsRunning()) {
- NOTREACHED();
- return;
- }
-
- VLOG(2) << "SyncerThread(" << this << ")" << " Nudge scheduled";
-
- ModelTypePayloadMap types_with_payloads =
- syncable::ModelTypePayloadMapFromBitSet(types, std::string());
- thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &SyncerThread::ScheduleNudgeImpl, delay,
- GetUpdatesFromNudgeSource(source), types_with_payloads, false,
- nudge_location));
-}
-
-void SyncerThread::ScheduleNudgeWithPayloads(const TimeDelta& delay,
- NudgeSource source, const ModelTypePayloadMap& types_with_payloads,
- const tracked_objects::Location& nudge_location) {
- if (!thread_.IsRunning()) {
- NOTREACHED();
- return;
- }
-
- VLOG(2) << "SyncerThread(" << this << ")" << " Nudge scheduled with payloads";
-
- thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &SyncerThread::ScheduleNudgeImpl, delay,
- GetUpdatesFromNudgeSource(source), types_with_payloads, false,
- nudge_location));
-}
-
-void SyncerThread::ScheduleClearUserDataImpl() {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- SyncSession* session = new SyncSession(session_context_.get(), this,
- SyncSourceInfo(), ModelSafeRoutingInfo(),
- std::vector<ModelSafeWorker*>());
- ScheduleSyncSessionJob(TimeDelta::FromSeconds(0),
- SyncSessionJob::CLEAR_USER_DATA, session, FROM_HERE);
-}
-
-void SyncerThread::ScheduleNudgeImpl(const TimeDelta& delay,
- GetUpdatesCallerInfo::GetUpdatesSource source,
- const ModelTypePayloadMap& types_with_payloads,
- bool is_canary_job, const tracked_objects::Location& nudge_location) {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
-
- VLOG(2) << "SyncerThread(" << this << ")" << " Running Schedule nudge impl";
- // Note we currently nudge for all types regardless of the ones incurring
- // the nudge. Doing different would throw off some syncer commands like
- // CleanupDisabledTypes. We may want to change this in the future.
- SyncSourceInfo info(source, types_with_payloads);
-
- SyncSession* session(CreateSyncSession(info));
- SyncSessionJob job(SyncSessionJob::NUDGE, TimeTicks::Now() + delay,
- make_linked_ptr(session), is_canary_job,
- nudge_location);
-
- session = NULL;
- if (!ShouldRunJob(job))
- return;
-
- if (pending_nudge_.get()) {
- if (IsBackingOff() && delay > TimeDelta::FromSeconds(1)) {
- VLOG(2) << "SyncerThread(" << this << ")" << " Dropping the nudge because"
- << "we are in backoff";
- return;
- }
-
- VLOG(2) << "SyncerThread(" << this << ")" << " Coalescing pending nudge";
- pending_nudge_->session->Coalesce(*(job.session.get()));
-
- if (!IsBackingOff()) {
- VLOG(2) << "SyncerThread(" << this << ")" << " Dropping a nudge because"
- << " we are not in backoff and the job was coalesced";
- return;
- } else {
- VLOG(2) << "SyncerThread(" << this << ")"
- << " Rescheduling pending nudge";
- SyncSession* s = pending_nudge_->session.get();
- job.session.reset(new SyncSession(s->context(), s->delegate(),
- s->source(), s->routing_info(), s->workers()));
- pending_nudge_.reset();
- }
- }
-
- // TODO(lipalani) - pass the job itself to ScheduleSyncSessionJob.
- ScheduleSyncSessionJob(delay, SyncSessionJob::NUDGE, job.session.release(),
- nudge_location);
-}
-
-// Helper to extract the routing info and workers corresponding to types in
-// |types| from |registrar|.
-void GetModelSafeParamsForTypes(const ModelTypeBitSet& types,
- ModelSafeWorkerRegistrar* registrar, ModelSafeRoutingInfo* routes,
- std::vector<ModelSafeWorker*>* workers) {
- ModelSafeRoutingInfo r_tmp;
- std::vector<ModelSafeWorker*> w_tmp;
- registrar->GetModelSafeRoutingInfo(&r_tmp);
- registrar->GetWorkers(&w_tmp);
-
- typedef std::vector<ModelSafeWorker*>::const_iterator iter;
- for (size_t i = syncable::FIRST_REAL_MODEL_TYPE; i < types.size(); ++i) {
- if (!types.test(i))
- continue;
- syncable::ModelType t = syncable::ModelTypeFromInt(i);
- DCHECK_EQ(1U, r_tmp.count(t));
- (*routes)[t] = r_tmp[t];
- iter it = std::find_if(w_tmp.begin(), w_tmp.end(),
- ModelSafeWorkerGroupIs(r_tmp[t]));
- if (it != w_tmp.end())
- workers->push_back(*it);
- else
- NOTREACHED();
- }
-
- iter it = std::find_if(w_tmp.begin(), w_tmp.end(),
- ModelSafeWorkerGroupIs(GROUP_PASSIVE));
- if (it != w_tmp.end())
- workers->push_back(*it);
- else
- NOTREACHED();
-}
-
-void SyncerThread::ScheduleConfig(const ModelTypeBitSet& types) {
- if (!thread_.IsRunning()) {
- NOTREACHED();
- return;
- }
-
- VLOG(2) << "SyncerThread(" << this << ")" << " Scheduling a config";
- ModelSafeRoutingInfo routes;
- std::vector<ModelSafeWorker*> workers;
- GetModelSafeParamsForTypes(types, session_context_->registrar(),
- &routes, &workers);
-
- thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &SyncerThread::ScheduleConfigImpl, routes, workers,
- GetUpdatesCallerInfo::FIRST_UPDATE));
-}
-
-void SyncerThread::ScheduleConfigImpl(const ModelSafeRoutingInfo& routing_info,
- const std::vector<ModelSafeWorker*>& workers,
- const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source) {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
-
- VLOG(2) << "SyncerThread(" << this << ")" << " ScheduleConfigImpl...";
- // TODO(tim): config-specific GetUpdatesCallerInfo value?
- SyncSession* session = new SyncSession(session_context_.get(), this,
- SyncSourceInfo(source,
- syncable::ModelTypePayloadMapFromRoutingInfo(
- routing_info, std::string())),
- routing_info, workers);
- ScheduleSyncSessionJob(TimeDelta::FromSeconds(0),
- SyncSessionJob::CONFIGURATION, session, FROM_HERE);
-}
-
-void SyncerThread::ScheduleSyncSessionJob(const base::TimeDelta& delay,
- SyncSessionJob::SyncSessionJobPurpose purpose,
- sessions::SyncSession* session,
- const tracked_objects::Location& nudge_location) {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
-
- SyncSessionJob job(purpose, TimeTicks::Now() + delay,
- make_linked_ptr(session), false, nudge_location);
- if (purpose == SyncSessionJob::NUDGE) {
- VLOG(2) << "SyncerThread(" << this << ")" << " Resetting pending_nudge in"
- << " ScheduleSyncSessionJob";
- DCHECK(!pending_nudge_.get() || pending_nudge_->session.get() == session);
- pending_nudge_.reset(new SyncSessionJob(job));
- }
- VLOG(2) << "SyncerThread(" << this << ")"
- << " Posting job to execute in DoSyncSessionJob. Job purpose "
- << job.purpose;
- MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(this,
- &SyncerThread::DoSyncSessionJob, job),
- delay.InMilliseconds());
-}
-
-void SyncerThread::SetSyncerStepsForPurpose(
- SyncSessionJob::SyncSessionJobPurpose purpose,
- SyncerStep* start, SyncerStep* end) {
- *end = SYNCER_END;
- switch (purpose) {
- case SyncSessionJob::CONFIGURATION:
- *start = DOWNLOAD_UPDATES;
- *end = APPLY_UPDATES;
- return;
- case SyncSessionJob::CLEAR_USER_DATA:
- *start = CLEAR_PRIVATE_DATA;
- return;
- case SyncSessionJob::NUDGE:
- case SyncSessionJob::POLL:
- *start = SYNCER_BEGIN;
- return;
- default:
- NOTREACHED();
- }
-}
-
-void SyncerThread::DoSyncSessionJob(const SyncSessionJob& job) {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- if (!ShouldRunJob(job))
- return;
-
- if (job.purpose == SyncSessionJob::NUDGE) {
- DCHECK(pending_nudge_.get());
- if (pending_nudge_->session != job.session)
- return; // Another nudge must have been scheduled in in the meantime.
- pending_nudge_.reset();
- }
- VLOG(2) << "SyncerThread(" << this << ")" << " DoSyncSessionJob. job purpose "
- << job.purpose;
-
- SyncerStep begin(SYNCER_BEGIN);
- SyncerStep end(SYNCER_END);
- SetSyncerStepsForPurpose(job.purpose, &begin, &end);
-
- bool has_more_to_sync = true;
- while (ShouldRunJob(job) && has_more_to_sync) {
- VLOG(2) << "SyncerThread(" << this << ")"
- << " SyncerThread: Calling SyncShare.";
- // Synchronously perform the sync session from this thread.
- syncer_->SyncShare(job.session.get(), begin, end);
- has_more_to_sync = job.session->HasMoreToSync();
- if (has_more_to_sync)
- job.session->ResetTransientState();
- }
- VLOG(2) << "SyncerThread(" << this << ")"
- << " SyncerThread: Done SyncShare looping.";
- FinishSyncSessionJob(job);
-}
-
-void SyncerThread::UpdateCarryoverSessionState(const SyncSessionJob& old_job) {
- if (old_job.purpose == SyncSessionJob::CONFIGURATION) {
- // Whatever types were part of a configuration task will have had updates
- // downloaded. For that reason, we make sure they get recorded in the
- // event that they get disabled at a later time.
- ModelSafeRoutingInfo r(session_context_->previous_session_routing_info());
- if (!r.empty()) {
- ModelSafeRoutingInfo temp_r;
- ModelSafeRoutingInfo old_info(old_job.session->routing_info());
- std::set_union(r.begin(), r.end(), old_info.begin(), old_info.end(),
- std::insert_iterator<ModelSafeRoutingInfo>(temp_r, temp_r.begin()));
- session_context_->set_previous_session_routing_info(temp_r);
- }
- } else {
- session_context_->set_previous_session_routing_info(
- old_job.session->routing_info());
- }
-}
-
-void SyncerThread::FinishSyncSessionJob(const SyncSessionJob& job) {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- // Update timing information for how often datatypes are triggering nudges.
- base::TimeTicks now = TimeTicks::Now();
- if (!last_sync_session_end_time_.is_null()) {
- ModelTypePayloadMap::const_iterator iter;
- for (iter = job.session->source().types.begin();
- iter != job.session->source().types.end();
- ++iter) {
- syncable::PostTimeToTypeHistogram(iter->first,
- now - last_sync_session_end_time_);
- }
- }
- last_sync_session_end_time_ = now;
- UpdateCarryoverSessionState(job);
- if (IsSyncingCurrentlySilenced()) {
- VLOG(2) << "SyncerThread(" << this << ")"
- << " We are currently throttled. So not scheduling the next sync.";
- SaveJob(job);
- return; // Nothing to do.
- }
-
- VLOG(2) << "SyncerThread(" << this << ")"
- << " Updating the next polling time after SyncMain";
- ScheduleNextSync(job);
-}
-
-void SyncerThread::ScheduleNextSync(const SyncSessionJob& old_job) {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- DCHECK(!old_job.session->HasMoreToSync());
- // Note: |num_server_changes_remaining| > 0 here implies that we received a
- // broken response while trying to download all updates, because the Syncer
- // will loop until this value is exhausted. Also, if unsynced_handles exist
- // but HasMoreToSync is false, this implies that the Syncer determined no
- // forward progress was possible at this time (an error, such as an HTTP
- // 500, is likely to have occurred during commit).
- const bool work_to_do =
- old_job.session->status_controller()->num_server_changes_remaining() > 0
- || old_job.session->status_controller()->unsynced_handles().size() > 0;
- VLOG(2) << "SyncerThread(" << this << ")" << " syncer has work to do: "
- << work_to_do;
-
- AdjustPolling(&old_job);
-
- // TODO(tim): Old impl had special code if notifications disabled. Needed?
- if (!work_to_do) {
- // Success implies backoff relief. Note that if this was a "one-off" job
- // (i.e. purpose == SyncSessionJob::CLEAR_USER_DATA), if there was
- // work_to_do before it ran this wont have changed, as jobs like this don't
- // run a full sync cycle. So we don't need special code here.
- wait_interval_.reset();
- VLOG(2) << "SyncerThread(" << this << ")"
- << " Job suceeded so not scheduling more jobs";
- return;
- }
-
- if (old_job.session->source().updates_source ==
- GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION) {
- VLOG(2) << "SyncerThread(" << this << ")"
- << " Job failed with source continuation";
- // We don't seem to have made forward progress. Start or extend backoff.
- HandleConsecutiveContinuationError(old_job);
- } else if (IsBackingOff()) {
- VLOG(2) << "SyncerThread(" << this << ")"
- << " A nudge during backoff failed";
- // We weren't continuing but we're in backoff; must have been a nudge.
- DCHECK_EQ(SyncSessionJob::NUDGE, old_job.purpose);
- DCHECK(!wait_interval_->had_nudge);
- wait_interval_->had_nudge = true;
- wait_interval_->timer.Reset();
- } else {
- VLOG(2) << "SyncerThread(" << this << ")"
- << " Failed. Schedule a job with continuation as source";
- // We weren't continuing and we aren't in backoff. Schedule a normal
- // continuation.
- if (old_job.purpose == SyncSessionJob::CONFIGURATION) {
- ScheduleConfigImpl(old_job.session->routing_info(),
- old_job.session->workers(),
- GetUpdatesFromNudgeSource(NUDGE_SOURCE_CONTINUATION));
- } else {
- // For all other purposes(nudge and poll) we schedule a retry nudge.
- ScheduleNudgeImpl(TimeDelta::FromSeconds(0),
- GetUpdatesFromNudgeSource(NUDGE_SOURCE_CONTINUATION),
- old_job.session->source().types, false, FROM_HERE);
- }
- }
-}
-
-void SyncerThread::AdjustPolling(const SyncSessionJob* old_job) {
- DCHECK(thread_.IsRunning());
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
-
- TimeDelta poll = (!session_context_->notifications_enabled()) ?
- syncer_short_poll_interval_seconds_ :
- syncer_long_poll_interval_seconds_;
- bool rate_changed = !poll_timer_.IsRunning() ||
- poll != poll_timer_.GetCurrentDelay();
-
- if (old_job && old_job->purpose != SyncSessionJob::POLL && !rate_changed)
- poll_timer_.Reset();
-
- if (!rate_changed)
- return;
-
- // Adjust poll rate.
- poll_timer_.Stop();
- poll_timer_.Start(poll, this, &SyncerThread::PollTimerCallback);
-}
-
-void SyncerThread::HandleConsecutiveContinuationError(
- const SyncSessionJob& old_job) {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- // This if conditions should be compiled out in retail builds.
- if (IsBackingOff()) {
- DCHECK(wait_interval_->timer.IsRunning() || old_job.is_canary_job);
- }
- SyncSession* old = old_job.session.get();
- SyncSession* s(new SyncSession(session_context_.get(), this,
- old->source(), old->routing_info(), old->workers()));
- TimeDelta length = delay_provider_->GetDelay(
- IsBackingOff() ? wait_interval_->length : TimeDelta::FromSeconds(1));
-
- VLOG(2) << "SyncerThread(" << this << ")"
- << " In handle continuation error. Old job purpose is "
- << old_job.purpose;
- VLOG(2) << "SyncerThread(" << this << ")"
- << " In Handle continuation error. The time delta(ms) is: "
- << length.InMilliseconds();
-
- // This will reset the had_nudge variable as well.
- wait_interval_.reset(new WaitInterval(WaitInterval::EXPONENTIAL_BACKOFF,
- length));
- if (old_job.purpose == SyncSessionJob::CONFIGURATION) {
- SyncSessionJob job(old_job.purpose, TimeTicks::Now() + length,
- make_linked_ptr(s), false, FROM_HERE);
- wait_interval_->pending_configure_job.reset(new SyncSessionJob(job));
- } else {
- // We are not in configuration mode. So wait_interval's pending job
- // should be null.
- DCHECK(wait_interval_->pending_configure_job.get() == NULL);
-
- // TODO(lipalani) - handle clear user data.
- InitOrCoalescePendingJob(old_job);
- }
- wait_interval_->timer.Start(length, this, &SyncerThread::DoCanaryJob);
-}
-
-// static
-TimeDelta SyncerThread::GetRecommendedDelay(const TimeDelta& last_delay) {
- if (last_delay.InSeconds() >= kMaxBackoffSeconds)
- return TimeDelta::FromSeconds(kMaxBackoffSeconds);
-
- // This calculates approx. base_delay_seconds * 2 +/- base_delay_seconds / 2
- int64 backoff_s =
- std::max(static_cast<int64>(1),
- last_delay.InSeconds() * kBackoffRandomizationFactor);
-
- // Flip a coin to randomize backoff interval by +/- 50%.
- int rand_sign = base::RandInt(0, 1) * 2 - 1;
-
- // Truncation is adequate for rounding here.
- backoff_s = backoff_s +
- (rand_sign * (last_delay.InSeconds() / kBackoffRandomizationFactor));
-
- // Cap the backoff interval.
- backoff_s = std::max(static_cast<int64>(1),
- std::min(backoff_s, kMaxBackoffSeconds));
-
- return TimeDelta::FromSeconds(backoff_s);
-}
-
-void SyncerThread::Stop() {
- VLOG(2) << "SyncerThread(" << this << ")" << " stop called";
- syncer_->RequestEarlyExit(); // Safe to call from any thread.
- session_context_->connection_manager()->RemoveListener(this);
- thread_.Stop();
-}
-
-void SyncerThread::DoCanaryJob() {
- VLOG(2) << "SyncerThread(" << this << ")" << " Do canary job";
- DoPendingJobIfPossible(true);
-}
-
-void SyncerThread::DoPendingJobIfPossible(bool is_canary_job) {
- SyncSessionJob* job_to_execute = NULL;
- if (mode_ == CONFIGURATION_MODE && wait_interval_.get()
- && wait_interval_->pending_configure_job.get()) {
- VLOG(2) << "SyncerThread(" << this << ")" << " Found pending configure job";
- job_to_execute = wait_interval_->pending_configure_job.get();
- } else if (mode_ == NORMAL_MODE && pending_nudge_.get()) {
- VLOG(2) << "SyncerThread(" << this << ")" << " Found pending nudge job";
- // Pending jobs mostly have time from the past. Reset it so this job
- // will get executed.
- if (pending_nudge_->scheduled_start < TimeTicks::Now())
- pending_nudge_->scheduled_start = TimeTicks::Now();
-
- scoped_ptr<SyncSession> session(CreateSyncSession(
- pending_nudge_->session->source()));
-
- // Also the routing info might have been changed since we cached the
- // pending nudge. Update it by coalescing to the latest.
- pending_nudge_->session->Coalesce(*(session.get()));
- // The pending nudge would be cleared in the DoSyncSessionJob function.
- job_to_execute = pending_nudge_.get();
- }
-
- if (job_to_execute != NULL) {
- VLOG(2) << "SyncerThread(" << this << ")" << " Executing pending job";
- SyncSessionJob copy = *job_to_execute;
- copy.is_canary_job = is_canary_job;
- DoSyncSessionJob(copy);
- }
-}
-
-SyncSession* SyncerThread::CreateSyncSession(const SyncSourceInfo& source) {
- ModelSafeRoutingInfo routes;
- std::vector<ModelSafeWorker*> workers;
- session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
- session_context_->registrar()->GetWorkers(&workers);
- SyncSourceInfo info(source);
-
- SyncSession* session(new SyncSession(session_context_.get(), this, info,
- routes, workers));
-
- return session;
-}
-
-void SyncerThread::PollTimerCallback() {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- ModelSafeRoutingInfo r;
- ModelTypePayloadMap types_with_payloads =
- syncable::ModelTypePayloadMapFromRoutingInfo(r, std::string());
- SyncSourceInfo info(GetUpdatesCallerInfo::PERIODIC, types_with_payloads);
- SyncSession* s = CreateSyncSession(info);
- ScheduleSyncSessionJob(TimeDelta::FromSeconds(0), SyncSessionJob::POLL, s,
- FROM_HERE);
-}
-
-void SyncerThread::Unthrottle() {
- DCHECK_EQ(WaitInterval::THROTTLED, wait_interval_->mode);
- VLOG(2) << "SyncerThread(" << this << ")" << " Unthrottled..";
- DoCanaryJob();
- wait_interval_.reset();
-}
-
-void SyncerThread::Notify(SyncEngineEvent::EventCause cause) {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- session_context_->NotifyListeners(SyncEngineEvent(cause));
-}
-
-bool SyncerThread::IsBackingOff() const {
- return wait_interval_.get() && wait_interval_->mode ==
- WaitInterval::EXPONENTIAL_BACKOFF;
-}
-
-void SyncerThread::OnSilencedUntil(const base::TimeTicks& silenced_until) {
- wait_interval_.reset(new WaitInterval(WaitInterval::THROTTLED,
- silenced_until - TimeTicks::Now()));
- wait_interval_->timer.Start(wait_interval_->length, this,
- &SyncerThread::Unthrottle);
-}
-
-bool SyncerThread::IsSyncingCurrentlySilenced() {
- return wait_interval_.get() && wait_interval_->mode ==
- WaitInterval::THROTTLED;
-}
-
-void SyncerThread::OnReceivedShortPollIntervalUpdate(
- const base::TimeDelta& new_interval) {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- syncer_short_poll_interval_seconds_ = new_interval;
-}
-
-void SyncerThread::OnReceivedLongPollIntervalUpdate(
- const base::TimeDelta& new_interval) {
- DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
- syncer_long_poll_interval_seconds_ = new_interval;
-}
-
-void SyncerThread::OnShouldStopSyncingPermanently() {
- VLOG(2) << "SyncerThread(" << this << ")"
- << " OnShouldStopSyncingPermanently";
- syncer_->RequestEarlyExit(); // Thread-safe.
- Notify(SyncEngineEvent::STOP_SYNCING_PERMANENTLY);
-}
-
-void SyncerThread::OnServerConnectionEvent(
- const ServerConnectionEvent2& event) {
- thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this,
- &SyncerThread::CheckServerConnectionManagerStatus,
- event.connection_code));
-}
-
-void SyncerThread::set_notifications_enabled(bool notifications_enabled) {
- session_context_->set_notifications_enabled(notifications_enabled);
-}
-
-} // s3
-} // browser_sync
diff --git a/chrome/browser/sync/engine/syncer_thread2.h b/chrome/browser/sync/engine/syncer_thread2.h
deleted file mode 100644
index 1c698db..0000000
--- a/chrome/browser/sync/engine/syncer_thread2.h
+++ /dev/null
@@ -1,344 +0,0 @@
-// 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.
-//
-// A class to run the syncer on a thread.
-#ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD2_H_
-#define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD2_H_
-#pragma once
-
-#include "base/callback.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/observer_list.h"
-#include "base/task.h"
-#include "base/threading/thread.h"
-#include "base/time.h"
-#include "base/timer.h"
-#include "chrome/browser/sync/engine/nudge_source.h"
-#include "chrome/browser/sync/engine/polling_constants.h"
-#include "chrome/browser/sync/engine/syncer.h"
-#include "chrome/browser/sync/syncable/model_type_payload_map.h"
-#include "chrome/browser/sync/engine/net/server_connection_manager.h"
-#include "chrome/browser/sync/sessions/sync_session.h"
-#include "chrome/browser/sync/sessions/sync_session_context.h"
-
-namespace browser_sync {
-
-struct ServerConnectionEvent;
-
-namespace s3 {
-
-class SyncerThread : public sessions::SyncSession::Delegate,
- public ServerConnectionEventListener {
- public:
- enum Mode {
- // In this mode, the thread only performs configuration tasks. This is
- // designed to make the case where we want to download updates for a
- // specific type only, and not continue syncing until we are moved into
- // normal mode.
- CONFIGURATION_MODE,
- // Resumes polling and allows nudges, drops configuration tasks. Runs
- // through entire sync cycle.
- NORMAL_MODE,
- };
-
- // Takes ownership of both |context| and |syncer|.
- SyncerThread(sessions::SyncSessionContext* context, Syncer* syncer);
- virtual ~SyncerThread();
-
- typedef Callback0::Type ModeChangeCallback;
-
- // Change the mode of operation.
- // We don't use a lock when changing modes, so we won't cause currently
- // scheduled jobs to adhere to the new mode. We could protect it, but it
- // doesn't buy very much as a) a session could already be in progress and it
- // will continue no matter what, b) the scheduled sessions already contain
- // all their required state and won't be affected by potential change at
- // higher levels (i.e. the registrar), and c) we service tasks FIFO, so once
- // the mode changes all future jobs will be run against the updated mode.
- // If supplied, |callback| will be invoked when the mode has been
- // changed to |mode| *from the SyncerThread*, and not from the caller
- // thread.
- void Start(Mode mode, ModeChangeCallback* callback);
-
- // Joins on the thread as soon as possible (currently running session
- // completes).
- void Stop();
-
- // The meat and potatoes.
- void ScheduleNudge(const base::TimeDelta& delay, NudgeSource source,
- const syncable::ModelTypeBitSet& types,
- const tracked_objects::Location& nudge_location);
- void ScheduleNudgeWithPayloads(
- const base::TimeDelta& delay, NudgeSource source,
- const syncable::ModelTypePayloadMap& types_with_payloads,
- const tracked_objects::Location& nudge_location);
- void ScheduleConfig(const syncable::ModelTypeBitSet& types);
- void ScheduleClearUserData();
-
- // Change status of notifications in the SyncSessionContext.
- void set_notifications_enabled(bool notifications_enabled);
-
- // DDOS avoidance function. Calculates how long we should wait before trying
- // again after a failed sync attempt, where the last delay was |base_delay|.
- // TODO(tim): Look at URLRequestThrottlerEntryInterface.
- static base::TimeDelta GetRecommendedDelay(const base::TimeDelta& base_delay);
-
- // SyncSession::Delegate implementation.
- virtual void OnSilencedUntil(const base::TimeTicks& silenced_until);
- virtual bool IsSyncingCurrentlySilenced();
- virtual void OnReceivedShortPollIntervalUpdate(
- const base::TimeDelta& new_interval);
- virtual void OnReceivedLongPollIntervalUpdate(
- const base::TimeDelta& new_interval);
- virtual void OnShouldStopSyncingPermanently();
-
- // ServerConnectionEventListener implementation.
- // TODO(tim): schedule a nudge when valid connection detected? in 1 minute?
- virtual void OnServerConnectionEvent(const ServerConnectionEvent2& event);
-
- private:
- enum JobProcessDecision {
- // Indicates we should continue with the current job.
- CONTINUE,
- // Indicates that we should save it to be processed later.
- SAVE,
- // Indicates we should drop this job.
- DROP,
- };
-
- struct SyncSessionJob {
- // An enum used to describe jobs for scheduling purposes.
- enum SyncSessionJobPurpose {
- // Our poll timer schedules POLL jobs periodically based on a server
- // assigned poll interval.
- POLL,
- // A nudge task can come from a variety of components needing to force
- // a sync. The source is inferable from |session.source()|.
- NUDGE,
- // The user invoked a function in the UI to clear their entire account
- // and stop syncing (globally).
- CLEAR_USER_DATA,
- // Typically used for fetching updates for a subset of the enabled types
- // during initial sync or reconfiguration. We don't run all steps of
- // the sync cycle for these (e.g. CleanupDisabledTypes is skipped).
- CONFIGURATION,
- };
- SyncSessionJob();
- SyncSessionJob(SyncSessionJobPurpose purpose, base::TimeTicks start,
- linked_ptr<sessions::SyncSession> session, bool is_canary_job,
- const tracked_objects::Location& nudge_location);
- ~SyncSessionJob();
- SyncSessionJobPurpose purpose;
- base::TimeTicks scheduled_start;
- linked_ptr<sessions::SyncSession> session;
- bool is_canary_job;
-
- // This is the location the nudge came from. used for debugging purpose.
- // In case of multiple nudges getting coalesced this stores the first nudge
- // that came in.
- tracked_objects::Location nudge_location;
- };
- friend class SyncerThread2Test;
- friend class SyncerThread2WhiteboxTest;
-
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
- DropNudgeWhileExponentialBackOff);
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, SaveNudge);
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueNudge);
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, DropPoll);
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinuePoll);
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueConfiguration);
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
- SaveConfigurationWhileThrottled);
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
- SaveNudgeWhileThrottled);
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
- ContinueClearUserDataUnderAllCircumstances);
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
- ContinueCanaryJobConfig);
- FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
- ContinueNudgeWhileExponentialBackOff);
-
- // A component used to get time delays associated with exponential backoff.
- // Encapsulated into a class to facilitate testing.
- class DelayProvider {
- public:
- DelayProvider();
- virtual base::TimeDelta GetDelay(const base::TimeDelta& last_delay);
- virtual ~DelayProvider();
- private:
- DISALLOW_COPY_AND_ASSIGN(DelayProvider);
- };
-
- struct WaitInterval {
- enum Mode {
- // A wait interval whose duration has been affected by exponential
- // backoff.
- // EXPONENTIAL_BACKOFF intervals are nudge-rate limited to 1 per interval.
- EXPONENTIAL_BACKOFF,
- // A server-initiated throttled interval. We do not allow any syncing
- // during such an interval.
- THROTTLED,
- };
- WaitInterval();
- ~WaitInterval();
-
- Mode mode;
-
- // This bool is set to true if we have observed a nudge during this
- // interval and mode == EXPONENTIAL_BACKOFF.
- bool had_nudge;
- base::TimeDelta length;
- base::OneShotTimer<SyncerThread> timer;
-
- // Configure jobs are saved only when backing off or throttling. So we
- // expose the pointer here.
- scoped_ptr<SyncSessionJob> pending_configure_job;
- WaitInterval(Mode mode, base::TimeDelta length);
- };
-
- // Helper to assemble a job and post a delayed task to sync.
- void ScheduleSyncSessionJob(
- const base::TimeDelta& delay,
- SyncSessionJob::SyncSessionJobPurpose purpose,
- sessions::SyncSession* session,
- const tracked_objects::Location& nudge_location);
-
- // Invoke the Syncer to perform a sync.
- void DoSyncSessionJob(const SyncSessionJob& job);
-
- // Called after the Syncer has performed the sync represented by |job|, to
- // reset our state.
- void FinishSyncSessionJob(const SyncSessionJob& job);
-
- // Record important state that might be needed in future syncs, such as which
- // data types may require cleanup.
- void UpdateCarryoverSessionState(const SyncSessionJob& old_job);
-
- // Helper to FinishSyncSessionJob to schedule the next sync operation.
- void ScheduleNextSync(const SyncSessionJob& old_job);
-
- // Helper to configure polling intervals. Used by Start and ScheduleNextSync.
- void AdjustPolling(const SyncSessionJob* old_job);
-
- // Helper to ScheduleNextSync in case of consecutive sync errors.
- void HandleConsecutiveContinuationError(const SyncSessionJob& old_job);
-
- // Determines if it is legal to run |job| by checking current
- // operational mode, backoff or throttling, freshness
- // (so we don't make redundant syncs), and connection.
- bool ShouldRunJob(const SyncSessionJob& job);
-
- // Decide whether we should CONTINUE, SAVE or DROP the job.
- JobProcessDecision DecideOnJob(const SyncSessionJob& job);
-
- // Decide on whether to CONTINUE, SAVE or DROP the job when we are in
- // backoff mode.
- JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job);
-
- // Saves the job for future execution. Note: It drops all the poll jobs.
- void SaveJob(const SyncSessionJob& job);
-
- // Coalesces the current job with the pending nudge.
- void InitOrCoalescePendingJob(const SyncSessionJob& job);
-
- // 'Impl' here refers to real implementation of public functions, running on
- // |thread_|.
- void StartImpl(Mode mode, linked_ptr<ModeChangeCallback> callback);
- void ScheduleNudgeImpl(
- const base::TimeDelta& delay,
- sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
- const syncable::ModelTypePayloadMap& types_with_payloads,
- bool is_canary_job, const tracked_objects::Location& nudge_location);
- void ScheduleConfigImpl(const ModelSafeRoutingInfo& routing_info,
- const std::vector<ModelSafeWorker*>& workers,
- const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source);
- void ScheduleClearUserDataImpl();
-
- // Returns true if the client is currently in exponential backoff.
- bool IsBackingOff() const;
-
- // Helper to signal all listeners registered with |session_context_|.
- void Notify(SyncEngineEvent::EventCause cause);
-
- // Callback to change backoff state.
- void DoCanaryJob();
- void Unthrottle();
-
- // Executes the pending job. Called whenever an event occurs that may
- // change conditions permitting a job to run. Like when network connection is
- // re-established, mode changes etc.
- void DoPendingJobIfPossible(bool is_canary_job);
-
- // The pointer is owned by the caller.
- browser_sync::sessions::SyncSession* CreateSyncSession(
- const browser_sync::sessions::SyncSourceInfo& info);
-
- // Creates a session for a poll and performs the sync.
- void PollTimerCallback();
-
- // Assign |start| and |end| to appropriate SyncerStep values for the
- // specified |purpose|.
- void SetSyncerStepsForPurpose(SyncSessionJob::SyncSessionJobPurpose purpose,
- SyncerStep* start,
- SyncerStep* end);
-
- // Initializes the hookup between the ServerConnectionManager and us.
- void WatchConnectionManager();
-
- // Used to update |server_connection_ok_|, see below.
- void CheckServerConnectionManagerStatus(
- HttpResponse::ServerConnectionCode code);
-
- // Called once the first time thread_ is started to broadcast an initial
- // session snapshot containing data like initial_sync_ended. Important when
- // the client starts up and does not need to perform an initial sync.
- void SendInitialSnapshot();
-
- base::Thread thread_;
-
- // Modifiable versions of kDefaultLongPollIntervalSeconds which can be
- // updated by the server.
- base::TimeDelta syncer_short_poll_interval_seconds_;
- base::TimeDelta syncer_long_poll_interval_seconds_;
-
- // Periodic timer for polling. See AdjustPolling.
- base::RepeatingTimer<SyncerThread> poll_timer_;
-
- // The mode of operation. We don't use a lock, see Start(...) comment.
- Mode mode_;
-
- // TODO(tim): Bug 26339. This needs to track more than just time I think,
- // since the nudges could be for different types. Current impl doesn't care.
- base::TimeTicks last_sync_session_end_time_;
-
- // Have we observed a valid server connection?
- bool server_connection_ok_;
-
- // Tracks in-flight nudges so we can coalesce.
- scoped_ptr<SyncSessionJob> pending_nudge_;
-
- // Current wait state. Null if we're not in backoff and not throttled.
- scoped_ptr<WaitInterval> wait_interval_;
-
- scoped_ptr<DelayProvider> delay_provider_;
-
- // Invoked to run through the sync cycle.
- scoped_ptr<Syncer> syncer_;
-
- scoped_ptr<sessions::SyncSessionContext> session_context_;
-
- DISALLOW_COPY_AND_ASSIGN(SyncerThread);
-};
-
-} // namespace s3
-
-} // namespace browser_sync
-
-// The SyncerThread manages its own internal thread and thus outlives it. We
-// don't need refcounting for posting tasks to this internal thread.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::s3::SyncerThread);
-
-#endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD2_H_
diff --git a/chrome/browser/sync/engine/syncer_thread2_unittest.cc b/chrome/browser/sync/engine/syncer_thread2_unittest.cc
index 2823567..d231a06 100644
--- a/chrome/browser/sync/engine/syncer_thread2_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_thread2_unittest.cc
@@ -6,7 +6,7 @@
#include "base/test/test_timeouts.h"
#include "chrome/browser/sync/engine/mock_model_safe_workers.h"
#include "chrome/browser/sync/engine/syncer.h"
-#include "chrome/browser/sync/engine/syncer_thread2.h"
+#include "chrome/browser/sync/engine/syncer_thread.h"
#include "chrome/browser/sync/sessions/test_util.h"
#include "chrome/test/sync/engine/mock_connection_manager.h"
#include "chrome/test/sync/engine/test_directory_setter_upper.h"
@@ -37,8 +37,6 @@ class MockSyncer : public Syncer {
SyncerStep));
};
-namespace s3 {
-
// Used when tests want to record syncing activity to examine later.
struct SyncShareRecords {
std::vector<TimeTicks> times;
@@ -929,8 +927,7 @@ TEST_F(SyncerThread2Test, SetsPreviousRoutingInfo) {
EXPECT_TRUE(expected == context()->previous_session_routing_info());
}
-} // namespace s3
} // namespace browser_sync
// SyncerThread won't outlive the test!
-DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::s3::SyncerThread2Test);
+DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::SyncerThread2Test);
diff --git a/chrome/browser/sync/engine/syncer_thread2_whitebox_unittest.cc b/chrome/browser/sync/engine/syncer_thread2_whitebox_unittest.cc
index e1d1218..e041aaa 100644
--- a/chrome/browser/sync/engine/syncer_thread2_whitebox_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_thread2_whitebox_unittest.cc
@@ -4,7 +4,7 @@
#include "base/time.h"
#include "chrome/browser/sync/engine/mock_model_safe_workers.h"
-#include "chrome/browser/sync/engine/syncer_thread2.h"
+#include "chrome/browser/sync/engine/syncer_thread.h"
#include "chrome/browser/sync/sessions/sync_session_context.h"
#include "chrome/browser/sync/sessions/test_util.h"
#include "chrome/test/sync/engine/mock_connection_manager.h"
@@ -19,8 +19,6 @@ namespace browser_sync {
using sessions::SyncSessionContext;
using browser_sync::Syncer;
-namespace s3 {
-
class SyncerThread2WhiteboxTest : public testing::Test {
public:
virtual void SetUp() {
@@ -226,10 +224,8 @@ TEST_F(SyncerThread2WhiteboxTest, ContinueCanaryJobConfig) {
EXPECT_EQ(decision, SyncerThread::CONTINUE);
}
-
-} // namespace s3
} // namespace browser_sync
// SyncerThread won't outlive the test!
DISABLE_RUNNABLE_METHOD_REFCOUNT(
- browser_sync::s3::SyncerThread2WhiteboxTest);
+ browser_sync::SyncerThread2WhiteboxTest);
diff --git a/chrome/browser/sync/engine/syncer_thread_adapter.cc b/chrome/browser/sync/engine/syncer_thread_adapter.cc
deleted file mode 100644
index 8a513e9..0000000
--- a/chrome/browser/sync/engine/syncer_thread_adapter.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-// 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 "base/time.h"
-#include "base/tracked.h"
-#include "chrome/browser/sync/engine/syncer_thread_adapter.h"
-#include "chrome/browser/sync/syncable/model_type.h"
-
-using base::TimeDelta;
-using syncable::ModelTypeBitSet;
-
-namespace browser_sync {
-
-SyncerThreadAdapter::SyncerThreadAdapter(sessions::SyncSessionContext* context,
- bool using_new_impl)
- : legacy_(NULL), new_impl_(NULL), using_new_impl_(using_new_impl) {
- if (using_new_impl_) {
- new_impl_.reset(new s3::SyncerThread(context, new Syncer()));
- } else {
- legacy_ = new SyncerThread(context);
- }
-}
-
-SyncerThreadAdapter::~SyncerThreadAdapter() {
- legacy_ = NULL;
- new_impl_.reset();
-}
-
-void SyncerThreadAdapter::WatchConnectionManager(
- ServerConnectionManager* conn_mgr) {
- DCHECK(!using_new_impl_);
- legacy_->WatchConnectionManager(conn_mgr);
-}
-
-bool SyncerThreadAdapter::Start() {
- if (using_new_impl_) {
- new_impl_->Start(s3::SyncerThread::NORMAL_MODE, NULL);
- return true;
- } else {
- return legacy_->Start();
- }
-}
-
-bool SyncerThreadAdapter::Stop(int max_wait) {
- if (using_new_impl_) {
- new_impl_->Stop();
- return true;
- } else {
- return legacy_->Stop(max_wait);
- }
-}
-
-bool SyncerThreadAdapter::RequestPause() {
- DCHECK(!using_new_impl_);
- return legacy_->RequestPause();
-}
-
-bool SyncerThreadAdapter::RequestResume() {
- DCHECK(!using_new_impl_);
- return legacy_->RequestResume();
-}
-
-s3::NudgeSource LegacyToNewSyncerThreadSource(SyncerThread::NudgeSource s) {
- switch (s) {
- case SyncerThread::kNotification:
- return s3::NUDGE_SOURCE_NOTIFICATION;
- case SyncerThread::kContinuation:
- return s3::NUDGE_SOURCE_CONTINUATION;
- case SyncerThread::kLocal:
- return s3::NUDGE_SOURCE_LOCAL;
- case SyncerThread::kUnknown:
- return s3::NUDGE_SOURCE_UNKNOWN;
- default:
- NOTREACHED();
- return s3::NUDGE_SOURCE_UNKNOWN;
- }
-}
-
-void SyncerThreadAdapter::NudgeSyncer(int milliseconds_from_now,
- SyncerThread::NudgeSource source,
- const tracked_objects::Location& nudge_location) {
- if (using_new_impl_) {
- if (source == SyncerThread::kClearPrivateData) {
- new_impl_->ScheduleClearUserData();
- return;
- }
- new_impl_->ScheduleNudge(
- TimeDelta::FromMilliseconds(milliseconds_from_now),
- LegacyToNewSyncerThreadSource(source), ModelTypeBitSet(),
- nudge_location);
- } else {
- legacy_->NudgeSyncer(milliseconds_from_now, source);
- }
-}
-
-void SyncerThreadAdapter::NudgeSyncerWithDataTypes(
- int milliseconds_from_now,
- SyncerThread::NudgeSource source,
- const syncable::ModelTypeBitSet& model_types,
- const tracked_objects::Location& nudge_location) {
- DCHECK_NE(SyncerThread::kClearPrivateData, source);
- if (using_new_impl_) {
- new_impl_->ScheduleNudge(
- TimeDelta::FromMilliseconds(milliseconds_from_now),
- LegacyToNewSyncerThreadSource(source), model_types,
- nudge_location);
- } else {
- legacy_->NudgeSyncerWithDataTypes(milliseconds_from_now, source,
- model_types);
- }
-}
-
-void SyncerThreadAdapter::NudgeSyncerWithPayloads(
- int milliseconds_from_now,
- SyncerThread::NudgeSource source,
- const syncable::ModelTypePayloadMap& model_types_with_payloads,
- const tracked_objects::Location& nudge_location) {
- DCHECK_NE(SyncerThread::kClearPrivateData, source);
- if (using_new_impl_) {
- new_impl_->ScheduleNudgeWithPayloads(
- TimeDelta::FromMilliseconds(milliseconds_from_now),
- LegacyToNewSyncerThreadSource(source), model_types_with_payloads,
- nudge_location);
- } else {
- legacy_->NudgeSyncerWithPayloads(milliseconds_from_now, source,
- model_types_with_payloads);
- }
-}
-
-void SyncerThreadAdapter::SetNotificationsEnabled(bool enabled) {
- if (using_new_impl_)
- new_impl_->set_notifications_enabled(enabled);
- else
- legacy_->SetNotificationsEnabled(enabled);
-}
-
-void SyncerThreadAdapter::CreateSyncer(const std::string& dirname) {
- if (!using_new_impl_)
- legacy_->CreateSyncer(dirname);
- // No-op if using new impl.
-}
-
-s3::SyncerThread* SyncerThreadAdapter::new_impl() {
- return new_impl_.get();
-}
-
-} // namespace browser_sync
diff --git a/chrome/browser/sync/engine/syncer_thread_adapter.h b/chrome/browser/sync/engine/syncer_thread_adapter.h
deleted file mode 100644
index 6b234e9..0000000
--- a/chrome/browser/sync/engine/syncer_thread_adapter.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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.
-#ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_ADAPTER_H_
-#define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_ADAPTER_H_
-#pragma once
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/tracked.h"
-#include "chrome/browser/sync/engine/net/server_connection_manager.h"
-#include "chrome/browser/sync/engine/syncer_thread.h"
-#include "chrome/browser/sync/engine/syncer_thread2.h"
-#include "chrome/browser/sync/sessions/sync_session_context.h"
-#include "chrome/browser/sync/syncable/model_type.h"
-#include "chrome/browser/sync/syncable/model_type_payload_map.h"
-
-namespace browser_sync {
-
-class SyncerThreadAdapter {
- public:
- SyncerThreadAdapter(sessions::SyncSessionContext* context,
- bool using_new_impl);
- ~SyncerThreadAdapter();
-
- // We mimic the SyncerThread interface (an adaptee).
- void WatchConnectionManager(ServerConnectionManager* conn_mgr);
- bool Start();
- bool Stop(int max_wait);
- bool RequestPause();
- bool RequestResume();
- void NudgeSyncer(int milliseconds_from_now,
- SyncerThread::NudgeSource source,
- const tracked_objects::Location& nudge_location);
- void NudgeSyncerWithDataTypes(
- int milliseconds_from_now,
- SyncerThread::NudgeSource source,
- const syncable::ModelTypeBitSet& model_types,
- const tracked_objects::Location& nudge_location);
- void NudgeSyncerWithPayloads(
- int milliseconds_from_now,
- SyncerThread::NudgeSource source,
- const syncable::ModelTypePayloadMap& model_types_with_payloads,
- const tracked_objects::Location& nudge_location);
- void SetNotificationsEnabled(bool enabled);
- void CreateSyncer(const std::string& dirname);
-
- // Expose the new impl to leverage new apis through the adapter.
- s3::SyncerThread* new_impl();
- private:
- scoped_refptr<SyncerThread> legacy_;
- scoped_ptr<s3::SyncerThread> new_impl_;
- bool using_new_impl_;
-
- DISALLOW_COPY_AND_ASSIGN(SyncerThreadAdapter);
-};
-
-} // namespace browser_sync
-
-#endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_ADAPTER_H_
diff --git a/chrome/browser/sync/engine/syncer_thread_unittest.cc b/chrome/browser/sync/engine/syncer_thread_unittest.cc
index faa0e9b..7a37f38 100644
--- a/chrome/browser/sync/engine/syncer_thread_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_thread_unittest.cc
@@ -1,1245 +1,3 @@
// 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 <list>
-#include <map>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "base/time.h"
-#include "base/synchronization/waitable_event.h"
-#include "chrome/browser/sync/engine/model_safe_worker.h"
-#include "chrome/browser/sync/engine/syncer_thread.h"
-#include "chrome/browser/sync/engine/syncer_types.h"
-#include "chrome/browser/sync/sessions/sync_session_context.h"
-#include "chrome/browser/sync/util/channel.h"
-#include "chrome/test/sync/engine/mock_connection_manager.h"
-#include "chrome/test/sync/engine/test_directory_setter_upper.h"
-#include "chrome/test/sync/sessions/test_scoped_session_event_listener.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::TimeTicks;
-using base::TimeDelta;
-using base::WaitableEvent;
-using testing::_;
-using testing::AnyNumber;
-using testing::Field;
-
-namespace browser_sync {
-using sessions::ErrorCounters;
-using sessions::TestScopedSessionEventListener;
-using sessions::SyncSessionContext;
-using sessions::SyncSessionSnapshot;
-using sessions::SyncerStatus;
-
-typedef testing::Test SyncerThreadTest;
-typedef SyncerThread::WaitInterval WaitInterval;
-
-ACTION_P(SignalEvent, event) {
- event->Signal();
-}
-
-SyncSessionSnapshot SessionSnapshotForTest(
- int64 num_server_changes_remaining,
- int64 unsynced_count) {
- std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
- for (int i = syncable::FIRST_REAL_MODEL_TYPE;
- i < syncable::MODEL_TYPE_COUNT;
- ++i) {
- syncable::ModelType type(syncable::ModelTypeFromInt(i));
- sync_pb::DataTypeProgressMarker token;
- token.set_data_type_id(
- syncable::GetExtensionFieldNumberFromModelType(type));
- token.set_token("foobar");
- token.SerializeToString(&download_progress_markers[i]);
- }
- return SyncSessionSnapshot(SyncerStatus(), ErrorCounters(),
- num_server_changes_remaining, false,
- syncable::ModelTypeBitSet(), download_progress_markers,
- false, false, unsynced_count, 0, false, sessions::SyncSourceInfo());
-}
-
-class ListenerMock : public SyncEngineEventListener {
- public:
- MOCK_METHOD1(OnSyncEngineEvent, void(const SyncEngineEvent&));
-};
-
-class SyncerThreadWithSyncerTest : public testing::Test,
- public ModelSafeWorkerRegistrar,
- public SyncEngineEventListener {
- public:
- SyncerThreadWithSyncerTest()
- : max_wait_time_(TimeDelta::FromSeconds(10)),
- sync_cycle_ended_event_(false, false) {}
- virtual void SetUp() {
- metadb_.SetUp();
- connection_.reset(new MockConnectionManager(metadb_.manager(),
- metadb_.name()));
- worker_ = new ModelSafeWorker();
- std::vector<SyncEngineEventListener*> listeners;
- listeners.push_back(this);
- context_ = new SyncSessionContext(connection_.get(), metadb_.manager(),
- this, listeners);
- context_->set_account_name(metadb_.name());
- syncer_thread_ = new SyncerThread(context_);
- syncer_thread_->SetConnected(true);
- syncable::ModelTypeBitSet expected_types;
- expected_types[syncable::BOOKMARKS] = true;
- connection_->ExpectGetUpdatesRequestTypes(expected_types);
- }
- virtual void TearDown() {
- context_ = NULL;
- syncer_thread_ = NULL;
- connection_.reset();
- metadb_.TearDown();
- }
-
- // ModelSafeWorkerRegistrar implementation.
- virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) {
- out->push_back(worker_.get());
- }
-
- virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) {
- // We're just testing the sync engine here, so we shunt everything to
- // the SyncerThread.
- (*out)[syncable::BOOKMARKS] = GROUP_PASSIVE;
- }
-
- ManuallyOpenedTestDirectorySetterUpper* metadb() { return &metadb_; }
- MockConnectionManager* connection() { return connection_.get(); }
- SyncerThread* syncer_thread() { return syncer_thread_; }
-
- // Waits an indefinite amount of sync cycles for the syncer thread to become
- // throttled. Only call this if a throttle is supposed to occur!
- bool WaitForThrottle() {
- int max_cycles = 5;
- while (max_cycles && !syncer_thread()->IsSyncingCurrentlySilenced()) {
- sync_cycle_ended_event_.TimedWait(max_wait_time_);
- max_cycles--;
- }
-
- return syncer_thread()->IsSyncingCurrentlySilenced();
- }
-
- void WaitForDisconnect() {
- // Wait for the SyncerThread to detect loss of connection, up to a max of
- // 10 seconds to timeout the test.
- base::AutoLock lock(syncer_thread()->lock_);
- TimeTicks start = TimeTicks::Now();
- TimeDelta ten_seconds = TimeDelta::FromSeconds(10);
- while (syncer_thread()->vault_.connected_) {
- syncer_thread()->vault_field_changed_.TimedWait(ten_seconds);
- if (TimeTicks::Now() - start > ten_seconds)
- break;
- }
- EXPECT_FALSE(syncer_thread()->vault_.connected_);
- }
-
- bool Pause(ListenerMock* listener) {
- WaitableEvent event(false, false);
- {
- base::AutoLock lock(syncer_thread()->lock_);
- EXPECT_CALL(*listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_PAUSED))).
- WillOnce(SignalEvent(&event));
- }
- if (!syncer_thread()->RequestPause())
- return false;
- return event.TimedWait(max_wait_time_);
- }
-
- bool Resume(ListenerMock* listener) {
- WaitableEvent event(false, false);
- {
- base::AutoLock lock(syncer_thread()->lock_);
- EXPECT_CALL(*listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_RESUMED))).
- WillOnce(SignalEvent(&event));
- }
- if (!syncer_thread()->RequestResume())
- return false;
- return event.TimedWait(max_wait_time_);
- }
-
- void PreventThreadFromPolling() {
- const TimeDelta poll_interval = TimeDelta::FromMinutes(5);
- syncer_thread()->SetSyncerShortPollInterval(poll_interval);
- }
-
- // Compare a provided TypePayloadMap to the pending nudge info stored in the
- // SyncerThread vault.
- bool CompareNudgeTypesToVault(const syncable::ModelTypePayloadMap& lhs) {
- const syncable::ModelTypePayloadMap& vault_nudge_types =
- syncer_thread()->vault_.pending_nudge_types_;
- return lhs == vault_nudge_types;
- }
-
- // Compare a provided ModelTypeBitset to the pending nudge info stored in the
- // SyncerThread vault. Nudge info in vault must not have any non-empty
- // payloads.
- bool CompareNudgeTypesBitSetToVault(const syncable::ModelTypeBitSet& lhs) {
- syncable::ModelTypePayloadMap model_types_with_payloads =
- syncable::ModelTypePayloadMapFromBitSet(lhs, std::string());
- size_t count = 0;
- for (syncable::ModelTypePayloadMap::const_iterator i =
- syncer_thread()->vault_.pending_nudge_types_.begin();
- i != syncer_thread()->vault_.pending_nudge_types_.end();
- ++i, ++count) {
- if (!lhs.test(i->first))
- return false;
- }
- if (lhs.count() != count)
- return false;
- return true;
- }
-
-
- private:
-
- virtual void OnSyncEngineEvent(const SyncEngineEvent& event) {
- if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED)
- sync_cycle_ended_event_.Signal();
- }
-
- protected:
- TimeDelta max_wait_time_;
- SyncSessionContext* context_;
-
- private:
- ManuallyOpenedTestDirectorySetterUpper metadb_;
- scoped_ptr<MockConnectionManager> connection_;
- scoped_refptr<SyncerThread> syncer_thread_;
- scoped_refptr<ModelSafeWorker> worker_;
- base::WaitableEvent sync_cycle_ended_event_;
- DISALLOW_COPY_AND_ASSIGN(SyncerThreadWithSyncerTest);
-};
-
-class SyncShareIntercept
- : public MockConnectionManager::ResponseCodeOverrideRequestor,
- public MockConnectionManager::MidCommitObserver {
- public:
- SyncShareIntercept() : sync_occured_(false, false),
- allow_multiple_interceptions_(true) {}
- virtual ~SyncShareIntercept() {}
- virtual void Observe() {
- if (!allow_multiple_interceptions_ && !times_sync_occured_.empty())
- FAIL() << "Multiple sync shares occured.";
- times_sync_occured_.push_back(TimeTicks::Now());
- sync_occured_.Signal();
- }
-
- // ResponseCodeOverrideRequestor implementation. This assumes any override
- // requested is intended to silence the SyncerThread.
- virtual void OnOverrideComplete() {
- // We should not see any syncing.
- allow_multiple_interceptions_ = false;
- times_sync_occured_.clear();
- }
-
- void WaitForSyncShare(int at_least_this_many, TimeDelta max_wait) {
- while (at_least_this_many-- > 0)
- sync_occured_.TimedWait(max_wait);
- }
- std::vector<TimeTicks> times_sync_occured() const {
- return times_sync_occured_;
- }
-
- void Reset() {
- allow_multiple_interceptions_ = true;
- times_sync_occured_.clear();
- sync_occured_.Reset();
- }
- private:
- std::vector<TimeTicks> times_sync_occured_;
- base::WaitableEvent sync_occured_;
- bool allow_multiple_interceptions_;
- DISALLOW_COPY_AND_ASSIGN(SyncShareIntercept);
-};
-
-TEST_F(SyncerThreadTest, Construction) {
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL,
- std::vector<SyncEngineEventListener*>());
- scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context));
-}
-
-TEST_F(SyncerThreadTest, StartStop) {
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL,
- std::vector<SyncEngineEventListener*>());
- scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context));
- EXPECT_TRUE(syncer_thread->Start());
- EXPECT_TRUE(syncer_thread->Stop(2000));
-
- // Do it again for good measure. I caught some bugs by adding this so
- // I would recommend keeping it.
- EXPECT_TRUE(syncer_thread->Start());
- EXPECT_TRUE(syncer_thread->Stop(2000));
-}
-
-TEST(SyncerThread, GetRecommendedDelay) {
- EXPECT_LE(0, SyncerThread::GetRecommendedDelaySeconds(0));
- EXPECT_LE(1, SyncerThread::GetRecommendedDelaySeconds(1));
- EXPECT_LE(50, SyncerThread::GetRecommendedDelaySeconds(50));
- EXPECT_LE(10, SyncerThread::GetRecommendedDelaySeconds(10));
- EXPECT_EQ(SyncerThread::kMaxBackoffSeconds,
- SyncerThread::GetRecommendedDelaySeconds(
- SyncerThread::kMaxBackoffSeconds));
- EXPECT_EQ(SyncerThread::kMaxBackoffSeconds,
- SyncerThread::GetRecommendedDelaySeconds(
- SyncerThread::kMaxBackoffSeconds+1));
-}
-
-TEST_F(SyncerThreadTest, CalculateSyncWaitTime) {
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL,
- std::vector<SyncEngineEventListener*>());
- scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context));
- syncer_thread->DisableIdleDetection();
-
- // Syncer_polling_interval_ is less than max poll interval.
- TimeDelta syncer_polling_interval = TimeDelta::FromSeconds(1);
-
- syncer_thread->SetSyncerPollingInterval(syncer_polling_interval);
-
- // user_idle_ms is less than 10 * (syncer_polling_interval*1000).
- ASSERT_EQ(syncer_polling_interval.InMilliseconds(),
- syncer_thread->CalculateSyncWaitTime(1000, 0));
- ASSERT_EQ(syncer_polling_interval.InMilliseconds(),
- syncer_thread->CalculateSyncWaitTime(1000, 1));
-
- // user_idle_ms is ge than 10 * (syncer_polling_interval*1000).
- int last_poll_time = 2000;
- ASSERT_TRUE(last_poll_time <=
- syncer_thread->CalculateSyncWaitTime(last_poll_time, 10000));
- ASSERT_TRUE(last_poll_time * 3 >=
- syncer_thread->CalculateSyncWaitTime(last_poll_time, 10000));
- ASSERT_TRUE(last_poll_time <=
- syncer_thread->CalculateSyncWaitTime(last_poll_time, 100000));
- ASSERT_TRUE(last_poll_time * 3 >=
- syncer_thread->CalculateSyncWaitTime(last_poll_time, 100000));
-
- // Maximum backoff time should be syncer_max_interval.
- int near_threshold = SyncerThread::kDefaultMaxPollIntervalMs / 2 - 1;
- int threshold = SyncerThread::kDefaultMaxPollIntervalMs;
- int over_threshold = SyncerThread::kDefaultMaxPollIntervalMs + 1;
- ASSERT_TRUE(near_threshold <=
- syncer_thread->CalculateSyncWaitTime(near_threshold, 10000));
- ASSERT_TRUE(SyncerThread::kDefaultMaxPollIntervalMs >=
- syncer_thread->CalculateSyncWaitTime(near_threshold, 10000));
- ASSERT_TRUE(SyncerThread::kDefaultMaxPollIntervalMs ==
- syncer_thread->CalculateSyncWaitTime(threshold, 10000));
- ASSERT_TRUE(SyncerThread::kDefaultMaxPollIntervalMs ==
- syncer_thread->CalculateSyncWaitTime(over_threshold, 10000));
-
- // Possible idle time must be capped by syncer_max_interval.
- int over_sync_max_interval =
- SyncerThread::kDefaultMaxPollIntervalMs + 1;
- syncer_polling_interval = TimeDelta::FromSeconds(
- over_sync_max_interval / 100); // so 1000* is right
- syncer_thread->SetSyncerPollingInterval(syncer_polling_interval);
- ASSERT_EQ(syncer_polling_interval.InSeconds() * 1000,
- syncer_thread->CalculateSyncWaitTime(1000, over_sync_max_interval));
- syncer_polling_interval = TimeDelta::FromSeconds(1);
- syncer_thread->SetSyncerPollingInterval(syncer_polling_interval);
- ASSERT_TRUE(last_poll_time <=
- syncer_thread->CalculateSyncWaitTime(last_poll_time,
- over_sync_max_interval));
- ASSERT_TRUE(last_poll_time * 3 >=
- syncer_thread->CalculateSyncWaitTime(last_poll_time,
- over_sync_max_interval));
-}
-
-TEST_F(SyncerThreadTest, CalculatePollingWaitTime) {
- // Set up the environment.
- int user_idle_milliseconds_param = 0;
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL,
- std::vector<SyncEngineEventListener*>());
- scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context));
- syncer_thread->DisableIdleDetection();
- // Hold the lock to appease asserts in code.
- base::AutoLock lock(syncer_thread->lock_);
-
- // Notifications disabled should result in a polling interval of
- // kDefaultShortPollInterval.
- {
- context->set_notifications_enabled(false);
- bool continue_sync_cycle_param = false;
-
- // No work and no backoff.
- WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds,
- interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_FALSE(continue_sync_cycle_param);
-
- // In this case the continue_sync_cycle is turned off.
- continue_sync_cycle_param = true;
- interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds,
- interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_FALSE(continue_sync_cycle_param);
- }
-
- // Notifications enabled should result in a polling interval of
- // SyncerThread::kDefaultLongPollIntervalSeconds.
- {
- context->set_notifications_enabled(true);
- bool continue_sync_cycle_param = false;
-
- // No work and no backoff.
- WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds,
- interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_FALSE(continue_sync_cycle_param);
-
- // In this case the continue_sync_cycle is turned off.
- continue_sync_cycle_param = true;
- interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds,
- interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_FALSE(continue_sync_cycle_param);
- }
-
- // There are two states which can cause a continuation, either the updates
- // available do not match the updates received, or the unsynced count is
- // non-zero.
- {
- // More server changes remaining to download.
- context->set_last_snapshot(SessionSnapshotForTest(1, 0));
- bool continue_sync_cycle_param = false;
-
- WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_LE(0, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- continue_sync_cycle_param = false;
- interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_GE(3, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_LE(0, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
-
- interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_GE(2, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- // Now simulate no more server changes remaining.
- context->set_last_snapshot(SessionSnapshotForTest(0, 0));
- interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds,
- interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_FALSE(continue_sync_cycle_param);
- }
-
- {
- // Now try with unsynced local items.
- context->set_last_snapshot(SessionSnapshotForTest(0, 1));
- bool continue_sync_cycle_param = false;
-
- WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_LE(0, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- continue_sync_cycle_param = false;
- interval = syncer_thread->CalculatePollingWaitTime(
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_GE(2, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- context->set_last_snapshot(SessionSnapshotForTest(0, 0));
- interval = syncer_thread->CalculatePollingWaitTime(
- 4,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds,
- interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_FALSE(continue_sync_cycle_param);
- }
-
- // Regression for exponential backoff reset when the syncer is nudged.
- {
- context->set_last_snapshot(SessionSnapshotForTest(0, 1));
- bool continue_sync_cycle_param = false;
-
- // Expect move from default polling interval to exponential backoff due to
- // unsynced_count != 0.
- WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
- 3600,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_LE(0, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- continue_sync_cycle_param = false;
- interval = syncer_thread->CalculatePollingWaitTime(
- 3600,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_GE(2, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- // Expect exponential backoff.
- interval = syncer_thread->CalculatePollingWaitTime(
- 2,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_LE(2, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- interval = syncer_thread->CalculatePollingWaitTime(
- 2,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_GE(6, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- syncer_thread->vault_.current_wait_interval_ = interval;
-
- interval = syncer_thread->CalculatePollingWaitTime(
- static_cast<int>(interval.poll_delta.InSeconds()),
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- true);
-
- // Don't change poll on a failed nudge during backoff.
- ASSERT_TRUE(syncer_thread->vault_.current_wait_interval_.poll_delta ==
- interval.poll_delta);
- ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
- ASSERT_TRUE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- // If we got a nudge and we weren't in backoff mode, we see exponential
- // backoff.
- syncer_thread->vault_.current_wait_interval_.mode = WaitInterval::NORMAL;
- interval = syncer_thread->CalculatePollingWaitTime(
- 2,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- true);
-
- // 5 and 3 are bounds on the backoff randomization formula given input of 2.
- ASSERT_GE(5, interval.poll_delta.InSeconds());
- ASSERT_LE(3, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- // And if another interval expires, we get a bigger backoff.
- WaitInterval new_interval = syncer_thread->CalculatePollingWaitTime(
- static_cast<int>(interval.poll_delta.InSeconds()),
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- false);
-
- ASSERT_GE(12, new_interval.poll_delta.InSeconds());
- ASSERT_LE(5, new_interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
- ASSERT_FALSE(new_interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- // A nudge resets the continue_sync_cycle_param value, so our backoff
- // should return to the minimum.
- continue_sync_cycle_param = false;
- interval = syncer_thread->CalculatePollingWaitTime(
- 3600,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- true);
-
- ASSERT_LE(0, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- continue_sync_cycle_param = false;
- interval = syncer_thread->CalculatePollingWaitTime(
- 3600,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- true);
-
- ASSERT_GE(2, interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_TRUE(continue_sync_cycle_param);
-
- // Setting unsynced_count = 0 returns us to the default polling interval.
- context->set_last_snapshot(SessionSnapshotForTest(0, 0));
- interval = syncer_thread->CalculatePollingWaitTime(
- 4,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param,
- true);
-
- ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds,
- interval.poll_delta.InSeconds());
- ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
- ASSERT_FALSE(interval.had_nudge_during_backoff);
- ASSERT_FALSE(continue_sync_cycle_param);
- }
-}
-
-TEST_F(SyncerThreadWithSyncerTest, Polling) {
- SyncShareIntercept interceptor;
- connection()->SetMidCommitObserver(&interceptor);
-
- const TimeDelta poll_interval = TimeDelta::FromSeconds(1);
- syncer_thread()->SetSyncerShortPollInterval(poll_interval);
- EXPECT_TRUE(syncer_thread()->Start());
-
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
-
- TimeDelta two_polls = poll_interval + poll_interval;
- // We could theoretically return immediately from the wait if the interceptor
- // was already signaled for a SyncShare (the first one comes quick).
- interceptor.WaitForSyncShare(1, two_polls);
- EXPECT_FALSE(interceptor.times_sync_occured().empty());
-
- // Wait for at least 2 more SyncShare operations.
- interceptor.WaitForSyncShare(2, two_polls);
- EXPECT_TRUE(syncer_thread()->Stop(2000));
-
- // Now analyze the run.
- std::vector<TimeTicks> data = interceptor.times_sync_occured();
-
- EXPECT_GE(data.size(), static_cast<unsigned int>(3));
- for (unsigned int i = 0; i < data.size() - 1; i++) {
- TimeTicks optimal_next_sync = data[i] + poll_interval;
- EXPECT_TRUE(data[i + 1] >= optimal_next_sync);
- // This should be reliable, as there are no blocking or I/O operations
- // except the explicit 2 second wait, so if it takes longer than this
- // there is a problem.
- EXPECT_TRUE(data[i + 1] < optimal_next_sync + poll_interval);
- }
-}
-
-TEST_F(SyncerThreadWithSyncerTest, Nudge) {
- SyncShareIntercept interceptor;
- connection()->SetMidCommitObserver(&interceptor);
- // We don't want a poll to happen during this test (except the first one).
- PreventThreadFromPolling();
- EXPECT_TRUE(syncer_thread()->Start());
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
- const TimeDelta poll_interval = TimeDelta::FromMinutes(5);
- interceptor.WaitForSyncShare(1, poll_interval + poll_interval);
-
- EXPECT_EQ(static_cast<unsigned int>(1),
- interceptor.times_sync_occured().size());
- // The SyncerThread should be waiting for the poll now. Nudge it to sync
- // immediately (5ms).
- syncer_thread()->NudgeSyncer(5, SyncerThread::kUnknown);
- interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1));
- EXPECT_EQ(static_cast<unsigned int>(2),
- interceptor.times_sync_occured().size());
-
- // SyncerThread should be waiting again. Signal it to stop.
- EXPECT_TRUE(syncer_thread()->Stop(2000));
-}
-
-TEST_F(SyncerThreadWithSyncerTest, NudgeWithDataTypes) {
- SyncShareIntercept interceptor;
- connection()->SetMidCommitObserver(&interceptor);
- // We don't want a poll to happen during this test (except the first one).
- PreventThreadFromPolling();
- EXPECT_TRUE(syncer_thread()->Start());
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
- const TimeDelta poll_interval = TimeDelta::FromMinutes(5);
- interceptor.WaitForSyncShare(1, poll_interval + poll_interval);
- EXPECT_EQ(static_cast<unsigned int>(1),
- interceptor.times_sync_occured().size());
-
- // The SyncerThread should be waiting for the poll now. Nudge it to sync
- // immediately (5ms).
- syncable::ModelTypeBitSet model_types;
- model_types[syncable::BOOKMARKS] = true;
-
- // Paused so we can verify the nudge types safely.
- syncer_thread()->RequestPause();
- syncer_thread()->NudgeSyncerWithDataTypes(5,
- SyncerThread::kUnknown,
- model_types);
- EXPECT_TRUE(CompareNudgeTypesBitSetToVault(model_types));
- syncer_thread()->RequestResume();
-
- interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1));
- EXPECT_EQ(static_cast<unsigned int>(2),
- interceptor.times_sync_occured().size());
-
- // SyncerThread should be waiting again. Signal it to stop.
- EXPECT_TRUE(syncer_thread()->Stop(2000));
- EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty());
-}
-
-TEST_F(SyncerThreadWithSyncerTest, NudgeWithDataTypesCoalesced) {
- SyncShareIntercept interceptor;
- connection()->SetMidCommitObserver(&interceptor);
- // We don't want a poll to happen during this test (except the first one).
- PreventThreadFromPolling();
- EXPECT_TRUE(syncer_thread()->Start());
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
- const TimeDelta poll_interval = TimeDelta::FromMinutes(5);
- interceptor.WaitForSyncShare(1, poll_interval + poll_interval);
- EXPECT_EQ(static_cast<unsigned int>(1),
- interceptor.times_sync_occured().size());
-
- // The SyncerThread should be waiting for the poll now. Nudge it to sync
- // immediately (5ms).
- syncable::ModelTypeBitSet model_types;
- model_types[syncable::BOOKMARKS] = true;
-
- // Paused so we can verify the nudge types safely.
- syncer_thread()->RequestPause();
- syncer_thread()->NudgeSyncerWithDataTypes(100,
- SyncerThread::kUnknown,
- model_types);
- EXPECT_TRUE(CompareNudgeTypesBitSetToVault(model_types));
-
- model_types[syncable::BOOKMARKS] = false;
- model_types[syncable::AUTOFILL] = true;
- syncer_thread()->NudgeSyncerWithDataTypes(0,
- SyncerThread::kUnknown,
- model_types);
-
- // Reset BOOKMARKS for expectations.
- model_types[syncable::BOOKMARKS] = true;
- EXPECT_TRUE(CompareNudgeTypesBitSetToVault(model_types));
-
- syncer_thread()->RequestResume();
-
- interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1));
- EXPECT_EQ(static_cast<unsigned int>(2),
- interceptor.times_sync_occured().size());
-
- // SyncerThread should be waiting again. Signal it to stop.
- EXPECT_TRUE(syncer_thread()->Stop(2000));
- EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty());
-}
-
-TEST_F(SyncerThreadWithSyncerTest, NudgeWithPayloads) {
- SyncShareIntercept interceptor;
- connection()->SetMidCommitObserver(&interceptor);
- // We don't want a poll to happen during this test (except the first one).
- PreventThreadFromPolling();
- EXPECT_TRUE(syncer_thread()->Start());
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
- const TimeDelta poll_interval = TimeDelta::FromMinutes(5);
- interceptor.WaitForSyncShare(1, poll_interval + poll_interval);
- EXPECT_EQ(static_cast<unsigned int>(1),
- interceptor.times_sync_occured().size());
-
- // The SyncerThread should be waiting for the poll now. Nudge it to sync
- // immediately (5ms).
- syncable::ModelTypePayloadMap nudge_types;
- nudge_types[syncable::BOOKMARKS] = "test";
- connection()->ExpectGetUpdatesRequestPayloads(nudge_types);
-
- // Paused so we can verify the nudge types safely.
- syncer_thread()->RequestPause();
- syncer_thread()->NudgeSyncerWithPayloads(5,
- SyncerThread::kUnknown,
- nudge_types);
- EXPECT_TRUE(CompareNudgeTypesToVault(nudge_types));
- syncer_thread()->RequestResume();
-
- interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1));
- EXPECT_EQ(static_cast<unsigned int>(2),
- interceptor.times_sync_occured().size());
-
- // SyncerThread should be waiting again. Signal it to stop.
- EXPECT_TRUE(syncer_thread()->Stop(2000));
- EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty());
-}
-
-TEST_F(SyncerThreadWithSyncerTest, NudgeWithPayloadsCoalesced) {
- SyncShareIntercept interceptor;
- connection()->SetMidCommitObserver(&interceptor);
- // We don't want a poll to happen during this test (except the first one).
- PreventThreadFromPolling();
- EXPECT_TRUE(syncer_thread()->Start());
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
- const TimeDelta poll_interval = TimeDelta::FromMinutes(5);
- interceptor.WaitForSyncShare(1, poll_interval + poll_interval);
- EXPECT_EQ(static_cast<unsigned int>(1),
- interceptor.times_sync_occured().size());
-
- // The SyncerThread should be waiting for the poll now. Nudge it to sync
- // immediately (5ms).
- syncable::ModelTypePayloadMap nudge_types;
- nudge_types[syncable::BOOKMARKS] = "books";
-
- // Paused so we can verify the nudge types safely.
- syncer_thread()->RequestPause();
- syncer_thread()->NudgeSyncerWithPayloads(100,
- SyncerThread::kUnknown,
- nudge_types);
- EXPECT_TRUE(CompareNudgeTypesToVault(nudge_types));
-
- nudge_types.erase(syncable::BOOKMARKS);
- nudge_types[syncable::AUTOFILL] = "auto";
- syncer_thread()->NudgeSyncerWithPayloads(0,
- SyncerThread::kUnknown,
- nudge_types);
-
- // Reset BOOKMARKS for expectations.
- nudge_types[syncable::BOOKMARKS] = "books";
- EXPECT_TRUE(CompareNudgeTypesToVault(nudge_types));
- connection()->ExpectGetUpdatesRequestPayloads(nudge_types);
-
- syncer_thread()->RequestResume();
-
- interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1));
- EXPECT_EQ(static_cast<unsigned int>(2),
- interceptor.times_sync_occured().size());
-
- // SyncerThread should be waiting again. Signal it to stop.
- EXPECT_TRUE(syncer_thread()->Stop(2000));
- EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty());
-}
-
-TEST_F(SyncerThreadWithSyncerTest, Throttling) {
- SyncShareIntercept interceptor;
- connection()->SetMidCommitObserver(&interceptor);
- const TimeDelta poll_interval = TimeDelta::FromMilliseconds(10);
- syncer_thread()->SetSyncerShortPollInterval(poll_interval);
-
- EXPECT_TRUE(syncer_thread()->Start());
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
-
- // Wait for some healthy syncing.
- interceptor.WaitForSyncShare(4, poll_interval + poll_interval);
-
- // Tell the server to throttle a single request, which should be all it takes
- // to silence our syncer (for 2 hours, so we shouldn't hit that in this test).
- // This will atomically visit the interceptor so it can switch to throttled
- // mode and fail on multiple requests.
- connection()->ThrottleNextRequest(&interceptor);
-
- // Try to trigger a sync (we have a really short poll interval already).
- syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown);
- syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown);
-
- // Wait until the syncer thread reports that it is throttled. Any further
- // sync share interceptions will result in failure. If things are broken,
- // we may never halt.
- ASSERT_TRUE(WaitForThrottle());
- EXPECT_TRUE(syncer_thread()->IsSyncingCurrentlySilenced());
-
- EXPECT_TRUE(syncer_thread()->Stop(2000));
-}
-
-TEST_F(SyncerThreadWithSyncerTest, StopSyncPermanently) {
- // The SyncerThread should request an exit from the Syncer and set
- // conditions for termination.
- const TimeDelta poll_interval = TimeDelta::FromMilliseconds(10);
- syncer_thread()->SetSyncerShortPollInterval(poll_interval);
-
- ListenerMock listener;
- WaitableEvent sync_cycle_ended_event(false, false);
- WaitableEvent syncer_thread_exiting_event(false, false);
- TestScopedSessionEventListener reg(context_, &listener);
-
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::STATUS_CHANGED))).
- Times(AnyNumber());
-
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNC_CYCLE_ENDED))).
- Times(AnyNumber()).
- WillOnce(SignalEvent(&sync_cycle_ended_event));
-
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::STOP_SYNCING_PERMANENTLY)));
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_EXITING))).
- WillOnce(SignalEvent(&syncer_thread_exiting_event));
-
- EXPECT_TRUE(syncer_thread()->Start());
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
- ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
-
- connection()->set_store_birthday("NotYourLuckyDay");
- ASSERT_TRUE(syncer_thread_exiting_event.TimedWait(max_wait_time_));
- EXPECT_TRUE(syncer_thread()->Stop(0));
-}
-
-TEST_F(SyncerThreadWithSyncerTest, AuthInvalid) {
- SyncShareIntercept interceptor;
- connection()->SetMidCommitObserver(&interceptor);
- const TimeDelta poll_interval = TimeDelta::FromMilliseconds(1);
-
- syncer_thread()->SetSyncerShortPollInterval(poll_interval);
- EXPECT_TRUE(syncer_thread()->Start());
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
-
- // Wait for some healthy syncing.
- interceptor.WaitForSyncShare(2, TimeDelta::FromSeconds(10));
- EXPECT_GE(interceptor.times_sync_occured().size(), 2U);
-
- // Atomically start returning auth invalid and set the interceptor to fail
- // on any sync.
- connection()->FailWithAuthInvalid(&interceptor);
- WaitForDisconnect();
-
- // Try to trigger a sync (the interceptor will assert if one occurs).
- syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown);
- syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown);
-
- // Wait several poll intervals but don't expect any syncing besides the cycle
- // that lost the connection.
- interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1));
- EXPECT_EQ(1U, interceptor.times_sync_occured().size());
-
- // Simulate a valid re-authentication and expect resumption of syncing.
- interceptor.Reset();
- ASSERT_TRUE(interceptor.times_sync_occured().empty());
- connection()->StopFailingWithAuthInvalid(NULL);
- ServerConnectionEvent e = {ServerConnectionEvent::STATUS_CHANGED,
- HttpResponse::SERVER_CONNECTION_OK,
- true};
- connection()->channel()->NotifyListeners(e);
-
- interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(10));
- EXPECT_FALSE(interceptor.times_sync_occured().empty());
-
- EXPECT_TRUE(syncer_thread()->Stop(2000));
-}
-
-// TODO(zea): Disabled, along with PauseWhenNotConnected, due to stalling on
-// windows, preventing further sync unit tests from running. See crbug/39070.
-TEST_F(SyncerThreadWithSyncerTest, DISABLED_Pause) {
- WaitableEvent sync_cycle_ended_event(false, false);
- WaitableEvent paused_event(false, false);
- WaitableEvent resumed_event(false, false);
- PreventThreadFromPolling();
-
- ListenerMock listener;
- TestScopedSessionEventListener reg(context_, &listener);
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::STATUS_CHANGED))).
- Times(AnyNumber());
-
- // Wait for the initial sync to complete.
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNC_CYCLE_ENDED))).
- WillOnce(SignalEvent(&sync_cycle_ended_event));
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_EXITING)));
-
- ASSERT_TRUE(syncer_thread()->Start());
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
- ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
-
- // Request a pause.
- ASSERT_TRUE(Pause(&listener));
-
- // Resuming the pause.
- ASSERT_TRUE(Resume(&listener));
-
- // Not paused, should fail.
- EXPECT_FALSE(syncer_thread()->RequestResume());
-
- // Request a pause.
- ASSERT_TRUE(Pause(&listener));
-
- // Nudge the syncer, this should do nothing while we are paused.
- syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown);
-
- // Resuming will cause the nudge to be processed and a sync cycle to run.
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNC_CYCLE_ENDED))).
- WillOnce(SignalEvent(&sync_cycle_ended_event));
- ASSERT_TRUE(Resume(&listener));
- ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
-
- EXPECT_TRUE(syncer_thread()->Stop(2000));
-}
-
-TEST_F(SyncerThreadWithSyncerTest, StartWhenNotConnected) {
- WaitableEvent sync_cycle_ended_event(false, false);
- WaitableEvent event(false, false);
- ListenerMock listener;
- TestScopedSessionEventListener reg(context_, &listener);
- PreventThreadFromPolling();
-
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::STATUS_CHANGED))).
- Times(AnyNumber());
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_EXITING)));
-
- connection()->SetServerNotReachable();
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
-
- // Syncer thread will always go through once cycle at the start,
- // then it will wait for a connection.
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNC_CYCLE_ENDED))).
- WillOnce(SignalEvent(&sync_cycle_ended_event));
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_WAITING_FOR_CONNECTION))).
- WillOnce(SignalEvent(&event));
- ASSERT_TRUE(syncer_thread()->Start());
- ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
- ASSERT_TRUE(event.TimedWait(max_wait_time_));
-
- // Connect, will put the syncer thread into its usually poll wait.
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_CONNECTED))).
- WillOnce(SignalEvent(&event));
- connection()->SetServerReachable();
- ASSERT_TRUE(event.TimedWait(max_wait_time_));
-
- // Nudge the syncer to complete a cycle.
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNC_CYCLE_ENDED))).
- WillOnce(SignalEvent(&sync_cycle_ended_event));
- syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown);
- ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
-
- EXPECT_TRUE(syncer_thread()->Stop(2000));
-}
-
-// See TODO comment on the "Pause" test above.
-TEST_F(SyncerThreadWithSyncerTest, DISABLED_PauseWhenNotConnected) {
- WaitableEvent sync_cycle_ended_event(false, false);
- WaitableEvent event(false, false);
- ListenerMock listener;
- TestScopedSessionEventListener reg(context_, &listener);
- PreventThreadFromPolling();
-
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::STATUS_CHANGED))).
- Times(AnyNumber());
-
- // Put the thread into a "waiting for connection" state.
- connection()->SetServerNotReachable();
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNC_CYCLE_ENDED))).
- WillOnce(SignalEvent(&sync_cycle_ended_event));
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_WAITING_FOR_CONNECTION))).
- WillOnce(SignalEvent(&event));
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
-
- ASSERT_TRUE(syncer_thread()->Start());
- ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
- ASSERT_TRUE(event.TimedWait(max_wait_time_));
-
- // Pause and resume the thread while waiting for a connection.
- ASSERT_TRUE(Pause(&listener));
- ASSERT_TRUE(Resume(&listener));
-
- // Make a connection and let the syncer cycle.
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNC_CYCLE_ENDED))).
- WillOnce(SignalEvent(&sync_cycle_ended_event));
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_CONNECTED))).
- WillOnce(SignalEvent(&event));
- connection()->SetServerReachable();
- ASSERT_TRUE(event.TimedWait(max_wait_time_));
- syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown);
- ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
-
- // Disconnect and get into the waiting for a connection state.
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_WAITING_FOR_CONNECTION))).
- WillOnce(SignalEvent(&event));
- connection()->SetServerNotReachable();
- ASSERT_TRUE(event.TimedWait(max_wait_time_));
-
- // Pause so we can test getting a connection while paused.
- ASSERT_TRUE(Pause(&listener));
-
- // Get a connection then resume.
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_CONNECTED))).
- WillOnce(SignalEvent(&event));
- connection()->SetServerReachable();
- ASSERT_TRUE(event.TimedWait(max_wait_time_));
-
- ASSERT_TRUE(Resume(&listener));
-
- // Cycle the syncer to show we are not longer paused.
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNC_CYCLE_ENDED))).
- WillOnce(SignalEvent(&sync_cycle_ended_event));
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_EXITING)));
-
- syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown);
- ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
-
- EXPECT_TRUE(syncer_thread()->Stop(2000));
-}
-
-TEST_F(SyncerThreadWithSyncerTest, PauseResumeWhenNotRunning) {
- WaitableEvent sync_cycle_ended_event(false, false);
- WaitableEvent event(false, false);
- ListenerMock listener;
- TestScopedSessionEventListener reg(context_, &listener);
- PreventThreadFromPolling();
-
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::STATUS_CHANGED))).
- Times(AnyNumber());
-
- // Pause and resume the syncer while not running
- ASSERT_TRUE(Pause(&listener));
- ASSERT_TRUE(Resume(&listener));
-
- // Pause the thread then start the syncer.
- ASSERT_TRUE(Pause(&listener));
- metadb()->Open();
- syncer_thread()->CreateSyncer(metadb()->name());
- ASSERT_TRUE(syncer_thread()->Start());
-
- // Resume and let the syncer cycle.
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNC_CYCLE_ENDED))).
- WillOnce(SignalEvent(&sync_cycle_ended_event));
- EXPECT_CALL(listener, OnSyncEngineEvent(
- Field(&SyncEngineEvent::what_happened,
- SyncEngineEvent::SYNCER_THREAD_EXITING)));
-
- ASSERT_TRUE(Resume(&listener));
- ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
- EXPECT_TRUE(syncer_thread()->Stop(2000));
-}
-
-} // namespace browser_sync
diff --git a/chrome/browser/sync/engine/syncer_types.h b/chrome/browser/sync/engine/syncer_types.h
index 50f079f..c4612c6 100644
--- a/chrome/browser/sync/engine/syncer_types.h
+++ b/chrome/browser/sync/engine/syncer_types.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
@@ -83,33 +83,6 @@ struct SyncEngineEvent {
SYNC_CYCLE_ENDED,
////////////////////////////////////////////////////////////////
- // SyncerThread generated events.
-
- // This event is sent when the thread is paused in response to a
- // pause request.
- // TODO(tim): Deprecated.
- SYNCER_THREAD_PAUSED,
-
- // This event is sent when the thread is resumed in response to a
- // resume request.
- // TODO(tim): Deprecated.
- SYNCER_THREAD_RESUMED,
-
- // This event is sent when the thread is waiting for a connection
- // to be established.
- // TODO(tim): Deprecated.
- SYNCER_THREAD_WAITING_FOR_CONNECTION,
-
- // This event is sent when a connection has been established and
- // the thread continues.
- // TODO(tim): Deprecated.
- SYNCER_THREAD_CONNECTED,
-
- // Sent when the main syncer loop finishes.
- // TODO(tim): Deprecated.
- SYNCER_THREAD_EXITING,
-
- ////////////////////////////////////////////////////////////////
// Generated in response to specific protocol actions or events.
// New token in updated_token.
diff --git a/chrome/browser/sync/glue/data_type_manager.h b/chrome/browser/sync/glue/data_type_manager.h
index 4bce344..0a42660 100644
--- a/chrome/browser/sync/glue/data_type_manager.h
+++ b/chrome/browser/sync/glue/data_type_manager.h
@@ -25,15 +25,10 @@ class DataTypeManager {
// complete the initial download of new data
// types.
- // TODO(tim): Deprecated. Bug 26339.
- PAUSE_PENDING, // Waiting for the sync backend to pause.
CONFIGURING, // Data types are being started.
BLOCKED, // We can't move forward with configuration because some
// external action must take place (i.e. passphrase).
- // TODO(tim): Deprecated. Bug 26339.
- RESUME_PENDING, // Waiting for the sync backend to resume.
-
CONFIGURED, // All enabled data types are running.
STOPPING // Data types are being stopped.
};
diff --git a/chrome/browser/sync/glue/data_type_manager_impl.cc b/chrome/browser/sync/glue/data_type_manager_impl.cc
index 2514c3e..f8aefed 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl.cc
+++ b/chrome/browser/sync/glue/data_type_manager_impl.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/browser/sync/glue/data_type_manager_impl.h"
+
#include <algorithm>
#include <functional>
+#include "base/compiler_specific.h"
#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/task.h"
#include "chrome/browser/sync/glue/data_type_controller.h"
-#include "chrome/browser/sync/glue/data_type_manager_impl.h"
#include "chrome/browser/sync/glue/sync_backend_host.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_details.h"
@@ -21,16 +21,23 @@ namespace browser_sync {
namespace {
static const syncable::ModelType kStartOrder[] = {
+ syncable::NIGORI, // Listed for completeness.
syncable::BOOKMARKS,
syncable::PREFERENCES,
syncable::AUTOFILL,
syncable::AUTOFILL_PROFILE,
+ syncable::EXTENSIONS,
+ syncable::APPS,
syncable::THEMES,
syncable::TYPED_URLS,
syncable::PASSWORDS,
syncable::SESSIONS,
};
+COMPILE_ASSERT(arraysize(kStartOrder) ==
+ syncable::MODEL_TYPE_COUNT - syncable::FIRST_REAL_MODEL_TYPE,
+ kStartOrder_IncorrectSize);
+
// Comparator used when sorting data type controllers.
class SortComparator : public std::binary_function<DataTypeController*,
DataTypeController*,
@@ -50,18 +57,14 @@ class SortComparator : public std::binary_function<DataTypeController*,
} // namespace
-DataTypeManagerImpl::DataTypeManagerImpl(
- SyncBackendHost* backend,
+DataTypeManagerImpl::DataTypeManagerImpl(SyncBackendHost* backend,
const DataTypeController::TypeMap& controllers)
: backend_(backend),
controllers_(controllers),
state_(DataTypeManager::STOPPED),
- syncer_paused_(false),
needs_reconfigure_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
DCHECK(backend_);
- DCHECK_GT(arraysize(kStartOrder), 0U);
// Ensure all data type controllers are stopped.
for (DataTypeController::TypeMap::const_iterator it = controllers_.begin();
it != controllers_.end(); ++it) {
@@ -73,8 +76,7 @@ DataTypeManagerImpl::DataTypeManagerImpl(
start_order_[kStartOrder[i]] = i;
}
-DataTypeManagerImpl::~DataTypeManagerImpl() {
-}
+DataTypeManagerImpl::~DataTypeManagerImpl() {}
bool DataTypeManagerImpl::GetControllersNeedingStart(
std::vector<DataTypeController*>* needs_start) {
@@ -147,7 +149,6 @@ void DataTypeManagerImpl::Configure(const TypeSet& desired_types) {
}
void DataTypeManagerImpl::Restart() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
VLOG(1) << "Restarting...";
DCHECK(state_ == STOPPED || state_ == CONFIGURED || state_ == BLOCKED);
@@ -171,50 +172,13 @@ void DataTypeManagerImpl::Restart() {
controllers_,
last_requested_types_,
method_factory_.NewRunnableMethod(&DataTypeManagerImpl::DownloadReady));
-
- // If there were new types needing download, a nudge will have been sent and
- // we should be in DOWNLOAD_PENDING. In that case we start the syncer thread
- // (which is idempotent) to fetch these updates.
- // However, we could actually be in PAUSE_PENDING here as if no new types
- // were needed, our DownloadReady callback will have fired and we will have
- // requested a pause already (so starting the syncer thread will still not
- // let it make forward progress as the pause needs to be resumed by us).
- // Because both the pause and start syncing commands are posted FCFS to the
- // core thread, there is no race between the pause and the start; the pause
- // will always win, so we will always start paused if we don't need to
- // download new types. Thus, in almost all cases, the syncer thread DOES NOT
- // start before model association. But...
- //
- // TODO(tim): Bug 47957. There is still subtle badness here. If we just
- // restarted the browser and were upgraded in between, we may be in a state
- // where a bunch of data types do have initial sync ended, but a new guy
- // does not. In this case, what we really want is to _only_ download updates
- // for that new type and not the ones that have already finished and we've
- // presumably associated before. What happens now is the syncer is nudged
- // and it does a sync from timestamp 0 for only the new types, and sends the
- // OnSyncCycleCompleted event, which is how we get the DownloadReady call.
- // We request a pause at this point, but it is done asynchronously. So in
- // theory, the syncer could charge forward with another sync (for _all_
- // types) before the pause is serviced, which could be bad for associating
- // models as we'll merge the present cloud with the immediate past, which
- // opens the door to bugs like "bookmark came back from dead". A lot more
- // stars have to align now for this to happen, but it's still there.
- backend_->StartSyncingWithServer();
}
void DataTypeManagerImpl::DownloadReady() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(state_ == DOWNLOAD_PENDING);
- if (syncer_paused_) {
- state_ = CONFIGURING;
- StartNextType();
- return;
- }
-
- // Pause the sync backend before starting the data types.
- state_ = PAUSE_PENDING;
- PauseSyncer();
+ state_ = CONFIGURING;
+ StartNextType();
}
void DataTypeManagerImpl::StartNextType() {
@@ -236,7 +200,7 @@ void DataTypeManagerImpl::StartNextType() {
// the most recent set of desired types, so we just call configure.
// Note: we do this whether or not GetControllersNeedingStart is true,
// because we may need to stop datatypes.
- state_ = BLOCKED;
+ SetBlockedAndNotify();
needs_reconfigure_ = false;
VLOG(1) << "Reconfiguring due to previous configure attempt occuring while"
<< " busy.";
@@ -248,14 +212,13 @@ void DataTypeManagerImpl::StartNextType() {
// things like encryption, which may still need to be sorted out before we
// can announce we're "Done" configuration entirely.
if (GetControllersNeedingStart(NULL)) {
- state_ = BLOCKED;
+ SetBlockedAndNotify();
return;
}
- // If no more data types need starting, we're done. Resume the sync backend
- // to finish.
- state_ = RESUME_PENDING;
- ResumeSyncer();
+ // If no more data types need starting, we're done.
+ state_ = CONFIGURED;
+ NotifyDone(OK, FROM_HERE);
}
void DataTypeManagerImpl::TypeStartCallback(
@@ -265,40 +228,35 @@ void DataTypeManagerImpl::TypeStartCallback(
// on the UI thread.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // We're done with the data type at the head of the list -- remove it.
- DataTypeController* started_dtc = needs_start_[0];
- DCHECK(needs_start_.size());
- DCHECK_EQ(needs_start_[0], started_dtc);
- needs_start_.erase(needs_start_.begin());
-
- // If we reach this callback while stopping, this means that
- // DataTypeManager::Stop() was called while the current data type
- // was starting. Now that it has finished starting, we can finish
- // stopping the DataTypeManager. This is considered an ABORT.
if (state_ == STOPPING) {
+ // If we reach this callback while stopping, this means that
+ // DataTypeManager::Stop() was called while the current data type
+ // was starting. Now that it has finished starting, we can finish
+ // stopping the DataTypeManager. This is considered an ABORT.
FinishStopAndNotify(ABORTED, FROM_HERE);
return;
- }
-
- // If our state_ is STOPPED, we have already stopped all of the data
- // types. We should not be getting callbacks from stopped data types.
- if (state_ == STOPPED) {
+ } else if (state_ == STOPPED) {
+ // If our state_ is STOPPED, we have already stopped all of the data
+ // types. We should not be getting callbacks from stopped data types.
LOG(ERROR) << "Start callback called by stopped data type!";
return;
}
- // If the type is waiting for the cryptographer, continue to the next type.
- // Once the cryptographer is ready, we'll attempt to restart this type.
+ // We're done with the data type at the head of the list -- remove it.
+ DataTypeController* started_dtc = needs_start_[0];
+ DCHECK(needs_start_.size());
+ DCHECK_EQ(needs_start_[0], started_dtc);
+ needs_start_.erase(needs_start_.begin());
+
if (result == DataTypeController::NEEDS_CRYPTO) {
- VLOG(1) << "Waiting for crypto " << started_dtc->name();
- StartNextType();
- return;
- }
+ }
// If the type started normally, continue to the next type.
- if (result == DataTypeController::OK ||
+ // If the type is waiting for the cryptographer, continue to the next type.
+ // Once the cryptographer is ready, we'll attempt to restart this type.
+ if (result == DataTypeController::NEEDS_CRYPTO ||
+ result == DataTypeController::OK ||
result == DataTypeController::OK_FIRST_RUN) {
- VLOG(1) << "Started " << started_dtc->name();
StartNextType();
return;
}
@@ -347,49 +305,21 @@ void DataTypeManagerImpl::Stop() {
return;
}
- // If Stop() is called while waiting for pause or resume, we no
- // longer care about this.
- bool aborted = false;
- if (state_ == PAUSE_PENDING) {
- RemoveObserver(NotificationType::SYNC_PAUSED);
- aborted = true;
- }
- if (state_ == RESUME_PENDING) {
- RemoveObserver(NotificationType::SYNC_RESUMED);
- aborted = true;
- }
-
- // If Stop() is called while waiting for download, cancel all
- // outstanding tasks.
- if (state_ == DOWNLOAD_PENDING) {
- method_factory_.RevokeAll();
- aborted = true;
- }
-
+ const bool download_pending = state_ == DOWNLOAD_PENDING;
state_ = STOPPING;
- if (aborted)
+ if (download_pending) {
+ // If Stop() is called while waiting for download, cancel all
+ // outstanding tasks.
+ method_factory_.RevokeAll();
FinishStopAndNotify(ABORTED, FROM_HERE);
- else
- FinishStop();
-}
-
-const DataTypeController::TypeMap& DataTypeManagerImpl::controllers() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return controllers_;
-}
+ return;
+ }
-DataTypeManager::State DataTypeManagerImpl::state() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return state_;
+ FinishStop();
}
void DataTypeManagerImpl::FinishStop() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(state_== CONFIGURING ||
- state_ == STOPPING ||
- state_ == PAUSE_PENDING ||
- state_ == RESUME_PENDING ||
- state_ == BLOCKED);
+ DCHECK(state_== CONFIGURING || state_ == STOPPING || state_ == BLOCKED);
// Simply call the Stop() method on all running data types.
for (DataTypeController::TypeMap::const_iterator it = controllers_.begin();
it != controllers_.end(); ++it) {
@@ -405,70 +335,11 @@ void DataTypeManagerImpl::FinishStop() {
void DataTypeManagerImpl::FinishStopAndNotify(ConfigureResult result,
const tracked_objects::Location& location) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
FinishStop();
NotifyDone(result, location);
}
-void DataTypeManagerImpl::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- switch (type.value) {
- case NotificationType::SYNC_PAUSED:
- DCHECK(state_ == PAUSE_PENDING);
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- syncer_paused_ = true;
- RemoveObserver(NotificationType::SYNC_PAUSED);
-
- state_ = CONFIGURING;
- StartNextType();
- break;
- case NotificationType::SYNC_RESUMED:
- DCHECK(state_ == RESUME_PENDING);
- RemoveObserver(NotificationType::SYNC_RESUMED);
- syncer_paused_ = false;
-
- if (needs_reconfigure_) {
- // An attempt was made to reconfigure while we were already configuring.
- // This can be because a passphrase was accepted or the user changed the
- // set of desired types. Either way, |last_requested_types_| will
- // contain the most recent set of desired types, so we just call
- // configure.
- // Note: we do this whether or not GetControllersNeedingStart is true,
- // because we may need to stop datatypes.
- state_ = BLOCKED;
- needs_reconfigure_ = false;
- VLOG(1) << "Reconfiguring due to previous configure attempt occuring "
- << " while busy.";
- Configure(last_requested_types_);
- return;
- }
-
- state_ = CONFIGURED;
- NotifyDone(OK, FROM_HERE);
- break;
- default:
- NOTREACHED();
- }
-}
-
-void DataTypeManagerImpl::AddObserver(NotificationType type) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- notification_registrar_.Add(this,
- type,
- NotificationService::AllSources());
-}
-
-void DataTypeManagerImpl::RemoveObserver(NotificationType type) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- notification_registrar_.Remove(this,
- type,
- NotificationService::AllSources());
-}
-
void DataTypeManagerImpl::NotifyStart() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
NotificationService::current()->Notify(
NotificationType::SYNC_CONFIGURE_START,
Source<DataTypeManager>(this),
@@ -477,7 +348,6 @@ void DataTypeManagerImpl::NotifyStart() {
void DataTypeManagerImpl::NotifyDone(ConfigureResult result,
const tracked_objects::Location& location) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ConfigureResultWithErrorLocation result_with_location(result, location);
NotificationService::current()->Notify(
NotificationType::SYNC_CONFIGURE_DONE,
@@ -485,22 +355,20 @@ void DataTypeManagerImpl::NotifyDone(ConfigureResult result,
Details<ConfigureResultWithErrorLocation>(&result_with_location));
}
-void DataTypeManagerImpl::ResumeSyncer() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- AddObserver(NotificationType::SYNC_RESUMED);
- if (!backend_->RequestResume()) {
- RemoveObserver(NotificationType::SYNC_RESUMED);
- FinishStopAndNotify(UNRECOVERABLE_ERROR, FROM_HERE);
- }
+const DataTypeController::TypeMap& DataTypeManagerImpl::controllers() {
+ return controllers_;
}
-void DataTypeManagerImpl::PauseSyncer() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- AddObserver(NotificationType::SYNC_PAUSED);
- if (!backend_->RequestPause()) {
- RemoveObserver(NotificationType::SYNC_PAUSED);
- FinishStopAndNotify(UNRECOVERABLE_ERROR, FROM_HERE);
- }
+DataTypeManager::State DataTypeManagerImpl::state() {
+ return state_;
+}
+
+void DataTypeManagerImpl::SetBlockedAndNotify() {
+ state_ = BLOCKED;
+ NotificationService::current()->Notify(
+ NotificationType::SYNC_CONFIGURE_BLOCKED,
+ Source<DataTypeManager>(this),
+ NotificationService::NoDetails());
}
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/data_type_manager_impl.h b/chrome/browser/sync/glue/data_type_manager_impl.h
index 0f23aed..841af2b 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl.h
+++ b/chrome/browser/sync/glue/data_type_manager_impl.h
@@ -13,39 +13,24 @@
#include "base/basictypes.h"
#include "base/task.h"
-#include "content/common/notification_observer.h"
-#include "content/common/notification_registrar.h"
-#include "content/common/notification_type.h"
-
-class NotificationSource;
-class NotificationDetails;
namespace browser_sync {
class DataTypeController;
class SyncBackendHost;
-class DataTypeManagerImpl : public DataTypeManager,
- public NotificationObserver {
+class DataTypeManagerImpl : public DataTypeManager {
public:
DataTypeManagerImpl(SyncBackendHost* backend,
- const DataTypeController::TypeMap& controllers);
+ const DataTypeController::TypeMap& controllers);
virtual ~DataTypeManagerImpl();
// DataTypeManager interface.
virtual void Configure(const TypeSet& desired_types);
-
virtual void Stop();
-
virtual const DataTypeController::TypeMap& controllers();
-
virtual State state();
- // NotificationObserver implementation.
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
-
private:
// Starts the next data type in the kStartOrder list, indicated by
// the current_type_ member. If there are no more data types to
@@ -54,12 +39,12 @@ class DataTypeManagerImpl : public DataTypeManager,
// Callback passed to each data type controller on startup.
void TypeStartCallback(DataTypeController::StartResult result,
- const tracked_objects::Location& location);
+ const tracked_objects::Location& from_here);
// Stops all data types.
void FinishStop();
void FinishStopAndNotify(ConfigureResult result,
- const tracked_objects::Location& location);
+ const tracked_objects::Location& location);
// Returns true if any last_requested_types_ currently needs to start model
// association. If non-null, fills |needs_start| with all such controllers.
@@ -68,13 +53,10 @@ class DataTypeManagerImpl : public DataTypeManager,
void Restart();
void DownloadReady();
- void AddObserver(NotificationType type);
- void RemoveObserver(NotificationType type);
void NotifyStart();
void NotifyDone(ConfigureResult result,
- const tracked_objects::Location& location);
- void ResumeSyncer();
- void PauseSyncer();
+ const tracked_objects::Location& location);
+ void SetBlockedAndNotify();
SyncBackendHost* backend_;
// Map of all data type controllers that are available for sync.
@@ -86,14 +68,10 @@ class DataTypeManagerImpl : public DataTypeManager,
std::vector<DataTypeController*> needs_start_;
std::vector<DataTypeController*> needs_stop_;
- // Whether we've observed a SYNC_PAUSED but not SYNC_RESUMED.
- bool syncer_paused_;
-
// Whether an attempt to reconfigure was made while we were busy configuring.
// The |last_requested_types_| will reflect the newest set of requested types.
bool needs_reconfigure_;
- NotificationRegistrar notification_registrar_;
ScopedRunnableMethodFactory<DataTypeManagerImpl> method_factory_;
DISALLOW_COPY_AND_ASSIGN(DataTypeManagerImpl);
diff --git a/chrome/browser/sync/glue/data_type_manager_impl2.cc b/chrome/browser/sync/glue/data_type_manager_impl2.cc
deleted file mode 100644
index 58a66b4..0000000
--- a/chrome/browser/sync/glue/data_type_manager_impl2.cc
+++ /dev/null
@@ -1,363 +0,0 @@
-// 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/glue/data_type_manager_impl2.h"
-
-#include <algorithm>
-#include <functional>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "chrome/browser/sync/glue/data_type_controller.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include "content/browser/browser_thread.h"
-#include "content/common/notification_details.h"
-#include "content/common/notification_service.h"
-#include "content/common/notification_source.h"
-
-namespace browser_sync {
-
-namespace {
-
-static const syncable::ModelType kStartOrder[] = {
- syncable::NIGORI, // Listed for completeness.
- syncable::BOOKMARKS,
- syncable::PREFERENCES,
- syncable::AUTOFILL,
- syncable::AUTOFILL_PROFILE,
- syncable::EXTENSIONS,
- syncable::APPS,
- syncable::THEMES,
- syncable::TYPED_URLS,
- syncable::PASSWORDS,
- syncable::SESSIONS,
-};
-
-COMPILE_ASSERT(arraysize(kStartOrder) ==
- syncable::MODEL_TYPE_COUNT - syncable::FIRST_REAL_MODEL_TYPE,
- kStartOrder_IncorrectSize);
-
-// Comparator used when sorting data type controllers.
-class SortComparator : public std::binary_function<DataTypeController*,
- DataTypeController*,
- bool> {
- public:
- explicit SortComparator(std::map<syncable::ModelType, int>* order)
- : order_(order) { }
-
- // Returns true if lhs precedes rhs.
- bool operator() (DataTypeController* lhs, DataTypeController* rhs) {
- return (*order_)[lhs->type()] < (*order_)[rhs->type()];
- }
-
- private:
- std::map<syncable::ModelType, int>* order_;
-};
-
-} // namespace
-
-DataTypeManagerImpl2::DataTypeManagerImpl2(SyncBackendHost* backend,
- const DataTypeController::TypeMap& controllers)
- : backend_(backend),
- controllers_(controllers),
- state_(DataTypeManager::STOPPED),
- needs_reconfigure_(false),
- method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
- DCHECK(backend_);
- // Ensure all data type controllers are stopped.
- for (DataTypeController::TypeMap::const_iterator it = controllers_.begin();
- it != controllers_.end(); ++it) {
- DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state());
- }
-
- // Build a ModelType -> order map for sorting.
- for (int i = 0; i < static_cast<int>(arraysize(kStartOrder)); i++)
- start_order_[kStartOrder[i]] = i;
-}
-
-DataTypeManagerImpl2::~DataTypeManagerImpl2() {}
-
-bool DataTypeManagerImpl2::GetControllersNeedingStart(
- std::vector<DataTypeController*>* needs_start) {
- // Add any data type controllers into the needs_start_ list that are
- // currently NOT_RUNNING or STOPPING.
- bool found_any = false;
- for (TypeSet::const_iterator it = last_requested_types_.begin();
- it != last_requested_types_.end(); ++it) {
- DataTypeController::TypeMap::const_iterator dtc = controllers_.find(*it);
- if (dtc != controllers_.end() &&
- (dtc->second->state() == DataTypeController::NOT_RUNNING ||
- dtc->second->state() == DataTypeController::STOPPING)) {
- found_any = true;
- if (needs_start)
- needs_start->push_back(dtc->second.get());
- }
- }
- return found_any;
-}
-
-void DataTypeManagerImpl2::Configure(const TypeSet& desired_types) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (state_ == STOPPING) {
- // You can not set a configuration while stopping.
- LOG(ERROR) << "Configuration set while stopping.";
- return;
- }
-
- last_requested_types_ = desired_types;
- // Only proceed if we're in a steady state or blocked.
- if (state_ != STOPPED && state_ != CONFIGURED && state_ != BLOCKED) {
- VLOG(1) << "Received configure request while configuration in flight. "
- << "Postponing until current configuration complete.";
- needs_reconfigure_ = true;
- return;
- }
-
- needs_start_.clear();
- GetControllersNeedingStart(&needs_start_);
- // Sort these according to kStartOrder.
- std::sort(needs_start_.begin(),
- needs_start_.end(),
- SortComparator(&start_order_));
-
- // Add any data type controllers into that needs_stop_ list that are
- // currently MODEL_STARTING, ASSOCIATING, or RUNNING.
- needs_stop_.clear();
- for (DataTypeController::TypeMap::const_iterator it = controllers_.begin();
- it != controllers_.end(); ++it) {
- DataTypeController* dtc = (*it).second;
- if (desired_types.count(dtc->type()) == 0 && (
- dtc->state() == DataTypeController::MODEL_STARTING ||
- dtc->state() == DataTypeController::ASSOCIATING ||
- dtc->state() == DataTypeController::RUNNING)) {
- needs_stop_.push_back(dtc);
- VLOG(1) << "Will stop " << dtc->name();
- }
- }
- // Sort these according to kStartOrder.
- std::sort(needs_stop_.begin(),
- needs_stop_.end(),
- SortComparator(&start_order_));
-
- // Restart to start/stop data types and notify the backend that the
- // desired types have changed (need to do this even if there aren't any
- // types to start/stop, because it could be that some types haven't
- // started due to crypto errors but the backend host needs to know that we're
- // disabling them anyway).
- Restart();
-}
-
-void DataTypeManagerImpl2::Restart() {
- VLOG(1) << "Restarting...";
-
- DCHECK(state_ == STOPPED || state_ == CONFIGURED || state_ == BLOCKED);
-
- // Starting from a "steady state" (stopped or configured) state
- // should send a start notification.
- if (state_ == STOPPED || state_ == CONFIGURED)
- NotifyStart();
-
- // Stop requested data types.
- for (size_t i = 0; i < needs_stop_.size(); ++i) {
- VLOG(1) << "Stopping " << needs_stop_[i]->name();
- needs_stop_[i]->Stop();
- }
- needs_stop_.clear();
-
- // Tell the backend about the new set of data types we wish to sync.
- // The task will be invoked when updates are downloaded.
- state_ = DOWNLOAD_PENDING;
- backend_->ConfigureDataTypes(
- controllers_,
- last_requested_types_,
- method_factory_.NewRunnableMethod(&DataTypeManagerImpl2::DownloadReady));
-}
-
-void DataTypeManagerImpl2::DownloadReady() {
- DCHECK(state_ == DOWNLOAD_PENDING);
-
- state_ = CONFIGURING;
- StartNextType();
-}
-
-void DataTypeManagerImpl2::StartNextType() {
- // If there are any data types left to start, start the one at the
- // front of the list.
- if (!needs_start_.empty()) {
- VLOG(1) << "Starting " << needs_start_[0]->name();
- needs_start_[0]->Start(
- NewCallback(this, &DataTypeManagerImpl2::TypeStartCallback));
- return;
- }
-
- DCHECK_EQ(state_, CONFIGURING);
-
- if (needs_reconfigure_) {
- // An attempt was made to reconfigure while we were already configuring.
- // This can be because a passphrase was accepted or the user changed the
- // set of desired types. Either way, |last_requested_types_| will contain
- // the most recent set of desired types, so we just call configure.
- // Note: we do this whether or not GetControllersNeedingStart is true,
- // because we may need to stop datatypes.
- state_ = BLOCKED;
- needs_reconfigure_ = false;
- VLOG(1) << "Reconfiguring due to previous configure attempt occuring while"
- << " busy.";
- Configure(last_requested_types_);
- return;
- }
-
- // Do a fresh calculation to see if controllers need starting to account for
- // things like encryption, which may still need to be sorted out before we
- // can announce we're "Done" configuration entirely.
- if (GetControllersNeedingStart(NULL)) {
- state_ = BLOCKED;
- return;
- }
-
- // If no more data types need starting, we're done.
- state_ = CONFIGURED;
- NotifyDone(OK, FROM_HERE);
-}
-
-void DataTypeManagerImpl2::TypeStartCallback(
- DataTypeController::StartResult result,
- const tracked_objects::Location& location) {
- // When the data type controller invokes this callback, it must be
- // on the UI thread.
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (state_ == STOPPING) {
- // If we reach this callback while stopping, this means that
- // DataTypeManager::Stop() was called while the current data type
- // was starting. Now that it has finished starting, we can finish
- // stopping the DataTypeManager. This is considered an ABORT.
- FinishStopAndNotify(ABORTED, FROM_HERE);
- return;
- } else if (state_ == STOPPED) {
- // If our state_ is STOPPED, we have already stopped all of the data
- // types. We should not be getting callbacks from stopped data types.
- LOG(ERROR) << "Start callback called by stopped data type!";
- return;
- }
-
- // We're done with the data type at the head of the list -- remove it.
- DataTypeController* started_dtc = needs_start_[0];
- DCHECK(needs_start_.size());
- DCHECK_EQ(needs_start_[0], started_dtc);
- needs_start_.erase(needs_start_.begin());
-
- // If the type started normally, continue to the next type.
- // If the type is waiting for the cryptographer, continue to the next type.
- // Once the cryptographer is ready, we'll attempt to restart this type.
- if (result == DataTypeController::NEEDS_CRYPTO ||
- result == DataTypeController::OK ||
- result == DataTypeController::OK_FIRST_RUN) {
- StartNextType();
- return;
- }
-
- // Any other result is a fatal error. Shut down any types we've
- // managed to start up to this point and pass the result to the
- // callback.
- VLOG(1) << "Failed " << started_dtc->name();
- ConfigureResult configure_result = DataTypeManager::ABORTED;
- switch (result) {
- case DataTypeController::ABORTED:
- configure_result = DataTypeManager::ABORTED;
- break;
- case DataTypeController::ASSOCIATION_FAILED:
- configure_result = DataTypeManager::ASSOCIATION_FAILED;
- break;
- case DataTypeController::UNRECOVERABLE_ERROR:
- configure_result = DataTypeManager::UNRECOVERABLE_ERROR;
- break;
- default:
- NOTREACHED();
- break;
- }
- FinishStopAndNotify(configure_result, location);
-}
-
-void DataTypeManagerImpl2::Stop() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (state_ == STOPPED)
- return;
-
- // If we are currently configuring, then the current type is in a
- // partially started state. Abort the startup of the current type,
- // which will synchronously invoke the start callback.
- if (state_ == CONFIGURING) {
- state_ = STOPPING;
-
- DCHECK_LT(0U, needs_start_.size());
- needs_start_[0]->Stop();
-
- // By this point, the datatype should have invoked the start callback,
- // triggering FinishStop to be called, and the state to reach STOPPED. If we
- // aren't STOPPED, it means that a datatype controller didn't call the start
- // callback appropriately.
- DCHECK_EQ(STOPPED, state_);
- return;
- }
-
- const bool download_pending = state_ == DOWNLOAD_PENDING;
- state_ = STOPPING;
- if (download_pending) {
- // If Stop() is called while waiting for download, cancel all
- // outstanding tasks.
- method_factory_.RevokeAll();
- FinishStopAndNotify(ABORTED, FROM_HERE);
- return;
- }
-
- FinishStop();
-}
-
-void DataTypeManagerImpl2::FinishStop() {
- DCHECK(state_== CONFIGURING || state_ == STOPPING || state_ == BLOCKED);
- // Simply call the Stop() method on all running data types.
- for (DataTypeController::TypeMap::const_iterator it = controllers_.begin();
- it != controllers_.end(); ++it) {
- DataTypeController* dtc = (*it).second;
- if (dtc->state() != DataTypeController::NOT_RUNNING &&
- dtc->state() != DataTypeController::STOPPING) {
- dtc->Stop();
- VLOG(1) << "Stopped " << dtc->name();
- }
- }
- state_ = STOPPED;
-}
-
-void DataTypeManagerImpl2::FinishStopAndNotify(ConfigureResult result,
- const tracked_objects::Location& location) {
- FinishStop();
- NotifyDone(result, location);
-}
-
-void DataTypeManagerImpl2::NotifyStart() {
- NotificationService::current()->Notify(
- NotificationType::SYNC_CONFIGURE_START,
- Source<DataTypeManager>(this),
- NotificationService::NoDetails());
-}
-
-void DataTypeManagerImpl2::NotifyDone(ConfigureResult result,
- const tracked_objects::Location& location) {
- ConfigureResultWithErrorLocation result_with_location(result, location);
- NotificationService::current()->Notify(
- NotificationType::SYNC_CONFIGURE_DONE,
- Source<DataTypeManager>(this),
- Details<ConfigureResultWithErrorLocation>(&result_with_location));
-}
-
-const DataTypeController::TypeMap& DataTypeManagerImpl2::controllers() {
- return controllers_;
-}
-
-DataTypeManager::State DataTypeManagerImpl2::state() {
- return state_;
-}
-
-} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/data_type_manager_impl2.h b/chrome/browser/sync/glue/data_type_manager_impl2.h
deleted file mode 100644
index 1db2908..0000000
--- a/chrome/browser/sync/glue/data_type_manager_impl2.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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.
-
-#ifndef CHROME_BROWSER_SYNC_GLUE_DATA_TYPE_MANAGER_IMPL2_H__
-#define CHROME_BROWSER_SYNC_GLUE_DATA_TYPE_MANAGER_IMPL2_H__
-#pragma once
-
-#include "chrome/browser/sync/glue/data_type_manager.h"
-
-#include <map>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/task.h"
-
-namespace browser_sync {
-
-class DataTypeController;
-class SyncBackendHost;
-
-class DataTypeManagerImpl2 : public DataTypeManager {
- public:
- DataTypeManagerImpl2(SyncBackendHost* backend,
- const DataTypeController::TypeMap& controllers);
- virtual ~DataTypeManagerImpl2();
-
- // DataTypeManager interface.
- virtual void Configure(const TypeSet& desired_types);
- virtual void Stop();
- virtual const DataTypeController::TypeMap& controllers();
- virtual State state();
-
- private:
- // Starts the next data type in the kStartOrder list, indicated by
- // the current_type_ member. If there are no more data types to
- // start, the stashed start_callback_ is invoked.
- void StartNextType();
-
- // Callback passed to each data type controller on startup.
- void TypeStartCallback(DataTypeController::StartResult result,
- const tracked_objects::Location& from_here);
-
- // Stops all data types.
- void FinishStop();
- void FinishStopAndNotify(ConfigureResult result,
- const tracked_objects::Location& location);
-
- // Returns true if any last_requested_types_ currently needs to start model
- // association. If non-null, fills |needs_start| with all such controllers.
- bool GetControllersNeedingStart(
- std::vector<DataTypeController*>* needs_start);
-
- void Restart();
- void DownloadReady();
- void NotifyStart();
- void NotifyDone(ConfigureResult result,
- const tracked_objects::Location& location);
-
- SyncBackendHost* backend_;
- // Map of all data type controllers that are available for sync.
- // This list is determined at startup by various command line flags.
- const DataTypeController::TypeMap controllers_;
- State state_;
- std::map<syncable::ModelType, int> start_order_;
- TypeSet last_requested_types_;
- std::vector<DataTypeController*> needs_start_;
- std::vector<DataTypeController*> needs_stop_;
-
- // Whether an attempt to reconfigure was made while we were busy configuring.
- // The |last_requested_types_| will reflect the newest set of requested types.
- bool needs_reconfigure_;
-
- ScopedRunnableMethodFactory<DataTypeManagerImpl2> method_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(DataTypeManagerImpl2);
-};
-
-} // namespace browser_sync
-
-#endif // CHROME_BROWSER_SYNC_GLUE_DATA_TYPE_MANAGER_IMPL2_H__
diff --git a/chrome/browser/sync/glue/data_type_manager_impl2_unittest.cc b/chrome/browser/sync/glue/data_type_manager_impl2_unittest.cc
index f7bf741..9c6c690 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl2_unittest.cc
+++ b/chrome/browser/sync/glue/data_type_manager_impl2_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/sync/glue/data_type_manager_impl2.h"
+#include "chrome/browser/sync/glue/data_type_manager_impl.h"
#include <set>
@@ -25,7 +25,7 @@
#include "testing/gtest/include/gtest/gtest.h"
using browser_sync::DataTypeManager;
-using browser_sync::DataTypeManagerImpl2;
+using browser_sync::DataTypeManagerImpl;
using browser_sync::DataTypeController;
using browser_sync::DataTypeControllerMock;
using browser_sync::SyncBackendHostMock;
@@ -163,7 +163,7 @@ class DataTypeManagerImpl2Test : public testing::Test {
};
TEST_F(DataTypeManagerImpl2Test, NoControllers) {
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
SetConfigureStartExpectation();
SetConfigureDoneExpectation(DataTypeManager::OK);
dtm.Configure(types_);
@@ -177,7 +177,7 @@ TEST_F(DataTypeManagerImpl2Test, ConfigureOne) {
SetStartStopExpectations(bookmark_dtc);
controllers_[syncable::BOOKMARKS] = bookmark_dtc;
EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
types_.insert(syncable::BOOKMARKS);
SetConfigureStartExpectation();
SetConfigureDoneExpectation(DataTypeManager::OK);
@@ -193,7 +193,7 @@ TEST_F(DataTypeManagerImpl2Test, ConfigureOneStopWhileStarting) {
DataTypeController::MODEL_STARTING);
controllers_[syncable::BOOKMARKS] = bookmark_dtc;
EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
types_.insert(syncable::BOOKMARKS);
SetConfigureStartExpectation();
SetConfigureDoneExpectation(DataTypeManager::OK);
@@ -208,7 +208,7 @@ TEST_F(DataTypeManagerImpl2Test, ConfigureOneStopWhileAssociating) {
SetBusyStartStopExpectations(bookmark_dtc, DataTypeController::ASSOCIATING);
controllers_[syncable::BOOKMARKS] = bookmark_dtc;
EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
types_.insert(syncable::BOOKMARKS);
SetConfigureStartExpectation();
SetConfigureDoneExpectation(DataTypeManager::OK);
@@ -228,7 +228,7 @@ TEST_F(DataTypeManagerImpl2Test, OneWaitingForCrypto) {
controllers_[syncable::PASSWORDS] = password_dtc;
EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
types_.insert(syncable::PASSWORDS);
SetConfigureStartExpectation();
@@ -264,7 +264,7 @@ TEST_F(DataTypeManagerImpl2Test, ConfigureOneThenAnother) {
controllers_[syncable::PREFERENCES] = preference_dtc;
EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2);
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
types_.insert(syncable::BOOKMARKS);
SetConfigureStartExpectation();
@@ -291,7 +291,7 @@ TEST_F(DataTypeManagerImpl2Test, ConfigureOneThenSwitch) {
controllers_[syncable::PREFERENCES] = preference_dtc;
EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2);
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
types_.insert(syncable::BOOKMARKS);
SetConfigureStartExpectation();
@@ -333,7 +333,7 @@ TEST_F(DataTypeManagerImpl2Test, ConfigureWhileOneInFlight) {
controllers_[syncable::PREFERENCES] = preference_dtc;
EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2);
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
types_.insert(syncable::BOOKMARKS);
SetConfigureStartExpectation();
@@ -362,7 +362,7 @@ TEST_F(DataTypeManagerImpl2Test, OneFailingController) {
WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
controllers_[syncable::BOOKMARKS] = bookmark_dtc;
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
SetConfigureStartExpectation();
SetConfigureDoneExpectation(DataTypeManager::ASSOCIATION_FAILED);
EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
@@ -386,7 +386,7 @@ TEST_F(DataTypeManagerImpl2Test, StopWhileInFlight) {
WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
controllers_[syncable::PREFERENCES] = preference_dtc;
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
SetConfigureStartExpectation();
SetConfigureDoneExpectation(DataTypeManager::ABORTED);
EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
@@ -418,7 +418,7 @@ TEST_F(DataTypeManagerImpl2Test, SecondControllerFails) {
WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
controllers_[syncable::PREFERENCES] = preference_dtc;
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
SetConfigureStartExpectation();
SetConfigureDoneExpectation(DataTypeManager::ASSOCIATION_FAILED);
EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
@@ -438,7 +438,7 @@ TEST_F(DataTypeManagerImpl2Test, ConfigureWhileDownloadPending) {
SetStartStopExpectations(preference_dtc);
controllers_[syncable::PREFERENCES] = preference_dtc;
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
SetConfigureStartExpectation();
SetConfigureDoneExpectation(DataTypeManager::OK);
CancelableTask* task;
@@ -473,7 +473,7 @@ TEST_F(DataTypeManagerImpl2Test, StopWhileDownloadPending) {
SetNotUsedExpectations(bookmark_dtc);
controllers_[syncable::BOOKMARKS] = bookmark_dtc;
- DataTypeManagerImpl2 dtm(&backend_, controllers_);
+ DataTypeManagerImpl dtm(&backend_, controllers_);
SetConfigureStartExpectation();
SetConfigureDoneExpectation(DataTypeManager::ABORTED);
CancelableTask* task;
diff --git a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
index d8d875b..7a37f38 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
+++ b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
@@ -1,688 +1,3 @@
// 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 <set>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop.h"
-#include "base/stl_util-inl.h"
-#include "base/task.h"
-#include "chrome/browser/sync/glue/data_type_controller.h"
-#include "chrome/browser/sync/glue/data_type_controller_mock.h"
-#include "chrome/browser/sync/glue/data_type_manager_impl.h"
-#include "chrome/browser/sync/glue/sync_backend_host_mock.h"
-#include "chrome/browser/sync/profile_sync_test_util.h"
-#include "chrome/browser/sync/syncable/model_type.h"
-#include "content/browser/browser_thread.h"
-#include "content/common/notification_details.h"
-#include "content/common/notification_observer_mock.h"
-#include "content/common/notification_registrar.h"
-#include "content/common/notification_service.h"
-#include "content/common/notification_type.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using browser_sync::DataTypeManager;
-using browser_sync::DataTypeManagerImpl;
-using browser_sync::DataTypeController;
-using browser_sync::DataTypeControllerMock;
-using browser_sync::SyncBackendHostMock;
-using testing::_;
-using testing::AtLeast;
-using testing::DoAll;
-using testing::DoDefault;
-using testing::InSequence;
-using testing::Mock;
-using testing::Property;
-using testing::Pointee;
-using testing::Return;
-using testing::SaveArg;
-
-ACTION_P(InvokeCallback, callback_result) {
- arg0->Run(callback_result, FROM_HERE);
- delete arg0;
-}
-
-ACTION_P2(InvokeCallbackPointer, callback, argument) {
- callback->Run(argument, FROM_HERE);
- delete callback;
-}
-
-class DataTypeManagerImplTest : public testing::Test {
- public:
- DataTypeManagerImplTest()
- : ui_thread_(BrowserThread::UI, &message_loop_) {}
-
- virtual ~DataTypeManagerImplTest() {
- }
-
- protected:
- virtual void SetUp() {
- registrar_.Add(&observer_,
- NotificationType::SYNC_CONFIGURE_START,
- NotificationService::AllSources());
- registrar_.Add(&observer_,
- NotificationType::SYNC_CONFIGURE_DONE,
- NotificationService::AllSources());
- }
-
- DataTypeControllerMock* MakeBookmarkDTC() {
- DataTypeControllerMock* dtc = new DataTypeControllerMock();
- EXPECT_CALL(*dtc, enabled()).WillRepeatedly(Return(true));
- EXPECT_CALL(*dtc, type()).WillRepeatedly(Return(syncable::BOOKMARKS));
- EXPECT_CALL(*dtc, name()).WillRepeatedly(Return("bookmark"));
- return dtc;
- }
-
- DataTypeControllerMock* MakePreferenceDTC() {
- DataTypeControllerMock* dtc = new DataTypeControllerMock();
- EXPECT_CALL(*dtc, enabled()).WillRepeatedly(Return(true));
- EXPECT_CALL(*dtc, type()).WillRepeatedly(Return(syncable::PREFERENCES));
- EXPECT_CALL(*dtc, name()).WillRepeatedly(Return("preference"));
- return dtc;
- }
-
- DataTypeControllerMock* MakePasswordDTC() {
- DataTypeControllerMock* dtc = new DataTypeControllerMock();
- SetPasswordDTCExpectations(dtc);
- return dtc;
- }
-
- void SetPasswordDTCExpectations(DataTypeControllerMock* dtc) {
- EXPECT_CALL(*dtc, enabled()).WillRepeatedly(Return(true));
- EXPECT_CALL(*dtc, type()).WillRepeatedly(Return(syncable::PASSWORDS));
- EXPECT_CALL(*dtc, name()).WillRepeatedly(Return("passwords"));
- }
-
- void SetStartStopExpectations(DataTypeControllerMock* mock_dtc) {
- InSequence seq;
- EXPECT_CALL(*mock_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- EXPECT_CALL(*mock_dtc, Start(_)).
- WillOnce(InvokeCallback((DataTypeController::OK)));
- EXPECT_CALL(*mock_dtc, state()).
- WillRepeatedly(Return(DataTypeController::RUNNING));
- EXPECT_CALL(*mock_dtc, Stop()).Times(1);
- EXPECT_CALL(*mock_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- }
-
- void SetBusyStartStopExpectations(DataTypeControllerMock* mock_dtc,
- DataTypeController::State busy_state) {
- InSequence seq;
- EXPECT_CALL(*mock_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- EXPECT_CALL(*mock_dtc, Start(_)).
- WillOnce(InvokeCallback((DataTypeController::OK)));
- EXPECT_CALL(*mock_dtc, state()).
- WillRepeatedly(Return(busy_state));
- EXPECT_CALL(*mock_dtc, Stop()).Times(1);
- EXPECT_CALL(*mock_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- }
-
- void SetNotUsedExpectations(DataTypeControllerMock* mock_dtc) {
- EXPECT_CALL(*mock_dtc, Start(_)).Times(0);
- EXPECT_CALL(*mock_dtc, Stop()).Times(0);
- EXPECT_CALL(*mock_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- }
-
- void SetConfigureStartExpectation() {
- EXPECT_CALL(
- observer_,
- Observe(NotificationType(NotificationType::SYNC_CONFIGURE_START),
- _, _));
- }
-
- void SetConfigureDoneExpectation(DataTypeManager::ConfigureResult result) {
- EXPECT_CALL(
- observer_,
- Observe(NotificationType(NotificationType::SYNC_CONFIGURE_DONE), _,
- Property(&Details<DataTypeManager::ConfigureResult>::ptr,
- Pointee(result))));
- }
-
- void SetBackendExpectations(int times) {
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(times);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(times);
- EXPECT_CALL(backend_, RequestPause()).Times(times);
- EXPECT_CALL(backend_, RequestResume()).Times(times);
- }
-
- MessageLoopForUI message_loop_;
- BrowserThread ui_thread_;
- DataTypeController::TypeMap controllers_;
- SyncBackendHostMock backend_;
- NotificationObserverMock observer_;
- NotificationRegistrar registrar_;
- std::set<syncable::ModelType> types_;
-};
-
-TEST_F(DataTypeManagerImplTest, NoControllers) {
- DataTypeManagerImpl dtm(&backend_, controllers_);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, ConfigureOne) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetStartStopExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
- SetBackendExpectations(1);
- DataTypeManagerImpl dtm(&backend_, controllers_);
- types_.insert(syncable::BOOKMARKS);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, ConfigureOneStopWhileStarting) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetBusyStartStopExpectations(bookmark_dtc,
- DataTypeController::MODEL_STARTING);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
- SetBackendExpectations(1);
- DataTypeManagerImpl dtm(&backend_, controllers_);
- types_.insert(syncable::BOOKMARKS);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, ConfigureOneStopWhileAssociating) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetBusyStartStopExpectations(bookmark_dtc, DataTypeController::ASSOCIATING);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
- SetBackendExpectations(1);
- DataTypeManagerImpl dtm(&backend_, controllers_);
- types_.insert(syncable::BOOKMARKS);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, OneWaitingForCrypto) {
- DataTypeControllerMock* password_dtc = MakePasswordDTC();
- EXPECT_CALL(*password_dtc, state()).Times(AtLeast(2)).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- EXPECT_CALL(*password_dtc, Start(_)).
- WillOnce(InvokeCallback((DataTypeController::NEEDS_CRYPTO)));
-
- controllers_[syncable::PASSWORDS] = password_dtc;
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
- EXPECT_CALL(backend_, RequestPause()).Times(1);
-
- DataTypeManagerImpl dtm(&backend_, controllers_);
- types_.insert(syncable::PASSWORDS);
- SetConfigureStartExpectation();
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::BLOCKED, dtm.state());
-
- Mock::VerifyAndClearExpectations(&backend_);
- Mock::VerifyAndClearExpectations(&observer_);
- Mock::VerifyAndClearExpectations(password_dtc);
-
- SetConfigureDoneExpectation(DataTypeManager::OK);
- SetPasswordDTCExpectations(password_dtc);
- EXPECT_CALL(*password_dtc, state()).
- WillOnce(Return(DataTypeController::NOT_RUNNING)).
- WillRepeatedly(Return(DataTypeController::RUNNING));
- EXPECT_CALL(*password_dtc, Start(_)).
- WillOnce(InvokeCallback((DataTypeController::OK)));
-
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
- EXPECT_CALL(backend_, RequestResume()).Times(1);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
- EXPECT_CALL(*password_dtc, Stop()).Times(1);
- dtm.Stop();
-
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-
-TEST_F(DataTypeManagerImplTest, ConfigureOneThenAnother) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetStartStopExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
- DataTypeControllerMock* preference_dtc = MakePreferenceDTC();
- SetStartStopExpectations(preference_dtc);
- controllers_[syncable::PREFERENCES] = preference_dtc;
-
- SetBackendExpectations(2);
- DataTypeManagerImpl dtm(&backend_, controllers_);
- types_.insert(syncable::BOOKMARKS);
-
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
-
- types_.insert(syncable::PREFERENCES);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
-
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
-
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, ConfigureOneThenSwitch) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetStartStopExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
- DataTypeControllerMock* preference_dtc = MakePreferenceDTC();
- SetStartStopExpectations(preference_dtc);
- controllers_[syncable::PREFERENCES] = preference_dtc;
-
- SetBackendExpectations(2);
- DataTypeManagerImpl dtm(&backend_, controllers_);
- types_.insert(syncable::BOOKMARKS);
-
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
-
- types_.clear();
- types_.insert(syncable::PREFERENCES);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
-
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, ConfigureWhileOneInFlight) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- // Save the callback here so we can interrupt startup.
- DataTypeController::StartCallback* callback;
- {
- InSequence seq;
- EXPECT_CALL(*bookmark_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- EXPECT_CALL(*bookmark_dtc, Start(_)).
- WillOnce(SaveArg<0>(&callback));
- EXPECT_CALL(*bookmark_dtc, state()).
- WillRepeatedly(Return(DataTypeController::RUNNING));
- EXPECT_CALL(*bookmark_dtc, Stop()).Times(1);
- EXPECT_CALL(*bookmark_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- }
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
-
- DataTypeControllerMock* preference_dtc = MakePreferenceDTC();
- SetStartStopExpectations(preference_dtc);
- controllers_[syncable::PREFERENCES] = preference_dtc;
-
- // Request/Resume only called once due to the configures being inlined.
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(2);
- EXPECT_CALL(backend_, RequestPause()).Times(1);
- EXPECT_CALL(backend_, RequestResume()).Times(1);
- DataTypeManagerImpl dtm(&backend_, controllers_);
- types_.insert(syncable::BOOKMARKS);
-
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- dtm.Configure(types_);
-
- // At this point, the bookmarks dtc should be in flight. Add
- // preferences and continue starting bookmarks.
- types_.insert(syncable::PREFERENCES);
- dtm.Configure(types_);
- callback->Run(DataTypeController::OK, FROM_HERE);
- delete callback;
-
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
-
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, ConfigureWhilePausePending) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetStartStopExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
- DataTypeControllerMock* preference_dtc = MakePreferenceDTC();
- SetStartStopExpectations(preference_dtc);
- controllers_[syncable::PREFERENCES] = preference_dtc;
-
- // Don't notify the first time pause is called.
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(2);
- EXPECT_CALL(backend_, RequestPause()).
- WillOnce(Return(true));
- EXPECT_CALL(backend_, RequestResume()).Times(1);
- DataTypeManagerImpl dtm(&backend_, controllers_);
- types_.insert(syncable::BOOKMARKS);
-
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::PAUSE_PENDING, dtm.state());
-
- // Configure while pause pending.
- types_.insert(syncable::PREFERENCES);
- dtm.Configure(types_);
-
- // Send the SYNC_PAUSED notification. This will allow the DTM to
- // wake up and restart itself with the new configuration.
- NotificationService::current()->Notify(NotificationType::SYNC_PAUSED,
- NotificationService::AllSources(),
- NotificationService::NoDetails());
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, StopWhilePausePending) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetNotUsedExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
-
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
- // Never notify when RequestPause is called.
- EXPECT_CALL(backend_, RequestPause()).WillOnce(Return(true));
- EXPECT_CALL(backend_, RequestResume()).Times(0);
- DataTypeManagerImpl dtm(&backend_, controllers_);
-
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::ABORTED);
- types_.insert(syncable::BOOKMARKS);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::PAUSE_PENDING, dtm.state());
-
- // Stop while pause pending.
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-
- // We should be able to safely handle a SYNC_PAUSED notification.
- NotificationService::current()->Notify(NotificationType::SYNC_PAUSED,
- NotificationService::AllSources(),
- NotificationService::NoDetails());
-}
-
-TEST_F(DataTypeManagerImplTest, ConfigureWhileResumePending) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetStartStopExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
- DataTypeControllerMock* preference_dtc = MakePreferenceDTC();
- SetStartStopExpectations(preference_dtc);
- controllers_[syncable::PREFERENCES] = preference_dtc;
-
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(2);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(2);
- EXPECT_CALL(backend_, RequestPause()).Times(2);
- // Don't notify the first time resume is called.
- EXPECT_CALL(backend_, RequestResume()).
- WillOnce(Return(true)).
- WillOnce(DoDefault());
- DataTypeManagerImpl dtm(&backend_, controllers_);
- types_.insert(syncable::BOOKMARKS);
-
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::RESUME_PENDING, dtm.state());
-
- // Configure while resume pending.
- types_.insert(syncable::PREFERENCES);
- dtm.Configure(types_);
-
- // Send the SYNC_PAUSED notification. This will allow the DTM to
- // wake up and restart itself with the new configuration.
- NotificationService::current()->Notify(NotificationType::SYNC_RESUMED,
- NotificationService::AllSources(),
- NotificationService::NoDetails());
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, StopWhileResumePending) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetStartStopExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
-
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
- EXPECT_CALL(backend_, RequestPause()).Times(1);
- // Never notify pause resumed.
- EXPECT_CALL(backend_, RequestResume()).WillOnce(Return(true));
- DataTypeManagerImpl dtm(&backend_, controllers_);
-
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::ABORTED);
- types_.insert(syncable::BOOKMARKS);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::RESUME_PENDING, dtm.state());
-
- // Stop while pause pending.
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-
- // We should be able to safely handle a SYNC_RESUMED notification.
- NotificationService::current()->Notify(NotificationType::SYNC_RESUMED,
- NotificationService::AllSources(),
- NotificationService::NoDetails());
-}
-
-TEST_F(DataTypeManagerImplTest, OneFailingController) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- EXPECT_CALL(*bookmark_dtc, Start(_)).
- WillOnce(InvokeCallback((DataTypeController::ASSOCIATION_FAILED)));
- EXPECT_CALL(*bookmark_dtc, Stop()).Times(0);
- EXPECT_CALL(*bookmark_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
-
- DataTypeManagerImpl dtm(&backend_, controllers_);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::ASSOCIATION_FAILED);
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
- EXPECT_CALL(backend_, RequestPause()).Times(1);
- EXPECT_CALL(backend_, RequestResume()).Times(0);
-
- types_.insert(syncable::BOOKMARKS);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, StopWhileInFlight) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetStartStopExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
-
- DataTypeControllerMock* preference_dtc = MakePreferenceDTC();
- // Save the callback here so we can interrupt startup.
- DataTypeController::StartCallback* callback;
- EXPECT_CALL(*preference_dtc, Start(_)).
- WillOnce(SaveArg<0>(&callback));
- EXPECT_CALL(*preference_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- controllers_[syncable::PREFERENCES] = preference_dtc;
-
- DataTypeManagerImpl dtm(&backend_, controllers_);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::ABORTED);
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
- EXPECT_CALL(backend_, RequestPause()).Times(1);
- EXPECT_CALL(backend_, RequestResume()).Times(0);
-
- types_.insert(syncable::BOOKMARKS);
- types_.insert(syncable::PREFERENCES);
- dtm.Configure(types_);
- // Configure should stop in the CONFIGURING state because we are
- // waiting for the preferences callback to be invoked.
- EXPECT_EQ(DataTypeManager::CONFIGURING, dtm.state());
-
- // Call stop before the preference callback is invoked.
- EXPECT_CALL(*preference_dtc, Stop()).
- WillOnce(InvokeCallbackPointer(callback, DataTypeController::ABORTED));
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, SecondControllerFails) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetStartStopExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
-
- DataTypeControllerMock* preference_dtc = MakePreferenceDTC();
- EXPECT_CALL(*preference_dtc, Start(_)).
- WillOnce(InvokeCallback((DataTypeController::ASSOCIATION_FAILED)));
- EXPECT_CALL(*preference_dtc, Stop()).Times(0);
- EXPECT_CALL(*preference_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- controllers_[syncable::PREFERENCES] = preference_dtc;
-
- DataTypeManagerImpl dtm(&backend_, controllers_);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::ASSOCIATION_FAILED);
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
- EXPECT_CALL(backend_, RequestPause()).Times(1);
- EXPECT_CALL(backend_, RequestResume()).Times(0);
-
- types_.insert(syncable::BOOKMARKS);
- types_.insert(syncable::PREFERENCES);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, PauseFailed) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- EXPECT_CALL(*bookmark_dtc, Start(_)).Times(0);
- EXPECT_CALL(*bookmark_dtc, state()).
- WillRepeatedly(Return(DataTypeController::NOT_RUNNING));
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
-
- DataTypeManagerImpl dtm(&backend_, controllers_);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
- EXPECT_CALL(backend_, RequestPause()).WillOnce(Return(false));
- EXPECT_CALL(backend_, RequestResume()).Times(0);
-
- types_.insert(syncable::BOOKMARKS);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, ResumeFailed) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetStartStopExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
-
- DataTypeManagerImpl dtm(&backend_, controllers_);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).Times(1);
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(1);
- EXPECT_CALL(backend_, RequestPause()).Times(1);
- EXPECT_CALL(backend_, RequestResume()).WillOnce(Return(false));
-
- types_.insert(syncable::BOOKMARKS);
- dtm.Configure(types_);
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, ConfigureWhileDownloadPending) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetStartStopExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
-
- DataTypeControllerMock* preference_dtc = MakePreferenceDTC();
- SetStartStopExpectations(preference_dtc);
- controllers_[syncable::PREFERENCES] = preference_dtc;
-
- DataTypeManagerImpl dtm(&backend_, controllers_);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::OK);
- CancelableTask* task;
- // Grab the task the first time this is called so we can configure
- // before it is finished.
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).
- WillOnce(SaveArg<2>(&task)).
- WillOnce(DoDefault());
- EXPECT_CALL(backend_, StartSyncingWithServer()).Times(2);
- EXPECT_CALL(backend_, RequestPause()).Times(1);
- EXPECT_CALL(backend_, RequestResume()).Times(1);
-
- types_.insert(syncable::BOOKMARKS);
- dtm.Configure(types_);
- // Configure should stop in the DOWNLOAD_PENDING state because we
- // are waiting for the download ready task to be run.
- EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm.state());
-
- types_.insert(syncable::PREFERENCES);
- dtm.Configure(types_);
-
- // Running the task will queue a restart task to the message loop, and
- // eventually get us configured.
- task->Run();
- delete task;
- MessageLoop::current()->RunAllPending();
- EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state());
-
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-}
-
-TEST_F(DataTypeManagerImplTest, StopWhileDownloadPending) {
- DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC();
- SetNotUsedExpectations(bookmark_dtc);
- controllers_[syncable::BOOKMARKS] = bookmark_dtc;
-
- DataTypeManagerImpl dtm(&backend_, controllers_);
- SetConfigureStartExpectation();
- SetConfigureDoneExpectation(DataTypeManager::ABORTED);
- CancelableTask* task;
- // Grab the task the first time this is called so we can stop
- // before it is finished.
- EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _)).
- WillOnce(SaveArg<2>(&task));
- EXPECT_CALL(backend_, StartSyncingWithServer());
- EXPECT_CALL(backend_, RequestPause()).Times(0);
- EXPECT_CALL(backend_, RequestResume()).Times(0);
-
- types_.insert(syncable::BOOKMARKS);
- dtm.Configure(types_);
- // Configure should stop in the DOWNLOAD_PENDING state because we
- // are waiting for the download ready task to be run.
- EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm.state());
-
- dtm.Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm.state());
-
- // It should be perfectly safe to run this task even though the DTM
- // has been stopped.
- task->Run();
- delete task;
-}
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc
index 50fc35c..9d57a8f 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/chrome/browser/sync/glue/sync_backend_host.cc
@@ -66,9 +66,6 @@ SyncBackendHost::SyncBackendHost(Profile* profile)
sync_data_folder_path_(
profile_->GetPath().Append(kSyncDataFolderName)),
last_auth_error_(AuthError::None()),
- using_new_syncer_thread_(
- CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kNewSyncerThread)),
syncapi_initialized_(false) {
}
@@ -78,9 +75,6 @@ SyncBackendHost::SyncBackendHost()
profile_(NULL),
frontend_(NULL),
last_auth_error_(AuthError::None()),
- using_new_syncer_thread_(
- CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kNewSyncerThread)),
syncapi_initialized_(false) {
}
@@ -409,16 +403,7 @@ void SyncBackendHost::ConfigureDataTypes(
&registrar_.routing_info));
}
- // If we're doing the first configure (at startup) this is redundant as the
- // syncer thread always must start in config mode.
- if (using_new_syncer_thread_) {
- core_thread_.message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(core_.get(),
- &SyncBackendHost::Core::DoStartConfigurationMode));
- } else {
- FinishConfigureDataTypesOnFrontendLoop();
- }
+ FinishConfigureDataTypesOnFrontendLoop();
}
void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop() {
@@ -433,15 +418,11 @@ void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop() {
// downloading updates for newly added data types. Once this is
// complete, the configure_state_.ready_task_ is run via an
// OnInitializationComplete notification.
- bool request_nudge = false;
+
if (pending_config_mode_state_->deleted_type) {
- if (using_new_syncer_thread_) {
- core_thread_.message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(core_.get(),
- &SyncBackendHost::Core::DeferNudgeForCleanup));
- } else {
- request_nudge = true;
- }
+ core_thread_.message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(core_.get(),
+ &SyncBackendHost::Core::DeferNudgeForCleanup));
}
if (pending_config_mode_state_->added_types.none() &&
@@ -464,17 +445,14 @@ void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop() {
pending_config_mode_state_->ready_task->Run();
} else {
pending_download_state_.reset(pending_config_mode_state_.release());
- if (using_new_syncer_thread_) {
- RequestConfig(pending_download_state_->added_types);
- } else {
- request_nudge = true;
- }
- }
- // TODO(tim): Remove this when we get rid of the old syncer thread.
- if (request_nudge) {
- CHECK(!using_new_syncer_thread_);
- RequestNudge(FROM_HERE);
+ syncable::ModelTypeBitSet types_copy(pending_download_state_->added_types);
+ if (IsNigoriEnabled())
+ types_copy.set(syncable::NIGORI);
+ core_thread_.message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(core_.get(),
+ &SyncBackendHost::Core::DoRequestConfig,
+ types_copy));
}
pending_config_mode_state_.reset();
@@ -499,17 +477,6 @@ void SyncBackendHost::RequestNudge(const tracked_objects::Location& location) {
location));
}
-void SyncBackendHost::RequestConfig(
- const syncable::ModelTypeBitSet& added_types) {
- DCHECK(core_->syncapi());
-
- syncable::ModelTypeBitSet types_copy(added_types);
- if (IsNigoriEnabled())
- types_copy.set(syncable::NIGORI);
-
- core_->syncapi()->RequestConfig(types_copy);
-}
-
void SyncBackendHost::ActivateDataType(
DataTypeController* data_type_controller,
ChangeProcessor* change_processor) {
@@ -541,20 +508,6 @@ void SyncBackendHost::DeactivateDataType(
DCHECK_EQ(erased, 1U);
}
-bool SyncBackendHost::RequestPause() {
- DCHECK(!using_new_syncer_thread_);
- core_thread_.message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoRequestPause));
- return true;
-}
-
-bool SyncBackendHost::RequestResume() {
- DCHECK(!using_new_syncer_thread_);
- core_thread_.message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoRequestResume));
- return true;
-}
-
bool SyncBackendHost::RequestClearServerData() {
core_thread_.message_loop()->PostTask(FROM_HERE,
NewRunnableMethod(core_.get(),
@@ -565,20 +518,6 @@ bool SyncBackendHost::RequestClearServerData() {
SyncBackendHost::Core::~Core() {
}
-void SyncBackendHost::Core::NotifyPaused() {
- DCHECK(!host_ || !host_->using_new_syncer_thread_);
- NotificationService::current()->Notify(NotificationType::SYNC_PAUSED,
- NotificationService::AllSources(),
- NotificationService::NoDetails());
-}
-
-void SyncBackendHost::Core::NotifyResumed() {
- DCHECK(!host_ || !host_->using_new_syncer_thread_);
- NotificationService::current()->Notify(NotificationType::SYNC_RESUMED,
- NotificationService::AllSources(),
- NotificationService::NoDetails());
-}
-
void SyncBackendHost::Core::NotifyPassphraseRequired(bool for_decryption) {
if (!host_ || !host_->frontend_)
return;
@@ -832,6 +771,11 @@ void SyncBackendHost::Core::DoEncryptDataTypes(
syncapi_->EncryptDataTypes(encrypted_types);
}
+void SyncBackendHost::Core::DoRequestConfig(
+ const syncable::ModelTypeBitSet& added_types) {
+ syncapi_->RequestConfig(added_types);
+}
+
UIModelWorker* SyncBackendHost::ui_worker() {
ModelSafeWorker* w = registrar_.workers[GROUP_UI];
if (w == NULL)
@@ -949,7 +893,6 @@ void SyncBackendHost::Core::HandleSyncCycleCompletedOnFrontendLoop(
}
if (!found_all_added) {
CHECK(false);
- DCHECK(!host_->using_new_syncer_thread_);
} else {
host_->pending_download_state_->ready_task->Run();
host_->pending_download_state_.reset();
@@ -1027,18 +970,6 @@ void SyncBackendHost::Core::OnPassphraseAccepted(
bootstrap_token));
}
-void SyncBackendHost::Core::OnPaused() {
- host_->frontend_loop_->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &Core::NotifyPaused));
-}
-
-void SyncBackendHost::Core::OnResumed() {
- host_->frontend_loop_->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &Core::NotifyResumed));
-}
-
void SyncBackendHost::Core::OnStopSyncingPermanently() {
host_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
&Core::HandleStopSyncingPermanentlyOnFrontendLoop));
@@ -1130,14 +1061,6 @@ void SyncBackendHost::Core::DoRequestClearServerData() {
syncapi_->RequestClearServerData();
}
-void SyncBackendHost::Core::DoRequestResume() {
- syncapi_->RequestResume();
-}
-
-void SyncBackendHost::Core::DoRequestPause() {
- syncapi()->RequestPause();
-}
-
void SyncBackendHost::Core::SaveChanges() {
syncapi_->SaveChanges();
}
@@ -1213,11 +1136,6 @@ void SyncBackendHost::Core::DoProcessMessage(
syncapi_->GetJsBackend()->ProcessMessage(name, args, sender);
}
-void SyncBackendHost::Core::DoStartConfigurationMode() {
- syncapi_->StartConfigurationMode(NewCallback(this,
- &SyncBackendHost::Core::FinishConfigureDataTypes));
-}
-
void SyncBackendHost::Core::DeferNudgeForCleanup() {
DCHECK_EQ(MessageLoop::current(), host_->core_thread_.message_loop());
deferred_nudge_for_cleanup_requested_ = true;
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h
index 086b2e0..586ca8d 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/chrome/browser/sync/glue/sync_backend_host.h
@@ -195,16 +195,6 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
void DeactivateDataType(DataTypeController* data_type_controller,
ChangeProcessor* change_processor);
- // Requests the backend to pause. Returns true if the request is
- // sent sucessfully. When the backend does pause, a SYNC_PAUSED
- // notification is sent to the notification service.
- virtual bool RequestPause();
-
- // Requests the backend to resume. Returns true if the request is
- // sent sucessfully. When the backend does resume, a SYNC_RESUMED
- // notification is sent to the notification service.
- virtual bool RequestResume();
-
// Asks the server to clear all data associated with ChromeSync.
virtual bool RequestClearServerData();
@@ -282,8 +272,6 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
virtual void OnPassphraseRequired(bool for_decryption);
virtual void OnPassphraseFailed();
virtual void OnPassphraseAccepted(const std::string& bootstrap_token);
- virtual void OnPaused();
- virtual void OnResumed();
virtual void OnStopSyncingPermanently();
virtual void OnUpdatedToken(const std::string& token);
virtual void OnClearServerDataFailed();
@@ -350,8 +338,6 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
// Called on the SyncBackendHost core_thread_ to nudge/pause/resume the
// syncer.
void DoRequestNudge(const tracked_objects::Location& location);
- void DoRequestPause();
- void DoRequestResume();
void DoRequestClearServerData();
// Sets |deferred_nudge_for_cleanup_requested_| to true. See comment below.
@@ -382,6 +368,9 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
// because the thread that was using them has exited (in step 2).
void DoShutdown(bool stopping_sync);
+ // Posts a config request on the core thread.
+ virtual void DoRequestConfig(const syncable::ModelTypeBitSet& added_types);
+
// Set the base request context to use when making HTTP calls.
// This method will add a reference to the context to persist it
// on the IO thread. Must be removed from IO thread.
@@ -401,8 +390,6 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
const std::string& name, const JsArgList& args,
const JsEventHandler* sender);
- void DoStartConfigurationMode();
-
// A callback from the SyncerThread when it is safe to continue config.
void FinishConfigureDataTypes();
@@ -432,15 +419,6 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
// Return change processor for a particular model (return NULL on failure).
ChangeProcessor* GetProcessor(syncable::ModelType modeltype);
-
- // Sends a SYNC_PAUSED notification to the notification service on
- // the UI thread.
- void NotifyPaused();
-
- // Sends a SYNC_RESUMED notification to the notification service
- // on the UI thread.
- void NotifyResumed();
-
// Invoked when initialization of syncapi is complete and we can start
// our timer.
// This must be called from the thread on which SaveChanges is intended to
@@ -541,9 +519,6 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
// Posts a nudge request on the core thread.
virtual void RequestNudge(const tracked_objects::Location& location);
- // Posts a config request on the core thread.
- virtual void RequestConfig(const syncable::ModelTypeBitSet& added_types);
-
// Called to finish the job of ConfigureDataTypes once the syncer is in
// configuration mode.
void FinishConfigureDataTypes();
@@ -657,9 +632,6 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
// UI-thread cache of the last SyncSessionSnapshot received from syncapi.
scoped_ptr<sessions::SyncSessionSnapshot> last_snapshot_;
- // While two impls are in flight, using this for sanity checking. Bug 26339.
- const bool using_new_syncer_thread_;
-
// Whether we've processed the initialization complete callback.
bool syncapi_initialized_;
diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.cc b/chrome/browser/sync/glue/sync_backend_host_mock.cc
index 2d618f7..8e16905 100644
--- a/chrome/browser/sync/glue/sync_backend_host_mock.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_mock.cc
@@ -12,15 +12,6 @@ ACTION(InvokeTask) {
}
SyncBackendHostMock::SyncBackendHostMock() {
- // By default, the RequestPause and RequestResume methods will
- // send the confirmation notification and return true.
- ON_CALL(*this, RequestPause()).
- WillByDefault(testing::DoAll(Notify(NotificationType::SYNC_PAUSED),
- testing::Return(true)));
- ON_CALL(*this, RequestResume()).
- WillByDefault(testing::DoAll(Notify(NotificationType::SYNC_RESUMED),
- testing::Return(true)));
-
// By default, invoke the ready callback.
ON_CALL(*this, ConfigureDataTypes(testing::_, testing::_, testing::_)).
WillByDefault(InvokeTask());
diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.h b/chrome/browser/sync/glue/sync_backend_host_mock.h
index 9d715f3..a594674 100644
--- a/chrome/browser/sync/glue/sync_backend_host_mock.h
+++ b/chrome/browser/sync/glue/sync_backend_host_mock.h
@@ -24,8 +24,6 @@ class SyncBackendHostMock : public SyncBackendHost {
MOCK_METHOD3(ConfigureDataTypes,
void(const DataTypeController::TypeMap&,
const std::set<syncable::ModelType>&, CancelableTask*));
- MOCK_METHOD0(RequestPause, bool());
- MOCK_METHOD0(RequestResume, bool());
MOCK_METHOD0(StartSyncingWithServer, void());
};
diff --git a/chrome/browser/sync/js_sync_manager_observer.cc b/chrome/browser/sync/js_sync_manager_observer.cc
index 3999fdd..b6266e7 100644
--- a/chrome/browser/sync/js_sync_manager_observer.cc
+++ b/chrome/browser/sync/js_sync_manager_observer.cc
@@ -103,14 +103,6 @@ void JsSyncManagerObserver::OnInitializationComplete() {
JsArgList(), NULL);
}
-void JsSyncManagerObserver::OnPaused() {
- parent_router_->RouteJsEvent("onPaused", JsArgList(), NULL);
-}
-
-void JsSyncManagerObserver::OnResumed() {
- parent_router_->RouteJsEvent("onResumed", JsArgList(), NULL);
-}
-
void JsSyncManagerObserver::OnStopSyncingPermanently() {
parent_router_->RouteJsEvent("onStopSyncingPermanently",
JsArgList(), NULL);
diff --git a/chrome/browser/sync/js_sync_manager_observer.h b/chrome/browser/sync/js_sync_manager_observer.h
index 2fa8638..c7d09e76 100644
--- a/chrome/browser/sync/js_sync_manager_observer.h
+++ b/chrome/browser/sync/js_sync_manager_observer.h
@@ -40,8 +40,6 @@ class JsSyncManagerObserver : public sync_api::SyncManager::Observer {
virtual void OnEncryptionComplete(
const syncable::ModelTypeSet& encrypted_types);
virtual void OnInitializationComplete();
- virtual void OnPaused();
- virtual void OnResumed();
virtual void OnStopSyncingPermanently();
virtual void OnClearServerDataSucceeded();
virtual void OnClearServerDataFailed();
diff --git a/chrome/browser/sync/js_sync_manager_observer_unittest.cc b/chrome/browser/sync/js_sync_manager_observer_unittest.cc
index b9c0c33..e854690 100644
--- a/chrome/browser/sync/js_sync_manager_observer_unittest.cc
+++ b/chrome/browser/sync/js_sync_manager_observer_unittest.cc
@@ -39,12 +39,7 @@ TEST_F(JsSyncManagerObserverTest, NoArgNotifiations) {
EXPECT_CALL(mock_router_,
RouteJsEvent("onPassphraseFailed",
HasArgs(JsArgList()), NULL));
- EXPECT_CALL(mock_router_,
- RouteJsEvent("onPaused",
- HasArgs(JsArgList()), NULL));
- EXPECT_CALL(mock_router_,
- RouteJsEvent("onResumed",
- HasArgs(JsArgList()), NULL));
+
EXPECT_CALL(mock_router_,
RouteJsEvent("onStopSyncingPermanently",
HasArgs(JsArgList()), NULL));
@@ -57,8 +52,6 @@ TEST_F(JsSyncManagerObserverTest, NoArgNotifiations) {
sync_manager_observer_.OnInitializationComplete();
sync_manager_observer_.OnPassphraseFailed();
- sync_manager_observer_.OnPaused();
- sync_manager_observer_.OnResumed();
sync_manager_observer_.OnStopSyncingPermanently();
sync_manager_observer_.OnClearServerDataSucceeded();
sync_manager_observer_.OnClearServerDataFailed();
diff --git a/chrome/browser/sync/profile_sync_factory_impl.cc b/chrome/browser/sync/profile_sync_factory_impl.cc
index b272f20..9102e88 100644
--- a/chrome/browser/sync/profile_sync_factory_impl.cc
+++ b/chrome/browser/sync/profile_sync_factory_impl.cc
@@ -16,7 +16,6 @@
#include "chrome/browser/sync/glue/bookmark_data_type_controller.h"
#include "chrome/browser/sync/glue/bookmark_model_associator.h"
#include "chrome/browser/sync/glue/data_type_manager_impl.h"
-#include "chrome/browser/sync/glue/data_type_manager_impl2.h"
#include "chrome/browser/sync/glue/extension_change_processor.h"
#include "chrome/browser/sync/glue/extension_data_type_controller.h"
#include "chrome/browser/sync/glue/extension_model_associator.h"
@@ -55,7 +54,6 @@ using browser_sync::BookmarkModelAssociator;
using browser_sync::DataTypeController;
using browser_sync::DataTypeManager;
using browser_sync::DataTypeManagerImpl;
-using browser_sync::DataTypeManagerImpl2;
using browser_sync::ExtensionChangeProcessor;
using browser_sync::ExtensionDataTypeController;
using browser_sync::ExtensionModelAssociator;
@@ -161,10 +159,7 @@ ProfileSyncService* ProfileSyncFactoryImpl::CreateProfileSyncService(
DataTypeManager* ProfileSyncFactoryImpl::CreateDataTypeManager(
SyncBackendHost* backend,
const DataTypeController::TypeMap& controllers) {
- if (command_line_->HasSwitch(switches::kNewSyncerThread))
- return new DataTypeManagerImpl2(backend, controllers);
- else
- return new DataTypeManagerImpl(backend, controllers);
+ return new DataTypeManagerImpl(backend, controllers);
}
ProfileSyncFactory::SyncComponents
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index aa95e2a..937af9f 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -598,6 +598,13 @@ void ProfileSyncService::OnClearServerDataSucceeded() {
void ProfileSyncService::OnPassphraseRequired(bool for_decryption) {
DCHECK(backend_.get());
DCHECK(backend_->IsNigoriEnabled());
+
+ // TODO(lipalani) : add this check to other locations as well.
+ if (unrecoverable_error_detected_) {
+ // When unrecoverable error is detected we post a task to shutdown the
+ // backend. The task might not have executed yet.
+ return;
+ }
observed_passphrase_required_ = true;
passphrase_required_for_decryption_ = for_decryption;
diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc
index 2e106c1..22005ce 100644
--- a/chrome/browser/sync/profile_sync_service_password_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc
@@ -153,7 +153,7 @@ class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest {
NotificationType::SYNC_CONFIGURE_DONE,
NotificationService::AllSources());
registrar_.Add(&observer_,
- NotificationType::SYNC_PAUSED,
+ NotificationType::SYNC_CONFIGURE_BLOCKED,
NotificationService::AllSources());
}
@@ -218,7 +218,8 @@ class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest {
NotificationType(NotificationType::SYNC_CONFIGURE_DONE),_,_));
EXPECT_CALL(observer_,
Observe(
- NotificationType(NotificationType::SYNC_PAUSED),_,_))
+ NotificationType(
+ NotificationType::SYNC_CONFIGURE_BLOCKED),_,_))
.WillOnce(InvokeWithoutArgs(QuitMessageLoop));
service_->RegisterDataTypeController(data_type_controller);
diff --git a/chrome/browser/sync/sessions/sync_session_context.cc b/chrome/browser/sync/sessions/sync_session_context.cc
index b5f072b..f0cbce4 100644
--- a/chrome/browser/sync/sessions/sync_session_context.cc
+++ b/chrome/browser/sync/sessions/sync_session_context.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -36,10 +36,5 @@ SyncSessionContext::~SyncSessionContext() {
}
}
-void SyncSessionContext::set_last_snapshot(
- const SyncSessionSnapshot& snapshot) {
- previous_session_snapshot_.reset(new SyncSessionSnapshot(snapshot));
-}
-
} // namespace sessions
} // namespace browser_sync
diff --git a/chrome/browser/sync/sessions/sync_session_context.h b/chrome/browser/sync/sessions/sync_session_context.h
index 4ec8612..a3a69ec 100644
--- a/chrome/browser/sync/sessions/sync_session_context.h
+++ b/chrome/browser/sync/sessions/sync_session_context.h
@@ -92,13 +92,6 @@ class SyncSessionContext {
previous_session_routing_info_ = info;
}
- // TODO(tim): Deprecated. Bug 26339.
- sessions::SyncSessionSnapshot* previous_session_snapshot() {
- return previous_session_snapshot_.get();
- }
-
- void set_last_snapshot(const SyncSessionSnapshot& snapshot);
-
void NotifyListeners(const SyncEngineEvent& event) {
FOR_EACH_OBSERVER(SyncEngineEventListener, listeners_,
OnSyncEngineEvent(event));
diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc
index 02b44ef..c36cd49 100644
--- a/chrome/browser/sync/test_profile_sync_service.cc
+++ b/chrome/browser/sync/test_profile_sync_service.cc
@@ -24,14 +24,6 @@ using syncable::ModelType;
using syncable::ScopedDirLookup;
using sync_api::UserShare;
-ACTION_P(CallOnPaused, core) {
- core->OnPaused();
-};
-
-ACTION_P(CallOnResumed, core) {
- core->OnResumed();
-}
-
namespace browser_sync {
using ::testing::_;
@@ -41,21 +33,10 @@ SyncBackendHostForProfileSyncTest::SyncBackendHostForProfileSyncTest(
bool synchronous_init)
: browser_sync::SyncBackendHost(profile),
synchronous_init_(synchronous_init) {
- // By default, the RequestPause and RequestResume methods will
- // send the confirmation notification and return true.
- ON_CALL(*this, RequestPause()).
- WillByDefault(testing::DoAll(CallOnPaused(core_),
- testing::Return(true)));
- ON_CALL(*this, RequestResume()).
- WillByDefault(testing::DoAll(CallOnResumed(core_),
- testing::Return(true)));
ON_CALL(*this, RequestNudge(_)).WillByDefault(
testing::Invoke(this,
&SyncBackendHostForProfileSyncTest::
SimulateSyncCycleCompletedInitialSyncEnded));
-
- EXPECT_CALL(*this, RequestPause()).Times(testing::AnyNumber());
- EXPECT_CALL(*this, RequestResume()).Times(testing::AnyNumber());
EXPECT_CALL(*this, RequestNudge(_)).Times(testing::AnyNumber());
}
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h
index bbe1d14..3cedde6 100644
--- a/chrome/browser/sync/test_profile_sync_service.h
+++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -40,8 +40,6 @@ class SyncBackendHostForProfileSyncTest
bool synchronous_init);
virtual ~SyncBackendHostForProfileSyncTest();
- MOCK_METHOD0(RequestPause, bool());
- MOCK_METHOD0(RequestResume, bool());
MOCK_METHOD1(RequestNudge, void(const tracked_objects::Location&));
virtual void ConfigureDataTypes(