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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/login/user_image_manager_impl.h
diff --git a/chrome/browser/chromeos/login/user_image_manager_impl.h b/chrome/browser/chromeos/login/user_image_manager_impl.h
index cec6915c8a8290f067c77246394b80b997f338fc..fa88f06b2e4245fbbeae022ae593f7596f452905 100644
--- a/chrome/browser/chromeos/login/user_image_manager_impl.h
+++ b/chrome/browser/chromeos/login/user_image_manager_impl.h
@@ -5,14 +5,18 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_MANAGER_IMPL_H_
+#include <map>
#include <set>
#include <string>
#include "base/basictypes.h"
+#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
+#include "base/values.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_image_loader.h"
#include "chrome/browser/chromeos/login/user_image_manager.h"
@@ -24,6 +28,7 @@ class UserImage;
namespace base {
class FilePath;
+class SequencedTaskRunner;
}
namespace chromeos {
@@ -37,33 +42,41 @@ class UserImageManagerImpl : public UserImageManager,
public:
UserImageManagerImpl();
- // UserImageManager implemenation:
+ // UserImageManager:
virtual ~UserImageManagerImpl();
virtual void LoadUserImages(const UserList& users) OVERRIDE;
- virtual void UserLoggedIn(const std::string& email,
+ virtual void UserLoggedIn(const std::string& user_id,
bool user_is_new,
bool user_is_local) OVERRIDE;
- virtual void SaveUserDefaultImageIndex(const std::string& username,
- int image_index) OVERRIDE;
- virtual void SaveUserImage(const std::string& username,
+ virtual void SaveUserDefaultImageIndex(const std::string& user_id,
+ int default_image_index) OVERRIDE;
+ virtual void SaveUserImage(const std::string& user_id,
const UserImage& user_image) OVERRIDE;
- virtual void SaveUserImageFromFile(const std::string& username,
+ virtual void SaveUserImageFromFile(const std::string& user_id,
const base::FilePath& path) OVERRIDE;
virtual void SaveUserImageFromProfileImage(
- const std::string& username) OVERRIDE;
- virtual void DeleteUserImage(const std::string& username) OVERRIDE;
+ const std::string& user_id) OVERRIDE;
+ virtual void DeleteUserImage(const std::string& user_id) OVERRIDE;
virtual void DownloadProfileImage(const std::string& reason) OVERRIDE;
virtual const gfx::ImageSkia& DownloadedProfileImage() const OVERRIDE;
virtual UserImageSyncObserver* GetSyncObserver() const OVERRIDE;
virtual void Shutdown() OVERRIDE;
private:
- friend class UserImageManagerTest;
-
- // Non-const for testing purposes.
- static int user_image_migration_delay_sec;
-
- // ProfileDownloaderDelegate implementation:
+ // Every image load or update is encapsulated by a Job. Whenever an image load
+ // or update is requested for a user, the Job currently running for that user
+ // (if any) is canceled. This ensures that at most one Job is running per user
+ // at any given time. There are two further guarantees:
+ //
+ // * Changes to User objects and local state are performed on the thread that
+ // |this| runs on.
+ // * File writes and deletions are performed via |background_task_runner_|.
+ //
+ // With the above, it is guaranteed that any changes made by a canceled Job
+ // cannot race against against changes made by the superseding Job.
+ class Job;
+
+ // ProfileDownloaderDelegate:
virtual bool NeedsProfilePicture() const OVERRIDE;
virtual int GetDesiredImageSideLength() const OVERRIDE;
virtual Profile* GetBrowserProfile() OVERRIDE;
@@ -73,72 +86,45 @@ class UserImageManagerImpl : public UserImageManager,
ProfileDownloader* downloader,
ProfileDownloaderDelegate::FailureReason reason) OVERRIDE;
- // Returns image filepath for the given user.
- base::FilePath GetImagePathForUser(const std::string& username);
-
- // Sets one of the default images for the specified user and saves this
- // setting in local state.
- // Does not send LOGIN_USER_IMAGE_CHANGED notification.
- void SetInitialUserImage(const std::string& username);
-
- // Sets image for user |username| and sends LOGIN_USER_IMAGE_CHANGED
- // notification unless this is a new user and image is set for the first time.
- // If |image| is empty, sets a stub image for the user.
- void SetUserImage(const std::string& username,
- int image_index,
- const GURL& image_url,
- const UserImage& user_image);
-
- // Saves image to file, updates local state preferences to given image index
- // and sends LOGIN_USER_IMAGE_CHANGED notification.
- void SaveUserImageInternal(const std::string& username,
- int image_index,
- const GURL& image_url,
- const UserImage& user_image);
-
- // Saves image to file with specified path and sends LOGIN_USER_IMAGE_CHANGED
- // notification. Runs on FILE thread. Posts task for saving image info to
- // Local State on UI thread.
- void SaveImageToFile(const std::string& username,
- const UserImage& user_image,
- const base::FilePath& image_path,
- int image_index,
- const GURL& image_url);
-
- // Stores path to the image and its index in local state. Runs on UI thread.
- // If |is_async| is true, it has been posted from the FILE thread after
- // saving the image.
- void SaveImageToLocalState(const std::string& username,
- const std::string& image_path,
- int image_index,
- const GURL& image_url,
- bool is_async);
-
- // Saves |image| to the specified |image_path|. Runs on FILE thread.
- bool SaveBitmapToFile(const UserImage& user_image,
- const base::FilePath& image_path);
-
- // Initializes |downloaded_profile_image_| with the picture of the logged-in
- // user.
- void InitDownloadedProfileImage();
-
- // Download user's profile data, including full name and picture, when
- // |download_image| is true.
- // |reason| is an arbitrary string (used to report UMA histograms with
- // download times).
- void DownloadProfileData(const std::string& reason, bool download_image);
-
- // Scheduled call for downloading profile data.
- void DownloadProfileDataScheduled();
-
- // Delayed call to retry downloading profile data.
- void DownloadProfileDataRetry(bool download_image);
-
- // Migrates image info for the current user and deletes the old image, if any.
- void MigrateUserImage();
-
- // Deletes old user image and dictionary entry.
- void DeleteOldUserImage(const std::string& username);
+ // Randomly chooses one of the default images for the specified user, sends a
+ // LOGIN_USER_IMAGE_CHANGED notification and updates local state.
+ void SetInitialUserImage(const std::string& user_id);
+
+ // Initializes the |downloaded_profile_image_| for the currently logged-in
+ // user to a profile image that had been downloaded and saved before if such
+ // a saved image is available and no updated image has been downloaded yet.
+ void TryToInitDownloadedProfileImage();
+
+ // Returns true if the profile image needs to be downloaded. This is the case
+ // when a GAIA user is logged in and at least one of the following applies:
+ // * The profile image has explicitly been requested by a call to
+ // DownloadProfileImage() and has not been successfully downloaded since.
+ // * The user's user image is the profile image.
+ bool NeedProfileImage() const;
+
+ // Downloads the profile data for the currently logged-in user. The user's
+ // full name and, if NeedProfileImage() is true, the profile image are
+ // downloaded. |reason| is an arbitrary string (used to report UMA histograms
+ // with download times).
+ void DownloadProfileData(const std::string& reason);
+
+ // Removes |user_id| from the dictionary |prefs_dict_root| in local state and
+ // deletes the image file that the dictionary referenced for that user.
+ void DeleteUserImageAndLocalStateEntry(const std::string& user_id,
+ const char* prefs_dict_root);
+
+ // Called when a Job updates the copy of the user image held in memory by
+ // |user|. Allows |this| to update |downloaded_profile_image_| and send a
+ // NOTIFICATION_LOGIN_USER_IMAGE_CHANGED notification.
+ void OnJobChangedUserImage(const User* user);
+
+ // Called when a Job for |user_id| finishes. If a migration was required for
+ // the user, the migration is now complete and the old image file for that
+ // user, if any, is deleted.
+ void OnJobDone(const std::string& user_id);
+
+ // Completes migration by removing |user_id| from the old prefs dictionary.
+ void UpdateLocalStateAfterMigration(const std::string& user_id);
// Loader for JPEG user images.
scoped_refptr<UserImageLoader> image_loader_;
@@ -146,45 +132,65 @@ class UserImageManagerImpl : public UserImageManager,
// Unsafe loader instance for all user images formats.
scoped_refptr<UserImageLoader> unsafe_image_loader_;
- // Download user profile image on login to update it if it's changed.
- scoped_ptr<ProfileDownloader> profile_image_downloader_;
+ // Whether the |profile_downloader_| is downloading the profile image for the
+ // currently logged-in user (and not just the full name). Only valid when a
+ // download is currently in progress.
+ bool downloading_profile_image_;
- // Arbitrary string passed to the last |DownloadProfileImage| call.
+ // Download reason given to DownloadProfileImage(), used for UMA histograms.
+ // Only valid when a download is currently in progress and
+ // |downloading_profile_image_| is true.
std::string profile_image_download_reason_;
- // Time when the profile image download has started.
- base::Time profile_image_load_start_time_;
+ // Time when the profile image download started. Only valid when a download is
+ // currently in progress and |downloading_profile_image_| is true.
+ base::TimeTicks profile_image_load_start_time_;
- // True if the last user image required async save operation (which may not
- // have been completed yet). This flag is used to avoid races when user image
- // is first set with |SaveUserImage| and then with |SaveUserImagePath|.
- bool last_image_set_async_;
+ // Downloader for the current user's profile data. NULL when no download is
+ // currently in progress.
+ scoped_ptr<ProfileDownloader> profile_downloader_;
- // Result of the last successful profile image download, if any.
+ // The currently logged-in user's downloaded profile image, if successfully
+ // downloaded or initialized from a previously downloaded and saved image.
gfx::ImageSkia downloaded_profile_image_;
- // Data URL for |downloaded_profile_image_|.
+ // Data URL corresponding to |downloaded_profile_image_|. Empty if no
+ // |downloaded_profile_image_| is currently available.
std::string downloaded_profile_image_data_url_;
- // Original URL of |downloaded_profile_image_|, from which it was downloaded.
+ // URL from which |downloaded_profile_image_| was downloaded. Empty if no
+ // |downloaded_profile_image_| is currently available.
GURL profile_image_url_;
- // True when |profile_image_downloader_| is fetching profile picture (not
- // just full name).
- bool downloading_profile_image_;
+ // Whether a download of the currently logged-in user's profile image has been
+ // explicitly requested by a call to DownloadProfileImage() and has not been
+ // satisfied by a successful download yet.
+ bool profile_image_requested_;
- // Timer triggering DownloadProfileDataScheduled for refreshing profile data.
- base::RepeatingTimer<UserImageManagerImpl> profile_download_timer_;
+ // Timer used to start a profile data download shortly after login and to
+ // restart the download after network errors.
+ base::OneShotTimer<UserImageManagerImpl> profile_download_one_shot_timer_;
- // Users that need image migration to JPEG.
- std::set<std::string> users_to_migrate_;
+ // Timer used to periodically start a profile data, ensuring the profile data
+ // stays up to date.
+ base::RepeatingTimer<UserImageManagerImpl> profile_download_periodic_timer_;
- // If |true|, current user image should be migrated right after it is loaded.
- bool migrate_current_user_on_load_;
+ // Users whose user images need to be migrated from the old dictionary pref to
+ // the new dictionary pref, converting any non-default images to JPEG format.
+ std::set<std::string> users_to_migrate_;
- // Sync observer attached to current user.
+ // Sync observer for the currently logged-in user.
scoped_ptr<UserImageSyncObserver> user_image_sync_observer_;
+ // Background task runner on which Jobs perform file I/O and the image
+ // decoders run.
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
+
+ // The currently running jobs.
+ std::map<std::string, linked_ptr<Job> > jobs_;
+
+ base::WeakPtrFactory<UserImageManagerImpl> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(UserImageManagerImpl);
};

Powered by Google App Engine
This is Rietveld 408576698