123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- // Copyright 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 "ash/services/multidevice_setup/grandfathered_easy_unlock_host_disabler.h"
- #include "ash/components/multidevice/logging/logging.h"
- #include "ash/constants/ash_features.h"
- #include "ash/services/device_sync/public/cpp/device_sync_client.h"
- #include "base/bind.h"
- #include "base/memory/ptr_util.h"
- #include "base/timer/timer.h"
- #include "components/prefs/pref_registry_simple.h"
- #include "components/prefs/pref_service.h"
- namespace ash {
- namespace multidevice_setup {
- namespace {
- // Name of the prefs that stores the legacy device ID and Instance ID of the
- // device which still potentially needs to have kSmartLockHost disabled on it.
- const char kEasyUnlockHostIdToDisablePrefName[] =
- "multidevice_setup.easy_unlock_host_id_to_disable";
- const char kEasyUnlockHostInstanceIdToDisablePrefName[] =
- "multidevice_setup.easy_unlock_host_instance_id_to_disable";
- const char kNoDevice[] = "";
- // The number of minutes to wait before retrying a failed attempt.
- const int kNumMinutesBetweenRetries = 5;
- bool IsEasyUnlockHost(const multidevice::RemoteDeviceRef& device) {
- return device.GetSoftwareFeatureState(
- multidevice::SoftwareFeature::kSmartLockHost) ==
- multidevice::SoftwareFeatureState::kEnabled;
- }
- } // namespace
- // static
- GrandfatheredEasyUnlockHostDisabler::Factory*
- GrandfatheredEasyUnlockHostDisabler::Factory::test_factory_ = nullptr;
- // static
- std::unique_ptr<GrandfatheredEasyUnlockHostDisabler>
- GrandfatheredEasyUnlockHostDisabler::Factory::Create(
- HostBackendDelegate* host_backend_delegate,
- device_sync::DeviceSyncClient* device_sync_client,
- PrefService* pref_service,
- std::unique_ptr<base::OneShotTimer> timer) {
- if (test_factory_) {
- return test_factory_->CreateInstance(host_backend_delegate,
- device_sync_client, pref_service,
- std::move(timer));
- }
- return base::WrapUnique(new GrandfatheredEasyUnlockHostDisabler(
- host_backend_delegate, device_sync_client, pref_service,
- std::move(timer)));
- }
- // static
- void GrandfatheredEasyUnlockHostDisabler::Factory::SetFactoryForTesting(
- Factory* test_factory) {
- test_factory_ = test_factory;
- }
- GrandfatheredEasyUnlockHostDisabler::Factory::~Factory() = default;
- // static
- void GrandfatheredEasyUnlockHostDisabler::RegisterPrefs(
- PrefRegistrySimple* registry) {
- registry->RegisterStringPref(kEasyUnlockHostIdToDisablePrefName, kNoDevice);
- registry->RegisterStringPref(kEasyUnlockHostInstanceIdToDisablePrefName,
- kNoDevice);
- }
- GrandfatheredEasyUnlockHostDisabler::~GrandfatheredEasyUnlockHostDisabler() {
- host_backend_delegate_->RemoveObserver(this);
- }
- GrandfatheredEasyUnlockHostDisabler::GrandfatheredEasyUnlockHostDisabler(
- HostBackendDelegate* host_backend_delegate,
- device_sync::DeviceSyncClient* device_sync_client,
- PrefService* pref_service,
- std::unique_ptr<base::OneShotTimer> timer)
- : host_backend_delegate_(host_backend_delegate),
- device_sync_client_(device_sync_client),
- pref_service_(pref_service),
- timer_(std::move(timer)),
- current_better_together_host_(
- host_backend_delegate_->GetMultiDeviceHostFromBackend()) {
- host_backend_delegate_->AddObserver(this);
- // There might be a device stored in the pref waiting for kSmartLockHost to
- // be disabled.
- DisableEasyUnlockHostIfNecessary();
- }
- void GrandfatheredEasyUnlockHostDisabler::OnHostChangedOnBackend() {
- // kSmartLockHost possibly needs to be disabled on the previous
- // BetterTogether host.
- SetPotentialEasyUnlockHostToDisable(current_better_together_host_);
- // Retrieve the new BetterTogether host.
- current_better_together_host_ =
- host_backend_delegate_->GetMultiDeviceHostFromBackend();
- DisableEasyUnlockHostIfNecessary();
- }
- void GrandfatheredEasyUnlockHostDisabler::DisableEasyUnlockHostIfNecessary() {
- timer_->Stop();
- absl::optional<multidevice::RemoteDeviceRef> host_to_disable =
- GetEasyUnlockHostToDisable();
- if (!host_to_disable)
- return;
- PA_LOG(VERBOSE) << "Attempting to disable kSmartLockHost on device "
- << host_to_disable->GetInstanceIdDeviceIdForLogs();
- if (features::ShouldUseV1DeviceSync()) {
- // Even if the host has a non-trivial Instance ID, we still invoke the v1
- // DeviceSync RPC to set the feature state. This ensures that GmsCore will
- // be notified of the change regardless of what version of DeviceSync it is
- // running. The v1 and v2 RPCs to change feature states ultimately update
- // the same backend database entry. Note: The RemoteDeviceProvider
- // guarantees that every device will have a public key while v1 DeviceSync
- // is enabled.
- DCHECK(!host_to_disable->public_key().empty());
- device_sync_client_->SetSoftwareFeatureState(
- host_to_disable->public_key(),
- multidevice::SoftwareFeature::kSmartLockHost, false /* enabled */,
- false /* is_exclusive */,
- base::BindOnce(
- &GrandfatheredEasyUnlockHostDisabler::OnDisableEasyUnlockHostResult,
- weak_ptr_factory_.GetWeakPtr(), *host_to_disable));
- } else {
- DCHECK(!host_to_disable->instance_id().empty());
- device_sync_client_->SetFeatureStatus(
- host_to_disable->instance_id(),
- multidevice::SoftwareFeature::kSmartLockHost,
- device_sync::FeatureStatusChange::kDisable,
- base::BindOnce(
- &GrandfatheredEasyUnlockHostDisabler::OnDisableEasyUnlockHostResult,
- weak_ptr_factory_.GetWeakPtr(), *host_to_disable));
- }
- }
- void GrandfatheredEasyUnlockHostDisabler::OnDisableEasyUnlockHostResult(
- multidevice::RemoteDeviceRef device,
- device_sync::mojom::NetworkRequestResult result_code) {
- bool success =
- result_code == device_sync::mojom::NetworkRequestResult::kSuccess;
- if (success) {
- PA_LOG(VERBOSE) << "Successfully disabled kSmartLockHost on device "
- << device.GetInstanceIdDeviceIdForLogs();
- } else {
- PA_LOG(WARNING) << "Failed to disable kSmartLockHost on device "
- << device.GetInstanceIdDeviceIdForLogs()
- << ", Error code: " << result_code;
- }
- // Return if the EasyUnlock host to disable changed between calls to
- // DisableEasyUnlockHostIfNecessary() and OnDisableEasyUnlockHostResult().
- if (device != GetEasyUnlockHostToDisable())
- return;
- if (success) {
- SetPotentialEasyUnlockHostToDisable(absl::nullopt);
- return;
- }
- PA_LOG(WARNING) << "Retrying in " << kNumMinutesBetweenRetries
- << " minutes if necessary.";
- timer_->Start(FROM_HERE, base::Minutes(kNumMinutesBetweenRetries),
- base::BindOnce(&GrandfatheredEasyUnlockHostDisabler::
- DisableEasyUnlockHostIfNecessary,
- base::Unretained(this)));
- }
- void GrandfatheredEasyUnlockHostDisabler::SetPotentialEasyUnlockHostToDisable(
- absl::optional<multidevice::RemoteDeviceRef> device) {
- pref_service_->SetString(kEasyUnlockHostIdToDisablePrefName,
- !device || device->GetDeviceId().empty()
- ? kNoDevice
- : device->GetDeviceId());
- pref_service_->SetString(kEasyUnlockHostInstanceIdToDisablePrefName,
- !device || device->instance_id().empty()
- ? kNoDevice
- : device->instance_id());
- }
- absl::optional<multidevice::RemoteDeviceRef>
- GrandfatheredEasyUnlockHostDisabler::GetEasyUnlockHostToDisable() {
- std::string legacy_device_id =
- pref_service_->GetString(kEasyUnlockHostIdToDisablePrefName);
- std::string instance_id =
- pref_service_->GetString(kEasyUnlockHostInstanceIdToDisablePrefName);
- if (legacy_device_id == kNoDevice && instance_id == kNoDevice)
- return absl::nullopt;
- multidevice::RemoteDeviceRefList synced_devices =
- device_sync_client_->GetSyncedDevices();
- auto it = std::find_if(
- synced_devices.begin(), synced_devices.end(),
- [&legacy_device_id, &instance_id](const auto& remote_device) {
- return (legacy_device_id != kNoDevice &&
- remote_device.GetDeviceId() == legacy_device_id) ||
- (instance_id != kNoDevice &&
- remote_device.instance_id() == instance_id);
- });
- // The device does not need to have kSmartLockHost disabled if any of the
- // following are true:
- // - the device is not in the list of synced devices anymore,
- // - the device is not the current EasyUnlock host, or
- // - the device is the BetterTogether host.
- if (it == synced_devices.end() || !IsEasyUnlockHost(*it) ||
- *it == current_better_together_host_) {
- SetPotentialEasyUnlockHostToDisable(absl::nullopt);
- return absl::nullopt;
- }
- return *it;
- }
- } // namespace multidevice_setup
- } // namespace ash
|