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.
5 #ifndef CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_GALLERIES_PREFERENCES_H_
6 #define CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_GALLERIES_PREFERENCES_H_
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"
25 class DictionaryValue;
28 namespace extensions {
33 namespace user_prefs {
34 class PrefRegistrySyncable;
37 typedef uint64 MediaGalleryPrefId;
38 const MediaGalleryPrefId kInvalidMediaGalleryPrefId = 0;
40 struct MediaGalleryPermission {
41 MediaGalleryPrefId pref_id;
45 struct MediaGalleryPrefInfo {
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.
53 MediaGalleryPrefInfo();
54 ~MediaGalleryPrefInfo();
56 // The absolute path of the gallery.
57 base::FilePath AbsolutePath() const;
59 // The ID that identifies this gallery in this Profile.
60 MediaGalleryPrefId pref_id;
62 // The user-visible name of this gallery.
63 string16 display_name;
65 // A string which uniquely and persistently identifies the device that the
67 std::string device_id;
69 // The root of the gallery, relative to the root of the device.
72 // The type of gallery.
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 string16 volume_label;
79 // Vendor name for the volume/device on which the gallery is located.
80 // Will be empty if unknown.
83 // Model name for the volume/device on which the gallery is located.
84 // Will be empty if unknown.
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;
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;
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
99 bool volume_metadata_valid;
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.
106 // Called by views to provide details for the gallery permission entries.
107 string16 GetGalleryDisplayName() const;
108 string16 GetGalleryTooltip() const;
109 string16 GetGalleryAdditionalDetails() const;
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;
116 typedef std::map<MediaGalleryPrefId, MediaGalleryPrefInfo>
117 MediaGalleriesPrefInfoMap;
118 typedef std::set<MediaGalleryPrefId> MediaGalleryPrefIdSet;
120 // A class to manage the media gallery preferences. There is one instance per
122 class MediaGalleriesPreferences : public BrowserContextKeyedService,
123 public RemovableStorageObserver {
125 class GalleryChangeObserver {
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) {}
133 virtual void OnPermissionRemoved(MediaGalleriesPreferences* pref,
134 const std::string& extension_id,
135 MediaGalleryPrefId pref_id) {}
137 virtual void OnGalleryAdded(MediaGalleriesPreferences* pref,
138 MediaGalleryPrefId pref_id) {}
140 virtual void OnGalleryRemoved(MediaGalleriesPreferences* pref,
141 MediaGalleryPrefId pref_id) {}
143 virtual void OnGalleryInfoUpdated(MediaGalleriesPreferences* pref,
144 MediaGalleryPrefId pref_id) {}
146 virtual ~GalleryChangeObserver();
149 explicit MediaGalleriesPreferences(Profile* profile);
150 virtual ~MediaGalleriesPreferences();
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);
162 // Return true if the storage monitor has already been initialized.
163 bool IsInitialized() const;
167 void AddGalleryChangeObserver(GalleryChangeObserver* observer);
168 void RemoveGalleryChangeObserver(GalleryChangeObserver* observer);
170 // RemovableStorageObserver implementation.
171 virtual void OnRemovableStorageAttached(const StorageInfo& info) OVERRIDE;
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;
181 MediaGalleryPrefIdSet LookUpGalleriesByDeviceId(
182 const std::string& device_id) const;
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);
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,
198 const string16& volume_label,
199 const string16& vendor_name,
200 const string16& model_name,
201 uint64 total_size_in_bytes,
202 base::Time last_attach_time);
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);
208 // Removes the gallery identified by |id| from the store.
209 void ForgetGalleryById(MediaGalleryPrefId id);
211 MediaGalleryPrefIdSet GalleriesForExtension(
212 const extensions::Extension& extension) const;
214 // Returns true if the permission changed. Returns false if there was
216 bool SetGalleryPermissionForExtension(const extensions::Extension& extension,
217 MediaGalleryPrefId pref_id,
218 bool has_permission);
220 const MediaGalleriesPrefInfoMap& known_galleries() const;
222 // BrowserContextKeyedService implementation:
223 virtual void Shutdown() OVERRIDE;
225 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
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);
233 friend class MediaGalleriesPreferencesTest;
234 friend class MediaGalleriesPermissionsTest;
236 typedef std::map<std::string /*device id*/, MediaGalleryPrefIdSet>
239 // These must be called on the UI thread.
240 void OnInitializationCallbackReturned();
241 void FinishInitialization();
243 // Populates the default galleries. Call only on fresh profiles.
244 void AddDefaultGalleries();
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);
257 void OnStorageMonitorInit(bool add_default_galleries);
259 // Handle an iPhoto, iTunes, or Picasa finder returning a device ID to us.
260 void OnFinderDeviceID(const std::string& device_id);
262 // Builds |known_galleries_| from the persistent store.
263 void InitFromPrefs();
265 MediaGalleryPrefId AddGalleryInternal(const std::string& device_id,
266 const string16& display_name,
267 const base::FilePath& relative_path,
269 const string16& volume_label,
270 const string16& vendor_name,
271 const string16& model_name,
272 uint64 total_size_in_bytes,
273 base::Time last_attach_time,
274 bool volume_metadata_valid,
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,
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);
289 // Return all media gallery permissions for the extension in the given
291 std::vector<MediaGalleryPermission> GetGalleryPermissionsFromPrefs(
292 const std::string& extension_id) const;
294 // Remove all the media gallery permissions in |prefs| for the gallery
295 // specified by |gallery_id|.
296 void RemoveGalleryPermissionsFromPrefs(MediaGalleryPrefId gallery_id);
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;
303 // Set the ExtensionPrefs object to be returned by GetExtensionPrefs().
304 void SetExtensionPrefsForTesting(extensions::ExtensionPrefs* extension_prefs);
307 std::vector<base::Closure> on_initialize_callbacks_;
308 int pre_initialization_callbacks_waiting_;
310 // The profile that owns |this|.
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_;
318 // An in-memory cache of known galleries.
319 MediaGalleriesPrefInfoMap known_galleries_;
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_;
325 ObserverList<GalleryChangeObserver> gallery_change_observers_;
327 base::WeakPtrFactory<MediaGalleriesPreferences> weak_factory_;
329 DISALLOW_COPY_AND_ASSIGN(MediaGalleriesPreferences);
332 #endif // CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_GALLERIES_PREFERENCES_H_