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 "chrome/browser/browser_process.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/profiles/profile_info_cache.h"
12 #include "chrome/browser/profiles/profile_manager.h"
13 #include "chrome/browser/signin/signin_manager_factory.h"
14 #include "chrome/browser/sync/profile_sync_service.h"
15 #include "chrome/common/pref_names.h"
16 #include "components/signin/core/common/profile_management_switches.h"
17 #include "content/public/browser/notification_details.h"
18 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "ui/gfx/image/image.h"
23 // Update the user's GAIA info every 24 hours.
24 const int kUpdateIntervalHours = 24;
26 // If the users's GAIA info is very out of date then wait at least this long
27 // before starting an update. This avoids slowdown during startup.
28 const int kMinUpdateIntervalSeconds = 5;
32 GAIAInfoUpdateService::GAIAInfoUpdateService(Profile* profile)
34 SigninManagerBase* signin_manager =
35 SigninManagerFactory::GetForProfile(profile_);
36 signin_manager->AddObserver(this);
38 PrefService* prefs = profile_->GetPrefs();
39 last_updated_ = base::Time::FromInternalValue(
40 prefs->GetInt64(prefs::kProfileGAIAInfoUpdateTime));
44 GAIAInfoUpdateService::~GAIAInfoUpdateService() {
45 DCHECK(!profile_) << "Shutdown not called before dtor";
48 void GAIAInfoUpdateService::Update() {
49 // The user must be logged in.
50 SigninManagerBase* signin_manager =
51 SigninManagerFactory::GetForProfile(profile_);
52 if (signin_manager->GetAuthenticatedAccountId().empty())
55 if (profile_image_downloader_)
57 profile_image_downloader_.reset(new ProfileDownloader(this));
58 profile_image_downloader_->Start();
62 bool GAIAInfoUpdateService::ShouldUseGAIAProfileInfo(Profile* profile) {
63 #if defined(OS_CHROMEOS)
67 // Sync must be allowed.
68 if (!profile->GetOriginalProfile()->IsSyncAccessible())
71 // To enable this feature for testing pass "--google-profile-info".
72 if (switches::IsGoogleProfileInfo())
75 // This feature is disable by default.
79 bool GAIAInfoUpdateService::NeedsProfilePicture() const {
83 int GAIAInfoUpdateService::GetDesiredImageSideLength() const {
87 Profile* GAIAInfoUpdateService::GetBrowserProfile() {
91 std::string GAIAInfoUpdateService::GetCachedPictureURL() const {
92 return profile_->GetPrefs()->GetString(prefs::kProfileGAIAInfoPictureURL);
95 void GAIAInfoUpdateService::OnProfileDownloadSuccess(
96 ProfileDownloader* downloader) {
97 // Make sure that |ProfileDownloader| gets deleted after return.
98 scoped_ptr<ProfileDownloader> profile_image_downloader(
99 profile_image_downloader_.release());
101 // Save the last updated time.
102 last_updated_ = base::Time::Now();
103 profile_->GetPrefs()->SetInt64(prefs::kProfileGAIAInfoUpdateTime,
104 last_updated_.ToInternalValue());
105 ScheduleNextUpdate();
107 base::string16 full_name = downloader->GetProfileFullName();
108 base::string16 given_name = downloader->GetProfileGivenName();
109 SkBitmap bitmap = downloader->GetProfilePicture();
110 ProfileDownloader::PictureStatus picture_status =
111 downloader->GetProfilePictureStatus();
112 std::string picture_url = downloader->GetProfilePictureURL();
114 ProfileInfoCache& cache =
115 g_browser_process->profile_manager()->GetProfileInfoCache();
116 size_t profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
117 if (profile_index == std::string::npos)
120 cache.SetGAIANameOfProfileAtIndex(profile_index, full_name);
121 // The profile index may have changed.
122 profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
123 DCHECK_NE(profile_index, std::string::npos);
125 cache.SetGAIAGivenNameOfProfileAtIndex(profile_index, given_name);
126 // The profile index may have changed.
127 profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
128 DCHECK_NE(profile_index, std::string::npos);
130 if (picture_status == ProfileDownloader::PICTURE_SUCCESS) {
131 profile_->GetPrefs()->SetString(prefs::kProfileGAIAInfoPictureURL,
133 gfx::Image gfx_image = gfx::Image::CreateFrom1xBitmap(bitmap);
134 cache.SetGAIAPictureOfProfileAtIndex(profile_index, &gfx_image);
135 } else if (picture_status == ProfileDownloader::PICTURE_DEFAULT) {
136 cache.SetGAIAPictureOfProfileAtIndex(profile_index, NULL);
140 void GAIAInfoUpdateService::OnProfileDownloadFailure(
141 ProfileDownloader* downloader,
142 ProfileDownloaderDelegate::FailureReason reason) {
143 profile_image_downloader_.reset();
145 // Save the last updated time.
146 last_updated_ = base::Time::Now();
147 profile_->GetPrefs()->SetInt64(prefs::kProfileGAIAInfoUpdateTime,
148 last_updated_.ToInternalValue());
149 ScheduleNextUpdate();
152 void GAIAInfoUpdateService::OnUsernameChanged(const std::string& username) {
153 ProfileInfoCache& cache =
154 g_browser_process->profile_manager()->GetProfileInfoCache();
155 size_t profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
156 if (profile_index == std::string::npos)
159 if (username.empty()) {
160 // Unset the old user's GAIA info.
161 cache.SetGAIANameOfProfileAtIndex(profile_index, base::string16());
162 cache.SetGAIAGivenNameOfProfileAtIndex(profile_index, base::string16());
163 // The profile index may have changed.
164 profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
165 if (profile_index == std::string::npos)
167 cache.SetGAIAPictureOfProfileAtIndex(profile_index, NULL);
168 // Unset the cached URL.
169 profile_->GetPrefs()->ClearPref(prefs::kProfileGAIAInfoPictureURL);
171 // Update the new user's GAIA info.
176 void GAIAInfoUpdateService::Shutdown() {
178 profile_image_downloader_.reset();
179 SigninManagerBase* signin_manager =
180 SigninManagerFactory::GetForProfile(profile_);
181 signin_manager->RemoveObserver(this);
183 // OK to reset |profile_| pointer here because GAIAInfoUpdateService will not
184 // access it again. This pointer is also used to implement the delegate for
185 // |profile_image_downloader_|. However that object was destroyed above.
189 void GAIAInfoUpdateService::ScheduleNextUpdate() {
190 if (timer_.IsRunning())
193 const base::TimeDelta desired_delta =
194 base::TimeDelta::FromHours(kUpdateIntervalHours);
195 const base::TimeDelta update_delta = base::Time::Now() - last_updated_;
197 base::TimeDelta delta;
198 if (update_delta < base::TimeDelta() || update_delta > desired_delta)
199 delta = base::TimeDelta::FromSeconds(kMinUpdateIntervalSeconds);
201 delta = desired_delta - update_delta;
203 timer_.Start(FROM_HERE, delta, this, &GAIAInfoUpdateService::Update);
206 void GAIAInfoUpdateService::GoogleSigninSucceeded(
207 const std::string& username,
208 const std::string& password) {
209 OnUsernameChanged(username);
212 void GAIAInfoUpdateService::GoogleSignedOut(const std::string& username) {
213 OnUsernameChanged(std::string());