summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/sync/notifier/chrome_invalidation_client.cc54
-rw-r--r--chrome/browser/sync/notifier/chrome_invalidation_client.h4
-rw-r--r--chrome/browser/sync/notifier/invalidation_util.cc20
-rw-r--r--chrome/browser/sync/notifier/invalidation_util.h7
-rw-r--r--chrome/browser/sync/notifier/registration_manager.cc132
-rw-r--r--chrome/browser/sync/notifier/registration_manager.h83
-rw-r--r--chrome/browser/sync/notifier/registration_manager_unittest.cc287
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--chrome/chrome_tests.gypi2
9 files changed, 548 insertions, 43 deletions
diff --git a/chrome/browser/sync/notifier/chrome_invalidation_client.cc b/chrome/browser/sync/notifier/chrome_invalidation_client.cc
index 0b84899..f183e61 100644
--- a/chrome/browser/sync/notifier/chrome_invalidation_client.cc
+++ b/chrome/browser/sync/notifier/chrome_invalidation_client.cc
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "chrome/browser/sync/notifier/cache_invalidation_packet_handler.h"
#include "chrome/browser/sync/notifier/invalidation_util.h"
+#include "chrome/browser/sync/notifier/registration_manager.h"
#include "chrome/browser/sync/syncable/model_type.h"
namespace sync_notifier {
@@ -46,6 +47,8 @@ void ChromeInvalidationClient::Start(
cache_invalidation_packet_handler_.reset(
new CacheInvalidationPacketHandler(xmpp_client,
invalidation_client_.get()));
+ registration_manager_.reset(
+ new RegistrationManager(invalidation_client_.get()));
RegisterTypes();
}
@@ -58,6 +61,7 @@ void ChromeInvalidationClient::Stop() {
chrome_system_resources_.StopScheduler();
+ registration_manager_.reset();
cache_invalidation_packet_handler_.reset();
invalidation_client_.reset();
listener_ = NULL;
@@ -70,35 +74,10 @@ void ChromeInvalidationClient::RegisterTypes() {
// notifications for all possible types.
for (int i = syncable::FIRST_REAL_MODEL_TYPE;
i < syncable::MODEL_TYPE_COUNT; ++i) {
- syncable::ModelType model_type = syncable::ModelTypeFromInt(i);
- std::string notification_type;
- if (!syncable::RealModelTypeToNotificationType(
- model_type, &notification_type)) {
- LOG(ERROR) << "Could not get notification type for model type "
- << syncable::ModelTypeToString(model_type);
- continue;
- }
- invalidation::ObjectId object_id;
- object_id.mutable_name()->set_string_value(notification_type);
- object_id.set_source(invalidation::ObjectId::CHROME_SYNC);
- invalidation_client_->Register(
- object_id,
- invalidation::NewPermanentCallback(
- this, &ChromeInvalidationClient::OnRegister));
+ registration_manager_->RegisterType(syncable::ModelTypeFromInt(i));
}
}
-namespace {
-
-bool GetInvalidationModelType(const invalidation::Invalidation& invalidation,
- syncable::ModelType* model_type) {
- return
- syncable::NotificationTypeToRealModelType(
- invalidation.object_id().name().string_value(), model_type);
-}
-
-} // namespace
-
void ChromeInvalidationClient::Invalidate(
const invalidation::Invalidation& invalidation,
invalidation::Closure* callback) {
@@ -106,7 +85,7 @@ void ChromeInvalidationClient::Invalidate(
DCHECK(invalidation::IsCallbackRepeatable(callback));
LOG(INFO) << "Invalidate: " << InvalidationToString(invalidation);
syncable::ModelType model_type;
- if (GetInvalidationModelType(invalidation, &model_type)) {
+ if (ObjectIdToRealModelType(invalidation.object_id(), &model_type)) {
listener_->OnInvalidate(model_type);
} else {
LOG(WARNING) << "Could not get invalidation model type; "
@@ -129,8 +108,8 @@ void ChromeInvalidationClient::AllRegistrationsLost(
invalidation::Closure* callback) {
DCHECK(non_thread_safe_.CalledOnValidThread());
DCHECK(invalidation::IsCallbackRepeatable(callback));
- LOG(INFO) << "AllRegistrationsLost; reregistering";
- RegisterTypes();
+ LOG(INFO) << "AllRegistrationsLost";
+ registration_manager_->MarkAllRegistrationsLost();
RunAndDeleteClosure(callback);
}
@@ -139,17 +118,14 @@ void ChromeInvalidationClient::RegistrationLost(
invalidation::Closure* callback) {
DCHECK(non_thread_safe_.CalledOnValidThread());
DCHECK(invalidation::IsCallbackRepeatable(callback));
- LOG(INFO) << "RegistrationLost; reregistering: "
- << ObjectIdToString(object_id);
- RegisterTypes();
+ LOG(INFO) << "RegistrationLost: " << ObjectIdToString(object_id);
+ syncable::ModelType model_type;
+ if (ObjectIdToRealModelType(object_id, &model_type)) {
+ registration_manager_->MarkRegistrationLost(model_type);
+ } else {
+ LOG(WARNING) << "Could not get object id model type; ignoring";
+ }
RunAndDeleteClosure(callback);
}
-void ChromeInvalidationClient::OnRegister(
- const invalidation::RegistrationUpdateResult& result) {
- DCHECK(non_thread_safe_.CalledOnValidThread());
- // TODO(akalin): Do something meaningful here.
- LOG(INFO) << "Registered: " << RegistrationUpdateResultToString(result);
-}
-
} // namespace sync_notifier
diff --git a/chrome/browser/sync/notifier/chrome_invalidation_client.h b/chrome/browser/sync/notifier/chrome_invalidation_client.h
index e227fcc..6b4f6cfe 100644
--- a/chrome/browser/sync/notifier/chrome_invalidation_client.h
+++ b/chrome/browser/sync/notifier/chrome_invalidation_client.h
@@ -24,6 +24,7 @@ class XmppClient;
namespace sync_notifier {
class CacheInvalidationPacketHandler;
+class RegistrationManager;
// TODO(akalin): Hook this up to a NetworkChangeNotifier so we can
// properly notify invalidation_client_.
@@ -77,8 +78,7 @@ class ChromeInvalidationClient : public invalidation::InvalidationListener {
scoped_ptr<invalidation::InvalidationClient> invalidation_client_;
scoped_ptr<CacheInvalidationPacketHandler>
cache_invalidation_packet_handler_;
-
- void OnRegister(const invalidation::RegistrationUpdateResult& result);
+ scoped_ptr<RegistrationManager> registration_manager_;
DISALLOW_COPY_AND_ASSIGN(ChromeInvalidationClient);
};
diff --git a/chrome/browser/sync/notifier/invalidation_util.cc b/chrome/browser/sync/notifier/invalidation_util.cc
index 2683fae..f61a0db 100644
--- a/chrome/browser/sync/notifier/invalidation_util.cc
+++ b/chrome/browser/sync/notifier/invalidation_util.cc
@@ -13,8 +13,24 @@ void RunAndDeleteClosure(invalidation::Closure* task) {
delete task;
}
-// We need to write our own protobuf to string functions because we
-// use LITE_RUNTIME, which doesn't support DebugString().
+bool RealModelTypeToObjectId(syncable::ModelType model_type,
+ invalidation::ObjectId* object_id) {
+ std::string notification_type;
+ if (!syncable::RealModelTypeToNotificationType(
+ model_type, &notification_type)) {
+ return false;
+ }
+ object_id->mutable_name()->set_string_value(notification_type);
+ object_id->set_source(invalidation::ObjectId::CHROME_SYNC);
+ return true;
+}
+
+bool ObjectIdToRealModelType(const invalidation::ObjectId& object_id,
+ syncable::ModelType* model_type) {
+ return
+ syncable::NotificationTypeToRealModelType(
+ object_id.name().string_value(), model_type);
+}
std::string ObjectIdToString(
const invalidation::ObjectId& object_id) {
diff --git a/chrome/browser/sync/notifier/invalidation_util.h b/chrome/browser/sync/notifier/invalidation_util.h
index 3ca5fe9..92e6a6e 100644
--- a/chrome/browser/sync/notifier/invalidation_util.h
+++ b/chrome/browser/sync/notifier/invalidation_util.h
@@ -9,12 +9,19 @@
#include <string>
+#include "chrome/browser/sync/syncable/model_type.h"
#include "google/cacheinvalidation/invalidation-client.h"
namespace sync_notifier {
void RunAndDeleteClosure(invalidation::Closure* task);
+bool RealModelTypeToObjectId(syncable::ModelType model_type,
+ invalidation::ObjectId* object_id);
+
+bool ObjectIdToRealModelType(const invalidation::ObjectId& object_id,
+ syncable::ModelType* model_type);
+
// We need to write our own protobuf-to-string functions because we
// use LITE_RUNTIME, which doesn't support DebugString().
diff --git a/chrome/browser/sync/notifier/registration_manager.cc b/chrome/browser/sync/notifier/registration_manager.cc
new file mode 100644
index 0000000..3895c91
--- /dev/null
+++ b/chrome/browser/sync/notifier/registration_manager.cc
@@ -0,0 +1,132 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/notifier/registration_manager.h"
+
+#include <string>
+
+#include "chrome/browser/sync/notifier/invalidation_util.h"
+#include "chrome/browser/sync/syncable/model_type.h"
+#include "google/cacheinvalidation/invalidation-client.h"
+
+namespace sync_notifier {
+
+RegistrationManager::RegistrationManager(
+ invalidation::InvalidationClient* invalidation_client)
+ : invalidation_client_(invalidation_client) {
+ DCHECK(invalidation_client_);
+}
+
+RegistrationManager::~RegistrationManager() {
+ DCHECK(non_thread_safe_.CalledOnValidThread());
+}
+
+bool RegistrationManager::RegisterType(syncable::ModelType model_type) {
+ DCHECK(non_thread_safe_.CalledOnValidThread());
+ invalidation::ObjectId object_id;
+ if (!RealModelTypeToObjectId(model_type, &object_id)) {
+ LOG(ERROR) << "Invalid model type: " << model_type;
+ return false;
+ }
+ RegistrationStatusMap::iterator it =
+ registration_status_.insert(
+ std::make_pair(model_type, UNREGISTERED)).first;
+ if (it->second == UNREGISTERED) {
+ RegisterObject(object_id, it);
+ }
+ return true;
+}
+
+bool RegistrationManager::IsRegistered(
+ syncable::ModelType model_type) const {
+ DCHECK(non_thread_safe_.CalledOnValidThread());
+ RegistrationStatusMap::const_iterator it =
+ registration_status_.find(model_type);
+ if (it == registration_status_.end()) {
+ return false;
+ }
+ return it->second == REGISTERED;
+}
+
+void RegistrationManager::MarkRegistrationLost(
+ syncable::ModelType model_type) {
+ DCHECK(non_thread_safe_.CalledOnValidThread());
+ invalidation::ObjectId object_id;
+ if (!RealModelTypeToObjectId(model_type, &object_id)) {
+ LOG(ERROR) << "Invalid model type: " << model_type;
+ return;
+ }
+ RegistrationStatusMap::iterator it =
+ registration_status_.find(model_type);
+ if (it == registration_status_.end()) {
+ LOG(ERROR) << "Unknown model type: "
+ << syncable::ModelTypeToString(model_type);
+ return;
+ }
+ it->second = UNREGISTERED;
+ RegisterObject(object_id, it);
+}
+
+void RegistrationManager::MarkAllRegistrationsLost() {
+ DCHECK(non_thread_safe_.CalledOnValidThread());
+ for (RegistrationStatusMap::iterator it =
+ registration_status_.begin();
+ it != registration_status_.end(); ++it) {
+ invalidation::ObjectId object_id;
+ if (!RealModelTypeToObjectId(it->first, &object_id)) {
+ LOG(DFATAL) << "Invalid model type: " << it->first;
+ continue;
+ }
+ it->second = UNREGISTERED;
+ RegisterObject(object_id, it);
+ }
+}
+
+void RegistrationManager::RegisterObject(
+ const invalidation::ObjectId& object_id,
+ RegistrationStatusMap::iterator it) {
+ DCHECK_EQ(it->second, UNREGISTERED);
+ invalidation_client_->Register(
+ object_id,
+ invalidation::NewPermanentCallback(
+ this, &RegistrationManager::OnRegister));
+ it->second = PENDING;
+}
+
+void RegistrationManager::OnRegister(
+ const invalidation::RegistrationUpdateResult& result) {
+ DCHECK(non_thread_safe_.CalledOnValidThread());
+ LOG(INFO) << "OnRegister: " << RegistrationUpdateResultToString(result);
+ if (result.operation().type() !=
+ invalidation::RegistrationUpdate::REGISTER) {
+ LOG(ERROR) << "Got non-register result";
+ return;
+ }
+ syncable::ModelType model_type;
+ if (!ObjectIdToRealModelType(result.operation().object_id(),
+ &model_type)) {
+ LOG(ERROR) << "Could not get model type";
+ return;
+ }
+ RegistrationStatusMap::iterator it =
+ registration_status_.find(model_type);
+ if (it == registration_status_.end()) {
+ LOG(ERROR) << "Unknown model type: " << model_type;
+ return;
+ }
+ invalidation::Status::Code code = result.status().code();
+ switch (code) {
+ case invalidation::Status::SUCCESS:
+ it->second = REGISTERED;
+ break;
+ case invalidation::Status::TRANSIENT_FAILURE:
+ // TODO(akalin): Add retry logic. For now, just fall through.
+ default:
+ // Treat everything else as a permanent failure.
+ LOG(ERROR) << "Registration failed with code: " << code;
+ break;
+ }
+}
+
+} // namespace sync_notifier
diff --git a/chrome/browser/sync/notifier/registration_manager.h b/chrome/browser/sync/notifier/registration_manager.h
new file mode 100644
index 0000000..52f299be
--- /dev/null
+++ b/chrome/browser/sync/notifier/registration_manager.h
@@ -0,0 +1,83 @@
+// Copyright (c) 2010 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 that manages the registration of types for server-issued
+// notifications.
+
+#ifndef CHROME_BROWSER_SYNC_NOTIFIER_REGISTRATION_MANAGER_H_
+#define CHROME_BROWSER_SYNC_NOTIFIER_REGISTRATION_MANAGER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/non_thread_safe.h"
+#include "chrome/browser/sync/syncable/model_type.h"
+
+namespace invalidation {
+class InvalidationClient;
+class ObjectId;
+class RegistrationUpdateResult;
+} // namespace
+
+namespace sync_notifier {
+
+class RegistrationManager {
+ public:
+ // Does not take ownership of |invalidation_client_|.
+ explicit RegistrationManager(
+ invalidation::InvalidationClient* invalidation_client);
+
+ ~RegistrationManager();
+
+ // If |model_type| is valid, starts the process to register it and
+ // returns true. Otherwise, returns false.
+ bool RegisterType(syncable::ModelType model_type);
+
+ // Returns true iff |model_type| has been successfully registered.
+ // Note that IsRegistered(model_type) may not immediately (or ever)
+ // return true after calling RegisterType(model_type).
+ //
+ // Currently only used by unit tests.
+ bool IsRegistered(syncable::ModelType model_type) const;
+
+ // TODO(akalin): We will eventually need an UnregisterType().
+
+ // Marks the registration for the |model_type| lost and re-registers
+ // it.
+ void MarkRegistrationLost(syncable::ModelType model_type);
+
+ // Marks all registrations lost and re-registers them.
+ void MarkAllRegistrationsLost();
+
+ private:
+ enum RegistrationStatus {
+ // Registration request has not yet been sent.
+ UNREGISTERED,
+ // Registration request has been sent; waiting on confirmation.
+ PENDING,
+ // Registration has been confirmed.
+ REGISTERED,
+ };
+
+ typedef std::map<syncable::ModelType, RegistrationStatus>
+ RegistrationStatusMap;
+
+ // Calls invalidation_client_->Register() on |object_id|. sets
+ // it->second to UNREGISTERED -> PENDING.
+ void RegisterObject(const invalidation::ObjectId& object_id,
+ RegistrationStatusMap::iterator it);
+
+ void OnRegister(const invalidation::RegistrationUpdateResult& result);
+
+ NonThreadSafe non_thread_safe_;
+ // Weak pointer.
+ invalidation::InvalidationClient* invalidation_client_;
+ RegistrationStatusMap registration_status_;
+
+ DISALLOW_COPY_AND_ASSIGN(RegistrationManager);
+};
+
+} // namespace sync_notifier
+
+#endif // CHROME_BROWSER_SYNC_NOTIFIER_REGISTRATION_MANAGER_H_
diff --git a/chrome/browser/sync/notifier/registration_manager_unittest.cc b/chrome/browser/sync/notifier/registration_manager_unittest.cc
new file mode 100644
index 0000000..0f47f88
--- /dev/null
+++ b/chrome/browser/sync/notifier/registration_manager_unittest.cc
@@ -0,0 +1,287 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/notifier/registration_manager.h"
+
+#include <cstddef>
+#include <deque>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "chrome/browser/sync/notifier/invalidation_util.h"
+#include "chrome/browser/sync/syncable/model_type.h"
+#include "google/cacheinvalidation/invalidation-client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sync_notifier {
+namespace {
+
+// Fake invalidation client that just stores the args of calls to
+// Register().
+class FakeInvalidationClient : public invalidation::InvalidationClient {
+ public:
+ struct Args {
+ Args() : callback(NULL) {}
+
+ Args(const invalidation::ObjectId& oid,
+ invalidation::RegistrationCallback* callback)
+ : oid(oid), callback(callback) {}
+
+ invalidation::ObjectId oid;
+ invalidation::RegistrationCallback* callback;
+ };
+
+ FakeInvalidationClient() {}
+
+ virtual ~FakeInvalidationClient() {
+ for (std::deque<Args>::iterator it = register_calls.begin();
+ it != register_calls.end(); ++it) {
+ delete it->callback;
+ }
+ }
+
+ void Register(const invalidation::ObjectId& oid,
+ invalidation::RegistrationCallback* callback) {
+ register_calls.push_back(Args(oid, callback));
+ }
+
+ void Unregister(const invalidation::ObjectId& oid,
+ invalidation::RegistrationCallback* callback) {
+ ADD_FAILURE();
+ delete callback;
+ }
+
+ invalidation::NetworkEndpoint* network_endpoint() {
+ ADD_FAILURE();
+ return NULL;
+ }
+
+ void GetClientUniquifier(invalidation::string* uniquifier) const {
+ ADD_FAILURE();
+ }
+
+ std::deque<Args> register_calls;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FakeInvalidationClient);
+};
+
+class RegistrationManagerTest : public testing::Test {
+ protected:
+ RegistrationManagerTest()
+ : registration_manager_(&fake_invalidation_client_) {}
+
+ virtual ~RegistrationManagerTest() {}
+
+ FakeInvalidationClient fake_invalidation_client_;
+ RegistrationManager registration_manager_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RegistrationManagerTest);
+};
+
+invalidation::ObjectId ModelTypeToObjectId(
+ syncable::ModelType model_type) {
+ invalidation::ObjectId object_id;
+ EXPECT_TRUE(RealModelTypeToObjectId(model_type, &object_id));
+ return object_id;
+}
+
+syncable::ModelType ObjectIdToModelType(
+ const invalidation::ObjectId& object_id) {
+ syncable::ModelType model_type = syncable::UNSPECIFIED;
+ EXPECT_TRUE(ObjectIdToRealModelType(object_id, &model_type));
+ return model_type;
+}
+
+invalidation::RegistrationUpdateResult MakeRegistrationUpdateResult(
+ syncable::ModelType model_type) {
+ invalidation::RegistrationUpdateResult result;
+ result.mutable_operation()->
+ set_type(invalidation::RegistrationUpdate::REGISTER);
+ *result.mutable_operation()->mutable_object_id() =
+ ModelTypeToObjectId(model_type);
+ result.mutable_status()->set_code(invalidation::Status::SUCCESS);
+ return result;
+}
+
+TEST_F(RegistrationManagerTest, RegisterType) {
+ const syncable::ModelType kModelTypes[] = {
+ syncable::BOOKMARKS,
+ syncable::PREFERENCES,
+ syncable::THEMES,
+ syncable::AUTOFILL,
+ syncable::EXTENSIONS,
+ };
+ const size_t kModelTypeCount = arraysize(kModelTypes);
+
+ // Register types.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ // Register twice; it shouldn't matter.
+ registration_manager_.RegisterType(kModelTypes[i]);
+ registration_manager_.RegisterType(kModelTypes[i]);
+ }
+
+ ASSERT_EQ(kModelTypeCount,
+ fake_invalidation_client_.register_calls.size());
+
+ // Nothing should be registered yet.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ EXPECT_FALSE(registration_manager_.IsRegistered(kModelTypes[i]));
+ }
+
+ // Check object IDs.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ EXPECT_EQ(kModelTypes[i],
+ ObjectIdToModelType(
+ fake_invalidation_client_.register_calls[i].oid));
+ }
+
+ // Prepare results.
+ std::vector<invalidation::RegistrationUpdateResult> results(
+ kModelTypeCount);
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ results[i] = MakeRegistrationUpdateResult(kModelTypes[i]);
+ }
+
+ // Generate a variety of error conditions in all but the first
+ // result.
+ results[1].mutable_operation()->set_type(
+ invalidation::RegistrationUpdate::UNREGISTER);
+ results[2].mutable_operation()->mutable_object_id()->
+ mutable_name()->set_string_value("garbage");
+ results[3].mutable_status()->
+ set_code(invalidation::Status::UNKNOWN_ERROR);
+ *results[4].mutable_operation()->mutable_object_id() =
+ ModelTypeToObjectId(syncable::TYPED_URLS);
+
+
+ // Send the registration results back.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ fake_invalidation_client_.register_calls[i].callback->Run(results[i]);
+ }
+
+ // Only the first one should be registered.
+ EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[0]));
+ for (size_t i = 1; i < kModelTypeCount; ++i) {
+ EXPECT_FALSE(registration_manager_.IsRegistered(kModelTypes[i]));
+ }
+}
+
+TEST_F(RegistrationManagerTest, MarkRegistrationLost) {
+ const syncable::ModelType kModelTypes[] = {
+ syncable::BOOKMARKS,
+ syncable::PREFERENCES,
+ syncable::THEMES,
+ syncable::AUTOFILL,
+ syncable::EXTENSIONS,
+ };
+ const size_t kModelTypeCount = arraysize(kModelTypes);
+
+ // Register types.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ registration_manager_.RegisterType(kModelTypes[i]);
+ }
+
+ ASSERT_EQ(kModelTypeCount,
+ fake_invalidation_client_.register_calls.size());
+
+ // Send the registration results back.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ fake_invalidation_client_.register_calls[i].callback->Run(
+ MakeRegistrationUpdateResult(kModelTypes[i]));
+ }
+
+ // All should be registered.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
+ }
+
+ // Mark the registrations of all but the first one lost.
+ for (size_t i = 1; i < kModelTypeCount; ++i) {
+ registration_manager_.MarkRegistrationLost(kModelTypes[i]);
+ }
+
+ ASSERT_EQ(2 * kModelTypeCount - 1,
+ fake_invalidation_client_.register_calls.size());
+
+ // Only the first one should be registered.
+ EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[0]));
+ for (size_t i = 1; i < kModelTypeCount; ++i) {
+ EXPECT_FALSE(registration_manager_.IsRegistered(kModelTypes[i]));
+ }
+
+ // Send more registration results back.
+ for (size_t i = 1; i < kModelTypeCount; ++i) {
+ fake_invalidation_client_.register_calls[kModelTypeCount + i - 1].
+ callback->Run(
+ MakeRegistrationUpdateResult(kModelTypes[i]));
+ }
+
+ // All should be registered.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
+ }
+}
+
+TEST_F(RegistrationManagerTest, MarkAllRegistrationsLost) {
+ const syncable::ModelType kModelTypes[] = {
+ syncable::BOOKMARKS,
+ syncable::PREFERENCES,
+ syncable::THEMES,
+ syncable::AUTOFILL,
+ syncable::EXTENSIONS,
+ };
+ const size_t kModelTypeCount = arraysize(kModelTypes);
+
+ // Register types.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ registration_manager_.RegisterType(kModelTypes[i]);
+ }
+
+ ASSERT_EQ(kModelTypeCount,
+ fake_invalidation_client_.register_calls.size());
+
+ // Send the registration results back.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ fake_invalidation_client_.register_calls[i].callback->Run(
+ MakeRegistrationUpdateResult(kModelTypes[i]));
+ }
+
+ // All should be registered.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
+ }
+
+ // Mark the registrations of all but the first one lost. Then mark
+ // everything lost.
+ for (size_t i = 1; i < kModelTypeCount; ++i) {
+ registration_manager_.MarkRegistrationLost(kModelTypes[i]);
+ }
+ registration_manager_.MarkAllRegistrationsLost();
+
+ ASSERT_EQ(3 * kModelTypeCount - 1,
+ fake_invalidation_client_.register_calls.size());
+
+ // None should be registered.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ EXPECT_FALSE(registration_manager_.IsRegistered(kModelTypes[i]));
+ }
+
+ // Send more registration results back.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ fake_invalidation_client_.register_calls[2 * kModelTypeCount + i - 1].
+ callback->Run(
+ MakeRegistrationUpdateResult(kModelTypes[i]));
+ }
+
+ // All should be registered.
+ for (size_t i = 0; i < kModelTypeCount; ++i) {
+ EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
+ }
+}
+
+} // namespace
+} // namespace notifier
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 320ab5d..d87ec30 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -993,6 +993,8 @@
'browser/sync/notifier/chrome_system_resources.h',
'browser/sync/notifier/invalidation_util.cc',
'browser/sync/notifier/invalidation_util.h',
+ 'browser/sync/notifier/registration_manager.cc',
+ 'browser/sync/notifier/registration_manager.h',
'browser/sync/notifier/server_notifier_thread.cc',
'browser/sync/notifier/server_notifier_thread.h',
],
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index a4daba3..e8eea76 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1821,6 +1821,7 @@
'browser/sync/engine/syncproto_unittest.cc',
'browser/sync/engine/verify_updates_command_unittest.cc',
'browser/sync/glue/change_processor_mock.h',
+ 'browser/sync/notifier/registration_manager_unittest.cc',
'browser/sync/profile_sync_factory_mock.cc',
'browser/sync/profile_sync_factory_mock.h',
'browser/sync/sessions/ordered_commit_set_unittest.cc',
@@ -1866,6 +1867,7 @@
'../third_party/libjingle/libjingle.gyp:libjingle',
'profile_import',
'syncapi',
+ 'sync_notifier',
'test_support_unit',
],
'conditions': [