Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(271)

Side by Side Diff: chrome/browser/chromeos/login/user_image_manager_impl.h

Issue 69863006: Address races in UserImageManagerImpl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix WallpaperManager browser tests now that UserImageLoader contains a DCHECK(success). Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_ 5 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_
6 #define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_ 6 #define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_
7 7
8 #include <map>
8 #include <set> 9 #include <set>
9 #include <string> 10 #include <string>
10 11
11 #include "base/basictypes.h" 12 #include "base/basictypes.h"
13 #include "base/memory/linked_ptr.h"
12 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/weak_ptr.h"
14 #include "base/time/time.h" 17 #include "base/time/time.h"
15 #include "base/timer/timer.h" 18 #include "base/timer/timer.h"
19 #include "base/values.h"
16 #include "chrome/browser/chromeos/login/user.h" 20 #include "chrome/browser/chromeos/login/user.h"
17 #include "chrome/browser/chromeos/login/user_image_loader.h" 21 #include "chrome/browser/chromeos/login/user_image_loader.h"
18 #include "chrome/browser/chromeos/login/user_image_manager.h" 22 #include "chrome/browser/chromeos/login/user_image_manager.h"
19 #include "chrome/browser/profiles/profile_downloader_delegate.h" 23 #include "chrome/browser/profiles/profile_downloader_delegate.h"
20 #include "ui/gfx/image/image_skia.h" 24 #include "ui/gfx/image/image_skia.h"
21 25
22 class ProfileDownloader; 26 class ProfileDownloader;
23 class UserImage; 27 class UserImage;
24 28
25 namespace base { 29 namespace base {
26 class FilePath; 30 class FilePath;
31 class SequencedTaskRunner;
27 } 32 }
28 33
29 namespace chromeos { 34 namespace chromeos {
30 class UserImageSyncObserver; 35 class UserImageSyncObserver;
31 } 36 }
32 37
33 namespace chromeos { 38 namespace chromeos {
34 39
35 class UserImageManagerImpl : public UserImageManager, 40 class UserImageManagerImpl : public UserImageManager,
36 public ProfileDownloaderDelegate { 41 public ProfileDownloaderDelegate {
37 public: 42 public:
38 UserImageManagerImpl(); 43 UserImageManagerImpl();
39 44
40 // UserImageManager implemenation: 45 // UserImageManager:
41 virtual ~UserImageManagerImpl(); 46 virtual ~UserImageManagerImpl();
42 virtual void LoadUserImages(const UserList& users) OVERRIDE; 47 virtual void LoadUserImages(const UserList& users) OVERRIDE;
43 virtual void UserLoggedIn(const std::string& email, 48 virtual void UserLoggedIn(const std::string& user_id,
44 bool user_is_new, 49 bool user_is_new,
45 bool user_is_local) OVERRIDE; 50 bool user_is_local) OVERRIDE;
46 virtual void SaveUserDefaultImageIndex(const std::string& username, 51 virtual void SaveUserDefaultImageIndex(const std::string& user_id,
47 int image_index) OVERRIDE; 52 int default_image_index) OVERRIDE;
48 virtual void SaveUserImage(const std::string& username, 53 virtual void SaveUserImage(const std::string& user_id,
49 const UserImage& user_image) OVERRIDE; 54 const UserImage& user_image) OVERRIDE;
50 virtual void SaveUserImageFromFile(const std::string& username, 55 virtual void SaveUserImageFromFile(const std::string& user_id,
51 const base::FilePath& path) OVERRIDE; 56 const base::FilePath& path) OVERRIDE;
52 virtual void SaveUserImageFromProfileImage( 57 virtual void SaveUserImageFromProfileImage(
53 const std::string& username) OVERRIDE; 58 const std::string& user_id) OVERRIDE;
54 virtual void DeleteUserImage(const std::string& username) OVERRIDE; 59 virtual void DeleteUserImage(const std::string& user_id) OVERRIDE;
55 virtual void DownloadProfileImage(const std::string& reason) OVERRIDE; 60 virtual void DownloadProfileImage(const std::string& reason) OVERRIDE;
56 virtual const gfx::ImageSkia& DownloadedProfileImage() const OVERRIDE; 61 virtual const gfx::ImageSkia& DownloadedProfileImage() const OVERRIDE;
57 virtual UserImageSyncObserver* GetSyncObserver() const OVERRIDE; 62 virtual UserImageSyncObserver* GetSyncObserver() const OVERRIDE;
58 virtual void Shutdown() OVERRIDE; 63 virtual void Shutdown() OVERRIDE;
59 64
60 private: 65 private:
61 friend class UserImageManagerTest; 66 // Every image load or update is encapsulated by a Job. Whenever an image load
67 // or update is requested for a user, the Job currently running for that user
68 // (if any) is canceled. This ensures that at most one Job is running per user
69 // at any given time. There are two further guarantees:
70 //
71 // * Changes to User objects and local state are performed on the thread that
72 // |this| runs on.
73 // * File writes and deletions are performed via |background_task_runner_|.
74 //
75 // With the above, it is guaranteed that any changes made by a canceled Job
76 // cannot race against against changes made by the superseding Job.
77 class Job;
62 78
63 // Non-const for testing purposes. 79 // ProfileDownloaderDelegate:
64 static int user_image_migration_delay_sec;
65
66 // ProfileDownloaderDelegate implementation:
67 virtual bool NeedsProfilePicture() const OVERRIDE; 80 virtual bool NeedsProfilePicture() const OVERRIDE;
68 virtual int GetDesiredImageSideLength() const OVERRIDE; 81 virtual int GetDesiredImageSideLength() const OVERRIDE;
69 virtual Profile* GetBrowserProfile() OVERRIDE; 82 virtual Profile* GetBrowserProfile() OVERRIDE;
70 virtual std::string GetCachedPictureURL() const OVERRIDE; 83 virtual std::string GetCachedPictureURL() const OVERRIDE;
71 virtual void OnProfileDownloadSuccess(ProfileDownloader* downloader) OVERRIDE; 84 virtual void OnProfileDownloadSuccess(ProfileDownloader* downloader) OVERRIDE;
72 virtual void OnProfileDownloadFailure( 85 virtual void OnProfileDownloadFailure(
73 ProfileDownloader* downloader, 86 ProfileDownloader* downloader,
74 ProfileDownloaderDelegate::FailureReason reason) OVERRIDE; 87 ProfileDownloaderDelegate::FailureReason reason) OVERRIDE;
75 88
76 // Returns image filepath for the given user. 89 // Randomly chooses one of the default images for the specified user, sends a
77 base::FilePath GetImagePathForUser(const std::string& username); 90 // LOGIN_USER_IMAGE_CHANGED notification and updates local state.
91 void SetInitialUserImage(const std::string& user_id);
78 92
79 // Sets one of the default images for the specified user and saves this 93 // Initializes the |downloaded_profile_image_| for the currently logged-in
80 // setting in local state. 94 // user to a profile image that had been downloaded and saved before if such
81 // Does not send LOGIN_USER_IMAGE_CHANGED notification. 95 // a saved image is available and no updated image has been downloaded yet.
82 void SetInitialUserImage(const std::string& username); 96 void TryToInitDownloadedProfileImage();
83 97
84 // Sets image for user |username| and sends LOGIN_USER_IMAGE_CHANGED 98 // Returns true if the profile image needs to be downloaded. This is the case
85 // notification unless this is a new user and image is set for the first time. 99 // when a GAIA user is logged in and at least one of the following applies:
86 // If |image| is empty, sets a stub image for the user. 100 // * The profile image has explicitly been requested by a call to
87 void SetUserImage(const std::string& username, 101 // DownloadProfileImage() and has not been successfully downloaded since.
88 int image_index, 102 // * The user's user image is the profile image.
89 const GURL& image_url, 103 bool NeedProfileImage() const;
90 const UserImage& user_image);
91 104
92 // Saves image to file, updates local state preferences to given image index 105 // Downloads the profile data for the currently logged-in user. The user's
93 // and sends LOGIN_USER_IMAGE_CHANGED notification. 106 // full name and, if NeedProfileImage() is true, the profile image are
94 void SaveUserImageInternal(const std::string& username, 107 // downloaded. |reason| is an arbitrary string (used to report UMA histograms
95 int image_index, 108 // with download times).
96 const GURL& image_url, 109 void DownloadProfileData(const std::string& reason);
97 const UserImage& user_image);
98 110
99 // Saves image to file with specified path and sends LOGIN_USER_IMAGE_CHANGED 111 // Removes |user_id| from the dictionary |prefs_dict_root| in local state and
100 // notification. Runs on FILE thread. Posts task for saving image info to 112 // deletes the image file that the dictionary referenced for that user.
101 // Local State on UI thread. 113 void DeleteUserImageAndLocalStateEntry(const std::string& user_id,
102 void SaveImageToFile(const std::string& username, 114 const char* prefs_dict_root);
103 const UserImage& user_image,
104 const base::FilePath& image_path,
105 int image_index,
106 const GURL& image_url);
107 115
108 // Stores path to the image and its index in local state. Runs on UI thread. 116 // Called when a Job updates the copy of the user image held in memory by
109 // If |is_async| is true, it has been posted from the FILE thread after 117 // |user|. Allows |this| to update |downloaded_profile_image_| and send a
110 // saving the image. 118 // NOTIFICATION_LOGIN_USER_IMAGE_CHANGED notification.
111 void SaveImageToLocalState(const std::string& username, 119 void OnJobChangedUserImage(const User* user);
112 const std::string& image_path,
113 int image_index,
114 const GURL& image_url,
115 bool is_async);
116 120
117 // Saves |image| to the specified |image_path|. Runs on FILE thread. 121 // Called when a Job for |user_id| finishes. If a migration was required for
118 bool SaveBitmapToFile(const UserImage& user_image, 122 // the user, the migration is now complete and the old image file for that
119 const base::FilePath& image_path); 123 // user, if any, is deleted.
124 void OnJobDone(const std::string& user_id);
120 125
121 // Initializes |downloaded_profile_image_| with the picture of the logged-in 126 // Completes migration by removing |user_id| from the old prefs dictionary.
122 // user. 127 void UpdateLocalStateAfterMigration(const std::string& user_id);
123 void InitDownloadedProfileImage();
124
125 // Download user's profile data, including full name and picture, when
126 // |download_image| is true.
127 // |reason| is an arbitrary string (used to report UMA histograms with
128 // download times).
129 void DownloadProfileData(const std::string& reason, bool download_image);
130
131 // Scheduled call for downloading profile data.
132 void DownloadProfileDataScheduled();
133
134 // Delayed call to retry downloading profile data.
135 void DownloadProfileDataRetry(bool download_image);
136
137 // Migrates image info for the current user and deletes the old image, if any.
138 void MigrateUserImage();
139
140 // Deletes old user image and dictionary entry.
141 void DeleteOldUserImage(const std::string& username);
142 128
143 // Loader for JPEG user images. 129 // Loader for JPEG user images.
144 scoped_refptr<UserImageLoader> image_loader_; 130 scoped_refptr<UserImageLoader> image_loader_;
145 131
146 // Unsafe loader instance for all user images formats. 132 // Unsafe loader instance for all user images formats.
147 scoped_refptr<UserImageLoader> unsafe_image_loader_; 133 scoped_refptr<UserImageLoader> unsafe_image_loader_;
148 134
149 // Download user profile image on login to update it if it's changed. 135 // Whether the |profile_downloader_| is downloading the profile image for the
150 scoped_ptr<ProfileDownloader> profile_image_downloader_; 136 // currently logged-in user (and not just the full name). Only valid when a
137 // download is currently in progress.
138 bool downloading_profile_image_;
151 139
152 // Arbitrary string passed to the last |DownloadProfileImage| call. 140 // Download reason given to DownloadProfileImage(), used for UMA histograms.
141 // Only valid when a download is currently in progress and
142 // |downloading_profile_image_| is true.
153 std::string profile_image_download_reason_; 143 std::string profile_image_download_reason_;
154 144
155 // Time when the profile image download has started. 145 // Time when the profile image download started. Only valid when a download is
156 base::Time profile_image_load_start_time_; 146 // currently in progress and |downloading_profile_image_| is true.
147 base::TimeTicks profile_image_load_start_time_;
157 148
158 // True if the last user image required async save operation (which may not 149 // Downloader for the current user's profile data. NULL when no download is
159 // have been completed yet). This flag is used to avoid races when user image 150 // currently in progress.
160 // is first set with |SaveUserImage| and then with |SaveUserImagePath|. 151 scoped_ptr<ProfileDownloader> profile_downloader_;
161 bool last_image_set_async_;
162 152
163 // Result of the last successful profile image download, if any. 153 // The currently logged-in user's downloaded profile image, if successfully
154 // downloaded or initialized from a previously downloaded and saved image.
164 gfx::ImageSkia downloaded_profile_image_; 155 gfx::ImageSkia downloaded_profile_image_;
165 156
166 // Data URL for |downloaded_profile_image_|. 157 // Data URL corresponding to |downloaded_profile_image_|. Empty if no
158 // |downloaded_profile_image_| is currently available.
167 std::string downloaded_profile_image_data_url_; 159 std::string downloaded_profile_image_data_url_;
168 160
169 // Original URL of |downloaded_profile_image_|, from which it was downloaded. 161 // URL from which |downloaded_profile_image_| was downloaded. Empty if no
162 // |downloaded_profile_image_| is currently available.
170 GURL profile_image_url_; 163 GURL profile_image_url_;
171 164
172 // True when |profile_image_downloader_| is fetching profile picture (not 165 // Whether a download of the currently logged-in user's profile image has been
173 // just full name). 166 // explicitly requested by a call to DownloadProfileImage() and has not been
174 bool downloading_profile_image_; 167 // satisfied by a successful download yet.
168 bool profile_image_requested_;
175 169
176 // Timer triggering DownloadProfileDataScheduled for refreshing profile data. 170 // Timer used to start a profile data download shortly after login and to
177 base::RepeatingTimer<UserImageManagerImpl> profile_download_timer_; 171 // restart the download after network errors.
172 base::OneShotTimer<UserImageManagerImpl> profile_download_one_shot_timer_;
178 173
179 // Users that need image migration to JPEG. 174 // Timer used to periodically start a profile data, ensuring the profile data
175 // stays up to date.
176 base::RepeatingTimer<UserImageManagerImpl> profile_download_periodic_timer_;
177
178 // Users whose user images need to be migrated from the old dictionary pref to
179 // the new dictionary pref, converting any non-default images to JPEG format.
180 std::set<std::string> users_to_migrate_; 180 std::set<std::string> users_to_migrate_;
181 181
182 // If |true|, current user image should be migrated right after it is loaded. 182 // Sync observer for the currently logged-in user.
183 bool migrate_current_user_on_load_; 183 scoped_ptr<UserImageSyncObserver> user_image_sync_observer_;
184 184
185 // Sync observer attached to current user. 185 // Background task runner on which Jobs perform file I/O and the image
186 scoped_ptr<UserImageSyncObserver> user_image_sync_observer_; 186 // decoders run.
187 scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
188
189 // The currently running jobs.
190 std::map<std::string, linked_ptr<Job> > jobs_;
191
192 base::WeakPtrFactory<UserImageManagerImpl> weak_factory_;
187 193
188 DISALLOW_COPY_AND_ASSIGN(UserImageManagerImpl); 194 DISALLOW_COPY_AND_ASSIGN(UserImageManagerImpl);
189 }; 195 };
190 196
191 } // namespace chromeos 197 } // namespace chromeos
192 198
193 #endif // CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_ 199 #endif // CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698