// 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/chromeos/arc/arc_session_manager.h"

#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/string_split.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/arc/arc_migration_guide_notification.h"
#include "chrome/browser/chromeos/arc/arc_optin_uma.h"
#include "chrome/browser/chromeos/arc/arc_support_host.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/arc/auth/arc_auth_service.h"
#include "chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator.h"
#include "chrome/browser/chromeos/arc/optin/arc_terms_of_service_oobe_negotiator.h"
#include "chrome/browser/chromeos/arc/policy/arc_android_management_checker.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_resources.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/app_list/arc/arc_app_launcher.h"
#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
#include "chrome/browser/ui/app_list/arc/arc_fast_app_reinstall_starter.h"
#include "chrome/browser/ui/app_list/arc/arc_pai_starter.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "components/account_id/account_id.h"
#include "components/arc/arc_data_remover.h"
#include "components/arc/arc_features.h"
#include "components/arc/arc_instance_mode.h"
#include "components/arc/arc_prefs.h"
#include "components/arc/arc_session_runner.h"
#include "components/arc/arc_supervision_transition.h"
#include "components/arc/arc_util.h"
#include "components/arc/metrics/arc_metrics_constants.h"
#include "components/arc/metrics/arc_metrics_service.h"
#include "components/prefs/pref_service.h"
#include "components/session_manager/core/session_manager.h"
#include "content/public/browser/browser_thread.h"
#include "ui/display/types/display_constants.h"

namespace arc {

namespace {

// Weak pointer.  This class is owned by ArcServiceManager.
ArcSessionManager* g_arc_session_manager = nullptr;

// Allows the session manager to skip creating UI in unit tests.
bool g_ui_enabled = true;

base::Optional<bool> g_enable_check_android_management_in_tests;

// Maximum amount of time we'll wait for ARC to finish booting up. Once this
// timeout expires, keep ARC running in case the user wants to file feedback,
// but present the UI to try again.
constexpr base::TimeDelta kArcSignInTimeout = base::TimeDelta::FromMinutes(5);

// Updates UMA with user cancel only if error is not currently shown.
void MaybeUpdateOptInCancelUMA(const ArcSupportHost* support_host) {
  if (!support_host ||
      support_host->ui_page() == ArcSupportHost::UIPage::NO_PAGE ||
      support_host->ui_page() == ArcSupportHost::UIPage::ERROR) {
    return;
  }

  UpdateOptInCancelUMA(OptInCancelReason::USER_CANCEL);
}

chromeos::SessionManagerClient* GetSessionManagerClient() {
  // If the DBusThreadManager or the SessionManagerClient aren't available,
  // there isn't much we can do. This should only happen when running tests.
  if (!chromeos::DBusThreadManager::IsInitialized() ||
      !chromeos::DBusThreadManager::Get() ||
      !chromeos::DBusThreadManager::Get()->GetSessionManagerClient())
    return nullptr;
  return chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
}

// Returns true if launching the Play Store on OptIn succeeded is needed.
// Launch Play Store app, except for the following cases:
// * When Opt-in verification is disabled (for tests);
// * In case ARC is enabled from OOBE.
// * In ARC Kiosk mode, because the only one UI in kiosk mode must be the
//   kiosk app and device is not needed for opt-in;
// * In Public Session mode, because Play Store will be hidden from users
//   and only apps configured by policy should be installed.
// * When ARC is managed and all OptIn preferences are managed/unused, too,
//   because the whole OptIn flow should happen as seamless as possible for
//   the user.
// For Active Directory users we always show a page notifying them that they
// have to authenticate with their identity provider (through SAML) to make
// it less weird that a browser window pops up.
// Some tests require the Play Store to be shown and forces this using chromeos
// switch kArcForceShowPlayStoreApp.
bool ShouldLaunchPlayStoreApp(Profile* profile,
                              bool oobe_or_assistant_wizard_start) {
  if (!IsPlayStoreAvailable())
    return false;

  if (oobe_or_assistant_wizard_start)
    return false;

  if (ShouldShowOptInForTesting())
    return true;

  if (IsRobotOrOfflineDemoAccountMode())
    return false;

  if (IsArcOptInVerificationDisabled())
    return false;

  if (IsArcPlayStoreEnabledPreferenceManagedForProfile(profile) &&
      AreArcAllOptInPreferencesIgnorableForProfile(profile)) {
    return false;
  }

  return true;
}

}  // namespace

// This class is used to track statuses on OptIn flow. It is created in case ARC
// is activated, and it needs to OptIn. Once started OptInFlowResult::STARTED is
// recorded via UMA. If it finishes successfully OptInFlowResult::SUCCEEDED is
// recorded. Optional OptInFlowResult::SUCCEEDED_AFTER_RETRY is recorded in this
// case if an error occurred during OptIn flow, and user pressed Retry. In case
// the user cancels OptIn flow before it was completed then
// OptInFlowResult::CANCELED is recorded and if an error occurred optional
// OptInFlowResult::CANCELED_AFTER_ERROR. If a shutdown happens during the OptIn
// nothing is recorded, except initial OptInFlowResult::STARTED.
// OptInFlowResult::STARTED = OptInFlowResult::SUCCEEDED +
// OptInFlowResult::CANCELED + cases happened during the shutdown.
class ArcSessionManager::ScopedOptInFlowTracker {
 public:
  ScopedOptInFlowTracker() {
    UpdateOptInFlowResultUMA(OptInFlowResult::STARTED);
  }

  ~ScopedOptInFlowTracker() {
    if (shutdown_)
      return;

    UpdateOptInFlowResultUMA(success_ ? OptInFlowResult::SUCCEEDED
                                      : OptInFlowResult::CANCELED);
    if (error_) {
      UpdateOptInFlowResultUMA(success_
                                   ? OptInFlowResult::SUCCEEDED_AFTER_RETRY
                                   : OptInFlowResult::CANCELED_AFTER_ERROR);
    }
  }

  // Tracks error occurred during the OptIn flow.
  void TrackError() {
    DCHECK(!success_ && !shutdown_);
    error_ = true;
  }

  // Tracks that OptIn finished successfully.
  void TrackSuccess() {
    DCHECK(!success_ && !shutdown_);
    success_ = true;
  }

  // Tracks that OptIn was not completed before shutdown.
  void TrackShutdown() {
    DCHECK(!success_ && !shutdown_);
    shutdown_ = true;
  }

 private:
  bool error_ = false;
  bool success_ = false;
  bool shutdown_ = false;

  DISALLOW_COPY_AND_ASSIGN(ScopedOptInFlowTracker);
};

ArcSessionManager::ArcSessionManager(
    std::unique_ptr<ArcSessionRunner> arc_session_runner)
    : arc_session_runner_(std::move(arc_session_runner)),
      attempt_user_exit_callback_(base::Bind(chrome::AttemptUserExit)),
      weak_ptr_factory_(this) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(!g_arc_session_manager);
  g_arc_session_manager = this;
  arc_session_runner_->AddObserver(this);
  chromeos::SessionManagerClient* client = GetSessionManagerClient();
  if (client)
    client->AddObserver(this);
}

ArcSessionManager::~ArcSessionManager() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  chromeos::SessionManagerClient* client = GetSessionManagerClient();
  if (client)
    client->RemoveObserver(this);

  Shutdown();
  arc_session_runner_->RemoveObserver(this);

  DCHECK_EQ(this, g_arc_session_manager);
  g_arc_session_manager = nullptr;
}

// static
ArcSessionManager* ArcSessionManager::Get() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  return g_arc_session_manager;
}

// static
void ArcSessionManager::SetUiEnabledForTesting(bool enable) {
  g_ui_enabled = enable;
}

// static
void ArcSessionManager::EnableCheckAndroidManagementForTesting(bool enable) {
  g_enable_check_android_management_in_tests = enable;
}

void ArcSessionManager::OnSessionStopped(ArcStopReason reason,
                                         bool restarting) {
  if (restarting) {
    DCHECK_EQ(state_, State::ACTIVE);
    // If ARC is being restarted, here do nothing, and just wait for its
    // next run.
    VLOG(1) << "ARC session is stopped, but being restarted: " << reason;
    return;
  }

  DCHECK(state_ == State::ACTIVE || state_ == State::STOPPING) << state_;
  state_ = State::STOPPED;

  // TODO(crbug.com/625923): Use |reason| to report more detailed errors.
  if (arc_sign_in_timer_.IsRunning())
    OnProvisioningFinished(ProvisioningResult::ARC_STOPPED);

  for (auto& observer : observer_list_)
    observer.OnArcSessionStopped(reason);

  MaybeStartArcDataRemoval();
}

void ArcSessionManager::OnSessionRestarting() {
  for (auto& observer : observer_list_)
    observer.OnArcSessionRestarting();
}

void ArcSessionManager::OnProvisioningFinished(ProvisioningResult result) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // If the Mojo message to notify finishing the provisioning is already sent
  // from the container, it will be processed even after requesting to stop the
  // container. Ignore all |result|s arriving while ARC is disabled, in order to
  // avoid popping up an error message triggered below. This code intentionally
  // does not support the case of reenabling.
  if (!enable_requested_) {
    LOG(WARNING) << "Provisioning result received after ARC was disabled. "
                 << "Ignoring result " << static_cast<int>(result) << ".";
    return;
  }

  // Due asynchronous nature of stopping the ARC instance,
  // OnProvisioningFinished may arrive after setting the |State::STOPPED| state
  // and |State::Active| is not guaranteed to be set here.
  // prefs::kArcDataRemoveRequested also can be active for now.

  const bool provisioning_successful =
      result == ProvisioningResult::SUCCESS ||
      result == ProvisioningResult::SUCCESS_ALREADY_PROVISIONED;
  if (provisioning_reported_) {
    // We don't expect ProvisioningResult::SUCCESS or
    // ProvisioningResult::SUCCESS_ALREADY_PROVISIONED to be reported twice or
    // reported after an error.
    DCHECK(!provisioning_successful);
    // TODO(khmel): Consider changing LOG to NOTREACHED once we guaranty that
    // no double message can happen in production.
    LOG(WARNING) << "Provisioning result was already reported. Ignoring "
                 << "additional result " << result << ".";
    return;
  }
  provisioning_reported_ = true;
  if (scoped_opt_in_tracker_ && !provisioning_successful)
    scoped_opt_in_tracker_->TrackError();

  if (result == ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR) {
    // TODO(poromov): Consider ARC PublicSession offline mode.
    // Currently ARC session will be exited below, while the main user session
    // will be kept alive without Android apps.
    if (IsRobotOrOfflineDemoAccountMode())
      VLOG(1) << "Robot account auth code fetching error";
    if (IsArcKioskMode()) {
      VLOG(1) << "Exiting kiosk session due to provisioning failure";
      // Log out the user. All the cleanup will be done in Shutdown() method.
      // The callback is not called because auth code is empty.
      attempt_user_exit_callback_.Run();
      return;
    }

    // For backwards compatibility, use NETWORK_ERROR for
    // CHROME_SERVER_COMMUNICATION_ERROR case.
    UpdateOptInCancelUMA(OptInCancelReason::NETWORK_ERROR);
  } else if (!sign_in_start_time_.is_null()) {
    arc_sign_in_timer_.Stop();

    UpdateProvisioningTiming(base::Time::Now() - sign_in_start_time_,
                             provisioning_successful, profile_);
    UpdateProvisioningResultUMA(result, profile_);
    if (!provisioning_successful)
      UpdateOptInCancelUMA(OptInCancelReason::CLOUD_PROVISION_FLOW_FAIL);
  }

  if (provisioning_successful) {
    if (support_host_)
      support_host_->Close();

    if (scoped_opt_in_tracker_) {
      scoped_opt_in_tracker_->TrackSuccess();
      scoped_opt_in_tracker_.reset();
    }

    PrefService* const prefs = profile_->GetPrefs();

    if (prefs->GetBoolean(prefs::kArcSignedIn))
      return;

    prefs->SetBoolean(prefs::kArcSignedIn, true);

    if (ShouldLaunchPlayStoreApp(
            profile_,
            prefs->GetBoolean(prefs::kArcProvisioningInitiatedFromOobe))) {
      playstore_launcher_ = std::make_unique<ArcAppLauncher>(
          profile_, kPlayStoreAppId,
          GetLaunchIntent(kPlayStorePackage, kPlayStoreActivity,
                          {kInitialStartParam}),
          false /* deferred_launch_allowed */, display::kInvalidDisplayId,
          arc::UserInteractionType::NOT_USER_INITIATED);
    }

    prefs->ClearPref(prefs::kArcProvisioningInitiatedFromOobe);

    for (auto& observer : observer_list_)
      observer.OnArcInitialStart();
    return;
  }

  ArcSupportHost::Error error;
  VLOG(1) << "ARC provisioning failed: " << result << ".";
  switch (result) {
    case ProvisioningResult::GMS_NETWORK_ERROR:
      error = ArcSupportHost::Error::SIGN_IN_NETWORK_ERROR;
      break;
    case ProvisioningResult::GMS_SERVICE_UNAVAILABLE:
    case ProvisioningResult::GMS_SIGN_IN_FAILED:
    case ProvisioningResult::GMS_SIGN_IN_TIMEOUT:
    case ProvisioningResult::GMS_SIGN_IN_INTERNAL_ERROR:
      error = ArcSupportHost::Error::SIGN_IN_SERVICE_UNAVAILABLE_ERROR;
      break;
    case ProvisioningResult::GMS_BAD_AUTHENTICATION:
      error = ArcSupportHost::Error::SIGN_IN_BAD_AUTHENTICATION_ERROR;
      break;
    case ProvisioningResult::DEVICE_CHECK_IN_FAILED:
    case ProvisioningResult::DEVICE_CHECK_IN_TIMEOUT:
    case ProvisioningResult::DEVICE_CHECK_IN_INTERNAL_ERROR:
      error = ArcSupportHost::Error::SIGN_IN_GMS_NOT_AVAILABLE_ERROR;
      break;
    case ProvisioningResult::CLOUD_PROVISION_FLOW_FAILED:
    case ProvisioningResult::CLOUD_PROVISION_FLOW_TIMEOUT:
    case ProvisioningResult::CLOUD_PROVISION_FLOW_INTERNAL_ERROR:
      error = ArcSupportHost::Error::SIGN_IN_CLOUD_PROVISION_FLOW_FAIL_ERROR;
      break;
    case ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR:
      error = ArcSupportHost::Error::SERVER_COMMUNICATION_ERROR;
      break;
    case ProvisioningResult::NO_NETWORK_CONNECTION:
      error = ArcSupportHost::Error::NETWORK_UNAVAILABLE_ERROR;
      break;
    case ProvisioningResult::ARC_DISABLED:
      error = ArcSupportHost::Error::ANDROID_MANAGEMENT_REQUIRED_ERROR;
      break;
    default:
      error = ArcSupportHost::Error::SIGN_IN_UNKNOWN_ERROR;
      break;
  }

  if (result == ProvisioningResult::ARC_STOPPED ||
      result == ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR) {
    if (profile_->GetPrefs()->HasPrefPath(prefs::kArcSignedIn))
      profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false);
    ShutdownSession();
    ShowArcSupportHostError(error, true);
    return;
  }

  if (result == ProvisioningResult::CLOUD_PROVISION_FLOW_FAILED ||
      result == ProvisioningResult::CLOUD_PROVISION_FLOW_TIMEOUT ||
      result == ProvisioningResult::CLOUD_PROVISION_FLOW_INTERNAL_ERROR ||
      // OVERALL_SIGN_IN_TIMEOUT might be an indication that ARC believes it is
      // fully setup, but Chrome does not.
      result == ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT ||
      // Just to be safe, remove data if we don't know the cause.
      result == ProvisioningResult::UNKNOWN_ERROR) {
    VLOG(1) << "ARC provisioning failed permanently. Removing user data";
    RequestArcDataRemoval();
  }

  // We'll delay shutting down the ARC instance in this case to allow people
  // to send feedback.
  ShowArcSupportHostError(error, true /* = show send feedback button */);
}

bool ArcSessionManager::IsAllowed() const {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  return profile_ != nullptr;
}

void ArcSessionManager::SetProfile(Profile* profile) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(!profile || !profile_);
  DCHECK(!profile || IsArcAllowedForProfile(profile));
  profile_ = profile;
}

void ArcSessionManager::Initialize() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(profile_);

  DCHECK_EQ(state_, State::NOT_INITIALIZED);
  state_ = State::STOPPED;

  // Create the support host at initialization. Note that, practically,
  // ARC support Chrome app is rarely used (only opt-in and re-auth flow).
  // So, it may be better to initialize it lazily.
  // TODO(hidehiko): Revisit to think about lazy initialization.
  //
  // Don't show UI for ARC Kiosk because the only one UI in kiosk mode must
  // be the kiosk app. In case of error the UI will be useless as well, because
  // in typical use case there will be no one nearby the kiosk device, who can
  // do some action to solve the problem be means of UI.
  if (g_ui_enabled && !IsArcOptInVerificationDisabled() &&
      !IsRobotOrOfflineDemoAccountMode()) {
    DCHECK(!support_host_);
    support_host_ = std::make_unique<ArcSupportHost>(profile_);
    support_host_->SetErrorDelegate(this);
  }
  data_remover_ = std::make_unique<ArcDataRemover>(
      profile_->GetPrefs(),
      cryptohome::Identification(
          multi_user_util::GetAccountIdFromProfile(profile_)));

  if (g_enable_check_android_management_in_tests.value_or(g_ui_enabled))
    ArcAndroidManagementChecker::StartClient();

  // Request removing data if enabled for a regular->child transition.
  if (GetSupervisionTransition(profile_) ==
          ArcSupervisionTransition::REGULAR_TO_CHILD &&
      base::FeatureList::IsEnabled(
          kCleanArcDataOnRegularToChildTransitionFeature)) {
    LOG(WARNING) << "User transited from regular to child, deleting ARC data";
    // Since method below starts removal procedure automatically, return.
    RequestArcDataRemoval();
    return;
  }

  // Chrome may be shut down before completing ARC data removal.
  // For such a case, start removing the data now, if necessary.
  MaybeStartArcDataRemoval();
}

void ArcSessionManager::Shutdown() {
  enable_requested_ = false;
  ResetArcState();
  arc_session_runner_->OnShutdown();
  data_remover_.reset();
  if (support_host_) {
    support_host_->SetErrorDelegate(nullptr);
    support_host_->Close();
    support_host_.reset();
  }
  pai_starter_.reset();
  fast_app_reinstall_starter_.reset();
  profile_ = nullptr;
  state_ = State::NOT_INITIALIZED;
  if (scoped_opt_in_tracker_) {
    scoped_opt_in_tracker_->TrackShutdown();
    scoped_opt_in_tracker_.reset();
  }
}

void ArcSessionManager::ShutdownSession() {
  ResetArcState();
  switch (state_) {
    case State::NOT_INITIALIZED:
      // Ignore in NOT_INITIALIZED case. This is called in initial SetProfile
      // invocation.
      // TODO(hidehiko): Remove this along with the clean up.
      break;
    case State::STOPPED:
      // Currently, ARC is stopped. Do nothing.
      break;
    case State::NEGOTIATING_TERMS_OF_SERVICE:
    case State::CHECKING_ANDROID_MANAGEMENT:
      // We need to kill the mini-container that might be running here.
      arc_session_runner_->RequestStop();
      // While RequestStop is asynchronous, ArcSessionManager is agnostic to the
      // state of the mini-container, so we can set it's state_ to STOPPED
      // immediately.
      state_ = State::STOPPED;
      break;
    case State::REMOVING_DATA_DIR:
      // When data removing is done, |state_| will be set to STOPPED.
      // Do nothing here.
      break;
    case State::ACTIVE:
      // Request to stop the ARC. |state_| will be set to STOPPED eventually.
      // Set state before requesting the runner to stop in order to prevent the
      // case when |OnSessionStopped| can be called inline and as result
      // |state_| might be changed.
      state_ = State::STOPPING;
      arc_session_runner_->RequestStop();
      break;
    case State::STOPPING:
      // Now ARC is stopping. Do nothing here.
      break;
  }
}

void ArcSessionManager::ResetArcState() {
  arc_sign_in_timer_.Stop();
  playstore_launcher_.reset();
  terms_of_service_negotiator_.reset();
  android_management_checker_.reset();
}

void ArcSessionManager::AddObserver(Observer* observer) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  observer_list_.AddObserver(observer);
}

void ArcSessionManager::RemoveObserver(Observer* observer) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  observer_list_.RemoveObserver(observer);
}

void ArcSessionManager::NotifyArcPlayStoreEnabledChanged(bool enabled) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  for (auto& observer : observer_list_)
    observer.OnArcPlayStoreEnabledChanged(enabled);
}

// This is the special method to support enterprise mojo API.
// TODO(hidehiko): Remove this.
void ArcSessionManager::StopAndEnableArc() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  reenable_arc_ = true;
  StopArc();
}

void ArcSessionManager::OnArcSignInTimeout() {
  LOG(ERROR) << "Timed out waiting for first sign in.";
  OnProvisioningFinished(ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT);
}

void ArcSessionManager::CancelAuthCode() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (state_ == State::NOT_INITIALIZED) {
    NOTREACHED();
    return;
  }

  // If ARC failed to boot normally, stop ARC. Similarly, if the current page is
  // ACTIVE_DIRECTORY_AUTH, closing the window should stop ARC since the user
  // chooses to not sign in. In any other case, ARC is booting normally and
  // the instance should not be stopped.
  if ((state_ != State::NEGOTIATING_TERMS_OF_SERVICE &&
       state_ != State::CHECKING_ANDROID_MANAGEMENT) &&
      (!support_host_ ||
       (support_host_->ui_page() != ArcSupportHost::UIPage::ERROR &&
        support_host_->ui_page() !=
            ArcSupportHost::UIPage::ACTIVE_DIRECTORY_AUTH))) {
    return;
  }

  MaybeUpdateOptInCancelUMA(support_host_.get());
  StopArc();
  SetArcPlayStoreEnabledForProfile(profile_, false);
}

void ArcSessionManager::RecordArcState() {
  // Only record legacy enabled state if ARC is allowed in the first place, so
  // we do not split the ARC population by devices that cannot run ARC.
  if (IsAllowed()) {
    UpdateEnabledStateUMA(enable_requested_);
    UpdateEnabledStateByUserTypeUMA(enable_requested_, profile_);
    ArcMetricsService* service =
        ArcMetricsService::GetForBrowserContext(profile_);
    service->RecordNativeBridgeUMA();
    return;
  }

  const Profile* profile = ProfileManager::GetPrimaryUserProfile();
  // Don't record UMA for the set of cases:
  // * No primary profile is set at this moment.
  // * Primary profile matches the built-in profile used for signing in or the
  //   lock screen.
  // * Primary profile matches guest session.
  // * Primary profile is in incognito mode.
  if (!profile || chromeos::ProfileHelper::IsSigninProfile(profile) ||
      chromeos::ProfileHelper::IsLockScreenAppProfile(profile) ||
      profile->IsOffTheRecord() || profile->IsGuestSession()) {
    return;
  }

  UpdateEnabledStateByUserTypeUMA(enable_requested_, profile);
}

void ArcSessionManager::RequestEnable() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(profile_);

  if (enable_requested_) {
    VLOG(1) << "ARC is already enabled. Do nothing.";
    return;
  }
  enable_requested_ = true;

  VLOG(1) << "ARC opt-in. Starting ARC session.";

  // |directly_started_| flag must be preserved during the internal ARC restart.
  // So set it only when ARC is externally requested to start.
  directly_started_ = RequestEnableImpl();
}

bool ArcSessionManager::IsPlaystoreLaunchRequestedForTesting() const {
  return playstore_launcher_.get();
}

bool ArcSessionManager::RequestEnableImpl() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(profile_);
  DCHECK(enable_requested_);
  DCHECK(state_ == State::STOPPED || state_ == State::STOPPING ||
         state_ == State::REMOVING_DATA_DIR)
      << state_;

  if (state_ != State::STOPPED) {
    // If the previous invocation of ARC is still running (but currently being
    // stopped) or ARC data removal is in progress, postpone the enabling
    // procedure.
    reenable_arc_ = true;
    return false;
  }

  PrefService* const prefs = profile_->GetPrefs();

  // |prefs::kArcProvisioningInitiatedFromOobe| is used to remember
  // |IsArcOobeOptInActive| or |IsArcOptInWizardForAssistantActive| state when
  // ARC start request was made initially. |IsArcOobeOptInActive| or
  // |IsArcOptInWizardForAssistantActive| will be changed by the time when
  // decision to auto-launch the Play Store would be made.
  // |IsArcOobeOptInActive| and |IsArcOptInWizardForAssistantActive| are not
  // preserved on Chrome restart also and in last case
  // |prefs::kArcProvisioningInitiatedFromOobe| is used to remember the state of
  // the initial request.
  // |prefs::kArcProvisioningInitiatedFromOobe| is reset when provisioning is
  // done or ARC is opted out.
  if (IsArcOobeOptInActive() || IsArcOptInWizardForAssistantActive())
    prefs->SetBoolean(prefs::kArcProvisioningInitiatedFromOobe, true);

  // If it is marked that sign in has been successfully done or if Play Store is
  // not available, then directly start ARC with skipping Play Store ToS.
  // For Kiosk mode, skip ToS because it is very likely that near the device
  // there will be no one who is eligible to accept them.
  // In Public Session mode ARC should be started silently without user
  // interaction. If opt-in verification is disabled, skip negotiation, too.
  // This is for testing purpose.
  const bool start_arc_directly =
      prefs->GetBoolean(prefs::kArcSignedIn) || ShouldArcAlwaysStart() ||
      IsRobotOrOfflineDemoAccountMode() || IsArcOptInVerificationDisabled();

  // When ARC is blocked because of filesystem compatibility, do not proceed
  // to starting ARC nor follow further state transitions.
  if (IsArcBlockedDueToIncompatibleFileSystem(profile_)) {
    // If the next step was the ToS negotiation, show a notification instead.
    // Otherwise, be silent now. Users are notified when clicking ARC app icons.
    if (!start_arc_directly && g_ui_enabled)
      arc::ShowArcMigrationGuideNotification(profile_);
    return false;
  }

  if (!pai_starter_ && IsPlayStoreAvailable()) {
    pai_starter_ =
        ArcPaiStarter::CreateIfNeeded(profile_, profile_->GetPrefs());
  }

  if (!fast_app_reinstall_starter_ && IsPlayStoreAvailable()) {
    fast_app_reinstall_starter_ = ArcFastAppReinstallStarter::CreateIfNeeded(
        profile_, profile_->GetPrefs());
  }

  if (start_arc_directly) {
    StartArc();
    // When in ARC kiosk mode, there's no Chrome tabs to restore. Remove the
    // cgroups now.
    if (IsArcKioskMode())
      SetArcCpuRestriction(false /* do_restrict */);
    // Check Android management in parallel.
    // Note: StartBackgroundAndroidManagementCheck() may call
    // OnBackgroundAndroidManagementChecked() synchronously (or
    // asynchronously). In the callback, Google Play Store enabled preference
    // can be set to false if managed, and it triggers RequestDisable() via
    // ArcPlayStoreEnabledPreferenceHandler.
    // Thus, StartArc() should be called so that disabling should work even
    // if synchronous call case.
    StartBackgroundAndroidManagementCheck();
    return true;
  }

  MaybeStartTermsOfServiceNegotiation();
  return false;
}

void ArcSessionManager::RequestDisable() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(profile_);

  if (!enable_requested_) {
    VLOG(1) << "ARC is already disabled. "
            << "Killing an instance for login screen (if any).";
    arc_session_runner_->RequestStop();
    return;
  }

  directly_started_ = false;
  enable_requested_ = false;
  scoped_opt_in_tracker_.reset();
  pai_starter_.reset();
  fast_app_reinstall_starter_.reset();

  // Reset any pending request to re-enable ARC.
  reenable_arc_ = false;
  StopArc();
  VLOG(1) << "ARC opt-out. Removing user data.";
  RequestArcDataRemoval();
}

void ArcSessionManager::RequestArcDataRemoval() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(profile_);
  DCHECK(data_remover_);

  // TODO(hidehiko): DCHECK the previous state. This is called for four cases;
  // 1) Supporting managed user initial disabled case (Please see also
  //    ArcPlayStoreEnabledPreferenceHandler::Start() for details).
  // 2) Supporting enterprise triggered data removal.
  // 3) One called in OnProvisioningFinished().
  // 4) On request disabling.
  // After the state machine is fixed, 2) should be replaced by
  // RequestDisable() immediately followed by RequestEnable().
  // 3) and 4) are internal state transition. So, as for public interface, 1)
  // should be the only use case, and the |state_| should be limited to
  // STOPPED, then.
  // TODO(hidehiko): Think a way to get rid of 1), too.

  data_remover_->Schedule();
  profile_->GetPrefs()->SetInteger(
      prefs::kArcSupervisionTransition,
      static_cast<int>(ArcSupervisionTransition::NO_TRANSITION));
  // To support 1) case above, maybe start data removal.
  if (state_ == State::STOPPED)
    MaybeStartArcDataRemoval();
}

void ArcSessionManager::MaybeStartTermsOfServiceNegotiation() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(profile_);
  DCHECK(!terms_of_service_negotiator_);
  // In Kiosk and Public Session mode, Terms of Service negotiation should be
  // skipped. See also RequestEnableImpl().
  DCHECK(!IsRobotOrOfflineDemoAccountMode());
  // If opt-in verification is disabled, Terms of Service negotiation should
  // be skipped, too. See also RequestEnableImpl().
  DCHECK(!IsArcOptInVerificationDisabled());

  DCHECK_EQ(state_, State::STOPPED);
  state_ = State::NEGOTIATING_TERMS_OF_SERVICE;

  // TODO(hidehiko): In kArcSignedIn = true case, this method should never
  // be called. Remove the check.
  // Conceptually, this is starting ToS negotiation, rather than opt-in flow.
  // Move to RequestEnabledImpl.
  if (!scoped_opt_in_tracker_ &&
      !profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn)) {
    scoped_opt_in_tracker_ = std::make_unique<ScopedOptInFlowTracker>();
  }

  if (!IsArcTermsOfServiceNegotiationNeeded(profile_)) {
    if (IsArcStatsReportingEnabled() &&
        !profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) {
      // Don't enable stats reporting for users who are not shown the reporting
      // notice during ARC setup.
      profile_->GetPrefs()->SetBoolean(prefs::kArcSkippedReportingNotice, true);
    }

    // Moves to next state, Android management check, immediately, as if
    // Terms of Service negotiation is done successfully.
    StartAndroidManagementCheck();
    return;
  }

  if (IsArcOobeOptInActive() || IsArcOptInWizardForAssistantActive()) {
    VLOG(1) << "Use OOBE negotiator.";
    terms_of_service_negotiator_ =
        std::make_unique<ArcTermsOfServiceOobeNegotiator>();
  } else if (support_host_) {
    VLOG(1) << "Use default negotiator.";
    terms_of_service_negotiator_ =
        std::make_unique<ArcTermsOfServiceDefaultNegotiator>(
            profile_->GetPrefs(), support_host_.get());
  }

  if (!terms_of_service_negotiator_) {
    // The only case reached here is when g_ui_enabled is false so ARC support
    // host is not created in SetProfile(), for testing purpose.
    DCHECK(!g_ui_enabled) << "Negotiator is not created on production.";
    return;
  }

  // Start the mini-container here to save time starting the container if the
  // user decides to opt-in.
  arc_session_runner_->RequestStartMiniInstance();

  terms_of_service_negotiator_->StartNegotiation(
      base::Bind(&ArcSessionManager::OnTermsOfServiceNegotiated,
                 weak_ptr_factory_.GetWeakPtr()));
}

void ArcSessionManager::OnTermsOfServiceNegotiated(bool accepted) {
  DCHECK_EQ(state_, State::NEGOTIATING_TERMS_OF_SERVICE);
  DCHECK(profile_);
  DCHECK(terms_of_service_negotiator_ || !g_ui_enabled);
  terms_of_service_negotiator_.reset();

  if (!accepted) {
    VLOG(1) << "Terms of services declined";
    // User does not accept the Terms of Service. Disable Google Play Store.
    MaybeUpdateOptInCancelUMA(support_host_.get());
    SetArcPlayStoreEnabledForProfile(profile_, false);
    return;
  }

  // Terms were accepted.
  VLOG(1) << "Terms of services accepted";
  profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true);
  StartAndroidManagementCheck();
}

void ArcSessionManager::StartAndroidManagementCheck() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // State::STOPPED appears here in following scenario.
  // Initial provisioning finished with state
  // ProvisioningResult::ArcStop or
  // ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR.
  // At this moment |prefs::kArcTermsAccepted| is set to true, once user
  // confirmed ToS prior to provisioning flow. Once user presses "Try Again"
  // button, OnRetryClicked calls this immediately.
  DCHECK(state_ == State::NEGOTIATING_TERMS_OF_SERVICE ||
         state_ == State::CHECKING_ANDROID_MANAGEMENT ||
         state_ == State::STOPPED)
      << state_;
  state_ = State::CHECKING_ANDROID_MANAGEMENT;

  // Show loading UI only if ARC support app's window is already shown.
  // User may not see any ARC support UI if everything needed is done in
  // background. In such a case, showing loading UI here (then closed sometime
  // soon later) would look just noisy.
  if (support_host_ &&
      support_host_->ui_page() != ArcSupportHost::UIPage::NO_PAGE) {
    support_host_->ShowArcLoading();
  }

  for (auto& observer : observer_list_)
    observer.OnArcOptInManagementCheckStarted();

  if (!g_ui_enabled)
    return;

  android_management_checker_ = std::make_unique<ArcAndroidManagementChecker>(
      profile_, false /* retry_on_error */);
  android_management_checker_->StartCheck(
      base::Bind(&ArcSessionManager::OnAndroidManagementChecked,
                 weak_ptr_factory_.GetWeakPtr()));
}

void ArcSessionManager::OnAndroidManagementChecked(
    policy::AndroidManagementClient::Result result) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK_EQ(state_, State::CHECKING_ANDROID_MANAGEMENT);
  DCHECK(android_management_checker_);
  android_management_checker_.reset();

  switch (result) {
    case policy::AndroidManagementClient::Result::UNMANAGED:
      VLOG(1) << "Starting ARC for first sign in.";
      sign_in_start_time_ = base::Time::Now();
      arc_sign_in_timer_.Start(
          FROM_HERE, kArcSignInTimeout,
          base::Bind(&ArcSessionManager::OnArcSignInTimeout,
                     weak_ptr_factory_.GetWeakPtr()));
      StartArc();
      // Since opt-in is an explicit user (or admin) action, relax the
      // cgroups restriction now.
      SetArcCpuRestriction(false /* do_restrict */);
      break;
    case policy::AndroidManagementClient::Result::MANAGED:
      ShowArcSupportHostError(
          ArcSupportHost::Error::ANDROID_MANAGEMENT_REQUIRED_ERROR, false);
      UpdateOptInCancelUMA(OptInCancelReason::ANDROID_MANAGEMENT_REQUIRED);
      break;
    case policy::AndroidManagementClient::Result::ERROR:
      ShowArcSupportHostError(ArcSupportHost::Error::SERVER_COMMUNICATION_ERROR,
                              true);
      UpdateOptInCancelUMA(OptInCancelReason::NETWORK_ERROR);
      break;
  }
}

void ArcSessionManager::StartBackgroundAndroidManagementCheck() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK_EQ(state_, State::ACTIVE);
  DCHECK(!android_management_checker_);

  // Skip Android management check for testing.
  // We also skip if Android management check for Kiosk and Public Session mode,
  // because there are no managed human users for them exist.
  if (IsArcOptInVerificationDisabled() || IsRobotOrOfflineDemoAccountMode() ||
      (!g_ui_enabled &&
       !g_enable_check_android_management_in_tests.value_or(false))) {
    return;
  }

  android_management_checker_ = std::make_unique<ArcAndroidManagementChecker>(
      profile_, true /* retry_on_error */);
  android_management_checker_->StartCheck(
      base::Bind(&ArcSessionManager::OnBackgroundAndroidManagementChecked,
                 weak_ptr_factory_.GetWeakPtr()));
}

void ArcSessionManager::OnBackgroundAndroidManagementChecked(
    policy::AndroidManagementClient::Result result) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(android_management_checker_);
  android_management_checker_.reset();

  switch (result) {
    case policy::AndroidManagementClient::Result::UNMANAGED:
      // Do nothing. ARC should be started already.
      break;
    case policy::AndroidManagementClient::Result::MANAGED:
      SetArcPlayStoreEnabledForProfile(profile_, false);
      break;
    case policy::AndroidManagementClient::Result::ERROR:
      // This code should not be reached. For background check,
      // retry_on_error should be set.
      NOTREACHED();
  }
}

void ArcSessionManager::StartArc() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(state_ == State::STOPPED ||
         state_ == State::CHECKING_ANDROID_MANAGEMENT)
      << state_;
  state_ = State::ACTIVE;

  // ARC must be started only if no pending data removal request exists.
  DCHECK(!profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested));

  for (auto& observer : observer_list_)
    observer.OnArcStarted();

  arc_start_time_ = base::Time::Now();
  provisioning_reported_ = false;

  std::string locale;
  std::string preferred_languages;
  GetLocaleAndPreferredLanguages(profile_, &locale, &preferred_languages);

  ArcSession::UpgradeParams params;

  const chromeos::DemoSession* demo_session = chromeos::DemoSession::Get();
  params.is_demo_session = demo_session && demo_session->started();
  if (params.is_demo_session) {
    DCHECK(demo_session->resources()->loaded());
    params.demo_session_apps_path =
        demo_session->resources()->GetDemoAppsPath();
  }

  params.supervision_transition = GetSupervisionTransition(profile_);
  params.locale = locale;
  // Empty |preferred_languages| is converted to empty array.
  params.preferred_languages = base::SplitString(
      preferred_languages, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);

  arc_session_runner_->RequestUpgrade(std::move(params));
}

void ArcSessionManager::StopArc() {
  // TODO(hidehiko): This STOPPED guard should be unnecessary. Remove it later.
  // |reenable_arc_| may be set in |StopAndEnableArc| in case enterprise
  // management state is lost.
  if (!reenable_arc_ && state_ != State::STOPPED) {
    profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false);
    profile_->GetPrefs()->SetBoolean(prefs::kArcPaiStarted, false);
    profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, false);
    profile_->GetPrefs()->SetBoolean(prefs::kArcFastAppReinstallStarted, false);
    profile_->GetPrefs()->SetBoolean(prefs::kArcProvisioningInitiatedFromOobe,
                                     false);
  }

  ShutdownSession();
  if (support_host_)
    support_host_->Close();
}

void ArcSessionManager::MaybeStartArcDataRemoval() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(profile_);

  // Data removal cannot run in parallel with ARC session.
  // LoginScreen instance does not use data directory, so removing should work.
  DCHECK_EQ(state_, State::STOPPED);

  state_ = State::REMOVING_DATA_DIR;
  data_remover_->Run(base::BindOnce(&ArcSessionManager::OnArcDataRemoved,
                                    weak_ptr_factory_.GetWeakPtr()));
}

void ArcSessionManager::OnArcDataRemoved(base::Optional<bool> result) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK_EQ(state_, State::REMOVING_DATA_DIR);
  DCHECK(profile_);
  state_ = State::STOPPED;

  if (result.has_value()) {
    // Remove Play user ID for Active Directory managed devices.
    profile_->GetPrefs()->SetString(prefs::kArcActiveDirectoryPlayUserId,
                                    std::string());

    // Regardless of whether it is successfully done or not, notify observers.
    for (auto& observer : observer_list_)
      observer.OnArcDataRemoved();

    // Note: Currently, we may re-enable ARC even if data removal fails.
    // We may have to avoid it.
  }

  MaybeReenableArc();
}

void ArcSessionManager::MaybeReenableArc() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK_EQ(state_, State::STOPPED);

  if (!reenable_arc_) {
    // Re-enabling is not triggered. Do nothing.
    return;
  }
  DCHECK(enable_requested_);

  // Restart ARC anyway. Let the enterprise reporting instance decide whether
  // the ARC user data wipe is still required or not.
  reenable_arc_ = false;
  VLOG(1) << "Reenable ARC";
  RequestEnableImpl();
}

void ArcSessionManager::OnWindowClosed() {
  CancelAuthCode();
}

void ArcSessionManager::OnRetryClicked() {
  DCHECK(!g_ui_enabled || support_host_);
  DCHECK(!g_ui_enabled ||
         support_host_->ui_page() == ArcSupportHost::UIPage::ERROR);
  DCHECK(!terms_of_service_negotiator_);
  DCHECK(!g_ui_enabled || !support_host_->HasAuthDelegate());

  UpdateOptInActionUMA(OptInActionType::RETRY);

  if (state_ == State::ACTIVE) {
    // ERROR_WITH_FEEDBACK is set in OnSignInFailed(). In the case, stopping
    // ARC was postponed to contain its internal state into the report.
    // Here, on retry, stop it, then restart.
    if (support_host_)
      support_host_->ShowArcLoading();
    // In unit tests ShutdownSession may be executed inline and OnSessionStopped
    // is called before |reenable_arc_| is set.
    reenable_arc_ = true;
    ShutdownSession();
  } else {
    // Otherwise, we start ARC once it is stopped now. Usually ARC container is
    // left active after provisioning failure but in case
    // ProvisioningResult::ARC_STOPPED and
    // ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR failures container
    // is stopped.
    // At this point ToS is already accepted and
    // IsArcTermsOfServiceNegotiationNeeded returns true or ToS needs not to be
    // shown at all. However there is an exception when this does not happen in
    // case an error page is shown when re-opt-in right after opt-out (this is a
    // bug as it should not show an error). When the user click the retry
    // button on this error page, we may start ToS negotiation instead of
    // recreating the instance.
    // TODO(hidehiko): consider removing this case after fixing the bug.
    MaybeStartTermsOfServiceNegotiation();
  }
}

void ArcSessionManager::OnSendFeedbackClicked() {
  DCHECK(support_host_);
  chrome::OpenFeedbackDialog(nullptr, chrome::kFeedbackSourceArcApp);
}

void ArcSessionManager::SetArcSessionRunnerForTesting(
    std::unique_ptr<ArcSessionRunner> arc_session_runner) {
  DCHECK(arc_session_runner);
  DCHECK(arc_session_runner_);
  arc_session_runner_->RemoveObserver(this);
  arc_session_runner_ = std::move(arc_session_runner);
  arc_session_runner_->AddObserver(this);
}

ArcSessionRunner* ArcSessionManager::GetArcSessionRunnerForTesting() {
  return arc_session_runner_.get();
}

void ArcSessionManager::SetAttemptUserExitCallbackForTesting(
    const base::Closure& callback) {
  DCHECK(!callback.is_null());
  attempt_user_exit_callback_ = callback;
}

void ArcSessionManager::ShowArcSupportHostError(
    ArcSupportHost::Error error,
    bool should_show_send_feedback) {
  if (support_host_)
    support_host_->ShowError(error, should_show_send_feedback);
  for (auto& observer : observer_list_)
    observer.OnArcErrorShowRequested(error);
}

void ArcSessionManager::EmitLoginPromptVisibleCalled() {
  // Since 'login-prompt-visible' Upstart signal starts all Upstart jobs the
  // instance may depend on such as cras, EmitLoginPromptVisibleCalled() is the
  // safe place to start a mini instance.
  if (!IsArcAvailable())
    return;

  arc_session_runner_->RequestStartMiniInstance();
}

std::ostream& operator<<(std::ostream& os,
                         const ArcSessionManager::State& state) {
#define MAP_STATE(name)                \
  case ArcSessionManager::State::name: \
    return os << #name

  switch (state) {
    MAP_STATE(NOT_INITIALIZED);
    MAP_STATE(STOPPED);
    MAP_STATE(NEGOTIATING_TERMS_OF_SERVICE);
    MAP_STATE(CHECKING_ANDROID_MANAGEMENT);
    MAP_STATE(REMOVING_DATA_DIR);
    MAP_STATE(ACTIVE);
    MAP_STATE(STOPPING);
  }

#undef MAP_STATE

  // Some compilers report an error even if all values of an enum-class are
  // covered exhaustively in a switch statement.
  NOTREACHED() << "Invalid value " << static_cast<int>(state);
  return os;
}

}  // namespace arc
