blob: 86c3d6a81e430e42b5ab5d67ef9391f75cfd7a1c [file] [log] [blame]
// Copyright 2017 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 "chrome/browser/chromeos/cryptauth/chrome_cryptauth_service.h"
#include "base/guid.h"
#include "base/linux_util.h"
#include "base/memory/ptr_util.h"
#include "base/system/sys_info.h"
#include "base/time/default_clock.h"
#include "base/version.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/chromeos/cryptauth/cryptauth_device_id_provider_impl.h"
#include "chrome/browser/chromeos/cryptauth/gcm_device_info_provider_impl.h"
#include "chrome/browser/gcm/gcm_profile_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/common/pref_names.h"
#include "chromeos/components/multidevice/logging/logging.h"
#include "chromeos/components/multidevice/secure_message_delegate_impl.h"
#include "chromeos/services/device_sync/cryptauth_client.h"
#include "chromeos/services/device_sync/cryptauth_client_impl.h"
#include "chromeos/services/device_sync/cryptauth_device_manager_impl.h"
#include "chromeos/services/device_sync/cryptauth_enroller.h"
#include "chromeos/services/device_sync/cryptauth_enroller_impl.h"
#include "chromeos/services/device_sync/cryptauth_enrollment_manager_impl.h"
#include "chromeos/services/device_sync/cryptauth_gcm_manager_impl.h"
#include "chromeos/services/device_sync/proto/cryptauth_api.pb.h"
#include "chromeos/services/device_sync/proto/device_classifier_util.h"
#include "chromeos/services/multidevice_setup/public/cpp/prefs.h"
#include "components/gcm_driver/gcm_profile_service.h"
#include "components/prefs/pref_service.h"
#include "components/translate/core/browser/translate_download_manager.h"
#include "components/version_info/version_info.h"
#include "ui/gfx/geometry/rect.h"
namespace chromeos {
namespace {
std::unique_ptr<device_sync::CryptAuthClientFactory>
CreateCryptAuthClientFactoryImpl(Profile* profile) {
return std::make_unique<device_sync::CryptAuthClientFactoryImpl>(
IdentityManagerFactory::GetForProfile(profile),
profile->GetURLLoaderFactory(),
device_sync::device_classifier_util::GetDeviceClassifier());
}
class CryptAuthEnrollerFactoryImpl
: public device_sync::CryptAuthEnrollerFactory {
public:
explicit CryptAuthEnrollerFactoryImpl(
device_sync::CryptAuthClientFactory* client_factory)
: client_factory_(client_factory) {}
std::unique_ptr<device_sync::CryptAuthEnroller> CreateInstance() override {
return std::make_unique<device_sync::CryptAuthEnrollerImpl>(
client_factory_,
multidevice::SecureMessageDelegateImpl::Factory::NewInstance());
}
private:
device_sync::CryptAuthClientFactory* client_factory_;
};
} // namespace
// static
std::unique_ptr<ChromeCryptAuthService> ChromeCryptAuthService::Create(
Profile* profile) {
std::unique_ptr<device_sync::CryptAuthClientFactory> client_factory =
CreateCryptAuthClientFactoryImpl(profile);
std::unique_ptr<device_sync::CryptAuthGCMManager> gcm_manager =
device_sync::CryptAuthGCMManagerImpl::Factory::NewInstance(
gcm::GCMProfileServiceFactory::GetForProfile(profile)->driver(),
profile->GetPrefs());
std::unique_ptr<device_sync::CryptAuthDeviceManager> device_manager =
device_sync::CryptAuthDeviceManagerImpl::Factory::NewInstance(
base::DefaultClock::GetInstance(), client_factory.get(),
gcm_manager.get(), profile->GetPrefs());
std::unique_ptr<device_sync::CryptAuthEnrollmentManager> enrollment_manager =
device_sync::CryptAuthEnrollmentManagerImpl::Factory::NewInstance(
base::DefaultClock::GetInstance(),
std::make_unique<CryptAuthEnrollerFactoryImpl>(client_factory.get()),
multidevice::SecureMessageDelegateImpl::Factory::NewInstance(),
GcmDeviceInfoProviderImpl::GetInstance()->GetGcmDeviceInfo(),
gcm_manager.get(), profile->GetPrefs());
// Note: ChromeCryptAuthServiceFactory DependsOn(IdentityManagerFactory),
// so |identity_manager| is guaranteed to outlast this service.
identity::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile);
return base::WrapUnique(new ChromeCryptAuthService(
std::move(client_factory), std::move(gcm_manager),
std::move(device_manager), std::move(enrollment_manager), profile,
identity_manager));
}
ChromeCryptAuthService::ChromeCryptAuthService(
std::unique_ptr<device_sync::CryptAuthClientFactory> client_factory,
std::unique_ptr<device_sync::CryptAuthGCMManager> gcm_manager,
std::unique_ptr<device_sync::CryptAuthDeviceManager> device_manager,
std::unique_ptr<device_sync::CryptAuthEnrollmentManager> enrollment_manager,
Profile* profile,
identity::IdentityManager* identity_manager)
: KeyedService(),
cryptauth::CryptAuthService(),
client_factory_(std::move(client_factory)),
gcm_manager_(std::move(gcm_manager)),
enrollment_manager_(std::move(enrollment_manager)),
device_manager_(std::move(device_manager)),
profile_(profile),
identity_manager_(identity_manager),
weak_ptr_factory_(this) {
gcm_manager_->StartListening();
registrar_.Init(profile_->GetPrefs());
registrar_.Add(multidevice_setup::kSmartLockAllowedPrefName,
base::Bind(&ChromeCryptAuthService::OnPrefsChanged,
weak_ptr_factory_.GetWeakPtr()));
registrar_.Add(multidevice_setup::kInstantTetheringAllowedPrefName,
base::Bind(&ChromeCryptAuthService::OnPrefsChanged,
weak_ptr_factory_.GetWeakPtr()));
if (!identity_manager_->HasPrimaryAccountWithRefreshToken()) {
PA_LOG(VERBOSE) << "Primary account with refresh token not yet available; "
<< "waiting before starting CryptAuth managers.";
identity_manager_->AddObserver(this);
return;
}
// Profile is authenticated and there is a refresh token available for the
// authenticated account id.
PerformEnrollmentAndDeviceSyncIfPossible();
}
ChromeCryptAuthService::~ChromeCryptAuthService() {}
void ChromeCryptAuthService::Shutdown() {
identity_manager_->RemoveObserver(this);
enrollment_manager_.reset();
device_manager_.reset();
gcm_manager_.reset();
}
device_sync::CryptAuthDeviceManager*
ChromeCryptAuthService::GetCryptAuthDeviceManager() {
return device_manager_.get();
}
device_sync::CryptAuthEnrollmentManager*
ChromeCryptAuthService::GetCryptAuthEnrollmentManager() {
return enrollment_manager_.get();
}
cryptauth::DeviceClassifier ChromeCryptAuthService::GetDeviceClassifier() {
return device_sync::device_classifier_util::GetDeviceClassifier();
}
std::string ChromeCryptAuthService::GetAccountId() {
return identity_manager_->GetPrimaryAccountId();
}
std::unique_ptr<device_sync::CryptAuthClientFactory>
ChromeCryptAuthService::CreateCryptAuthClientFactory() {
return CreateCryptAuthClientFactoryImpl(profile_);
}
void ChromeCryptAuthService::OnEnrollmentFinished(bool success) {
if (success)
device_manager_->Start();
else
PA_LOG(ERROR) << "CryptAuth enrollment failed. Device manager was not "
<< " started.";
enrollment_manager_->RemoveObserver(this);
}
void ChromeCryptAuthService::OnAuthenticationStateChanged() {
if (!identity_manager_->HasPrimaryAccountWithRefreshToken()) {
PA_LOG(VERBOSE) << "Primary account with refresh token not yet available; "
<< "waiting before starting CryptAuth managers.";
return;
}
identity_manager_->RemoveObserver(this);
PerformEnrollmentAndDeviceSyncIfPossible();
}
void ChromeCryptAuthService::OnPrimaryAccountSet(
const AccountInfo& primary_account_info) {
OnAuthenticationStateChanged();
}
void ChromeCryptAuthService::OnRefreshTokenUpdatedForAccount(
const AccountInfo& account_info) {
OnAuthenticationStateChanged();
}
void ChromeCryptAuthService::PerformEnrollmentAndDeviceSyncIfPossible() {
DCHECK(identity_manager_->HasPrimaryAccountWithRefreshToken());
// CryptAuth enrollment is allowed only if at least one multi-device feature
// is enabled. This ensures that we do not unnecessarily register devices on
// the CryptAuth back-end when the registration would never actually be used.
if (!multidevice_setup::AreAnyMultiDeviceFeaturesAllowed(
profile_->GetPrefs())) {
PA_LOG(VERBOSE) << "CryptAuth enrollment is disabled by enterprise policy.";
return;
}
if (enrollment_manager_->IsEnrollmentValid()) {
device_manager_->Start();
} else {
// If enrollment is not valid, wait for the new enrollment attempt to finish
// before starting CryptAuthDeviceManager. See OnEnrollmentFinished(),
enrollment_manager_->AddObserver(this);
}
// Even if enrollment was valid, CryptAuthEnrollmentManager must be started in
// order to schedule the next enrollment attempt.
enrollment_manager_->Start();
}
void ChromeCryptAuthService::OnPrefsChanged() {
// Note: We only start the CryptAuth services if a feature was toggled on. In
// the inverse case, we simply leave the services running until the user logs
// off.
PerformEnrollmentAndDeviceSyncIfPossible();
}
} // namespace chromeos