blob: 407b6ea8c9e5e995fe3d59755fb2b76fcd0f6d2f [file] [log] [blame]
// Copyright 2020 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/login/parent_access_controller.h"
#include "ash/login/login_screen_controller.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string16.h"
#include "ui/base/l10n/l10n_util.h"
namespace ash {
namespace {
// Number of digits displayed in parent access code input.
constexpr int kParentAccessCodePinLength = 6;
base::string16 GetTitle(ParentAccessRequestReason reason) {
int title_id;
switch (reason) {
case ParentAccessRequestReason::kUnlockTimeLimits:
title_id = IDS_ASH_LOGIN_PARENT_ACCESS_TITLE;
break;
case ParentAccessRequestReason::kChangeTime:
title_id = IDS_ASH_LOGIN_PARENT_ACCESS_TITLE_CHANGE_TIME;
break;
case ParentAccessRequestReason::kChangeTimezone:
title_id = IDS_ASH_LOGIN_PARENT_ACCESS_TITLE_CHANGE_TIMEZONE;
break;
}
return l10n_util::GetStringUTF16(title_id);
}
base::string16 GetDescription(ParentAccessRequestReason reason) {
int description_id;
switch (reason) {
case ParentAccessRequestReason::kUnlockTimeLimits:
description_id = IDS_ASH_LOGIN_PARENT_ACCESS_DESCRIPTION;
break;
case ParentAccessRequestReason::kChangeTime:
case ParentAccessRequestReason::kChangeTimezone:
description_id = IDS_ASH_LOGIN_PARENT_ACCESS_GENERIC_DESCRIPTION;
break;
}
return l10n_util::GetStringUTF16(description_id);
}
base::string16 GetAccessibleTitle() {
return l10n_util::GetStringUTF16(IDS_ASH_LOGIN_PARENT_ACCESS_DIALOG_NAME);
}
} // namespace
ParentAccessController::ParentAccessController() {}
ParentAccessController::~ParentAccessController() = default;
// static
constexpr char ParentAccessController::kUMAParentAccessCodeAction[];
// static
constexpr char ParentAccessController::kUMAParentAccessCodeUsage[];
void RecordParentAccessAction(ParentAccessController::UMAAction action) {
UMA_HISTOGRAM_ENUMERATION(ParentAccessController::kUMAParentAccessCodeAction,
action);
}
void RecordParentAccessUsage(ParentAccessRequestReason reason) {
switch (reason) {
case ParentAccessRequestReason::kUnlockTimeLimits: {
UMA_HISTOGRAM_ENUMERATION(
ParentAccessController::kUMAParentAccessCodeUsage,
ParentAccessController::UMAUsage::kTimeLimits);
return;
}
case ParentAccessRequestReason::kChangeTime: {
bool is_login = Shell::Get()->session_controller()->GetSessionState() ==
session_manager::SessionState::LOGIN_PRIMARY;
UMA_HISTOGRAM_ENUMERATION(
ParentAccessController::kUMAParentAccessCodeUsage,
is_login ? ParentAccessController::UMAUsage::kTimeChangeLoginScreen
: ParentAccessController::UMAUsage::kTimeChangeInSession);
return;
}
case ParentAccessRequestReason::kChangeTimezone: {
UMA_HISTOGRAM_ENUMERATION(
ParentAccessController::kUMAParentAccessCodeUsage,
ParentAccessController::UMAUsage::kTimezoneChange);
return;
}
}
NOTREACHED() << "Unknown ParentAccessRequestReason";
}
PinRequestView::SubmissionResult ParentAccessController::OnPinSubmitted(
const std::string& pin) {
bool pin_is_valid =
Shell::Get()->login_screen_controller()->ValidateParentAccessCode(
account_id_, validation_time_, pin);
if (pin_is_valid) {
VLOG(1) << "Parent access code successfully validated";
RecordParentAccessAction(
ParentAccessController::UMAAction::kValidationSuccess);
return PinRequestView::SubmissionResult::kPinAccepted;
}
VLOG(1) << "Invalid parent access code entered";
RecordParentAccessAction(ParentAccessController::UMAAction::kValidationError);
PinRequestWidget::Get()->UpdateState(
PinRequestViewState::kError,
l10n_util::GetStringUTF16(IDS_ASH_LOGIN_PARENT_ACCESS_TITLE_ERROR),
GetDescription(reason_));
return PinRequestView::SubmissionResult::kPinError;
}
void ParentAccessController::OnBack() {
RecordParentAccessAction(ParentAccessController::UMAAction::kCanceledByUser);
}
void ParentAccessController::OnHelp(gfx::NativeWindow parent_window) {
RecordParentAccessAction(ParentAccessController::UMAAction::kGetHelp);
// TODO(https://crbug.com/999387): Remove this when handling touch
// cancellation is fixed for system modal windows.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(
[](gfx::NativeWindow parent_window) {
Shell::Get()->login_screen_controller()->ShowParentAccessHelpApp(
parent_window);
},
parent_window));
}
bool ParentAccessController::ShowWidget(
const AccountId& child_account_id,
PinRequest::OnPinRequestDone on_exit_callback,
ParentAccessRequestReason reason,
bool extra_dimmer,
base::Time validation_time) {
if (PinRequestWidget::Get())
return false;
account_id_ = child_account_id;
reason_ = reason;
validation_time_ = validation_time;
PinRequest request;
request.on_pin_request_done = std::move(on_exit_callback);
request.help_button_enabled = true;
request.extra_dimmer = extra_dimmer;
request.pin_length = kParentAccessCodePinLength;
request.obscure_pin = false;
request.title = GetTitle(reason);
request.description = GetDescription(reason);
request.accessible_title = GetAccessibleTitle();
PinRequestWidget::Show(std::move(request), this);
RecordParentAccessUsage(reason);
return true;
}
} // namespace ash