• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_GALLERIES_PREFERENCES_H_
6 #define CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_GALLERIES_PREFERENCES_H_
7 
8 #include <map>
9 #include <set>
10 #include <string>
11 
12 #include "base/basictypes.h"
13 #include "base/callback_forward.h"
14 #include "base/files/file_path.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/observer_list.h"
17 #include "base/strings/string16.h"
18 #include "base/time/time.h"
19 #include "components/keyed_service/core/keyed_service.h"
20 #include "components/storage_monitor/removable_storage_observer.h"
21 
22 class Profile;
23 
24 namespace base {
25 class DictionaryValue;
26 }
27 
28 namespace extensions {
29 class Extension;
30 class ExtensionPrefs;
31 }
32 
33 namespace user_prefs {
34 class PrefRegistrySyncable;
35 }
36 
37 typedef uint64 MediaGalleryPrefId;
38 const MediaGalleryPrefId kInvalidMediaGalleryPrefId = 0;
39 
40 struct MediaGalleryPermission {
41   MediaGalleryPrefId pref_id;
42   bool has_permission;
43 };
44 
45 struct MediaGalleryPrefInfo {
46   enum Type {
47     kUserAdded,     // Explicitly added by the user.
48     kAutoDetected,  // Auto added to the list of galleries.
49     kBlackListed,   // Auto added but then removed by the user.
50     kScanResult,    // Discovered by a disk scan.
51     kRemovedScan,   // Discovered by a disk scan but then removed by the user.
52     kInvalidType,
53   };
54 
55   MediaGalleryPrefInfo();
56   ~MediaGalleryPrefInfo();
57 
58   // The absolute path of the gallery.
59   base::FilePath AbsolutePath() const;
60 
61   // True if the gallery should not be displayed to the user
62   // i.e. kBlackListed || kRemovedScan.
63   bool IsBlackListedType() const;
64 
65   // The ID that identifies this gallery in this Profile.
66   MediaGalleryPrefId pref_id;
67 
68   // The user-visible name of this gallery.
69   base::string16 display_name;
70 
71   // A string which uniquely and persistently identifies the device that the
72   // gallery lives on.
73   std::string device_id;
74 
75   // The root of the gallery, relative to the root of the device.
76   base::FilePath path;
77 
78   // The type of gallery.
79   Type type;
80 
81   // The volume label of the volume/device on which the gallery
82   // resides. Empty if there is no such label or it is unknown.
83   base::string16 volume_label;
84 
85   // Vendor name for the volume/device on which the gallery is located.
86   // Will be empty if unknown.
87   base::string16 vendor_name;
88 
89   // Model name for the volume/device on which the gallery is located.
90   // Will be empty if unknown.
91   base::string16 model_name;
92 
93   // The capacity in bytes of the volume/device on which the gallery is
94   // located. Will be zero if unknown.
95   uint64 total_size_in_bytes;
96 
97   // If the gallery is on a removable device, the time that device was last
98   // attached. It is stored in preferences by the base::Time internal value,
99   // which is microseconds since the epoch.
100   base::Time last_attach_time;
101 
102   // Set to true if the volume metadata fields (volume_label, vendor_name,
103   // model_name, total_size_in_bytes) were set. False if these fields were
104   // never written.
105   bool volume_metadata_valid;
106 
107   // The following fields are populated with the audio, image, and video file
108   // counts from the last scan. For files where it is hard to determine the
109   // exact type, the file should be counted in all possible counts.
110   int audio_count;
111   int image_count;
112   int video_count;
113 
114   // 0 if the display_name is set externally and always used for display.
115   // 1 if the display_name is only set externally when it is overriding
116   // the name constructed from volume metadata.
117   int prefs_version;
118 
119   // Called by views to provide details for the gallery permission entries.
120   base::string16 GetGalleryDisplayName() const;
121   base::string16 GetGalleryTooltip() const;
122   base::string16 GetGalleryAdditionalDetails() const;
123 
124   // Returns true if the gallery is currently a removable device gallery which
125   // is now attached, or a fixed storage gallery.
126   bool IsGalleryAvailable() const;
127 };
128 
129 typedef std::map<MediaGalleryPrefId, MediaGalleryPrefInfo>
130     MediaGalleriesPrefInfoMap;
131 typedef std::set<MediaGalleryPrefId> MediaGalleryPrefIdSet;
132 
133 // A class to manage the media gallery preferences.  There is one instance per
134 // user profile.
135 class MediaGalleriesPreferences
136     : public KeyedService,
137       public storage_monitor::RemovableStorageObserver {
138  public:
139   class GalleryChangeObserver {
140    public:
141     // |extension_id| specifies the extension affected by this change.
142     // |pref_id| refers to the gallery.
OnPermissionAdded(MediaGalleriesPreferences * pref,const std::string & extension_id,MediaGalleryPrefId pref_id)143     virtual void OnPermissionAdded(MediaGalleriesPreferences* pref,
144                                    const std::string& extension_id,
145                                    MediaGalleryPrefId pref_id) {}
146 
OnPermissionRemoved(MediaGalleriesPreferences * pref,const std::string & extension_id,MediaGalleryPrefId pref_id)147     virtual void OnPermissionRemoved(MediaGalleriesPreferences* pref,
148                                      const std::string& extension_id,
149                                      MediaGalleryPrefId pref_id) {}
150 
OnGalleryAdded(MediaGalleriesPreferences * pref,MediaGalleryPrefId pref_id)151     virtual void OnGalleryAdded(MediaGalleriesPreferences* pref,
152                                 MediaGalleryPrefId pref_id) {}
153 
OnGalleryRemoved(MediaGalleriesPreferences * pref,MediaGalleryPrefId pref_id)154     virtual void OnGalleryRemoved(MediaGalleriesPreferences* pref,
155                                   MediaGalleryPrefId pref_id) {}
156 
OnGalleryInfoUpdated(MediaGalleriesPreferences * pref,MediaGalleryPrefId pref_id)157     virtual void OnGalleryInfoUpdated(MediaGalleriesPreferences* pref,
158                                       MediaGalleryPrefId pref_id) {}
159 
160    protected:
161     virtual ~GalleryChangeObserver();
162   };
163 
164   explicit MediaGalleriesPreferences(Profile* profile);
165   virtual ~MediaGalleriesPreferences();
166 
167   // Ensures that the preferences is initialized. The provided callback, if
168   // non-null, will be called when initialization is complete. If initialization
169   // has already completed, this callback will be invoked in the calling stack.
170   // Before the callback is run, other calls may not return the correct results.
171   // Should be invoked on the UI thread; callbacks will be run on the UI thread.
172   // This call also ensures that the StorageMonitor is initialized.
173   // Note for unit tests: This requires an active FILE thread and
174   // EnsureMediaDirectoriesExists instance to complete reliably.
175   void EnsureInitialized(base::Closure callback);
176 
177   // Return true if the storage monitor has already been initialized.
178   bool IsInitialized() const;
179 
180   Profile* profile();
181 
182   void AddGalleryChangeObserver(GalleryChangeObserver* observer);
183   void RemoveGalleryChangeObserver(GalleryChangeObserver* observer);
184 
185   // RemovableStorageObserver implementation.
186   virtual void OnRemovableStorageAttached(
187       const storage_monitor::StorageInfo& info) OVERRIDE;
188 
189   // Lookup a media gallery and fill in information about it and return true if
190   // it exists. Return false if it does not, filling in default information.
191   bool LookUpGalleryByPath(const base::FilePath& path,
192                            MediaGalleryPrefInfo* gallery) const;
193 
194   MediaGalleryPrefIdSet LookUpGalleriesByDeviceId(
195       const std::string& device_id) const;
196 
197   // Returns the absolute file path of the gallery specified by the
198   // |gallery_id|. Returns an empty file path if the |gallery_id| is invalid.
199   // Set |include_unpermitted_galleries| to true to get the file path of the
200   // gallery to which this |extension| has no access permission.
201   base::FilePath LookUpGalleryPathForExtension(
202       MediaGalleryPrefId gallery_id,
203       const extensions::Extension* extension,
204       bool include_unpermitted_galleries);
205 
206   // Teaches the registry about a new gallery. If the gallery is in a
207   // blacklisted state, it is unblacklisted. |type| should not be a blacklisted
208   // type. Returns the gallery's pref id.
209   MediaGalleryPrefId AddGallery(const std::string& device_id,
210                                 const base::FilePath& relative_path,
211                                 MediaGalleryPrefInfo::Type type,
212                                 const base::string16& volume_label,
213                                 const base::string16& vendor_name,
214                                 const base::string16& model_name,
215                                 uint64 total_size_in_bytes,
216                                 base::Time last_attach_time,
217                                 int audio_count,
218                                 int image_count,
219                                 int video_count);
220 
221   // Teach the registry about a gallery simply from the path. If the gallery is
222   // in a blacklisted state, it is unblacklisted. |type| should not be a
223   // blacklisted type. Returns the gallery's pref id.
224   MediaGalleryPrefId AddGalleryByPath(const base::FilePath& path,
225                                       MediaGalleryPrefInfo::Type type);
226 
227   // Logically removes the gallery identified by |id| from the store. For
228   // auto added or scan result galleries, this means moving them into a
229   // blacklisted state, otherwise they may come back when they are detected
230   // again.
231   void ForgetGalleryById(MediaGalleryPrefId id);
232 
233   // Remove the gallery identified by |id| from the store entirely. If it is an
234   // auto added or scan result gallery, it could get added again when the
235   // location is noticed again.
236   void EraseGalleryById(MediaGalleryPrefId id);
237 
238   // Returns true if some extension has permission for |id|, which may not be
239   // an auto detected type.
240   bool NonAutoGalleryHasPermission(MediaGalleryPrefId id) const;
241 
242   MediaGalleryPrefIdSet GalleriesForExtension(
243       const extensions::Extension& extension) const;
244 
245   // Returns true if the permission changed. Returns false if there was
246   // no change.
247   bool SetGalleryPermissionForExtension(const extensions::Extension& extension,
248                                         MediaGalleryPrefId pref_id,
249                                         bool has_permission);
250 
251   const MediaGalleriesPrefInfoMap& known_galleries() const;
252 
253   // These keep track of when we last successfully completed a media scan.
254   // This is used to provide cached results when appropriate.
255   base::Time GetLastScanCompletionTime() const;
256   void SetLastScanCompletionTime(const base::Time& time);
257 
258   // KeyedService implementation:
259   virtual void Shutdown() OVERRIDE;
260 
261   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
262 
263   // Returns true if the media gallery preferences system has ever been used
264   // for this profile. To be exact, it checks if a gallery has ever been added
265   // (including defaults).
266   static bool APIHasBeenUsed(Profile* profile);
267 
268  private:
269   friend class MediaGalleriesPreferencesTest;
270   friend class MediaGalleriesPermissionsTest;
271 
272   typedef std::map<std::string /*device id*/, MediaGalleryPrefIdSet>
273       DeviceIdPrefIdsMap;
274 
275   // These must be called on the UI thread.
276   void OnInitializationCallbackReturned();
277   void FinishInitialization();
278 
279   // Populates the default galleries. Call only on fresh profiles.
280   void AddDefaultGalleries();
281 
282   // This is a hack - Some devices (iTunes, Picasa) are singletons in that only
283   // one instance of that type is supported at a time. As such, the device id
284   // should just be "itunes:" or "picasa:" but that would mean finding the
285   // location of the database file multiple times, which may be an async
286   // operation. Storing the location of the backing database in the device
287   // id allows that look up to be avoided. However, the cost is that if the
288   // database moves, the device id in preferences has to be updated.  This
289   // method searches for a gallery of the type passed in and updates its
290   // device id.  It returns true if the device id is up to date.
291   bool UpdateDeviceIDForSingletonType(const std::string& device_id);
292 
293   void OnStorageMonitorInit(bool add_default_galleries);
294 
295   // Handle an iPhoto, iTunes, or Picasa finder returning a device ID to us.
296   void OnFinderDeviceID(const std::string& device_id);
297 
298   // Builds |known_galleries_| from the persistent store.
299   void InitFromPrefs();
300 
301   MediaGalleryPrefId AddGalleryInternal(const std::string& device_id,
302                                         const base::string16& display_name,
303                                         const base::FilePath& relative_path,
304                                         MediaGalleryPrefInfo::Type type,
305                                         const base::string16& volume_label,
306                                         const base::string16& vendor_name,
307                                         const base::string16& model_name,
308                                         uint64 total_size_in_bytes,
309                                         base::Time last_attach_time,
310                                         bool volume_metadata_valid,
311                                         int audio_count,
312                                         int image_count,
313                                         int video_count,
314                                         int prefs_version);
315 
316   void EraseOrBlacklistGalleryById(MediaGalleryPrefId id, bool erase);
317 
318   // Sets permission for the media galleries identified by |gallery_id| for the
319   // extension in the given |prefs|. Returns true only if anything changed.
320   bool SetGalleryPermissionInPrefs(const std::string& extension_id,
321                                    MediaGalleryPrefId gallery_id,
322                                    bool has_access);
323 
324   // Removes the entry for the media galleries permissions identified by
325   // |gallery_id| for the extension in the given |prefs|.
326   // Returns true only if anything changed.
327   bool UnsetGalleryPermissionInPrefs(const std::string& extension_id,
328                                      MediaGalleryPrefId gallery_id);
329 
330   // Return all media gallery permissions for the extension in the given
331   // |prefs|.
332   std::vector<MediaGalleryPermission> GetGalleryPermissionsFromPrefs(
333       const std::string& extension_id) const;
334 
335   // Remove all the media gallery permissions in |prefs| for the gallery
336   // specified by |gallery_id|.
337   void RemoveGalleryPermissionsFromPrefs(MediaGalleryPrefId gallery_id);
338 
339   // Get the ExtensionPrefs to use; this will be either the ExtensionPrefs
340   // object associated with |profile_|, or extension_prefs_for_testing_, if
341   // SetExtensionPrefsForTesting() has been called.
342   extensions::ExtensionPrefs* GetExtensionPrefs() const;
343 
344   // Set the ExtensionPrefs object to be returned by GetExtensionPrefs().
345   void SetExtensionPrefsForTesting(extensions::ExtensionPrefs* extension_prefs);
346 
347   bool initialized_;
348   std::vector<base::Closure> on_initialize_callbacks_;
349   int pre_initialization_callbacks_waiting_;
350 
351   // The profile that owns |this|.
352   Profile* profile_;
353 
354   // The ExtensionPrefs used in a testing environment, where KeyedServices
355   // aren't used. This will be NULL unless it is set with
356   // SetExtensionPrefsForTesting().
357   extensions::ExtensionPrefs* extension_prefs_for_testing_;
358 
359   // An in-memory cache of known galleries.
360   MediaGalleriesPrefInfoMap known_galleries_;
361 
362   // A mapping from device id to the set of gallery pref ids on that device.
363   // All pref ids in |device_map_| are also in |known_galleries_|.
364   DeviceIdPrefIdsMap device_map_;
365 
366   ObserverList<GalleryChangeObserver> gallery_change_observers_;
367 
368   base::WeakPtrFactory<MediaGalleriesPreferences> weak_factory_;
369 
370   DISALLOW_COPY_AND_ASSIGN(MediaGalleriesPreferences);
371 };
372 
373 #endif  // CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_GALLERIES_PREFERENCES_H_
374