OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |