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