| Index: chrome/browser/chromeos/arc/arc_session_manager.cc
|
| diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc
|
| index 31f1eda5da1a2fce5a0500f52c6a132c3f45438e..98cf2ba90edae8804e6707e34880abf5dd068094 100644
|
| --- a/chrome/browser/chromeos/arc/arc_session_manager.cc
|
| +++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
|
| @@ -162,89 +162,23 @@ void ArcSessionManager::OnSessionStopped(ArcStopReason reason,
|
| if (arc_sign_in_timer_.IsRunning())
|
| OnProvisioningFinished(ProvisioningResult::ARC_STOPPED);
|
|
|
| - if (profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) {
|
| - // This should be always true, but just in case as this is looked at
|
| - // inside RemoveArcData() at first.
|
| - VLOG(1) << "ARC had previously requested to remove user data.";
|
| - DCHECK(arc_session_runner_->IsStopped());
|
| - RemoveArcData();
|
| - } else {
|
| - // To support special "Stop and enable ARC" procedure for enterprise,
|
| - // here call MaybeReenableArc() asyncronously.
|
| - // TODO(hidehiko): Restructure the code. crbug.com/665316
|
| - base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| - FROM_HERE, base::Bind(&ArcSessionManager::MaybeReenableArc,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| - }
|
| -
|
| for (auto& observer : observer_list_)
|
| observer.OnArcSessionStopped(reason);
|
| -}
|
| -
|
| -void ArcSessionManager::RemoveArcData() {
|
| - // Ignore redundant data removal request.
|
| - if (state() == State::REMOVING_DATA_DIR)
|
| - return;
|
| -
|
| - // OnArcDataRemoved resets this flag.
|
| - profile_->GetPrefs()->SetBoolean(prefs::kArcDataRemoveRequested, true);
|
|
|
| - if (!arc_session_runner_->IsStopped()) {
|
| - // Just set a flag. On session stopped, this will be re-called,
|
| - // then session manager should remove the data.
|
| + // Transition to the ARC data remove state.
|
| + if (!profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) {
|
| + // TODO(crbug.com/665316): This is the workaround for the bug.
|
| + // If it is not necessary to remove the data, MaybeStartArcDataRemoval()
|
| + // synchronously calls MaybeReenableArc(), which causes unexpected
|
| + // ARC session stop. (Please see the bug for details).
|
| + SetState(State::REMOVING_DATA_DIR);
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| + FROM_HERE, base::Bind(&ArcSessionManager::MaybeReenableArc,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| return;
|
| }
|
|
|
| - VLOG(1) << "Starting ARC data removal";
|
| -
|
| - // Remove Play user ID for Active Directory managed devices.
|
| - profile_->GetPrefs()->SetString(prefs::kArcActiveDirectoryPlayUserId,
|
| - std::string());
|
| -
|
| - SetState(State::REMOVING_DATA_DIR);
|
| - chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->RemoveArcData(
|
| - cryptohome::Identification(
|
| - multi_user_util::GetAccountIdFromProfile(profile_)),
|
| - base::Bind(&ArcSessionManager::OnArcDataRemoved,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| -}
|
| -
|
| -void ArcSessionManager::OnArcDataRemoved(bool success) {
|
| - if (success)
|
| - VLOG(1) << "ARC data removal successful";
|
| - else
|
| - LOG(ERROR) << "Request for ARC user data removal failed.";
|
| -
|
| - // TODO(khmel): Browser tests may shutdown profile by itself. Update browser
|
| - // tests and remove this check.
|
| - if (state() == State::NOT_INITIALIZED)
|
| - return;
|
| -
|
| - for (auto& observer : observer_list_)
|
| - observer.OnArcDataRemoved();
|
| -
|
| - profile_->GetPrefs()->SetBoolean(prefs::kArcDataRemoveRequested, false);
|
| - DCHECK_EQ(state(), State::REMOVING_DATA_DIR);
|
| - SetState(State::STOPPED);
|
| -
|
| - MaybeReenableArc();
|
| -}
|
| -
|
| -void ArcSessionManager::MaybeReenableArc() {
|
| - // Here check if |reenable_arc_| is marked or not.
|
| - // The only case this happens should be in the special case for enterprise
|
| - // "on managed lost" case. In that case, OnSessionStopped() should trigger
|
| - // the RemoveArcData(), then this.
|
| - // TODO(hidehiko): It looks necessary to reset |reenable_arc_| regardless of
|
| - // |enable_requested_|. Fix it.
|
| - if (!reenable_arc_ || !enable_requested_)
|
| - return;
|
| -
|
| - // 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();
|
| + MaybeStartArcDataRemoval();
|
| }
|
|
|
| void ArcSessionManager::OnProvisioningFinished(ProvisioningResult result) {
|
| @@ -391,7 +325,7 @@ void ArcSessionManager::OnProvisioningFinished(ProvisioningResult result) {
|
| // 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";
|
| - RemoveArcData();
|
| + RequestArcDataRemoval();
|
| }
|
|
|
| // We'll delay shutting down the ARC instance in this case to allow people
|
| @@ -448,11 +382,8 @@ void ArcSessionManager::SetProfile(Profile* profile) {
|
| }
|
|
|
| // Chrome may be shut down before completing ARC data removal.
|
| - // In such a case, start removing the data now.
|
| - if (profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) {
|
| - VLOG(1) << "ARC data removal requested in previous session.";
|
| - RemoveArcData();
|
| - }
|
| + // For such a case, start removing the data now, if necessary.
|
| + MaybeStartArcDataRemoval();
|
| }
|
|
|
| void ArcSessionManager::Shutdown() {
|
| @@ -606,7 +537,7 @@ void ArcSessionManager::RequestEnableImpl() {
|
| return;
|
| }
|
|
|
| - StartTermsOfServiceNegotiation();
|
| + MaybeStartTermsOfServiceNegotiation();
|
| }
|
|
|
| void ArcSessionManager::RequestDisable() {
|
| @@ -620,13 +551,39 @@ void ArcSessionManager::RequestDisable() {
|
| enable_requested_ = false;
|
|
|
| // Reset any pending request to re-enable ARC.
|
| - VLOG(1) << "ARC opt-out. Removing user data.";
|
| reenable_arc_ = false;
|
| StopArc();
|
| - RemoveArcData();
|
| + VLOG(1) << "ARC opt-out. Removing user data.";
|
| + RequestArcDataRemoval();
|
| }
|
|
|
| -void ArcSessionManager::StartTermsOfServiceNegotiation() {
|
| +void ArcSessionManager::RequestArcDataRemoval() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + DCHECK(profile_);
|
| + // TODO(hidehiko): DCHECK the previous state. This is called for three 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.
|
| +
|
| + // Just remember the request in persistent data. The actual removal
|
| + // is done via MaybeStartArcDataRemoval(). On completion (in
|
| + // OnArcDataRemoved()), this flag should be reset.
|
| + profile_->GetPrefs()->SetBoolean(prefs::kArcDataRemoveRequested, true);
|
| +
|
| + // To support 1) case above, maybe start data removal.
|
| + if (state_ == State::STOPPED && arc_session_runner_->IsStopped())
|
| + MaybeStartArcDataRemoval();
|
| +}
|
| +
|
| +void ArcSessionManager::MaybeStartTermsOfServiceNegotiation() {
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| DCHECK(profile_);
|
| DCHECK(!terms_of_service_negotiator_);
|
| @@ -850,6 +807,85 @@ void ArcSessionManager::StopArc() {
|
| support_host_->Close();
|
| }
|
|
|
| +void ArcSessionManager::MaybeStartArcDataRemoval() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + DCHECK(profile_);
|
| + // Data removal cannot run in parallel with ARC session.
|
| + DCHECK(arc_session_runner_->IsStopped());
|
| +
|
| + // TODO(hidehiko): DCHECK the previous state, when the state machine is
|
| + // fixed.
|
| + SetState(State::REMOVING_DATA_DIR);
|
| +
|
| + // TODO(hidehiko): Extract the implementation of data removal, so that
|
| + // shutdown can cancel the operation not to call OnArcDataRemoved callback.
|
| + if (!profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) {
|
| + // ARC data removal is not requested. Just move to the next state.
|
| + MaybeReenableArc();
|
| + return;
|
| + }
|
| +
|
| + VLOG(1) << "Starting ARC data removal";
|
| +
|
| + // Remove Play user ID for Active Directory managed devices.
|
| + profile_->GetPrefs()->SetString(prefs::kArcActiveDirectoryPlayUserId,
|
| + std::string());
|
| +
|
| + chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->RemoveArcData(
|
| + cryptohome::Identification(
|
| + multi_user_util::GetAccountIdFromProfile(profile_)),
|
| + base::Bind(&ArcSessionManager::OnArcDataRemoved,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void ArcSessionManager::OnArcDataRemoved(bool success) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| +
|
| + // TODO(khmel): Browser tests may shutdown profile by itself. Update browser
|
| + // tests and remove this check.
|
| + if (state() == State::NOT_INITIALIZED)
|
| + return;
|
| +
|
| + DCHECK_EQ(state_, State::REMOVING_DATA_DIR);
|
| + DCHECK(profile_);
|
| + DCHECK(profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested));
|
| + if (success) {
|
| + VLOG(1) << "ARC data removal successful";
|
| + } else {
|
| + LOG(ERROR) << "Request for ARC user data removal failed. "
|
| + << "See session_manager logs for more details.";
|
| + }
|
| + profile_->GetPrefs()->SetBoolean(prefs::kArcDataRemoveRequested, false);
|
| +
|
| + // Regardless of whether it is successfully done or not, notify observers.
|
| + for (auto& observer : observer_list_)
|
| + observer.OnArcDataRemoved();
|
| +
|
| + MaybeReenableArc();
|
| +}
|
| +
|
| +void ArcSessionManager::MaybeReenableArc() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + DCHECK_EQ(state_, State::REMOVING_DATA_DIR);
|
| + SetState(State::STOPPED);
|
| +
|
| + // Here check if |reenable_arc_| is marked or not.
|
| + // TODO(hidehiko): Conceptually |reenable_arc_| should be always false
|
| + // if |enable_requested_| is false. Replace by DCHECK after state machine
|
| + // fix is done.
|
| + if (!reenable_arc_ || !enable_requested_) {
|
| + // Reset the flag, just in case. TODO(hidehiko): Remove this.
|
| + reenable_arc_ = false;
|
| + return;
|
| + }
|
| +
|
| + // 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() {
|
| DCHECK(support_host_);
|
| if (terms_of_service_negotiator_) {
|
| @@ -878,7 +914,7 @@ void ArcSessionManager::OnRetryClicked() {
|
| // Currently Terms of service is shown. ArcTermsOfServiceNegotiator should
|
| // handle this.
|
| } else if (!profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) {
|
| - StartTermsOfServiceNegotiation();
|
| + MaybeStartTermsOfServiceNegotiation();
|
| } else if (support_host_->ui_page() == ArcSupportHost::UIPage::ERROR &&
|
| !arc_session_runner_->IsStopped()) {
|
| // ERROR_WITH_FEEDBACK is set in OnSignInFailed(). In the case, stopping
|
|
|