blob: 08e1e84371b46d780e7ed0c4d4c2880ee30bb025 [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 "chrome/browser/policy/machine_level_user_cloud_policy_register_watcher.h"
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/metrics/histogram_macros.h"
#include "base/syslog_logging.h"
#include "chrome/browser/policy/browser_dm_token_storage.h"
#include "chrome/grit/chromium_strings.h"
#include "ui/base/l10n/l10n_util.h"
namespace policy {
using RegisterResult = MachineLevelUserCloudPolicyController::RegisterResult;
const char
MachineLevelUserCloudPolicyRegisterWatcher::kStartupDialogHistogramName[] =
"Enterprise.MachineLevelUserCloudPolicyEnrollment.StartupDialog";
MachineLevelUserCloudPolicyRegisterWatcher::
MachineLevelUserCloudPolicyRegisterWatcher(
MachineLevelUserCloudPolicyController* controller)
: controller_(controller) {
controller_->AddObserver(this);
}
MachineLevelUserCloudPolicyRegisterWatcher::
~MachineLevelUserCloudPolicyRegisterWatcher() {
controller_->RemoveObserver(this);
}
RegisterResult MachineLevelUserCloudPolicyRegisterWatcher::
WaitUntilCloudPolicyEnrollmentFinished() {
BrowserDMTokenStorage* token_storage = BrowserDMTokenStorage::Get();
if (token_storage->RetrieveEnrollmentToken().empty())
return RegisterResult::kNoEnrollmentNeeded;
// We are already enrolled successfully.
if (!token_storage->RetrieveDMToken().empty())
return RegisterResult::kEnrollmentSuccessBeforeDialogDisplayed;
EnterpriseStartupDialog::DialogResultCallback callback = base::BindOnce(
&MachineLevelUserCloudPolicyRegisterWatcher::OnDialogClosed,
base::Unretained(this));
if (dialog_creation_callback_)
dialog_ = std::move(dialog_creation_callback_).Run(std::move(callback));
else
dialog_ = EnterpriseStartupDialog::CreateAndShowDialog(std::move(callback));
visible_start_time_ = base::Time::Now();
if (register_result_) {
// |register_result_| has been set only if the enrollment has finished.
// And it must be failed if it's finished without a DM token which is
// checked above. Show the error message directly.
DCHECK(!register_result_.value());
if (!token_storage->ShouldDisplayErrorMessageOnFailure())
return RegisterResult::kEnrollmentFailedSilentlyBeforeDialogDisplayed;
DisplayErrorMessage();
} else {
// Display the loading dialog and wait for the enrollment process.
dialog_->DisplayLaunchingInformationWithThrobber(l10n_util::GetStringUTF16(
IDS_ENTERPRISE_STARTUP_CLOUD_POLICY_ENROLLMENT_TOOLTIP));
}
RecordEnrollmentStartDialog(EnrollmentStartupDialog::kShown);
run_loop_.Run();
if (register_result_.value_or(false))
return RegisterResult::kEnrollmentSuccess;
if (!token_storage->ShouldDisplayErrorMessageOnFailure() &&
register_result_) {
SYSLOG(ERROR) << "Machine level user cloud policy enrollment has failed.";
return RegisterResult::kEnrollmentFailedSilently;
}
SYSLOG(ERROR) << "Can not start Chrome as machine level user cloud policy "
"enrollment has failed. Please double check network "
"connection and the status of enrollment token then open "
"Chrome again.";
if (is_restart_needed_)
return RegisterResult::kRestartDueToFailure;
return RegisterResult::kQuitDueToFailure;
}
bool MachineLevelUserCloudPolicyRegisterWatcher::IsDialogShowing() {
return (dialog_ && dialog_->IsShowing()) || run_loop_.running();
}
void MachineLevelUserCloudPolicyRegisterWatcher::
SetDialogCreationCallbackForTesting(DialogCreationCallback callback) {
dialog_creation_callback_ = std::move(callback);
}
// static
void MachineLevelUserCloudPolicyRegisterWatcher::RecordEnrollmentStartDialog(
EnrollmentStartupDialog dialog_startup) {
UMA_HISTOGRAM_ENUMERATION(kStartupDialogHistogramName, dialog_startup);
}
void MachineLevelUserCloudPolicyRegisterWatcher::OnPolicyRegisterFinished(
bool succeeded) {
register_result_ = succeeded;
// If dialog still exists, dismiss the dialog for a success enrollment or
// show the error message. If dialog has been closed before enrollment
// finished, Chrome should already be in the shutdown process.
if (dialog_ && dialog_->IsShowing()) {
if (register_result_.value() ||
!BrowserDMTokenStorage::Get()->ShouldDisplayErrorMessageOnFailure()) {
dialog_.reset();
} else {
DisplayErrorMessage();
}
}
}
void MachineLevelUserCloudPolicyRegisterWatcher::OnDialogClosed(
bool is_accepted,
bool can_show_browser_window) {
if (can_show_browser_window) {
// Chrome startup can continue normally.
if (register_result_.value()) {
RecordEnrollmentStartDialog(EnrollmentStartupDialog::kClosedSuccess);
} else {
RecordEnrollmentStartDialog(
EnrollmentStartupDialog::kClosedFailAndIgnore);
}
} else if (is_accepted) {
// User chose to restart chrome and try re-enrolling.
RecordEnrollmentStartDialog(EnrollmentStartupDialog::kClosedRelaunch);
} else if (register_result_.has_value()) {
// User closed the dialog after seeing a message that enrollment failed.
RecordEnrollmentStartDialog(EnrollmentStartupDialog::kClosedFail);
} else {
// User closed the dialog after waiting too long with no result.
RecordEnrollmentStartDialog(EnrollmentStartupDialog::kClosedAbort);
}
base::TimeDelta visible_time = base::Time::Now() - visible_start_time_;
UMA_HISTOGRAM_TIMES(
"Enterprise.MachineLevelUserCloudPolicyEnrollment.StartupDialogTime",
visible_time);
// User confirm the dialog to relaunch Chrome to retry the register.
is_restart_needed_ = is_accepted;
// Resume the launch process once the dialog is closed.
run_loop_.Quit();
}
void MachineLevelUserCloudPolicyRegisterWatcher::DisplayErrorMessage() {
dialog_->DisplayErrorMessage(
l10n_util::GetStringUTF16(
IDS_ENTERPRISE_STARTUP_CLOUD_POLICY_ENROLLMENT_ERROR),
l10n_util::GetStringUTF16(IDS_ENTERPRISE_STARTUP_RELAUNCH_BUTTON));
}
} // namespace policy