// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_MEDIA_GALLERIES_GALLERY_WATCH_MANAGER_H_ #define CHROME_BROWSER_MEDIA_GALLERIES_GALLERY_WATCH_MANAGER_H_ #include #include #include "base/callback_forward.h" #include "base/files/file_path.h" #include "base/files/file_path_watcher.h" #include "base/macros.h" #include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "chrome/browser/media_galleries/media_galleries_preferences.h" #include "components/keyed_service/core/keyed_service_shutdown_notifier.h" #include "components/storage_monitor/removable_storage_observer.h" class GalleryWatchManagerObserver; namespace content { class BrowserContext; } namespace extensions { class Extension; } // The GalleryWatchManager is owned by MediaFileSystemRegistry, which is global. // This class manages all watches on media galleries, regardless of profile. // It tracks outstanding watch requests and creates one FilePathWatcher per // watched directory. This class lives and is called on the UI thread. class GalleryWatchManager : public MediaGalleriesPreferences::GalleryChangeObserver, public storage_monitor::RemovableStorageObserver { public: // On success, |error| is empty. typedef base::Callback ResultCallback; static const char kInvalidGalleryIDError[]; static const char kNoPermissionError[]; static const char kCouldNotWatchGalleryError[]; GalleryWatchManager(); ~GalleryWatchManager() override; // Add or remove observer of change events - this is the only way to // get the result of the file watches. There can only be one observer per // browser context. void AddObserver(content::BrowserContext* browser_context, GalleryWatchManagerObserver* observer); void RemoveObserver(content::BrowserContext* browser_context); // Must be called when |browser_context| is shut down. void ShutdownBrowserContext(content::BrowserContext* browser_context); // Add a watch for |gallery_id|. void AddWatch(content::BrowserContext* browser_context, const extensions::Extension* extension, MediaGalleryPrefId gallery_id, const ResultCallback& callback); // Remove the watch for |gallery_id|. It is valid to call this method on // non-existent watches. void RemoveWatch(content::BrowserContext* browser_context, const std::string& extension_id, MediaGalleryPrefId gallery_id); // Remove all the watches for |extension_id|. void RemoveAllWatches(content::BrowserContext* browser_context, const std::string& extension_id); // Return the set of galleries being watched for |extension_id|. MediaGalleryPrefIdSet GetWatchSet(content::BrowserContext* browser_context, const std::string& extension_id); private: class FileWatchManager; // Used to track the gallery watches connected to a specific path. struct WatchOwner { WatchOwner(content::BrowserContext* browser_context, const std::string& extension_id, MediaGalleryPrefId gallery_id); content::BrowserContext* browser_context; const std::string extension_id; MediaGalleryPrefId gallery_id; // Needed to support storage in STL set, as well as usage as map key. bool operator<(const WatchOwner& other) const; }; struct NotificationInfo { NotificationInfo(); NotificationInfo(const NotificationInfo& other); ~NotificationInfo(); std::set owners; base::Time last_notify_time; bool delayed_notification_pending; }; typedef std::map WatchesMap; typedef std::map WatchedPaths; typedef std::map ObserverMap; typedef std::map> BrowserContextSubscriptionMap; // Ensure there is a subscription to shutdown notifications for // |browser_context|. void EnsureBrowserContextSubscription( content::BrowserContext* browser_context); // Stop the FilePathWatcher for |path|. Updates |watched_paths_| but not // |registered_watches_|. void DeactivateFileWatch(const WatchOwner& owner, const base::FilePath& path); // Called by FilePathWatcher on the UI thread to respond to a request to // watch the path. void OnFileWatchActivated(const WatchOwner& owner, const base::FilePath& path, const ResultCallback& callback, bool success); // Called by FilePathWatcher on the UI thread on a change event for |path|. void OnFilePathChanged(const base::FilePath& path, bool error); // MediaGalleriesPreferences::GalleryChangeObserver implementation. void OnPermissionRemoved(MediaGalleriesPreferences* pref, const std::string& extension_id, MediaGalleryPrefId pref_id) override; void OnGalleryRemoved(MediaGalleriesPreferences* pref, MediaGalleryPrefId pref_id) override; // storage_monitor::RemovableStorageObserver implementation. void OnRemovableStorageDetached( const storage_monitor::StorageInfo& info) override; // True if the we are already observing the storage monitor. bool storage_monitor_observed_; // MediaGalleriesPreferences we are currently observing. std::set observed_preferences_; // All registered watches, keyed by WatchOwner. WatchesMap watches_; // Reverse mapping of watched paths to the set of owning WatchOwners. WatchedPaths watched_paths_; // Things that want to hear about gallery changes. ObserverMap observers_; // Helper that does the watches on the FILE thread. scoped_ptr watch_manager_; // Removes watches when a browser context is shut down as watches contain raw // pointers. BrowserContextSubscriptionMap browser_context_subscription_map_; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(GalleryWatchManager); }; #endif // CHROME_BROWSER_MEDIA_GALLERIES_GALLERY_WATCH_MANAGER_H_