Reland: Keep poll intervals in prefs.
Cause for breakage: Side effect in DCHECK() which wasn't exercised on trybots
(apparently they have all DCHECKs enabled)
Without persisting them, server-side provided intervals are less efficient on
platforms with relatively short app lifetime.
This also allows lower poll intervals for latency-sensitive use cases in cases
when our notifications are not reliable enough (yet).
Bug: 832019
Change-Id: Ifcd55edcbb9fb17583caac847f6c110024a83e19
Reviewed-on: https://chromium-review.googlesource.com/1013457
Reviewed-by: Marc Treib <treib@chromium.org>
Commit-Queue: Tim Schumann <tschumann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#550984}
diff --git a/chrome/browser/sync/test/integration/sync_client_command_test.cc b/chrome/browser/sync/test/integration/sync_client_command_test.cc
new file mode 100644
index 0000000..89c968c5
--- /dev/null
+++ b/chrome/browser/sync/test/integration/sync_client_command_test.cc
@@ -0,0 +1,91 @@
+// Copyright (c) 2018 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/macros.h"
+#include "base/run_loop.h"
+#include "build/build_config.h"
+
+#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/session_hierarchy_match_checker.h"
+#include "chrome/browser/sync/test/integration/sessions_helper.h"
+#include "chrome/browser/sync/test/integration/sync_test.h"
+#include "chrome/common/webui_url_constants.h"
+#include "components/sync/base/sync_prefs.h"
+#include "components/sync/engine/polling_constants.h"
+#include "components/sync/protocol/client_commands.pb.h"
+#include "components/sync/test/fake_server/sessions_hierarchy.h"
+
+#include "components/sync/protocol/client_commands.pb.h"
+
+using sessions_helper::CheckInitialState;
+using sessions_helper::OpenTab;
+using syncer::SyncPrefs;
+
+namespace {
+
+class SyncClientCommandTest : public SyncTest {
+ public:
+ SyncClientCommandTest() : SyncTest(SINGLE_CLIENT) {}
+ ~SyncClientCommandTest() override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SyncClientCommandTest);
+};
+
+IN_PROC_BROWSER_TEST_F(SyncClientCommandTest, ShouldPersistPollIntervals) {
+ // Setup clients and verify no poll intervals are present yet.
+ ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
+ std::unique_ptr<SyncPrefs> sync_prefs =
+ std::make_unique<SyncPrefs>(GetProfile(0)->GetPrefs());
+ EXPECT_TRUE(sync_prefs->GetShortPollInterval().is_zero());
+ EXPECT_TRUE(sync_prefs->GetLongPollInterval().is_zero());
+
+ // Execute a sync cycle and verify the client set up (and persisted) the
+ // default values.
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+ EXPECT_EQ(sync_prefs->GetShortPollInterval().InSeconds(),
+ syncer::kDefaultShortPollIntervalSeconds);
+ EXPECT_EQ(sync_prefs->GetLongPollInterval().InSeconds(),
+ syncer::kDefaultLongPollIntervalSeconds);
+
+ // Simulate server-provided poll intervals and make sure they get persisted.
+ sync_pb::ClientCommand client_command;
+ client_command.set_set_sync_poll_interval(67);
+ client_command.set_set_sync_long_poll_interval(199);
+ GetFakeServer()->SetClientCommand(client_command);
+
+ // Trigger a sync-cycle.
+ ASSERT_TRUE(CheckInitialState(0));
+ ASSERT_TRUE(OpenTab(0, GURL(chrome::kChromeUIHistoryURL)));
+ SessionHierarchyMatchChecker checker(
+ fake_server::SessionsHierarchy(
+ {{GURL(chrome::kChromeUIHistoryURL).spec()}}),
+ GetSyncService(0), GetFakeServer());
+ EXPECT_TRUE(checker.Wait());
+
+ EXPECT_EQ(sync_prefs->GetShortPollInterval().InSeconds(), 67);
+ EXPECT_EQ(sync_prefs->GetLongPollInterval().InSeconds(), 199);
+}
+
+IN_PROC_BROWSER_TEST_F(SyncClientCommandTest, ShouldUsePollIntervalsFromPrefs) {
+ // Setup clients and provide new poll intervals via prefs.
+ ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
+ std::unique_ptr<SyncPrefs> sync_prefs =
+ std::make_unique<SyncPrefs>(GetProfile(0)->GetPrefs());
+ sync_prefs->SetShortPollInterval(base::TimeDelta::FromSeconds(123));
+ sync_prefs->SetLongPollInterval(base::TimeDelta::FromSeconds(1234));
+
+ // Execute a sync cycle and verify this cycle used those intervals.
+ // This test assumes the SyncScheduler reads the actual intervals from the
+ // context. This is covered in the SyncSchedulerImpl's unittest.
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+ EXPECT_EQ(
+ 123,
+ GetClient(0)->GetLastCycleSnapshot().short_poll_interval().InSeconds());
+ EXPECT_EQ(
+ 1234,
+ GetClient(0)->GetLastCycleSnapshot().long_poll_interval().InSeconds());
+}
+
+} // namespace
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index c838970..d0bfa28 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -5272,6 +5272,7 @@
"../browser/sync/test/integration/single_client_wallet_sync_test.cc",
"../browser/sync/test/integration/single_client_wifi_credentials_sync_test.cc",
"../browser/sync/test/integration/sync_auth_test.cc",
+ "../browser/sync/test/integration/sync_client_command_test.cc",
"../browser/sync/test/integration/sync_errors_test.cc",
"../browser/sync/test/integration/sync_exponential_backoff_test.cc",
"../browser/sync/test/integration/two_client_app_list_sync_test.cc",
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index f89a149..3a11e525 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -955,6 +955,11 @@
UpdateLastSyncedTime();
if (!snapshot.poll_finish_time().is_null())
sync_prefs_.SetLastPollTime(snapshot.poll_finish_time());
+ DCHECK(!snapshot.short_poll_interval().is_zero());
+ sync_prefs_.SetShortPollInterval(snapshot.short_poll_interval());
+
+ DCHECK(!snapshot.long_poll_interval().is_zero());
+ sync_prefs_.SetLongPollInterval(snapshot.long_poll_interval());
if (IsDataTypeControllerRunning(syncer::SESSIONS) &&
snapshot.model_neutral_state().get_updates_request_types.Has(
diff --git a/components/browser_sync/profile_sync_service_unittest.cc b/components/browser_sync/profile_sync_service_unittest.cc
index 5bceb20c..dd1da3f 100644
--- a/components/browser_sync/profile_sync_service_unittest.cc
+++ b/components/browser_sync/profile_sync_service_unittest.cc
@@ -1071,7 +1071,14 @@
TEST_F(ProfileSyncServiceTest, ValidPointersInDTCMap) {
CreateService(ProfileSyncService::AUTO_START);
service()->OnSessionRestoreComplete();
- service()->OnSyncCycleCompleted(syncer::SyncCycleSnapshot());
+ service()->OnSyncCycleCompleted(syncer::SyncCycleSnapshot(
+ syncer::ModelNeutralState(), syncer::ProgressMarkerMap(), false, 0, 0, 0,
+ false, 0, base::Time::Now(), base::Time::Now(),
+ std::vector<int>(syncer::MODEL_TYPE_COUNT, 0),
+ std::vector<int>(syncer::MODEL_TYPE_COUNT, 0),
+ sync_pb::SyncEnums::UNKNOWN_ORIGIN,
+ /*short_poll_interval=*/base::TimeDelta::FromMinutes(30),
+ /*long_poll_interval=*/base::TimeDelta::FromMinutes(180)));
}
// The OpenTabsUIDelegate should only be accessable when PROXY_TABS is enabled.
diff --git a/components/suggestions/suggestions_service_impl_unittest.cc b/components/suggestions/suggestions_service_impl_unittest.cc
index e99c5d9..e6fc7cf 100644
--- a/components/suggestions/suggestions_service_impl_unittest.cc
+++ b/components/suggestions/suggestions_service_impl_unittest.cc
@@ -8,6 +8,7 @@
#include <memory>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/macros.h"
@@ -182,7 +183,9 @@
2, 7, false, 0, base::Time::Now(), base::Time::Now(),
std::vector<int>(syncer::MODEL_TYPE_COUNT, 0),
std::vector<int>(syncer::MODEL_TYPE_COUNT, 0),
- sync_pb::SyncEnums::UNKNOWN_ORIGIN)));
+ sync_pb::SyncEnums::UNKNOWN_ORIGIN,
+ /*short_poll_interval=*/base::TimeDelta::FromMinutes(30),
+ /*long_poll_interval=*/base::TimeDelta::FromMinutes(180))));
// These objects are owned by the SuggestionsService, but we keep the
// pointers around for testing.
test_suggestions_store_ = new TestSuggestionsStore();
diff --git a/components/sync/driver/glue/sync_backend_host_core.cc b/components/sync/driver/glue/sync_backend_host_core.cc
index ef24a5e..b8603bc 100644
--- a/components/sync/driver/glue/sync_backend_host_core.cc
+++ b/components/sync/driver/glue/sync_backend_host_core.cc
@@ -328,6 +328,8 @@
params.report_unrecoverable_error_function;
args.cancelation_signal = &stop_syncing_signal_;
args.saved_nigori_state = std::move(params.saved_nigori_state);
+ args.short_poll_interval = params.short_poll_interval;
+ args.long_poll_interval = params.long_poll_interval;
sync_manager_->Init(&args);
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
this, "SyncDirectory", base::ThreadTaskRunnerHandle::Get());
diff --git a/components/sync/driver/sync_service_base.cc b/components/sync/driver/sync_service_base.cc
index acd7836..4636db18 100644
--- a/components/sync/driver/sync_service_base.cc
+++ b/components/sync/driver/sync_service_base.cc
@@ -18,6 +18,7 @@
#include "components/sync/device_info/local_device_info_provider.h"
#include "components/sync/driver/sync_driver_switches.h"
#include "components/sync/engine/engine_components_factory_impl.h"
+#include "components/sync/engine/polling_constants.h"
namespace syncer {
@@ -154,6 +155,16 @@
base::Bind(ReportUnrecoverableError, channel_);
params.saved_nigori_state = crypto_->TakeSavedNigoriState();
sync_prefs_.GetInvalidationVersions(¶ms.invalidation_versions);
+ params.short_poll_interval = sync_prefs_.GetShortPollInterval();
+ if (params.short_poll_interval.is_zero()) {
+ params.short_poll_interval =
+ base::TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds);
+ }
+ params.long_poll_interval = sync_prefs_.GetLongPollInterval();
+ if (params.long_poll_interval.is_zero()) {
+ params.long_poll_interval =
+ base::TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds);
+ }
engine_->Initialize(std::move(params));
}
diff --git a/components/sync/driver/sync_service_utils_unittest.cc b/components/sync/driver/sync_service_utils_unittest.cc
index 60cfcb8..48928e3 100644
--- a/components/sync/driver/sync_service_utils_unittest.cc
+++ b/components/sync/driver/sync_service_utils_unittest.cc
@@ -49,12 +49,14 @@
}
SyncCycleSnapshot GetLastCycleSnapshot() const override {
if (sync_cycle_complete_) {
- return SyncCycleSnapshot(ModelNeutralState(), ProgressMarkerMap(), false,
- 5, 2, 7, false, 0, base::Time::Now(),
- base::Time::Now(),
- std::vector<int>(MODEL_TYPE_COUNT, 0),
- std::vector<int>(MODEL_TYPE_COUNT, 0),
- sync_pb::SyncEnums::UNKNOWN_ORIGIN);
+ return SyncCycleSnapshot(
+ ModelNeutralState(), ProgressMarkerMap(), false, 5, 2, 7, false, 0,
+ base::Time::Now(), base::Time::Now(),
+ std::vector<int>(MODEL_TYPE_COUNT, 0),
+ std::vector<int>(MODEL_TYPE_COUNT, 0),
+ sync_pb::SyncEnums::UNKNOWN_ORIGIN,
+ /*short_poll_interval=*/base::TimeDelta::FromMinutes(30),
+ /*long_poll_interval=*/base::TimeDelta::FromMinutes(180));
}
return SyncCycleSnapshot();
}
diff --git a/components/sync/engine/cycle/sync_cycle_snapshot.cc b/components/sync/engine/cycle/sync_cycle_snapshot.cc
index 20823b5..90a6fa4 100644
--- a/components/sync/engine/cycle/sync_cycle_snapshot.cc
+++ b/components/sync/engine/cycle/sync_cycle_snapshot.cc
@@ -36,7 +36,9 @@
base::Time poll_finish_time,
const std::vector<int>& num_entries_by_type,
const std::vector<int>& num_to_delete_entries_by_type,
- sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin)
+ sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin,
+ base::TimeDelta short_poll_interval,
+ base::TimeDelta long_poll_interval)
: model_neutral_state_(model_neutral_state),
download_progress_markers_(download_progress_markers),
is_silenced_(is_silenced),
@@ -50,6 +52,8 @@
num_entries_by_type_(num_entries_by_type),
num_to_delete_entries_by_type_(num_to_delete_entries_by_type),
get_updates_origin_(get_updates_origin),
+ short_poll_interval_(short_poll_interval),
+ long_poll_interval_(long_poll_interval),
is_initialized_(true) {}
SyncCycleSnapshot::SyncCycleSnapshot(const SyncCycleSnapshot& other) = default;
@@ -162,4 +166,12 @@
return get_updates_origin_;
}
+base::TimeDelta SyncCycleSnapshot::short_poll_interval() const {
+ return short_poll_interval_;
+}
+
+base::TimeDelta SyncCycleSnapshot::long_poll_interval() const {
+ return long_poll_interval_;
+}
+
} // namespace syncer
diff --git a/components/sync/engine/cycle/sync_cycle_snapshot.h b/components/sync/engine/cycle/sync_cycle_snapshot.h
index 62aee7e..ac4fb8c 100644
--- a/components/sync/engine/cycle/sync_cycle_snapshot.h
+++ b/components/sync/engine/cycle/sync_cycle_snapshot.h
@@ -42,7 +42,9 @@
base::Time poll_finish_time,
const std::vector<int>& num_entries_by_type,
const std::vector<int>& num_to_delete_entries_by_type,
- sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin);
+ sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin,
+ base::TimeDelta short_poll_interval,
+ base::TimeDelta long_poll_interval);
SyncCycleSnapshot(const SyncCycleSnapshot& other);
~SyncCycleSnapshot();
@@ -63,6 +65,8 @@
const std::vector<int>& num_entries_by_type() const;
const std::vector<int>& num_to_delete_entries_by_type() const;
sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin() const;
+ base::TimeDelta short_poll_interval() const;
+ base::TimeDelta long_poll_interval() const;
// Set iff this snapshot was not built using the default constructor.
bool is_initialized() const;
@@ -84,6 +88,9 @@
sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin_;
+ base::TimeDelta short_poll_interval_;
+ base::TimeDelta long_poll_interval_;
+
bool is_initialized_;
};
diff --git a/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc b/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc
index ca0f243..4a86538 100644
--- a/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc
+++ b/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc
@@ -41,13 +41,14 @@
const int kNumHierarchyConflicts = 1055;
const int kNumServerConflicts = 1057;
- SyncCycleSnapshot snapshot(model_neutral, download_progress_markers,
- kIsSilenced, kNumEncryptionConflicts,
- kNumHierarchyConflicts, kNumServerConflicts, false,
- 0, base::Time::Now(), base::Time::Now(),
- std::vector<int>(MODEL_TYPE_COUNT, 0),
- std::vector<int>(MODEL_TYPE_COUNT, 0),
- sync_pb::SyncEnums::UNKNOWN_ORIGIN);
+ SyncCycleSnapshot snapshot(
+ model_neutral, download_progress_markers, kIsSilenced,
+ kNumEncryptionConflicts, kNumHierarchyConflicts, kNumServerConflicts,
+ false, 0, base::Time::Now(), base::Time::Now(),
+ std::vector<int>(MODEL_TYPE_COUNT, 0),
+ std::vector<int>(MODEL_TYPE_COUNT, 0), sync_pb::SyncEnums::UNKNOWN_ORIGIN,
+ /*short_poll_interval=*/base::TimeDelta::FromMinutes(30),
+ /*long_poll_interval=*/base::TimeDelta::FromMinutes(180));
std::unique_ptr<base::DictionaryValue> value(snapshot.ToValue());
EXPECT_EQ(16u, value->size());
ExpectDictIntegerValue(model_neutral.num_successful_commits, *value,
diff --git a/components/sync/engine/engine_components_factory.h b/components/sync/engine/engine_components_factory.h
index 70c6b1f..8b7170f 100644
--- a/components/sync/engine/engine_components_factory.h
+++ b/components/sync/engine/engine_components_factory.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/files/file_path.h"
+#include "base/time/time.h"
#include "components/sync/engine/model_safe_worker.h"
namespace syncer {
@@ -100,7 +101,9 @@
const std::vector<SyncEngineEventListener*>& listeners,
DebugInfoGetter* debug_info_getter,
ModelTypeRegistry* model_type_registry,
- const std::string& invalidator_client_id) = 0;
+ const std::string& invalidator_client_id,
+ base::TimeDelta short_poll_interval,
+ base::TimeDelta long_poll_interval) = 0;
virtual std::unique_ptr<syncable::DirectoryBackingStore>
BuildDirectoryBackingStore(StorageOption storage,
diff --git a/components/sync/engine/engine_components_factory_impl.cc b/components/sync/engine/engine_components_factory_impl.cc
index efaa68a..41d73c9 100644
--- a/components/sync/engine/engine_components_factory_impl.cc
+++ b/components/sync/engine/engine_components_factory_impl.cc
@@ -67,14 +67,16 @@
const std::vector<SyncEngineEventListener*>& listeners,
DebugInfoGetter* debug_info_getter,
ModelTypeRegistry* model_type_registry,
- const std::string& invalidation_client_id) {
- return std::unique_ptr<SyncCycleContext>(
- new SyncCycleContext(connection_manager, directory, extensions_activity,
- listeners, debug_info_getter, model_type_registry,
- switches_.encryption_method == ENCRYPTION_KEYSTORE,
- switches_.pre_commit_updates_policy ==
- FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE,
- invalidation_client_id));
+ const std::string& invalidation_client_id,
+ base::TimeDelta short_poll_interval,
+ base::TimeDelta long_poll_interval) {
+ return std::make_unique<SyncCycleContext>(
+ connection_manager, directory, extensions_activity, listeners,
+ debug_info_getter, model_type_registry,
+ switches_.encryption_method == ENCRYPTION_KEYSTORE,
+ switches_.pre_commit_updates_policy ==
+ FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE,
+ invalidation_client_id, short_poll_interval, long_poll_interval);
}
std::unique_ptr<syncable::DirectoryBackingStore>
diff --git a/components/sync/engine/engine_components_factory_impl.h b/components/sync/engine/engine_components_factory_impl.h
index a16cc5e..9ddc96d 100644
--- a/components/sync/engine/engine_components_factory_impl.h
+++ b/components/sync/engine/engine_components_factory_impl.h
@@ -34,7 +34,9 @@
const std::vector<SyncEngineEventListener*>& listeners,
DebugInfoGetter* debug_info_getter,
ModelTypeRegistry* model_type_registry,
- const std::string& invalidator_client_id) override;
+ const std::string& invalidator_client_id,
+ base::TimeDelta short_poll_interval,
+ base::TimeDelta long_poll_interval) override;
std::unique_ptr<syncable::DirectoryBackingStore> BuildDirectoryBackingStore(
StorageOption storage,
diff --git a/components/sync/engine/sync_engine.h b/components/sync/engine/sync_engine.h
index e7d7484..9d9d4bf 100644
--- a/components/sync/engine/sync_engine.h
+++ b/components/sync/engine/sync_engine.h
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
#include "components/sync/base/extensions_activity.h"
#include "components/sync/base/model_type.h"
#include "components/sync/base/weak_handle.h"
@@ -76,6 +77,10 @@
std::unique_ptr<SyncEncryptionHandler::NigoriState> saved_nigori_state;
std::map<ModelType, int64_t> invalidation_versions;
+ // Define the polling intervals. Must not be zero.
+ base::TimeDelta short_poll_interval;
+ base::TimeDelta long_poll_interval;
+
private:
DISALLOW_COPY_AND_ASSIGN(InitParams);
};
diff --git a/components/sync/engine/sync_manager.h b/components/sync/engine/sync_manager.h
index 8ece474..aee26e8 100644
--- a/components/sync/engine/sync_manager.h
+++ b/components/sync/engine/sync_manager.h
@@ -267,6 +267,10 @@
// Optional nigori state to be restored.
std::unique_ptr<SyncEncryptionHandler::NigoriState> saved_nigori_state;
+
+ // Define the polling intervals. Must not be zero.
+ base::TimeDelta short_poll_interval;
+ base::TimeDelta long_poll_interval;
};
SyncManager();
diff --git a/components/sync/engine/test_engine_components_factory.cc b/components/sync/engine/test_engine_components_factory.cc
index d71f1b53..29e7e05 100644
--- a/components/sync/engine/test_engine_components_factory.cc
+++ b/components/sync/engine/test_engine_components_factory.cc
@@ -37,7 +37,9 @@
const std::vector<SyncEngineEventListener*>& listeners,
DebugInfoGetter* debug_info_getter,
ModelTypeRegistry* model_type_registry,
- const std::string& invalidator_client_id) {
+ const std::string& invalidator_client_id,
+ base::TimeDelta short_poll_interval,
+ base::TimeDelta long_poll_interval) {
// Tests don't wire up listeners.
std::vector<SyncEngineEventListener*> empty_listeners;
return std::unique_ptr<SyncCycleContext>(new SyncCycleContext(
@@ -46,7 +48,7 @@
switches_.encryption_method == ENCRYPTION_KEYSTORE,
switches_.pre_commit_updates_policy ==
FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE,
- invalidator_client_id));
+ invalidator_client_id, short_poll_interval, long_poll_interval));
}
std::unique_ptr<syncable::DirectoryBackingStore>
diff --git a/components/sync/engine/test_engine_components_factory.h b/components/sync/engine/test_engine_components_factory.h
index 0f2ec77..6280fd5 100644
--- a/components/sync/engine/test_engine_components_factory.h
+++ b/components/sync/engine/test_engine_components_factory.h
@@ -34,7 +34,9 @@
const std::vector<SyncEngineEventListener*>& listeners,
DebugInfoGetter* debug_info_getter,
ModelTypeRegistry* model_type_registry,
- const std::string& invalidator_client_id) override;
+ const std::string& invalidator_client_id,
+ base::TimeDelta short_poll_interval,
+ base::TimeDelta long_poll_interval) override;
std::unique_ptr<syncable::DirectoryBackingStore> BuildDirectoryBackingStore(
StorageOption storage,
diff --git a/components/sync/engine_impl/cycle/sync_cycle.cc b/components/sync/engine_impl/cycle/sync_cycle.cc
index 7127f036..6f6e3c3 100644
--- a/components/sync/engine_impl/cycle/sync_cycle.cc
+++ b/components/sync/engine_impl/cycle/sync_cycle.cc
@@ -47,7 +47,8 @@
context_->notifications_enabled(), dir->GetEntriesCount(),
status_controller_->sync_start_time(),
status_controller_->poll_finish_time(), num_entries_by_type,
- num_to_delete_entries_by_type, get_updates_origin);
+ num_to_delete_entries_by_type, get_updates_origin,
+ context_->short_poll_interval(), context_->long_poll_interval());
return snapshot;
}
diff --git a/components/sync/engine_impl/cycle/sync_cycle_context.cc b/components/sync/engine_impl/cycle/sync_cycle_context.cc
index c50ea25..5dd33e4 100644
--- a/components/sync/engine_impl/cycle/sync_cycle_context.cc
+++ b/components/sync/engine_impl/cycle/sync_cycle_context.cc
@@ -17,7 +17,9 @@
ModelTypeRegistry* model_type_registry,
bool keystore_encryption_enabled,
bool client_enabled_pre_commit_update_avoidance,
- const std::string& invalidator_client_id)
+ const std::string& invalidator_client_id,
+ base::TimeDelta short_poll_interval,
+ base::TimeDelta long_poll_interval)
: connection_manager_(connection_manager),
directory_(directory),
extensions_activity_(extensions_activity),
@@ -31,7 +33,11 @@
client_enabled_pre_commit_update_avoidance_(
client_enabled_pre_commit_update_avoidance),
cookie_jar_mismatch_(false),
- cookie_jar_empty_(false) {
+ cookie_jar_empty_(false),
+ short_poll_interval_(short_poll_interval),
+ long_poll_interval_(long_poll_interval) {
+ DCHECK(!short_poll_interval.is_zero());
+ DCHECK(!long_poll_interval.is_zero());
std::vector<SyncEngineEventListener*>::const_iterator it;
for (it = listeners.begin(); it != listeners.end(); ++it)
listeners_.AddObserver(*it);
diff --git a/components/sync/engine_impl/cycle/sync_cycle_context.h b/components/sync/engine_impl/cycle/sync_cycle_context.h
index 1e7e0aef..400ba9f 100644
--- a/components/sync/engine_impl/cycle/sync_cycle_context.h
+++ b/components/sync/engine_impl/cycle/sync_cycle_context.h
@@ -11,6 +11,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/time/time.h"
#include "components/sync/engine_impl/cycle/debug_info_getter.h"
#include "components/sync/engine_impl/model_type_registry.h"
#include "components/sync/engine_impl/sync_engine_event_listener.h"
@@ -47,7 +48,9 @@
ModelTypeRegistry* model_type_registry,
bool keystore_encryption_enabled,
bool client_enabled_pre_commit_update_avoidance,
- const std::string& invalidator_client_id);
+ const std::string& invalidator_client_id,
+ base::TimeDelta short_poll_interval,
+ base::TimeDelta long_poll_interval);
~SyncCycleContext();
@@ -116,6 +119,18 @@
void set_cookie_jar_empty(bool empty_jar) { cookie_jar_empty_ = empty_jar; }
+ base::TimeDelta short_poll_interval() const { return short_poll_interval_; }
+ void set_short_poll_interval(base::TimeDelta interval) {
+ DCHECK(!interval.is_zero());
+ short_poll_interval_ = interval;
+ }
+
+ base::TimeDelta long_poll_interval() const { return long_poll_interval_; }
+ void set_long_poll_interval(base::TimeDelta interval) {
+ DCHECK(!interval.is_zero());
+ long_poll_interval_ = interval;
+ }
+
private:
base::ObserverList<SyncEngineEventListener> listeners_;
@@ -173,6 +188,9 @@
// If there's a cookie jar mismatch, whether the cookie jar was empty or not.
bool cookie_jar_empty_;
+ base::TimeDelta short_poll_interval_;
+ base::TimeDelta long_poll_interval_;
+
DISALLOW_COPY_AND_ASSIGN(SyncCycleContext);
};
diff --git a/components/sync/engine_impl/js_sync_manager_observer_unittest.cc b/components/sync/engine_impl/js_sync_manager_observer_unittest.cc
index 8dc6370f..af2493e 100644
--- a/components/sync/engine_impl/js_sync_manager_observer_unittest.cc
+++ b/components/sync/engine_impl/js_sync_manager_observer_unittest.cc
@@ -61,12 +61,13 @@
}
TEST_F(JsSyncManagerObserverTest, OnSyncCycleCompleted) {
- SyncCycleSnapshot snapshot(ModelNeutralState(), ProgressMarkerMap(), false, 5,
- 2, 7, false, 0, base::Time::Now(),
- base::Time::Now(),
- std::vector<int>(MODEL_TYPE_COUNT, 0),
- std::vector<int>(MODEL_TYPE_COUNT, 0),
- sync_pb::SyncEnums::UNKNOWN_ORIGIN);
+ SyncCycleSnapshot snapshot(
+ ModelNeutralState(), ProgressMarkerMap(), false, 5, 2, 7, false, 0,
+ base::Time::Now(), base::Time::Now(),
+ std::vector<int>(MODEL_TYPE_COUNT, 0),
+ std::vector<int>(MODEL_TYPE_COUNT, 0), sync_pb::SyncEnums::UNKNOWN_ORIGIN,
+ /*short_poll_interval=*/base::TimeDelta::FromMinutes(30),
+ /*long_poll_interval=*/base::TimeDelta::FromMinutes(180));
base::DictionaryValue expected_details;
expected_details.Set("snapshot", snapshot.ToValue());
diff --git a/components/sync/engine_impl/sync_manager_impl.cc b/components/sync/engine_impl/sync_manager_impl.cc
index 2f3a289..8d890dc 100644
--- a/components/sync/engine_impl/sync_manager_impl.cc
+++ b/components/sync/engine_impl/sync_manager_impl.cc
@@ -200,6 +200,8 @@
DCHECK(!initialized_);
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(args->post_factory.get());
+ DCHECK(!args->short_poll_interval.is_zero());
+ DCHECK(!args->long_poll_interval.is_zero());
if (!args->enable_local_sync_backend) {
DCHECK(!args->credentials.account_id.empty());
DCHECK(!args->credentials.sync_token.empty());
@@ -301,7 +303,8 @@
cycle_context_ = args->engine_components_factory->BuildContext(
connection_manager_.get(), directory(), args->extensions_activity,
listeners, &debug_info_event_listener_, model_type_registry_.get(),
- args->invalidator_client_id);
+ args->invalidator_client_id, args->short_poll_interval,
+ args->long_poll_interval);
scheduler_ = args->engine_components_factory->BuildScheduler(
name_, cycle_context_.get(), args->cancelation_signal,
args->enable_local_sync_backend);
diff --git a/components/sync/engine_impl/sync_manager_impl_unittest.cc b/components/sync/engine_impl/sync_manager_impl_unittest.cc
index ef1a524..247da28 100644
--- a/components/sync/engine_impl/sync_manager_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_manager_impl_unittest.cc
@@ -969,6 +969,8 @@
args.unrecoverable_error_handler =
MakeWeakHandle(mock_unrecoverable_error_handler_.GetWeakPtr());
args.cancelation_signal = &cancelation_signal_;
+ args.short_poll_interval = base::TimeDelta::FromMinutes(60);
+ args.long_poll_interval = base::TimeDelta::FromMinutes(120);
sync_manager_.Init(&args);
sync_manager_.GetEncryptionHandler()->AddObserver(&encryption_observer_);
diff --git a/components/sync/engine_impl/sync_scheduler_impl.cc b/components/sync/engine_impl/sync_scheduler_impl.cc
index def9afe7..5d15250 100644
--- a/components/sync/engine_impl/sync_scheduler_impl.cc
+++ b/components/sync/engine_impl/sync_scheduler_impl.cc
@@ -138,10 +138,8 @@
bool ignore_auth_credentials)
: name_(name),
started_(false),
- syncer_short_poll_interval_seconds_(
- TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)),
- syncer_long_poll_interval_seconds_(
- TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)),
+ syncer_short_poll_interval_seconds_(context->short_poll_interval()),
+ syncer_long_poll_interval_seconds_(context->long_poll_interval()),
mode_(CONFIGURATION_MODE),
delay_provider_(delay_provider),
syncer_(syncer),
diff --git a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
index d309241..824c0c6 100644
--- a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
@@ -115,7 +115,6 @@
void SetUp() override {
test_user_share_.SetUp();
- syncer_ = new testing::StrictMock<MockSyncer>();
delay_ = nullptr;
extensions_activity_ = new ExtensionsActivity();
@@ -141,9 +140,17 @@
model_type_registry_.get(),
true, // enable keystore encryption
false, // force enable pre-commit GU avoidance
- "fake_invalidator_client_id");
+ "fake_invalidator_client_id",
+ /*short_poll_interval=*/base::TimeDelta::FromMinutes(30),
+ /*long_poll_interval=*/base::TimeDelta::FromMinutes(120));
context_->set_notifications_enabled(true);
context_->set_account_name("Test");
+ RebuildScheduler();
+ }
+
+ void RebuildScheduler() {
+ // The old syncer is destroyed with the scheduler that owns it.
+ syncer_ = new testing::StrictMock<MockSyncer>();
scheduler_ = std::make_unique<SyncSchedulerImpl>(
"TestSyncScheduler", BackoffDelayProvider::FromDefaults(), context(),
syncer_, false);
@@ -674,6 +681,30 @@
AnalyzePollRun(times, kMinNumSamples, optimal_start, poll_interval);
}
+// Test that polling gets the intervals from the provided context.
+TEST_F(SyncSchedulerImplTest, ShouldUseInitialPollIntervalFromContext) {
+ SyncShareTimes times;
+ TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
+ context()->set_short_poll_interval(poll_interval);
+ context()->set_long_poll_interval(poll_interval);
+ RebuildScheduler();
+
+ EXPECT_CALL(*syncer(), PollSyncShare(_, _))
+ .Times(AtLeast(kMinNumSamples))
+ .WillRepeatedly(
+ DoAll(Invoke(test_util::SimulatePollSuccess),
+ RecordSyncShareMultiple(×, kMinNumSamples, true)));
+
+ TimeTicks optimal_start = TimeTicks::Now() + poll_interval;
+ StartSyncScheduler(base::Time());
+
+ // Run again to wait for polling.
+ RunLoop();
+
+ StopSyncScheduler();
+ AnalyzePollRun(times, kMinNumSamples, optimal_start, poll_interval);
+}
+
// Test that we reuse the previous poll time on startup, triggering the first
// poll based on when the last one happened. Subsequent polls should have the
// normal delay.
diff --git a/components/sync/engine_impl/syncer_proto_util.cc b/components/sync/engine_impl/syncer_proto_util.cc
index d6b5b4e..f564d37e 100644
--- a/components/sync/engine_impl/syncer_proto_util.cc
+++ b/components/sync/engine_impl/syncer_proto_util.cc
@@ -410,13 +410,27 @@
}
if (command.has_set_sync_long_poll_interval()) {
- cycle->delegate()->OnReceivedLongPollIntervalUpdate(
- base::TimeDelta::FromSeconds(command.set_sync_long_poll_interval()));
+ base::TimeDelta interval =
+ base::TimeDelta::FromSeconds(command.set_sync_long_poll_interval());
+ if (interval.is_zero()) {
+ DLOG(WARNING)
+ << "Received zero long poll interval from server. Ignoring.";
+ } else {
+ cycle->context()->set_long_poll_interval(interval);
+ cycle->delegate()->OnReceivedLongPollIntervalUpdate(interval);
+ }
}
if (command.has_set_sync_poll_interval()) {
- cycle->delegate()->OnReceivedShortPollIntervalUpdate(
- base::TimeDelta::FromSeconds(command.set_sync_poll_interval()));
+ base::TimeDelta interval =
+ base::TimeDelta::FromSeconds(command.set_sync_poll_interval());
+ if (interval.is_zero()) {
+ DLOG(WARNING)
+ << "Received zero short poll interval from server. Ignoring.";
+ } else {
+ cycle->context()->set_short_poll_interval(interval);
+ cycle->delegate()->OnReceivedShortPollIntervalUpdate(interval);
+ }
}
if (command.has_sessions_commit_delay_seconds()) {
diff --git a/components/sync/engine_impl/syncer_unittest.cc b/components/sync/engine_impl/syncer_unittest.cc
index c95fb2c..312946a9 100644
--- a/components/sync/engine_impl/syncer_unittest.cc
+++ b/components/sync/engine_impl/syncer_unittest.cc
@@ -288,7 +288,9 @@
debug_info_getter_.get(), model_type_registry_.get(),
true, // enable keystore encryption
false, // force enable pre-commit GU avoidance experiment
- "fake_invalidator_client_id");
+ "fake_invalidator_client_id",
+ /*short_poll_interval=*/base::TimeDelta::FromMinutes(30),
+ /*long_poll_interval=*/base::TimeDelta::FromMinutes(180));
syncer_ = new Syncer(&cancelation_signal_);
scheduler_ = std::make_unique<SyncSchedulerImpl>(
"TestSyncScheduler", BackoffDelayProvider::FromDefaults(),
diff --git a/components/sync/test/fake_server/fake_server.cc b/components/sync/test/fake_server/fake_server.cc
index e494b7e..a754fe6 100644
--- a/components/sync/test/fake_server/fake_server.cc
+++ b/components/sync/test/fake_server/fake_server.cc
@@ -21,8 +21,6 @@
#include "net/base/net_errors.h"
#include "net/http/http_status_code.h"
-using std::string;
-using std::vector;
using syncer::GetModelType;
using syncer::GetModelTypeFromSpecifics;
using syncer::LoopbackServer;
@@ -51,7 +49,7 @@
FakeServer::~FakeServer() {}
-void FakeServer::HandleCommand(const string& request,
+void FakeServer::HandleCommand(const std::string& request,
const base::Closure& completion_closure,
int* error_code,
int* response_code,
@@ -61,7 +59,7 @@
if (!network_enabled_) {
*error_code = net::ERR_FAILED;
*response_code = net::ERR_FAILED;
- *response = string();
+ *response = std::string();
completion_closure.Run();
return;
}
@@ -70,7 +68,7 @@
if (!authenticated_) {
*error_code = 0;
*response_code = net::HTTP_UNAUTHORIZED;
- *response = string();
+ *response = std::string();
completion_closure.Run();
return;
}
@@ -100,13 +98,10 @@
break;
// Don't care.
}
-
- int64_t response_code_large;
- syncer::HttpResponse::ServerConnectionCode server_status;
- base::ThreadRestrictions::SetIOAllowed(true);
- loopback_server_->HandleCommand(request, &server_status,
- &response_code_large, response);
- *response_code = static_cast<int>(response_code_large);
+ *response_code = SendToLoopbackServer(request, response);
+ if (*response_code == net::HTTP_OK) {
+ InjectClientCommand(response);
+ }
completion_closure.Run();
return;
}
@@ -116,6 +111,26 @@
completion_closure.Run();
}
+int FakeServer::SendToLoopbackServer(const std::string& request,
+ std::string* response) {
+ int64_t response_code;
+ syncer::HttpResponse::ServerConnectionCode server_status;
+ base::ThreadRestrictions::SetIOAllowed(true);
+ loopback_server_->HandleCommand(request, &server_status, &response_code,
+ response);
+ return static_cast<int>(response_code);
+}
+
+void FakeServer::InjectClientCommand(std::string* response) {
+ sync_pb::ClientToServerResponse response_proto;
+ bool parse_ok = response_proto.ParseFromString(*response);
+ DCHECK(parse_ok) << "Unable to parse-back the server response";
+ if (response_proto.error_code() == sync_pb::SyncEnums::SUCCESS) {
+ *response_proto.mutable_client_command() = client_command_;
+ *response = response_proto.SerializeAsString();
+ }
+}
+
bool FakeServer::GetLastCommitMessage(sync_pb::ClientToServerMessage* message) {
if (!last_commit_message_.has_commit())
return false;
@@ -184,6 +199,12 @@
authenticated_ = false;
}
+void FakeServer::SetClientCommand(
+ const sync_pb::ClientCommand& client_command) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ client_command_ = client_command;
+}
+
bool FakeServer::TriggerError(const sync_pb::SyncEnums::ErrorType& error_type) {
DCHECK(thread_checker_.CalledOnValidThread());
if (triggered_actionable_error_.get()) {
@@ -197,8 +218,8 @@
bool FakeServer::TriggerActionableError(
const sync_pb::SyncEnums::ErrorType& error_type,
- const string& description,
- const string& url,
+ const std::string& description,
+ const std::string& url,
const sync_pb::SyncEnums::Action& action) {
DCHECK(thread_checker_.CalledOnValidThread());
if (error_type_ != sync_pb::SyncEnums::SUCCESS) {
diff --git a/components/sync/test/fake_server/fake_server.h b/components/sync/test/fake_server/fake_server.h
index 1355e38a..ab14de8 100644
--- a/components/sync/test/fake_server/fake_server.h
+++ b/components/sync/test/fake_server/fake_server.h
@@ -23,6 +23,7 @@
#include "components/sync/engine_impl/loopback_server/persistent_bookmark_entity.h"
#include "components/sync/engine_impl/loopback_server/persistent_tombstone_entity.h"
#include "components/sync/engine_impl/loopback_server/persistent_unique_client_entity.h"
+#include "components/sync/protocol/client_commands.pb.h"
#include "components/sync/protocol/sync.pb.h"
namespace fake_server {
@@ -107,6 +108,9 @@
// authentication error.
void SetUnauthenticated();
+ // Sets the provided |client_command| in all subsequent successful requests.
+ void SetClientCommand(const sync_pb::ClientCommand& client_command);
+
// Force the server to return |error_type| in the error_code field of
// ClientToServerResponse on all subsequent sync requests. This method should
// not be called if TriggerActionableError has previously been called. Returns
@@ -164,6 +168,8 @@
private:
// Returns whether a triggered error should be sent for the request.
bool ShouldSendTriggeredError() const;
+ int SendToLoopbackServer(const std::string& request, std::string* response);
+ void InjectClientCommand(std::string* response);
// Whether the server should act as if incoming connections are properly
// authenticated.
@@ -191,6 +197,9 @@
bool alternate_triggered_errors_;
int request_counter_;
+ // Client command to be included in every response.
+ sync_pb::ClientCommand client_command_;
+
// FakeServer's observers.
base::ObserverList<Observer, true> observers_;