Home | History | Annotate | Download | only in media_galleries
      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.
    143     virtual void OnPermissionAdded(MediaGalleriesPreferences* pref,
    144                                    const std::string& extension_id,
    145                                    MediaGalleryPrefId pref_id) {}
    146 
    147     virtual void OnPermissionRemoved(MediaGalleriesPreferences* pref,
    148                                      const std::string& extension_id,
    149                                      MediaGalleryPrefId pref_id) {}
    150 
    151     virtual void OnGalleryAdded(MediaGalleriesPreferences* pref,
    152                                 MediaGalleryPrefId pref_id) {}
    153 
    154     virtual void OnGalleryRemoved(MediaGalleriesPreferences* pref,
    155                                   MediaGalleryPrefId pref_id) {}
    156 
    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