active_devices_provider_impl.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <map>
  5. #include <memory>
  6. #include <utility>
  7. #include <vector>
  8. #include "base/containers/cxx20_erase.h"
  9. #include "base/feature_list.h"
  10. #include "base/metrics/field_trial_params.h"
  11. #include "base/ranges/algorithm.h"
  12. #include "components/browser_sync/active_devices_provider_impl.h"
  13. #include "components/browser_sync/browser_sync_switches.h"
  14. #include "components/sync/base/model_type.h"
  15. namespace browser_sync {
  16. ActiveDevicesProviderImpl::ActiveDevicesProviderImpl(
  17. syncer::DeviceInfoTracker* device_info_tracker,
  18. base::Clock* clock)
  19. : device_info_tracker_(device_info_tracker), clock_(clock) {
  20. DCHECK(device_info_tracker_);
  21. device_info_tracker_->AddObserver(this);
  22. }
  23. ActiveDevicesProviderImpl::~ActiveDevicesProviderImpl() {
  24. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  25. DCHECK(callback_.is_null());
  26. device_info_tracker_->RemoveObserver(this);
  27. }
  28. syncer::ActiveDevicesInvalidationInfo
  29. ActiveDevicesProviderImpl::CalculateInvalidationInfo(
  30. const std::string& local_cache_guid) const {
  31. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  32. const std::vector<std::unique_ptr<syncer::DeviceInfo>> active_devices =
  33. GetActiveDevicesSortedByUpdateTime();
  34. if (active_devices.empty()) {
  35. // This may happen if the engine is not initialized yet. In other cases,
  36. // |active_devices| must contain at least the local device.
  37. return syncer::ActiveDevicesInvalidationInfo::CreateUninitialized();
  38. }
  39. std::vector<std::string> all_fcm_registration_tokens;
  40. // List of interested data types for all other clients.
  41. syncer::ModelTypeSet all_interested_data_types;
  42. // FCM registration tokens with corresponding interested data types for all
  43. // the clients with enabled sync standalone invalidations.
  44. std::map<std::string, syncer::ModelTypeSet>
  45. fcm_token_and_interested_data_types;
  46. for (const std::unique_ptr<syncer::DeviceInfo>& device : active_devices) {
  47. if (!local_cache_guid.empty() && device->guid() == local_cache_guid) {
  48. continue;
  49. }
  50. all_interested_data_types.PutAll(device->interested_data_types());
  51. if (!device->fcm_registration_token().empty()) {
  52. // If there is a duplicate FCM registration token, use the latest one. To
  53. // achieve this, rely on sorted |active_devices| by update time. Two
  54. // DeviceInfo entities can have the same FCM registration token if the
  55. // sync engine was reset without signout.
  56. fcm_token_and_interested_data_types[device->fcm_registration_token()] =
  57. device->interested_data_types();
  58. if (base::FeatureList::IsEnabled(
  59. switches::kSyncUseFCMRegistrationTokensList)) {
  60. all_fcm_registration_tokens.push_back(device->fcm_registration_token());
  61. }
  62. }
  63. }
  64. // Do not send tokens if the list of active devices is huge. This is similar
  65. // to the case when the client doesn't know about other devices, so return an
  66. // empty list. Otherwise the client would return only a part of all active
  67. // clients and other clients might miss an invalidation.
  68. if (all_fcm_registration_tokens.size() >
  69. static_cast<size_t>(
  70. switches::kSyncFCMRegistrationTokensListMaxSize.Get())) {
  71. all_fcm_registration_tokens.clear();
  72. }
  73. return syncer::ActiveDevicesInvalidationInfo::Create(
  74. std::move(all_fcm_registration_tokens), all_interested_data_types,
  75. std::move(fcm_token_and_interested_data_types));
  76. }
  77. void ActiveDevicesProviderImpl::SetActiveDevicesChangedCallback(
  78. ActiveDevicesChangedCallback callback) {
  79. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  80. // The |callback_| must not be replaced with another non-null |callback|.
  81. DCHECK(callback_.is_null() || callback.is_null());
  82. callback_ = std::move(callback);
  83. }
  84. void ActiveDevicesProviderImpl::OnDeviceInfoChange() {
  85. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  86. if (callback_) {
  87. callback_.Run();
  88. }
  89. }
  90. std::vector<std::unique_ptr<syncer::DeviceInfo>>
  91. ActiveDevicesProviderImpl::GetActiveDevicesSortedByUpdateTime() const {
  92. std::vector<std::unique_ptr<syncer::DeviceInfo>> all_devices =
  93. device_info_tracker_->GetAllDeviceInfo();
  94. base::ranges::sort(
  95. all_devices, [](const std::unique_ptr<syncer::DeviceInfo>& left_device,
  96. const std::unique_ptr<syncer::DeviceInfo>& right_device) {
  97. return left_device->last_updated_timestamp() <
  98. right_device->last_updated_timestamp();
  99. });
  100. if (!base::FeatureList::IsEnabled(
  101. switches::kSyncFilterOutInactiveDevicesForSingleClient)) {
  102. return all_devices;
  103. }
  104. base::EraseIf(
  105. all_devices, [this](const std::unique_ptr<syncer::DeviceInfo>& device) {
  106. const base::Time expected_expiration_time =
  107. device->last_updated_timestamp() + device->pulse_interval() +
  108. switches::kSyncActiveDeviceMargin.Get();
  109. // If the device's expiration time hasn't been reached, then
  110. // it is considered active device.
  111. return expected_expiration_time <= clock_->Now();
  112. });
  113. return all_devices;
  114. }
  115. } // namespace browser_sync