parent_access_controller_impl.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/child_accounts/parent_access_controller_impl.h"
  5. #include <string>
  6. #include "ash/login/login_screen_controller.h"
  7. #include "ash/session/session_controller_impl.h"
  8. #include "ash/shell.h"
  9. #include "ash/strings/grit/ash_strings.h"
  10. #include "base/bind.h"
  11. #include "base/check.h"
  12. #include "base/metrics/histogram_functions.h"
  13. #include "base/metrics/histogram_macros.h"
  14. #include "base/strings/string_util.h"
  15. #include "components/session_manager/session_manager_types.h"
  16. #include "ui/base/l10n/l10n_util.h"
  17. namespace ash {
  18. namespace {
  19. // Number of digits displayed in parent access code input.
  20. constexpr int kParentAccessCodePinLength = 6;
  21. // Base name of the histogram to log parent access code validation result.
  22. constexpr char kUMAParentAccessCodeValidationResultBase[] =
  23. "Supervision.ParentAccessCode.ValidationResult";
  24. // Suffix of the histogram to log aggregated parent access code validation
  25. // results.
  26. constexpr char kUMAValidationResultSuffixAll[] = "All";
  27. // Suffix of the histogram to log parent access code validation results for
  28. // reauth flow.
  29. constexpr char kUMAValidationResultSuffixReauth[] = "Reauth";
  30. // Suffix of the histogram to log parent access code validation results for add
  31. // user flow.
  32. constexpr char kUMAValidationResultSuffixAddUser[] = "AddUser";
  33. // Suffix of the histogram to log parent access code validation results for time
  34. // limits override.
  35. constexpr char kUMAValidationResultSuffixTimeLimits[] = "TimeLimits";
  36. // Suffix of the histogram to log parent access code validation results for
  37. // timezone change.
  38. constexpr char kUMAValidationResultSuffixTimezone[] = "TimezoneChange";
  39. // Suffix of the histogram to log parent access code validation results for
  40. // clock change.
  41. constexpr char kUMAValidationResultSuffixClock[] = "ClockChange";
  42. std::u16string GetTitle(SupervisedAction action) {
  43. int title_id;
  44. switch (action) {
  45. case SupervisedAction::kUnlockTimeLimits:
  46. title_id = IDS_ASH_LOGIN_PARENT_ACCESS_TITLE;
  47. break;
  48. case SupervisedAction::kUpdateClock:
  49. title_id = IDS_ASH_LOGIN_PARENT_ACCESS_TITLE_CHANGE_TIME;
  50. break;
  51. case SupervisedAction::kUpdateTimezone:
  52. title_id = IDS_ASH_LOGIN_PARENT_ACCESS_TITLE_CHANGE_TIMEZONE;
  53. break;
  54. case SupervisedAction::kAddUser:
  55. case SupervisedAction::kReauth:
  56. title_id = IDS_ASH_LOGIN_PARENT_ACCESS_GENERIC_TITLE;
  57. break;
  58. }
  59. return l10n_util::GetStringUTF16(title_id);
  60. }
  61. std::u16string GetDescription(SupervisedAction action) {
  62. int description_id;
  63. switch (action) {
  64. case SupervisedAction::kUnlockTimeLimits:
  65. description_id = IDS_ASH_LOGIN_PARENT_ACCESS_DESCRIPTION;
  66. break;
  67. case SupervisedAction::kUpdateClock:
  68. case SupervisedAction::kUpdateTimezone:
  69. description_id = IDS_ASH_LOGIN_PARENT_ACCESS_GENERIC_DESCRIPTION;
  70. break;
  71. case SupervisedAction::kAddUser:
  72. description_id = IDS_ASH_LOGIN_PARENT_ACCESS_DESCRIPTION_ADD_USER;
  73. break;
  74. case SupervisedAction::kReauth:
  75. description_id = IDS_ASH_LOGIN_PARENT_ACCESS_DESCRIPTION_REAUTH;
  76. break;
  77. }
  78. return l10n_util::GetStringUTF16(description_id);
  79. }
  80. std::u16string GetAccessibleTitle() {
  81. return l10n_util::GetStringUTF16(IDS_ASH_LOGIN_PARENT_ACCESS_DIALOG_NAME);
  82. }
  83. void RecordParentCodeValidationResultToHistogram(
  84. ParentCodeValidationResult result,
  85. const std::string& histogram_name) {
  86. DCHECK(!histogram_name.empty());
  87. switch (result) {
  88. case ParentCodeValidationResult::kValid:
  89. base::UmaHistogramEnumeration(
  90. histogram_name,
  91. ParentAccessControllerImpl::UMAValidationResult::kValid);
  92. return;
  93. case ParentCodeValidationResult::kInvalid:
  94. base::UmaHistogramEnumeration(
  95. histogram_name,
  96. ParentAccessControllerImpl::UMAValidationResult::kInvalid);
  97. return;
  98. case ParentCodeValidationResult::kNoConfig:
  99. base::UmaHistogramEnumeration(
  100. histogram_name,
  101. ParentAccessControllerImpl::UMAValidationResult::kNoConfig);
  102. return;
  103. case ParentCodeValidationResult::kInternalError:
  104. base::UmaHistogramEnumeration(
  105. histogram_name,
  106. ParentAccessControllerImpl::UMAValidationResult::kInternalError);
  107. return;
  108. }
  109. }
  110. void RecordParentCodeValidationResult(ParentCodeValidationResult result,
  111. SupervisedAction action) {
  112. // Record to the action specific histogram.
  113. const std::string action_result_histogram =
  114. ParentAccessControllerImpl::GetUMAParentCodeValidationResultHistorgam(
  115. action);
  116. RecordParentCodeValidationResultToHistogram(result, action_result_histogram);
  117. // Record the action to the aggregated histogram.
  118. const std::string all_results_histogram =
  119. ParentAccessControllerImpl::GetUMAParentCodeValidationResultHistorgam(
  120. absl::nullopt);
  121. RecordParentCodeValidationResultToHistogram(result, all_results_histogram);
  122. }
  123. } // namespace
  124. // static
  125. constexpr char ParentAccessControllerImpl::kUMAParentAccessCodeAction[];
  126. // static
  127. constexpr char ParentAccessControllerImpl::kUMAParentAccessCodeUsage[];
  128. // static
  129. std::string
  130. ParentAccessControllerImpl::GetUMAParentCodeValidationResultHistorgam(
  131. absl::optional<SupervisedAction> action) {
  132. const std::string separator = ".";
  133. if (!action) {
  134. return base::JoinString({kUMAParentAccessCodeValidationResultBase,
  135. kUMAValidationResultSuffixAll},
  136. separator);
  137. }
  138. switch (action.value()) {
  139. case SupervisedAction::kUnlockTimeLimits:
  140. return base::JoinString({kUMAParentAccessCodeValidationResultBase,
  141. kUMAValidationResultSuffixTimeLimits},
  142. separator);
  143. case SupervisedAction::kAddUser:
  144. return base::JoinString({kUMAParentAccessCodeValidationResultBase,
  145. kUMAValidationResultSuffixAddUser},
  146. separator);
  147. case SupervisedAction::kReauth:
  148. return base::JoinString({kUMAParentAccessCodeValidationResultBase,
  149. kUMAValidationResultSuffixReauth},
  150. separator);
  151. case SupervisedAction::kUpdateTimezone:
  152. return base::JoinString({kUMAParentAccessCodeValidationResultBase,
  153. kUMAValidationResultSuffixTimezone},
  154. separator);
  155. case SupervisedAction::kUpdateClock:
  156. return base::JoinString({kUMAParentAccessCodeValidationResultBase,
  157. kUMAValidationResultSuffixClock},
  158. separator);
  159. }
  160. }
  161. ParentAccessControllerImpl::ParentAccessControllerImpl() = default;
  162. ParentAccessControllerImpl::~ParentAccessControllerImpl() = default;
  163. void RecordParentAccessAction(ParentAccessControllerImpl::UMAAction action) {
  164. UMA_HISTOGRAM_ENUMERATION(
  165. ParentAccessControllerImpl::kUMAParentAccessCodeAction, action);
  166. }
  167. void RecordParentAccessUsage(const AccountId& child_account_id,
  168. SupervisedAction action) {
  169. switch (action) {
  170. case SupervisedAction::kUnlockTimeLimits: {
  171. UMA_HISTOGRAM_ENUMERATION(
  172. ParentAccessControllerImpl::kUMAParentAccessCodeUsage,
  173. ParentAccessControllerImpl::UMAUsage::kTimeLimits);
  174. return;
  175. }
  176. case SupervisedAction::kUpdateClock: {
  177. bool is_login = Shell::Get()->session_controller()->GetSessionState() ==
  178. session_manager::SessionState::LOGIN_PRIMARY;
  179. UMA_HISTOGRAM_ENUMERATION(
  180. ParentAccessControllerImpl::kUMAParentAccessCodeUsage,
  181. is_login
  182. ? ParentAccessControllerImpl::UMAUsage::kTimeChangeLoginScreen
  183. : ParentAccessControllerImpl::UMAUsage::kTimeChangeInSession);
  184. return;
  185. }
  186. case SupervisedAction::kUpdateTimezone: {
  187. UMA_HISTOGRAM_ENUMERATION(
  188. ParentAccessControllerImpl::kUMAParentAccessCodeUsage,
  189. ParentAccessControllerImpl::UMAUsage::kTimezoneChange);
  190. return;
  191. }
  192. case SupervisedAction::kAddUser:
  193. UMA_HISTOGRAM_ENUMERATION(
  194. ParentAccessControllerImpl::kUMAParentAccessCodeUsage,
  195. ParentAccessControllerImpl::UMAUsage::kAddUserLoginScreen);
  196. return;
  197. case SupervisedAction::kReauth:
  198. UMA_HISTOGRAM_ENUMERATION(
  199. ParentAccessControllerImpl::kUMAParentAccessCodeUsage,
  200. ParentAccessControllerImpl::UMAUsage::kReauhLoginScreen);
  201. return;
  202. }
  203. NOTREACHED() << "Unknown SupervisedAction";
  204. }
  205. PinRequestView::SubmissionResult ParentAccessControllerImpl::OnPinSubmitted(
  206. const std::string& pin) {
  207. ParentCodeValidationResult pin_validation_result =
  208. Shell::Get()->login_screen_controller()->ValidateParentAccessCode(
  209. account_id_, validation_time_, pin);
  210. RecordParentCodeValidationResult(pin_validation_result, action_);
  211. if (pin_validation_result == ParentCodeValidationResult::kValid) {
  212. VLOG(1) << "Parent access code successfully validated";
  213. RecordParentAccessAction(
  214. ParentAccessControllerImpl::UMAAction::kValidationSuccess);
  215. return PinRequestView::SubmissionResult::kPinAccepted;
  216. }
  217. VLOG(1) << "Invalid parent access code entered";
  218. RecordParentAccessAction(
  219. ParentAccessControllerImpl::UMAAction::kValidationError);
  220. PinRequestWidget::Get()->UpdateState(
  221. PinRequestViewState::kError,
  222. l10n_util::GetStringUTF16(IDS_ASH_LOGIN_PARENT_ACCESS_TITLE_ERROR),
  223. GetDescription(action_));
  224. return PinRequestView::SubmissionResult::kPinError;
  225. }
  226. void ParentAccessControllerImpl::OnBack() {
  227. RecordParentAccessAction(
  228. ParentAccessControllerImpl::UMAAction::kCanceledByUser);
  229. }
  230. void ParentAccessControllerImpl::OnHelp() {
  231. RecordParentAccessAction(ParentAccessControllerImpl::UMAAction::kGetHelp);
  232. // TODO(https://crbug.com/999387): Remove this when handling touch
  233. // cancellation is fixed for system modal windows.
  234. base::ThreadTaskRunnerHandle::Get()->PostTask(
  235. FROM_HERE, base::BindOnce([]() {
  236. Shell::Get()->login_screen_controller()->ShowParentAccessHelpApp();
  237. }));
  238. }
  239. bool ParentAccessControllerImpl::ShowWidget(
  240. const AccountId& child_account_id,
  241. PinRequest::OnPinRequestDone on_exit_callback,
  242. SupervisedAction action,
  243. bool extra_dimmer,
  244. base::Time validation_time) {
  245. if (PinRequestWidget::Get())
  246. return false;
  247. // When there is no logged in user we should accept parent access code for any
  248. // of child account added to the device.
  249. const auto session_state =
  250. Shell::Get()->session_controller()->GetSessionState();
  251. const bool user_in_session =
  252. session_state == session_manager::SessionState::LOGGED_IN_NOT_ACTIVE ||
  253. session_state == session_manager::SessionState::ACTIVE ||
  254. session_state == session_manager::SessionState::LOCKED;
  255. DCHECK(user_in_session || child_account_id.empty());
  256. account_id_ = child_account_id;
  257. action_ = action;
  258. validation_time_ = validation_time;
  259. PinRequest request;
  260. request.on_pin_request_done = std::move(on_exit_callback);
  261. request.help_button_enabled = true;
  262. request.extra_dimmer = extra_dimmer;
  263. request.pin_length = kParentAccessCodePinLength;
  264. request.obscure_pin = false;
  265. request.title = GetTitle(action);
  266. request.description = GetDescription(action);
  267. request.accessible_title = GetAccessibleTitle();
  268. PinRequestWidget::Show(std::move(request), this);
  269. RecordParentAccessUsage(account_id_, action);
  270. return true;
  271. }
  272. } // namespace ash