1 // Copyright 2015 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_PROFILES_PROFILE_ATTRIBUTES_STORAGE_H_
6 #define CHROME_BROWSER_PROFILES_PROFILE_ATTRIBUTES_STORAGE_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 #include <string>
12 #include <unordered_map>
13 #include <vector>
14 
15 #include "base/callback_forward.h"
16 #include "base/files/file_path.h"
17 #include "base/gtest_prod_util.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/observer_list.h"
20 #include "base/strings/string16.h"
21 #include "build/build_config.h"
22 #include "chrome/browser/profiles/profile_attributes_entry.h"
23 #include "chrome/browser/profiles/profile_info_cache_observer.h"
24 
25 namespace base {
26 class SequencedTaskRunner;
27 }
28 
29 namespace gfx {
30 class Image;
31 }
32 
33 class AccountId;
34 class PrefService;
35 class ProfileAttributesEntry;
36 class ProfileAvatarDownloader;
37 
38 class ProfileAttributesStorage
39     : public base::SupportsWeakPtr<ProfileAttributesStorage> {
40  public:
41   using Observer = ProfileInfoCacheObserver;
42 
43   explicit ProfileAttributesStorage(PrefService* prefs);
44   ProfileAttributesStorage(const ProfileAttributesStorage&) = delete;
45   ProfileAttributesStorage& operator=(const ProfileAttributesStorage&) = delete;
46   virtual ~ProfileAttributesStorage();
47 
48   // If the |supervised_user_id| is non-empty, the profile will be marked to be
49   // omitted from the avatar-menu list on desktop versions. This is used while a
50   // supervised user is in the process of being registered with the server. Use
51   // ProfileAttributesEntry::SetIsOmitted() to clear the flag when the profile
52   // is ready to be shown in the menu.
53   virtual void AddProfile(const base::FilePath& profile_path,
54                           const base::string16& name,
55                           const std::string& gaia_id,
56                           const base::string16& user_name,
57                           bool is_consented_primary_account,
58                           size_t icon_index,
59                           const std::string& supervised_user_id,
60                           const AccountId& account_id) = 0;
61 
62   // Removes the profile matching given |account_id| from this storage.
63   // Calculates profile path and calls RemoveProfile() on it.
64   virtual void RemoveProfileByAccountId(const AccountId& account_id) = 0;
65 
66   // Removes the profile at |profile_path| from this storage. Does not delete or
67   // affect the actual profile's data.
68   virtual void RemoveProfile(const base::FilePath& profile_path) = 0;
69 
70   // Returns a vector containing one attributes entry per known profile. They
71   // are not sorted in any particular order.
72   std::vector<ProfileAttributesEntry*> GetAllProfilesAttributes();
73   std::vector<ProfileAttributesEntry*> GetAllProfilesAttributesSortedByName();
74 
75   // Populates |entry| with the data for the profile at |path| and returns true
76   // if the operation is successful and |entry| can be used. Returns false
77   // otherwise.
78   // |entry| should not be cached as it may not reflect subsequent changes to
79   // the profile's metadata.
80   virtual bool GetProfileAttributesWithPath(
81       const base::FilePath& path, ProfileAttributesEntry** entry) = 0;
82 
83   // Returns the count of known profiles.
84   virtual size_t GetNumberOfProfiles() const = 0;
85 
86   // Returns a unique name that can be assigned to a newly created profile.
87   base::string16 ChooseNameForNewProfile(size_t icon_index) const;
88 
89   // Determines whether |name| is one of the default assigned names.
90   // On Desktop, if |include_check_for_legacy_profile_name| is false,
91   // |IsDefaultProfileName()| would only return true if the |name| is in the
92   // form of |Person %n| which is the new default local profile name. If
93   // |include_check_for_legacy_profile_name| is true, we will also check if name
94   // is one of the legacy profile names (e.g. Saratoga, Default user, ..).
95   // For other platforms, so far |include_check_for_legacy_profile_name|
96   // is not used.
97   bool IsDefaultProfileName(const base::string16& name,
98                             bool include_check_for_legacy_profile_name) const;
99 
100 #if !defined(OS_ANDROID)
101   // Records statistics about a profile `entry` that is being deleted. If the
102   // profile has opened browser window(s) in the moment of deletion, this
103   // function must be called before these windows get closed.
104   void RecordDeletedProfileState(ProfileAttributesEntry* entry);
105 #endif
106 
107   // Records statistics about profiles as would be visible in the profile picker
108   // (if we would display it in this moment).
109   void RecordProfilesState();
110 
111   // Returns an avatar icon index that can be assigned to a newly created
112   // profile. Note that the icon may not be unique since there are a limited
113   // set of default icons.
114   size_t ChooseAvatarIconIndexForNewProfile() const;
115 
116   // Returns the decoded image at |image_path|. Used both by the GAIA profile
117   // image and the high res avatars.
118   const gfx::Image* LoadAvatarPictureFromPath(
119       const base::FilePath& profile_path,
120       const std::string& key,
121       const base::FilePath& image_path) const;
122 
123   // Checks whether the high res avatar at index |icon_index| exists, and if it
124   // does not, calls |DownloadHighResAvatar|.
125   void DownloadHighResAvatarIfNeeded(size_t icon_index,
126                                      const base::FilePath& profile_path);
127 
128   void AddObserver(Observer* observer);
129   void RemoveObserver(Observer* observer);
130 
GetDisableAvatarDownloadForTesting()131   bool GetDisableAvatarDownloadForTesting() {
132     return disable_avatar_download_for_testing_;
133   }
134 
set_disable_avatar_download_for_testing(bool disable_avatar_download_for_testing)135   void set_disable_avatar_download_for_testing(
136       bool disable_avatar_download_for_testing) {
137     disable_avatar_download_for_testing_ = disable_avatar_download_for_testing;
138   }
139 
140   // Notifies observers. The following methods are accessed by
141   // ProfileAttributesEntry.
142   void NotifyOnProfileAvatarChanged(const base::FilePath& profile_path) const;
143 
144   // Disables the periodic reporting of profile metrics, as this is causing
145   // tests to time out.
DisableProfileMetricsForTesting()146   virtual void DisableProfileMetricsForTesting() {}
147 
148  protected:
149   FRIEND_TEST_ALL_PREFIXES(ProfileInfoCacheTest, EntriesInAttributesStorage);
150   FRIEND_TEST_ALL_PREFIXES(ProfileAttributesStorageTest,
151                            DownloadHighResAvatarTest);
152   FRIEND_TEST_ALL_PREFIXES(ProfileAttributesStorageTest,
153                            NothingToDownloadHighResAvatarTest);
154 
155   // Starts downloading the high res avatar at index |icon_index| for profile
156   // with path |profile_path|.
157   void DownloadHighResAvatar(size_t icon_index,
158                              const base::FilePath& profile_path);
159 
160   // Saves the avatar |image| at |image_path|. This is used both for the GAIA
161   // profile pictures and the ProfileAvatarDownloader that is used to download
162   // the high res avatars.
163   void SaveAvatarImageAtPath(const base::FilePath& profile_path,
164                              gfx::Image image,
165                              const std::string& key,
166                              const base::FilePath& image_path,
167                              base::OnceClosure callback);
168 
169   PrefService* const prefs_;
170   mutable std::unordered_map<base::FilePath::StringType,
171                              std::unique_ptr<ProfileAttributesEntry>>
172       profile_attributes_entries_;
173 
174   mutable base::ObserverList<Observer>::Unchecked observer_list_;
175 
176   // A cache of gaia/high res avatar profile pictures. This cache is updated
177   // lazily so it needs to be mutable.
178   mutable std::unordered_map<std::string, gfx::Image> cached_avatar_images_;
179 
180   // Marks a profile picture as loading from disk. This prevents a picture from
181   // loading multiple times.
182   mutable std::unordered_map<std::string, bool> cached_avatar_images_loading_;
183 
184   // Hash table of profile pictures currently being downloaded from the remote
185   // location and the ProfileAvatarDownloader instances downloading them.
186   // This prevents a picture from being downloaded multiple times. The
187   // ProfileAvatarDownloader instances are deleted when the download completes
188   // or when the ProfileInfoCache is destroyed.
189   std::unordered_map<std::string, std::unique_ptr<ProfileAvatarDownloader>>
190       avatar_images_downloads_in_progress_;
191 
192   // Determines of the ProfileAvatarDownloader should be created and executed
193   // or not. Only set to true for tests.
194   bool disable_avatar_download_for_testing_ = false;
195 
196   // Task runner used for file operation on avatar images.
197   scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
198 
199  private:
200   // Called when the picture given by |key| has been loaded from disk and
201   // decoded into |image|.
202   void OnAvatarPictureLoaded(const base::FilePath& profile_path,
203                              const std::string& key,
204                              gfx::Image image) const;
205 
206   // Called when the picture given by |file_name| has been saved to disk. Used
207   // both for the GAIA profile picture and the high res avatar files.
208   void OnAvatarPictureSaved(const std::string& file_name,
209                             const base::FilePath& profile_path,
210                             base::OnceClosure callback,
211                             bool success) const;
212 
213   // Helper function that calls SaveAvatarImageAtPath without a callback.
214   void SaveAvatarImageAtPathNoCallback(const base::FilePath& profile_path,
215                                        gfx::Image image,
216                                        const std::string& key,
217                                        const base::FilePath& image_path);
218 
219   // Notifies observers.
220   void NotifyOnProfileHighResAvatarLoaded(
221       const base::FilePath& profile_path) const;
222 };
223 
224 #endif  // CHROME_BROWSER_PROFILES_PROFILE_ATTRIBUTES_STORAGE_H_
225