Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Side by Side Diff: chrome/browser/chromeos/arc/arc_session_manager.cc

Issue 2737453003: Fix ArcSessionManager state machine, part 1. (Closed)
Patch Set: Rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/arc/arc_session_manager.h" 5 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "ash/common/shelf/shelf_delegate.h" 9 #include "ash/common/shelf/shelf_delegate.h"
10 #include "ash/common/wm_shell.h" 10 #include "ash/common/wm_shell.h"
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 57
58 // The Android management check is disabled by default, it's used only for 58 // The Android management check is disabled by default, it's used only for
59 // testing. 59 // testing.
60 bool g_enable_check_android_management_for_testing = false; 60 bool g_enable_check_android_management_for_testing = false;
61 61
62 // Maximum amount of time we'll wait for ARC to finish booting up. Once this 62 // Maximum amount of time we'll wait for ARC to finish booting up. Once this
63 // timeout expires, keep ARC running in case the user wants to file feedback, 63 // timeout expires, keep ARC running in case the user wants to file feedback,
64 // but present the UI to try again. 64 // but present the UI to try again.
65 constexpr base::TimeDelta kArcSignInTimeout = base::TimeDelta::FromMinutes(5); 65 constexpr base::TimeDelta kArcSignInTimeout = base::TimeDelta::FromMinutes(5);
66 66
67 // Updates UMA with user cancel only if error is not currently shown.
68 void MaybeUpdateOptInCancelUMA(const ArcSupportHost* support_host) {
69 if (!support_host ||
70 support_host->ui_page() == ArcSupportHost::UIPage::NO_PAGE ||
71 support_host->ui_page() == ArcSupportHost::UIPage::ERROR) {
72 return;
73 }
74
75 UpdateOptInCancelUMA(OptInCancelReason::USER_CANCEL);
76 }
77
67 } // namespace 78 } // namespace
68 79
69 ArcSessionManager::ArcSessionManager( 80 ArcSessionManager::ArcSessionManager(
70 std::unique_ptr<ArcSessionRunner> arc_session_runner) 81 std::unique_ptr<ArcSessionRunner> arc_session_runner)
71 : arc_session_runner_(std::move(arc_session_runner)), 82 : arc_session_runner_(std::move(arc_session_runner)),
72 attempt_user_exit_callback_(base::Bind(chrome::AttemptUserExit)), 83 attempt_user_exit_callback_(base::Bind(chrome::AttemptUserExit)),
73 weak_ptr_factory_(this) { 84 weak_ptr_factory_(this) {
74 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 85 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
75 DCHECK(!g_arc_session_manager); 86 DCHECK(!g_arc_session_manager);
76 g_arc_session_manager = this; 87 g_arc_session_manager = this;
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 526
516 if (state_ == State::NOT_INITIALIZED) { 527 if (state_ == State::NOT_INITIALIZED) {
517 NOTREACHED(); 528 NOTREACHED();
518 return; 529 return;
519 } 530 }
520 531
521 // If ARC failed to boot normally, stop ARC. Similarly, if the current page is 532 // If ARC failed to boot normally, stop ARC. Similarly, if the current page is
522 // LSO, closing the window should stop ARC since the user activity chooses to 533 // LSO, closing the window should stop ARC since the user activity chooses to
523 // not sign in. In any other case, ARC is booting normally and the instance 534 // not sign in. In any other case, ARC is booting normally and the instance
524 // should not be stopped. 535 // should not be stopped.
525 if ((state_ != State::SHOWING_TERMS_OF_SERVICE && 536 if ((state_ != State::NEGOTIATING_TERMS_OF_SERVICE &&
526 state_ != State::CHECKING_ANDROID_MANAGEMENT) && 537 state_ != State::CHECKING_ANDROID_MANAGEMENT) &&
527 (!support_host_ || 538 (!support_host_ ||
528 (support_host_->ui_page() != ArcSupportHost::UIPage::ERROR && 539 (support_host_->ui_page() != ArcSupportHost::UIPage::ERROR &&
529 support_host_->ui_page() != ArcSupportHost::UIPage::LSO))) { 540 support_host_->ui_page() != ArcSupportHost::UIPage::LSO))) {
530 return; 541 return;
531 } 542 }
532 543
533 // Update UMA with user cancel only if error is not currently shown. 544 MaybeUpdateOptInCancelUMA(support_host_.get());
534 if (support_host_ &&
535 support_host_->ui_page() != ArcSupportHost::UIPage::NO_PAGE &&
536 support_host_->ui_page() != ArcSupportHost::UIPage::ERROR) {
537 UpdateOptInCancelUMA(OptInCancelReason::USER_CANCEL);
538 }
539
540 StopArc(); 545 StopArc();
541 SetArcPlayStoreEnabledForProfile(profile_, false); 546 SetArcPlayStoreEnabledForProfile(profile_, false);
542 } 547 }
543 548
544 void ArcSessionManager::RecordArcState() { 549 void ArcSessionManager::RecordArcState() {
545 // Only record Enabled state if ARC is allowed in the first place, so we do 550 // Only record Enabled state if ARC is allowed in the first place, so we do
546 // not split the ARC population by devices that cannot run ARC. 551 // not split the ARC population by devices that cannot run ARC.
547 if (IsAllowed()) 552 if (IsAllowed())
548 UpdateEnabledStateUMA(enable_requested_); 553 UpdateEnabledStateUMA(enable_requested_);
549 } 554 }
(...skipping 23 matching lines...) Expand all
573 578
574 if (state_ == State::REMOVING_DATA_DIR) { 579 if (state_ == State::REMOVING_DATA_DIR) {
575 // Data removal request is in progress. Set flag to re-enable ARC once it 580 // Data removal request is in progress. Set flag to re-enable ARC once it
576 // is finished. 581 // is finished.
577 reenable_arc_ = true; 582 reenable_arc_ = true;
578 return; 583 return;
579 } 584 }
580 585
581 PrefService* const prefs = profile_->GetPrefs(); 586 PrefService* const prefs = profile_->GetPrefs();
582 587
583 // For ARC Kiosk we skip ToS because it is very likely that near the device
584 // there will be no one who is eligible to accept them.
585 // TODO(poromov): Move to more Kiosk dedicated set-up phase.
586 if (IsArcKioskMode())
587 prefs->SetBoolean(prefs::kArcTermsAccepted, true);
588
589 // Skip to show UI asking users to set up ARC OptIn preferences, if all of
590 // them are managed by the admin policy. Note that the ToS agreement is anyway
591 // not shown in the case of the managed ARC.
592 if (IsArcPlayStoreEnabledPreferenceManagedForProfile(profile_) &&
593 AreArcAllOptInPreferencesManagedForProfile(profile_)) {
594 prefs->SetBoolean(prefs::kArcTermsAccepted, true);
595 }
596
597 // If it is marked that sign in has been successfully done, if ARC has been 588 // If it is marked that sign in has been successfully done, if ARC has been
598 // set up to always start, then directly start ARC. 589 // set up to always start, then directly start ARC.
599 // For testing, and for Kiosk mode, we also skip ToS negotiation procedure. 590 // For Kiosk mode, skip ToS because it is very likely that near the device
600 // For backward compatibility, this check needs to be prior to the 591 // there will be no one who is eligible to accept them.
601 // kArcTermsAccepted check below. 592 // If opt-in verification is disabled, skip negotiation, too. This is for
593 // testing purpose.
602 if (prefs->GetBoolean(prefs::kArcSignedIn) || ShouldArcAlwaysStart() || 594 if (prefs->GetBoolean(prefs::kArcSignedIn) || ShouldArcAlwaysStart() ||
603 IsArcOptInVerificationDisabled() || IsArcKioskMode()) { 595 IsArcKioskMode() || IsArcOptInVerificationDisabled()) {
604 StartArc(); 596 StartArc();
605 // Check Android management in parallel. 597 // Check Android management in parallel.
606 // Note: StartBackgroundAndroidManagementCheck() may call 598 // Note: StartBackgroundAndroidManagementCheck() may call
607 // OnBackgroundAndroidManagementChecked() synchronously (or 599 // OnBackgroundAndroidManagementChecked() synchronously (or
608 // asynchornously). In the callback, Google Play Store enabled preference 600 // asynchornously). In the callback, Google Play Store enabled preference
609 // can be set to false if managed, and it triggers RequestDisable() via 601 // can be set to false if managed, and it triggers RequestDisable() via
610 // ArcPlayStoreEnabledPreferenceHandler. 602 // ArcPlayStoreEnabledPreferenceHandler.
611 // Thus, StartArc() should be called so that disabling should work even 603 // Thus, StartArc() should be called so that disabling should work even
612 // if synchronous call case. 604 // if synchronous call case.
613 StartBackgroundAndroidManagementCheck(); 605 StartBackgroundAndroidManagementCheck();
614 return; 606 return;
615 } 607 }
616 608
617 // If it is marked that the Terms of service is accepted already,
618 // just skip the negotiation with user, and start Android management
619 // check directly.
620 // This happens, e.g., when;
621 // 1) User accepted the Terms of service on OOBE flow.
622 // 2) User accepted the Terms of service on Opt-in flow, but logged out
623 // before ARC sign in procedure was done. Then, logs in again.
624 if (prefs->GetBoolean(prefs::kArcTermsAccepted)) {
625 // Don't show UI for this progress if it was not shown.
626 if (support_host_ &&
627 support_host_->ui_page() != ArcSupportHost::UIPage::NO_PAGE) {
628 support_host_->ShowArcLoading();
629 }
630 StartAndroidManagementCheck();
631 return;
632 }
633
634 StartTermsOfServiceNegotiation(); 609 StartTermsOfServiceNegotiation();
635 } 610 }
636 611
637 void ArcSessionManager::RequestDisable() { 612 void ArcSessionManager::RequestDisable() {
638 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 613 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
639 DCHECK(profile_); 614 DCHECK(profile_);
640 615
641 if (!enable_requested_) { 616 if (!enable_requested_) {
642 VLOG(1) << "ARC is already disabled. Do nothing."; 617 VLOG(1) << "ARC is already disabled. Do nothing.";
643 return; 618 return;
644 } 619 }
645 enable_requested_ = false; 620 enable_requested_ = false;
646 621
647 // Reset any pending request to re-enable ARC. 622 // Reset any pending request to re-enable ARC.
648 VLOG(1) << "ARC opt-out. Removing user data."; 623 VLOG(1) << "ARC opt-out. Removing user data.";
649 reenable_arc_ = false; 624 reenable_arc_ = false;
650 StopArc(); 625 StopArc();
651 RemoveArcData(); 626 RemoveArcData();
652 } 627 }
653 628
654 void ArcSessionManager::StartTermsOfServiceNegotiation() { 629 void ArcSessionManager::StartTermsOfServiceNegotiation() {
655 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 630 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
631 DCHECK(profile_);
656 DCHECK(!terms_of_service_negotiator_); 632 DCHECK(!terms_of_service_negotiator_);
633 // In Kiosk-mode, Terms of Service negotiation should be skipped.
634 // See also RequestEnableImpl().
635 DCHECK(!IsArcKioskMode());
636 // If opt-in verification is disabled, Terms of Service negotiation should
637 // be skipped, too. See also RequestEnableImpl().
638 DCHECK(!IsArcOptInVerificationDisabled());
657 639
640 // TODO(hidehiko): Remove this condition, when the state machine is fixed.
658 if (!arc_session_runner_->IsStopped()) { 641 if (!arc_session_runner_->IsStopped()) {
659 // If the user attempts to re-enable ARC while the ARC instance is still 642 // If the user attempts to re-enable ARC while the ARC instance is still
660 // running the user should not be able to continue until the ARC instance 643 // running the user should not be able to continue until the ARC instance
661 // has stopped. 644 // has stopped.
662 if (support_host_) { 645 if (support_host_) {
663 support_host_->ShowError( 646 support_host_->ShowError(
664 ArcSupportHost::Error::SIGN_IN_SERVICE_UNAVAILABLE_ERROR, false); 647 ArcSupportHost::Error::SIGN_IN_SERVICE_UNAVAILABLE_ERROR, false);
665 } 648 }
666 return; 649 return;
667 } 650 }
668 651
669 SetState(State::SHOWING_TERMS_OF_SERVICE); 652 // TODO(hidehiko): DCHECK if |state_| is STOPPED, when the state machine
653 // is fixed.
654 SetState(State::NEGOTIATING_TERMS_OF_SERVICE);
655
656 if (!IsArcTermsOfServiceNegotiationNeeded()) {
657 // Moves to next state, Android management check, immediately, as if
658 // Terms of Service negotiation is done successfully.
659 StartAndroidManagementCheck();
660 return;
661 }
662
670 if (IsOobeOptInActive()) { 663 if (IsOobeOptInActive()) {
671 VLOG(1) << "Use OOBE negotiator."; 664 VLOG(1) << "Use OOBE negotiator.";
672 terms_of_service_negotiator_ = 665 terms_of_service_negotiator_ =
673 base::MakeUnique<ArcTermsOfServiceOobeNegotiator>(); 666 base::MakeUnique<ArcTermsOfServiceOobeNegotiator>();
674 } else if (support_host_) { 667 } else if (support_host_) {
675 VLOG(1) << "Use default negotiator."; 668 VLOG(1) << "Use default negotiator.";
676 terms_of_service_negotiator_ = 669 terms_of_service_negotiator_ =
677 base::MakeUnique<ArcTermsOfServiceDefaultNegotiator>( 670 base::MakeUnique<ArcTermsOfServiceDefaultNegotiator>(
678 profile_->GetPrefs(), support_host_.get()); 671 profile_->GetPrefs(), support_host_.get());
672 } else {
673 // The only case reached here is when g_disable_ui_for_testing is set
674 // so ARC support host is not created in SetProfile(), for testing purpose.
675 DCHECK(g_disable_ui_for_testing)
676 << "Negotiator is not created on production.";
677 return;
679 } 678 }
680 679
681 if (terms_of_service_negotiator_) { 680 terms_of_service_negotiator_->StartNegotiation(
682 terms_of_service_negotiator_->StartNegotiation( 681 base::Bind(&ArcSessionManager::OnTermsOfServiceNegotiated,
683 base::Bind(&ArcSessionManager::OnTermsOfServiceNegotiated, 682 weak_ptr_factory_.GetWeakPtr()));
684 weak_ptr_factory_.GetWeakPtr()));
685 }
686 } 683 }
687 684
688 void ArcSessionManager::OnTermsOfServiceNegotiated(bool accepted) { 685 void ArcSessionManager::OnTermsOfServiceNegotiated(bool accepted) {
686 DCHECK_EQ(state_, State::NEGOTIATING_TERMS_OF_SERVICE);
687 DCHECK(profile_);
689 DCHECK(terms_of_service_negotiator_); 688 DCHECK(terms_of_service_negotiator_);
690 terms_of_service_negotiator_.reset(); 689 terms_of_service_negotiator_.reset();
691 690
692 if (!accepted) { 691 if (!accepted) {
693 // To cancel, user needs to close the window. Note that clicking "Cancel" 692 // User does not accept the Terms of Service. Disable Google Play Store.
694 // button effectively just closes the window. 693 MaybeUpdateOptInCancelUMA(support_host_.get());
695 CancelAuthCode(); 694 SetArcPlayStoreEnabledForProfile(profile_, false);
696 return; 695 return;
697 } 696 }
698 697
699 // Terms were accepted. 698 // Terms were accepted.
700 profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true); 699 profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true);
700 StartAndroidManagementCheck();
701 }
701 702
702 // Don't show UI for this progress if it was not shown. 703 bool ArcSessionManager::IsArcTermsOfServiceNegotiationNeeded() const {
703 if (support_host_ && 704 DCHECK(profile_);
704 support_host_->ui_page() != ArcSupportHost::UIPage::NO_PAGE) 705
705 support_host_->ShowArcLoading(); 706 // Skip to show UI asking users to set up ARC OptIn preferences, if all of
706 StartAndroidManagementCheck(); 707 // them are managed by the admin policy. Note that the ToS agreement is anyway
708 // not shown in the case of the managed ARC.
709 if (AreArcAllOptInPreferencesManagedForProfile(profile_)) {
710 VLOG(1) << "All opt-in preferences are under managed. "
711 << "Skip ARC Terms of Service negotiation.";
712 return false;
713 }
714
715 // If it is marked that the Terms of service is accepted already,
716 // just skip the negotiation with user, and start Android management
717 // check directly.
718 // This happens, e.g., when a user accepted the Terms of service on Opt-in
719 // flow, but logged out before ARC sign in procedure was done. Then, logs
720 // in again.
721 if (profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) {
722 VLOG(1) << "The user already accepts ARC Terms of Service.";
723 return false;
724 }
725
726 return true;
707 } 727 }
708 728
709 void ArcSessionManager::StartAndroidManagementCheck() { 729 void ArcSessionManager::StartAndroidManagementCheck() {
710 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 730 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
711 DCHECK(arc_session_runner_->IsStopped()); 731 DCHECK(arc_session_runner_->IsStopped());
712 DCHECK(state_ == State::SHOWING_TERMS_OF_SERVICE || 732 DCHECK(state_ == State::NEGOTIATING_TERMS_OF_SERVICE ||
713 state_ == State::CHECKING_ANDROID_MANAGEMENT || 733 state_ == State::CHECKING_ANDROID_MANAGEMENT);
714 (state_ == State::STOPPED &&
715 profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)));
716 DCHECK(!android_management_checker_);
717 SetState(State::CHECKING_ANDROID_MANAGEMENT); 734 SetState(State::CHECKING_ANDROID_MANAGEMENT);
718 735
736 // Show loading UI only if ARC support app's window is already shown.
737 // User may not see any ARC support UI if everything needed is done in
738 // background. In such a case, showing loading UI here (then closed sometime
739 // soon later) would look just noisy.
740 if (support_host_ &&
741 support_host_->ui_page() != ArcSupportHost::UIPage::NO_PAGE) {
742 support_host_->ShowArcLoading();
743 }
744
719 android_management_checker_ = base::MakeUnique<ArcAndroidManagementChecker>( 745 android_management_checker_ = base::MakeUnique<ArcAndroidManagementChecker>(
720 profile_, context_->token_service(), context_->account_id(), 746 profile_, context_->token_service(), context_->account_id(),
721 false /* retry_on_error */); 747 false /* retry_on_error */);
722 android_management_checker_->StartCheck( 748 android_management_checker_->StartCheck(
723 base::Bind(&ArcSessionManager::OnAndroidManagementChecked, 749 base::Bind(&ArcSessionManager::OnAndroidManagementChecked,
724 weak_ptr_factory_.GetWeakPtr())); 750 weak_ptr_factory_.GetWeakPtr()));
725 } 751 }
726 752
727 void ArcSessionManager::OnAndroidManagementChecked( 753 void ArcSessionManager::OnAndroidManagementChecked(
728 policy::AndroidManagementClient::Result result) { 754 policy::AndroidManagementClient::Result result) {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 support_host_->ShowArcLoading(); 888 support_host_->ShowArcLoading();
863 ShutdownSession(); 889 ShutdownSession();
864 reenable_arc_ = true; 890 reenable_arc_ = true;
865 } else if (state_ == State::ACTIVE) { 891 } else if (state_ == State::ACTIVE) {
866 // This case is handled in ArcAuthService. 892 // This case is handled in ArcAuthService.
867 // Do nothing. 893 // Do nothing.
868 } else { 894 } else {
869 // Otherwise, we restart ARC. Note: this is the first boot case. 895 // Otherwise, we restart ARC. Note: this is the first boot case.
870 // For second or later boot, either ERROR_WITH_FEEDBACK case or ACTIVE 896 // For second or later boot, either ERROR_WITH_FEEDBACK case or ACTIVE
871 // case must hit. 897 // case must hit.
872 support_host_->ShowArcLoading();
873 StartAndroidManagementCheck(); 898 StartAndroidManagementCheck();
874 } 899 }
875 } 900 }
876 901
877 void ArcSessionManager::OnSendFeedbackClicked() { 902 void ArcSessionManager::OnSendFeedbackClicked() {
878 DCHECK(support_host_); 903 DCHECK(support_host_);
879 chrome::OpenFeedbackDialog(nullptr); 904 chrome::OpenFeedbackDialog(nullptr);
880 } 905 }
881 906
882 void ArcSessionManager::SetArcSessionRunnerForTesting( 907 void ArcSessionManager::SetArcSessionRunnerForTesting(
(...skipping 14 matching lines...) Expand all
897 922
898 std::ostream& operator<<(std::ostream& os, 923 std::ostream& operator<<(std::ostream& os,
899 const ArcSessionManager::State& state) { 924 const ArcSessionManager::State& state) {
900 #define MAP_STATE(name) \ 925 #define MAP_STATE(name) \
901 case ArcSessionManager::State::name: \ 926 case ArcSessionManager::State::name: \
902 return os << #name 927 return os << #name
903 928
904 switch (state) { 929 switch (state) {
905 MAP_STATE(NOT_INITIALIZED); 930 MAP_STATE(NOT_INITIALIZED);
906 MAP_STATE(STOPPED); 931 MAP_STATE(STOPPED);
907 MAP_STATE(SHOWING_TERMS_OF_SERVICE); 932 MAP_STATE(NEGOTIATING_TERMS_OF_SERVICE);
908 MAP_STATE(CHECKING_ANDROID_MANAGEMENT); 933 MAP_STATE(CHECKING_ANDROID_MANAGEMENT);
909 MAP_STATE(REMOVING_DATA_DIR); 934 MAP_STATE(REMOVING_DATA_DIR);
910 MAP_STATE(ACTIVE); 935 MAP_STATE(ACTIVE);
911 } 936 }
912 937
913 #undef MAP_STATE 938 #undef MAP_STATE
914 939
915 // Some compilers report an error even if all values of an enum-class are 940 // Some compilers report an error even if all values of an enum-class are
916 // covered exhaustively in a switch statement. 941 // covered exhaustively in a switch statement.
917 NOTREACHED() << "Invalid value " << static_cast<int>(state); 942 NOTREACHED() << "Invalid value " << static_cast<int>(state);
918 return os; 943 return os;
919 } 944 }
920 945
921 } // namespace arc 946 } // namespace arc
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/arc/arc_session_manager.h ('k') | chrome/browser/chromeos/arc/arc_session_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698