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/command_line.h"
      8 #include "base/prefs/pref_service.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/sync/profile_sync_service.h"
     15 #include "chrome/common/chrome_switches.h"
     16 #include "chrome/common/pref_names.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   PrefService* prefs = profile_->GetPrefs();
     35   username_pref_.Init(prefs::kGoogleServicesUsername, prefs,
     36                       base::Bind(&GAIAInfoUpdateService::OnUsernameChanged,
     37                                  base::Unretained(this)));
     38 
     39   last_updated_ = base::Time::FromInternalValue(
     40       prefs->GetInt64(prefs::kProfileGAIAInfoUpdateTime));
     41   ScheduleNextUpdate();
     42 }
     43 
     44 GAIAInfoUpdateService::~GAIAInfoUpdateService() {
     45 }
     46 
     47 void GAIAInfoUpdateService::Update() {
     48   // The user must be logged in.
     49   std::string username = profile_->GetPrefs()->GetString(
     50       prefs::kGoogleServicesUsername);
     51   if (username.empty())
     52     return;
     53 
     54   if (profile_image_downloader_)
     55     return;
     56   profile_image_downloader_.reset(new ProfileDownloader(this));
     57   profile_image_downloader_->Start();
     58 }
     59 
     60 // static
     61 bool GAIAInfoUpdateService::ShouldUseGAIAProfileInfo(Profile* profile) {
     62 #if defined(OS_CHROMEOS)
     63   return false;
     64 #endif
     65 
     66   // Sync must be allowed.
     67   if (!profile->GetOriginalProfile()->IsSyncAccessible())
     68     return false;
     69 
     70   // To enable this feature for testing pass "--google-profile-info".
     71   if (CommandLine::ForCurrentProcess()->HasSwitch(
     72       switches::kGoogleProfileInfo)) {
     73     return true;
     74   }
     75 
     76   // This feature is disable by default.
     77   return false;
     78 }
     79 
     80 bool GAIAInfoUpdateService::NeedsProfilePicture() const {
     81   return true;
     82 }
     83 
     84 int GAIAInfoUpdateService::GetDesiredImageSideLength() const {
     85   return 256;
     86 }
     87 
     88 Profile* GAIAInfoUpdateService::GetBrowserProfile() {
     89   return profile_;
     90 }
     91 
     92 std::string GAIAInfoUpdateService::GetCachedPictureURL() const {
     93   return profile_->GetPrefs()->GetString(prefs::kProfileGAIAInfoPictureURL);
     94 }
     95 
     96 void GAIAInfoUpdateService::OnProfileDownloadSuccess(
     97     ProfileDownloader* downloader) {
     98   // Make sure that |ProfileDownloader| gets deleted after return.
     99   scoped_ptr<ProfileDownloader> profile_image_downloader(
    100       profile_image_downloader_.release());
    101 
    102   // Save the last updated time.
    103   last_updated_ = base::Time::Now();
    104   profile_->GetPrefs()->SetInt64(prefs::kProfileGAIAInfoUpdateTime,
    105                                  last_updated_.ToInternalValue());
    106   ScheduleNextUpdate();
    107 
    108   base::string16 full_name = downloader->GetProfileFullName();
    109   base::string16 given_name = downloader->GetProfileGivenName();
    110   SkBitmap bitmap = downloader->GetProfilePicture();
    111   ProfileDownloader::PictureStatus picture_status =
    112       downloader->GetProfilePictureStatus();
    113   std::string picture_url = downloader->GetProfilePictureURL();
    114 
    115   ProfileInfoCache& cache =
    116       g_browser_process->profile_manager()->GetProfileInfoCache();
    117   size_t profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
    118   if (profile_index == std::string::npos)
    119     return;
    120 
    121   cache.SetGAIANameOfProfileAtIndex(profile_index, full_name);
    122   cache.SetGAIAGivenNameOfProfileAtIndex(profile_index, given_name);
    123 
    124   // The profile index may have changed.
    125   profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
    126   if (profile_index == std::string::npos)
    127     return;
    128   if (picture_status == ProfileDownloader::PICTURE_SUCCESS) {
    129     profile_->GetPrefs()->SetString(prefs::kProfileGAIAInfoPictureURL,
    130                                     picture_url);
    131     gfx::Image gfx_image = gfx::Image::CreateFrom1xBitmap(bitmap);
    132     cache.SetGAIAPictureOfProfileAtIndex(profile_index, &gfx_image);
    133   } else if (picture_status == ProfileDownloader::PICTURE_DEFAULT) {
    134     cache.SetGAIAPictureOfProfileAtIndex(profile_index, NULL);
    135   }
    136 
    137   // If this profile hasn't switched to using GAIA information for the profile
    138   // name and picture then switch it now. Once the profile has switched this
    139   // preference guards against clobbering the user's custom settings.
    140   if (!cache.GetHasMigratedToGAIAInfoOfProfileAtIndex(profile_index)) {
    141     cache.SetHasMigratedToGAIAInfoOfProfileAtIndex(profile_index, true);
    142     // Order matters here for shortcut management, like in
    143     // ProfileShortcutManagerWin::OnProfileAdded, as the picture update does not
    144     // allow us to change the target, so we have to apply any renaming first. We
    145     // also need to re-fetch the index, as SetIsUsingGAIANameOfProfileAtIndex
    146     // may alter it.
    147     cache.SetIsUsingGAIANameOfProfileAtIndex(profile_index, true);
    148     profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
    149     cache.SetIsUsingGAIAPictureOfProfileAtIndex(profile_index, true);
    150   }
    151 }
    152 
    153 void GAIAInfoUpdateService::OnProfileDownloadFailure(
    154     ProfileDownloader* downloader,
    155     ProfileDownloaderDelegate::FailureReason reason) {
    156   profile_image_downloader_.reset();
    157 
    158   // Save the last updated time.
    159   last_updated_ = base::Time::Now();
    160   profile_->GetPrefs()->SetInt64(prefs::kProfileGAIAInfoUpdateTime,
    161                                  last_updated_.ToInternalValue());
    162   ScheduleNextUpdate();
    163 }
    164 
    165 void GAIAInfoUpdateService::OnUsernameChanged() {
    166   ProfileInfoCache& cache =
    167       g_browser_process->profile_manager()->GetProfileInfoCache();
    168   size_t profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
    169   if (profile_index == std::string::npos)
    170     return;
    171 
    172   std::string username = profile_->GetPrefs()->GetString(
    173       prefs::kGoogleServicesUsername);
    174   if (username.empty()) {
    175     // Unset the old user's GAIA info.
    176     cache.SetGAIANameOfProfileAtIndex(profile_index, base::string16());
    177     // The profile index may have changed.
    178     profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
    179     if (profile_index == std::string::npos)
    180       return;
    181     cache.SetGAIAPictureOfProfileAtIndex(profile_index, NULL);
    182     // Unset the cached URL.
    183     profile_->GetPrefs()->ClearPref(prefs::kProfileGAIAInfoPictureURL);
    184   } else {
    185     // Update the new user's GAIA info.
    186     Update();
    187   }
    188 }
    189 
    190 void GAIAInfoUpdateService::ScheduleNextUpdate() {
    191   if (timer_.IsRunning())
    192     return;
    193 
    194   const base::TimeDelta desired_delta =
    195       base::TimeDelta::FromHours(kUpdateIntervalHours);
    196   const base::TimeDelta update_delta = base::Time::Now() - last_updated_;
    197 
    198   base::TimeDelta delta;
    199   if (update_delta < base::TimeDelta() || update_delta > desired_delta)
    200     delta = base::TimeDelta::FromSeconds(kMinUpdateIntervalSeconds);
    201   else
    202     delta = desired_delta - update_delta;
    203 
    204   timer_.Start(FROM_HERE, delta, this, &GAIAInfoUpdateService::Update);
    205 }
    206