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

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

Issue 2507073002: Split ArcSessionManager from ArcAuthService. (Closed)
Patch Set: Fix rebase mistake Created 4 years, 1 month 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 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>
8
9 #include "ash/common/shelf/shelf_delegate.h"
10 #include "ash/common/wm_shell.h"
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h" 7 #include "base/command_line.h"
14 #include "base/logging.h" 8 #include "base/logging.h"
15 #include "base/strings/string16.h" 9 #include "base/memory/ptr_util.h"
16 #include "base/time/time.h"
17 #include "chrome/browser/chromeos/arc/arc_auth_code_fetcher.h" 10 #include "chrome/browser/chromeos/arc/arc_auth_code_fetcher.h"
18 #include "chrome/browser/chromeos/arc/arc_auth_context.h"
19 #include "chrome/browser/chromeos/arc/arc_optin_uma.h" 11 #include "chrome/browser/chromeos/arc/arc_optin_uma.h"
20 #include "chrome/browser/chromeos/arc/arc_support_host.h" 12 #include "chrome/browser/chromeos/arc/arc_optin_uma.h"
13 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
21 #include "chrome/browser/chromeos/arc/auth/arc_robot_auth.h" 14 #include "chrome/browser/chromeos/arc/auth/arc_robot_auth.h"
22 #include "chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.h"
23 #include "chrome/browser/chromeos/arc/policy/arc_android_management_checker.h"
24 #include "chrome/browser/chromeos/arc/policy/arc_policy_util.h" 15 #include "chrome/browser/chromeos/arc/policy/arc_policy_util.h"
25 #include "chrome/browser/chromeos/profiles/profile_helper.h"
26 #include "chrome/browser/lifetime/application_lifetime.h" 16 #include "chrome/browser/lifetime/application_lifetime.h"
27 #include "chrome/browser/policy/profile_policy_connector.h"
28 #include "chrome/browser/policy/profile_policy_connector_factory.h"
29 #include "chrome/browser/prefs/pref_service_syncable_util.h"
30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/browser/ui/app_list/arc/arc_app_launcher.h"
32 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
33 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
34 #include "chrome/browser/ui/browser_commands.h"
35 #include "chrome/common/pref_names.h"
36 #include "chrome/grit/generated_resources.h"
37 #include "chromeos/chromeos_switches.h" 17 #include "chromeos/chromeos_switches.h"
38 #include "chromeos/cryptohome/cryptohome_parameters.h"
39 #include "chromeos/dbus/dbus_thread_manager.h"
40 #include "chromeos/dbus/session_manager_client.h"
41 #include "components/arc/arc_bridge_service.h" 18 #include "components/arc/arc_bridge_service.h"
42 #include "components/pref_registry/pref_registry_syncable.h"
43 #include "components/prefs/pref_service.h"
44 #include "components/sync_preferences/pref_service_syncable.h"
45 #include "components/user_manager/user.h"
46 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
47 #include "extensions/browser/extension_prefs.h"
48 20
49 namespace arc { 21 namespace arc {
50
51 namespace { 22 namespace {
52 23
53 constexpr size_t kMinVersionForOnAccountInfoReady = 5;
54
55 // Weak pointer. This class is owned by ArcServiceManager.
56 ArcAuthService* g_arc_auth_service = nullptr; 24 ArcAuthService* g_arc_auth_service = nullptr;
57 25
58 // Skip creating UI in unit tests 26 constexpr uint32_t kMinVersionForOnAccountInfoReady = 5;
59 bool g_disable_ui_for_testing = false;
60 27
61 // Use specified ash::ShelfDelegate for unit tests. 28 // Convers mojom::ArcSignInFailureReason into ProvisiningResult.
62 ash::ShelfDelegate* g_shelf_delegate_for_testing = nullptr;
63
64 // The Android management check is disabled by default, it's used only for
65 // testing.
66 bool g_enable_check_android_management_for_testing = false;
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
73 ash::ShelfDelegate* GetShelfDelegate() {
74 if (g_shelf_delegate_for_testing)
75 return g_shelf_delegate_for_testing;
76 if (ash::WmShell::HasInstance()) {
77 DCHECK(ash::WmShell::Get()->shelf_delegate());
78 return ash::WmShell::Get()->shelf_delegate();
79 }
80 return nullptr;
81 }
82
83 ProvisioningResult ConvertArcSignInFailureReasonToProvisioningResult( 29 ProvisioningResult ConvertArcSignInFailureReasonToProvisioningResult(
84 mojom::ArcSignInFailureReason reason) { 30 mojom::ArcSignInFailureReason reason) {
85 using ArcSignInFailureReason = mojom::ArcSignInFailureReason; 31 using ArcSignInFailureReason = mojom::ArcSignInFailureReason;
86 32
87 #define MAP_PROVISIONING_RESULT(name) \ 33 #define MAP_PROVISIONING_RESULT(name) \
88 case ArcSignInFailureReason::name: \ 34 case ArcSignInFailureReason::name: \
89 return ProvisioningResult::name 35 return ProvisioningResult::name
90 36
91 switch (reason) { 37 switch (reason) {
92 MAP_PROVISIONING_RESULT(UNKNOWN_ERROR); 38 MAP_PROVISIONING_RESULT(UNKNOWN_ERROR);
(...skipping 11 matching lines...) Expand all
104 MAP_PROVISIONING_RESULT(CLOUD_PROVISION_FLOW_FAILED); 50 MAP_PROVISIONING_RESULT(CLOUD_PROVISION_FLOW_FAILED);
105 MAP_PROVISIONING_RESULT(CLOUD_PROVISION_FLOW_TIMEOUT); 51 MAP_PROVISIONING_RESULT(CLOUD_PROVISION_FLOW_TIMEOUT);
106 MAP_PROVISIONING_RESULT(CLOUD_PROVISION_FLOW_INTERNAL_ERROR); 52 MAP_PROVISIONING_RESULT(CLOUD_PROVISION_FLOW_INTERNAL_ERROR);
107 } 53 }
108 #undef MAP_PROVISIONING_RESULT 54 #undef MAP_PROVISIONING_RESULT
109 55
110 NOTREACHED() << "unknown reason: " << static_cast<int>(reason); 56 NOTREACHED() << "unknown reason: " << static_cast<int>(reason);
111 return ProvisioningResult::UNKNOWN_ERROR; 57 return ProvisioningResult::UNKNOWN_ERROR;
112 } 58 }
113 59
114 bool IsArcKioskMode() {
115 return user_manager::UserManager::Get()->IsLoggedInAsArcKioskApp();
116 }
117
118 mojom::ChromeAccountType GetAccountType() { 60 mojom::ChromeAccountType GetAccountType() {
119 if (IsArcKioskMode()) 61 return ArcSessionManager::IsArcKioskMode()
120 return mojom::ChromeAccountType::ROBOT_ACCOUNT; 62 ? mojom::ChromeAccountType::ROBOT_ACCOUNT
121 return mojom::ChromeAccountType::USER_ACCOUNT; 63 : mojom::ChromeAccountType::USER_ACCOUNT;
122 } 64 }
123 65
124 } // namespace 66 } // namespace
125 67
126 // TODO(lhchavez): Get rid of this class once we can safely remove all the 68 // TODO(lhchavez): Get rid of this class once we can safely remove all the
127 // deprecated interfaces and only need to care about one type of callback. 69 // deprecated interfaces and only need to care about one type of callback.
128 class ArcAuthService::AccountInfoNotifier { 70 class ArcAuthService::AccountInfoNotifier {
129 public: 71 public:
130 explicit AccountInfoNotifier( 72 explicit AccountInfoNotifier(
131 const GetAuthCodeDeprecatedCallback& auth_callback) 73 const GetAuthCodeDeprecatedCallback& auth_callback)
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 enum class CallbackType { AUTH_CODE, AUTH_CODE_AND_ACCOUNT, ACCOUNT_INFO }; 115 enum class CallbackType { AUTH_CODE, AUTH_CODE_AND_ACCOUNT, ACCOUNT_INFO };
174 116
175 const CallbackType callback_type_; 117 const CallbackType callback_type_;
176 const GetAuthCodeDeprecatedCallback auth_callback_; 118 const GetAuthCodeDeprecatedCallback auth_callback_;
177 const GetAuthCodeAndAccountTypeDeprecatedCallback auth_account_callback_; 119 const GetAuthCodeAndAccountTypeDeprecatedCallback auth_account_callback_;
178 const AccountInfoCallback account_info_callback_; 120 const AccountInfoCallback account_info_callback_;
179 }; 121 };
180 122
181 ArcAuthService::ArcAuthService(ArcBridgeService* bridge_service) 123 ArcAuthService::ArcAuthService(ArcBridgeService* bridge_service)
182 : ArcService(bridge_service), binding_(this), weak_ptr_factory_(this) { 124 : ArcService(bridge_service), binding_(this), weak_ptr_factory_(this) {
183 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
184 DCHECK(!g_arc_auth_service); 125 DCHECK(!g_arc_auth_service);
185
186 g_arc_auth_service = this; 126 g_arc_auth_service = this;
187
188 arc_bridge_service()->AddObserver(this);
189 arc_bridge_service()->auth()->AddObserver(this); 127 arc_bridge_service()->auth()->AddObserver(this);
190 } 128 }
191 129
192 ArcAuthService::~ArcAuthService() { 130 ArcAuthService::~ArcAuthService() {
193 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 131 arc_bridge_service()->auth()->RemoveObserver(this);
194 DCHECK_EQ(this, g_arc_auth_service);
195 132
196 Shutdown(); 133 DCHECK_EQ(g_arc_auth_service, this);
197 arc_bridge_service()->auth()->RemoveObserver(this);
198 arc_bridge_service()->RemoveObserver(this);
199
200 g_arc_auth_service = nullptr; 134 g_arc_auth_service = nullptr;
201 } 135 }
202 136
203 // static 137 // static
204 ArcAuthService* ArcAuthService::Get() { 138 ArcAuthService* ArcAuthService::GetForTest() {
205 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 139 DCHECK(g_arc_auth_service);
206 return g_arc_auth_service; 140 return g_arc_auth_service;
207 } 141 }
208 142
209 // static
210 void ArcAuthService::RegisterProfilePrefs(
211 user_prefs::PrefRegistrySyncable* registry) {
212 // TODO(dspaid): Implement a mechanism to allow this to sync on first boot
213 // only.
214 registry->RegisterBooleanPref(prefs::kArcEnabled, false);
215 registry->RegisterBooleanPref(prefs::kArcSignedIn, false);
216 registry->RegisterBooleanPref(prefs::kArcTermsAccepted, false);
217 registry->RegisterBooleanPref(prefs::kArcBackupRestoreEnabled, true);
218 registry->RegisterBooleanPref(prefs::kArcLocationServiceEnabled, true);
219 }
220
221 // static
222 void ArcAuthService::DisableUIForTesting() {
223 g_disable_ui_for_testing = true;
224 }
225
226 // static
227 void ArcAuthService::SetShelfDelegateForTesting(
228 ash::ShelfDelegate* shelf_delegate) {
229 g_shelf_delegate_for_testing = shelf_delegate;
230 }
231
232 // static
233 bool ArcAuthService::IsOptInVerificationDisabled() {
234 return base::CommandLine::ForCurrentProcess()->HasSwitch(
235 chromeos::switches::kDisableArcOptInVerification);
236 }
237
238 // static
239 void ArcAuthService::EnableCheckAndroidManagementForTesting() {
240 g_enable_check_android_management_for_testing = true;
241 }
242
243 // static
244 bool ArcAuthService::IsAllowedForProfile(const Profile* profile) {
245 if (!ArcBridgeService::GetEnabled(base::CommandLine::ForCurrentProcess())) {
246 VLOG(1) << "Arc is not enabled.";
247 return false;
248 }
249
250 if (!profile) {
251 VLOG(1) << "ARC is not supported for systems without profile.";
252 return false;
253 }
254
255 if (!chromeos::ProfileHelper::IsPrimaryProfile(profile)) {
256 VLOG(1) << "Non-primary users are not supported in ARC.";
257 return false;
258 }
259
260 if (profile->IsLegacySupervised()) {
261 VLOG(1) << "Supervised users are not supported in ARC.";
262 return false;
263 }
264
265 user_manager::User const* const user =
266 chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
267 if ((!user || !user->HasGaiaAccount()) && !IsArcKioskMode()) {
268 VLOG(1) << "Users without GAIA accounts are not supported in ARC.";
269 return false;
270 }
271
272 if (user_manager::UserManager::Get()
273 ->IsCurrentUserCryptohomeDataEphemeral()) {
274 VLOG(2) << "Users with ephemeral data are not supported in Arc.";
275 return false;
276 }
277
278 return true;
279 }
280
281 void ArcAuthService::OnInstanceReady() { 143 void ArcAuthService::OnInstanceReady() {
282 auto* instance = arc_bridge_service()->auth()->GetInstanceForMethod("Init"); 144 auto* instance = arc_bridge_service()->auth()->GetInstanceForMethod("Init");
283 DCHECK(instance); 145 DCHECK(instance);
284 instance->Init(binding_.CreateInterfacePtrAndBind()); 146 instance->Init(binding_.CreateInterfacePtrAndBind());
285 } 147 }
286 148
287 void ArcAuthService::OnBridgeStopped(ArcBridgeService::StopReason reason) { 149 void ArcAuthService::OnInstanceClosed() {
288 // TODO(crbug.com/625923): Use |reason| to report more detailed errors. 150 ArcSupportHost* support_host = ArcSessionManager::Get()->support_host();
289 if (arc_sign_in_timer_.IsRunning()) { 151 if (support_host)
290 OnProvisioningFinished(ProvisioningResult::ARC_STOPPED); 152 support_host->RemoveObserver(this);
291 } 153 notifier_.reset();
292 154 arc_robot_auth_.reset();
293 if (clear_required_) { 155 auth_code_fetcher_.reset();
294 // This should be always true, but just in case as this is looked at
295 // inside RemoveArcData() at first.
296 DCHECK(arc_bridge_service()->stopped());
297 RemoveArcData();
298 } else {
299 // To support special "Stop and enable ARC" procedure for enterprise,
300 // here call OnArcDataRemoved(true) as if the data removal is successfully
301 // done.
302 // TODO(hidehiko): Restructure the code. crbug.com/665316
303 base::ThreadTaskRunnerHandle::Get()->PostTask(
304 FROM_HERE, base::Bind(&ArcAuthService::OnArcDataRemoved,
305 weak_ptr_factory_.GetWeakPtr(), true));
306 }
307 } 156 }
308 157
309 void ArcAuthService::RemoveArcData() { 158 void ArcAuthService::OnSignInComplete() {
310 if (!arc_bridge_service()->stopped()) { 159 ArcSessionManager::Get()->OnProvisioningFinished(ProvisioningResult::SUCCESS);
311 // Just set a flag. On bridge stopped, this will be re-called,
312 // then session manager should remove the data.
313 clear_required_ = true;
314 return;
315 }
316 clear_required_ = false;
317 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->RemoveArcData(
318 cryptohome::Identification(
319 multi_user_util::GetAccountIdFromProfile(profile_)),
320 base::Bind(&ArcAuthService::OnArcDataRemoved,
321 weak_ptr_factory_.GetWeakPtr()));
322 } 160 }
323 161
324 void ArcAuthService::OnArcDataRemoved(bool success) { 162 void ArcAuthService::OnSignInFailed(mojom::ArcSignInFailureReason reason) {
325 LOG_IF(ERROR, !success) << "Required ARC user data wipe failed."; 163 ArcSessionManager::Get()->OnProvisioningFinished(
164 ConvertArcSignInFailureReasonToProvisioningResult(reason));
165 }
326 166
327 // Here check if |reenable_arc_| is marked or not. 167 void ArcAuthService::RequestAccountInfo() {
328 // The only case this happens should be in the special case for enterprise 168 RequestAccountInfoInternal(
329 // "on managed lost" case. In that case, OnBridgeStopped() should trigger 169 base::MakeUnique<ArcAuthService::AccountInfoNotifier>(
330 // the RemoveArcData(), then this. 170 base::Bind(&ArcAuthService::OnAccountInfoReady,
331 // TODO(hidehiko): Restructure the code. 171 weak_ptr_factory_.GetWeakPtr())));
332 if (!reenable_arc_)
333 return;
334
335 // Restart ARC anyway. Let the enterprise reporting instance decide whether
336 // the ARC user data wipe is still required or not.
337 reenable_arc_ = false;
338 VLOG(1) << "Reenable ARC";
339 EnableArc();
340 } 172 }
341 173
342 void ArcAuthService::GetAuthCodeDeprecated0( 174 void ArcAuthService::GetAuthCodeDeprecated0(
343 const GetAuthCodeDeprecated0Callback& callback) { 175 const GetAuthCodeDeprecated0Callback& callback) {
344 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 176 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
345 NOTREACHED() << "GetAuthCodeDeprecated0() should no longer be callable"; 177 NOTREACHED() << "GetAuthCodeDeprecated0() should no longer be callable";
346 } 178 }
347 179
348 void ArcAuthService::GetAuthCodeDeprecated( 180 void ArcAuthService::GetAuthCodeDeprecated(
349 const GetAuthCodeDeprecatedCallback& callback) { 181 const GetAuthCodeDeprecatedCallback& callback) {
350 // For robot account we must use RequestAccountInfo because it allows 182 // For robot account we must use RequestAccountInfo because it allows
351 // to specify account type. 183 // to specify account type.
352 DCHECK(!IsArcKioskMode()); 184 DCHECK(!ArcSessionManager::IsArcKioskMode());
353 RequestAccountInfoInternal( 185 RequestAccountInfoInternal(
354 base::MakeUnique<ArcAuthService::AccountInfoNotifier>(callback)); 186 base::MakeUnique<ArcAuthService::AccountInfoNotifier>(callback));
355 } 187 }
356 188
357 void ArcAuthService::GetAuthCodeAndAccountTypeDeprecated( 189 void ArcAuthService::GetAuthCodeAndAccountTypeDeprecated(
358 const GetAuthCodeAndAccountTypeDeprecatedCallback& callback) { 190 const GetAuthCodeAndAccountTypeDeprecatedCallback& callback) {
359 RequestAccountInfoInternal( 191 RequestAccountInfoInternal(
360 base::MakeUnique<ArcAuthService::AccountInfoNotifier>(callback)); 192 base::MakeUnique<ArcAuthService::AccountInfoNotifier>(callback));
361 } 193 }
362 194
363 void ArcAuthService::RequestAccountInfo() { 195 void ArcAuthService::GetIsAccountManagedDeprecated(
364 RequestAccountInfoInternal( 196 const GetIsAccountManagedDeprecatedCallback& callback) {
365 base::MakeUnique<ArcAuthService::AccountInfoNotifier>(
366 base::Bind(&ArcAuthService::OnAccountInfoReady,
367 weak_ptr_factory_.GetWeakPtr())));
368 }
369
370 void ArcAuthService::OnAccountInfoReady(mojom::AccountInfoPtr account_info) {
371 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 197 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
372 auto* instance = arc_bridge_service()->auth()->GetInstanceForMethod( 198 callback.Run(
373 "OnAccountInfoReady", kMinVersionForOnAccountInfoReady); 199 policy_util::IsAccountManaged(ArcSessionManager::Get()->profile()));
374 DCHECK(instance);
375 instance->OnAccountInfoReady(std::move(account_info));
376 } 200 }
377 201
378 void ArcAuthService::RequestAccountInfoInternal( 202 void ArcAuthService::RequestAccountInfoInternal(
379 std::unique_ptr<ArcAuthService::AccountInfoNotifier> 203 std::unique_ptr<AccountInfoNotifier> notifier) {
380 account_info_notifier) {
381 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 204 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
382 // No other auth code-related operation may be in progress. 205 // No other auth code-related operation may be in progress.
383 DCHECK(!account_info_notifier_); 206 DCHECK(!notifier_);
384 207
385 if (IsOptInVerificationDisabled()) { 208 if (ArcSessionManager::IsOptInVerificationDisabled()) {
386 account_info_notifier->Notify(false /* = is_enforced */, std::string(), 209 notifier->Notify(
387 GetAccountType(), 210 false /* = is_enforced */, std::string(), GetAccountType(),
388 policy_util::IsAccountManaged(profile_)); 211 policy_util::IsAccountManaged(ArcSessionManager::Get()->profile()));
389 return; 212 return;
390 } 213 }
391 214
392 // Hereafter asynchronous operation. Remember the notifier. 215 // Hereafter asynchronous operation. Remember the notifier.
393 account_info_notifier_ = std::move(account_info_notifier); 216 notifier_ = std::move(notifier);
394 217
395 // In Kiosk mode, use Robot auth code fetching. 218 // In Kiosk mode, use Robot auth code fetching.
396 if (IsArcKioskMode()) { 219 if (ArcSessionManager::IsArcKioskMode()) {
397 arc_robot_auth_.reset(new ArcRobotAuth()); 220 arc_robot_auth_.reset(new ArcRobotAuth());
398 arc_robot_auth_->FetchRobotAuthCode( 221 arc_robot_auth_->FetchRobotAuthCode(
399 base::Bind(&ArcAuthService::OnRobotAuthCodeFetched, 222 base::Bind(&ArcAuthService::OnRobotAuthCodeFetched,
400 weak_ptr_factory_.GetWeakPtr())); 223 weak_ptr_factory_.GetWeakPtr()));
401 return; 224 return;
402 } 225 }
403 226
404 // If endpoint is passed via command line flag, use automatic auth code 227 // If endpoint is passed via command line flag, use automatic auth code
405 // fetching. 228 // fetching.
406 const base::CommandLine* command_line = 229 const base::CommandLine* command_line =
407 base::CommandLine::ForCurrentProcess(); 230 base::CommandLine::ForCurrentProcess();
231 std::string auth_endpoint;
408 if (command_line->HasSwitch(chromeos::switches::kArcUseAuthEndpoint)) { 232 if (command_line->HasSwitch(chromeos::switches::kArcUseAuthEndpoint)) {
409 std::string auth_endpoint = command_line->GetSwitchValueASCII( 233 auth_endpoint = command_line->GetSwitchValueASCII(
410 chromeos::switches::kArcUseAuthEndpoint); 234 chromeos::switches::kArcUseAuthEndpoint);
411 if (!auth_endpoint.empty()) { 235 }
412 DCHECK(!auth_code_fetcher_); 236 if (!auth_endpoint.empty()) {
413 auth_code_fetcher_ = base::MakeUnique<ArcAuthCodeFetcher>( 237 DCHECK(!auth_code_fetcher_);
414 profile_, context_.get(), auth_endpoint); 238 auth_code_fetcher_ = base::MakeUnique<ArcAuthCodeFetcher>(
415 auth_code_fetcher_->Fetch(base::Bind(&ArcAuthService::OnAuthCodeFetched, 239 ArcSessionManager::Get()->profile(),
416 weak_ptr_factory_.GetWeakPtr())); 240 ArcSessionManager::Get()->auth_context(), auth_endpoint);
417 return; 241 auth_code_fetcher_->Fetch(base::Bind(&ArcAuthService::OnAuthCodeFetched,
418 } 242 weak_ptr_factory_.GetWeakPtr()));
243 return;
419 } 244 }
420 245
421 // Otherwise, show LSO page to user after HTTP context preparation, and let 246 // Otherwise, show LSO page to user after HTTP context preparation, and let
422 // them click "Sign in" button. 247 // them click "Sign in" button.
423 DCHECK(context_); 248 ArcSessionManager::Get()->auth_context()->Prepare(base::Bind(
424 context_->Prepare(base::Bind(&ArcAuthService::OnContextPrepared, 249 &ArcAuthService::OnContextPrepared, weak_ptr_factory_.GetWeakPtr()));
425 weak_ptr_factory_.GetWeakPtr()));
426 } 250 }
427 251
428 void ArcAuthService::OnContextPrepared( 252 void ArcAuthService::OnContextPrepared(
429 net::URLRequestContextGetter* request_context_getter) { 253 net::URLRequestContextGetter* request_context_getter) {
430 if (!support_host_) 254 ArcSupportHost* support_host = ArcSessionManager::Get()->support_host();
431 return; 255 // Here, support_host should be available always. The case support_host is
256 // not created is when 1) IsOptInVerificationDisabled() is true or 2)
257 // IsArcKioskMode() is true. Both cases are handled above.
258 DCHECK(support_host);
259 if (!support_host->HasObserver(this))
260 support_host->AddObserver(this);
432 261
433 if (request_context_getter) { 262 if (request_context_getter) {
434 support_host_->ShowLso(); 263 support_host->ShowLso();
435 } else { 264 } else {
436 support_host_->ShowError(ArcSupportHost::Error::SIGN_IN_NETWORK_ERROR, 265 support_host->ShowError(ArcSupportHost::Error::SIGN_IN_NETWORK_ERROR,
437 false); 266 false);
438 } 267 }
439 } 268 }
440 269
270 void ArcAuthService::OnAccountInfoReady(mojom::AccountInfoPtr account_info) {
271 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
272 auto* instance = arc_bridge_service()->auth()->GetInstanceForMethod(
273 "OnAccountInfoReady", kMinVersionForOnAccountInfoReady);
274 DCHECK(instance);
275 instance->OnAccountInfoReady(std::move(account_info));
276 }
277
441 void ArcAuthService::OnRobotAuthCodeFetched( 278 void ArcAuthService::OnRobotAuthCodeFetched(
442 const std::string& robot_auth_code) { 279 const std::string& robot_auth_code) {
443 // We fetching robot auth code for ARC kiosk only. 280 // We fetching robot auth code for ARC kiosk only.
444 DCHECK(IsArcKioskMode()); 281 DCHECK(ArcSessionManager::IsArcKioskMode());
445 282
446 // Current instance of ArcRobotAuth became useless. 283 // Current instance of ArcRobotAuth became useless.
447 arc_robot_auth_.reset(); 284 arc_robot_auth_.reset();
448 285
449 if (robot_auth_code.empty()) { 286 if (robot_auth_code.empty()) {
450 VLOG(1) << "Robot account auth code fetching error"; 287 VLOG(1) << "Robot account auth code fetching error";
451 // Log out the user. All the cleanup will be done in Shutdown() method. 288 // Log out the user. All the cleanup will be done in Shutdown() method.
452 // The callback is not called because auth code is empty. 289 // The callback is not called because auth code is empty.
453 chrome::AttemptUserExit(); 290 chrome::AttemptUserExit();
454 return; 291 return;
455 } 292 }
456 293
457 OnAuthCodeObtained(robot_auth_code); 294 OnAuthCodeObtained(robot_auth_code);
458 } 295 }
459 296
460 void ArcAuthService::OnAuthCodeFetched(const std::string& auth_code) { 297 void ArcAuthService::OnAuthCodeFetched(const std::string& auth_code) {
461 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 298 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
462 auth_code_fetcher_.reset(); 299 auth_code_fetcher_.reset();
463 300
464 if (auth_code.empty()) { 301 if (auth_code.empty()) {
465 OnProvisioningFinished( 302 ArcSessionManager::Get()->OnProvisioningFinished(
466 ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR); 303 ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR);
467 return; 304 return;
468 } 305 }
469 306
470 OnAuthCodeObtained(auth_code); 307 OnAuthCodeObtained(auth_code);
471 } 308 }
472 309
473 void ArcAuthService::OnSignInComplete() {
474 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
475 DCHECK_EQ(state_, State::ACTIVE);
476 OnProvisioningFinished(ProvisioningResult::SUCCESS);
477 }
478
479 void ArcAuthService::OnSignInFailed(mojom::ArcSignInFailureReason reason) {
480 OnProvisioningFinished(
481 ConvertArcSignInFailureReasonToProvisioningResult(reason));
482 }
483
484 void ArcAuthService::OnProvisioningFinished(ProvisioningResult result) {
485 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
486 DCHECK_EQ(state_, State::ACTIVE);
487
488 if (result == ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR) {
489 // For backwards compatibility, use NETWORK_ERROR for
490 // CHROME_SERVER_COMMUNICATION_ERROR case.
491 UpdateOptInCancelUMA(OptInCancelReason::NETWORK_ERROR);
492 } else if (!sign_in_time_.is_null()) {
493 arc_sign_in_timer_.Stop();
494
495 UpdateProvisioningTiming(base::Time::Now() - sign_in_time_,
496 result == ProvisioningResult::SUCCESS,
497 policy_util::IsAccountManaged(profile_));
498 UpdateProvisioningResultUMA(result,
499 policy_util::IsAccountManaged(profile_));
500 if (result != ProvisioningResult::SUCCESS)
501 UpdateOptInCancelUMA(OptInCancelReason::CLOUD_PROVISION_FLOW_FAIL);
502 }
503
504 if (result == ProvisioningResult::SUCCESS) {
505 if (support_host_)
506 support_host_->Close();
507
508 if (profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn))
509 return;
510
511 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true);
512 // Don't show Play Store app for ARC Kiosk because the only one UI in kiosk
513 // mode must be the kiosk app and device is not needed for opt-in.
514 if (!IsOptInVerificationDisabled() && !IsArcKioskMode()) {
515 playstore_launcher_.reset(
516 new ArcAppLauncher(profile_, kPlayStoreAppId, true));
517 }
518
519 for (auto& observer : observer_list_)
520 observer.OnInitialStart();
521 return;
522 }
523
524 ArcSupportHost::Error error;
525 switch (result) {
526 case ProvisioningResult::GMS_NETWORK_ERROR:
527 error = ArcSupportHost::Error::SIGN_IN_NETWORK_ERROR;
528 break;
529 case ProvisioningResult::GMS_SERVICE_UNAVAILABLE:
530 case ProvisioningResult::GMS_SIGN_IN_FAILED:
531 case ProvisioningResult::GMS_SIGN_IN_TIMEOUT:
532 case ProvisioningResult::GMS_SIGN_IN_INTERNAL_ERROR:
533 error = ArcSupportHost::Error::SIGN_IN_SERVICE_UNAVAILABLE_ERROR;
534 break;
535 case ProvisioningResult::GMS_BAD_AUTHENTICATION:
536 error = ArcSupportHost::Error::SIGN_IN_BAD_AUTHENTICATION_ERROR;
537 break;
538 case ProvisioningResult::DEVICE_CHECK_IN_FAILED:
539 case ProvisioningResult::DEVICE_CHECK_IN_TIMEOUT:
540 case ProvisioningResult::DEVICE_CHECK_IN_INTERNAL_ERROR:
541 error = ArcSupportHost::Error::SIGN_IN_GMS_NOT_AVAILABLE_ERROR;
542 break;
543 case ProvisioningResult::CLOUD_PROVISION_FLOW_FAILED:
544 case ProvisioningResult::CLOUD_PROVISION_FLOW_TIMEOUT:
545 case ProvisioningResult::CLOUD_PROVISION_FLOW_INTERNAL_ERROR:
546 error = ArcSupportHost::Error::SIGN_IN_CLOUD_PROVISION_FLOW_FAIL_ERROR;
547 break;
548 case ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR:
549 error = ArcSupportHost::Error::SERVER_COMMUNICATION_ERROR;
550 break;
551 default:
552 error = ArcSupportHost::Error::SIGN_IN_UNKNOWN_ERROR;
553 break;
554 }
555
556 if (result == ProvisioningResult::ARC_STOPPED ||
557 result == ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR) {
558 if (profile_->GetPrefs()->HasPrefPath(prefs::kArcSignedIn))
559 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false);
560 ShutdownBridge();
561 if (support_host_)
562 support_host_->ShowError(error, false);
563 return;
564 }
565
566 if (result == ProvisioningResult::CLOUD_PROVISION_FLOW_FAILED ||
567 result == ProvisioningResult::CLOUD_PROVISION_FLOW_TIMEOUT ||
568 result == ProvisioningResult::CLOUD_PROVISION_FLOW_INTERNAL_ERROR ||
569 // OVERALL_SIGN_IN_TIMEOUT might be an indication that ARC believes it is
570 // fully setup, but Chrome does not.
571 result == ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT ||
572 // Just to be safe, remove data if we don't know the cause.
573 result == ProvisioningResult::UNKNOWN_ERROR) {
574 RemoveArcData();
575 }
576
577 // We'll delay shutting down the bridge in this case to allow people to send
578 // feedback.
579 if (support_host_)
580 support_host_->ShowError(error, true /* = show send feedback button */);
581 }
582
583 void ArcAuthService::GetIsAccountManagedDeprecated(
584 const GetIsAccountManagedDeprecatedCallback& callback) {
585 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
586
587 callback.Run(policy_util::IsAccountManaged(profile_));
588 }
589
590 void ArcAuthService::SetState(State state) {
591 state_ = state;
592 }
593
594 bool ArcAuthService::IsAllowed() const {
595 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
596 return profile_ != nullptr;
597 }
598
599 void ArcAuthService::OnPrimaryUserProfilePrepared(Profile* profile) {
600 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
601 DCHECK(profile && profile != profile_);
602
603 Shutdown();
604
605 if (!IsAllowedForProfile(profile))
606 return;
607
608 // TODO(khmel): Move this to IsAllowedForProfile.
609 if (policy_util::IsArcDisabledForEnterprise() &&
610 policy_util::IsAccountManaged(profile)) {
611 VLOG(2) << "Enterprise users are not supported in ARC.";
612 return;
613 }
614
615 profile_ = profile;
616
617 // Create the support host at initialization. Note that, practically,
618 // ARC support Chrome app is rarely used (only opt-in and re-auth flow).
619 // So, it may be better to initialize it lazily.
620 // TODO(hidehiko): Revisit to think about lazy initialization.
621 //
622 // Don't show UI for ARC Kiosk because the only one UI in kiosk mode must
623 // be the kiosk app. In case of error the UI will be useless as well, because
624 // in typical use case there will be no one nearby the kiosk device, who can
625 // do some action to solve the problem be means of UI.
626 if (!g_disable_ui_for_testing && !IsOptInVerificationDisabled() &&
627 !IsArcKioskMode()) {
628 DCHECK(!support_host_);
629 support_host_ = base::MakeUnique<ArcSupportHost>(profile_);
630 support_host_->AddObserver(this);
631
632 preference_handler_ = base::MakeUnique<arc::ArcOptInPreferenceHandler>(
633 this, profile_->GetPrefs());
634 // This automatically updates all preferences.
635 preference_handler_->Start();
636 }
637
638 DCHECK_EQ(State::NOT_INITIALIZED, state_);
639 SetState(State::STOPPED);
640
641 PrefServiceSyncableFromProfile(profile_)->AddSyncedPrefObserver(
642 prefs::kArcEnabled, this);
643
644 context_.reset(new ArcAuthContext(profile_));
645
646 if (!g_disable_ui_for_testing ||
647 g_enable_check_android_management_for_testing) {
648 ArcAndroidManagementChecker::StartClient();
649 }
650 pref_change_registrar_.Init(profile_->GetPrefs());
651 pref_change_registrar_.Add(
652 prefs::kArcEnabled, base::Bind(&ArcAuthService::OnOptInPreferenceChanged,
653 weak_ptr_factory_.GetWeakPtr()));
654 if (profile_->GetPrefs()->GetBoolean(prefs::kArcEnabled)) {
655 OnOptInPreferenceChanged();
656 } else {
657 RemoveArcData();
658 PrefServiceSyncableFromProfile(profile_)->AddObserver(this);
659 OnIsSyncingChanged();
660 }
661 }
662
663 void ArcAuthService::OnIsSyncingChanged() {
664 sync_preferences::PrefServiceSyncable* const pref_service_syncable =
665 PrefServiceSyncableFromProfile(profile_);
666 if (!pref_service_syncable->IsSyncing())
667 return;
668
669 pref_service_syncable->RemoveObserver(this);
670
671 if (IsArcEnabled())
672 OnOptInPreferenceChanged();
673 }
674
675 void ArcAuthService::Shutdown() {
676 ShutdownBridge();
677 if (support_host_) {
678 support_host_->Close();
679 support_host_->RemoveObserver(this);
680 support_host_.reset();
681 }
682 if (profile_) {
683 sync_preferences::PrefServiceSyncable* pref_service_syncable =
684 PrefServiceSyncableFromProfile(profile_);
685 pref_service_syncable->RemoveObserver(this);
686 pref_service_syncable->RemoveSyncedPrefObserver(prefs::kArcEnabled, this);
687 }
688 pref_change_registrar_.RemoveAll();
689 context_.reset();
690 profile_ = nullptr;
691 arc_robot_auth_.reset();
692 SetState(State::NOT_INITIALIZED);
693 }
694
695 void ArcAuthService::OnSyncedPrefChanged(const std::string& path,
696 bool from_sync) {
697 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
698
699 // Update UMA only for local changes
700 if (!from_sync) {
701 const bool arc_enabled =
702 profile_->GetPrefs()->GetBoolean(prefs::kArcEnabled);
703 UpdateOptInActionUMA(arc_enabled ? OptInActionType::OPTED_IN
704 : OptInActionType::OPTED_OUT);
705
706 if (!arc_enabled && !IsArcManaged()) {
707 ash::ShelfDelegate* shelf_delegate = GetShelfDelegate();
708 if (shelf_delegate)
709 shelf_delegate->UnpinAppWithID(ArcSupportHost::kHostAppId);
710 }
711 }
712 }
713
714 void ArcAuthService::StopArc() {
715 if (state_ != State::STOPPED) {
716 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false);
717 profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, false);
718 }
719 ShutdownBridge();
720 if (support_host_)
721 support_host_->Close();
722 }
723
724 void ArcAuthService::OnOptInPreferenceChanged() {
725 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
726 DCHECK(profile_);
727
728 // TODO(dspaid): Move code from OnSyncedPrefChanged into this method.
729 OnSyncedPrefChanged(prefs::kArcEnabled, IsArcManaged());
730
731 const bool arc_enabled = IsArcEnabled();
732 for (auto& observer : observer_list_)
733 observer.OnOptInEnabled(arc_enabled);
734
735 if (!arc_enabled) {
736 StopArc();
737 RemoveArcData();
738 return;
739 }
740
741 if (state_ == State::ACTIVE)
742 return;
743
744 if (support_host_)
745 support_host_->SetArcManaged(IsArcManaged());
746
747 // In case UI is disabled we assume that ARC is opted-in. For ARC Kiosk we
748 // skip ToS because it is very likely that near the device there will be
749 // no one who is eligible to accept them. We skip if Android management check
750 // because there are no managed human users for Kiosk exist.
751 if (IsOptInVerificationDisabled() || IsArcKioskMode()) {
752 // Automatically accept terms in kiosk mode. This is not required for
753 // IsOptInVerificationDisabled mode because in last case it may cause
754 // a privacy issue on next run without this flag set.
755 if (IsArcKioskMode())
756 profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true);
757 StartArc();
758 return;
759 }
760
761 if (!profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn)) {
762 if (profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) {
763 StartArc();
764 } else {
765 // Need pre-fetch auth code and show OptIn UI if needed.
766 StartUI();
767 }
768 } else {
769 // Ready to start Arc, but check Android management in parallel.
770 StartArc();
771 // Note: Because the callback may be called in synchronous way (i.e. called
772 // on the same stack), StartCheck() needs to be called *after* StartArc().
773 // Otherwise, DisableArc() which may be called in
774 // OnBackgroundAndroidManagementChecked() could be ignored.
775 if (!g_disable_ui_for_testing ||
776 g_enable_check_android_management_for_testing) {
777 android_management_checker_.reset(new ArcAndroidManagementChecker(
778 profile_, context_->token_service(), context_->account_id(),
779 true /* retry_on_error */));
780 android_management_checker_->StartCheck(
781 base::Bind(&ArcAuthService::OnBackgroundAndroidManagementChecked,
782 weak_ptr_factory_.GetWeakPtr()));
783 }
784 }
785 }
786
787 void ArcAuthService::ShutdownBridge() {
788 arc_sign_in_timer_.Stop();
789 playstore_launcher_.reset();
790 account_info_notifier_.reset();
791 android_management_checker_.reset();
792 auth_code_fetcher_.reset();
793 arc_bridge_service()->RequestStop();
794 if (state_ != State::NOT_INITIALIZED)
795 SetState(State::STOPPED);
796 for (auto& observer : observer_list_)
797 observer.OnShutdownBridge();
798 }
799
800 void ArcAuthService::AddObserver(Observer* observer) {
801 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
802 observer_list_.AddObserver(observer);
803 }
804
805 void ArcAuthService::RemoveObserver(Observer* observer) {
806 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
807 observer_list_.RemoveObserver(observer);
808 }
809
810 // This is the special method to support enterprise mojo API.
811 // TODO(hidehiko): Remove this.
812 void ArcAuthService::StopAndEnableArc() {
813 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
814 DCHECK(!arc_bridge_service()->stopped());
815 reenable_arc_ = true;
816 StopArc();
817 }
818
819 void ArcAuthService::StartArc() {
820 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
821 arc_bridge_service()->RequestStart();
822 SetState(State::ACTIVE);
823 }
824
825 void ArcAuthService::OnAuthCodeObtained(const std::string& auth_code) { 310 void ArcAuthService::OnAuthCodeObtained(const std::string& auth_code) {
826 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 311 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
827 DCHECK(!auth_code.empty()); 312 DCHECK(!auth_code.empty());
828 313
829 account_info_notifier_->Notify(!IsOptInVerificationDisabled(), auth_code, 314 notifier_->Notify(
830 GetAccountType(), 315 !ArcSessionManager::IsOptInVerificationDisabled(), auth_code,
831 policy_util::IsAccountManaged(profile_)); 316 GetAccountType(),
832 account_info_notifier_.reset(); 317 policy_util::IsAccountManaged(ArcSessionManager::Get()->profile()));
833 } 318 notifier_.reset();
834
835 void ArcAuthService::OnArcSignInTimeout() {
836 LOG(ERROR) << "Timed out waiting for first sign in.";
837 OnProvisioningFinished(ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT);
838 }
839
840 void ArcAuthService::CancelAuthCode() {
841 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
842
843 if (state_ == State::NOT_INITIALIZED) {
844 NOTREACHED();
845 return;
846 }
847
848 // In case |state_| is ACTIVE, UI page can be ARC_LOADING (which means normal
849 // ARC booting) or ERROR (in case ARC can not be started). If ARC is booting
850 // normally don't stop it on progress close.
851 if ((state_ != State::SHOWING_TERMS_OF_SERVICE &&
852 state_ != State::CHECKING_ANDROID_MANAGEMENT) &&
853 (!support_host_ ||
854 support_host_->ui_page() != ArcSupportHost::UIPage::ERROR)) {
855 return;
856 }
857
858 // Update UMA with user cancel only if error is not currently shown.
859 if (support_host_ &&
860 support_host_->ui_page() != ArcSupportHost::UIPage::NO_PAGE &&
861 support_host_->ui_page() != ArcSupportHost::UIPage::ERROR) {
862 UpdateOptInCancelUMA(OptInCancelReason::USER_CANCEL);
863 }
864
865 StopArc();
866
867 if (IsArcManaged())
868 return;
869
870 DisableArc();
871 }
872
873 bool ArcAuthService::IsArcManaged() const {
874 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
875 DCHECK(profile_);
876 return profile_->GetPrefs()->IsManagedPreference(prefs::kArcEnabled);
877 }
878
879 bool ArcAuthService::IsArcEnabled() const {
880 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
881 if (!IsAllowed())
882 return false;
883
884 DCHECK(profile_);
885 return profile_->GetPrefs()->GetBoolean(prefs::kArcEnabled);
886 }
887
888 void ArcAuthService::EnableArc() {
889 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
890 DCHECK(profile_);
891
892 if (IsArcEnabled()) {
893 OnOptInPreferenceChanged();
894 return;
895 }
896
897 if (!IsArcManaged())
898 profile_->GetPrefs()->SetBoolean(prefs::kArcEnabled, true);
899 }
900
901 void ArcAuthService::DisableArc() {
902 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
903 DCHECK(profile_);
904 profile_->GetPrefs()->SetBoolean(prefs::kArcEnabled, false);
905 }
906
907 void ArcAuthService::RecordArcState() {
908 // Only record Enabled state if ARC is allowed in the first place, so we do
909 // not split the ARC population by devices that cannot run ARC.
910 if (IsAllowed())
911 UpdateEnabledStateUMA(IsArcEnabled());
912 }
913
914 void ArcAuthService::StartUI() {
915 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
916
917 if (!arc_bridge_service()->stopped()) {
918 // If the user attempts to re-enable ARC while the bridge is still running
919 // the user should not be able to continue until the bridge has stopped.
920 if (support_host_) {
921 support_host_->ShowError(
922 ArcSupportHost::Error::SIGN_IN_SERVICE_UNAVAILABLE_ERROR, false);
923 }
924 return;
925 }
926
927 SetState(State::SHOWING_TERMS_OF_SERVICE);
928 if (support_host_)
929 support_host_->ShowTermsOfService();
930 }
931
932 void ArcAuthService::StartArcAndroidManagementCheck() {
933 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
934 DCHECK(arc_bridge_service()->stopped());
935 DCHECK(state_ == State::SHOWING_TERMS_OF_SERVICE ||
936 state_ == State::CHECKING_ANDROID_MANAGEMENT);
937 SetState(State::CHECKING_ANDROID_MANAGEMENT);
938
939 android_management_checker_.reset(new ArcAndroidManagementChecker(
940 profile_, context_->token_service(), context_->account_id(),
941 false /* retry_on_error */));
942 android_management_checker_->StartCheck(
943 base::Bind(&ArcAuthService::OnAndroidManagementChecked,
944 weak_ptr_factory_.GetWeakPtr()));
945 }
946
947 void ArcAuthService::OnAndroidManagementChecked(
948 policy::AndroidManagementClient::Result result) {
949 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
950 DCHECK_EQ(state_, State::CHECKING_ANDROID_MANAGEMENT);
951
952 switch (result) {
953 case policy::AndroidManagementClient::Result::UNMANAGED:
954 VLOG(1) << "Starting ARC for first sign in.";
955 sign_in_time_ = base::Time::Now();
956 arc_sign_in_timer_.Start(FROM_HERE, kArcSignInTimeout,
957 base::Bind(&ArcAuthService::OnArcSignInTimeout,
958 weak_ptr_factory_.GetWeakPtr()));
959 StartArc();
960 break;
961 case policy::AndroidManagementClient::Result::MANAGED:
962 ShutdownBridge();
963 if (support_host_) {
964 support_host_->ShowError(
965 ArcSupportHost::Error::ANDROID_MANAGEMENT_REQUIRED_ERROR, false);
966 }
967 UpdateOptInCancelUMA(OptInCancelReason::ANDROID_MANAGEMENT_REQUIRED);
968 break;
969 case policy::AndroidManagementClient::Result::ERROR:
970 ShutdownBridge();
971 if (support_host_) {
972 support_host_->ShowError(
973 ArcSupportHost::Error::SERVER_COMMUNICATION_ERROR, false);
974 }
975 UpdateOptInCancelUMA(OptInCancelReason::NETWORK_ERROR);
976 break;
977 }
978 }
979
980 void ArcAuthService::OnBackgroundAndroidManagementChecked(
981 policy::AndroidManagementClient::Result result) {
982 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
983 switch (result) {
984 case policy::AndroidManagementClient::Result::UNMANAGED:
985 // Do nothing. ARC should be started already.
986 break;
987 case policy::AndroidManagementClient::Result::MANAGED:
988 DisableArc();
989 break;
990 case policy::AndroidManagementClient::Result::ERROR:
991 // This code should not be reached. For background check,
992 // retry_on_error should be set.
993 NOTREACHED();
994 }
995 }
996
997 void ArcAuthService::OnWindowClosed() {
998 DCHECK(support_host_);
999 CancelAuthCode();
1000 }
1001
1002 void ArcAuthService::OnTermsAgreed(bool is_metrics_enabled,
1003 bool is_backup_and_restore_enabled,
1004 bool is_location_service_enabled) {
1005 DCHECK(support_host_);
1006
1007 // Terms were accepted
1008 profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true);
1009
1010 // Since this is ARC support's UI event callback, preference_handler_
1011 // should be always created (see OnPrimaryUserProfilePrepared()).
1012 // TODO(hidehiko): Simplify the logic with the code restructuring.
1013 DCHECK(preference_handler_);
1014 preference_handler_->EnableMetrics(is_metrics_enabled);
1015 preference_handler_->EnableBackupRestore(is_backup_and_restore_enabled);
1016 preference_handler_->EnableLocationService(is_location_service_enabled);
1017 support_host_->ShowArcLoading();
1018 StartArcAndroidManagementCheck();
1019 } 319 }
1020 320
1021 void ArcAuthService::OnAuthSucceeded(const std::string& auth_code) { 321 void ArcAuthService::OnAuthSucceeded(const std::string& auth_code) {
1022 DCHECK(support_host_);
1023 OnAuthCodeObtained(auth_code); 322 OnAuthCodeObtained(auth_code);
1024 } 323 }
1025 324
1026 void ArcAuthService::OnRetryClicked() { 325 void ArcAuthService::OnRetryClicked() {
1027 DCHECK(support_host_); 326 ArcSupportHost* support_host = ArcSessionManager::Get()->support_host();
1028 327 // This is the callback for the UI event, so support_host should be always
1029 UpdateOptInActionUMA(OptInActionType::RETRY); 328 // available here.
1030 329 DCHECK(support_host);
1031 // TODO(hidehiko): Simplify the retry logic. 330 if (support_host->ui_page() == ArcSupportHost::UIPage::ERROR) {
1032 if (!profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) { 331 // This case is handled by ArcSessionManager::OnRetryClicked().
1033 // If the user has not yet agreed on Terms of Service, then show it.
1034 support_host_->ShowTermsOfService();
1035 } else if (support_host_->ui_page() == ArcSupportHost::UIPage::ERROR &&
1036 !arc_bridge_service()->stopped()) {
1037 // ERROR_WITH_FEEDBACK is set in OnSignInFailed(). In the case, stopping
1038 // ARC was postponed to contain its internal state into the report.
1039 // Here, on retry, stop it, then restart.
1040 DCHECK_EQ(State::ACTIVE, state_);
1041 support_host_->ShowArcLoading();
1042 ShutdownBridge();
1043 reenable_arc_ = true;
1044 } else if (state_ == State::ACTIVE) {
1045 // This happens when ARC support Chrome app reports an error on "Sign in"
1046 // page.
1047 DCHECK(context_);
1048 context_->Prepare(base::Bind(&ArcAuthService::OnContextPrepared,
1049 weak_ptr_factory_.GetWeakPtr()));
1050 } else {
1051 // Otherwise, we restart ARC. Note: this is the first boot case.
1052 // For second or later boot, either ERROR_WITH_FEEDBACK case or ACTIVE
1053 // case must hit.
1054 support_host_->ShowArcLoading();
1055 StartArcAndroidManagementCheck();
1056 }
1057 }
1058
1059 void ArcAuthService::OnSendFeedbackClicked() {
1060 DCHECK(support_host_);
1061 chrome::OpenFeedbackDialog(nullptr);
1062 }
1063
1064 void ArcAuthService::OnMetricsModeChanged(bool enabled, bool managed) {
1065 if (!support_host_)
1066 return; 332 return;
1067 support_host_->SetMetricsPreferenceCheckbox(enabled, managed);
1068 }
1069
1070 void ArcAuthService::OnBackupAndRestoreModeChanged(bool enabled, bool managed) {
1071 if (!support_host_)
1072 return;
1073 support_host_->SetBackupAndRestorePreferenceCheckbox(enabled, managed);
1074 }
1075
1076 void ArcAuthService::OnLocationServicesModeChanged(bool enabled, bool managed) {
1077 if (!support_host_)
1078 return;
1079 support_host_->SetLocationServicesPreferenceCheckbox(enabled, managed);
1080 }
1081
1082 std::ostream& operator<<(std::ostream& os, const ArcAuthService::State& state) {
1083 switch (state) {
1084 case ArcAuthService::State::NOT_INITIALIZED:
1085 return os << "NOT_INITIALIZED";
1086 case ArcAuthService::State::STOPPED:
1087 return os << "STOPPED";
1088 case ArcAuthService::State::SHOWING_TERMS_OF_SERVICE:
1089 return os << "SHOWING_TERMS_OF_SERVICE";
1090 case ArcAuthService::State::CHECKING_ANDROID_MANAGEMENT:
1091 return os << "CHECKING_ANDROID_MANAGEMENT";
1092 case ArcAuthService::State::ACTIVE:
1093 return os << "ACTIVE";
1094 } 333 }
1095 334
1096 // Some compiler reports an error even if all values of an enum-class are 335 ArcSessionManager::Get()->auth_context()->Prepare(base::Bind(
1097 // covered indivisually in a switch statement. 336 &ArcAuthService::OnContextPrepared, weak_ptr_factory_.GetWeakPtr()));
1098 NOTREACHED();
1099 return os;
1100 } 337 }
1101 338
1102 } // namespace arc 339 } // namespace arc
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/arc/arc_auth_service.h ('k') | chrome/browser/chromeos/arc/arc_auth_service_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698