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

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

Issue 2507073002: Split ArcSessionManager from ArcAuthService. (Closed)
Patch Set: Split ArcSessionManager from ArcAuthService 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(g_arc_auth_service == this);
xiyuan 2016/11/16 18:55:52 nit: DCHECK_EQ(this, g_arc_auth_service);
hidehiko 2016/11/16 19:52:05 Done.
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, and let them click "Sign in" button. 246 // Otherwise, show LSO page to user, and let them click "Sign in" button.
422 if (support_host_) 247 ArcSupportHost* support_host = ArcSessionManager::Get()->support_host();
423 support_host_->ShowLso(); 248 if (support_host) {
Luis Héctor Chávez 2016/11/16 17:13:34 What happens if this is not available? Wouldn't AR
hidehiko 2016/11/16 19:52:05 Oh, good point. I re-check this and it turned out
249 if (!support_host->HasObserver(this))
250 support_host->AddObserver(this);
251 support_host->ShowLso();
252 }
253 }
254
255 void ArcAuthService::OnAccountInfoReady(mojom::AccountInfoPtr account_info) {
256 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
257 auto* instance = arc_bridge_service()->auth()->GetInstanceForMethod(
258 "OnAccountInfoReady", kMinVersionForOnAccountInfoReady);
259 DCHECK(instance);
260 instance->OnAccountInfoReady(std::move(account_info));
424 } 261 }
425 262
426 void ArcAuthService::OnRobotAuthCodeFetched( 263 void ArcAuthService::OnRobotAuthCodeFetched(
427 const std::string& robot_auth_code) { 264 const std::string& robot_auth_code) {
428 // We fetching robot auth code for ARC kiosk only. 265 // We fetching robot auth code for ARC kiosk only.
429 DCHECK(IsArcKioskMode()); 266 DCHECK(ArcSessionManager::IsArcKioskMode());
430 267
431 // Current instance of ArcRobotAuth became useless. 268 // Current instance of ArcRobotAuth became useless.
432 arc_robot_auth_.reset(); 269 arc_robot_auth_.reset();
433 270
434 if (robot_auth_code.empty()) { 271 if (robot_auth_code.empty()) {
435 VLOG(1) << "Robot account auth code fetching error"; 272 VLOG(1) << "Robot account auth code fetching error";
436 // Log out the user. All the cleanup will be done in Shutdown() method. 273 // Log out the user. All the cleanup will be done in Shutdown() method.
437 // The callback is not called because auth code is empty. 274 // The callback is not called because auth code is empty.
438 chrome::AttemptUserExit(); 275 chrome::AttemptUserExit();
439 return; 276 return;
440 } 277 }
441 278
442 OnAuthCodeObtained(robot_auth_code); 279 OnAuthCodeObtained(robot_auth_code);
443 } 280 }
444 281
445 void ArcAuthService::OnAuthCodeFetched(const std::string& auth_code) { 282 void ArcAuthService::OnAuthCodeFetched(const std::string& auth_code) {
446 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 283 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
447 auth_code_fetcher_.reset(); 284 auth_code_fetcher_.reset();
448 285
449 if (auth_code.empty()) { 286 if (auth_code.empty()) {
450 OnProvisioningFinished( 287 ArcSessionManager::Get()->OnProvisioningFinished(
451 ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR); 288 ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR);
452 return; 289 return;
453 } 290 }
454 291
455 OnAuthCodeObtained(auth_code); 292 OnAuthCodeObtained(auth_code);
456 } 293 }
457 294
458 void ArcAuthService::OnSignInComplete() {
459 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
460 DCHECK_EQ(state_, State::ACTIVE);
461 OnProvisioningFinished(ProvisioningResult::SUCCESS);
462 }
463
464 void ArcAuthService::OnSignInFailed(mojom::ArcSignInFailureReason reason) {
465 OnProvisioningFinished(
466 ConvertArcSignInFailureReasonToProvisioningResult(reason));
467 }
468
469 void ArcAuthService::OnProvisioningFinished(ProvisioningResult result) {
470 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
471 DCHECK_EQ(state_, State::ACTIVE);
472
473 if (result == ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR) {
474 // For backword compatibility, use NETWORK_ERROR for
475 // CHROME_SERVER_COMMUNICATION_ERROR case.
476 UpdateOptInCancelUMA(OptInCancelReason::NETWORK_ERROR);
477 } else if (!sign_in_time_.is_null()) {
478 arc_sign_in_timer_.Stop();
479
480 UpdateProvisioningTiming(base::Time::Now() - sign_in_time_,
481 result == ProvisioningResult::SUCCESS,
482 policy_util::IsAccountManaged(profile_));
483 UpdateProvisioningResultUMA(result,
484 policy_util::IsAccountManaged(profile_));
485 if (result != ProvisioningResult::SUCCESS) {
486 UpdateOptInCancelUMA(OptInCancelReason::CLOUD_PROVISION_FLOW_FAIL);
487 }
488 }
489
490 if (result == ProvisioningResult::SUCCESS) {
491 if (support_host_)
492 support_host_->Close();
493
494 if (profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn))
495 return;
496
497 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true);
498 if (!IsOptInVerificationDisabled()) {
499 playstore_launcher_.reset(
500 new ArcAppLauncher(profile_, kPlayStoreAppId, true));
501 }
502
503 for (auto& observer : observer_list_)
504 observer.OnInitialStart();
505 return;
506 }
507
508 ArcSupportHost::Error error;
509 switch (result) {
510 case ProvisioningResult::GMS_NETWORK_ERROR:
511 error = ArcSupportHost::Error::SIGN_IN_NETWORK_ERROR;
512 break;
513 case ProvisioningResult::GMS_SERVICE_UNAVAILABLE:
514 case ProvisioningResult::GMS_SIGN_IN_FAILED:
515 case ProvisioningResult::GMS_SIGN_IN_TIMEOUT:
516 case ProvisioningResult::GMS_SIGN_IN_INTERNAL_ERROR:
517 error = ArcSupportHost::Error::SIGN_IN_SERVICE_UNAVAILABLE_ERROR;
518 break;
519 case ProvisioningResult::GMS_BAD_AUTHENTICATION:
520 error = ArcSupportHost::Error::SIGN_IN_BAD_AUTHENTICATION_ERROR;
521 break;
522 case ProvisioningResult::DEVICE_CHECK_IN_FAILED:
523 case ProvisioningResult::DEVICE_CHECK_IN_TIMEOUT:
524 case ProvisioningResult::DEVICE_CHECK_IN_INTERNAL_ERROR:
525 error = ArcSupportHost::Error::SIGN_IN_GMS_NOT_AVAILABLE_ERROR;
526 break;
527 case ProvisioningResult::CLOUD_PROVISION_FLOW_FAILED:
528 case ProvisioningResult::CLOUD_PROVISION_FLOW_TIMEOUT:
529 case ProvisioningResult::CLOUD_PROVISION_FLOW_INTERNAL_ERROR:
530 error = ArcSupportHost::Error::SIGN_IN_CLOUD_PROVISION_FLOW_FAIL_ERROR;
531 break;
532 case ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR:
533 error = ArcSupportHost::Error::SERVER_COMMUNICATION_ERROR;
534 break;
535 default:
536 error = ArcSupportHost::Error::SIGN_IN_UNKNOWN_ERROR;
537 break;
538 }
539
540 if (result == ProvisioningResult::ARC_STOPPED ||
541 result == ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR) {
542 if (profile_->GetPrefs()->HasPrefPath(prefs::kArcSignedIn))
543 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false);
544 ShutdownBridge();
545 if (support_host_)
546 support_host_->ShowError(error, false);
547 return;
548 }
549
550 if (result == ProvisioningResult::CLOUD_PROVISION_FLOW_FAILED ||
551 result == ProvisioningResult::CLOUD_PROVISION_FLOW_TIMEOUT ||
552 result == ProvisioningResult::CLOUD_PROVISION_FLOW_INTERNAL_ERROR ||
553 // OVERALL_SIGN_IN_TIMEOUT might be an indication that ARC believes it is
554 // fully setup, but Chrome does not.
555 result == ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT ||
556 // Just to be safe, remove data if we don't know the cause.
557 result == ProvisioningResult::UNKNOWN_ERROR) {
558 RemoveArcData();
559 }
560
561 // We'll delay shutting down the bridge in this case to allow people to send
562 // feedback.
563 if (support_host_)
564 support_host_->ShowError(error, true /* = show send feedback button */);
565 }
566
567 void ArcAuthService::GetIsAccountManagedDeprecated(
568 const GetIsAccountManagedDeprecatedCallback& callback) {
569 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
570
571 callback.Run(policy_util::IsAccountManaged(profile_));
572 }
573
574 void ArcAuthService::SetState(State state) {
575 state_ = state;
576 }
577
578 bool ArcAuthService::IsAllowed() const {
579 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
580 return profile_ != nullptr;
581 }
582
583 void ArcAuthService::OnPrimaryUserProfilePrepared(Profile* profile) {
584 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
585 DCHECK(profile && profile != profile_);
586
587 Shutdown();
588
589 if (!IsAllowedForProfile(profile))
590 return;
591
592 // TODO(khmel): Move this to IsAllowedForProfile.
593 if (policy_util::IsArcDisabledForEnterprise() &&
594 policy_util::IsAccountManaged(profile)) {
595 VLOG(2) << "Enterprise users are not supported in ARC.";
596 return;
597 }
598
599 profile_ = profile;
600
601 // Create the support host at initialization. Note that, practically,
602 // ARC support Chrome app is rarely used (only opt-in and re-auth flow).
603 // So, it may be better to initialize it lazily.
604 // TODO(hidehiko): Revisit to think about lazy initialization.
605 //
606 // Don't show UI for ARC Kiosk because the only one UI in kiosk mode must
607 // be the kiosk app. In case of error the UI will be useless as well, because
608 // in typical use case there will be no one nearby the kiosk device, who can
609 // do some action to solve the problem be means of UI.
610 if (!g_disable_ui_for_testing && !IsOptInVerificationDisabled() &&
611 !IsArcKioskMode()) {
612 DCHECK(!support_host_);
613 support_host_ = base::MakeUnique<ArcSupportHost>(profile_);
614 support_host_->AddObserver(this);
615
616 preference_handler_ = base::MakeUnique<arc::ArcOptInPreferenceHandler>(
617 this, profile_->GetPrefs());
618 // This automatically updates all preferences.
619 preference_handler_->Start();
620 }
621
622 DCHECK_EQ(State::NOT_INITIALIZED, state_);
623 SetState(State::STOPPED);
624
625 PrefServiceSyncableFromProfile(profile_)->AddSyncedPrefObserver(
626 prefs::kArcEnabled, this);
627
628 context_.reset(new ArcAuthContext(profile_));
629
630 // In case UI is disabled we assume that ARC is opted-in. For ARC Kiosk we
631 // skip ToS because it is very likely that near the device there will be
632 // no one who is eligible to accept them. We skip if Android management check
633 // because there are no managed human users for Kiosk exist.
634 if (IsOptInVerificationDisabled() || IsArcKioskMode()) {
635 StartArc();
636 return;
637 }
638
639 if (!g_disable_ui_for_testing ||
640 g_enable_check_android_management_for_testing) {
641 ArcAndroidManagementChecker::StartClient();
642 }
643 pref_change_registrar_.Init(profile_->GetPrefs());
644 pref_change_registrar_.Add(
645 prefs::kArcEnabled, base::Bind(&ArcAuthService::OnOptInPreferenceChanged,
646 weak_ptr_factory_.GetWeakPtr()));
647 if (profile_->GetPrefs()->GetBoolean(prefs::kArcEnabled)) {
648 OnOptInPreferenceChanged();
649 } else {
650 RemoveArcData();
651 PrefServiceSyncableFromProfile(profile_)->AddObserver(this);
652 OnIsSyncingChanged();
653 }
654 }
655
656 void ArcAuthService::OnIsSyncingChanged() {
657 sync_preferences::PrefServiceSyncable* const pref_service_syncable =
658 PrefServiceSyncableFromProfile(profile_);
659 if (!pref_service_syncable->IsSyncing())
660 return;
661
662 pref_service_syncable->RemoveObserver(this);
663
664 if (IsArcEnabled())
665 OnOptInPreferenceChanged();
666 }
667
668 void ArcAuthService::Shutdown() {
669 ShutdownBridge();
670 if (support_host_) {
671 support_host_->Close();
672 support_host_->RemoveObserver(this);
673 support_host_.reset();
674 }
675 if (profile_) {
676 sync_preferences::PrefServiceSyncable* pref_service_syncable =
677 PrefServiceSyncableFromProfile(profile_);
678 pref_service_syncable->RemoveObserver(this);
679 pref_service_syncable->RemoveSyncedPrefObserver(prefs::kArcEnabled, this);
680 }
681 pref_change_registrar_.RemoveAll();
682 context_.reset();
683 profile_ = nullptr;
684 arc_robot_auth_.reset();
685 SetState(State::NOT_INITIALIZED);
686 }
687
688 void ArcAuthService::OnSyncedPrefChanged(const std::string& path,
689 bool from_sync) {
690 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
691
692 // Update UMA only for local changes
693 if (!from_sync) {
694 const bool arc_enabled =
695 profile_->GetPrefs()->GetBoolean(prefs::kArcEnabled);
696 UpdateOptInActionUMA(arc_enabled ? OptInActionType::OPTED_IN
697 : OptInActionType::OPTED_OUT);
698
699 if (!arc_enabled && !IsArcManaged()) {
700 ash::ShelfDelegate* shelf_delegate = GetShelfDelegate();
701 if (shelf_delegate)
702 shelf_delegate->UnpinAppWithID(ArcSupportHost::kHostAppId);
703 }
704 }
705 }
706
707 void ArcAuthService::StopArc() {
708 if (state_ != State::STOPPED) {
709 profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false);
710 profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, false);
711 }
712 ShutdownBridge();
713 if (support_host_)
714 support_host_->Close();
715 }
716
717 void ArcAuthService::OnOptInPreferenceChanged() {
718 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
719 DCHECK(profile_);
720
721 // TODO(dspaid): Move code from OnSyncedPrefChanged into this method.
722 OnSyncedPrefChanged(prefs::kArcEnabled, IsArcManaged());
723
724 const bool arc_enabled = IsArcEnabled();
725 for (auto& observer : observer_list_)
726 observer.OnOptInEnabled(arc_enabled);
727
728 if (!arc_enabled) {
729 StopArc();
730 RemoveArcData();
731 return;
732 }
733
734 if (state_ == State::ACTIVE)
735 return;
736
737 if (support_host_)
738 support_host_->SetArcManaged(IsArcManaged());
739
740 if (!profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn)) {
741 if (profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) {
742 StartArc();
743 } else {
744 // Need pre-fetch auth code and show OptIn UI if needed.
745 StartUI();
746 }
747 } else {
748 // Ready to start Arc, but check Android management in parallel.
749 StartArc();
750 // Note: Because the callback may be called in synchronous way (i.e. called
751 // on the same stack), StartCheck() needs to be called *after* StartArc().
752 // Otherwise, DisableArc() which may be called in
753 // OnBackgroundAndroidManagementChecked() could be ignored.
754 if (!g_disable_ui_for_testing ||
755 g_enable_check_android_management_for_testing) {
756 android_management_checker_.reset(new ArcAndroidManagementChecker(
757 profile_, context_->token_service(), context_->account_id(),
758 true /* retry_on_error */));
759 android_management_checker_->StartCheck(
760 base::Bind(&ArcAuthService::OnBackgroundAndroidManagementChecked,
761 weak_ptr_factory_.GetWeakPtr()));
762 }
763 }
764 }
765
766 void ArcAuthService::ShutdownBridge() {
767 arc_sign_in_timer_.Stop();
768 playstore_launcher_.reset();
769 account_info_notifier_.reset();
770 android_management_checker_.reset();
771 auth_code_fetcher_.reset();
772 arc_bridge_service()->RequestStop();
773 if (state_ != State::NOT_INITIALIZED)
774 SetState(State::STOPPED);
775 for (auto& observer : observer_list_)
776 observer.OnShutdownBridge();
777 }
778
779 void ArcAuthService::AddObserver(Observer* observer) {
780 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
781 observer_list_.AddObserver(observer);
782 }
783
784 void ArcAuthService::RemoveObserver(Observer* observer) {
785 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
786 observer_list_.RemoveObserver(observer);
787 }
788
789 // This is the special method to support enterprise mojo API.
790 // TODO(hidehiko): Remove this.
791 void ArcAuthService::StopAndEnableArc() {
792 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
793 DCHECK(!arc_bridge_service()->stopped());
794 reenable_arc_ = true;
795 StopArc();
796 }
797
798 void ArcAuthService::StartArc() {
799 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
800 arc_bridge_service()->RequestStart();
801 SetState(State::ACTIVE);
802 }
803
804 void ArcAuthService::OnAuthCodeObtained(const std::string& auth_code) { 295 void ArcAuthService::OnAuthCodeObtained(const std::string& auth_code) {
805 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 296 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
806 DCHECK(!auth_code.empty()); 297 DCHECK(!auth_code.empty());
807 298
808 account_info_notifier_->Notify(!IsOptInVerificationDisabled(), auth_code, 299 notifier_->Notify(
809 GetAccountType(), 300 !ArcSessionManager::IsOptInVerificationDisabled(), auth_code,
810 policy_util::IsAccountManaged(profile_)); 301 GetAccountType(),
811 account_info_notifier_.reset(); 302 policy_util::IsAccountManaged(ArcSessionManager::Get()->profile()));
812 } 303 notifier_.reset();
813
814 void ArcAuthService::OnArcSignInTimeout() {
815 LOG(ERROR) << "Timed out waiting for first sign in.";
816 OnProvisioningFinished(ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT);
817 }
818
819 void ArcAuthService::CancelAuthCode() {
820 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
821
822 if (state_ == State::NOT_INITIALIZED) {
823 NOTREACHED();
824 return;
825 }
826
827 // In case |state_| is ACTIVE, UI page can be ARC_LOADING (which means normal
828 // ARC booting) or ERROR (in case ARC can not be started). If ARC is booting
829 // normally don't stop it on progress close.
830 if ((state_ != State::SHOWING_TERMS_OF_SERVICE &&
831 state_ != State::CHECKING_ANDROID_MANAGEMENT) &&
832 (!support_host_ ||
833 support_host_->ui_page() != ArcSupportHost::UIPage::ERROR)) {
834 return;
835 }
836
837 // Update UMA with user cancel only if error is not currently shown.
838 if (support_host_ &&
839 support_host_->ui_page() != ArcSupportHost::UIPage::NO_PAGE &&
840 support_host_->ui_page() != ArcSupportHost::UIPage::ERROR) {
841 UpdateOptInCancelUMA(OptInCancelReason::USER_CANCEL);
842 }
843
844 StopArc();
845
846 if (IsArcManaged())
847 return;
848
849 DisableArc();
850 }
851
852 bool ArcAuthService::IsArcManaged() const {
853 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
854 DCHECK(profile_);
855 return profile_->GetPrefs()->IsManagedPreference(prefs::kArcEnabled);
856 }
857
858 bool ArcAuthService::IsArcEnabled() const {
859 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
860 if (!IsAllowed())
861 return false;
862
863 DCHECK(profile_);
864 return profile_->GetPrefs()->GetBoolean(prefs::kArcEnabled);
865 }
866
867 void ArcAuthService::EnableArc() {
868 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
869 DCHECK(profile_);
870
871 if (IsArcEnabled()) {
872 OnOptInPreferenceChanged();
873 return;
874 }
875
876 if (!IsArcManaged())
877 profile_->GetPrefs()->SetBoolean(prefs::kArcEnabled, true);
878 }
879
880 void ArcAuthService::DisableArc() {
881 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
882 DCHECK(profile_);
883 profile_->GetPrefs()->SetBoolean(prefs::kArcEnabled, false);
884 }
885
886 void ArcAuthService::RecordArcState() {
887 // Only record Enabled state if ARC is allowed in the first place, so we do
888 // not split the ARC population by devices that cannot run ARC.
889 if (IsAllowed())
890 UpdateEnabledStateUMA(IsArcEnabled());
891 }
892
893 void ArcAuthService::StartUI() {
894 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
895
896 if (!arc_bridge_service()->stopped()) {
897 // If the user attempts to re-enable ARC while the bridge is still running
898 // the user should not be able to continue until the bridge has stopped.
899 if (support_host_) {
900 support_host_->ShowError(
901 ArcSupportHost::Error::SIGN_IN_SERVICE_UNAVAILABLE_ERROR, false);
902 }
903 return;
904 }
905
906 SetState(State::SHOWING_TERMS_OF_SERVICE);
907 if (support_host_)
908 support_host_->ShowTermsOfService();
909 }
910
911 void ArcAuthService::StartArcAndroidManagementCheck() {
912 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
913 DCHECK(arc_bridge_service()->stopped());
914 DCHECK(state_ == State::SHOWING_TERMS_OF_SERVICE ||
915 state_ == State::CHECKING_ANDROID_MANAGEMENT);
916 SetState(State::CHECKING_ANDROID_MANAGEMENT);
917
918 android_management_checker_.reset(new ArcAndroidManagementChecker(
919 profile_, context_->token_service(), context_->account_id(),
920 false /* retry_on_error */));
921 android_management_checker_->StartCheck(
922 base::Bind(&ArcAuthService::OnAndroidManagementChecked,
923 weak_ptr_factory_.GetWeakPtr()));
924 }
925
926 void ArcAuthService::OnAndroidManagementChecked(
927 policy::AndroidManagementClient::Result result) {
928 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
929 DCHECK_EQ(state_, State::CHECKING_ANDROID_MANAGEMENT);
930
931 switch (result) {
932 case policy::AndroidManagementClient::Result::UNMANAGED:
933 VLOG(1) << "Starting ARC for first sign in.";
934 sign_in_time_ = base::Time::Now();
935 arc_sign_in_timer_.Start(FROM_HERE, kArcSignInTimeout,
936 base::Bind(&ArcAuthService::OnArcSignInTimeout,
937 weak_ptr_factory_.GetWeakPtr()));
938 StartArc();
939 break;
940 case policy::AndroidManagementClient::Result::MANAGED:
941 ShutdownBridge();
942 if (support_host_) {
943 support_host_->ShowError(
944 ArcSupportHost::Error::ANDROID_MANAGEMENT_REQUIRED_ERROR, false);
945 }
946 UpdateOptInCancelUMA(OptInCancelReason::ANDROID_MANAGEMENT_REQUIRED);
947 break;
948 case policy::AndroidManagementClient::Result::ERROR:
949 ShutdownBridge();
950 if (support_host_) {
951 support_host_->ShowError(
952 ArcSupportHost::Error::SERVER_COMMUNICATION_ERROR, false);
953 }
954 UpdateOptInCancelUMA(OptInCancelReason::NETWORK_ERROR);
955 break;
956 }
957 }
958
959 void ArcAuthService::OnBackgroundAndroidManagementChecked(
960 policy::AndroidManagementClient::Result result) {
961 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
962 switch (result) {
963 case policy::AndroidManagementClient::Result::UNMANAGED:
964 // Do nothing. ARC should be started already.
965 break;
966 case policy::AndroidManagementClient::Result::MANAGED:
967 DisableArc();
968 break;
969 case policy::AndroidManagementClient::Result::ERROR:
970 // This code should not be reached. For background check,
971 // retry_on_error should be set.
972 NOTREACHED();
973 }
974 }
975
976 void ArcAuthService::OnWindowClosed() {
977 DCHECK(support_host_);
978 CancelAuthCode();
979 }
980
981 void ArcAuthService::OnTermsAgreed(bool is_metrics_enabled,
982 bool is_backup_and_restore_enabled,
983 bool is_location_service_enabled) {
984 DCHECK(support_host_);
985
986 // Terms were accepted
987 profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true);
988
989 // Since this is ARC support's UI event callback, preference_handler_
990 // should be always created (see OnPrimaryUserProfilePrepared()).
991 // TODO(hidehiko): Simplify the logic with the code restructuring.
992 DCHECK(preference_handler_);
993 preference_handler_->EnableMetrics(is_metrics_enabled);
994 preference_handler_->EnableBackupRestore(is_backup_and_restore_enabled);
995 preference_handler_->EnableLocationService(is_location_service_enabled);
996 support_host_->ShowArcLoading();
997 StartArcAndroidManagementCheck();
998 } 304 }
999 305
1000 void ArcAuthService::OnAuthSucceeded(const std::string& auth_code) { 306 void ArcAuthService::OnAuthSucceeded(const std::string& auth_code) {
1001 DCHECK(support_host_);
1002 OnAuthCodeObtained(auth_code); 307 OnAuthCodeObtained(auth_code);
1003 } 308 }
1004 309
1005 void ArcAuthService::OnRetryClicked() { 310 void ArcAuthService::OnRetryClicked() {
1006 DCHECK(support_host_); 311 ArcSupportHost* support_host = ArcSessionManager::Get()->support_host();
1007 312 DCHECK(support_host);
Luis Héctor Chávez 2016/11/16 17:13:34 Please mention this is a callback from the Support
hidehiko 2016/11/16 19:52:05 Done.
1008 UpdateOptInActionUMA(OptInActionType::RETRY); 313 if (support_host->ui_page() == ArcSupportHost::UIPage::ERROR) {
1009 314 // This case is handled by ArcSessionManager::OnRetryClicked().
1010 // TODO(hidehiko): Simplify the retry logic. 315 return;
1011 if (!profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) {
1012 // If the user has not yet agreed on Terms of Service, then show it.
1013 support_host_->ShowTermsOfService();
1014 } else if (support_host_->ui_page() == ArcSupportHost::UIPage::ERROR &&
1015 !arc_bridge_service()->stopped()) {
1016 // ERROR_WITH_FEEDBACK is set in OnSignInFailed(). In the case, stopping
1017 // ARC was postponed to contain its internal state into the report.
1018 // Here, on retry, stop it, then restart.
1019 DCHECK_EQ(State::ACTIVE, state_);
1020 support_host_->ShowArcLoading();
1021 ShutdownBridge();
1022 reenable_arc_ = true;
1023 } else if (state_ == State::ACTIVE) {
1024 // This happens when ARC support Chrome app reports an error on "Sign in"
1025 // page.
1026 support_host_->ShowLso();
1027 } else {
1028 // Otherwise, we restart ARC. Note: this is the first boot case.
1029 // For second or later boot, either ERROR_WITH_FEEDBACK case or ACTIVE
1030 // case must hit.
1031 support_host_->ShowArcLoading();
1032 StartArcAndroidManagementCheck();
1033 } 316 }
1034 } 317 support_host->ShowLso();
1035
1036 void ArcAuthService::OnSendFeedbackClicked() {
1037 DCHECK(support_host_);
1038 chrome::OpenFeedbackDialog(nullptr);
1039 }
1040
1041 void ArcAuthService::OnMetricsModeChanged(bool enabled, bool managed) {
1042 if (!support_host_)
1043 return;
1044 support_host_->SetMetricsPreferenceCheckbox(enabled, managed);
1045 }
1046
1047 void ArcAuthService::OnBackupAndRestoreModeChanged(bool enabled, bool managed) {
1048 if (!support_host_)
1049 return;
1050 support_host_->SetBackupAndRestorePreferenceCheckbox(enabled, managed);
1051 }
1052
1053 void ArcAuthService::OnLocationServicesModeChanged(bool enabled, bool managed) {
1054 if (!support_host_)
1055 return;
1056 support_host_->SetLocationServicesPreferenceCheckbox(enabled, managed);
1057 }
1058
1059 std::ostream& operator<<(std::ostream& os, const ArcAuthService::State& state) {
1060 switch (state) {
1061 case ArcAuthService::State::NOT_INITIALIZED:
1062 return os << "NOT_INITIALIZED";
1063 case ArcAuthService::State::STOPPED:
1064 return os << "STOPPED";
1065 case ArcAuthService::State::SHOWING_TERMS_OF_SERVICE:
1066 return os << "SHOWING_TERMS_OF_SERVICE";
1067 case ArcAuthService::State::CHECKING_ANDROID_MANAGEMENT:
1068 return os << "CHECKING_ANDROID_MANAGEMENT";
1069 case ArcAuthService::State::ACTIVE:
1070 return os << "ACTIVE";
1071 }
1072
1073 // Some compiler reports an error even if all values of an enum-class are
1074 // covered indivisually in a switch statement.
1075 NOTREACHED();
1076 return os;
1077 } 318 }
1078 319
1079 } // namespace arc 320 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698