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