blob: 3ff6d1a99308b0e4a82591b66327e0e164be4701 [file] [log] [blame]
// 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 "chromeos/services/multidevice_setup/host_device_timestamp_manager_impl.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "base/time/clock.h"
#include "chromeos/components/multidevice/logging/logging.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
namespace chromeos {
namespace multidevice_setup {
namespace {
const int64_t kTimestampNotSet = 0;
} // namespace
// static
HostDeviceTimestampManagerImpl::Factory*
HostDeviceTimestampManagerImpl::Factory::test_factory_ = nullptr;
// static
HostDeviceTimestampManagerImpl::Factory*
HostDeviceTimestampManagerImpl::Factory::Get() {
if (test_factory_)
return test_factory_;
static base::NoDestructor<HostDeviceTimestampManagerImpl::Factory> factory;
return factory.get();
}
// static
void HostDeviceTimestampManagerImpl::Factory::SetFactoryForTesting(
Factory* test_factory) {
test_factory_ = test_factory;
}
HostDeviceTimestampManagerImpl::Factory::~Factory() = default;
std::unique_ptr<HostDeviceTimestampManager>
HostDeviceTimestampManagerImpl::Factory::BuildInstance(
HostStatusProvider* host_status_provider,
PrefService* pref_service,
base::Clock* clock) {
return base::WrapUnique(new HostDeviceTimestampManagerImpl(
host_status_provider, pref_service, clock));
}
// static
const char
HostDeviceTimestampManagerImpl::kWasHostSetFromThisChromebookPrefName[] =
"multidevice_setup.was_host_set_from_this_chromebook";
// static
const char HostDeviceTimestampManagerImpl::kSetupFlowCompletedPrefName[] =
"multidevice_setup.setup_flow_completed";
// static
const char
HostDeviceTimestampManagerImpl::kHostVerifiedUpdateReceivedPrefName[] =
"multidevice_setup.host_verified_update_received";
// static
void HostDeviceTimestampManagerImpl::RegisterPrefs(
PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(kWasHostSetFromThisChromebookPrefName, false);
registry->RegisterInt64Pref(kSetupFlowCompletedPrefName, kTimestampNotSet);
registry->RegisterInt64Pref(kHostVerifiedUpdateReceivedPrefName,
kTimestampNotSet);
}
HostDeviceTimestampManagerImpl::~HostDeviceTimestampManagerImpl() {
host_status_provider_->RemoveObserver(this);
}
HostDeviceTimestampManagerImpl::HostDeviceTimestampManagerImpl(
HostStatusProvider* host_status_provider,
PrefService* pref_service,
base::Clock* clock)
: host_status_provider_(host_status_provider),
pref_service_(pref_service),
clock_(clock) {
host_status_provider_->AddObserver(this);
}
bool HostDeviceTimestampManagerImpl::WasHostSetFromThisChromebook() {
return pref_service_->GetBoolean(kWasHostSetFromThisChromebookPrefName);
}
base::Optional<base::Time>
HostDeviceTimestampManagerImpl::GetLatestSetupFlowCompletionTimestamp() {
if (pref_service_->GetInt64(kSetupFlowCompletedPrefName) == kTimestampNotSet)
return base::nullopt;
return base::Time::FromJavaTime(
pref_service_->GetInt64(kSetupFlowCompletedPrefName));
}
base::Optional<base::Time>
HostDeviceTimestampManagerImpl::GetLatestVerificationTimestamp() {
if (pref_service_->GetInt64(kHostVerifiedUpdateReceivedPrefName) ==
kTimestampNotSet)
return base::nullopt;
return base::Time::FromJavaTime(
pref_service_->GetInt64(kHostVerifiedUpdateReceivedPrefName));
}
void HostDeviceTimestampManagerImpl::OnHostStatusChange(
const HostStatusProvider::HostStatusWithDevice& host_status_with_device) {
// Check if setup flow was completed on this Chromebook. Note that it suffices
// to use a host status update with the status
// kHostSetLocallyButWaitingForBackendConfirmation as a proxy for completing
// setup flow because the Chromebook sets a host locally (i.e. enters this
// state) exactly when it successfully completes the flow. Note that this is
// equivalent to a host being set on the Chromebook.
if (host_status_with_device.host_status() ==
mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation) {
pref_service_->SetInt64(kSetupFlowCompletedPrefName,
clock_->Now().ToJavaTime());
pref_service_->SetBoolean(kWasHostSetFromThisChromebookPrefName, true);
PA_LOG(VERBOSE) << "HostDeviceTimestampManagerImpl::OnHostStatusChange(): "
<< "Setup flow successfully completed. Recording timestamp "
<< pref_service_->GetInt64(kSetupFlowCompletedPrefName)
<< ".";
}
// Check if a host has been verified.
if (host_status_with_device.host_status() ==
mojom::HostStatus::kHostVerified) {
pref_service_->SetInt64(kHostVerifiedUpdateReceivedPrefName,
clock_->Now().ToJavaTime());
PA_LOG(VERBOSE) << "HostDeviceTimestampManagerImpl::OnHostStatusChange(): "
<< "New host verified. Recording timestamp "
<< pref_service_->GetInt64(
kHostVerifiedUpdateReceivedPrefName)
<< ".";
}
// If there is no host set, set the "was host set form this Chromebook" bit to
// false.
if (host_status_with_device.host_status() ==
mojom::HostStatus::kNoEligibleHosts ||
host_status_with_device.host_status() ==
mojom::HostStatus::kEligibleHostExistsButNoHostSet) {
pref_service_->SetBoolean(kWasHostSetFromThisChromebookPrefName, false);
}
}
} // namespace multidevice_setup
} // namespace chromeos