Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2013 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 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_
      6 #define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_
      7 
      8 #include <map>
      9 #include <set>
     10 #include <string>
     11 
     12 #include "base/basictypes.h"
     13 #include "base/compiler_specific.h"
     14 #include "base/memory/linked_ptr.h"
     15 #include "base/memory/ref_counted.h"
     16 #include "base/memory/scoped_ptr.h"
     17 #include "base/memory/weak_ptr.h"
     18 #include "base/time/time.h"
     19 #include "base/timer/timer.h"
     20 #include "base/values.h"
     21 #include "chrome/browser/chromeos/login/user.h"
     22 #include "chrome/browser/chromeos/login/user_image_loader.h"
     23 #include "chrome/browser/chromeos/login/user_image_manager.h"
     24 #include "chrome/browser/chromeos/policy/cloud_external_data_policy_observer.h"
     25 #include "chrome/browser/profiles/profile_downloader_delegate.h"
     26 #include "ui/gfx/image/image_skia.h"
     27 
     28 class ProfileDownloader;
     29 class UserImage;
     30 
     31 namespace base {
     32 class FilePath;
     33 class SequencedTaskRunner;
     34 }
     35 
     36 namespace chromeos {
     37 
     38 class CrosSettings;
     39 class UserImageSyncObserver;
     40 class UserManager;
     41 
     42 class UserImageManagerImpl
     43     : public UserImageManager,
     44       public ProfileDownloaderDelegate,
     45       public policy::CloudExternalDataPolicyObserver::Delegate {
     46  public:
     47   UserImageManagerImpl(CrosSettings* cros_settings, UserManager* user_manager);
     48 
     49   // UserImageManager:
     50   virtual ~UserImageManagerImpl();
     51   virtual void LoadUserImages(const UserList& users) OVERRIDE;
     52   virtual void UserLoggedIn(const std::string& user_id,
     53                             bool user_is_new,
     54                             bool user_is_local) OVERRIDE;
     55   virtual void SaveUserDefaultImageIndex(const std::string& user_id,
     56                                          int default_image_index) OVERRIDE;
     57   virtual void SaveUserImage(const std::string& user_id,
     58                              const UserImage& user_image) OVERRIDE;
     59   virtual void SaveUserImageFromFile(const std::string& user_id,
     60                                      const base::FilePath& path) OVERRIDE;
     61   virtual void SaveUserImageFromProfileImage(
     62       const std::string& user_id) OVERRIDE;
     63   virtual void DeleteUserImage(const std::string& user_id) OVERRIDE;
     64   virtual void DownloadProfileImage(const std::string& reason) OVERRIDE;
     65   virtual const gfx::ImageSkia& DownloadedProfileImage() const OVERRIDE;
     66   virtual UserImageSyncObserver* GetSyncObserver() const OVERRIDE;
     67   virtual void Shutdown() OVERRIDE;
     68 
     69   // policy::CloudExternalDataPolicyObserver::Delegate:
     70   virtual void OnExternalDataSet(const std::string& policy,
     71                                  const std::string& user_id) OVERRIDE;
     72   virtual void OnExternalDataCleared(const std::string& policy,
     73                                      const std::string& user_id) OVERRIDE;
     74   virtual void OnExternalDataFetched(const std::string& policy,
     75                                      const std::string& user_id,
     76                                      scoped_ptr<std::string> data) OVERRIDE;
     77 
     78   static void IgnoreProfileDataDownloadDelayForTesting();
     79   void StopPolicyObserverForTesting();
     80 
     81  private:
     82   friend class UserImageManagerTest;
     83 
     84   // Every image load or update is encapsulated by a Job. Whenever an image load
     85   // or update is requested for a user, the Job currently running for that user
     86   // (if any) is canceled. This ensures that at most one Job is running per user
     87   // at any given time. There are two further guarantees:
     88   //
     89   // * Changes to User objects and local state are performed on the thread that
     90   //   |this| runs on.
     91   // * File writes and deletions are performed via |background_task_runner_|.
     92   //
     93   // With the above, it is guaranteed that any changes made by a canceled Job
     94   // cannot race against against changes made by the superseding Job.
     95   class Job;
     96 
     97   // ProfileDownloaderDelegate:
     98   virtual bool NeedsProfilePicture() const OVERRIDE;
     99   virtual int GetDesiredImageSideLength() const OVERRIDE;
    100   virtual Profile* GetBrowserProfile() OVERRIDE;
    101   virtual std::string GetCachedPictureURL() const OVERRIDE;
    102   virtual void OnProfileDownloadSuccess(ProfileDownloader* downloader) OVERRIDE;
    103   virtual void OnProfileDownloadFailure(
    104       ProfileDownloader* downloader,
    105       ProfileDownloaderDelegate::FailureReason reason) OVERRIDE;
    106 
    107   // Returns true if the user image for |user_id| is managed by policy and the
    108   // user is not allowed to change it.
    109   bool IsUserImageManaged(const std::string& user_id) const;
    110 
    111   // Randomly chooses one of the default images for the specified user, sends a
    112   // LOGIN_USER_IMAGE_CHANGED notification and updates local state.
    113   void SetInitialUserImage(const std::string& user_id);
    114 
    115   // Initializes the |downloaded_profile_image_| for the currently logged-in
    116   // user to a profile image that had been downloaded and saved before if such
    117   // a saved image is available and no updated image has been downloaded yet.
    118   void TryToInitDownloadedProfileImage();
    119 
    120   // Returns true if the profile image needs to be downloaded. This is the case
    121   // when a GAIA user is logged in and at least one of the following applies:
    122   // * The profile image has explicitly been requested by a call to
    123   //   DownloadProfileImage() and has not been successfully downloaded since.
    124   // * The user's user image is the profile image.
    125   bool NeedProfileImage() const;
    126 
    127   // Downloads the profile data for the currently logged-in user. The user's
    128   // full name and, if NeedProfileImage() is true, the profile image are
    129   // downloaded. |reason| is an arbitrary string (used to report UMA histograms
    130   // with download times).
    131   void DownloadProfileData(const std::string& reason);
    132 
    133   // Removes |user_id| from the dictionary |prefs_dict_root| in local state and
    134   // deletes the image file that the dictionary referenced for that user.
    135   void DeleteUserImageAndLocalStateEntry(const std::string& user_id,
    136                                          const char* prefs_dict_root);
    137 
    138   // Called when a Job updates the copy of the user image held in memory by
    139   // |user|. Allows |this| to update |downloaded_profile_image_| and send a
    140   // NOTIFICATION_LOGIN_USER_IMAGE_CHANGED notification.
    141   void OnJobChangedUserImage(const User* user);
    142 
    143   // Called when a Job for |user_id| finishes. If a migration was required for
    144   // the user, the migration is now complete and the old image file for that
    145   // user, if any, is deleted.
    146   void OnJobDone(const std::string& user_id);
    147 
    148   // Completes migration by removing |user_id| from the old prefs dictionary.
    149   void UpdateLocalStateAfterMigration(const std::string& user_id);
    150 
    151   // Create a sync observer if a user is logged in, the user's user image is
    152   // allowed to be synced and no sync observer exists yet.
    153   void TryToCreateImageSyncObserver();
    154 
    155   // The user manager.
    156   UserManager* user_manager_;
    157 
    158   // Loader for JPEG user images.
    159   scoped_refptr<UserImageLoader> image_loader_;
    160 
    161   // Unsafe loader instance for all user images formats.
    162   scoped_refptr<UserImageLoader> unsafe_image_loader_;
    163 
    164   // Whether the |profile_downloader_| is downloading the profile image for the
    165   // currently logged-in user (and not just the full name). Only valid when a
    166   // download is currently in progress.
    167   bool downloading_profile_image_;
    168 
    169   // Download reason given to DownloadProfileImage(), used for UMA histograms.
    170   // Only valid when a download is currently in progress and
    171   // |downloading_profile_image_| is true.
    172   std::string profile_image_download_reason_;
    173 
    174   // Time when the profile image download started. Only valid when a download is
    175   // currently in progress and |downloading_profile_image_| is true.
    176   base::TimeTicks profile_image_load_start_time_;
    177 
    178   // Downloader for the current user's profile data. NULL when no download is
    179   // currently in progress.
    180   scoped_ptr<ProfileDownloader> profile_downloader_;
    181 
    182   // The currently logged-in user's downloaded profile image, if successfully
    183   // downloaded or initialized from a previously downloaded and saved image.
    184   gfx::ImageSkia downloaded_profile_image_;
    185 
    186   // Data URL corresponding to |downloaded_profile_image_|. Empty if no
    187   // |downloaded_profile_image_| is currently available.
    188   std::string downloaded_profile_image_data_url_;
    189 
    190   // URL from which |downloaded_profile_image_| was downloaded. Empty if no
    191   // |downloaded_profile_image_| is currently available.
    192   GURL profile_image_url_;
    193 
    194   // Whether a download of the currently logged-in user's profile image has been
    195   // explicitly requested by a call to DownloadProfileImage() and has not been
    196   // satisfied by a successful download yet.
    197   bool profile_image_requested_;
    198 
    199   // Timer used to start a profile data download shortly after login and to
    200   // restart the download after network errors.
    201   base::OneShotTimer<UserImageManagerImpl> profile_download_one_shot_timer_;
    202 
    203   // Timer used to periodically start a profile data, ensuring the profile data
    204   // stays up to date.
    205   base::RepeatingTimer<UserImageManagerImpl> profile_download_periodic_timer_;
    206 
    207   // Users whose user images need to be migrated from the old dictionary pref to
    208   // the new dictionary pref, converting any non-default images to JPEG format.
    209   std::set<std::string> users_to_migrate_;
    210 
    211   // Sync observer for the currently logged-in user.
    212   scoped_ptr<UserImageSyncObserver> user_image_sync_observer_;
    213 
    214   // Observer for the policy that can be used to manage user images.
    215   scoped_ptr<policy::CloudExternalDataPolicyObserver> policy_observer_;
    216 
    217   // Background task runner on which Jobs perform file I/O and the image
    218   // decoders run.
    219   scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
    220 
    221   // The currently running jobs.
    222   std::map<std::string, linked_ptr<Job> > jobs_;
    223 
    224   // List of user_ids whose user image is managed by policy.
    225   std::set<std::string> users_with_managed_images_;
    226 
    227   base::WeakPtrFactory<UserImageManagerImpl> weak_factory_;
    228 
    229   DISALLOW_COPY_AND_ASSIGN(UserImageManagerImpl);
    230 };
    231 
    232 }  // namespace chromeos
    233 
    234 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_
    235