blob: cf4abce8683a04c346c39b70e581df7e2cf5a073 [file] [log] [blame]
// Copyright 2016 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/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h"
#include "base/command_line.h"
#include "base/hash/sha1.h"
#include "base/i18n/timezone.h"
#include "chrome/browser/chromeos/arc/arc_support_host.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.h"
#include "chrome/browser/chromeos/login/screens/arc_terms_of_service_screen.h"
#include "chrome/browser/chromeos/login/ui/login_display_host.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/consent_auditor/consent_auditor_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "components/arc/arc_prefs.h"
#include "components/consent_auditor/consent_auditor.h"
#include "components/login/localized_values_builder.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "services/identity/public/cpp/identity_manager.h"
#include "ui/base/l10n/l10n_util.h"
using ArcBackupAndRestoreConsent =
sync_pb::UserConsentTypes::ArcBackupAndRestoreConsent;
using ArcGoogleLocationServiceConsent =
sync_pb::UserConsentTypes::ArcGoogleLocationServiceConsent;
using ArcPlayTermsOfServiceConsent =
sync_pb::UserConsentTypes::ArcPlayTermsOfServiceConsent;
using sync_pb::UserConsentTypes;
namespace chromeos {
constexpr StaticOobeScreenId ArcTermsOfServiceScreenView::kScreenId;
ArcTermsOfServiceScreenHandler::ArcTermsOfServiceScreenHandler(
JSCallsContainer* js_calls_container)
: BaseScreenHandler(kScreenId, js_calls_container),
is_child_account_(
user_manager::UserManager::Get()->IsLoggedInAsChildUser()) {
set_user_acted_method_path("login.ArcTermsOfServiceScreen.userActed");
}
ArcTermsOfServiceScreenHandler::~ArcTermsOfServiceScreenHandler() {
OobeUI* oobe_ui = GetOobeUI();
if (oobe_ui)
oobe_ui->RemoveObserver(this);
chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
this, FROM_HERE);
system::TimezoneSettings::GetInstance()->RemoveObserver(this);
for (auto& observer : observer_list_)
observer.OnViewDestroyed(this);
}
void ArcTermsOfServiceScreenHandler::RegisterMessages() {
BaseScreenHandler::RegisterMessages();
AddCallback("arcTermsOfServiceSkip",
&ArcTermsOfServiceScreenHandler::HandleSkip);
AddCallback("arcTermsOfServiceAccept",
&ArcTermsOfServiceScreenHandler::HandleAccept);
}
void ArcTermsOfServiceScreenHandler::MaybeLoadPlayStoreToS(
bool ignore_network_state) {
const chromeos::NetworkState* default_network =
chromeos::NetworkHandler::Get()
->network_state_handler()
->DefaultNetwork();
if (!ignore_network_state && !default_network)
return;
const std::string country_code = base::CountryCodeForCurrentTimezone();
CallJS("login.ArcTermsOfServiceScreen.loadPlayStoreToS", country_code);
}
void ArcTermsOfServiceScreenHandler::OnCurrentScreenChanged(
OobeScreenId current_screen,
OobeScreenId new_screen) {
if (new_screen != GaiaView::kScreenId)
return;
MaybeLoadPlayStoreToS(false);
StartNetworkAndTimeZoneObserving();
}
void ArcTermsOfServiceScreenHandler::TimezoneChanged(
const icu::TimeZone& timezone) {
MaybeLoadPlayStoreToS(false);
}
void ArcTermsOfServiceScreenHandler::DefaultNetworkChanged(
const NetworkState* network) {
MaybeLoadPlayStoreToS(false);
}
void ArcTermsOfServiceScreenHandler::DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) {
builder->Add("arcTermsOfServiceScreenHeading", IDS_ARC_OOBE_TERMS_HEADING);
builder->Add("arcTermsOfServiceScreenDescription",
IDS_ARC_OOBE_TERMS_DESCRIPTION);
builder->Add("arcTermsOfServiceLoading", IDS_ARC_OOBE_TERMS_LOADING);
builder->Add("arcTermsOfServiceError", IDS_ARC_OOBE_TERMS_LOAD_ERROR);
builder->Add("arcTermsOfServiceSkipButton", IDS_ARC_OOBE_TERMS_BUTTON_SKIP);
builder->Add("arcTermsOfServiceRetryButton", IDS_ARC_OOBE_TERMS_BUTTON_RETRY);
builder->Add("arcTermsOfServiceAcceptButton",
IDS_ARC_OOBE_TERMS_BUTTON_ACCEPT);
builder->Add("arcTermsOfServiceAcceptAndContinueButton",
IDS_ARC_OOBE_TERMS_BUTTON_ACCEPT_AND_CONTINUE);
builder->Add("arcTermsOfServiceNextButton",
IDS_ARC_OPT_IN_DIALOG_BUTTON_NEXT);
builder->Add("arcPolicyLink", IDS_ARC_OPT_IN_PRIVACY_POLICY_LINK);
builder->Add("arcTextBackupRestore",
is_child_account_ ? IDS_ARC_OPT_IN_DIALOG_BACKUP_RESTORE_CHILD
: IDS_ARC_OPT_IN_DIALOG_BACKUP_RESTORE);
builder->Add("arcTextLocationService",
is_child_account_ ? IDS_ARC_OPT_IN_LOCATION_SETTING_CHILD
: IDS_ARC_OPT_IN_LOCATION_SETTING);
builder->Add("arcTextPaiService", IDS_ARC_OPT_IN_PAI);
builder->Add("arcTextGoogleServiceConfirmation",
IDS_ARC_OPT_IN_GOOGLE_SERVICE_CONFIRMATION);
builder->Add("arcTextReviewSettings", IDS_ARC_REVIEW_SETTINGS);
builder->Add("arcTextMetricsManagedEnabled",
IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_ENABLED);
builder->Add("arcTextMetricsDemoApps", IDS_ARC_OOBE_TERMS_DIALOG_DEMO_APPS);
builder->Add("arcAcceptAndContinueGoogleServiceConfirmation",
IDS_ARC_OPT_IN_ACCEPT_AND_CONTINUE_GOOGLE_SERVICE_CONFIRMATION);
builder->Add("arcLearnMoreStatistics",
is_child_account_ ? IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_CHILD
: IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS);
builder->Add("arcLearnMoreLocationService",
is_child_account_
? IDS_ARC_OPT_IN_LEARN_MORE_LOCATION_SERVICES_CHILD
: IDS_ARC_OPT_IN_LEARN_MORE_LOCATION_SERVICES);
builder->Add("arcLearnMoreBackupAndRestore",
is_child_account_
? IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_CHILD
: IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE);
builder->Add("arcLearnMorePaiService", IDS_ARC_OPT_IN_LEARN_MORE_PAI_SERVICE);
builder->Add("arcOverlayClose", IDS_ARC_OOBE_TERMS_POPUP_HELP_CLOSE_BUTTON);
builder->Add("arcOverlayLoading", IDS_ARC_POPUP_HELP_LOADING);
}
void ArcTermsOfServiceScreenHandler::OnMetricsModeChanged(bool enabled,
bool managed) {
const Profile* const profile = ProfileManager::GetActiveUserProfile();
CHECK(profile);
const user_manager::User* user =
ProfileHelper::Get()->GetUserByProfile(profile);
CHECK(user);
const AccountId owner =
user_manager::UserManager::Get()->GetOwnerAccountId();
// Owner may not be set in case of initial account setup. Note, in case of
// enterprise enrolled devices owner is always empty and we need to account
// managed flag.
const bool owner_profile = !owner.is_valid() || user->GetAccountId() == owner;
int message_id;
if (owner_profile && !managed) {
if (is_child_account_) {
message_id = enabled ? IDS_ARC_OOBE_TERMS_DIALOG_METRICS_ENABLED_CHILD
: IDS_ARC_OOBE_TERMS_DIALOG_METRICS_DISABLED_CHILD;
} else {
message_id = enabled ? IDS_ARC_OOBE_TERMS_DIALOG_METRICS_ENABLED
: IDS_ARC_OOBE_TERMS_DIALOG_METRICS_DISABLED;
}
} else {
if (is_child_account_) {
message_id =
enabled ? IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_ENABLED_CHILD
: IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_DISABLED_CHILD;
} else {
message_id = enabled ? IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_ENABLED
: IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_DISABLED;
}
}
CallJS("login.ArcTermsOfServiceScreen.setMetricsMode",
l10n_util::GetStringUTF16(message_id), true);
}
void ArcTermsOfServiceScreenHandler::OnBackupAndRestoreModeChanged(
bool enabled, bool managed) {
backup_restore_managed_ = managed;
CallJS("login.ArcTermsOfServiceScreen.setBackupAndRestoreMode", enabled,
managed);
}
void ArcTermsOfServiceScreenHandler::OnLocationServicesModeChanged(
bool enabled, bool managed) {
location_services_managed_ = managed;
CallJS("login.ArcTermsOfServiceScreen.setLocationServicesMode", enabled,
managed);
}
void ArcTermsOfServiceScreenHandler::AddObserver(
ArcTermsOfServiceScreenViewObserver* observer) {
observer_list_.AddObserver(observer);
}
void ArcTermsOfServiceScreenHandler::RemoveObserver(
ArcTermsOfServiceScreenViewObserver* observer) {
observer_list_.RemoveObserver(observer);
}
void ArcTermsOfServiceScreenHandler::Show() {
if (!page_is_ready()) {
show_on_init_ = true;
return;
}
// Demo mode setup flow requires different variant of Play Store terms. It
// does not allow to skip, but instead has back button. Some options are not
// displayed, because they are not relevant for demo mode usage.
if (arc::IsArcDemoModeSetupFlow()) {
DoShowForDemoModeSetup();
} else {
DoShow();
}
}
void ArcTermsOfServiceScreenHandler::Hide() {
system::TimezoneSettings::GetInstance()->RemoveObserver(this);
pref_handler_.reset();
}
void ArcTermsOfServiceScreenHandler::Bind(ArcTermsOfServiceScreen* screen) {
BaseScreenHandler::SetBaseScreen(screen);
}
void ArcTermsOfServiceScreenHandler::StartNetworkAndTimeZoneObserving() {
if (network_time_zone_observing_)
return;
chromeos::NetworkHandler::Get()->network_state_handler()->AddObserver(
this, FROM_HERE);
system::TimezoneSettings::GetInstance()->AddObserver(this);
network_time_zone_observing_ = true;
}
void ArcTermsOfServiceScreenHandler::Initialize() {
if (!show_on_init_) {
// Send time zone information as soon as possible to able to pre-load the
// Play Store ToS.
GetOobeUI()->AddObserver(this);
return;
}
Show();
show_on_init_ = false;
}
void ArcTermsOfServiceScreenHandler::DoShow() {
Profile* profile = ProfileManager::GetActiveUserProfile();
CHECK(profile);
CallJS("login.ArcTermsOfServiceScreen.clearDemoMode");
// Enable ARC to match ArcSessionManager logic. ArcSessionManager expects that
// ARC is enabled (prefs::kArcEnabled = true) on showing Terms of Service. If
// user accepts ToS then prefs::kArcEnabled is left activated. If user skips
// ToS then prefs::kArcEnabled is automatically reset in ArcSessionManager.
arc::SetArcPlayStoreEnabledForProfile(profile, true);
// Hide the Skip button if the ToS screen can not be skipped during OOBE.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kEnableArcOobeOptinNoSkip) ||
arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile)) {
CallJS("login.ArcTermsOfServiceScreen.hideSkipButton");
}
action_taken_ = false;
ShowScreen(kScreenId);
arc_managed_ = arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile);
CallJS("login.ArcTermsOfServiceScreen.setArcManaged", arc_managed_);
MaybeLoadPlayStoreToS(true);
StartNetworkAndTimeZoneObserving();
pref_handler_.reset(new arc::ArcOptInPreferenceHandler(
this, profile->GetPrefs()));
pref_handler_->Start();
}
void ArcTermsOfServiceScreenHandler::DoShowForDemoModeSetup() {
DCHECK(arc::IsArcDemoModeSetupFlow());
CallJS("login.ArcTermsOfServiceScreen.setupForDemoMode");
action_taken_ = false;
ShowScreen(kScreenId);
MaybeLoadPlayStoreToS(true);
StartNetworkAndTimeZoneObserving();
}
bool ArcTermsOfServiceScreenHandler::NeedDispatchEventOnAction() {
if (action_taken_)
return false;
action_taken_ = true;
return true;
}
void ArcTermsOfServiceScreenHandler::RecordConsents(
const std::string& tos_content,
bool record_tos_consent,
bool tos_accepted,
bool record_backup_consent,
bool backup_accepted,
bool record_location_consent,
bool location_accepted) {
Profile* profile = ProfileManager::GetActiveUserProfile();
consent_auditor::ConsentAuditor* consent_auditor =
ConsentAuditorFactory::GetForProfile(profile);
auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
DCHECK(identity_manager->HasPrimaryAccount());
const std::string account_id = identity_manager->GetPrimaryAccountId();
ArcPlayTermsOfServiceConsent play_consent;
play_consent.set_status(tos_accepted ? UserConsentTypes::GIVEN
: UserConsentTypes::NOT_GIVEN);
play_consent.set_confirmation_grd_id(IDS_ARC_OOBE_TERMS_BUTTON_ACCEPT);
play_consent.set_consent_flow(ArcPlayTermsOfServiceConsent::SETUP);
if (record_tos_consent) {
play_consent.set_play_terms_of_service_text_length(tos_content.length());
play_consent.set_play_terms_of_service_hash(
base::SHA1HashString(tos_content));
}
consent_auditor->RecordArcPlayConsent(account_id, play_consent);
if (record_backup_consent) {
ArcBackupAndRestoreConsent backup_and_restore_consent;
backup_and_restore_consent.set_confirmation_grd_id(
IDS_ARC_OOBE_TERMS_BUTTON_ACCEPT);
backup_and_restore_consent.add_description_grd_ids(
is_child_account_ ? IDS_ARC_OPT_IN_DIALOG_BACKUP_RESTORE_CHILD
: IDS_ARC_OPT_IN_DIALOG_BACKUP_RESTORE);
backup_and_restore_consent.set_status(backup_accepted
? UserConsentTypes::GIVEN
: UserConsentTypes::NOT_GIVEN);
consent_auditor->RecordArcBackupAndRestoreConsent(
account_id, backup_and_restore_consent);
}
if (record_location_consent) {
ArcGoogleLocationServiceConsent location_service_consent;
location_service_consent.set_confirmation_grd_id(
IDS_ARC_OOBE_TERMS_BUTTON_ACCEPT);
location_service_consent.add_description_grd_ids(
is_child_account_ ? IDS_ARC_OPT_IN_LOCATION_SETTING
: IDS_ARC_OPT_IN_LOCATION_SETTING);
location_service_consent.set_status(location_accepted
? UserConsentTypes::GIVEN
: UserConsentTypes::NOT_GIVEN);
consent_auditor->RecordArcGoogleLocationServiceConsent(
account_id, location_service_consent);
}
}
void ArcTermsOfServiceScreenHandler::HandleSkip(
const std::string& tos_content) {
DCHECK(!arc::IsArcDemoModeSetupFlow());
if (!NeedDispatchEventOnAction())
return;
// Record consents as not accepted for consents that are under user control
// when the user skips ARC setup.
RecordConsents(tos_content, !arc_managed_, /*tos_accepted=*/false,
!backup_restore_managed_, /*backup_accepted=*/false,
!location_services_managed_, /*location_accepted=*/false);
for (auto& observer : observer_list_)
observer.OnSkip();
}
void ArcTermsOfServiceScreenHandler::HandleAccept(
bool enable_backup_restore,
bool enable_location_services,
bool review_arc_settings,
const std::string& tos_content) {
if (arc::IsArcDemoModeSetupFlow()) {
for (auto& observer : observer_list_)
observer.OnAccept(false);
// TODO(agawronska): Record consent.
return;
}
if (!NeedDispatchEventOnAction())
return;
pref_handler_->EnableBackupRestore(enable_backup_restore);
pref_handler_->EnableLocationService(enable_location_services);
// Record consents as accepted or not accepted as appropriate for consents
// that are under user control when the user completes ARC setup.
RecordConsents(tos_content, !arc_managed_, /*tos_accepted=*/true,
!backup_restore_managed_, enable_backup_restore,
!location_services_managed_, enable_location_services);
for (auto& observer : observer_list_)
observer.OnAccept(review_arc_settings);
}
} // namespace chromeos