• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/profiles/gaia_info_update_service.h"
6 
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"
20 
21 namespace {
22 
23 // Update the user's GAIA info every 24 hours.
24 const int kUpdateIntervalHours = 24;
25 
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;
29 
30 }  // namespace
31 
GAIAInfoUpdateService(Profile * profile)32 GAIAInfoUpdateService::GAIAInfoUpdateService(Profile* profile)
33     : profile_(profile) {
34   SigninManagerBase* signin_manager =
35       SigninManagerFactory::GetForProfile(profile_);
36   signin_manager->AddObserver(this);
37 
38   PrefService* prefs = profile_->GetPrefs();
39   last_updated_ = base::Time::FromInternalValue(
40       prefs->GetInt64(prefs::kProfileGAIAInfoUpdateTime));
41   ScheduleNextUpdate();
42 }
43 
~GAIAInfoUpdateService()44 GAIAInfoUpdateService::~GAIAInfoUpdateService() {
45   DCHECK(!profile_) << "Shutdown not called before dtor";
46 }
47 
Update()48 void GAIAInfoUpdateService::Update() {
49   // The user must be logged in.
50   SigninManagerBase* signin_manager =
51       SigninManagerFactory::GetForProfile(profile_);
52   if (!signin_manager->IsAuthenticated())
53     return;
54 
55   if (profile_image_downloader_)
56     return;
57   profile_image_downloader_.reset(new ProfileDownloader(this));
58   profile_image_downloader_->Start();
59 }
60 
61 // static
ShouldUseGAIAProfileInfo(Profile * profile)62 bool GAIAInfoUpdateService::ShouldUseGAIAProfileInfo(Profile* profile) {
63 #if defined(OS_CHROMEOS)
64   return false;
65 #endif
66 
67   // Sync must be allowed.
68   if (!profile->GetOriginalProfile()->IsSyncAccessible())
69     return false;
70 
71   // To enable this feature for testing pass "--google-profile-info".
72   if (switches::IsGoogleProfileInfo())
73     return true;
74 
75   // This feature is disable by default.
76   return false;
77 }
78 
NeedsProfilePicture() const79 bool GAIAInfoUpdateService::NeedsProfilePicture() const {
80   return true;
81 }
82 
GetDesiredImageSideLength() const83 int GAIAInfoUpdateService::GetDesiredImageSideLength() const {
84   return 256;
85 }
86 
GetBrowserProfile()87 Profile* GAIAInfoUpdateService::GetBrowserProfile() {
88   return profile_;
89 }
90 
GetCachedPictureURL() const91 std::string GAIAInfoUpdateService::GetCachedPictureURL() const {
92   return profile_->GetPrefs()->GetString(prefs::kProfileGAIAInfoPictureURL);
93 }
94 
OnProfileDownloadSuccess(ProfileDownloader * downloader)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());
100 
101   // Save the last updated time.
102   last_updated_ = base::Time::Now();
103   profile_->GetPrefs()->SetInt64(prefs::kProfileGAIAInfoUpdateTime,
104                                  last_updated_.ToInternalValue());
105   ScheduleNextUpdate();
106 
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();
113 
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)
118     return;
119 
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);
124 
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);
129 
130   if (picture_status == ProfileDownloader::PICTURE_SUCCESS) {
131     profile_->GetPrefs()->SetString(prefs::kProfileGAIAInfoPictureURL,
132                                     picture_url);
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);
137   }
138 }
139 
OnProfileDownloadFailure(ProfileDownloader * downloader,ProfileDownloaderDelegate::FailureReason reason)140 void GAIAInfoUpdateService::OnProfileDownloadFailure(
141     ProfileDownloader* downloader,
142     ProfileDownloaderDelegate::FailureReason reason) {
143   profile_image_downloader_.reset();
144 
145   // Save the last updated time.
146   last_updated_ = base::Time::Now();
147   profile_->GetPrefs()->SetInt64(prefs::kProfileGAIAInfoUpdateTime,
148                                  last_updated_.ToInternalValue());
149   ScheduleNextUpdate();
150 }
151 
OnUsernameChanged(const std::string & username)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)
157     return;
158 
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)
166       return;
167     cache.SetGAIAPictureOfProfileAtIndex(profile_index, NULL);
168     // Unset the cached URL.
169     profile_->GetPrefs()->ClearPref(prefs::kProfileGAIAInfoPictureURL);
170   } else {
171     // Update the new user's GAIA info.
172     Update();
173   }
174 }
175 
Shutdown()176 void GAIAInfoUpdateService::Shutdown() {
177   timer_.Stop();
178   profile_image_downloader_.reset();
179   SigninManagerBase* signin_manager =
180       SigninManagerFactory::GetForProfile(profile_);
181   signin_manager->RemoveObserver(this);
182 
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.
186   profile_ = NULL;
187 }
188 
ScheduleNextUpdate()189 void GAIAInfoUpdateService::ScheduleNextUpdate() {
190   if (timer_.IsRunning())
191     return;
192 
193   const base::TimeDelta desired_delta =
194       base::TimeDelta::FromHours(kUpdateIntervalHours);
195   const base::TimeDelta update_delta = base::Time::Now() - last_updated_;
196 
197   base::TimeDelta delta;
198   if (update_delta < base::TimeDelta() || update_delta > desired_delta)
199     delta = base::TimeDelta::FromSeconds(kMinUpdateIntervalSeconds);
200   else
201     delta = desired_delta - update_delta;
202 
203   timer_.Start(FROM_HERE, delta, this, &GAIAInfoUpdateService::Update);
204 }
205 
GoogleSigninSucceeded(const std::string & account_id,const std::string & username,const std::string & password)206 void GAIAInfoUpdateService::GoogleSigninSucceeded(
207     const std::string& account_id,
208     const std::string& username,
209     const std::string& password) {
210   OnUsernameChanged(username);
211 }
212 
GoogleSignedOut(const std::string & account_id,const std::string & username)213 void GAIAInfoUpdateService::GoogleSignedOut(const std::string& account_id,
214                                             const std::string& username) {
215   OnUsernameChanged(std::string());
216 }
217