Home | History | Annotate | Download | only in profiles
      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 
     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 
     44 GAIAInfoUpdateService::~GAIAInfoUpdateService() {
     45   DCHECK(!profile_) << "Shutdown not called before dtor";
     46 }
     47 
     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
     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 
     79 bool GAIAInfoUpdateService::NeedsProfilePicture() const {
     80   return true;
     81 }
     82 
     83 int GAIAInfoUpdateService::GetDesiredImageSideLength() const {
     84   return 256;
     85 }
     86 
     87 Profile* GAIAInfoUpdateService::GetBrowserProfile() {
     88   return profile_;
     89 }
     90 
     91 std::string GAIAInfoUpdateService::GetCachedPictureURL() const {
     92   return profile_->GetPrefs()->GetString(prefs::kProfileGAIAInfoPictureURL);
     93 }
     94 
     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 
    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 
    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 
    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 
    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 
    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 
    213 void GAIAInfoUpdateService::GoogleSignedOut(const std::string& account_id,
    214                                             const std::string& username) {
    215   OnUsernameChanged(std::string());
    216 }
    217