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

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

Issue 2734873002: Fix ArcSessionManager state machine, part 2. (Closed)
Patch Set: Address comment. 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 // If ARC is being restarted, here do nothing, and just wait for its 144 // If ARC is being restarted, here do nothing, and just wait for its
145 // next run. 145 // next run.
146 VLOG(1) << "ARC session is stopped, but being restarted: " << reason; 146 VLOG(1) << "ARC session is stopped, but being restarted: " << reason;
147 return; 147 return;
148 } 148 }
149 149
150 // TODO(crbug.com/625923): Use |reason| to report more detailed errors. 150 // TODO(crbug.com/625923): Use |reason| to report more detailed errors.
151 if (arc_sign_in_timer_.IsRunning()) 151 if (arc_sign_in_timer_.IsRunning())
152 OnProvisioningFinished(ProvisioningResult::ARC_STOPPED); 152 OnProvisioningFinished(ProvisioningResult::ARC_STOPPED);
153 153
154 if (profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) { 154 for (auto& observer : observer_list_)
155 // This should be always true, but just in case as this is looked at 155 observer.OnArcSessionStopped(reason);
156 // inside RemoveArcData() at first. 156
157 VLOG(1) << "ARC had previously requested to remove user data."; 157 // Transition to the ARC data remove state.
158 DCHECK(arc_session_runner_->IsStopped()); 158 if (!profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) {
159 RemoveArcData(); 159 // TODO(crbug.com/665316): This is the workaround for the bug.
160 } else { 160 // If it is not necessary to remove the data, StartArcDataRemoval()
161 // To support special "Stop and enable ARC" procedure for enterprise, 161 // synchronously calls OnArcDataRemoved(), which causes unexpected
Yusuke Sato 2017/03/07 21:03:08 This line seems outdated now. StartArcDataRemoval
hidehiko 2017/03/09 09:25:51 Done.
162 // here call MaybeReenableArc() asyncronously. 162 // ARC session stop. (Please see the bug for details).
163 // TODO(hidehiko): Restructure the code. crbug.com/665316 163 SetState(State::REMOVING_DATA_DIR);
164 base::ThreadTaskRunnerHandle::Get()->PostTask( 164 base::ThreadTaskRunnerHandle::Get()->PostTask(
165 FROM_HERE, base::Bind(&ArcSessionManager::MaybeReenableArc, 165 FROM_HERE, base::Bind(&ArcSessionManager::MaybeReenableArc,
166 weak_ptr_factory_.GetWeakPtr())); 166 weak_ptr_factory_.GetWeakPtr()));
167 }
168
169 for (auto& observer : observer_list_)
170 observer.OnArcSessionStopped(reason);
171 }
172
173 void ArcSessionManager::RemoveArcData() {
174 // Ignore redundant data removal request.
175 if (state() == State::REMOVING_DATA_DIR)
176 return;
177
178 // OnArcDataRemoved resets this flag.
179 profile_->GetPrefs()->SetBoolean(prefs::kArcDataRemoveRequested, true);
180
181 if (!arc_session_runner_->IsStopped()) {
182 // Just set a flag. On session stopped, this will be re-called,
183 // then session manager should remove the data.
184 return; 167 return;
185 } 168 }
186 169
187 VLOG(1) << "Starting ARC data removal"; 170 StartArcDataRemoval();
188
189 // Remove Play user ID for Active Directory managed devices.
190 profile_->GetPrefs()->SetString(prefs::kArcActiveDirectoryPlayUserId,
191 std::string());
192
193 SetState(State::REMOVING_DATA_DIR);
194 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->RemoveArcData(
195 cryptohome::Identification(
196 multi_user_util::GetAccountIdFromProfile(profile_)),
197 base::Bind(&ArcSessionManager::OnArcDataRemoved,
198 weak_ptr_factory_.GetWeakPtr()));
199 }
200
201 void ArcSessionManager::OnArcDataRemoved(bool success) {
202 if (success)
203 VLOG(1) << "ARC data removal successful";
204 else
205 LOG(ERROR) << "Request for ARC user data removal failed.";
206
207 // TODO(khmel): Browser tests may shutdown profile by itself. Update browser
208 // tests and remove this check.
209 if (state() == State::NOT_INITIALIZED)
210 return;
211
212 for (auto& observer : observer_list_)
213 observer.OnArcDataRemoved();
214
215 profile_->GetPrefs()->SetBoolean(prefs::kArcDataRemoveRequested, false);
216 DCHECK_EQ(state(), State::REMOVING_DATA_DIR);
217 SetState(State::STOPPED);
218
219 MaybeReenableArc();
220 }
221
222 void ArcSessionManager::MaybeReenableArc() {
223 // Here check if |reenable_arc_| is marked or not.
224 // The only case this happens should be in the special case for enterprise
225 // "on managed lost" case. In that case, OnSessionStopped() should trigger
226 // the RemoveArcData(), then this.
227 // TODO(hidehiko): It looks necessary to reset |reenable_arc_| regardless of
228 // |enable_requested_|. Fix it.
229 if (!reenable_arc_ || !enable_requested_)
230 return;
231
232 // Restart ARC anyway. Let the enterprise reporting instance decide whether
233 // the ARC user data wipe is still required or not.
234 reenable_arc_ = false;
235 VLOG(1) << "Reenable ARC";
236 RequestEnableImpl();
237 } 171 }
238 172
239 void ArcSessionManager::OnProvisioningFinished(ProvisioningResult result) { 173 void ArcSessionManager::OnProvisioningFinished(ProvisioningResult result) {
240 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 174 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
241 175
242 // If the Mojo message to notify finishing the provisioning is already sent 176 // If the Mojo message to notify finishing the provisioning is already sent
243 // from the container, it will be processed even after requesting to stop the 177 // from the container, it will be processed even after requesting to stop the
244 // container. Ignore all |result|s arriving while ARC is disabled, in order to 178 // container. Ignore all |result|s arriving while ARC is disabled, in order to
245 // avoid popping up an error message triggered below. This code intentionally 179 // avoid popping up an error message triggered below. This code intentionally
246 // does not support the case of reenabling. 180 // does not support the case of reenabling.
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 304
371 if (result == ProvisioningResult::CLOUD_PROVISION_FLOW_FAILED || 305 if (result == ProvisioningResult::CLOUD_PROVISION_FLOW_FAILED ||
372 result == ProvisioningResult::CLOUD_PROVISION_FLOW_TIMEOUT || 306 result == ProvisioningResult::CLOUD_PROVISION_FLOW_TIMEOUT ||
373 result == ProvisioningResult::CLOUD_PROVISION_FLOW_INTERNAL_ERROR || 307 result == ProvisioningResult::CLOUD_PROVISION_FLOW_INTERNAL_ERROR ||
374 // OVERALL_SIGN_IN_TIMEOUT might be an indication that ARC believes it is 308 // OVERALL_SIGN_IN_TIMEOUT might be an indication that ARC believes it is
375 // fully setup, but Chrome does not. 309 // fully setup, but Chrome does not.
376 result == ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT || 310 result == ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT ||
377 // Just to be safe, remove data if we don't know the cause. 311 // Just to be safe, remove data if we don't know the cause.
378 result == ProvisioningResult::UNKNOWN_ERROR) { 312 result == ProvisioningResult::UNKNOWN_ERROR) {
379 VLOG(1) << "ARC provisioning failed permanently. Removing user data"; 313 VLOG(1) << "ARC provisioning failed permanently. Removing user data";
380 RemoveArcData(); 314 RequestArcDataRemoval();
381 } 315 }
382 316
383 // We'll delay shutting down the ARC instance in this case to allow people 317 // We'll delay shutting down the ARC instance in this case to allow people
384 // to send feedback. 318 // to send feedback.
385 if (support_host_) 319 if (support_host_)
386 support_host_->ShowError(error, true /* = show send feedback button */); 320 support_host_->ShowError(error, true /* = show send feedback button */);
387 } 321 }
388 322
389 void ArcSessionManager::SetState(State state) { 323 void ArcSessionManager::SetState(State state) {
390 state_ = state; 324 state_ = state;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 SetState(State::STOPPED); 361 SetState(State::STOPPED);
428 362
429 context_ = base::MakeUnique<ArcAuthContext>(profile_); 363 context_ = base::MakeUnique<ArcAuthContext>(profile_);
430 364
431 if (!g_disable_ui_for_testing || 365 if (!g_disable_ui_for_testing ||
432 g_enable_check_android_management_for_testing) { 366 g_enable_check_android_management_for_testing) {
433 ArcAndroidManagementChecker::StartClient(); 367 ArcAndroidManagementChecker::StartClient();
434 } 368 }
435 369
436 // Chrome may be shut down before completing ARC data removal. 370 // Chrome may be shut down before completing ARC data removal.
437 // In such a case, start removing the data now. 371 // For such a case, start removing the data now, if necessary.
438 if (profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) { 372 StartArcDataRemoval();
439 VLOG(1) << "ARC data removal requested in previous session.";
440 RemoveArcData();
441 }
442 } 373 }
443 374
444 void ArcSessionManager::Shutdown() { 375 void ArcSessionManager::Shutdown() {
445 enable_requested_ = false; 376 enable_requested_ = false;
446 ShutdownSession(); 377 ShutdownSession();
447 if (support_host_) { 378 if (support_host_) {
448 support_host_->Close(); 379 support_host_->Close();
449 support_host_->RemoveObserver(this); 380 support_host_->RemoveObserver(this);
450 support_host_.reset(); 381 support_host_.reset();
451 } 382 }
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 567 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
637 DCHECK(profile_); 568 DCHECK(profile_);
638 569
639 if (!enable_requested_) { 570 if (!enable_requested_) {
640 VLOG(1) << "ARC is already disabled. Do nothing."; 571 VLOG(1) << "ARC is already disabled. Do nothing.";
641 return; 572 return;
642 } 573 }
643 enable_requested_ = false; 574 enable_requested_ = false;
644 575
645 // Reset any pending request to re-enable ARC. 576 // Reset any pending request to re-enable ARC.
646 VLOG(1) << "ARC opt-out. Removing user data.";
647 reenable_arc_ = false; 577 reenable_arc_ = false;
648 StopArc(); 578 StopArc();
649 RemoveArcData(); 579 VLOG(1) << "ARC opt-out. Removing user data.";
580 RequestArcDataRemoval();
581 }
582
583 void ArcSessionManager::RequestArcDataRemoval() {
584 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
585 DCHECK(profile_);
586 // TODO(hidehiko): DCHECK the previous state. This is called for three cases;
587 // 1) Supporting managed user initial disabled case (Please see also
588 // ArcPlayStoreEnabledPreferenceHandler::Start() for details).
589 // 2) Supporting enterprise triggered data removal.
590 // 3) One called in OnProvisioningFinished().
591 // 4) On request disabling.
592 // After the state machine is fixed, 2) should be replaced by
593 // RequestDisable() immediately followed by RequestEnable().
594 // 3) and 4) are internal state transition. So, as for public interface, 1)
595 // should be the only use case, and the |state_| should be limited to
596 // STOPPED, then.
597 // TODO(hidehiko): Think a way to get rid of 1), too.
598
599 // Just remember the request in persistent data. The actual removal
600 // is done via StartArcDataRemoval(). On completion (in OnArcDataRemoved()),
601 // this flag should be reset.
602 profile_->GetPrefs()->SetBoolean(prefs::kArcDataRemoveRequested, true);
603
604 // To support 1) case above, maybe start data removal.
605 if (state_ == State::STOPPED && arc_session_runner_->IsStopped())
606 StartArcDataRemoval();
650 } 607 }
651 608
652 void ArcSessionManager::StartTermsOfServiceNegotiation() { 609 void ArcSessionManager::StartTermsOfServiceNegotiation() {
653 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 610 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
654 DCHECK(!terms_of_service_negotiator_); 611 DCHECK(!terms_of_service_negotiator_);
655 612
656 if (!arc_session_runner_->IsStopped()) { 613 if (!arc_session_runner_->IsStopped()) {
657 // If the user attempts to re-enable ARC while the ARC instance is still 614 // If the user attempts to re-enable ARC while the ARC instance is still
658 // running the user should not be able to continue until the ARC instance 615 // running the user should not be able to continue until the ARC instance
659 // has stopped. 616 // has stopped.
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
815 void ArcSessionManager::StopArc() { 772 void ArcSessionManager::StopArc() {
816 if (state_ != State::STOPPED) { 773 if (state_ != State::STOPPED) {
817 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false); 774 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false);
818 profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, false); 775 profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, false);
819 } 776 }
820 ShutdownSession(); 777 ShutdownSession();
821 if (support_host_) 778 if (support_host_)
822 support_host_->Close(); 779 support_host_->Close();
823 } 780 }
824 781
782 void ArcSessionManager::StartArcDataRemoval() {
783 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
784 DCHECK(profile_);
785 // Data removal cannot run, in parallel with ARC session.
Luis Héctor Chávez 2017/03/07 21:52:00 nit: remove comma.
hidehiko 2017/03/09 09:25:51 Done.
786 DCHECK(arc_session_runner_->IsStopped());
787
788 // TODO(hidehiko): DCHECK the previous state, when the state machine is
789 // fixed.
790 SetState(State::REMOVING_DATA_DIR);
791
792 // TODO(hidehiko): Extract the implementation of data removal, so that
793 // shutdown can cancel the operation not to call OnArcDataRemoved callback.
794 if (!profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) {
795 // ARC data removal is not requested. Just move to the next state.
796 MaybeReenableArc();
797 return;
798 }
799
800 VLOG(1) << "Starting ARC data removal";
801
802 // Remove Play user ID for Active Directory managed devices.
803 profile_->GetPrefs()->SetString(prefs::kArcActiveDirectoryPlayUserId,
804 std::string());
805
806 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->RemoveArcData(
807 cryptohome::Identification(
808 multi_user_util::GetAccountIdFromProfile(profile_)),
809 base::Bind(&ArcSessionManager::OnArcDataRemoved,
810 weak_ptr_factory_.GetWeakPtr()));
811 }
812
813 void ArcSessionManager::OnArcDataRemoved(bool success) {
814 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
815
816 // TODO(khmel): Browser tests may shutdown profile by itself. Update browser
817 // tests and remove this check.
818 if (state() == State::NOT_INITIALIZED)
819 return;
820
821 DCHECK_EQ(state_, State::REMOVING_DATA_DIR);
822 DCHECK(profile_);
823 DCHECK(profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested));
Yusuke Sato 2017/03/07 21:03:08 Thanks, the cb function is much easier to follow n
hidehiko 2017/03/09 09:25:50 Could you explain a bit more details about your qu
824 if (success)
825 VLOG(1) << "ARC data removal successful";
826 else
827 LOG(ERROR) << "Request for ARC user data removal failed.";
Yusuke Sato 2017/03/07 21:03:08 nit: What about adding 'See session_manager logs f
hidehiko 2017/03/09 09:25:51 Done.
828 profile_->GetPrefs()->SetBoolean(prefs::kArcDataRemoveRequested, false);
829
830 // Data removal runs (regardless of whether it is successfully done or
Luis Héctor Chávez 2017/03/07 21:52:00 This is not strictly true: there have been cases w
hidehiko 2017/03/09 09:25:51 I just wanted to say this is called regardless of
831 // not), so notify observers.
832 for (auto& observer : observer_list_)
833 observer.OnArcDataRemoved();
834
835 MaybeReenableArc();
836 }
837
838 void ArcSessionManager::MaybeReenableArc() {
Yusuke Sato 2017/03/07 21:03:08 nit: why did you move this down? shouldn't we pres
hidehiko 2017/03/09 09:25:50 Yes, (and that's the order of the state transition
839 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
840 DCHECK_EQ(state_, State::REMOVING_DATA_DIR);
841 SetState(State::STOPPED);
842
843 // Here check if |reenable_arc_| is marked or not.
844 // TODO(hidehiko): Conceptually |reenable_arc_| should be always false
845 // if |enable_requested_| is false. Replace by DCHECK after state machine
846 // fix is done.
847 if (!reenable_arc_ || !enable_requested_) {
848 // Reset the flag, just in case. TODO(hidehiko): Remove this.
849 reenable_arc_ = false;
850 return;
851 }
852
853 // Restart ARC anyway. Let the enterprise reporting instance decide whether
854 // the ARC user data wipe is still required or not.
855 reenable_arc_ = false;
856 VLOG(1) << "Reenable ARC";
857 RequestEnableImpl();
858 }
859
825 void ArcSessionManager::OnWindowClosed() { 860 void ArcSessionManager::OnWindowClosed() {
826 DCHECK(support_host_); 861 DCHECK(support_host_);
827 if (terms_of_service_negotiator_) { 862 if (terms_of_service_negotiator_) {
828 // In this case, ArcTermsOfServiceNegotiator should handle the case. 863 // In this case, ArcTermsOfServiceNegotiator should handle the case.
829 // Do nothing. 864 // Do nothing.
830 return; 865 return;
831 } 866 }
832 CancelAuthCode(); 867 CancelAuthCode();
833 } 868 }
834 869
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 945
911 #undef MAP_STATE 946 #undef MAP_STATE
912 947
913 // Some compilers report an error even if all values of an enum-class are 948 // Some compilers report an error even if all values of an enum-class are
914 // covered exhaustively in a switch statement. 949 // covered exhaustively in a switch statement.
915 NOTREACHED() << "Invalid value " << static_cast<int>(state); 950 NOTREACHED() << "Invalid value " << static_cast<int>(state);
916 return os; 951 return os;
917 } 952 }
918 953
919 } // namespace arc 954 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698