| 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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 support_host->ui_page() == ArcSupportHost::UIPage::NO_PAGE || | 70 support_host->ui_page() == ArcSupportHost::UIPage::NO_PAGE || |
| 71 support_host->ui_page() == ArcSupportHost::UIPage::ERROR) { | 71 support_host->ui_page() == ArcSupportHost::UIPage::ERROR) { |
| 72 return; | 72 return; |
| 73 } | 73 } |
| 74 | 74 |
| 75 UpdateOptInCancelUMA(OptInCancelReason::USER_CANCEL); | 75 UpdateOptInCancelUMA(OptInCancelReason::USER_CANCEL); |
| 76 } | 76 } |
| 77 | 77 |
| 78 } // namespace | 78 } // namespace |
| 79 | 79 |
| 80 // This class is used to track statuses on OptIn flow. It is created in case ARC |
| 81 // is activated, and it needs to OptIn. Once started OptInFlowResult::STARTED is |
| 82 // recorded via UMA. If it finishes successfully OptInFlowResult::SUCCEEDED is |
| 83 // recorded. Optional OptInFlowResult::SUCCEEDED_AFTER_RETRY is recorded in this |
| 84 // case if an error occurred during OptIn flow, and user pressed Retry. In case |
| 85 // the user cancels OptIn flow before it was completed then |
| 86 // OptInFlowResult::CANCELED is recorded and if an error occurred optional |
| 87 // OptInFlowResult::CANCELED_AFTER_ERROR. If a shutdown happens during the OptIn |
| 88 // nothing is recorded, except initial OptInFlowResult::STARTED. |
| 89 // OptInFlowResult::STARTED = OptInFlowResult::SUCCEEDED + |
| 90 // OptInFlowResult::CANCELED + cases happened during the shutdown. |
| 91 class ArcSessionManager::ScopedOptInFlowTracker { |
| 92 public: |
| 93 ScopedOptInFlowTracker() { |
| 94 UpdateOptInFlowResultUMA(OptInFlowResult::STARTED); |
| 95 } |
| 96 |
| 97 ~ScopedOptInFlowTracker() { |
| 98 if (shutdown_) |
| 99 return; |
| 100 |
| 101 UpdateOptInFlowResultUMA(success_ ? OptInFlowResult::SUCCEEDED |
| 102 : OptInFlowResult::CANCELED); |
| 103 if (error_) { |
| 104 UpdateOptInFlowResultUMA(success_ |
| 105 ? OptInFlowResult::SUCCEEDED_AFTER_RETRY |
| 106 : OptInFlowResult::CANCELED_AFTER_ERROR); |
| 107 } |
| 108 } |
| 109 |
| 110 // Tracks error occurred during the OptIn flow. |
| 111 void TrackError() { |
| 112 DCHECK(!success_ && !shutdown_); |
| 113 error_ = true; |
| 114 } |
| 115 |
| 116 // Tracks that OptIn finished successfully. |
| 117 void TrackSuccess() { |
| 118 DCHECK(!success_ && !shutdown_); |
| 119 success_ = true; |
| 120 } |
| 121 |
| 122 // Tracks that OptIn was not completed before shutdown. |
| 123 void TrackShutdown() { |
| 124 DCHECK(!success_ && !shutdown_); |
| 125 shutdown_ = true; |
| 126 } |
| 127 |
| 128 private: |
| 129 bool error_ = false; |
| 130 bool success_ = false; |
| 131 bool shutdown_ = false; |
| 132 |
| 133 DISALLOW_COPY_AND_ASSIGN(ScopedOptInFlowTracker); |
| 134 }; |
| 135 |
| 80 ArcSessionManager::ArcSessionManager( | 136 ArcSessionManager::ArcSessionManager( |
| 81 std::unique_ptr<ArcSessionRunner> arc_session_runner) | 137 std::unique_ptr<ArcSessionRunner> arc_session_runner) |
| 82 : arc_session_runner_(std::move(arc_session_runner)), | 138 : arc_session_runner_(std::move(arc_session_runner)), |
| 83 attempt_user_exit_callback_(base::Bind(chrome::AttemptUserExit)), | 139 attempt_user_exit_callback_(base::Bind(chrome::AttemptUserExit)), |
| 84 weak_ptr_factory_(this) { | 140 weak_ptr_factory_(this) { |
| 85 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 141 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 86 DCHECK(!g_arc_session_manager); | 142 DCHECK(!g_arc_session_manager); |
| 87 g_arc_session_manager = this; | 143 g_arc_session_manager = this; |
| 88 arc_session_runner_->AddObserver(this); | 144 arc_session_runner_->AddObserver(this); |
| 89 } | 145 } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 // We don't expect ProvisioningResult::SUCCESS is reported twice or reported | 260 // We don't expect ProvisioningResult::SUCCESS is reported twice or reported |
| 205 // after an error. | 261 // after an error. |
| 206 DCHECK_NE(result, ProvisioningResult::SUCCESS); | 262 DCHECK_NE(result, ProvisioningResult::SUCCESS); |
| 207 // TODO(khmel): Consider changing LOG to NOTREACHED once we guaranty that | 263 // TODO(khmel): Consider changing LOG to NOTREACHED once we guaranty that |
| 208 // no double message can happen in production. | 264 // no double message can happen in production. |
| 209 LOG(WARNING) << "Provisioning result was already reported. Ignoring " | 265 LOG(WARNING) << "Provisioning result was already reported. Ignoring " |
| 210 << "additional result " << static_cast<int>(result) << "."; | 266 << "additional result " << static_cast<int>(result) << "."; |
| 211 return; | 267 return; |
| 212 } | 268 } |
| 213 provisioning_reported_ = true; | 269 provisioning_reported_ = true; |
| 270 if (scoped_opt_in_tracker_ && result != ProvisioningResult::SUCCESS) |
| 271 scoped_opt_in_tracker_->TrackError(); |
| 214 | 272 |
| 215 if (result == ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR) { | 273 if (result == ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR) { |
| 216 if (IsArcKioskMode()) { | 274 if (IsArcKioskMode()) { |
| 217 VLOG(1) << "Robot account auth code fetching error"; | 275 VLOG(1) << "Robot account auth code fetching error"; |
| 218 // Log out the user. All the cleanup will be done in Shutdown() method. | 276 // Log out the user. All the cleanup will be done in Shutdown() method. |
| 219 // The callback is not called because auth code is empty. | 277 // The callback is not called because auth code is empty. |
| 220 attempt_user_exit_callback_.Run(); | 278 attempt_user_exit_callback_.Run(); |
| 221 return; | 279 return; |
| 222 } | 280 } |
| 223 | 281 |
| 224 // For backwards compatibility, use NETWORK_ERROR for | 282 // For backwards compatibility, use NETWORK_ERROR for |
| 225 // CHROME_SERVER_COMMUNICATION_ERROR case. | 283 // CHROME_SERVER_COMMUNICATION_ERROR case. |
| 226 UpdateOptInCancelUMA(OptInCancelReason::NETWORK_ERROR); | 284 UpdateOptInCancelUMA(OptInCancelReason::NETWORK_ERROR); |
| 227 } else if (!sign_in_start_time_.is_null()) { | 285 } else if (!sign_in_start_time_.is_null()) { |
| 228 arc_sign_in_timer_.Stop(); | 286 arc_sign_in_timer_.Stop(); |
| 229 | 287 |
| 230 UpdateProvisioningTiming(base::Time::Now() - sign_in_start_time_, | 288 UpdateProvisioningTiming(base::Time::Now() - sign_in_start_time_, |
| 231 result == ProvisioningResult::SUCCESS, | 289 result == ProvisioningResult::SUCCESS, |
| 232 policy_util::IsAccountManaged(profile_)); | 290 policy_util::IsAccountManaged(profile_)); |
| 233 UpdateProvisioningResultUMA(result, | 291 UpdateProvisioningResultUMA(result, |
| 234 policy_util::IsAccountManaged(profile_)); | 292 policy_util::IsAccountManaged(profile_)); |
| 235 if (result != ProvisioningResult::SUCCESS) | 293 if (result != ProvisioningResult::SUCCESS) |
| 236 UpdateOptInCancelUMA(OptInCancelReason::CLOUD_PROVISION_FLOW_FAIL); | 294 UpdateOptInCancelUMA(OptInCancelReason::CLOUD_PROVISION_FLOW_FAIL); |
| 237 } | 295 } |
| 238 | 296 |
| 239 if (result == ProvisioningResult::SUCCESS) { | 297 if (result == ProvisioningResult::SUCCESS) { |
| 240 if (support_host_) | 298 if (support_host_) |
| 241 support_host_->Close(); | 299 support_host_->Close(); |
| 242 | 300 |
| 301 if (scoped_opt_in_tracker_) { |
| 302 scoped_opt_in_tracker_->TrackSuccess(); |
| 303 scoped_opt_in_tracker_.reset(); |
| 304 } |
| 305 |
| 243 if (profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn)) | 306 if (profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn)) |
| 244 return; | 307 return; |
| 245 | 308 |
| 246 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true); | 309 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true); |
| 247 | 310 |
| 248 // Launch Play Store app, except for the following cases: | 311 // Launch Play Store app, except for the following cases: |
| 249 // * When Opt-in verification is disabled (for tests); | 312 // * When Opt-in verification is disabled (for tests); |
| 250 // * In ARC Kiosk mode, because the only one UI in kiosk mode must be the | 313 // * In ARC Kiosk mode, because the only one UI in kiosk mode must be the |
| 251 // kiosk app and device is not needed for opt-in; | 314 // kiosk app and device is not needed for opt-in; |
| 252 // * When ARC is managed and all OptIn preferences are managed too, because | 315 // * When ARC is managed and all OptIn preferences are managed too, because |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 enable_requested_ = false; | 452 enable_requested_ = false; |
| 390 ShutdownSession(); | 453 ShutdownSession(); |
| 391 if (support_host_) { | 454 if (support_host_) { |
| 392 support_host_->Close(); | 455 support_host_->Close(); |
| 393 support_host_->RemoveObserver(this); | 456 support_host_->RemoveObserver(this); |
| 394 support_host_.reset(); | 457 support_host_.reset(); |
| 395 } | 458 } |
| 396 context_.reset(); | 459 context_.reset(); |
| 397 profile_ = nullptr; | 460 profile_ = nullptr; |
| 398 SetState(State::NOT_INITIALIZED); | 461 SetState(State::NOT_INITIALIZED); |
| 462 if (scoped_opt_in_tracker_) { |
| 463 scoped_opt_in_tracker_->TrackShutdown(); |
| 464 scoped_opt_in_tracker_.reset(); |
| 465 } |
| 399 } | 466 } |
| 400 | 467 |
| 401 void ArcSessionManager::ShutdownSession() { | 468 void ArcSessionManager::ShutdownSession() { |
| 402 arc_sign_in_timer_.Stop(); | 469 arc_sign_in_timer_.Stop(); |
| 403 playstore_launcher_.reset(); | 470 playstore_launcher_.reset(); |
| 404 terms_of_service_negotiator_.reset(); | 471 terms_of_service_negotiator_.reset(); |
| 405 android_management_checker_.reset(); | 472 android_management_checker_.reset(); |
| 406 arc_session_runner_->RequestStop(); | 473 arc_session_runner_->RequestStop(); |
| 407 // TODO(hidehiko): The ARC instance's stopping is asynchronous, so it might | 474 // TODO(hidehiko): The ARC instance's stopping is asynchronous, so it might |
| 408 // still be running when we return from this function. Do not set the | 475 // still be running when we return from this function. Do not set the |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 | 608 |
| 542 void ArcSessionManager::RequestDisable() { | 609 void ArcSessionManager::RequestDisable() { |
| 543 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 610 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 544 DCHECK(profile_); | 611 DCHECK(profile_); |
| 545 | 612 |
| 546 if (!enable_requested_) { | 613 if (!enable_requested_) { |
| 547 VLOG(1) << "ARC is already disabled. Do nothing."; | 614 VLOG(1) << "ARC is already disabled. Do nothing."; |
| 548 return; | 615 return; |
| 549 } | 616 } |
| 550 enable_requested_ = false; | 617 enable_requested_ = false; |
| 618 scoped_opt_in_tracker_.reset(); |
| 551 | 619 |
| 552 // Reset any pending request to re-enable ARC. | 620 // Reset any pending request to re-enable ARC. |
| 553 reenable_arc_ = false; | 621 reenable_arc_ = false; |
| 554 StopArc(); | 622 StopArc(); |
| 555 VLOG(1) << "ARC opt-out. Removing user data."; | 623 VLOG(1) << "ARC opt-out. Removing user data."; |
| 556 RequestArcDataRemoval(); | 624 RequestArcDataRemoval(); |
| 557 } | 625 } |
| 558 | 626 |
| 559 void ArcSessionManager::RequestArcDataRemoval() { | 627 void ArcSessionManager::RequestArcDataRemoval() { |
| 560 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 628 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 | 663 |
| 596 // TODO(hidehiko): Remove this condition, when the state machine is fixed. | 664 // TODO(hidehiko): Remove this condition, when the state machine is fixed. |
| 597 if (!arc_session_runner_->IsStopped()) { | 665 if (!arc_session_runner_->IsStopped()) { |
| 598 // If the user attempts to re-enable ARC while the ARC instance is still | 666 // If the user attempts to re-enable ARC while the ARC instance is still |
| 599 // running the user should not be able to continue until the ARC instance | 667 // running the user should not be able to continue until the ARC instance |
| 600 // has stopped. | 668 // has stopped. |
| 601 if (support_host_) { | 669 if (support_host_) { |
| 602 support_host_->ShowError( | 670 support_host_->ShowError( |
| 603 ArcSupportHost::Error::SIGN_IN_SERVICE_UNAVAILABLE_ERROR, false); | 671 ArcSupportHost::Error::SIGN_IN_SERVICE_UNAVAILABLE_ERROR, false); |
| 604 } | 672 } |
| 673 UpdateOptInCancelUMA(OptInCancelReason::SESSION_BUSY); |
| 605 return; | 674 return; |
| 606 } | 675 } |
| 607 | 676 |
| 608 // TODO(hidehiko): DCHECK if |state_| is STOPPED, when the state machine | 677 // TODO(hidehiko): DCHECK if |state_| is STOPPED, when the state machine |
| 609 // is fixed. | 678 // is fixed. |
| 610 SetState(State::NEGOTIATING_TERMS_OF_SERVICE); | 679 SetState(State::NEGOTIATING_TERMS_OF_SERVICE); |
| 611 | 680 |
| 681 if (!scoped_opt_in_tracker_ && |
| 682 !profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn)) { |
| 683 scoped_opt_in_tracker_ = base::MakeUnique<ScopedOptInFlowTracker>(); |
| 684 } |
| 685 |
| 612 if (!IsArcTermsOfServiceNegotiationNeeded()) { | 686 if (!IsArcTermsOfServiceNegotiationNeeded()) { |
| 613 // Moves to next state, Android management check, immediately, as if | 687 // Moves to next state, Android management check, immediately, as if |
| 614 // Terms of Service negotiation is done successfully. | 688 // Terms of Service negotiation is done successfully. |
| 615 StartAndroidManagementCheck(); | 689 StartAndroidManagementCheck(); |
| 616 return; | 690 return; |
| 617 } | 691 } |
| 618 | 692 |
| 619 if (IsOobeOptInActive()) { | 693 if (IsOobeOptInActive()) { |
| 620 VLOG(1) << "Use OOBE negotiator."; | 694 VLOG(1) << "Use OOBE negotiator."; |
| 621 terms_of_service_negotiator_ = | 695 terms_of_service_negotiator_ = |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 | 1047 |
| 974 #undef MAP_STATE | 1048 #undef MAP_STATE |
| 975 | 1049 |
| 976 // Some compilers report an error even if all values of an enum-class are | 1050 // Some compilers report an error even if all values of an enum-class are |
| 977 // covered exhaustively in a switch statement. | 1051 // covered exhaustively in a switch statement. |
| 978 NOTREACHED() << "Invalid value " << static_cast<int>(state); | 1052 NOTREACHED() << "Invalid value " << static_cast<int>(state); |
| 979 return os; | 1053 return os; |
| 980 } | 1054 } |
| 981 | 1055 |
| 982 } // namespace arc | 1056 } // namespace arc |
| OLD | NEW |