summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzea@chromium.org <zea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-26 00:44:53 +0000
committerzea@chromium.org <zea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-26 00:44:53 +0000
commit6990e4e02b98a3d5b9469483173c54609317c763 (patch)
tree3fafe3fda2a29ec928ee0827a2ddc48af6d897f7
parentc164db57dbcf8374b4adc1ff6c39542e9fc5686b (diff)
downloadchromium_src-6990e4e02b98a3d5b9469483173c54609317c763.zip
chromium_src-6990e4e02b98a3d5b9469483173c54609317c763.tar.gz
chromium_src-6990e4e02b98a3d5b9469483173c54609317c763.tar.bz2
[Sync] Add sessions API and sync plumbing for refreshing sessions data.
SessionModelAssociator now has an AttemptSessionsDataRefresh method for triggering sync cycles to update the sessions data. Currently it has no effect (the actual hookup to sync notifications will be added in a subsequent patch). In addition, we automatically trigger the refresh when chrome://newtab/#opentabs is accessed. To support local datatype refreshes, we introduce the notion of local notifications. Nudges originating from local notifications will result in GetUpdates with source DATATYPE_REFRESH. Lastly, we now no longer consider chrome:// and file:// url's for syncing. BUG=103469 TEST=unit_tests Review URL: http://codereview.chromium.org/8619002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119157 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/sync/engine/nudge_source.cc3
-rw-r--r--chrome/browser/sync/engine/nudge_source.h4
-rw-r--r--chrome/browser/sync/engine/sync_scheduler.cc4
-rw-r--r--chrome/browser/sync/glue/session_change_processor.cc24
-rw-r--r--chrome/browser/sync/glue/session_change_processor.h5
-rw-r--r--chrome/browser/sync/glue/session_model_associator.cc18
-rw-r--r--chrome/browser/sync/glue/session_model_associator.h12
-rw-r--r--chrome/browser/sync/glue/session_model_associator_unittest.cc72
-rw-r--r--chrome/browser/sync/internal_api/sync_manager.cc26
-rw-r--r--chrome/browser/sync/internal_api/syncapi_unittest.cc3
-rw-r--r--chrome/browser/sync/notifier/invalidation_notifier.cc5
-rw-r--r--chrome/browser/sync/notifier/invalidation_notifier_unittest.cc6
-rw-r--r--chrome/browser/sync/notifier/mock_sync_notifier_observer.h7
-rw-r--r--chrome/browser/sync/notifier/non_blocking_invalidation_notifier.cc16
-rw-r--r--chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h5
-rw-r--r--chrome/browser/sync/notifier/non_blocking_invalidation_notifier_unittest.cc9
-rw-r--r--chrome/browser/sync/notifier/p2p_notifier.cc4
-rw-r--r--chrome/browser/sync/notifier/p2p_notifier_unittest.cc20
-rw-r--r--chrome/browser/sync/notifier/sync_notifier_observer.h12
-rw-r--r--chrome/browser/sync/profile_sync_service_session_unittest.cc52
-rw-r--r--chrome/browser/sync/protocol/proto_enum_conversions.cc5
-rw-r--r--chrome/browser/sync/protocol/sync.proto3
-rw-r--r--chrome/browser/sync/tools/sync_listen_notifications.cc9
-rw-r--r--chrome/common/chrome_notification_types.h4
24 files changed, 271 insertions, 57 deletions
diff --git a/chrome/browser/sync/engine/nudge_source.cc b/chrome/browser/sync/engine/nudge_source.cc
index c8942f7..b8e4bc8 100644
--- a/chrome/browser/sync/engine/nudge_source.cc
+++ b/chrome/browser/sync/engine/nudge_source.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -16,6 +16,7 @@ const char* GetNudgeSourceString(NudgeSource nudge_source) {
ENUM_CASE(NUDGE_SOURCE_NOTIFICATION);
ENUM_CASE(NUDGE_SOURCE_LOCAL);
ENUM_CASE(NUDGE_SOURCE_CONTINUATION);
+ ENUM_CASE(NUDGE_SOURCE_LOCAL_REFRESH);
};
NOTREACHED();
return "";
diff --git a/chrome/browser/sync/engine/nudge_source.h b/chrome/browser/sync/engine/nudge_source.h
index 4b92ee2..9968b8a 100644
--- a/chrome/browser/sync/engine/nudge_source.h
+++ b/chrome/browser/sync/engine/nudge_source.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -16,6 +16,8 @@ enum NudgeSource {
NUDGE_SOURCE_LOCAL,
// A previous sync cycle did not fully complete (e.g. HTTP error).
NUDGE_SOURCE_CONTINUATION,
+ // A local event is triggering an optimistic datatype refresh.
+ NUDGE_SOURCE_LOCAL_REFRESH,
};
const char* GetNudgeSourceString(NudgeSource nudge_source);
diff --git a/chrome/browser/sync/engine/sync_scheduler.cc b/chrome/browser/sync/engine/sync_scheduler.cc
index 09e6668..13c822d 100644
--- a/chrome/browser/sync/engine/sync_scheduler.cc
+++ b/chrome/browser/sync/engine/sync_scheduler.cc
@@ -133,6 +133,8 @@ GetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource(
return GetUpdatesCallerInfo::LOCAL;
case NUDGE_SOURCE_CONTINUATION:
return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION;
+ case NUDGE_SOURCE_LOCAL_REFRESH:
+ return GetUpdatesCallerInfo::DATATYPE_REFRESH;
case NUDGE_SOURCE_UNKNOWN:
return GetUpdatesCallerInfo::UNKNOWN;
default:
@@ -584,6 +586,8 @@ void SyncScheduler::ScheduleNudgeImpl(
pending_nudge_.reset();
}
+ // TODO(zea): Consider adding separate throttling/backoff for datatype
+ // refresh requests.
ScheduleSyncSessionJob(job);
}
diff --git a/chrome/browser/sync/glue/session_change_processor.cc b/chrome/browser/sync/glue/session_change_processor.cc
index f08b4d3..34f850b 100644
--- a/chrome/browser/sync/glue/session_change_processor.cc
+++ b/chrome/browser/sync/glue/session_change_processor.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
@@ -33,6 +34,10 @@ namespace browser_sync {
namespace {
+// The URL at which the set of synced tabs is displayed. We treat it differently
+// from all other URL's as accessing it triggers a sync refresh of Sessions.
+static const char kNTPOpenTabSyncURL[] = "chrome://newtab/#opentabs";
+
// Extract the source SyncedTabDelegate from a NotificationSource originating
// from a NavigationController, if it exists. Returns |NULL| otherwise.
SyncedTabDelegate* ExtractSyncedTabDelegate(
@@ -186,6 +191,25 @@ void SessionChangeProcessor::Observe(
break;
}
+ // Check if this tab should trigger a session sync refresh. By virtue of
+ // it being a modified tab, we know the tab is active (so we won't do
+ // refreshes just because the refresh page is open in a background tab).
+ if (!modified_tabs.empty()) {
+ SyncedTabDelegate* tab = modified_tabs.front();
+ const content::NavigationEntry* entry = tab->GetActiveEntry();
+ if (!tab->IsBeingDestroyed() &&
+ entry &&
+ entry->GetVirtualURL().is_valid() &&
+ entry->GetVirtualURL().spec() == kNTPOpenTabSyncURL) {
+ DVLOG(1) << "Triggering sync refresh for sessions datatype.";
+ const syncable::ModelType type = syncable::SESSIONS;
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_SYNC_REFRESH,
+ content::Source<Profile>(profile_),
+ content::Details<const syncable::ModelType>(&type));
+ }
+ }
+
// Associate tabs first so the synced session tracker is aware of them.
// Note that if we fail to associate, it means something has gone wrong,
// such as our local session being deleted, so we disassociate and associate
diff --git a/chrome/browser/sync/glue/session_change_processor.h b/chrome/browser/sync/glue/session_change_processor.h
index d6cc011..392e839 100644
--- a/chrome/browser/sync/glue/session_change_processor.h
+++ b/chrome/browser/sync/glue/session_change_processor.h
@@ -31,6 +31,7 @@ class SessionChangeProcessor : public ChangeProcessor,
SessionChangeProcessor(
UnrecoverableErrorHandler* error_handler,
SessionModelAssociator* session_model_associator);
+ // For testing only.
SessionChangeProcessor(
UnrecoverableErrorHandler* error_handler,
SessionModelAssociator* session_model_associator,
@@ -56,12 +57,14 @@ class SessionChangeProcessor : public ChangeProcessor,
private:
friend class ScopedStopObserving<SessionChangeProcessor>;
+
void StartObserving();
void StopObserving();
+
SessionModelAssociator* session_model_associator_;
content::NotificationRegistrar notification_registrar_;
- // Owner of the SessionService. Non-NULL iff |running()| is true.
+ // Profile being synced. Non-null if |running()| is true.
Profile* profile_;
// To bypass some checks/codepaths not applicable in tests.
diff --git a/chrome/browser/sync/glue/session_model_associator.cc b/chrome/browser/sync/glue/session_model_associator.cc
index 1ce4f84..f8aa61d 100644
--- a/chrome/browser/sync/glue/session_model_associator.cc
+++ b/chrome/browser/sync/glue/session_model_associator.cc
@@ -65,9 +65,11 @@ SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service)
stale_session_threshold_days_(kDefaultStaleSessionThresholdDays),
setup_for_test_(false),
waiting_for_change_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(test_weak_factory_(this)) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(test_weak_factory_(this)),
+ profile_(sync_service->profile()) {
DCHECK(CalledOnValidThread());
DCHECK(sync_service_);
+ DCHECK(profile_);
}
SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service,
@@ -78,8 +80,11 @@ SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service,
stale_session_threshold_days_(kDefaultStaleSessionThresholdDays),
setup_for_test_(setup_for_test),
waiting_for_change_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(test_weak_factory_(this)) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(test_weak_factory_(this)),
+ profile_(sync_service->profile()) {
DCHECK(CalledOnValidThread());
+ DCHECK(sync_service_);
+ DCHECK(profile_);
}
SessionModelAssociator::~SessionModelAssociator() {
@@ -953,6 +958,15 @@ void SessionModelAssociator::TabNodePool::FreeTabNode(int64 sync_id) {
tab_syncid_pool_[static_cast<size_t>(++tab_pool_fp_)] = sync_id;
}
+void SessionModelAssociator::AttemptSessionsDataRefresh() const {
+ DVLOG(1) << "Triggering sync refresh for sessions datatype.";
+ const syncable::ModelType type = syncable::SESSIONS;
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_SYNC_REFRESH,
+ content::Source<Profile>(profile_),
+ content::Details<const syncable::ModelType>(&type));
+}
+
bool SessionModelAssociator::GetLocalSession(
const SyncedSession* * local_session) {
DCHECK(CalledOnValidThread());
diff --git a/chrome/browser/sync/glue/session_model_associator.h b/chrome/browser/sync/glue/session_model_associator.h
index 76b2345..9237626 100644
--- a/chrome/browser/sync/glue/session_model_associator.h
+++ b/chrome/browser/sync/glue/session_model_associator.h
@@ -153,6 +153,12 @@ class SessionModelAssociator
// found for that session.
bool DisassociateForeignSession(const std::string& foreign_session_tag);
+ // Attempts to asynchronously refresh the sessions sync data. If new data is
+ // received, the FOREIGN_SESSIONS_UPDATED notification is sent. No
+ // notification will be sent otherwise. This method is not guaranteed to
+ // trigger a sync cycle.
+ void AttemptSessionsDataRefresh() const;
+
// Sets |*local_session| to point to the associator's representation of the
// local machine. Used primarily for testing.
bool GetLocalSession(const SyncedSession* * local_session);
@@ -211,8 +217,7 @@ class SessionModelAssociator
WriteForeignSessionToNode);
FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, TabNodePoolEmpty);
FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, TabNodePoolNonEmpty);
- FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
- ValidTabs);
+ FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, ValidTabs);
FRIEND_TEST_ALL_PREFIXES(SessionModelAssociatorTest, PopulateSessionHeader);
FRIEND_TEST_ALL_PREFIXES(SessionModelAssociatorTest, PopulateSessionWindow);
FRIEND_TEST_ALL_PREFIXES(SessionModelAssociatorTest, PopulateSessionTab);
@@ -449,6 +454,9 @@ class SessionModelAssociator
bool waiting_for_change_;
base::WeakPtrFactory<SessionModelAssociator> test_weak_factory_;
+ // Profile being synced.
+ const Profile* const profile_;
+
DISALLOW_COPY_AND_ASSIGN(SessionModelAssociator);
};
diff --git a/chrome/browser/sync/glue/session_model_associator_unittest.cc b/chrome/browser/sync/glue/session_model_associator_unittest.cc
index e22e3a5..fa951bd 100644
--- a/chrome/browser/sync/glue/session_model_associator_unittest.cc
+++ b/chrome/browser/sync/glue/session_model_associator_unittest.cc
@@ -11,7 +11,13 @@
#include "chrome/browser/sync/glue/session_model_associator.h"
#include "chrome/browser/sync/glue/synced_tab_delegate.h"
#include "chrome/browser/sync/protocol/session_specifics.pb.h"
+#include "chrome/browser/sync/profile_sync_service_mock.h"
+#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/url_constants.h"
+#include "chrome/test/base/profile_mock.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_details.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/common/page_transition_types.h"
#include "content/test/test_browser_thread.h"
@@ -24,7 +30,25 @@ using testing::Return;
namespace browser_sync {
-typedef testing::Test SessionModelAssociatorTest;
+class SessionModelAssociatorTest : public testing::Test {
+ public:
+ SessionModelAssociatorTest()
+ : ui_thread_(BrowserThread::UI, &message_loop_),
+ sync_service_(&profile_) {}
+ virtual void SetUp() OVERRIDE {
+ model_associator_.reset(new SessionModelAssociator(&sync_service_, true));
+ }
+ virtual void TearDown() OVERRIDE {
+ model_associator_.reset();
+ }
+
+ protected:
+ MessageLoopForUI message_loop_;
+ content::TestBrowserThread ui_thread_;
+ NiceMock<ProfileMock> profile_;
+ NiceMock<ProfileSyncServiceMock> sync_service_;
+ scoped_ptr<SessionModelAssociator> model_associator_;
+};
TEST_F(SessionModelAssociatorTest, SessionWindowHasNoTabsToSync) {
SessionWindow win;
@@ -208,13 +232,43 @@ class SyncedTabDelegateMock : public SyncedTabDelegate {
MOCK_CONST_METHOD0(GetActiveEntry, content::NavigationEntry*());
};
+class SyncRefreshListener : public content::NotificationObserver {
+ public:
+ SyncRefreshListener() : notified_of_refresh_(false) {
+ registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH,
+ content::NotificationService::AllSources());
+ }
+
+ void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_SYNC_REFRESH) {
+ notified_of_refresh_ = true;
+ }
+ }
+
+ bool notified_of_refresh() const { return notified_of_refresh_; }
+
+ private:
+ bool notified_of_refresh_;
+ content::NotificationRegistrar registrar_;
+};
+
} // namespace.
-TEST_F(SessionModelAssociatorTest, ValidTabs) {
- MessageLoopForUI message_loop;
- content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
- SessionModelAssociator model_associator(NULL, true);
+// Test that AttemptSessionsDataRefresh() triggers the NOTIFICATION_SYNC_REFRESH
+// notification.
+TEST_F(SessionModelAssociatorTest, TriggerSessionRefresh) {
+ SyncRefreshListener refresh_listener;
+ EXPECT_FALSE(refresh_listener.notified_of_refresh());
+ model_associator_->AttemptSessionsDataRefresh();
+ EXPECT_TRUE(refresh_listener.notified_of_refresh());
+}
+
+// Test that we exclude tabs with only chrome:// and file:// schemed navigations
+// from ShouldSyncTab(..).
+TEST_F(SessionModelAssociatorTest, ValidTabs) {
NiceMock<SyncedTabDelegateMock> tab_mock;
// A null entry shouldn't crash.
@@ -223,7 +277,7 @@ TEST_F(SessionModelAssociatorTest, ValidTabs) {
Return((content::NavigationEntry *)NULL));
EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(1));
EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1));
- EXPECT_FALSE(model_associator.ShouldSyncTab(tab_mock));
+ EXPECT_FALSE(model_associator_->ShouldSyncTab(tab_mock));
// A chrome:// entry isn't valid.
scoped_ptr<content::NavigationEntry> entry(
@@ -234,7 +288,7 @@ TEST_F(SessionModelAssociatorTest, ValidTabs) {
EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly(Return(entry.get()));
EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(1));
EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1));
- EXPECT_FALSE(model_associator.ShouldSyncTab(tab_mock));
+ EXPECT_FALSE(model_associator_->ShouldSyncTab(tab_mock));
// A file:// entry isn't valid, even in addition to another entry.
scoped_ptr<content::NavigationEntry> entry2(
@@ -247,7 +301,7 @@ TEST_F(SessionModelAssociatorTest, ValidTabs) {
Return(entry2.get()));
EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(2));
EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1));
- EXPECT_FALSE(model_associator.ShouldSyncTab(tab_mock));
+ EXPECT_FALSE(model_associator_->ShouldSyncTab(tab_mock));
// Add a valid scheme entry to tab, making the tab valid.
scoped_ptr<content::NavigationEntry> entry3(
@@ -263,7 +317,7 @@ TEST_F(SessionModelAssociatorTest, ValidTabs) {
Return(entry3.get()));
EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(3));
EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1));
- EXPECT_TRUE(model_associator.ShouldSyncTab(tab_mock));
+ EXPECT_TRUE(model_associator_->ShouldSyncTab(tab_mock));
}
} // namespace browser_sync
diff --git a/chrome/browser/sync/internal_api/sync_manager.cc b/chrome/browser/sync/internal_api/sync_manager.cc
index c7c9485..09739d2 100644
--- a/chrome/browser/sync/internal_api/sync_manager.cc
+++ b/chrome/browser/sync/internal_api/sync_manager.cc
@@ -95,6 +95,8 @@ typedef GoogleServiceAuthError AuthError;
namespace {
+// Delays for syncer nudges.
+static const int kSyncRefreshDelayMsec = 500;
static const int kSyncSchedulerDelayMsec = 250;
#if defined(OS_CHROMEOS)
@@ -277,7 +279,8 @@ class SyncManager::SyncInternal
bool notifications_enabled) OVERRIDE;
virtual void OnIncomingNotification(
- const syncable::ModelTypePayloadMap& type_payloads) OVERRIDE;
+ const syncable::ModelTypePayloadMap& type_payloads,
+ sync_notifier::IncomingNotificationSource source) OVERRIDE;
virtual void StoreState(const std::string& cookie) OVERRIDE;
@@ -1716,10 +1719,11 @@ SyncManager::Status SyncManager::SyncInternal::GetStatus() {
void SyncManager::SyncInternal::RequestNudge(
const tracked_objects::Location& location) {
- if (scheduler())
+ if (scheduler()) {
scheduler()->ScheduleNudge(
TimeDelta::FromMilliseconds(0), browser_sync::NUDGE_SOURCE_LOCAL,
ModelTypeSet(), location);
+ }
}
TimeDelta SyncManager::SyncInternal::GetNudgeDelayTimeDelta(
@@ -2070,8 +2074,17 @@ void SyncManager::SyncInternal::UpdateNotificationInfo(
}
void SyncManager::SyncInternal::OnIncomingNotification(
- const syncable::ModelTypePayloadMap& type_payloads) {
- if (!type_payloads.empty()) {
+ const syncable::ModelTypePayloadMap& type_payloads,
+ sync_notifier::IncomingNotificationSource source) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (source == sync_notifier::LOCAL_NOTIFICATION) {
+ if (scheduler()) {
+ scheduler()->ScheduleNudgeWithPayloads(
+ TimeDelta::FromMilliseconds(kSyncRefreshDelayMsec),
+ browser_sync::NUDGE_SOURCE_LOCAL_REFRESH,
+ type_payloads, FROM_HERE);
+ }
+ } else if (!type_payloads.empty()) {
if (scheduler()) {
scheduler()->ScheduleNudgeWithPayloads(
TimeDelta::FromMilliseconds(kSyncSchedulerDelayMsec),
@@ -2095,6 +2108,8 @@ void SyncManager::SyncInternal::OnIncomingNotification(
syncable::ModelTypeToString(it->first);
changed_types->Append(Value::CreateStringValue(model_type_str));
}
+ details.SetString("source", (source == sync_notifier::LOCAL_NOTIFICATION) ?
+ "LOCAL_NOTIFICATION" : "REMOTE_NOTIFICATION");
js_event_handler_.Call(FROM_HERE,
&JsEventHandler::HandleJsEvent,
"onIncomingNotification",
@@ -2214,7 +2229,8 @@ void SyncManager::TriggerOnIncomingNotificationForTest(
syncable::ModelTypePayloadMapFromEnumSet(model_types,
std::string());
- data_->OnIncomingNotification(model_types_with_payloads);
+ data_->OnIncomingNotification(model_types_with_payloads,
+ sync_notifier::REMOTE_NOTIFICATION);
}
// Helper function that converts a PassphraseRequiredReason value to a string.
diff --git a/chrome/browser/sync/internal_api/syncapi_unittest.cc b/chrome/browser/sync/internal_api/syncapi_unittest.cc
index 8d50baf..0fb6e4a 100644
--- a/chrome/browser/sync/internal_api/syncapi_unittest.cc
+++ b/chrome/browser/sync/internal_api/syncapi_unittest.cc
@@ -1253,6 +1253,7 @@ TEST_F(SyncManagerTest, OnIncomingNotification) {
DictionaryValue expected_details;
{
ListValue* model_type_list = new ListValue();
+ expected_details.SetString("source", "REMOTE_NOTIFICATION");
expected_details.Set("changedTypes", model_type_list);
for (syncable::ModelTypeSet::Iterator it = model_types.First();
it.Good(); it.Inc()) {
@@ -1264,7 +1265,7 @@ TEST_F(SyncManagerTest, OnIncomingNotification) {
EXPECT_CALL(event_handler,
HandleJsEvent("onIncomingNotification",
- HasDetailsAsDictionary(expected_details)));
+ HasDetailsAsDictionary(expected_details)));
sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types);
sync_manager_.TriggerOnIncomingNotificationForTest(model_types);
diff --git a/chrome/browser/sync/notifier/invalidation_notifier.cc b/chrome/browser/sync/notifier/invalidation_notifier.cc
index 9a69048..be7acb9 100644
--- a/chrome/browser/sync/notifier/invalidation_notifier.cc
+++ b/chrome/browser/sync/notifier/invalidation_notifier.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -133,7 +133,8 @@ void InvalidationNotifier::OnInvalidate(
const syncable::ModelTypePayloadMap& type_payloads) {
DCHECK(non_thread_safe_.CalledOnValidThread());
FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
- OnIncomingNotification(type_payloads));
+ OnIncomingNotification(type_payloads,
+ sync_notifier::REMOTE_NOTIFICATION));
}
void InvalidationNotifier::OnSessionStatusChanged(bool has_session) {
diff --git a/chrome/browser/sync/notifier/invalidation_notifier_unittest.cc b/chrome/browser/sync/notifier/invalidation_notifier_unittest.cc
index 4ec2d65..93b123a 100644
--- a/chrome/browser/sync/notifier/invalidation_notifier_unittest.cc
+++ b/chrome/browser/sync/notifier/invalidation_notifier_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -72,7 +72,9 @@ TEST_F(InvalidationNotifierTest, Basic) {
EXPECT_CALL(mock_observer_, OnNotificationStateChange(true));
EXPECT_CALL(mock_observer_, StoreState("new_fake_state"));
- EXPECT_CALL(mock_observer_, OnIncomingNotification(type_payloads));
+ EXPECT_CALL(mock_observer_,
+ OnIncomingNotification(type_payloads,
+ REMOTE_NOTIFICATION));
EXPECT_CALL(mock_observer_, OnNotificationStateChange(false));
invalidation_notifier_->SetState("fake_state");
diff --git a/chrome/browser/sync/notifier/mock_sync_notifier_observer.h b/chrome/browser/sync/notifier/mock_sync_notifier_observer.h
index a9e141f..8c53329 100644
--- a/chrome/browser/sync/notifier/mock_sync_notifier_observer.h
+++ b/chrome/browser/sync/notifier/mock_sync_notifier_observer.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -18,8 +18,9 @@ class MockSyncNotifierObserver : public SyncNotifierObserver {
MockSyncNotifierObserver();
virtual ~MockSyncNotifierObserver();
- MOCK_METHOD1(OnIncomingNotification,
- void(const syncable::ModelTypePayloadMap&));
+ MOCK_METHOD2(OnIncomingNotification,
+ void(const syncable::ModelTypePayloadMap&,
+ IncomingNotificationSource));
MOCK_METHOD1(OnNotificationStateChange, void(bool));
MOCK_METHOD1(StoreState, void(const std::string&));
};
diff --git a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.cc b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.cc
index 6aff10c..0f441a4 100644
--- a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.cc
+++ b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -37,7 +37,8 @@ class NonBlockingInvalidationNotifier::Core
// SyncNotifierObserver implementation (all called on I/O thread).
virtual void OnIncomingNotification(
- const syncable::ModelTypePayloadMap& type_payloads);
+ const syncable::ModelTypePayloadMap& type_payloads,
+ IncomingNotificationSource source);
virtual void OnNotificationStateChange(bool notifications_enabled);
virtual void StoreState(const std::string& state);
@@ -119,11 +120,13 @@ void NonBlockingInvalidationNotifier::Core::UpdateEnabledTypes(
}
void NonBlockingInvalidationNotifier::Core::OnIncomingNotification(
- const syncable::ModelTypePayloadMap& type_payloads) {
+ const syncable::ModelTypePayloadMap& type_payloads,
+ IncomingNotificationSource source) {
DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
delegate_observer_.Call(FROM_HERE,
&SyncNotifierObserver::OnIncomingNotification,
- type_payloads);
+ type_payloads,
+ source);
}
void NonBlockingInvalidationNotifier::Core::OnNotificationStateChange(
@@ -241,10 +244,11 @@ void NonBlockingInvalidationNotifier::SendNotification(
}
void NonBlockingInvalidationNotifier::OnIncomingNotification(
- const syncable::ModelTypePayloadMap& type_payloads) {
+ const syncable::ModelTypePayloadMap& type_payloads,
+ IncomingNotificationSource source) {
DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
- OnIncomingNotification(type_payloads));
+ OnIncomingNotification(type_payloads, source));
}
void NonBlockingInvalidationNotifier::OnNotificationStateChange(
diff --git a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h
index 9299b3b..7fa736d 100644
--- a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h
+++ b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
//
@@ -56,7 +56,8 @@ class NonBlockingInvalidationNotifier
// SyncNotifierObserver implementation.
virtual void OnIncomingNotification(
- const syncable::ModelTypePayloadMap& type_payloads) OVERRIDE;
+ const syncable::ModelTypePayloadMap& type_payloads,
+ IncomingNotificationSource source) OVERRIDE;
virtual void OnNotificationStateChange(bool notifications_enabled) OVERRIDE;
virtual void StoreState(const std::string& state) OVERRIDE;
diff --git a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier_unittest.cc b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier_unittest.cc
index 3d81713..c293bdb 100644
--- a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier_unittest.cc
+++ b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -76,7 +76,9 @@ TEST_F(NonBlockingInvalidationNotifierTest, Basic) {
EXPECT_CALL(mock_observer_, OnNotificationStateChange(true));
EXPECT_CALL(mock_observer_, StoreState("new_fake_state"));
- EXPECT_CALL(mock_observer_, OnIncomingNotification(type_payloads));
+ EXPECT_CALL(mock_observer_,
+ OnIncomingNotification(type_payloads,
+ REMOTE_NOTIFICATION));
EXPECT_CALL(mock_observer_, OnNotificationStateChange(false));
invalidation_notifier_->SetState("fake_state");
@@ -85,7 +87,8 @@ TEST_F(NonBlockingInvalidationNotifierTest, Basic) {
invalidation_notifier_->OnNotificationStateChange(true);
invalidation_notifier_->StoreState("new_fake_state");
- invalidation_notifier_->OnIncomingNotification(type_payloads);
+ invalidation_notifier_->OnIncomingNotification(type_payloads,
+ REMOTE_NOTIFICATION);
invalidation_notifier_->OnNotificationStateChange(false);
ui_loop_.RunAllPending();
diff --git a/chrome/browser/sync/notifier/p2p_notifier.cc b/chrome/browser/sync/notifier/p2p_notifier.cc
index 60555a3..1cc50ca 100644
--- a/chrome/browser/sync/notifier/p2p_notifier.cc
+++ b/chrome/browser/sync/notifier/p2p_notifier.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -279,7 +279,7 @@ void P2PNotifier::OnIncomingNotification(
syncable::ModelTypePayloadMapFromEnumSet(
notification_data.GetChangedTypes(), std::string());
FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_,
- OnIncomingNotification(type_payloads));
+ OnIncomingNotification(type_payloads, REMOTE_NOTIFICATION));
}
void P2PNotifier::OnOutgoingNotification() {}
diff --git a/chrome/browser/sync/notifier/p2p_notifier_unittest.cc b/chrome/browser/sync/notifier/p2p_notifier_unittest.cc
index 51344ba..a7c8ad0 100644
--- a/chrome/browser/sync/notifier/p2p_notifier_unittest.cc
+++ b/chrome/browser/sync/notifier/p2p_notifier_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -163,7 +163,8 @@ TEST_F(P2PNotifierTest, NotificationsBasic) {
EXPECT_CALL(mock_observer_, OnNotificationStateChange(true));
EXPECT_CALL(mock_observer_,
- OnIncomingNotification(MakePayloadMap(enabled_types)));
+ OnIncomingNotification(MakePayloadMap(enabled_types),
+ REMOTE_NOTIFICATION));
p2p_notifier_->SetUniqueId("sender");
p2p_notifier_->UpdateCredentials("foo@bar.com", "fake_token");
@@ -189,7 +190,8 @@ TEST_F(P2PNotifierTest, SendNotificationData) {
EXPECT_CALL(mock_observer_, OnNotificationStateChange(true));
EXPECT_CALL(mock_observer_,
- OnIncomingNotification(MakePayloadMap(enabled_types)));
+ OnIncomingNotification(MakePayloadMap(enabled_types),
+ REMOTE_NOTIFICATION));
p2p_notifier_->SetUniqueId("sender");
p2p_notifier_->UpdateCredentials("foo@bar.com", "fake_token");
@@ -201,7 +203,8 @@ TEST_F(P2PNotifierTest, SendNotificationData) {
// Should be propagated.
Mock::VerifyAndClearExpectations(&mock_observer_);
- EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map,
+ REMOTE_NOTIFICATION));
p2p_notifier_->SendNotificationDataForTest(
P2PNotificationData("sender", NOTIFY_SELF, changed_types));
@@ -221,7 +224,8 @@ TEST_F(P2PNotifierTest, SendNotificationData) {
// Should be propagated.
Mock::VerifyAndClearExpectations(&mock_observer_);
- EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map,
+ REMOTE_NOTIFICATION));
p2p_notifier_->SendNotificationDataForTest(
P2PNotificationData("sender2", NOTIFY_OTHERS, changed_types));
@@ -232,13 +236,15 @@ TEST_F(P2PNotifierTest, SendNotificationData) {
// Should be propagated.
Mock::VerifyAndClearExpectations(&mock_observer_);
- EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map,
+ REMOTE_NOTIFICATION));
p2p_notifier_->SendNotificationDataForTest(
P2PNotificationData("sender", NOTIFY_ALL, changed_types));
// Should be propagated.
Mock::VerifyAndClearExpectations(&mock_observer_);
- EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map,
+ REMOTE_NOTIFICATION));
p2p_notifier_->SendNotificationDataForTest(
P2PNotificationData("sender2", NOTIFY_ALL, changed_types));
diff --git a/chrome/browser/sync/notifier/sync_notifier_observer.h b/chrome/browser/sync/notifier/sync_notifier_observer.h
index f2d7cda..103655c2 100644
--- a/chrome/browser/sync/notifier/sync_notifier_observer.h
+++ b/chrome/browser/sync/notifier/sync_notifier_observer.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -12,13 +12,21 @@
namespace sync_notifier {
+enum IncomingNotificationSource {
+ // The server is notifying us that one or more datatypes have stale data.
+ REMOTE_NOTIFICATION,
+ // A chrome datatype is requesting an optimistic refresh of its data.
+ LOCAL_NOTIFICATION,
+};
+
class SyncNotifierObserver {
public:
SyncNotifierObserver() {}
virtual ~SyncNotifierObserver() {}
virtual void OnIncomingNotification(
- const syncable::ModelTypePayloadMap& type_payloads) = 0;
+ const syncable::ModelTypePayloadMap& type_payloads,
+ IncomingNotificationSource source) = 0;
virtual void OnNotificationStateChange(bool notifications_enabled) = 0;
// TODO(nileshagrawal): Find a way to hide state handling inside the
diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc
index 7e082f2..4cd3e0e 100644
--- a/chrome/browser/sync/profile_sync_service_session_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc
@@ -158,7 +158,8 @@ class ProfileSyncServiceSessionTest
ProfileSyncServiceSessionTest()
: io_thread_(BrowserThread::IO),
window_bounds_(0, 1, 2, 3),
- notified_of_update_(false) {}
+ notified_of_update_(false),
+ notified_of_refresh_(false) {}
ProfileSyncService* sync_service() { return sync_service_.get(); }
TestIdFactory* ids() { return sync_service_->id_factory(); }
@@ -172,6 +173,8 @@ class ProfileSyncServiceSessionTest
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED,
content::NotificationService::AllSources());
+ registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH,
+ content::NotificationService::AllSources());
}
void Observe(int type,
@@ -181,6 +184,9 @@ class ProfileSyncServiceSessionTest
case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED:
notified_of_update_ = true;
break;
+ case chrome::NOTIFICATION_SYNC_REFRESH:
+ notified_of_refresh_ = true;
+ break;
default:
NOTREACHED();
break;
@@ -253,6 +259,7 @@ class ProfileSyncServiceSessionTest
scoped_ptr<TestProfileSyncService> sync_service_;
const gfx::Rect window_bounds_;
bool notified_of_update_;
+ bool notified_of_refresh_;
content::NotificationRegistrar registrar_;
};
@@ -899,4 +906,47 @@ TEST_F(ProfileSyncServiceSessionTest, StaleSessionRefresh) {
VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
}
+// Test that tabs with nothing but "chrome://*" and "file://*" navigations are
+// not be synced.
+TEST_F(ProfileSyncServiceSessionTest, ValidTabs) {
+ CreateRootHelper create_root(this);
+ ASSERT_TRUE(StartSyncService(create_root.callback(), false));
+ ASSERT_TRUE(create_root.success());
+
+ AddTab(browser(), GURL("chrome://bla1/"));
+ NavigateAndCommitActiveTab(GURL("chrome://bla2"));
+ AddTab(browser(), GURL("file://bla3/"));
+ AddTab(browser(), GURL("bla://bla"));
+ // Note: chrome://newtab has special handling which crashes in unit tests.
+
+ // Get the tabs for this machine. Only the bla:// url should be synced.
+ SessionModelAssociator::TabLinksMap tab_map = model_associator_->tab_map_;
+ ASSERT_EQ(1U, tab_map.size());
+ SessionModelAssociator::TabLinksMap::iterator iter = tab_map.begin();
+ ASSERT_EQ(1, iter->second.tab()->GetEntryCount());
+ ASSERT_EQ(GURL("bla://bla"), iter->second.tab()->
+ GetEntryAtIndex(0)->GetVirtualURL());
+}
+
+// Verify that AttemptSessionsDataRefresh triggers the NOTIFICATION_SYNC_REFRESH
+// notification.
+// TODO(zea): Once we can have unit tests that are able to open to the NTP,
+// test that the NTP/#opentabs URL triggers a refresh as well (but only when
+// it is the active tab).
+TEST_F(ProfileSyncServiceSessionTest, SessionsRefresh) {
+ CreateRootHelper create_root(this);
+ ASSERT_TRUE(StartSyncService(create_root.callback(), false));
+ ASSERT_TRUE(create_root.success());
+
+ // Empty, so returns false.
+ std::vector<const SyncedSession*> foreign_sessions;
+ ASSERT_FALSE(model_associator_->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_FALSE(notified_of_refresh_);
+ model_associator_->AttemptSessionsDataRefresh();
+ ASSERT_TRUE(notified_of_refresh_);
+
+ // Nothing should have changed since we don't have unapplied data.
+ ASSERT_FALSE(model_associator_->GetAllForeignSessions(&foreign_sessions));
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync/protocol/proto_enum_conversions.cc b/chrome/browser/sync/protocol/proto_enum_conversions.cc
index 7cb95ad..4832b85 100644
--- a/chrome/browser/sync/protocol/proto_enum_conversions.cc
+++ b/chrome/browser/sync/protocol/proto_enum_conversions.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -71,7 +71,7 @@ const char* GetPageTransitionQualifierString(
const char* GetUpdatesSourceString(
sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source) {
ASSERT_ENUM_BOUNDS(sync_pb::GetUpdatesCallerInfo, GetUpdatesSource,
- UNKNOWN, RECONFIGURATION);
+ UNKNOWN, DATATYPE_REFRESH);
switch (updates_source) {
ENUM_CASE(sync_pb::GetUpdatesCallerInfo, UNKNOWN);
ENUM_CASE(sync_pb::GetUpdatesCallerInfo, FIRST_UPDATE);
@@ -84,6 +84,7 @@ const char* GetUpdatesSourceString(
ENUM_CASE(sync_pb::GetUpdatesCallerInfo, MIGRATION);
ENUM_CASE(sync_pb::GetUpdatesCallerInfo, NEW_CLIENT);
ENUM_CASE(sync_pb::GetUpdatesCallerInfo, RECONFIGURATION);
+ ENUM_CASE(sync_pb::GetUpdatesCallerInfo, DATATYPE_REFRESH);
}
NOTREACHED();
return "";
diff --git a/chrome/browser/sync/protocol/sync.proto b/chrome/browser/sync/protocol/sync.proto
index 1c497ef..41ef933 100644
--- a/chrome/browser/sync/protocol/sync.proto
+++ b/chrome/browser/sync/protocol/sync.proto
@@ -304,6 +304,9 @@ message GetUpdatesCallerInfo {
// confused with FIRST_UPDATE.
RECONFIGURATION = 10; // The client is in configuration mode because the
// user opted to sync a different set of datatypes.
+ DATATYPE_REFRESH = 11; // A datatype has requested a refresh. This is
+ // typically used when datatype's have custom
+ // sync UI, e.g. sessions.
}
required GetUpdatesSource source = 1;
diff --git a/chrome/browser/sync/tools/sync_listen_notifications.cc b/chrome/browser/sync/tools/sync_listen_notifications.cc
index fa1c099..32055af 100644
--- a/chrome/browser/sync/tools/sync_listen_notifications.cc
+++ b/chrome/browser/sync/tools/sync_listen_notifications.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -39,10 +39,13 @@ class NotificationPrinter : public sync_notifier::SyncNotifierObserver {
virtual ~NotificationPrinter() {}
virtual void OnIncomingNotification(
- const syncable::ModelTypePayloadMap& type_payloads) OVERRIDE {
+ const syncable::ModelTypePayloadMap& type_payloads,
+ sync_notifier::IncomingNotificationSource source) OVERRIDE {
for (syncable::ModelTypePayloadMap::const_iterator it =
type_payloads.begin(); it != type_payloads.end(); ++it) {
- LOG(INFO) << "Notification: type = "
+ LOG(INFO) << (source == sync_notifier::REMOTE_NOTIFICATION ?
+ "Remote" : "Local")
+ << " Notification: type = "
<< syncable::ModelTypeToString(it->first)
<< ", payload = " << it->second;
}
diff --git a/chrome/common/chrome_notification_types.h b/chrome/common/chrome_notification_types.h
index 90f06c3..02c625d 100644
--- a/chrome/common/chrome_notification_types.h
+++ b/chrome/common/chrome_notification_types.h
@@ -698,6 +698,10 @@ enum NotificationType {
// The sync service is finished the configuration process.
NOTIFICATION_SYNC_CONFIGURE_DONE,
+ // A service is requesting a sync datatype refresh for the current profile.
+ // The details value is a const syncable::ModelType.
+ NOTIFICATION_SYNC_REFRESH,
+
// The session service has been saved. This notification type is only sent
// if there were new SessionService commands to save, and not for no-op save
// operations.