1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/login/signin/auth_sync_observer.h"
6
7#include "base/metrics/user_metrics.h"
8#include "base/metrics/user_metrics_action.h"
9#include "base/prefs/pref_service.h"
10#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
11#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
12#include "chrome/browser/chromeos/profiles/profile_helper.h"
13#include "chrome/browser/sync/profile_sync_service.h"
14#include "chrome/browser/sync/profile_sync_service_factory.h"
15#include "chrome/common/pref_names.h"
16#include "components/user_manager/user_manager.h"
17#include "components/user_manager/user_type.h"
18#include "content/public/browser/user_metrics.h"
19#include "google_apis/gaia/gaia_auth_util.h"
20
21class Profile;
22class ProfileSyncService;
23
24namespace chromeos {
25
26AuthSyncObserver::AuthSyncObserver(Profile* profile)
27    : profile_(profile) {
28}
29
30AuthSyncObserver::~AuthSyncObserver() {
31}
32
33void AuthSyncObserver::StartObserving() {
34  ProfileSyncService* sync_service =
35      ProfileSyncServiceFactory::GetForProfile(profile_);
36  if (sync_service)
37    sync_service->AddObserver(this);
38}
39
40void AuthSyncObserver::Shutdown() {
41  ProfileSyncService* sync_service =
42      ProfileSyncServiceFactory::GetForProfile(profile_);
43  if (sync_service)
44    sync_service->RemoveObserver(this);
45}
46
47void AuthSyncObserver::OnStateChanged() {
48  DCHECK(user_manager::UserManager::Get()->IsLoggedInAsRegularUser() ||
49         user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser());
50  ProfileSyncService* sync_service =
51      ProfileSyncServiceFactory::GetForProfile(profile_);
52  user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile_);
53  GoogleServiceAuthError::State state =
54      sync_service->GetAuthError().state();
55  if (state != GoogleServiceAuthError::NONE &&
56      state != GoogleServiceAuthError::CONNECTION_FAILED &&
57      state != GoogleServiceAuthError::SERVICE_UNAVAILABLE &&
58      state != GoogleServiceAuthError::REQUEST_CANCELED) {
59    // Invalidate OAuth2 refresh token to force Gaia sign-in flow. This is
60    // needed because sign-out/sign-in solution is suggested to the user.
61    // TODO(nkostylev): Remove after crosbug.com/25978 is implemented.
62    LOG(WARNING) << "Invalidate OAuth token because of a sync error: "
63                 << sync_service->GetAuthError().ToString();
64    std::string email = user->email();
65    DCHECK(!email.empty());
66    // TODO(nkostyelv): Change observer after active user has changed.
67    user_manager::User::OAuthTokenStatus old_status =
68        user->oauth_token_status();
69    user_manager::UserManager::Get()->SaveUserOAuthStatus(
70        email, user_manager::User::OAUTH2_TOKEN_STATUS_INVALID);
71    if (user->GetType() == user_manager::USER_TYPE_SUPERVISED &&
72        old_status != user_manager::User::OAUTH2_TOKEN_STATUS_INVALID) {
73       // Attempt to restore token from file.
74      ChromeUserManager::Get()
75          ->GetSupervisedUserManager()
76          ->LoadSupervisedUserToken(
77              profile_,
78              base::Bind(&AuthSyncObserver::OnSupervisedTokenLoaded,
79                         base::Unretained(this)));
80       content::RecordAction(
81           base::UserMetricsAction("ManagedUsers_Chromeos_Sync_Invalidated"));
82    }
83  } else if (state == GoogleServiceAuthError::NONE) {
84    if (user->GetType() == user_manager::USER_TYPE_SUPERVISED &&
85        user->oauth_token_status() ==
86            user_manager::User::OAUTH2_TOKEN_STATUS_INVALID) {
87      LOG(ERROR) <<
88          "Got an incorrectly invalidated token case, restoring token status.";
89      user_manager::UserManager::Get()->SaveUserOAuthStatus(
90          user->email(), user_manager::User::OAUTH2_TOKEN_STATUS_VALID);
91       content::RecordAction(
92           base::UserMetricsAction("ManagedUsers_Chromeos_Sync_Recovered"));
93    }
94  }
95}
96
97void AuthSyncObserver::OnSupervisedTokenLoaded(const std::string& token) {
98  ChromeUserManager::Get()->GetSupervisedUserManager()->ConfigureSyncWithToken(
99      profile_, token);
100}
101
102}  // namespace chromeos
103