1 // Copyright (c) 2012 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.
5 #include "chrome/browser/profiles/gaia_info_update_service.h"
7 #include "base/prefs/pref_service.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/profiles/profile_info_cache.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/profiles/profile_metrics.h"
15 #include "chrome/browser/profiles/profiles_state.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "chrome/common/pref_names.h"
18 #include "components/signin/core/common/profile_management_switches.h"
19 #include "content/public/browser/notification_details.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "ui/gfx/image/image.h"
25 // Update the user's GAIA info every 24 hours.
26 const int kUpdateIntervalHours
= 24;
28 // If the users's GAIA info is very out of date then wait at least this long
29 // before starting an update. This avoids slowdown during startup.
30 const int kMinUpdateIntervalSeconds
= 5;
34 GAIAInfoUpdateService::GAIAInfoUpdateService(Profile
* profile
)
36 SigninManagerBase
* signin_manager
=
37 SigninManagerFactory::GetForProfile(profile_
);
38 signin_manager
->AddObserver(this);
40 PrefService
* prefs
= profile_
->GetPrefs();
41 last_updated_
= base::Time::FromInternalValue(
42 prefs
->GetInt64(prefs::kProfileGAIAInfoUpdateTime
));
46 GAIAInfoUpdateService::~GAIAInfoUpdateService() {
47 DCHECK(!profile_
) << "Shutdown not called before dtor";
50 void GAIAInfoUpdateService::Update() {
51 // UMA Profile Metrics should be logged regularly.
52 ProfileMetrics::LogNumberOfProfiles(g_browser_process
->profile_manager());
54 // The user must be logged in.
55 SigninManagerBase
* signin_manager
=
56 SigninManagerFactory::GetForProfile(profile_
);
57 if (!signin_manager
->IsAuthenticated())
60 if (profile_image_downloader_
)
62 profile_image_downloader_
.reset(new ProfileDownloader(this));
63 profile_image_downloader_
->Start();
67 bool GAIAInfoUpdateService::ShouldUseGAIAProfileInfo(Profile
* profile
) {
68 #if defined(OS_CHROMEOS)
72 // To enable this feature for testing pass "--google-profile-info".
73 if (switches::IsGoogleProfileInfo())
76 // This feature is disable by default.
80 bool GAIAInfoUpdateService::NeedsProfilePicture() const {
84 int GAIAInfoUpdateService::GetDesiredImageSideLength() const {
88 Profile
* GAIAInfoUpdateService::GetBrowserProfile() {
92 std::string
GAIAInfoUpdateService::GetCachedPictureURL() const {
93 return profile_
->GetPrefs()->GetString(prefs::kProfileGAIAInfoPictureURL
);
96 bool GAIAInfoUpdateService::IsPreSignin() const {
100 void GAIAInfoUpdateService::OnProfileDownloadSuccess(
101 ProfileDownloader
* downloader
) {
102 // Make sure that |ProfileDownloader| gets deleted after return.
103 scoped_ptr
<ProfileDownloader
> profile_image_downloader(
104 profile_image_downloader_
.release());
106 // Save the last updated time.
107 last_updated_
= base::Time::Now();
108 profile_
->GetPrefs()->SetInt64(prefs::kProfileGAIAInfoUpdateTime
,
109 last_updated_
.ToInternalValue());
110 ScheduleNextUpdate();
112 base::string16 full_name
= downloader
->GetProfileFullName();
113 base::string16 given_name
= downloader
->GetProfileGivenName();
114 SkBitmap bitmap
= downloader
->GetProfilePicture();
115 ProfileDownloader::PictureStatus picture_status
=
116 downloader
->GetProfilePictureStatus();
117 std::string picture_url
= downloader
->GetProfilePictureURL();
119 ProfileInfoCache
& cache
=
120 g_browser_process
->profile_manager()->GetProfileInfoCache();
121 size_t profile_index
= cache
.GetIndexOfProfileWithPath(profile_
->GetPath());
122 if (profile_index
== std::string::npos
)
125 cache
.SetGAIANameOfProfileAtIndex(profile_index
, full_name
);
126 // The profile index may have changed.
127 profile_index
= cache
.GetIndexOfProfileWithPath(profile_
->GetPath());
128 DCHECK_NE(profile_index
, std::string::npos
);
130 cache
.SetGAIAGivenNameOfProfileAtIndex(profile_index
, given_name
);
131 // The profile index may have changed.
132 profile_index
= cache
.GetIndexOfProfileWithPath(profile_
->GetPath());
133 DCHECK_NE(profile_index
, std::string::npos
);
135 if (picture_status
== ProfileDownloader::PICTURE_SUCCESS
) {
136 profile_
->GetPrefs()->SetString(prefs::kProfileGAIAInfoPictureURL
,
138 gfx::Image gfx_image
= gfx::Image::CreateFrom1xBitmap(bitmap
);
139 cache
.SetGAIAPictureOfProfileAtIndex(profile_index
, &gfx_image
);
140 } else if (picture_status
== ProfileDownloader::PICTURE_DEFAULT
) {
141 cache
.SetGAIAPictureOfProfileAtIndex(profile_index
, NULL
);
144 const base::string16 hosted_domain
= downloader
->GetProfileHostedDomain();
145 profile_
->GetPrefs()->SetString(prefs::kGoogleServicesHostedDomain
,
146 (hosted_domain
.empty() ? Profile::kNoHostedDomainFound
:
147 base::UTF16ToUTF8(hosted_domain
)));
150 void GAIAInfoUpdateService::OnProfileDownloadFailure(
151 ProfileDownloader
* downloader
,
152 ProfileDownloaderDelegate::FailureReason reason
) {
153 profile_image_downloader_
.reset();
155 // Save the last updated time.
156 last_updated_
= base::Time::Now();
157 profile_
->GetPrefs()->SetInt64(prefs::kProfileGAIAInfoUpdateTime
,
158 last_updated_
.ToInternalValue());
159 ScheduleNextUpdate();
162 void GAIAInfoUpdateService::OnUsernameChanged(const std::string
& username
) {
163 ProfileInfoCache
& cache
=
164 g_browser_process
->profile_manager()->GetProfileInfoCache();
165 size_t profile_index
= cache
.GetIndexOfProfileWithPath(profile_
->GetPath());
166 if (profile_index
== std::string::npos
)
169 if (username
.empty()) {
170 // Unset the old user's GAIA info.
171 cache
.SetGAIANameOfProfileAtIndex(profile_index
, base::string16());
172 cache
.SetGAIAGivenNameOfProfileAtIndex(profile_index
, base::string16());
173 // The profile index may have changed.
174 profile_index
= cache
.GetIndexOfProfileWithPath(profile_
->GetPath());
175 if (profile_index
== std::string::npos
)
177 cache
.SetGAIAPictureOfProfileAtIndex(profile_index
, NULL
);
178 // Unset the cached URL.
179 profile_
->GetPrefs()->ClearPref(prefs::kProfileGAIAInfoPictureURL
);
181 // Update the new user's GAIA info.
186 void GAIAInfoUpdateService::Shutdown() {
188 profile_image_downloader_
.reset();
189 SigninManagerBase
* signin_manager
=
190 SigninManagerFactory::GetForProfile(profile_
);
191 signin_manager
->RemoveObserver(this);
193 // OK to reset |profile_| pointer here because GAIAInfoUpdateService will not
194 // access it again. This pointer is also used to implement the delegate for
195 // |profile_image_downloader_|. However that object was destroyed above.
199 void GAIAInfoUpdateService::ScheduleNextUpdate() {
200 if (timer_
.IsRunning())
203 const base::TimeDelta desired_delta
=
204 base::TimeDelta::FromHours(kUpdateIntervalHours
);
205 const base::TimeDelta update_delta
= base::Time::Now() - last_updated_
;
207 base::TimeDelta delta
;
208 if (update_delta
< base::TimeDelta() || update_delta
> desired_delta
)
209 delta
= base::TimeDelta::FromSeconds(kMinUpdateIntervalSeconds
);
211 delta
= desired_delta
- update_delta
;
213 timer_
.Start(FROM_HERE
, delta
, this, &GAIAInfoUpdateService::Update
);
216 void GAIAInfoUpdateService::GoogleSigninSucceeded(
217 const std::string
& account_id
,
218 const std::string
& username
,
219 const std::string
& password
) {
220 OnUsernameChanged(username
);
223 void GAIAInfoUpdateService::GoogleSignedOut(const std::string
& account_id
,
224 const std::string
& username
) {
225 OnUsernameChanged(std::string());