| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_auth_service.h" | 5 #include "chrome/browser/chromeos/arc/arc_auth_service.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" |
| 11 #include "base/auto_reset.h" | 11 #include "base/auto_reset.h" |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/strings/string16.h" | 15 #include "base/strings/string16.h" |
| 16 #include "base/time/time.h" |
| 16 #include "chrome/browser/chromeos/arc/arc_android_management_checker.h" | 17 #include "chrome/browser/chromeos/arc/arc_android_management_checker.h" |
| 17 #include "chrome/browser/chromeos/arc/arc_auth_context.h" | 18 #include "chrome/browser/chromeos/arc/arc_auth_context.h" |
| 18 #include "chrome/browser/chromeos/arc/arc_auth_notification.h" | 19 #include "chrome/browser/chromeos/arc/arc_auth_notification.h" |
| 19 #include "chrome/browser/chromeos/arc/arc_optin_uma.h" | 20 #include "chrome/browser/chromeos/arc/arc_optin_uma.h" |
| 20 #include "chrome/browser/chromeos/arc/arc_support_host.h" | 21 #include "chrome/browser/chromeos/arc/arc_support_host.h" |
| 21 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 22 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| 22 #include "chrome/browser/extensions/extension_util.h" | 23 #include "chrome/browser/extensions/extension_util.h" |
| 23 #include "chrome/browser/policy/profile_policy_connector.h" | 24 #include "chrome/browser/policy/profile_policy_connector.h" |
| 24 #include "chrome/browser/policy/profile_policy_connector_factory.h" | 25 #include "chrome/browser/policy/profile_policy_connector_factory.h" |
| 25 #include "chrome/browser/prefs/pref_service_syncable_util.h" | 26 #include "chrome/browser/prefs/pref_service_syncable_util.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 // Skip creating UI in unit tests | 58 // Skip creating UI in unit tests |
| 58 bool g_disable_ui_for_testing = false; | 59 bool g_disable_ui_for_testing = false; |
| 59 | 60 |
| 60 // Use specified ash::ShelfDelegate for unit tests. | 61 // Use specified ash::ShelfDelegate for unit tests. |
| 61 ash::ShelfDelegate* g_shelf_delegate_for_testing = nullptr; | 62 ash::ShelfDelegate* g_shelf_delegate_for_testing = nullptr; |
| 62 | 63 |
| 63 // The Android management check is disabled by default, it's used only for | 64 // The Android management check is disabled by default, it's used only for |
| 64 // testing. | 65 // testing. |
| 65 bool g_enable_check_android_management_for_testing = false; | 66 bool g_enable_check_android_management_for_testing = false; |
| 66 | 67 |
| 68 // Maximum amount of time we'll wait for ARC to finish booting up. Once this |
| 69 // timeout expires, keep ARC running in case the user wants to file feedback, |
| 70 // but present the UI to try again. |
| 71 constexpr base::TimeDelta kArcSignInTimeout = base::TimeDelta::FromMinutes(5); |
| 72 |
| 67 const char kStateNotInitialized[] = "NOT_INITIALIZED"; | 73 const char kStateNotInitialized[] = "NOT_INITIALIZED"; |
| 68 const char kStateStopped[] = "STOPPED"; | 74 const char kStateStopped[] = "STOPPED"; |
| 69 const char kStateFetchingCode[] = "FETCHING_CODE"; | 75 const char kStateFetchingCode[] = "FETCHING_CODE"; |
| 70 const char kStateActive[] = "ACTIVE"; | 76 const char kStateActive[] = "ACTIVE"; |
| 71 | 77 |
| 72 bool IsAccountManaged(Profile* profile) { | 78 bool IsAccountManaged(Profile* profile) { |
| 73 return policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile) | 79 return policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile) |
| 74 ->IsManaged(); | 80 ->IsManaged(); |
| 75 } | 81 } |
| 76 | 82 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 return true; | 227 return true; |
| 222 } | 228 } |
| 223 | 229 |
| 224 void ArcAuthService::OnInstanceReady() { | 230 void ArcAuthService::OnInstanceReady() { |
| 225 arc_bridge_service()->auth()->instance()->Init( | 231 arc_bridge_service()->auth()->instance()->Init( |
| 226 binding_.CreateInterfacePtrAndBind()); | 232 binding_.CreateInterfacePtrAndBind()); |
| 227 } | 233 } |
| 228 | 234 |
| 229 void ArcAuthService::OnBridgeStopped(ArcBridgeService::StopReason reason) { | 235 void ArcAuthService::OnBridgeStopped(ArcBridgeService::StopReason reason) { |
| 230 // TODO(crbug.com/625923): Use |reason| to report more detailed errors. | 236 // TODO(crbug.com/625923): Use |reason| to report more detailed errors. |
| 231 if (waiting_for_reply_) { | 237 if (arc_sign_in_timer_.IsRunning()) { |
| 232 // Using SERVICE_UNAVAILABLE instead of UNKNOWN_ERROR, since the latter | |
| 233 // causes this code to not try to stop ARC, so it would retry without the | |
| 234 // user noticing. | |
| 235 OnSignInFailedInternal(ProvisioningResult::ARC_STOPPED); | 238 OnSignInFailedInternal(ProvisioningResult::ARC_STOPPED); |
| 236 } | 239 } |
| 237 | 240 |
| 238 if (clear_required_) { | 241 if (clear_required_) { |
| 239 // This should be always true, but just in case as this is looked at | 242 // This should be always true, but just in case as this is looked at |
| 240 // inside RemoveArcData() at first. | 243 // inside RemoveArcData() at first. |
| 241 DCHECK(arc_bridge_service()->stopped()); | 244 DCHECK(arc_bridge_service()->stopped()); |
| 242 RemoveArcData(); | 245 RemoveArcData(); |
| 243 } else { | 246 } else { |
| 244 // To support special "Stop and enable ARC" procedure for enterprise, | 247 // To support special "Stop and enable ARC" procedure for enterprise, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 initial_opt_in_ = false; | 312 initial_opt_in_ = false; |
| 310 auth_callback_ = callback; | 313 auth_callback_ = callback; |
| 311 StartUI(); | 314 StartUI(); |
| 312 } | 315 } |
| 313 | 316 |
| 314 void ArcAuthService::OnSignInComplete() { | 317 void ArcAuthService::OnSignInComplete() { |
| 315 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 318 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 316 DCHECK_EQ(state_, State::ACTIVE); | 319 DCHECK_EQ(state_, State::ACTIVE); |
| 317 DCHECK(!sign_in_time_.is_null()); | 320 DCHECK(!sign_in_time_.is_null()); |
| 318 | 321 |
| 319 waiting_for_reply_ = false; | 322 arc_sign_in_timer_.Stop(); |
| 320 | 323 |
| 321 if (!IsOptInVerificationDisabled() && | 324 if (!IsOptInVerificationDisabled() && |
| 322 !profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn)) { | 325 !profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn)) { |
| 323 playstore_launcher_.reset( | 326 playstore_launcher_.reset( |
| 324 new ArcAppLauncher(profile_, kPlayStoreAppId, true)); | 327 new ArcAppLauncher(profile_, kPlayStoreAppId, true)); |
| 325 } | 328 } |
| 326 | 329 |
| 327 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true); | 330 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true); |
| 328 CloseUI(); | 331 CloseUI(); |
| 329 UpdateProvisioningTiming(base::Time::Now() - sign_in_time_, true, | 332 UpdateProvisioningTiming(base::Time::Now() - sign_in_time_, true, |
| 330 IsAccountManaged(profile_)); | 333 IsAccountManaged(profile_)); |
| 331 UpdateProvisioningResultUMA(ProvisioningResult::SUCCESS); | 334 UpdateProvisioningResultUMA(ProvisioningResult::SUCCESS); |
| 332 | 335 |
| 333 FOR_EACH_OBSERVER(Observer, observer_list_, OnInitialStart()); | 336 FOR_EACH_OBSERVER(Observer, observer_list_, OnInitialStart()); |
| 334 } | 337 } |
| 335 | 338 |
| 336 void ArcAuthService::OnSignInFailed(arc::mojom::ArcSignInFailureReason reason) { | 339 void ArcAuthService::OnSignInFailed(arc::mojom::ArcSignInFailureReason reason) { |
| 337 OnSignInFailedInternal( | 340 OnSignInFailedInternal( |
| 338 ConvertArcSignInFailureReasonToProvisioningResult(reason)); | 341 ConvertArcSignInFailureReasonToProvisioningResult(reason)); |
| 339 } | 342 } |
| 340 | 343 |
| 341 void ArcAuthService::OnSignInFailedInternal(ProvisioningResult result) { | 344 void ArcAuthService::OnSignInFailedInternal(ProvisioningResult result) { |
| 342 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 345 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 343 DCHECK_EQ(state_, State::ACTIVE); | 346 DCHECK_EQ(state_, State::ACTIVE); |
| 344 DCHECK(!sign_in_time_.is_null()); | 347 DCHECK(!sign_in_time_.is_null()); |
| 345 | 348 |
| 346 waiting_for_reply_ = false; | 349 arc_sign_in_timer_.Stop(); |
| 347 | 350 |
| 348 UpdateProvisioningTiming(base::Time::Now() - sign_in_time_, false, | 351 UpdateProvisioningTiming(base::Time::Now() - sign_in_time_, false, |
| 349 IsAccountManaged(profile_)); | 352 IsAccountManaged(profile_)); |
| 350 UpdateOptInCancelUMA(OptInCancelReason::CLOUD_PROVISION_FLOW_FAIL); | 353 UpdateOptInCancelUMA(OptInCancelReason::CLOUD_PROVISION_FLOW_FAIL); |
| 351 UpdateProvisioningResultUMA(result); | 354 UpdateProvisioningResultUMA(result); |
| 352 | 355 |
| 353 int error_message_id; | 356 int error_message_id; |
| 354 switch (result) { | 357 switch (result) { |
| 355 case ProvisioningResult::GMS_NETWORK_ERROR: | 358 case ProvisioningResult::GMS_NETWORK_ERROR: |
| 356 error_message_id = IDS_ARC_SIGN_IN_NETWORK_ERROR; | 359 error_message_id = IDS_ARC_SIGN_IN_NETWORK_ERROR; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 383 if (profile_->GetPrefs()->HasPrefPath(prefs::kArcSignedIn)) | 386 if (profile_->GetPrefs()->HasPrefPath(prefs::kArcSignedIn)) |
| 384 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false); | 387 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false); |
| 385 ShutdownBridgeAndShowUI(UIPage::ERROR, | 388 ShutdownBridgeAndShowUI(UIPage::ERROR, |
| 386 l10n_util::GetStringUTF16(error_message_id)); | 389 l10n_util::GetStringUTF16(error_message_id)); |
| 387 return; | 390 return; |
| 388 } | 391 } |
| 389 | 392 |
| 390 if (result == ProvisioningResult::CLOUD_PROVISION_FLOW_FAILED || | 393 if (result == ProvisioningResult::CLOUD_PROVISION_FLOW_FAILED || |
| 391 result == ProvisioningResult::CLOUD_PROVISION_FLOW_TIMEOUT || | 394 result == ProvisioningResult::CLOUD_PROVISION_FLOW_TIMEOUT || |
| 392 result == ProvisioningResult::CLOUD_PROVISION_FLOW_INTERNAL_ERROR || | 395 result == ProvisioningResult::CLOUD_PROVISION_FLOW_INTERNAL_ERROR || |
| 393 result == ProvisioningResult::UNKNOWN_ERROR) | 396 // OVERALL_SIGN_IN_TIMEOUT might be an indication that ARC believes it is |
| 397 // fully setup, but Chrome does not. |
| 398 result == ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT || |
| 399 // Just to be safe, remove data if we don't know the cause. |
| 400 result == ProvisioningResult::UNKNOWN_ERROR) { |
| 394 RemoveArcData(); | 401 RemoveArcData(); |
| 402 } |
| 395 | 403 |
| 396 // We'll delay shutting down the bridge in this case to allow people to send | 404 // We'll delay shutting down the bridge in this case to allow people to send |
| 397 // feedback. | 405 // feedback. |
| 398 ShowUI(UIPage::ERROR_WITH_FEEDBACK, | 406 ShowUI(UIPage::ERROR_WITH_FEEDBACK, |
| 399 l10n_util::GetStringUTF16(error_message_id)); | 407 l10n_util::GetStringUTF16(error_message_id)); |
| 400 } | 408 } |
| 401 | 409 |
| 402 void ArcAuthService::GetIsAccountManaged( | 410 void ArcAuthService::GetIsAccountManaged( |
| 403 const GetIsAccountManagedCallback& callback) { | 411 const GetIsAccountManagedCallback& callback) { |
| 404 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 412 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 CheckAndroidManagement(true); | 595 CheckAndroidManagement(true); |
| 588 } else { | 596 } else { |
| 589 StartArc(); | 597 StartArc(); |
| 590 } | 598 } |
| 591 } | 599 } |
| 592 | 600 |
| 593 UpdateEnabledStateUMA(true); | 601 UpdateEnabledStateUMA(true); |
| 594 } | 602 } |
| 595 | 603 |
| 596 void ArcAuthService::ShutdownBridge() { | 604 void ArcAuthService::ShutdownBridge() { |
| 605 arc_sign_in_timer_.Stop(); |
| 597 playstore_launcher_.reset(); | 606 playstore_launcher_.reset(); |
| 598 auth_callback_.Reset(); | 607 auth_callback_.Reset(); |
| 599 android_management_checker_.reset(); | 608 android_management_checker_.reset(); |
| 600 arc_bridge_service()->Shutdown(); | 609 arc_bridge_service()->Shutdown(); |
| 601 if (state_ != State::NOT_INITIALIZED) | 610 if (state_ != State::NOT_INITIALIZED) |
| 602 SetState(State::STOPPED); | 611 SetState(State::STOPPED); |
| 603 FOR_EACH_OBSERVER(Observer, observer_list_, OnShutdownBridge()); | 612 FOR_EACH_OBSERVER(Observer, observer_list_, OnShutdownBridge()); |
| 604 } | 613 } |
| 605 | 614 |
| 606 void ArcAuthService::ShutdownBridgeAndCloseUI() { | 615 void ArcAuthService::ShutdownBridgeAndCloseUI() { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 return; | 674 return; |
| 666 } | 675 } |
| 667 | 676 |
| 668 State state = state_; | 677 State state = state_; |
| 669 if (state != State::FETCHING_CODE) { | 678 if (state != State::FETCHING_CODE) { |
| 670 ShutdownBridgeAndCloseUI(); | 679 ShutdownBridgeAndCloseUI(); |
| 671 return; | 680 return; |
| 672 } | 681 } |
| 673 | 682 |
| 674 sign_in_time_ = base::Time::Now(); | 683 sign_in_time_ = base::Time::Now(); |
| 684 VLOG(1) << "Starting ARC for first sign in."; |
| 675 | 685 |
| 676 SetUIPage(UIPage::START_PROGRESS, base::string16()); | 686 SetUIPage(UIPage::START_PROGRESS, base::string16()); |
| 677 ShutdownBridge(); | 687 ShutdownBridge(); |
| 678 auth_code_ = auth_code; | 688 auth_code_ = auth_code; |
| 679 waiting_for_reply_ = true; | 689 arc_sign_in_timer_.Start(FROM_HERE, kArcSignInTimeout, |
| 690 base::Bind(&ArcAuthService::OnArcSignInTimeout, |
| 691 weak_ptr_factory_.GetWeakPtr())); |
| 680 StartArc(); | 692 StartArc(); |
| 681 } | 693 } |
| 682 | 694 |
| 695 void ArcAuthService::OnArcSignInTimeout() { |
| 696 LOG(ERROR) << "Timed out waiting for first sign in."; |
| 697 OnSignInFailedInternal(ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT); |
| 698 } |
| 699 |
| 683 void ArcAuthService::StartLso() { | 700 void ArcAuthService::StartLso() { |
| 684 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 701 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 685 | 702 |
| 686 // Update UMA only if error (with or without feedback) is currently shown. | 703 // Update UMA only if error (with or without feedback) is currently shown. |
| 687 if (ui_page_ == UIPage::ERROR) { | 704 if (ui_page_ == UIPage::ERROR) { |
| 688 UpdateOptInActionUMA(OptInActionType::RETRY); | 705 UpdateOptInActionUMA(OptInActionType::RETRY); |
| 689 } else if (ui_page_ == UIPage::ERROR_WITH_FEEDBACK) { | 706 } else if (ui_page_ == UIPage::ERROR_WITH_FEEDBACK) { |
| 690 UpdateOptInActionUMA(OptInActionType::RETRY); | 707 UpdateOptInActionUMA(OptInActionType::RETRY); |
| 691 ShutdownBridge(); | 708 ShutdownBridge(); |
| 692 } | 709 } |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 return os << kStateFetchingCode; | 876 return os << kStateFetchingCode; |
| 860 case ArcAuthService::State::ACTIVE: | 877 case ArcAuthService::State::ACTIVE: |
| 861 return os << kStateActive; | 878 return os << kStateActive; |
| 862 default: | 879 default: |
| 863 NOTREACHED(); | 880 NOTREACHED(); |
| 864 return os; | 881 return os; |
| 865 } | 882 } |
| 866 } | 883 } |
| 867 | 884 |
| 868 } // namespace arc | 885 } // namespace arc |
| OLD | NEW |