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 22class Profile; 23 24namespace base { 25class DictionaryValue; 26} 27 28namespace extensions { 29class Extension; 30class ExtensionPrefs; 31} 32 33namespace user_prefs { 34class PrefRegistrySyncable; 35} 36 37typedef uint64 MediaGalleryPrefId; 38const MediaGalleryPrefId kInvalidMediaGalleryPrefId = 0; 39 40struct MediaGalleryPermission { 41 MediaGalleryPrefId pref_id; 42 bool has_permission; 43}; 44 45struct 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 129typedef std::map<MediaGalleryPrefId, MediaGalleryPrefInfo> 130 MediaGalleriesPrefInfoMap; 131typedef std::set<MediaGalleryPrefId> MediaGalleryPrefIdSet; 132 133// A class to manage the media gallery preferences. There is one instance per 134// user profile. 135class 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