summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-10 19:26:16 +0000
committerrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-10 19:26:16 +0000
commite85797cd8652628481291a6c202e150d1f8adf78 (patch)
treed1b2e3441d5e79c60b9e95c11b36aa5177e668b4
parentedfdd0d4d3dd10f5c0f3f9de204961191656878f (diff)
downloadchromium_src-e85797cd8652628481291a6c202e150d1f8adf78.zip
chromium_src-e85797cd8652628481291a6c202e150d1f8adf78.tar.gz
chromium_src-e85797cd8652628481291a6c202e150d1f8adf78.tar.bz2
Commit InvalidationService implementations
This commit introduces a new ProfileKeyedService, the InvalidationService. Clients may register with this service to receive notifications from a server informing them when they need to fetch updates to their cached state. (In other words, they will receive notifications when their cache has become invalid.) There are three different implementations of this service, all of which inherit from InvalidationFrontend. The current provider of invalidations, ProfileSyncService, also inherits from this interface. The TiclInvalidationService receives notifications through the C++ version of the googlecacheinvalidation (aka. TICL) library. It is used on Chromium for Desktop operating systems. The AndroidInvalidationService receives notifications by listening to the in-process NotificationService (content/public/browser/notification_service.h). The code that actually sends these notifications is a small bridge from Java-land, which is not affected by this CL. The P2PInvalidationService uses XMPP peer-to-peer connections to send and receive invalidations. This has not been used in Chromium for a very long time. We keep it around because some of our integration tests rely on it. This CL also includes an InvalidationServiceFactory to help manage the selection and construction of these InvalidationServices. The tests for these new services are based on a modified version of sync/notifier/invalidator_test_template.h. The P2PInvalidationService is not tested at all because it is itself a test-only utility. In addition to the new code, this CL moves around some old code to help populate a new directory, chrome/browser/invalidation. We're trying to separate invalidations from sync, so the chrome/browser/sync/invalidations directory was no longer needed. Finally, note that this commit does not change Chromium in any way. It adds new classes and test for them, but the rest of the code has not been modified to make use of them. Those changes will happen in a future CL. BUG=124137 Review URL: https://chromiumcodereview.appspot.com/13991017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@199520 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.cc4
-rw-r--r--chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h6
-rw-r--r--chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc4
-rw-r--r--chrome/browser/invalidation/DEPS8
-rw-r--r--chrome/browser/invalidation/OWNERS5
-rw-r--r--chrome/browser/invalidation/invalidation_frontend.h (renamed from chrome/browser/sync/invalidation_frontend.h)32
-rw-r--r--chrome/browser/invalidation/invalidation_frontend_test_template.cc27
-rw-r--r--chrome/browser/invalidation/invalidation_frontend_test_template.h384
-rw-r--r--chrome/browser/invalidation/invalidation_service_android.cc95
-rw-r--r--chrome/browser/invalidation/invalidation_service_android.h71
-rw-r--r--chrome/browser/invalidation/invalidation_service_android_unittest.cc61
-rw-r--r--chrome/browser/invalidation/invalidation_service_factory.cc70
-rw-r--r--chrome/browser/invalidation/invalidation_service_factory.h55
-rw-r--r--chrome/browser/invalidation/invalidation_service_util.cc56
-rw-r--r--chrome/browser/invalidation/invalidation_service_util.h22
-rw-r--r--chrome/browser/invalidation/invalidator_storage.cc (renamed from chrome/browser/sync/invalidations/invalidator_storage.cc)8
-rw-r--r--chrome/browser/invalidation/invalidator_storage.h (renamed from chrome/browser/sync/invalidations/invalidator_storage.h)16
-rw-r--r--chrome/browser/invalidation/invalidator_storage_unittest.cc (renamed from chrome/browser/sync/invalidations/invalidator_storage_unittest.cc)9
-rw-r--r--chrome/browser/invalidation/p2p_invalidation_service.cc79
-rw-r--r--chrome/browser/invalidation/p2p_invalidation_service.h65
-rw-r--r--chrome/browser/invalidation/ticl_invalidation_service.cc244
-rw-r--r--chrome/browser/invalidation/ticl_invalidation_service.h103
-rw-r--r--chrome/browser/invalidation/ticl_invalidation_service_unittest.cc59
-rw-r--r--chrome/browser/prefs/browser_prefs.cc4
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.cc4
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.h8
-rw-r--r--chrome/browser/sync/glue/sync_backend_host_unittest.cc6
-rw-r--r--chrome/browser/sync/profile_sync_service.h8
-rw-r--r--chrome/browser/sync/test_profile_sync_service.cc2
-rw-r--r--chrome/browser/sync/test_profile_sync_service.h5
-rw-r--r--chrome/chrome_browser.gypi20
-rw-r--r--chrome/chrome_tests_unit.gypi9
32 files changed, 1486 insertions, 63 deletions
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.cc
index 140991c..95eb4e7 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.cc
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.cc
@@ -10,7 +10,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_delegate.h"
-#include "chrome/browser/sync/invalidation_frontend.h"
+#include "chrome/browser/invalidation/invalidation_frontend.h"
#include "chrome/common/extensions/extension.h"
#include "google/cacheinvalidation/types.pb.h"
@@ -78,7 +78,7 @@ bool ObjectIdToExtensionAndSubchannel(const invalidation::ObjectId& object_id,
} // namespace
PushMessagingInvalidationHandler::PushMessagingInvalidationHandler(
- InvalidationFrontend* service,
+ invalidation::InvalidationFrontend* service,
PushMessagingInvalidationHandlerDelegate* delegate)
: service_(service),
delegate_(delegate) {
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h
index 2268aec..ef40b76 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h
@@ -14,7 +14,9 @@
#include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_mapper.h"
#include "sync/notifier/invalidation_handler.h"
+namespace invalidation {
class InvalidationFrontend;
+}
namespace extensions {
@@ -30,7 +32,7 @@ class PushMessagingInvalidationHandler : public PushMessagingInvalidationMapper,
// |extension_ids| is the set of extension IDs for which push messaging is
// enabled.
PushMessagingInvalidationHandler(
- InvalidationFrontend* service,
+ invalidation::InvalidationFrontend* service,
PushMessagingInvalidationHandlerDelegate* delegate);
virtual ~PushMessagingInvalidationHandler();
@@ -54,7 +56,7 @@ class PushMessagingInvalidationHandler : public PushMessagingInvalidationMapper,
void UpdateRegistrations();
base::ThreadChecker thread_checker_;
- InvalidationFrontend* const service_;
+ invalidation::InvalidationFrontend* const service_;
std::set<std::string> registered_extensions_;
syncer::ObjectIdSet suppressed_ids_;
PushMessagingInvalidationHandlerDelegate* const delegate_;
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc
index bc03c5d..9ab280b 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc
@@ -7,7 +7,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_delegate.h"
-#include "chrome/browser/sync/invalidation_frontend.h"
+#include "chrome/browser/invalidation/invalidation_frontend.h"
#include "google/cacheinvalidation/types.pb.h"
#include "sync/internal_api/public/base/invalidation_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -22,7 +22,7 @@ namespace extensions {
namespace {
-class MockInvalidationFrontend : public InvalidationFrontend {
+class MockInvalidationFrontend : public invalidation::InvalidationFrontend {
public:
MockInvalidationFrontend();
~MockInvalidationFrontend();
diff --git a/chrome/browser/invalidation/DEPS b/chrome/browser/invalidation/DEPS
new file mode 100644
index 0000000..808be5d
--- /dev/null
+++ b/chrome/browser/invalidation/DEPS
@@ -0,0 +1,8 @@
+include_rules = [
+ # Needed for P2PInvalidationService construction.
+ "+jingle/notifier",
+
+ # Needed for SyncMaxInvalidationVersions Migration.
+ "+sync/internal_api/public/base/model_type.h",
+ "+sync/internal_api/public/base/invalidation_test_util.h",
+]
diff --git a/chrome/browser/invalidation/OWNERS b/chrome/browser/invalidation/OWNERS
new file mode 100644
index 0000000..e838315
--- /dev/null
+++ b/chrome/browser/invalidation/OWNERS
@@ -0,0 +1,5 @@
+akalin@chromium.org
+dcheng@chromium.org
+nyquist@chromium.org
+rlarocque@chromium.org
+tim@chromium.org
diff --git a/chrome/browser/sync/invalidation_frontend.h b/chrome/browser/invalidation/invalidation_frontend.h
index 0c76770..8344e27 100644
--- a/chrome/browser/sync/invalidation_frontend.h
+++ b/chrome/browser/invalidation/invalidation_frontend.h
@@ -2,15 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_SYNC_INVALIDATION_FRONTEND_H_
-#define CHROME_BROWSER_SYNC_INVALIDATION_FRONTEND_H_
+#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_H_
+#define CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_H_
#include "sync/notifier/invalidation_util.h"
+#include "sync/notifier/invalidator_state.h"
namespace syncer {
class InvalidationHandler;
+class AckHandle;
} // namespace syncer
+namespace invalidation {
+
// Interface for classes that handle invalidation registrations and send out
// invalidations to register handlers.
//
@@ -26,19 +30,10 @@ class InvalidationHandler;
//
// frontend->UpdateRegisteredInvalidationIds(client_handler, client_ids);
//
-// When shutting down the client for browser shutdown:
+// To unregister for all invalidations:
//
// frontend->UnregisterInvalidationHandler(client_handler);
//
-// Note that there's no call to UpdateRegisteredIds() -- this is because the
-// invalidation API persists registrations across browser restarts.
-//
-// When permanently shutting down the client, e.g. when disabling the related
-// feature:
-//
-// frontend->UpdateRegisteredInvalidationIds(client_handler, ObjectIdSet());
-// frontend->UnregisterInvalidationHandler(client_handler);
-//
// If an invalidation handler cares about the invalidator state, it should also
// do the following when starting the client:
//
@@ -47,11 +42,10 @@ class InvalidationHandler;
// It can also do the above in OnInvalidatorStateChange(), or it can use the
// argument to OnInvalidatorStateChange().
//
-// It is an error to have registered handlers when an
-// InvalidationFrontend is shut down; clients must ensure that they
-// unregister themselves before then. (Depending on the
-// InvalidationFrontend, shutdown may be equivalent to destruction, or
-// a separate function call like Shutdown()).
+// It is an error to have registered handlers when an InvalidationFrontend is
+// shut down; clients must ensure that they unregister themselves before then.
+//
+// TODO(rlarocque): This class should extend ProfileKeyedService.
//
// NOTE(akalin): Invalidations that come in during browser shutdown may get
// dropped. This won't matter once we have an Acknowledge API, though: see
@@ -96,4 +90,6 @@ class InvalidationFrontend {
virtual ~InvalidationFrontend() { }
};
-#endif // CHROME_BROWSER_SYNC_INVALIDATION_FRONTEND_H_
+} // namespace invalidation
+
+#endif // CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_H_
diff --git a/chrome/browser/invalidation/invalidation_frontend_test_template.cc b/chrome/browser/invalidation/invalidation_frontend_test_template.cc
new file mode 100644
index 0000000..b454623
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_frontend_test_template.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2013 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/invalidation/invalidation_frontend_test_template.h"
+
+namespace internal {
+
+BoundFakeInvalidationHandler::BoundFakeInvalidationHandler(
+ const invalidation::InvalidationFrontend& invalidator)
+ : invalidator_(invalidator),
+ last_retrieved_state_(syncer::DEFAULT_INVALIDATION_ERROR) {}
+
+BoundFakeInvalidationHandler::~BoundFakeInvalidationHandler() {}
+
+syncer::InvalidatorState
+BoundFakeInvalidationHandler::GetLastRetrievedState() const {
+ return last_retrieved_state_;
+}
+
+void BoundFakeInvalidationHandler::OnInvalidatorStateChange(
+ syncer::InvalidatorState state) {
+ FakeInvalidationHandler::OnInvalidatorStateChange(state);
+ last_retrieved_state_ = invalidator_.GetInvalidatorState();
+}
+
+}
diff --git a/chrome/browser/invalidation/invalidation_frontend_test_template.h b/chrome/browser/invalidation/invalidation_frontend_test_template.h
new file mode 100644
index 0000000..9643504
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_frontend_test_template.h
@@ -0,0 +1,384 @@
+// Copyright (c) 2013 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.
+
+// This class defines tests that implementations of InvalidationFrontend should
+// pass in order to be conformant. Here's how you use it to test your
+// implementation.
+//
+// Say your class is called MyInvalidationFrontend. Then you need to define a
+// class called MyInvalidationFrontendTestDelegate in
+// my_invalidation_frontend_unittest.cc like this:
+//
+// class MyInvalidationFrontendTestDelegate {
+// public:
+// MyInvalidationFrontendTestDelegate() ...
+//
+// ~MyInvalidationFrontendTestDelegate() {
+// // DestroyInvalidator() may not be explicitly called by tests.
+// DestroyInvalidator();
+// }
+//
+// // Create the InvalidationFrontend implementation with the given params.
+// void CreateInvalidationFrontend() {
+// ...
+// }
+//
+// // Should return the InvalidationFrontend implementation. Only called
+// // after CreateInvalidator and before DestroyInvalidator.
+// MyInvalidationFrontend* GetInvalidationFrontend() {
+// ...
+// }
+//
+// // Destroy the InvalidationFrontend implementation.
+// void DestroyInvalidationFrontend() {
+// ...
+// }
+//
+// // The Trigger* functions below should block until the effects of
+// // the call are visible on the current thread.
+//
+// // Should cause OnInvalidatorStateChange() to be called on all
+// // observers of the InvalidationFrontend implementation with the given
+// // parameters.
+// void TriggerOnInvalidatorStateChange(InvalidatorState state) {
+// ...
+// }
+//
+// // Should cause OnIncomingInvalidation() to be called on all
+// // observers of the InvalidationFrontend implementation with the given
+// // parameters.
+// void TriggerOnIncomingInvalidation(
+// const ObjectIdInvalidationMap& invalidation_map) {
+// ...
+// }
+// };
+//
+// The InvalidationFrontendTest test harness will have a member variable of
+// this delegate type and will call its functions in the various
+// tests.
+//
+// Then you simply #include this file as well as gtest.h and add the
+// following statement to my_sync_notifier_unittest.cc:
+//
+// INSTANTIATE_TYPED_TEST_CASE_P(
+// MyInvalidationFrontend,
+// InvalidationFrontendTest,
+// MyInvalidatorTestDelegate);
+//
+// Easy!
+
+#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_TEST_TEMPLATE_H_
+#define CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_TEST_TEMPLATE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "google/cacheinvalidation/include/types.h"
+#include "google/cacheinvalidation/types.pb.h"
+#include "sync/notifier/fake_invalidation_handler.h"
+#include "sync/notifier/object_id_invalidation_map.h"
+#include "sync/notifier/object_id_invalidation_map_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+template <typename InvalidatorTestDelegate>
+class InvalidationFrontendTest : public testing::Test {
+ protected:
+ // Note: The IDs defined below must be valid. Otherwise they won't make it
+ // through the round-trip to ModelTypeInvalidationMap and back that the
+ // AndroidInvalidation test requires.
+ InvalidationFrontendTest()
+ : id1(ipc::invalidation::ObjectSource::CHROME_SYNC, "BOOKMARK"),
+ id2(ipc::invalidation::ObjectSource::CHROME_SYNC, "PREFERENCE"),
+ id3(ipc::invalidation::ObjectSource::CHROME_SYNC, "AUTOFILL"),
+ id4(ipc::invalidation::ObjectSource::CHROME_SYNC, "EXPERIMENTS") {
+ }
+
+ invalidation::InvalidationFrontend*
+ CreateAndInitializeInvalidationFrontend() {
+ this->delegate_.CreateInvalidationFrontend();
+ return this->delegate_.GetInvalidationFrontend();
+ }
+
+ InvalidatorTestDelegate delegate_;
+
+ const invalidation::ObjectId id1;
+ const invalidation::ObjectId id2;
+ const invalidation::ObjectId id3;
+ const invalidation::ObjectId id4;
+};
+
+TYPED_TEST_CASE_P(InvalidationFrontendTest);
+
+// Initialize the invalidator, register a handler, register some IDs for that
+// handler, and then unregister the handler, dispatching invalidations in
+// between. The handler should only see invalidations when its registered and
+// its IDs are registered.
+TYPED_TEST_P(InvalidationFrontendTest, Basic) {
+ invalidation::InvalidationFrontend* const invalidator =
+ this->CreateAndInitializeInvalidationFrontend();
+
+ syncer::FakeInvalidationHandler handler;
+
+ invalidator->RegisterInvalidationHandler(&handler);
+
+ syncer::ObjectIdInvalidationMap states;
+ states[this->id1].payload = "1";
+ states[this->id2].payload = "2";
+ states[this->id3].payload = "3";
+
+ // Should be ignored since no IDs are registered to |handler|.
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+ EXPECT_EQ(0, handler.GetInvalidationCount());
+
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id1);
+ ids.insert(this->id2);
+ invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::INVALIDATIONS_ENABLED);
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
+
+ syncer::ObjectIdInvalidationMap expected_states;
+ expected_states[this->id1].payload = "1";
+ expected_states[this->id2].payload = "2";
+
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+ EXPECT_EQ(1, handler.GetInvalidationCount());
+ EXPECT_THAT(expected_states, Eq(handler.GetLastInvalidationMap()));
+
+ ids.erase(this->id1);
+ ids.insert(this->id3);
+ invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
+
+ expected_states.erase(this->id1);
+ expected_states[this->id3].payload = "3";
+
+ // Removed object IDs should not be notified, newly-added ones should.
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+ EXPECT_EQ(2, handler.GetInvalidationCount());
+ EXPECT_THAT(expected_states, Eq(handler.GetLastInvalidationMap()));
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::TRANSIENT_INVALIDATION_ERROR);
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler.GetInvalidatorState());
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::INVALIDATION_CREDENTIALS_REJECTED);
+ EXPECT_EQ(syncer::INVALIDATION_CREDENTIALS_REJECTED,
+ handler.GetInvalidatorState());
+
+ invalidator->UnregisterInvalidationHandler(&handler);
+
+ // Should be ignored since |handler| isn't registered anymore.
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+ EXPECT_EQ(2, handler.GetInvalidationCount());
+}
+
+// Register handlers and some IDs for those handlers, register a handler with
+// no IDs, and register a handler with some IDs but unregister it. Then,
+// dispatch some invalidations and invalidations. Handlers that are registered
+// should get invalidations, and the ones that have registered IDs should
+// receive invalidations for those IDs.
+TYPED_TEST_P(InvalidationFrontendTest, MultipleHandlers) {
+ invalidation::InvalidationFrontend* const invalidator =
+ this->CreateAndInitializeInvalidationFrontend();
+
+ syncer::FakeInvalidationHandler handler1;
+ syncer::FakeInvalidationHandler handler2;
+ syncer::FakeInvalidationHandler handler3;
+ syncer::FakeInvalidationHandler handler4;
+
+ invalidator->RegisterInvalidationHandler(&handler1);
+ invalidator->RegisterInvalidationHandler(&handler2);
+ invalidator->RegisterInvalidationHandler(&handler3);
+ invalidator->RegisterInvalidationHandler(&handler4);
+
+ {
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id1);
+ ids.insert(this->id2);
+ invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
+ }
+
+ {
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id3);
+ invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
+ }
+
+ // Don't register any IDs for handler3.
+
+ {
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id4);
+ invalidator->UpdateRegisteredInvalidationIds(&handler4, ids);
+ }
+
+ invalidator->UnregisterInvalidationHandler(&handler4);
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::INVALIDATIONS_ENABLED);
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler3.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler4.GetInvalidatorState());
+
+ {
+ syncer::ObjectIdInvalidationMap states;
+ states[this->id1].payload = "1";
+ states[this->id2].payload = "2";
+ states[this->id3].payload = "3";
+ states[this->id4].payload = "4";
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+
+ syncer::ObjectIdInvalidationMap expected_states;
+ expected_states[this->id1].payload = "1";
+ expected_states[this->id2].payload = "2";
+
+ EXPECT_EQ(1, handler1.GetInvalidationCount());
+ EXPECT_THAT(expected_states, Eq(handler1.GetLastInvalidationMap()));
+
+ expected_states.clear();
+ expected_states[this->id3].payload = "3";
+
+ EXPECT_EQ(1, handler2.GetInvalidationCount());
+ EXPECT_THAT(expected_states, Eq(handler2.GetLastInvalidationMap()));
+
+ EXPECT_EQ(0, handler3.GetInvalidationCount());
+ EXPECT_EQ(0, handler4.GetInvalidationCount());
+ }
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::TRANSIENT_INVALIDATION_ERROR);
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler1.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler2.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler3.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler4.GetInvalidatorState());
+
+ invalidator->UnregisterInvalidationHandler(&handler3);
+ invalidator->UnregisterInvalidationHandler(&handler2);
+ invalidator->UnregisterInvalidationHandler(&handler1);
+}
+
+// Make sure that passing an empty set to UpdateRegisteredInvalidationIds clears
+// the corresponding entries for the handler.
+TYPED_TEST_P(InvalidationFrontendTest, EmptySetUnregisters) {
+ invalidation::InvalidationFrontend* const invalidator =
+ this->CreateAndInitializeInvalidationFrontend();
+
+ syncer::FakeInvalidationHandler handler1;
+
+ // Control observer.
+ syncer::FakeInvalidationHandler handler2;
+
+ invalidator->RegisterInvalidationHandler(&handler1);
+ invalidator->RegisterInvalidationHandler(&handler2);
+
+ {
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id1);
+ ids.insert(this->id2);
+ invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
+ }
+
+ {
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id3);
+ invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
+ }
+
+ // Unregister the IDs for the first observer. It should not receive any
+ // further invalidations.
+ invalidator->UpdateRegisteredInvalidationIds(&handler1,
+ syncer::ObjectIdSet());
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::INVALIDATIONS_ENABLED);
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
+
+ {
+ syncer::ObjectIdInvalidationMap states;
+ states[this->id1].payload = "1";
+ states[this->id2].payload = "2";
+ states[this->id3].payload = "3";
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+ EXPECT_EQ(0, handler1.GetInvalidationCount());
+ EXPECT_EQ(1, handler2.GetInvalidationCount());
+ }
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::TRANSIENT_INVALIDATION_ERROR);
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler1.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler2.GetInvalidatorState());
+
+ invalidator->UnregisterInvalidationHandler(&handler2);
+ invalidator->UnregisterInvalidationHandler(&handler1);
+}
+
+namespace internal {
+
+// A FakeInvalidationHandler that is "bound" to a specific
+// InvalidationFrontend. This is for cross-referencing state information with
+// the bound InvalidationFrontend.
+class BoundFakeInvalidationHandler : public syncer::FakeInvalidationHandler {
+ public:
+ explicit BoundFakeInvalidationHandler(
+ const invalidation::InvalidationFrontend& invalidator);
+ virtual ~BoundFakeInvalidationHandler();
+
+ // Returns the last return value of GetInvalidatorState() on the
+ // bound invalidator from the last time the invalidator state
+ // changed.
+ syncer::InvalidatorState GetLastRetrievedState() const;
+
+ // InvalidationHandler implementation.
+ virtual void OnInvalidatorStateChange(
+ syncer::InvalidatorState state) OVERRIDE;
+
+ private:
+ const invalidation::InvalidationFrontend& invalidator_;
+ syncer::InvalidatorState last_retrieved_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler);
+};
+
+} // namespace internal
+
+TYPED_TEST_P(InvalidationFrontendTest, GetInvalidatorStateAlwaysCurrent) {
+ invalidation::InvalidationFrontend* const invalidator =
+ this->CreateAndInitializeInvalidationFrontend();
+
+ internal::BoundFakeInvalidationHandler handler(*invalidator);
+ invalidator->RegisterInvalidationHandler(&handler);
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::INVALIDATIONS_ENABLED);
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetLastRetrievedState());
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::TRANSIENT_INVALIDATION_ERROR);
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler.GetLastRetrievedState());
+
+ invalidator->UnregisterInvalidationHandler(&handler);
+}
+
+REGISTER_TYPED_TEST_CASE_P(InvalidationFrontendTest,
+ Basic, MultipleHandlers, EmptySetUnregisters,
+ GetInvalidatorStateAlwaysCurrent);
+
+#endif // CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_TEST_TEMPLATE_H_
diff --git a/chrome/browser/invalidation/invalidation_service_android.cc b/chrome/browser/invalidation/invalidation_service_android.cc
new file mode 100644
index 0000000..664aef1
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_service_android.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2013 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/invalidation/invalidation_service_android.h"
+
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/notification_service.h"
+
+namespace invalidation {
+
+InvalidationServiceAndroid::InvalidationServiceAndroid(Profile* profile)
+ : invalidator_state_(syncer::INVALIDATIONS_ENABLED) {
+ DCHECK(CalledOnValidThread());
+ registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
+ content::Source<Profile>(profile));
+}
+
+InvalidationServiceAndroid::~InvalidationServiceAndroid() { }
+
+void InvalidationServiceAndroid::RegisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) {
+ DCHECK(CalledOnValidThread());
+ invalidator_registrar_.RegisterHandler(handler);
+}
+
+void InvalidationServiceAndroid::UpdateRegisteredInvalidationIds(
+ syncer::InvalidationHandler* handler,
+ const syncer::ObjectIdSet& ids) {
+ DCHECK(CalledOnValidThread());
+ invalidator_registrar_.UpdateRegisteredIds(handler, ids);
+}
+
+void InvalidationServiceAndroid::UnregisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) {
+ DCHECK(CalledOnValidThread());
+ invalidator_registrar_.UnregisterHandler(handler);
+}
+
+void InvalidationServiceAndroid::AcknowledgeInvalidation(
+ const invalidation::ObjectId& id,
+ const syncer::AckHandle& ack_handle) {
+ DCHECK(CalledOnValidThread());
+ // Do nothing. The Android invalidator does not support ack tracking.
+}
+
+syncer::InvalidatorState
+InvalidationServiceAndroid::GetInvalidatorState() const {
+ DCHECK(CalledOnValidThread());
+ return invalidator_state_;
+}
+
+std::string InvalidationServiceAndroid::GetInvalidatorClientId() const {
+ DCHECK(CalledOnValidThread());
+ // TODO: Return a valid ID here. See crbug.com/172391.
+ return "Bogus";
+}
+
+void InvalidationServiceAndroid::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ DCHECK(CalledOnValidThread());
+ DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_REMOTE);
+
+ // TODO(akalin): Use ObjectIdInvalidationMap here instead. We'll have to
+ // make sure all emitters of the relevant notifications also use
+ // ObjectIdInvalidationMap.
+ content::Details<const syncer::ModelTypeInvalidationMap>
+ state_details(details);
+ const syncer::ModelTypeInvalidationMap& model_type_invalidation_map =
+ *(state_details.ptr());
+ syncer::ObjectIdInvalidationMap object_invalidation_map =
+ ModelTypeInvalidationMapToObjectIdInvalidationMap(
+ model_type_invalidation_map);
+
+ // An empty map implies that we should invalidate all.
+ const syncer::ObjectIdInvalidationMap& effective_invalidation_map =
+ object_invalidation_map.empty() ?
+ ObjectIdSetToInvalidationMap(
+ invalidator_registrar_.GetAllRegisteredIds(), std::string()) :
+ object_invalidation_map;
+
+ invalidator_registrar_.DispatchInvalidationsToHandlers(
+ effective_invalidation_map);
+}
+
+void InvalidationServiceAndroid::TriggerStateChangeForTest(
+ syncer::InvalidatorState state) {
+ DCHECK(CalledOnValidThread());
+ invalidator_state_ = state;
+ invalidator_registrar_.UpdateInvalidatorState(invalidator_state_);
+}
+
+} // namespace invalidation
diff --git a/chrome/browser/invalidation/invalidation_service_android.h b/chrome/browser/invalidation/invalidation_service_android.h
new file mode 100644
index 0000000..8f51b13
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_service_android.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2013 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_INVALIDATION_INVALIDATION_SERVICE_ANDROID_H_
+#define CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_ANDROID_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/threading/non_thread_safe.h"
+#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "chrome/browser/profiles/profile_keyed_service.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "sync/notifier/invalidator_registrar.h"
+
+class Profile;
+
+namespace invalidation {
+
+// This InvalidationService is used to deliver invalidations on Android. The
+// Android operating system has its own mechanisms for delivering invalidations.
+// This class uses the NotificationService to communicate with a thin wrapper
+// around Android's invalidations service.
+class InvalidationServiceAndroid
+ : public base::NonThreadSafe,
+ public ProfileKeyedService,
+ public InvalidationFrontend,
+ public content::NotificationObserver {
+ public:
+ explicit InvalidationServiceAndroid(Profile* profile);
+ virtual ~InvalidationServiceAndroid();
+
+ // InvalidationService implementation.
+ //
+ // Note that this implementation does not properly support Ack-tracking,
+ // fetching the invalidator state, or querying the client's ID. Support for
+ // exposing the client ID should be available soon; see crbug.com/172391.
+ virtual void RegisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) OVERRIDE;
+ virtual void UpdateRegisteredInvalidationIds(
+ syncer::InvalidationHandler* handler,
+ const syncer::ObjectIdSet& ids) OVERRIDE;
+ virtual void UnregisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) OVERRIDE;
+ virtual void AcknowledgeInvalidation(
+ const invalidation::ObjectId& id,
+ const syncer::AckHandle& ack_handle) OVERRIDE;
+ virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE;
+ virtual std::string GetInvalidatorClientId() const;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // The InvalidationServiceAndroid always reports that it is enabled.
+ // This is used only by unit tests.
+ void TriggerStateChangeForTest(syncer::InvalidatorState state);
+
+ private:
+ syncer::InvalidatorRegistrar invalidator_registrar_;
+ content::NotificationRegistrar registrar_;
+ syncer::InvalidatorState invalidator_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(InvalidationServiceAndroid);
+};
+
+} // namespace invalidation
+
+#endif // CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_ANDROID_H_
diff --git a/chrome/browser/invalidation/invalidation_service_android_unittest.cc b/chrome/browser/invalidation/invalidation_service_android_unittest.cc
new file mode 100644
index 0000000..feadf24
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_service_android_unittest.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 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/invalidation/invalidation_service_android.h"
+
+#include "chrome/browser/invalidation/invalidation_frontend_test_template.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/notification_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace invalidation {
+
+class InvalidationServiceAndroidTestDelegate {
+ public:
+ InvalidationServiceAndroidTestDelegate() { }
+
+ ~InvalidationServiceAndroidTestDelegate() {
+ DestroyInvalidationFrontend();
+ }
+
+ void CreateInvalidationFrontend() {
+ profile_.reset(new TestingProfile());
+ invalidation_service_android_.reset(
+ new InvalidationServiceAndroid(profile_.get()));
+ }
+
+ InvalidationFrontend* GetInvalidationFrontend() {
+ return invalidation_service_android_.get();
+ }
+
+ void DestroyInvalidationFrontend() {
+ invalidation_service_android_->Shutdown();
+ }
+
+ void TriggerOnInvalidatorStateChange(syncer::InvalidatorState state) {
+ invalidation_service_android_->TriggerStateChangeForTest(state);
+ }
+
+ void TriggerOnIncomingInvalidation(
+ const syncer::ObjectIdInvalidationMap& invalidation_map) {
+ syncer::ModelTypeInvalidationMap model_invalidation_map =
+ ObjectIdInvalidationMapToModelTypeInvalidationMap(invalidation_map);
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
+ content::Source<Profile>(profile_.get()),
+ content::Details<const syncer::ModelTypeInvalidationMap>(
+ &model_invalidation_map));
+ }
+
+ scoped_ptr<TestingProfile> profile_;
+ scoped_ptr<InvalidationServiceAndroid> invalidation_service_android_;
+};
+
+INSTANTIATE_TYPED_TEST_CASE_P(
+ AndroidInvalidationServiceTest, InvalidationFrontendTest,
+ InvalidationServiceAndroidTestDelegate);
+
+} // namespace invalidation
diff --git a/chrome/browser/invalidation/invalidation_service_factory.cc b/chrome/browser/invalidation/invalidation_service_factory.cc
new file mode 100644
index 0000000..f79badc
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_service_factory.cc
@@ -0,0 +1,70 @@
+// Copyright (c) 2013 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/invalidation/invalidation_service_factory.h"
+
+#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "chrome/browser/invalidation/invalidation_service_android.h"
+#include "chrome/browser/invalidation/p2p_invalidation_service.h"
+#include "chrome/browser/invalidation/ticl_invalidation_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_dependency_manager.h"
+#include "chrome/browser/signin/signin_manager.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/token_service_factory.h"
+
+class TokenService;
+
+namespace invalidation {
+
+// TODO(rlarocque): Re-enable this once InvalidationFrontend can
+// extend ProfileKeyedService.
+// // static
+// InvalidationFrontend* InvalidationServiceFactory::GetForProfile(
+// Profile* profile) {
+// return static_cast<InvalidationFrontend*>(
+// GetInstance()->GetServiceForProfile(profile, true));
+// }
+
+// static
+InvalidationServiceFactory* InvalidationServiceFactory::GetInstance() {
+ return Singleton<InvalidationServiceFactory>::get();
+}
+
+InvalidationServiceFactory::InvalidationServiceFactory()
+ : ProfileKeyedServiceFactory("InvalidationService",
+ ProfileDependencyManager::GetInstance()) {
+#if !defined(OS_ANDROID)
+ DependsOn(SigninManagerFactory::GetInstance());
+ DependsOn(TokenServiceFactory::GetInstance());
+#endif
+}
+
+InvalidationServiceFactory::~InvalidationServiceFactory() {}
+
+// static
+ProfileKeyedService*
+InvalidationServiceFactory::BuildP2PInvalidationServiceFor(Profile* profile) {
+ return new P2PInvalidationService(profile);
+}
+
+ProfileKeyedService* InvalidationServiceFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ Profile* profile = static_cast<Profile*>(context);
+#if defined(OS_ANDROID)
+ InvalidationServiceAndroid* service = new InvalidationServiceAndroid(profile);
+ return service;
+#else
+ SigninManagerBase* signin_manager =
+ SigninManagerFactory::GetForProfile(profile);
+ TokenService* token_service = TokenServiceFactory::GetForProfile(profile);
+
+ TiclInvalidationService* service = new TiclInvalidationService(
+ signin_manager, token_service, profile);
+ service->Init();
+ return service;
+#endif
+}
+
+} // namespace invalidation
diff --git a/chrome/browser/invalidation/invalidation_service_factory.h b/chrome/browser/invalidation/invalidation_service_factory.h
new file mode 100644
index 0000000..79644f6
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_service_factory.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2013 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_INVALIDATION_INVALIDATION_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_FACTORY_H_
+
+#include "base/basictypes.h"
+#include "base/memory/singleton.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
+
+namespace syncer {
+class Invalidator;
+}
+
+class InvalidationFrontend;
+class Profile;
+
+namespace invalidation {
+
+// A ProfileKeyedServiceFactory to construct InvalidationServices. The
+// implementation of the InvalidationService may be completely different on
+// different platforms; this class should help to hide this complexity. It also
+// exposes some factory methods that are useful for setting up tests that rely
+// on invalidations.
+class InvalidationServiceFactory : public ProfileKeyedServiceFactory {
+ public:
+ // TODO(rlarocque): Re-enable this once InvalidationFrontend can extend
+ // ProfileKeyedService.
+ // static InvalidationFrontend* GetForProfile(Profile* profile);
+
+ static InvalidationServiceFactory* GetInstance();
+
+ static ProfileKeyedService* BuildP2PInvalidationServiceFor(Profile* profile);
+ static ProfileKeyedService* BuildTestServiceInstanceFor(Profile* profile);
+
+ private:
+ friend struct DefaultSingletonTraits<InvalidationServiceFactory>;
+
+ InvalidationServiceFactory();
+ virtual ~InvalidationServiceFactory();
+
+ // ProfileKeyedServiceFactory:
+ virtual ProfileKeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* profile) const OVERRIDE;
+ // TODO(rlarocque): Use this class, not InvalidatorStorage, to register
+ // for user prefs.
+ // virtual void RegisterUserPrefs(PrefRegistrySyncable* registry) OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(InvalidationServiceFactory);
+};
+
+} // namespace invalidation
+
+#endif // CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_FACTORY_H_
diff --git a/chrome/browser/invalidation/invalidation_service_util.cc b/chrome/browser/invalidation/invalidation_service_util.cc
new file mode 100644
index 0000000..a5912fc
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_service_util.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2013 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/invalidation/invalidation_service_util.h"
+
+#include "base/base64.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/rand_util.h"
+#include "chrome/common/chrome_switches.h"
+
+namespace invalidation {
+
+notifier::NotifierOptions ParseNotifierOptions(
+ const CommandLine& command_line) {
+ notifier::NotifierOptions notifier_options;
+
+ if (command_line.HasSwitch(switches::kSyncNotificationHostPort)) {
+ notifier_options.xmpp_host_port =
+ net::HostPortPair::FromString(
+ command_line.GetSwitchValueASCII(
+ switches::kSyncNotificationHostPort));
+ DVLOG(1) << "Using " << notifier_options.xmpp_host_port.ToString()
+ << " for test sync notification server.";
+ }
+
+ notifier_options.try_ssltcp_first =
+ command_line.HasSwitch(switches::kSyncTrySsltcpFirstForXmpp);
+ DVLOG_IF(1, notifier_options.try_ssltcp_first)
+ << "Trying SSL/TCP port before XMPP port for notifications.";
+
+ notifier_options.invalidate_xmpp_login =
+ command_line.HasSwitch(switches::kSyncInvalidateXmppLogin);
+ DVLOG_IF(1, notifier_options.invalidate_xmpp_login)
+ << "Invalidating sync XMPP login.";
+
+ notifier_options.allow_insecure_connection =
+ command_line.HasSwitch(switches::kSyncAllowInsecureXmppConnection);
+ DVLOG_IF(1, notifier_options.allow_insecure_connection)
+ << "Allowing insecure XMPP connections.";
+
+ return notifier_options;
+}
+
+std::string GenerateInvalidatorClientId() {
+ // Generate a GUID with 128 bits worth of base64-encoded randomness.
+ // This format is similar to that of sync's cache_guid.
+ const int kGuidBytes = 128 / 8;
+ std::string guid;
+ base::Base64Encode(base::RandBytesAsString(kGuidBytes), &guid);
+ DCHECK(!guid.empty());
+ return guid;
+}
+
+} // namespace invalidation
diff --git a/chrome/browser/invalidation/invalidation_service_util.h b/chrome/browser/invalidation/invalidation_service_util.h
new file mode 100644
index 0000000..7f44c31
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_service_util.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2013 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_INVALIDATION_INVALIDATION_SERVICE_UTIL_H_
+#define CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_UTIL_H_
+
+#include "jingle/notifier/base/notifier_options.h"
+
+class CommandLine;
+
+namespace invalidation {
+
+// Parses the given command line for notifier options.
+notifier::NotifierOptions ParseNotifierOptions(const CommandLine& command_line);
+
+// Generates a unique client ID for the invalidator.
+std::string GenerateInvalidatorClientId();
+
+} // namespace invalidation
+
+#endif // CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_UTIL_H_
diff --git a/chrome/browser/sync/invalidations/invalidator_storage.cc b/chrome/browser/invalidation/invalidator_storage.cc
index ab3b5a6..780ba12 100644
--- a/chrome/browser/sync/invalidations/invalidator_storage.cc
+++ b/chrome/browser/invalidation/invalidator_storage.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/invalidations/invalidator_storage.h"
+#include "chrome/browser/invalidation/invalidator_storage.h"
#include "base/base64.h"
#include "base/bind.h"
@@ -20,8 +20,6 @@
using syncer::InvalidationStateMap;
-namespace browser_sync {
-
namespace {
const char kSourceKey[] = "source";
@@ -94,6 +92,8 @@ DictionaryValue* ObjectIdAndStateToValue(
} // namespace
+namespace invalidation {
+
// static
void InvalidatorStorage::RegisterUserPrefs(
user_prefs::PrefRegistrySyncable* registry) {
@@ -345,4 +345,4 @@ void InvalidatorStorage::Acknowledge(const invalidation::ObjectId& id,
state_map_list);
}
-} // namespace browser_sync
+} // namespace invalidation
diff --git a/chrome/browser/sync/invalidations/invalidator_storage.h b/chrome/browser/invalidation/invalidator_storage.h
index 9db657b..e8b7ba5 100644
--- a/chrome/browser/sync/invalidations/invalidator_storage.h
+++ b/chrome/browser/invalidation/invalidator_storage.h
@@ -6,8 +6,8 @@
// to use PrefService as persistence for invalidation state. It is not thread
// safe, and lives on the UI thread.
-#ifndef CHROME_BROWSER_SYNC_INVALIDATIONS_INVALIDATOR_STORAGE_H_
-#define CHROME_BROWSER_SYNC_INVALIDATIONS_INVALIDATOR_STORAGE_H_
+#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATOR_STORAGE_H_
+#define CHROME_BROWSER_INVALIDATION_INVALIDATOR_STORAGE_H_
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
@@ -16,6 +16,7 @@
#include "sync/notifier/invalidation_state_tracker.h"
class PrefService;
+class PrefRegistrySyncable;
namespace base {
class DictionaryValue;
@@ -26,13 +27,8 @@ namespace user_prefs {
class PrefRegistrySyncable;
}
-namespace browser_sync {
+namespace invalidation {
-// TODO(tim): Bug 124137. We may want to move this outside of sync/ into a
-// browser/invalidations directory, or re-organize to have a browser
-// subdirectory that contains signin/ sync/ invalidations/ and other cloud
-// services. For now this is still tied to sync while we refactor, so minimize
-// churn and keep it here.
class InvalidatorStorage : public base::SupportsWeakPtr<InvalidatorStorage>,
public syncer::InvalidationStateTracker {
public:
@@ -104,6 +100,6 @@ class InvalidatorStorage : public base::SupportsWeakPtr<InvalidatorStorage>,
DISALLOW_COPY_AND_ASSIGN(InvalidatorStorage);
};
-} // namespace browser_sync
+} // namespace invalidation
-#endif // CHROME_BROWSER_SYNC_INVALIDATIONS_INVALIDATOR_STORAGE_H_
+#endif // CHROME_BROWSER_INVALIDATION_INVALIDATOR_STORAGE_H_
diff --git a/chrome/browser/sync/invalidations/invalidator_storage_unittest.cc b/chrome/browser/invalidation/invalidator_storage_unittest.cc
index e69782a..5e59b43 100644
--- a/chrome/browser/sync/invalidations/invalidator_storage_unittest.cc
+++ b/chrome/browser/invalidation/invalidator_storage_unittest.cc
@@ -1,9 +1,8 @@
// Copyright (c) 2012 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/invalidations/invalidator_storage.h"
+#include "chrome/browser/invalidation/invalidator_storage.h"
#include "base/bind.h"
#include "base/message_loop.h"
@@ -19,8 +18,6 @@
using syncer::InvalidationStateMap;
-namespace browser_sync {
-
namespace {
const char kSourceKey[] = "source";
@@ -39,6 +36,8 @@ void GenerateAckHandlesTestHelper(syncer::AckHandleMap* output,
} // namespace
+namespace invalidation {
+
class InvalidatorStorageTest : public testing::Test {
public:
InvalidatorStorageTest()
@@ -504,4 +503,4 @@ TEST_F(InvalidatorStorageTest, GenerateAckHandlesAndAcknowledge) {
EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
}
-} // namespace browser_sync
+} // namespace invalidation
diff --git a/chrome/browser/invalidation/p2p_invalidation_service.cc b/chrome/browser/invalidation/p2p_invalidation_service.cc
new file mode 100644
index 0000000..855d052
--- /dev/null
+++ b/chrome/browser/invalidation/p2p_invalidation_service.cc
@@ -0,0 +1,79 @@
+// Copyright (c) 2013 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/invalidation/p2p_invalidation_service.h"
+
+#include "base/command_line.h"
+#include "chrome/browser/invalidation/invalidation_service_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_switches.h"
+#include "jingle/notifier/base/notifier_options.h"
+#include "jingle/notifier/listener/push_client.h"
+#include "sync/notifier/p2p_invalidator.h"
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace invalidation {
+
+P2PInvalidationService::P2PInvalidationService(Profile* profile) {
+ notifier::NotifierOptions notifier_options =
+ ParseNotifierOptions(*CommandLine::ForCurrentProcess());
+ notifier_options.request_context_getter = profile->GetRequestContext();
+ invalidator_id_ = GenerateInvalidatorClientId();
+ invalidator_.reset(new syncer::P2PInvalidator(
+ notifier::PushClient::CreateDefault(notifier_options),
+ invalidator_id_,
+ syncer::NOTIFY_ALL));
+}
+
+P2PInvalidationService::~P2PInvalidationService() {
+}
+
+void P2PInvalidationService::UpdateCredentials(const std::string& username,
+ const std::string& password) {
+ invalidator_->UpdateCredentials(username, password);
+}
+
+void P2PInvalidationService::Shutdown() {
+ invalidator_.reset();
+}
+
+void P2PInvalidationService::RegisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) {
+ invalidator_->RegisterHandler(handler);
+}
+
+void P2PInvalidationService::UpdateRegisteredInvalidationIds(
+ syncer::InvalidationHandler* handler,
+ const syncer::ObjectIdSet& ids) {
+ invalidator_->UpdateRegisteredIds(handler, ids);
+}
+
+void P2PInvalidationService::UnregisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) {
+ invalidator_->UnregisterHandler(handler);
+}
+
+void P2PInvalidationService::AcknowledgeInvalidation(
+ const invalidation::ObjectId& id,
+ const syncer::AckHandle& ack_handle) {
+ invalidator_->Acknowledge(id, ack_handle);
+}
+
+void P2PInvalidationService::SendInvalidation(
+ const syncer::ObjectIdInvalidationMap& invalidation_map) {
+ invalidator_->SendInvalidation(invalidation_map);
+}
+
+syncer::InvalidatorState P2PInvalidationService::GetInvalidatorState() const {
+ return invalidator_->GetInvalidatorState();
+}
+
+std::string P2PInvalidationService::GetInvalidatorClientId() const {
+ return invalidator_id_;
+}
+
+} // namespace invalidation
diff --git a/chrome/browser/invalidation/p2p_invalidation_service.h b/chrome/browser/invalidation/p2p_invalidation_service.h
new file mode 100644
index 0000000..6692e9b
--- /dev/null
+++ b/chrome/browser/invalidation/p2p_invalidation_service.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2013 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/threading/non_thread_safe.h"
+#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "chrome/browser/profiles/profile_keyed_service.h"
+#include "sync/notifier/object_id_invalidation_map.h"
+
+#ifndef CHROME_BROWSER_INVALIDATION_P2P_INVALIDATION_SERVICE_H_
+#define CHROME_BROWSER_INVALIDATION_P2P_INVALIDATION_SERVICE_H_
+
+namespace syncer {
+class P2PInvalidator;
+}
+
+class Profile;
+
+namespace invalidation {
+
+// This service is a wrapper around P2PInvalidator. Unlike other
+// InvalidationServices, it can both send and receive invalidations. It is used
+// only in tests, where we're unable to connect to a real invalidations server.
+class P2PInvalidationService
+ : public base::NonThreadSafe,
+ public ProfileKeyedService,
+ public InvalidationFrontend {
+ public:
+ explicit P2PInvalidationService(Profile* profile);
+ virtual ~P2PInvalidationService();
+
+ // Overrides ProfileKeyedService method.
+ virtual void Shutdown() OVERRIDE;
+
+ // InvalidationFrontend implementation.
+ // It is an error to have registered handlers when Shutdown() is called.
+ virtual void RegisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) OVERRIDE;
+ virtual void UpdateRegisteredInvalidationIds(
+ syncer::InvalidationHandler* handler,
+ const syncer::ObjectIdSet& ids) OVERRIDE;
+ virtual void UnregisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) OVERRIDE;
+ virtual void AcknowledgeInvalidation(
+ const invalidation::ObjectId& id,
+ const syncer::AckHandle& ack_handle) OVERRIDE;
+ virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE;
+ virtual std::string GetInvalidatorClientId() const;
+
+ void UpdateCredentials(const std::string& username,
+ const std::string& password);
+
+ void SendInvalidation(
+ const syncer::ObjectIdInvalidationMap& invalidation_map);
+
+ private:
+ scoped_ptr<syncer::P2PInvalidator> invalidator_;
+ std::string invalidator_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(P2PInvalidationService);
+};
+
+} // namespace invalidation
+
+#endif // CHROME_BROWSER_INVALIDATION_P2P_INVALIDATION_SERVICE_H_
diff --git a/chrome/browser/invalidation/ticl_invalidation_service.cc b/chrome/browser/invalidation/ticl_invalidation_service.cc
new file mode 100644
index 0000000..49e81f7
--- /dev/null
+++ b/chrome/browser/invalidation/ticl_invalidation_service.cc
@@ -0,0 +1,244 @@
+// Copyright (c) 2013 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/invalidation/ticl_invalidation_service.h"
+
+#include "base/command_line.h"
+#include "chrome/browser/invalidation/invalidation_service_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/signin_manager.h"
+#include "chrome/browser/signin/token_service.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/notification_service.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "sync/notifier/invalidator.h"
+#include "sync/notifier/invalidator_state.h"
+#include "sync/notifier/non_blocking_invalidator.h"
+
+namespace invalidation {
+
+TiclInvalidationService::TiclInvalidationService(SigninManagerBase* signin,
+ TokenService* token_service,
+ Profile* profile)
+ : profile_(profile),
+ signin_manager_(signin),
+ token_service_(token_service),
+ invalidator_registrar_(new syncer::InvalidatorRegistrar()) { }
+
+TiclInvalidationService::~TiclInvalidationService() {
+ DCHECK(CalledOnValidThread());
+}
+
+void TiclInvalidationService::Init() {
+ DCHECK(CalledOnValidThread());
+
+ invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs()));
+ if (invalidator_storage_->GetInvalidatorClientId().empty()) {
+ // This also clears any existing state. We can't reuse old invalidator
+ // state with the new ID anyway.
+ invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId());
+ }
+
+ if (IsReadyToStart()) {
+ Start();
+ }
+
+ notification_registrar_.Add(this,
+ chrome::NOTIFICATION_TOKEN_AVAILABLE,
+ content::Source<TokenService>(token_service_));
+ notification_registrar_.Add(this,
+ chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
+ content::NotificationService::AllSources());
+}
+
+void TiclInvalidationService::InitForTest(syncer::Invalidator* invalidator) {
+ // Here we perform the equivalent of Init() and Start(), but with some minor
+ // changes to account for the fact that we're injecting the invalidator.
+ invalidator_.reset(invalidator);
+
+ invalidator_->RegisterHandler(this);
+ invalidator_->UpdateRegisteredIds(
+ this,
+ invalidator_registrar_->GetAllRegisteredIds());
+}
+
+void TiclInvalidationService::RegisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(2) << "Registering an invalidation handler";
+ invalidator_registrar_->RegisterHandler(handler);
+}
+
+void TiclInvalidationService::UpdateRegisteredInvalidationIds(
+ syncer::InvalidationHandler* handler,
+ const syncer::ObjectIdSet& ids) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(2) << "Registering ids: " << ids.size();
+ invalidator_registrar_->UpdateRegisteredIds(handler, ids);
+ if (invalidator_) {
+ invalidator_->UpdateRegisteredIds(
+ this,
+ invalidator_registrar_->GetAllRegisteredIds());
+ }
+}
+
+void TiclInvalidationService::UnregisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(2) << "Unregistering";
+ invalidator_registrar_->UnregisterHandler(handler);
+ if (invalidator_) {
+ invalidator_->UpdateRegisteredIds(
+ this,
+ invalidator_registrar_->GetAllRegisteredIds());
+ }
+}
+
+void TiclInvalidationService::AcknowledgeInvalidation(
+ const invalidation::ObjectId& id,
+ const syncer::AckHandle& ack_handle) {
+ DCHECK(CalledOnValidThread());
+ if (invalidator_) {
+ invalidator_->Acknowledge(id, ack_handle);
+ }
+}
+
+syncer::InvalidatorState TiclInvalidationService::GetInvalidatorState() const {
+ DCHECK(CalledOnValidThread());
+ if (invalidator_) {
+ DVLOG(2) << "GetInvalidatorState returning " << GetInvalidatorState();
+ return invalidator_->GetInvalidatorState();
+ } else {
+ DVLOG(2) << "Invalidator currently stopped";
+ return syncer::TRANSIENT_INVALIDATION_ERROR;
+ }
+}
+
+std::string TiclInvalidationService::GetInvalidatorClientId() const {
+ DCHECK(CalledOnValidThread());
+ // invalidator_storage_ will be initialized between calls to Init() and
+ // Stop(). No one should attempt to get the ID of an uninitialized or stopped
+ // service.
+ return invalidator_storage_->GetInvalidatorClientId();
+}
+
+void TiclInvalidationService::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ DCHECK(CalledOnValidThread());
+
+ switch (type) {
+ case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
+ const TokenService::TokenAvailableDetails& token_details =
+ *(content::Details<const TokenService::TokenAvailableDetails>(
+ details).ptr());
+ if (token_details.service() == GaiaConstants::kSyncService) {
+ DCHECK(IsReadyToStart());
+ if (!IsStarted()) {
+ Start();
+ } else {
+ UpdateToken();
+ }
+ }
+ break;
+ }
+ case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: {
+ Stop();
+ break;
+ }
+ default: {
+ NOTREACHED();
+ }
+ }
+}
+
+void TiclInvalidationService::OnInvalidatorStateChange(
+ syncer::InvalidatorState state) {
+ invalidator_registrar_->UpdateInvalidatorState(state);
+}
+
+void TiclInvalidationService::OnIncomingInvalidation(
+ const syncer::ObjectIdInvalidationMap& invalidation_map) {
+ invalidator_registrar_->DispatchInvalidationsToHandlers(invalidation_map);
+}
+
+void TiclInvalidationService::Shutdown() {
+ DCHECK(CalledOnValidThread());
+ Stop();
+ invalidator_registrar_.reset();
+}
+
+bool TiclInvalidationService::IsReadyToStart() {
+ if (signin_manager_->GetAuthenticatedUsername().empty()) {
+ DVLOG(2) << "Not starting TiclInvalidationService: user is not signed in.";
+ return false;
+ }
+
+ if (!token_service_) {
+ DVLOG(2)
+ << "Not starting TiclInvalidationService: TokenService unavailable.";
+ return false;
+ }
+
+ if (!token_service_->HasTokenForService(GaiaConstants::kSyncService)) {
+ DVLOG(2) << "Not starting TiclInvalidationService: Sync token unavailable.";
+ return false;
+ }
+
+ return true;
+}
+
+bool TiclInvalidationService::IsStarted() {
+ return invalidator_.get() != NULL;
+}
+
+void TiclInvalidationService::Start() {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!invalidator_);
+
+ notifier::NotifierOptions options =
+ ParseNotifierOptions(*CommandLine::ForCurrentProcess());
+ options.request_context_getter = profile_->GetRequestContext();
+ invalidator_.reset(new syncer::NonBlockingInvalidator(
+ options,
+ invalidator_storage_->GetInvalidatorClientId(),
+ invalidator_storage_->GetAllInvalidationStates(),
+ invalidator_storage_->GetBootstrapData(),
+ syncer::WeakHandle<syncer::InvalidationStateTracker>(
+ invalidator_storage_->AsWeakPtr()),
+ content::GetUserAgent(GURL())));
+
+ UpdateToken();
+
+ invalidator_->RegisterHandler(this);
+ invalidator_->UpdateRegisteredIds(
+ this,
+ invalidator_registrar_->GetAllRegisteredIds());
+}
+
+void TiclInvalidationService::UpdateToken() {
+ std::string email = signin_manager_->GetAuthenticatedUsername();
+ DCHECK(!email.empty()) << "Expected user to be signed in.";
+ DCHECK(token_service_->HasTokenForService(GaiaConstants::kSyncService));
+
+ std::string sync_token = token_service_->GetTokenForService(
+ GaiaConstants::kSyncService);
+
+ DVLOG(2) << "UpdateCredentials: " << email;
+ invalidator_->UpdateCredentials(email, sync_token);
+}
+
+void TiclInvalidationService::Stop() {
+ if (invalidator_) {
+ invalidator_->UnregisterHandler(this);
+ invalidator_.reset();
+ }
+ if (invalidator_storage_) {
+ invalidator_storage_->Clear();
+ invalidator_storage_.reset();
+ }
+}
+
+} // namespace invalidation
diff --git a/chrome/browser/invalidation/ticl_invalidation_service.h b/chrome/browser/invalidation/ticl_invalidation_service.h
new file mode 100644
index 0000000..ec6a14c
--- /dev/null
+++ b/chrome/browser/invalidation/ticl_invalidation_service.h
@@ -0,0 +1,103 @@
+// Copyright (c) 2013 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_INVALIDATION_TICL_INVALIDATION_SERVICE_H_
+#define CHROME_BROWSER_INVALIDATION_TICL_INVALIDATION_SERVICE_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "chrome/browser/invalidation/invalidator_storage.h"
+#include "chrome/browser/profiles/profile_keyed_service.h"
+#include "chrome/browser/signin/signin_global_error.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "sync/notifier/invalidation_handler.h"
+#include "sync/notifier/invalidator_registrar.h"
+
+class Profile;
+class SigninManagerBase;
+class TokenService;
+
+namespace syncer {
+class Invalidator;
+}
+
+namespace invalidation {
+
+// This InvalidationService wraps the C++ Invalidation Client (TICL) library.
+// It provides invalidations for desktop platforms (Win, Mac, Linux).
+class TiclInvalidationService
+ : public base::NonThreadSafe,
+ public ProfileKeyedService,
+ public InvalidationFrontend,
+ public content::NotificationObserver,
+ public syncer::InvalidationHandler {
+ public:
+ TiclInvalidationService(SigninManagerBase* signin,
+ TokenService* token_service,
+ Profile* profile);
+ virtual ~TiclInvalidationService();
+
+ void Init();
+
+ // InvalidationFrontend implementation.
+ // It is an error to have registered handlers when Shutdown() is called.
+ virtual void RegisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) OVERRIDE;
+ virtual void UpdateRegisteredInvalidationIds(
+ syncer::InvalidationHandler* handler,
+ const syncer::ObjectIdSet& ids) OVERRIDE;
+ virtual void UnregisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) OVERRIDE;
+ virtual void AcknowledgeInvalidation(
+ const invalidation::ObjectId& id,
+ const syncer::AckHandle& ack_handle) OVERRIDE;
+ virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE;
+ virtual std::string GetInvalidatorClientId() const;
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // syncer::InvalidationHandler implementation.
+ virtual void OnInvalidatorStateChange(
+ syncer::InvalidatorState state) OVERRIDE;
+ virtual void OnIncomingInvalidation(
+ const syncer::ObjectIdInvalidationMap& invalidation_map) OVERRIDE;
+
+ // Override of ProfileKeyedService methods.
+ virtual void Shutdown() OVERRIDE;
+
+ protected:
+ // Initializes with an injected invalidator.
+ void InitForTest(syncer::Invalidator* invalidator);
+
+ friend class TiclInvalidationServiceTestDelegate;
+
+ private:
+ bool IsReadyToStart();
+ bool IsStarted();
+
+ void Start();
+ void UpdateToken();
+ void Stop();
+
+ Profile *const profile_;
+ SigninManagerBase *const signin_manager_;
+ TokenService *const token_service_;
+
+ scoped_ptr<syncer::InvalidatorRegistrar> invalidator_registrar_;
+ scoped_ptr<InvalidatorStorage> invalidator_storage_;
+ scoped_ptr<syncer::Invalidator> invalidator_;
+
+ content::NotificationRegistrar notification_registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(TiclInvalidationService);
+};
+
+}
+
+#endif // CHROME_BROWSER_INVALIDATION_TICL_INVALIDATION_SERVICE_H_
diff --git a/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc b/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
new file mode 100644
index 0000000..225dc0a
--- /dev/null
+++ b/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2013 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/invalidation/ticl_invalidation_service.h"
+
+#include "chrome/browser/invalidation/invalidation_frontend_test_template.h"
+#include "chrome/browser/invalidation/invalidation_service_factory.h"
+#include "chrome/test/base/testing_profile.h"
+#include "sync/notifier/fake_invalidation_handler.h"
+#include "sync/notifier/fake_invalidator.h"
+#include "sync/notifier/invalidation_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace invalidation {
+
+class TiclInvalidationServiceTestDelegate {
+ public:
+ TiclInvalidationServiceTestDelegate() { }
+
+ ~TiclInvalidationServiceTestDelegate() {
+ DestroyInvalidationFrontend();
+ }
+
+ void CreateInvalidationFrontend() {
+ fake_invalidator_ = new syncer::FakeInvalidator();
+ profile_.reset(new TestingProfile());
+ invalidation_service_.reset(
+ new TiclInvalidationService(NULL, NULL, profile_.get()));
+ invalidation_service_->InitForTest(fake_invalidator_);
+ }
+
+ InvalidationFrontend* GetInvalidationFrontend() {
+ return invalidation_service_.get();
+ }
+
+ void DestroyInvalidationFrontend() {
+ invalidation_service_->Shutdown();
+ }
+
+ void TriggerOnInvalidatorStateChange(syncer::InvalidatorState state) {
+ fake_invalidator_->EmitOnInvalidatorStateChange(state);
+ }
+
+ void TriggerOnIncomingInvalidation(
+ const syncer::ObjectIdInvalidationMap& invalidation_map) {
+ fake_invalidator_->EmitOnIncomingInvalidation(invalidation_map);
+ }
+
+ syncer::FakeInvalidator* fake_invalidator_; // owned by the service.
+ scoped_ptr<TiclInvalidationService> invalidation_service_;
+ scoped_ptr<TestingProfile> profile_;
+};
+
+INSTANTIATE_TYPED_TEST_CASE_P(
+ TiclInvalidationServiceTest, InvalidationFrontendTest,
+ TiclInvalidationServiceTestDelegate);
+
+} // namespace invalidation
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 5026636..70559d3 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -34,6 +34,7 @@
#include "chrome/browser/gpu/gl_string_manager.h"
#include "chrome/browser/gpu/gpu_mode_manager.h"
#include "chrome/browser/intranet_redirect_detector.h"
+#include "chrome/browser/invalidation/invalidator_storage.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/managed_mode/managed_mode.h"
#include "chrome/browser/managed_mode/managed_user_service.h"
@@ -67,7 +68,6 @@
#include "chrome/browser/search/search.h"
#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
#include "chrome/browser/signin/signin_manager_factory.h"
-#include "chrome/browser/sync/invalidations/invalidator_storage.h"
#include "chrome/browser/sync/sync_prefs.h"
#include "chrome/browser/task_manager/task_manager.h"
#include "chrome/browser/translate/translate_prefs.h"
@@ -295,7 +295,7 @@ void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry) {
HostContentSettingsMap::RegisterUserPrefs(registry);
IncognitoModePrefs::RegisterUserPrefs(registry);
InstantUI::RegisterUserPrefs(registry);
- browser_sync::InvalidatorStorage::RegisterUserPrefs(registry);
+ invalidation::InvalidatorStorage::RegisterUserPrefs(registry);
MediaCaptureDevicesDispatcher::RegisterUserPrefs(registry);
MediaStreamDevicesController::RegisterUserPrefs(registry);
NetPrefObserver::RegisterUserPrefs(registry);
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc
index dd53fbb..8820876 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/chrome/browser/sync/glue/sync_backend_host.cc
@@ -21,6 +21,7 @@
#include "base/tracked_objects.h"
#include "base/utf_string_conversions.h"
#include "build/build_config.h"
+#include "chrome/browser/invalidation/invalidator_storage.h"
#include "chrome/browser/net/network_time_tracker.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/token_service.h"
@@ -32,7 +33,6 @@
#include "chrome/browser/sync/glue/device_info.h"
#include "chrome/browser/sync/glue/sync_backend_registrar.h"
#include "chrome/browser/sync/glue/synced_device_tracker.h"
-#include "chrome/browser/sync/invalidations/invalidator_storage.h"
#include "chrome/browser/sync/sync_prefs.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_notification_types.h"
@@ -350,7 +350,7 @@ SyncBackendHost::SyncBackendHost(
const std::string& name,
Profile* profile,
const base::WeakPtr<SyncPrefs>& sync_prefs,
- const base::WeakPtr<InvalidatorStorage>& invalidator_storage)
+ const base::WeakPtr<invalidation::InvalidatorStorage>& invalidator_storage)
: weak_ptr_factory_(this),
sync_thread_("Chrome_SyncThread"),
frontend_loop_(MessageLoop::current()),
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h
index 2489d6a..03db00b 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/chrome/browser/sync/glue/sync_backend_host.h
@@ -44,11 +44,14 @@ namespace syncer {
class SyncManagerFactory;
}
+namespace invalidation {
+class InvalidatorStorage;
+}
+
namespace browser_sync {
class AndroidInvalidatorBridge;
class ChangeProcessor;
-class InvalidatorStorage;
class SyncBackendRegistrar;
class SyncPrefs;
class SyncedDeviceTracker;
@@ -163,7 +166,8 @@ class SyncBackendHost
Profile* profile,
const base::WeakPtr<SyncPrefs>& sync_prefs,
// TODO(tim): Temporary, remove when bug 124137 finished.
- const base::WeakPtr<InvalidatorStorage>& invalidator_storage);
+ const base::WeakPtr<invalidation::InvalidatorStorage>&
+ invalidator_storage);
// For testing.
// TODO(skrul): Extract an interface so this is not needed.
diff --git a/chrome/browser/sync/glue/sync_backend_host_unittest.cc b/chrome/browser/sync/glue/sync_backend_host_unittest.cc
index f890e41..1379825 100644
--- a/chrome/browser/sync/glue/sync_backend_host_unittest.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_unittest.cc
@@ -11,10 +11,10 @@
#include "base/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
+#include "chrome/browser/invalidation/invalidator_storage.h"
#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/browser/sync/glue/device_info.h"
#include "chrome/browser/sync/glue/synced_device_tracker.h"
-#include "chrome/browser/sync/invalidations/invalidator_storage.h"
#include "chrome/browser/sync/sync_prefs.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/test/base/testing_profile.h"
@@ -146,7 +146,7 @@ class SyncBackendHostTest : public testing::Test {
profile_.reset(new TestingProfile());
profile_->CreateRequestContext();
sync_prefs_.reset(new SyncPrefs(profile_->GetPrefs()));
- invalidator_storage_.reset(new InvalidatorStorage(
+ invalidator_storage_.reset(new invalidation::InvalidatorStorage(
profile_->GetPrefs()));
backend_.reset(new SyncBackendHost(
profile_->GetDebugName(),
@@ -264,7 +264,7 @@ class SyncBackendHostTest : public testing::Test {
syncer::TestUnrecoverableErrorHandler handler_;
scoped_ptr<TestingProfile> profile_;
scoped_ptr<SyncPrefs> sync_prefs_;
- scoped_ptr<InvalidatorStorage> invalidator_storage_;
+ scoped_ptr<invalidation::InvalidatorStorage> invalidator_storage_;
scoped_ptr<SyncBackendHost> backend_;
FakeSyncManager* fake_manager_;
FakeSyncManagerFactory fake_manager_factory_;
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 5d3a453..5e2f07f 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -20,6 +20,8 @@
#include "base/string16.h"
#include "base/time.h"
#include "base/timer.h"
+#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "chrome/browser/invalidation/invalidator_storage.h"
#include "chrome/browser/profiles/profile_keyed_service.h"
#include "chrome/browser/signin/signin_global_error.h"
#include "chrome/browser/sync/backend_unrecoverable_error_handler.h"
@@ -28,8 +30,6 @@
#include "chrome/browser/sync/glue/data_type_manager.h"
#include "chrome/browser/sync/glue/data_type_manager_observer.h"
#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include "chrome/browser/sync/invalidation_frontend.h"
-#include "chrome/browser/sync/invalidations/invalidator_storage.h"
#include "chrome/browser/sync/profile_sync_service_base.h"
#include "chrome/browser/sync/profile_sync_service_observer.h"
#include "chrome/browser/sync/sync_prefs.h"
@@ -162,7 +162,7 @@ class ProfileSyncService : public ProfileSyncServiceBase,
public syncer::UnrecoverableErrorHandler,
public content::NotificationObserver,
public ProfileKeyedService,
- public InvalidationFrontend {
+ public invalidation::InvalidationFrontend {
public:
typedef browser_sync::SyncBackendHost::Status Status;
@@ -814,7 +814,7 @@ class ProfileSyncService : public ProfileSyncServiceBase,
browser_sync::SyncPrefs sync_prefs_;
// TODO(tim): Move this to InvalidationService, once it exists. Bug 124137.
- browser_sync::InvalidatorStorage invalidator_storage_;
+ invalidation::InvalidatorStorage invalidator_storage_;
// TODO(ncarter): Put this in a profile, once there is UI for it.
// This specifies where to find the sync server.
diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc
index 44049d8..e335800 100644
--- a/chrome/browser/sync/test_profile_sync_service.cc
+++ b/chrome/browser/sync/test_profile_sync_service.cc
@@ -36,7 +36,7 @@ namespace browser_sync {
SyncBackendHostForProfileSyncTest::SyncBackendHostForProfileSyncTest(
Profile* profile,
const base::WeakPtr<SyncPrefs>& sync_prefs,
- const base::WeakPtr<InvalidatorStorage>& invalidator_storage,
+ const base::WeakPtr<invalidation::InvalidatorStorage>& invalidator_storage,
syncer::TestIdFactory& id_factory,
base::Closure& callback,
bool set_initial_sync_ended_on_init,
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h
index 241307b..5d4000f 100644
--- a/chrome/browser/sync/test_profile_sync_service.h
+++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -10,8 +10,8 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
+#include "chrome/browser/invalidation/invalidator_storage.h"
#include "chrome/browser/sync/glue/data_type_manager_impl.h"
-#include "chrome/browser/sync/invalidations/invalidator_storage.h"
#include "chrome/browser/sync/profile_sync_components_factory_mock.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/sync_prefs.h"
@@ -38,7 +38,8 @@ class SyncBackendHostForProfileSyncTest : public SyncBackendHost {
SyncBackendHostForProfileSyncTest(
Profile* profile,
const base::WeakPtr<SyncPrefs>& sync_prefs,
- const base::WeakPtr<InvalidatorStorage>& invalidator_storage,
+ const base::WeakPtr<invalidation::InvalidatorStorage>&
+ invalidator_storage,
syncer::TestIdFactory& id_factory,
base::Closure& callback,
bool set_initial_sync_ended_on_init,
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index b804637..9b790af 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -873,6 +873,19 @@
'browser/internal_auth.h',
'browser/intranet_redirect_detector.cc',
'browser/intranet_redirect_detector.h',
+ 'browser/invalidation/invalidation_frontend.h',
+ 'browser/invalidation/invalidation_service_android.cc',
+ 'browser/invalidation/invalidation_service_android.h',
+ 'browser/invalidation/invalidation_service_factory.cc',
+ 'browser/invalidation/invalidation_service_factory.h',
+ 'browser/invalidation/invalidation_service_util.cc',
+ 'browser/invalidation/invalidation_service_util.h',
+ 'browser/invalidation/invalidator_storage.cc',
+ 'browser/invalidation/invalidator_storage.h',
+ 'browser/invalidation/p2p_invalidation_service.cc',
+ 'browser/invalidation/p2p_invalidation_service.h',
+ 'browser/invalidation/ticl_invalidation_service.cc',
+ 'browser/invalidation/ticl_invalidation_service.h',
'browser/io_thread.cc',
'browser/io_thread.h',
'browser/jankometer.cc',
@@ -2038,9 +2051,6 @@
'browser/sync/glue/ui_data_type_controller.h',
'browser/sync/glue/ui_model_worker.cc',
'browser/sync/glue/ui_model_worker.h',
- 'browser/sync/invalidations/invalidator_storage.cc',
- 'browser/sync/invalidations/invalidator_storage.h',
- 'browser/sync/invalidation_frontend.h',
'browser/sync/profile_sync_components_factory.h',
'browser/sync/profile_sync_components_factory_impl.cc',
'browser/sync/profile_sync_components_factory_impl.h',
@@ -2799,6 +2809,10 @@
'browser/chrome_browser_main_posix.h',
'browser/chrome_process_singleton.cc',
'browser/process_singleton.cc',
+
+ # Android uses a different invalidation service
+ 'browser/invalidation/ticl_invalidation_service.cc',
+ 'browser/invalidation/ticl_invalidation_service.h',
],
'sources/': [
['exclude', '^browser/captive_portal/'],
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 36b0085..1d9f216 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -888,6 +888,11 @@
'browser/importer/safari_importer_unittest.mm',
'browser/importer/toolbar_importer_unittest.cc',
'browser/internal_auth_unittest.cc',
+ 'browser/invalidation/invalidation_frontend_test_template.cc',
+ 'browser/invalidation/invalidation_frontend_test_template.h',
+ 'browser/invalidation/invalidation_service_android_unittest.cc',
+ 'browser/invalidation/invalidator_storage_unittest.cc',
+ 'browser/invalidation/ticl_invalidation_service_unittest.cc',
'browser/language_usage_metrics_unittest.cc',
'browser/mac/keystone_glue_unittest.mm',
'browser/managed_mode/managed_mode_unittest.cc',
@@ -1182,7 +1187,6 @@
'browser/sync/glue/typed_url_model_associator_unittest.cc',
'browser/sync/glue/ui_data_type_controller_unittest.cc',
'browser/sync/glue/ui_model_worker_unittest.cc',
- 'browser/sync/invalidations/invalidator_storage_unittest.cc',
'browser/sync/profile_sync_components_factory_impl_unittest.cc',
'browser/sync/profile_sync_components_factory_mock.cc',
'browser/sync/profile_sync_components_factory_mock.h',
@@ -2300,6 +2304,9 @@
# The autofill popup is implemented in mostly native code on
# Android.
'browser/ui/autofill/autofill_popup_controller_unittest.cc',
+
+ # Android uses a different invaliator.
+ 'browser/invalidation/ticl_invalidation_service_unittest.cc',
],
'sources/': [
['exclude', '^browser/captive_portal/'],