Commit 0e7f03fd authored by Paula Vidas's avatar Paula Vidas Committed by Commit Bot

[SyncInvalidations] Send GetUpdates after interested data types change.

This is to work around race conditions, between one device enabling a
data type (and marking it as "interesting") vs. another device
committing some new data for the type.

Bug: 1126014
Change-Id: I53cb8f8db17d0595a0ee2400fdc33a0299d0e1c9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2403640
Commit-Queue: Paula Vidas <paulavidas@google.com>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Cr-Commit-Position: refs/heads/master@{#807093}
parent b029a29f
......@@ -1466,7 +1466,9 @@ void ProfileSyncService::UpdateDataTypesForInvalidations() {
if (!sessions_invalidations_enabled_) {
types.Remove(SESSIONS);
}
invalidations_service->SetInterestedDataTypes(types);
invalidations_service->SetInterestedDataTypes(
types, base::BindRepeating(&ProfileSyncService::TriggerRefresh,
sync_enabled_weak_factory_.GetWeakPtr()));
}
SyncCycleSnapshot ProfileSyncService::GetLastCycleSnapshotForDebugging() const {
......
......@@ -1625,7 +1625,7 @@ TEST_F(ProfileSyncServiceTestWithSubscribeForSyncInvalidations,
ShouldSendDataTypesToSyncInvalidationsService) {
CreateService(ProfileSyncService::AUTO_START);
SignIn();
EXPECT_CALL(*sync_invalidations_service(), SetInterestedDataTypes(_));
EXPECT_CALL(*sync_invalidations_service(), SetInterestedDataTypes(_, _));
InitializeForFirstSync();
}
......@@ -1641,10 +1641,10 @@ TEST_F(ProfileSyncServiceTestWithSubscribeForSyncInvalidations,
InitializeForNthSync();
EXPECT_CALL(*sync_invalidations_service(),
SetInterestedDataTypes(ContainsSessions()));
SetInterestedDataTypes(ContainsSessions(), _));
service()->SetInvalidationsForSessionsEnabled(true);
EXPECT_CALL(*sync_invalidations_service(),
SetInterestedDataTypes(Not(ContainsSessions())));
SetInterestedDataTypes(Not(ContainsSessions()), _));
service()->SetInvalidationsForSessionsEnabled(false);
}
......
......@@ -9,9 +9,9 @@ static_library("invalidations") {
"fcm_handler.cc",
"fcm_handler.h",
"fcm_registration_token_observer.h",
"interested_data_types_handler.h",
"interested_data_types_manager.cc",
"interested_data_types_manager.h",
"interested_data_types_observer.h",
"invalidations_listener.h",
"switches.cc",
"switches.h",
......
......@@ -2,21 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SYNC_INVALIDATIONS_INTERESTED_DATA_TYPES_OBSERVER_H_
#define COMPONENTS_SYNC_INVALIDATIONS_INTERESTED_DATA_TYPES_OBSERVER_H_
#ifndef COMPONENTS_SYNC_INVALIDATIONS_INTERESTED_DATA_TYPES_HANDLER_H_
#define COMPONENTS_SYNC_INVALIDATIONS_INTERESTED_DATA_TYPES_HANDLER_H_
#include "base/observer_list.h"
#include "base/callback.h"
namespace syncer {
// An interface to observe changes on data types for which the device wants to
// receive invalidations.
class InterestedDataTypesObserver : public base::CheckedObserver {
// An interface to handle changes on data types for which the device wants to
// receive invalidations. Implementations are expected to call the provided
// callback when the list of data types is sent to the Sync server.
class InterestedDataTypesHandler {
public:
// Called on each change of interested data types.
virtual void OnInterestedDataTypesChanged() = 0;
virtual void OnInterestedDataTypesChanged(base::OnceClosure callback) = 0;
};
} // namespace syncer
#endif // COMPONENTS_SYNC_INVALIDATIONS_INTERESTED_DATA_TYPES_OBSERVER_H_
#endif // COMPONENTS_SYNC_INVALIDATIONS_INTERESTED_DATA_TYPES_HANDLER_H_
......@@ -4,22 +4,24 @@
#include "components/sync/invalidations/interested_data_types_manager.h"
#include "components/sync/invalidations/interested_data_types_observer.h"
#include <utility>
#include "base/bind.h"
#include "components/sync/base/model_type.h"
#include "components/sync/invalidations/interested_data_types_handler.h"
namespace syncer {
InterestedDataTypesManager::InterestedDataTypesManager() = default;
InterestedDataTypesManager::~InterestedDataTypesManager() = default;
void InterestedDataTypesManager::AddInterestedDataTypesObserver(
InterestedDataTypesObserver* observer) {
observers_.AddObserver(observer);
InterestedDataTypesManager::~InterestedDataTypesManager() {
DCHECK(!interested_data_types_handler_);
}
void InterestedDataTypesManager::RemoveInterestedDataTypesObserver(
InterestedDataTypesObserver* observer) {
observers_.RemoveObserver(observer);
void InterestedDataTypesManager::SetInterestedDataTypesHandler(
InterestedDataTypesHandler* handler) {
DCHECK(!interested_data_types_handler_ || !handler);
interested_data_types_handler_ = handler;
}
const ModelTypeSet& InterestedDataTypesManager::GetInterestedDataTypes() const {
......@@ -27,10 +29,13 @@ const ModelTypeSet& InterestedDataTypesManager::GetInterestedDataTypes() const {
}
void InterestedDataTypesManager::SetInterestedDataTypes(
const ModelTypeSet& data_types) {
const ModelTypeSet& data_types,
SyncInvalidationsService::InterestedDataTypesAppliedCallback callback) {
ModelTypeSet new_data_types = Difference(data_types, data_types_);
data_types_ = data_types;
for (InterestedDataTypesObserver& observer : observers_) {
observer.OnInterestedDataTypesChanged();
if (interested_data_types_handler_) {
interested_data_types_handler_->OnInterestedDataTypesChanged(
base::BindOnce(std::move(callback), new_data_types));
}
}
......
......@@ -5,11 +5,11 @@
#ifndef COMPONENTS_SYNC_INVALIDATIONS_INTERESTED_DATA_TYPES_MANAGER_H_
#define COMPONENTS_SYNC_INVALIDATIONS_INTERESTED_DATA_TYPES_MANAGER_H_
#include "base/observer_list.h"
#include "components/sync/base/model_type.h"
#include "components/sync/invalidations/sync_invalidations_service.h"
namespace syncer {
class InterestedDataTypesObserver;
class InterestedDataTypesHandler;
// Manages for which data types are invalidations sent to this device.
class InterestedDataTypesManager {
......@@ -20,20 +20,18 @@ class InterestedDataTypesManager {
InterestedDataTypesManager& operator=(const InterestedDataTypesManager&) =
delete;
// Add or remove a interested data types change observer. |observer| must not
// be nullptr.
void AddInterestedDataTypesObserver(InterestedDataTypesObserver* observer);
void RemoveInterestedDataTypesObserver(InterestedDataTypesObserver* observer);
// Set the interested data types change handler. |handler| can be nullptr to
// unregister any existing handler. There can be at most one handler.
void SetInterestedDataTypesHandler(InterestedDataTypesHandler* handler);
// Get or set the interested data types.
const ModelTypeSet& GetInterestedDataTypes() const;
void SetInterestedDataTypes(const ModelTypeSet& data_types);
void SetInterestedDataTypes(
const ModelTypeSet& data_types,
SyncInvalidationsService::InterestedDataTypesAppliedCallback callback);
private:
base::ObserverList<InterestedDataTypesObserver,
/*check_empty=*/true,
/*allow_reentrancy=*/false>
observers_;
InterestedDataTypesHandler* interested_data_types_handler_ = nullptr;
ModelTypeSet data_types_;
};
......
......@@ -4,16 +4,19 @@
#include "components/sync/invalidations/interested_data_types_manager.h"
#include "components/sync/invalidations/interested_data_types_observer.h"
#include "base/bind_helpers.h"
#include "components/sync/invalidations/interested_data_types_handler.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
namespace syncer {
namespace {
class MockDataTypesObserver : public InterestedDataTypesObserver {
class MockDataTypesHandler : public InterestedDataTypesHandler {
public:
MOCK_METHOD0(OnInterestedDataTypesChanged, void());
MOCK_METHOD1(OnInterestedDataTypesChanged, void(base::OnceClosure callback));
};
class InterestedDataTypesManagerTest : public testing::Test {
......@@ -22,20 +25,23 @@ class InterestedDataTypesManagerTest : public testing::Test {
};
TEST_F(InterestedDataTypesManagerTest, ShouldReturnGivenDataTypes) {
manager_.SetInterestedDataTypes(ModelTypeSet(BOOKMARKS, PREFERENCES));
manager_.SetInterestedDataTypes(ModelTypeSet(BOOKMARKS, PREFERENCES),
base::DoNothing());
EXPECT_EQ(ModelTypeSet(BOOKMARKS, PREFERENCES),
manager_.GetInterestedDataTypes());
manager_.SetInterestedDataTypes(ModelTypeSet(PREFERENCES, PASSWORDS));
manager_.SetInterestedDataTypes(ModelTypeSet(PREFERENCES, PASSWORDS),
base::DoNothing());
EXPECT_EQ(ModelTypeSet(PREFERENCES, PASSWORDS),
manager_.GetInterestedDataTypes());
}
TEST_F(InterestedDataTypesManagerTest, ShouldNotifyOnChange) {
testing::NiceMock<MockDataTypesObserver> observer;
manager_.AddInterestedDataTypesObserver(&observer);
EXPECT_CALL(observer, OnInterestedDataTypesChanged());
manager_.SetInterestedDataTypes(ModelTypeSet(PASSWORDS, AUTOFILL));
manager_.RemoveInterestedDataTypesObserver(&observer);
testing::NiceMock<MockDataTypesHandler> handler;
manager_.SetInterestedDataTypesHandler(&handler);
EXPECT_CALL(handler, OnInterestedDataTypesChanged(_));
manager_.SetInterestedDataTypes(ModelTypeSet(PASSWORDS, AUTOFILL),
base::DoNothing());
manager_.SetInterestedDataTypesHandler(nullptr);
}
} // namespace
......
......@@ -28,13 +28,13 @@ class MockSyncInvalidationsService : public SyncInvalidationsService {
(FCMRegistrationTokenObserver * observer));
MOCK_METHOD(const std::string&, GetFCMRegistrationToken, (), (const));
MOCK_METHOD(void,
AddInterestedDataTypesObserver,
(InterestedDataTypesObserver * observer));
MOCK_METHOD(void,
RemoveInterestedDataTypesObserver,
(InterestedDataTypesObserver * observer));
SetInterestedDataTypesHandler,
(InterestedDataTypesHandler * handler));
MOCK_METHOD(const ModelTypeSet&, GetInterestedDataTypes, (), (const));
MOCK_METHOD(void, SetInterestedDataTypes, (const ModelTypeSet& data_types));
MOCK_METHOD(void,
SetInterestedDataTypes,
(const ModelTypeSet& data_types,
InterestedDataTypesAppliedCallback callback));
};
} // namespace syncer
......
......@@ -7,13 +7,14 @@
#include <string>
#include "base/callback.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/sync/base/model_type.h"
namespace syncer {
class FCMRegistrationTokenObserver;
class InvalidationsListener;
class InterestedDataTypesObserver;
class InterestedDataTypesHandler;
// Service which is used to register with FCM. It is used to obtain an FCM token
// which is used to send invalidations from the server. The service also
......@@ -22,6 +23,11 @@ class InterestedDataTypesObserver;
// should be added.
class SyncInvalidationsService : public KeyedService {
public:
// Data types which are newly marked as interesting will be passed to the
// callback.
using InterestedDataTypesAppliedCallback =
base::OnceCallback<void(const ModelTypeSet&)>;
// Start or stop listening to invalidations.
virtual void SetActive(bool active) = 0;
......@@ -39,16 +45,16 @@ class SyncInvalidationsService : public KeyedService {
// received yet.
virtual const std::string& GetFCMRegistrationToken() const = 0;
// Add or remove an interested data types change observer. |observer| must not
// be nullptr.
virtual void AddInterestedDataTypesObserver(
InterestedDataTypesObserver* observer) = 0;
virtual void RemoveInterestedDataTypesObserver(
InterestedDataTypesObserver* observer) = 0;
// Set the interested data types change handler. |handler| can be nullptr to
// unregister any existing handler. There can be at most one handler.
virtual void SetInterestedDataTypesHandler(
InterestedDataTypesHandler* handler) = 0;
// Get or set for which data types should the device receive invalidations.
virtual const ModelTypeSet& GetInterestedDataTypes() const = 0;
virtual void SetInterestedDataTypes(const ModelTypeSet& data_types) = 0;
virtual void SetInterestedDataTypes(
const ModelTypeSet& data_types,
InterestedDataTypesAppliedCallback callback) = 0;
};
} // namespace syncer
......
......@@ -4,6 +4,8 @@
#include "components/sync/invalidations/sync_invalidations_service_impl.h"
#include <utility>
#include "components/sync/invalidations/fcm_handler.h"
namespace syncer {
......@@ -62,14 +64,9 @@ const std::string& SyncInvalidationsServiceImpl::GetFCMRegistrationToken()
return fcm_handler_->GetFCMRegistrationToken();
}
void SyncInvalidationsServiceImpl::AddInterestedDataTypesObserver(
InterestedDataTypesObserver* observer) {
data_types_manager_.AddInterestedDataTypesObserver(observer);
}
void SyncInvalidationsServiceImpl::RemoveInterestedDataTypesObserver(
InterestedDataTypesObserver* observer) {
data_types_manager_.RemoveInterestedDataTypesObserver(observer);
void SyncInvalidationsServiceImpl::SetInterestedDataTypesHandler(
InterestedDataTypesHandler* handler) {
data_types_manager_.SetInterestedDataTypesHandler(handler);
}
const ModelTypeSet& SyncInvalidationsServiceImpl::GetInterestedDataTypes()
......@@ -78,8 +75,9 @@ const ModelTypeSet& SyncInvalidationsServiceImpl::GetInterestedDataTypes()
}
void SyncInvalidationsServiceImpl::SetInterestedDataTypes(
const ModelTypeSet& data_types) {
data_types_manager_.SetInterestedDataTypes(data_types);
const ModelTypeSet& data_types,
InterestedDataTypesAppliedCallback callback) {
data_types_manager_.SetInterestedDataTypes(data_types, std::move(callback));
}
void SyncInvalidationsServiceImpl::Shutdown() {
......
......@@ -38,12 +38,12 @@ class SyncInvalidationsServiceImpl : public SyncInvalidationsService {
void AddTokenObserver(FCMRegistrationTokenObserver* observer) override;
void RemoveTokenObserver(FCMRegistrationTokenObserver* observer) override;
const std::string& GetFCMRegistrationToken() const override;
void AddInterestedDataTypesObserver(
InterestedDataTypesObserver* observer) override;
void RemoveInterestedDataTypesObserver(
InterestedDataTypesObserver* observer) override;
void SetInterestedDataTypesHandler(
InterestedDataTypesHandler* handler) override;
const ModelTypeSet& GetInterestedDataTypes() const override;
void SetInterestedDataTypes(const ModelTypeSet& data_types) override;
void SetInterestedDataTypes(
const ModelTypeSet& data_types,
InterestedDataTypesAppliedCallback callback) override;
// KeyedService overrides.
void Shutdown() override;
......
......@@ -225,7 +225,11 @@ LocalDeviceInfoProvider* DeviceInfoSyncBridge::GetLocalDeviceInfoProvider() {
return local_device_info_provider_.get();
}
void DeviceInfoSyncBridge::RefreshLocalDeviceInfo() {
void DeviceInfoSyncBridge::RefreshLocalDeviceInfo(base::OnceClosure callback) {
if (!callback.is_null()) {
device_info_synced_callback_list_.push_back(std::move(callback));
}
SendLocalData();
}
......@@ -318,6 +322,15 @@ base::Optional<ModelError> DeviceInfoSyncBridge::ApplySyncChanges(
batch->TakeMetadataChangesFrom(std::move(metadata_change_list));
CommitAndNotify(std::move(batch), has_changes);
DCHECK(!local_cache_guid_.empty());
if (!change_processor()->IsEntityUnsynced(local_cache_guid_)) {
for (base::OnceClosure& callback : device_info_synced_callback_list_) {
std::move(callback).Run();
}
device_info_synced_callback_list_.clear();
}
return base::nullopt;
}
......
......@@ -51,8 +51,9 @@ class DeviceInfoSyncBridge : public ModelTypeSyncBridge,
// Refresh local copy of device info in memory, and informs sync of the
// change. Used when the caller knows a property of local device info has
// changed (e.g. SharingInfo), and must be sync-ed to other devices as soon as
// possible, without waiting for the periodic commits.
void RefreshLocalDeviceInfo();
// possible, without waiting for the periodic commits. |callback| will be
// called when device info is synced.
void RefreshLocalDeviceInfo(base::OnceClosure callback);
// ModelTypeSyncBridge implementation.
void OnSyncStarting(const DataTypeActivationRequest& request) override;
......@@ -163,6 +164,8 @@ class DeviceInfoSyncBridge : public ModelTypeSyncBridge,
// Used to update our local device info once every pulse interval.
base::OneShotTimer pulse_timer_;
std::vector<base::OnceClosure> device_info_synced_callback_list_;
const std::unique_ptr<DeviceInfoPrefs> device_info_prefs_;
base::WeakPtrFactory<DeviceInfoSyncBridge> weak_ptr_factory_{this};
......
......@@ -12,6 +12,7 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind_test_util.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_clock.h"
#include "base/test/task_environment.h"
......@@ -502,7 +503,9 @@ class DeviceInfoSyncBridgeTest : public testing::Test,
void ForcePulse() { bridge()->ForcePulseForTest(); }
void RefreshLocalDeviceInfo() { bridge()->RefreshLocalDeviceInfo(); }
void RefreshLocalDeviceInfo() {
bridge()->RefreshLocalDeviceInfo(base::OnceClosure());
}
void CommitToStoreAndWait(std::unique_ptr<WriteBatch> batch) {
base::RunLoop loop;
......@@ -1307,6 +1310,24 @@ TEST_F(DeviceInfoSyncBridgeTest, ShouldSendInvalidationFields) {
InitializeAndMergeInitialData(SyncMode::kFull);
}
TEST_F(DeviceInfoSyncBridgeTest, ShouldNotifyWhenDeviceInfoIsSynced) {
InitializeAndMergeInitialData(SyncMode::kFull);
base::MockOnceClosure callback;
bridge()->RefreshLocalDeviceInfo(callback.Get());
std::string guid = local_device()->GetLocalDeviceInfo()->guid();
EXPECT_CALL(*processor(), IsEntityUnsynced(guid)).WillOnce(Return(true));
EXPECT_CALL(callback, Run()).Times(0);
bridge()->ApplySyncChanges(bridge()->CreateMetadataChangeList(),
EntityChangeList());
EXPECT_CALL(*processor(), IsEntityUnsynced(guid)).WillOnce(Return(false));
EXPECT_CALL(callback, Run());
bridge()->ApplySyncChanges(bridge()->CreateMetadataChangeList(),
EntityChangeList());
}
} // namespace
} // namespace syncer
......@@ -8,6 +8,7 @@
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
......@@ -37,8 +38,10 @@ class DeviceInfoSyncService : public KeyedService {
// Interface to refresh local copy of device info in memory, and informs sync
// of the change. Used when the caller knows a property of local device info
// has changed (e.g. SharingInfo), and must be sync-ed to other devices as
// soon as possible, without waiting for the periodic commits.
virtual void RefreshLocalDeviceInfo() = 0;
// soon as possible, without waiting for the periodic commits. |callback| will
// be called when device info is synced.
virtual void RefreshLocalDeviceInfo(
base::OnceClosure callback = base::OnceClosure()) = 0;
};
} // namespace syncer
......
......@@ -46,7 +46,7 @@ DeviceInfoSyncServiceImpl::DeviceInfoSyncServiceImpl(
if (sync_invalidations_service_) {
sync_invalidations_service_->AddTokenObserver(this);
sync_invalidations_service_->AddInterestedDataTypesObserver(this);
sync_invalidations_service_->SetInterestedDataTypesHandler(this);
}
}
......@@ -66,22 +66,24 @@ DeviceInfoSyncServiceImpl::GetControllerDelegate() {
return bridge_->change_processor()->GetControllerDelegate();
}
void DeviceInfoSyncServiceImpl::RefreshLocalDeviceInfo() {
bridge_->RefreshLocalDeviceInfo();
void DeviceInfoSyncServiceImpl::RefreshLocalDeviceInfo(
base::OnceClosure callback) {
bridge_->RefreshLocalDeviceInfo(std::move(callback));
}
void DeviceInfoSyncServiceImpl::OnFCMRegistrationTokenChanged() {
RefreshLocalDeviceInfo();
}
void DeviceInfoSyncServiceImpl::OnInterestedDataTypesChanged() {
RefreshLocalDeviceInfo();
void DeviceInfoSyncServiceImpl::OnInterestedDataTypesChanged(
base::OnceClosure callback) {
RefreshLocalDeviceInfo(std::move(callback));
}
void DeviceInfoSyncServiceImpl::Shutdown() {
if (sync_invalidations_service_) {
sync_invalidations_service_->RemoveTokenObserver(this);
sync_invalidations_service_->RemoveInterestedDataTypesObserver(this);
sync_invalidations_service_->SetInterestedDataTypesHandler(nullptr);
}
}
......
......@@ -9,7 +9,7 @@
#include <string>
#include "components/sync/invalidations/fcm_registration_token_observer.h"
#include "components/sync/invalidations/interested_data_types_observer.h"
#include "components/sync/invalidations/interested_data_types_handler.h"
#include "components/sync/model/model_type_store.h"
#include "components/sync_device_info/device_info_sync_service.h"
......@@ -23,7 +23,7 @@ class SyncInvalidationsService;
class DeviceInfoSyncServiceImpl : public DeviceInfoSyncService,
public FCMRegistrationTokenObserver,
public InterestedDataTypesObserver {
public InterestedDataTypesHandler {
public:
// |local_device_info_provider| must not be null.
// |device_info_prefs| must not be null.
......@@ -43,13 +43,14 @@ class DeviceInfoSyncServiceImpl : public DeviceInfoSyncService,
LocalDeviceInfoProvider* GetLocalDeviceInfoProvider() override;
DeviceInfoTracker* GetDeviceInfoTracker() override;
base::WeakPtr<ModelTypeControllerDelegate> GetControllerDelegate() override;
void RefreshLocalDeviceInfo() override;
void RefreshLocalDeviceInfo(
base::OnceClosure callback = base::OnceClosure()) override;
// FCMRegistrationTokenObserver implementation.
void OnFCMRegistrationTokenChanged() override;
// InterestedDataTypesObserver implementation.
void OnInterestedDataTypesChanged() override;
// InterestedDataTypesHandler implementation.
void OnInterestedDataTypesChanged(base::OnceClosure callback) override;
// KeyedService overrides.
void Shutdown() override;
......
......@@ -25,8 +25,12 @@ FakeDeviceInfoSyncService::GetControllerDelegate() {
return fake_model_type_controller_delegate_.GetWeakPtr();
}
void FakeDeviceInfoSyncService::RefreshLocalDeviceInfo() {
void FakeDeviceInfoSyncService::RefreshLocalDeviceInfo(
base::OnceClosure callback) {
refresh_local_device_info_count_++;
if (!callback.is_null()) {
std::move(callback).Run();
}
}
int FakeDeviceInfoSyncService::RefreshLocalDeviceInfoCount() {
......
......@@ -5,6 +5,7 @@
#ifndef COMPONENTS_SYNC_DEVICE_INFO_FAKE_DEVICE_INFO_SYNC_SERVICE_H_
#define COMPONENTS_SYNC_DEVICE_INFO_FAKE_DEVICE_INFO_SYNC_SERVICE_H_
#include "base/callback.h"
#include "components/sync/model/fake_model_type_controller_delegate.h"
#include "components/sync_device_info/device_info_sync_service.h"
#include "components/sync_device_info/fake_device_info_tracker.h"
......@@ -21,9 +22,9 @@ class FakeDeviceInfoSyncService : public DeviceInfoSyncService {
FakeLocalDeviceInfoProvider* GetLocalDeviceInfoProvider() override;
FakeDeviceInfoTracker* GetDeviceInfoTracker() override;
base::WeakPtr<ModelTypeControllerDelegate> GetControllerDelegate() override;
void RefreshLocalDeviceInfo() override;
void RefreshLocalDeviceInfo(base::OnceClosure callback) override;
// Returns number of times RefreshLocalDeviceInfo() has neen called.
// Returns number of times RefreshLocalDeviceInfo() has been called.
int RefreshLocalDeviceInfoCount();
private:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment