Chromium Code Reviews| Index: chrome/browser/chromeos/arc/arc_auth_service.cc |
| diff --git a/chrome/browser/chromeos/arc/arc_auth_service.cc b/chrome/browser/chromeos/arc/arc_auth_service.cc |
| index 58f9a48b753f1bd729de483e9859e22e348e6e31..2e2514d4118814ed3997c394a2522b2cac9733bb 100644 |
| --- a/chrome/browser/chromeos/arc/arc_auth_service.cc |
| +++ b/chrome/browser/chromeos/arc/arc_auth_service.cc |
| @@ -10,10 +10,14 @@ |
| #include "base/bind_helpers.h" |
| #include "base/command_line.h" |
| #include "base/lazy_instance.h" |
| +#include "base/strings/string16.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/threading/thread_checker.h" |
| +#include "chrome/browser/browser_process.h" |
| +#include "chrome/browser/browser_process_platform_part.h" |
| #include "chrome/browser/chromeos/arc/arc_auth_notification.h" |
| #include "chrome/browser/chromeos/arc/arc_optin_uma.h" |
| +#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
| #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| #include "chrome/browser/extensions/extension_util.h" |
| #include "chrome/browser/policy/profile_policy_connector.h" |
| @@ -29,6 +33,8 @@ |
| #include "chrome/grit/generated_resources.h" |
| #include "chromeos/chromeos_switches.h" |
| #include "components/arc/arc_bridge_service.h" |
| +#include "components/policy/core/browser/browser_policy_connector.h" |
| +#include "components/policy/core/common/cloud/device_management_service.h" |
| #include "components/pref_registry/pref_registry_syncable.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/signin/core/browser/profile_oauth2_token_service.h" |
| @@ -60,13 +66,21 @@ const char kArcSupportStorageId[] = "arc_support"; |
| // Skip creating UI in unit tests |
| bool disable_ui_for_testing = false; |
| +// Do check Android management requirement in browser tests. |
| +bool enable_check_android_management_for_testing = false; |
| +const char* fake_access_token = nullptr; |
| + |
| const char kStateStopped[] = "STOPPED"; |
| const char kStateFetchingCode[] = "FETCHING_CODE"; |
| const char kStateActive[] = "ACTIVE"; |
| + |
| } // namespace |
| ArcAuthService::ArcAuthService(ArcBridgeService* bridge_service) |
| - : ArcService(bridge_service), binding_(this) { |
| + : ArcService(bridge_service), |
| + OAuth2TokenService::Consumer("arc_auth_service"), |
| + binding_(this), |
| + weak_ptr_factory_(this) { |
| DCHECK(!arc_auth_service); |
| DCHECK(thread_checker.Get().CalledOnValidThread()); |
| @@ -111,6 +125,13 @@ bool ArcAuthService::IsOptInVerificationDisabled() { |
| chromeos::switches::kDisableArcOptInVerification); |
| } |
| +// static |
| +void ArcAuthService::EnableCheckAndroidManagementForTesting( |
| + const char* access_token) { |
| + enable_check_android_management_for_testing = true; |
| + fake_access_token = access_token; |
| +} |
| + |
| void ArcAuthService::OnAuthInstanceReady() { |
| arc_bridge_service()->auth_instance()->Init( |
| binding_.CreateInterfacePtrAndBind()); |
| @@ -209,7 +230,7 @@ void ArcAuthService::GetIsAccountManaged( |
| } |
| void ArcAuthService::SetState(State state) { |
| - if (state_ == state) |
| + if (state_ == state && !enable_check_android_management_for_testing) |
|
xiyuan
2016/04/26 17:48:10
Why we need this? Could ArcAuthServiceStateObserve
Polina Bondarenko
2016/04/27 15:19:57
We need this to test ManagedAndroidAccount scenari
xiyuan
2016/04/27 16:00:57
It is strange to observe a state change which does
Polina Bondarenko
2016/05/02 12:22:06
Sorry, I've missed this comment. Yes, that's much
|
| return; |
| state_ = state; |
| @@ -244,6 +265,9 @@ void ArcAuthService::OnPrimaryUserProfilePrepared(Profile* profile) { |
| // In case UI is disabled we assume that ARC is opted-in. |
| if (!IsOptInVerificationDisabled()) { |
| + if (!disable_ui_for_testing || enable_check_android_management_for_testing) |
| + StartAndroidManagementClient(); |
| + |
| pref_change_registrar_.Init(profile_->GetPrefs()); |
| pref_change_registrar_.Add( |
| prefs::kArcEnabled, |
| @@ -287,6 +311,7 @@ void ArcAuthService::Shutdown() { |
| pref_service_syncable->RemoveObserver(this); |
| pref_service_syncable->RemoveSyncedPrefObserver(prefs::kArcEnabled, this); |
| } |
| + android_management_client_.reset(); |
| pref_change_registrar_.RemoveAll(); |
| profile_ = nullptr; |
| } |
| @@ -316,8 +341,7 @@ void ArcAuthService::OnMergeSessionSuccess(const std::string& data) { |
| DCHECK(thread_checker.Get().CalledOnValidThread()); |
| DCHECK(!initial_opt_in_); |
| - context_prepared_ = true; |
| - ShowUI(UIPage::LSO_PROGRESS, base::string16()); |
| + CheckAndroidManagement(); |
| } |
| void ArcAuthService::OnMergeSessionFailure( |
| @@ -367,8 +391,13 @@ void ArcAuthService::OnOptInPreferenceChanged() { |
| initial_opt_in_ = true; |
| StartUI(); |
| } else { |
| - // Ready to start Arc. |
| - StartArc(); |
| + // Ready to start Arc, but check android management first. |
| + if (!disable_ui_for_testing || |
| + enable_check_android_management_for_testing) { |
| + CheckAndroidManagement(); |
| + } else { |
| + StartArc(); |
| + } |
| } |
| UpdateEnabledStateUMA(true); |
| @@ -385,6 +414,8 @@ void ArcAuthService::ShutdownBridge() { |
| auth_callback_.reset(); |
| ubertoken_fethcher_.reset(); |
| merger_fetcher_.reset(); |
| + token_service_ = nullptr; |
| + account_id_ = ""; |
| arc_bridge_service()->Shutdown(); |
| SetState(State::STOPPED); |
| } |
| @@ -467,7 +498,7 @@ void ArcAuthService::StartLso() { |
| void ArcAuthService::CancelAuthCode() { |
| DCHECK(thread_checker.Get().CalledOnValidThread()); |
| - if (state_ != State::FETCHING_CODE) |
| + if (state_ != State::FETCHING_CODE && ui_page_ != UIPage::ERROR) |
| return; |
| // Update UMA with user cancel only if error is not currently shown. |
| @@ -490,17 +521,17 @@ void ArcAuthService::DisableArc() { |
| void ArcAuthService::PrepareContext() { |
| DCHECK(thread_checker.Get().CalledOnValidThread()); |
| - // Get auth token to continue. |
| - ProfileOAuth2TokenService* token_service = |
| - ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| + // Get token service and account ID to fetch auth tokens. |
| + token_service_ = ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| SigninManagerBase* signin_manager = |
| SigninManagerFactory::GetForProfile(profile_); |
| - CHECK(token_service && signin_manager); |
| - const std::string& account_id = signin_manager->GetAuthenticatedAccountId(); |
| + CHECK(token_service_ && signin_manager); |
| + account_id_ = signin_manager->GetAuthenticatedAccountId(); |
| + |
| ubertoken_fethcher_.reset( |
| - new UbertokenFetcher(token_service, this, GaiaConstants::kChromeOSSource, |
| + new UbertokenFetcher(token_service_, this, GaiaConstants::kChromeOSSource, |
| storage_partition_->GetURLRequestContext())); |
| - ubertoken_fethcher_->StartFetchingToken(account_id); |
| + ubertoken_fethcher_->StartFetchingToken(account_id_); |
| } |
| void ArcAuthService::StartUI() { |
| @@ -527,6 +558,97 @@ void ArcAuthService::OnPrepareContextFailed() { |
| UpdateOptInCancelUMA(OptInCancelReason::NETWORK_ERROR); |
| } |
| +void ArcAuthService::OnGetTokenSuccess( |
| + const OAuth2TokenService::Request* request, |
| + const std::string& access_token, |
| + const base::Time& expiration_time) { |
| + DCHECK_EQ(token_request_.get(), request); |
| + android_management_client_->CheckAndroidManagement( |
| + access_token, base::Bind(&ArcAuthService::OnAndroidManagementChecked, |
| + weak_ptr_factory_.GetWeakPtr())); |
| +} |
| + |
| +void ArcAuthService::OnGetTokenFailure( |
| + const OAuth2TokenService::Request* request, |
| + const GoogleServiceAuthError& error) { |
| + DCHECK_EQ(token_request_.get(), request); |
| + OnAndroidManagementChecked( |
| + policy::AndroidManagementClient::Result::RESULT_ERROR); |
| +} |
| + |
| +void ArcAuthService::StartAndroidManagementClient() { |
| + policy::BrowserPolicyConnectorChromeOS* const connector = |
| + g_browser_process->platform_part()->browser_policy_connector_chromeos(); |
| + policy::DeviceManagementService* const service = |
| + connector->device_management_service(); |
| + service->ScheduleInitialization(0); |
| + android_management_client_.reset(new policy::AndroidManagementClient( |
| + service, g_browser_process->system_request_context())); |
| +} |
| + |
| +void ArcAuthService::CheckAndroidManagement() { |
| + // Do not send requests for Chrome OS managed users. |
| + if (policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile_) |
| + ->IsManaged()) { |
| + OnAndroidManagementChecked( |
| + policy::AndroidManagementClient::Result::RESULT_UNMANAGED); |
| + return; |
| + } |
| + |
| + // Do not send requests for well-known consumer domains. |
| + if (policy::BrowserPolicyConnector::IsNonEnterpriseUser( |
| + profile_->GetProfileUserName())) { |
| + OnAndroidManagementChecked( |
| + policy::AndroidManagementClient::Result::RESULT_UNMANAGED); |
| + return; |
| + } |
| + |
| + // Do not request access token for testing, use |fake_access_token|. |
| + if (enable_check_android_management_for_testing) { |
| + android_management_client_->CheckAndroidManagement( |
| + fake_access_token, |
| + base::Bind(&ArcAuthService::OnAndroidManagementChecked, |
| + weak_ptr_factory_.GetWeakPtr())); |
| + return; |
| + } |
| + |
| + DCHECK(!token_request_); |
| + // The user must be signed in already. |
| + DCHECK(token_service_->RefreshTokenIsAvailable(account_id_)); |
| + |
| + OAuth2TokenService::ScopeSet scopes; |
| + scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth); |
| + scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope); |
| + token_request_ = token_service_->StartRequest(account_id_, scopes, this); |
|
xiyuan
2016/04/26 17:48:09
Think we should move access token fetching etc int
Polina Bondarenko
2016/04/27 15:19:57
Done.
|
| +} |
| + |
| +void ArcAuthService::OnAndroidManagementChecked( |
| + policy::AndroidManagementClient::Result result) { |
| + switch (result) { |
| + case policy::AndroidManagementClient::Result::RESULT_UNMANAGED: |
| + context_prepared_ = true; |
| + if (!profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn)) |
| + ShowUI(UIPage::LSO_PROGRESS, base::string16()); |
| + else |
| + StartArc(); |
| + break; |
| + case policy::AndroidManagementClient::Result::RESULT_MANAGED: |
| + ShutdownBridgeAndShowUI( |
| + UIPage::ERROR, |
| + l10n_util::GetStringUTF16(IDS_ARC_ANDROID_MANAGEMENT_REQUIRED_ERROR)); |
| + UpdateOptInCancelUMA(OptInCancelReason::ANDROID_MANAGEMENT_REQUIRED); |
| + break; |
| + case policy::AndroidManagementClient::Result::RESULT_ERROR: |
| + ShutdownBridgeAndShowUI( |
| + UIPage::ERROR, |
| + l10n_util::GetStringUTF16(IDS_ARC_SERVER_COMMUNICATION_ERROR)); |
| + UpdateOptInCancelUMA(OptInCancelReason::NETWORK_ERROR); |
| + break; |
| + default: |
| + NOTREACHED(); |
| + } |
| +} |
| + |
| std::ostream& operator<<(std::ostream& os, const ArcAuthService::State& state) { |
| switch (state) { |
| case ArcAuthService::State::STOPPED: |