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