1// Copyright 2014 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_GALLERY_WATCH_MANAGER_H_
6#define CHROME_BROWSER_MEDIA_GALLERIES_GALLERY_WATCH_MANAGER_H_
7
8#include <map>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/callback_forward.h"
13#include "base/files/file_path.h"
14#include "base/files/file_path_watcher.h"
15#include "base/memory/linked_ptr.h"
16#include "base/memory/scoped_ptr.h"
17#include "base/memory/weak_ptr.h"
18#include "base/time/time.h"
19#include "chrome/browser/media_galleries/media_galleries_preferences.h"
20#include "components/storage_monitor/removable_storage_observer.h"
21
22class GalleryWatchManagerObserver;
23
24namespace content {
25class BrowserContext;
26}
27
28namespace extensions {
29class Extension;
30}
31
32// The GalleryWatchManager is owned by MediaFileSystemRegistry, which is global.
33// This class manages all watches on media galleries, regardless of profile.
34// It tracks outstanding watch requests and creates one FilePathWatcher per
35// watched directory. This class lives and is called on the UI thread.
36class GalleryWatchManager
37    : public MediaGalleriesPreferences::GalleryChangeObserver,
38      public storage_monitor::RemovableStorageObserver {
39 public:
40  // On success, |error| is empty.
41  typedef base::Callback<void(const std::string& /* error */)> ResultCallback;
42
43  static const char kInvalidGalleryIDError[];
44  static const char kNoPermissionError[];
45  static const char kCouldNotWatchGalleryError[];
46
47  GalleryWatchManager();
48  virtual ~GalleryWatchManager();
49
50  // Add or remove observer of change events - this is the only way to
51  // get the result of the file watches. There can only be one observer per
52  // browser context.
53  void AddObserver(content::BrowserContext* browser_context,
54                   GalleryWatchManagerObserver* observer);
55  void RemoveObserver(content::BrowserContext* browser_context);
56
57  // Must be called when |browser_context| is shut down.
58  void ShutdownBrowserContext(content::BrowserContext* browser_context);
59
60  // Add a watch for |gallery_id|.
61  void AddWatch(content::BrowserContext* browser_context,
62                const extensions::Extension* extension,
63                MediaGalleryPrefId gallery_id,
64                const ResultCallback& callback);
65
66  // Remove the watch for |gallery_id|. It is valid to call this method on
67  // non-existent watches.
68  void RemoveWatch(content::BrowserContext* browser_context,
69                   const std::string& extension_id,
70                   MediaGalleryPrefId gallery_id);
71
72  // Remove all the watches for |extension_id|.
73  void RemoveAllWatches(content::BrowserContext* browser_context,
74                        const std::string& extension_id);
75
76  // Return the set of galleries being watched for |extension_id|.
77  MediaGalleryPrefIdSet GetWatchSet(content::BrowserContext* browser_context,
78                                    const std::string& extension_id);
79
80 private:
81  class FileWatchManager;
82
83  // Used to track the gallery watches connected to a specific path.
84  struct WatchOwner {
85    WatchOwner(content::BrowserContext* browser_context,
86               const std::string& extension_id,
87               MediaGalleryPrefId gallery_id);
88
89    content::BrowserContext* browser_context;
90    const std::string extension_id;
91    MediaGalleryPrefId gallery_id;
92
93    // Needed to support storage in STL set, as well as usage as map key.
94    bool operator<(const WatchOwner& other) const;
95  };
96
97  struct NotificationInfo {
98    NotificationInfo();
99    ~NotificationInfo();
100
101    std::set<WatchOwner> owners;
102    base::Time last_notify_time;
103    bool delayed_notification_pending;
104  };
105
106  typedef std::map<WatchOwner, base::FilePath> WatchesMap;
107  typedef std::map<base::FilePath, NotificationInfo> WatchedPaths;
108  typedef std::map<content::BrowserContext*, GalleryWatchManagerObserver*>
109      ObserverMap;
110
111  // Stop the FilePathWatcher for |path|. Updates |watched_paths_| but not
112  // |registered_watches_|.
113  void DeactivateFileWatch(const WatchOwner& owner, const base::FilePath& path);
114
115  // Called by FilePathWatcher on the UI thread to respond to a request to
116  // watch the path.
117  void OnFileWatchActivated(const WatchOwner& owner,
118                            const base::FilePath& path,
119                            const ResultCallback& callback,
120                            bool success);
121
122  // Called by FilePathWatcher on the UI thread on a change event for |path|.
123  void OnFilePathChanged(const base::FilePath& path, bool error);
124
125  // MediaGalleriesPreferences::GalleryChangeObserver implementation.
126  virtual void OnPermissionRemoved(MediaGalleriesPreferences* pref,
127                                   const std::string& extension_id,
128                                   MediaGalleryPrefId pref_id) OVERRIDE;
129  virtual void OnGalleryRemoved(MediaGalleriesPreferences* pref,
130                                MediaGalleryPrefId pref_id) OVERRIDE;
131
132  // storage_monitor::RemovableStorageObserver implementation.
133  virtual void OnRemovableStorageDetached(
134      const storage_monitor::StorageInfo& info) OVERRIDE;
135
136  // True if the we are already observing the storage monitor.
137  bool storage_monitor_observed_;
138
139  // MediaGalleriesPreferences we are currently observing.
140  std::set<MediaGalleriesPreferences*> observed_preferences_;
141
142  // All registered watches, keyed by WatchOwner.
143  WatchesMap watches_;
144
145  // Reverse mapping of watched paths to the set of owning WatchOwners.
146  WatchedPaths watched_paths_;
147
148  // Things that want to hear about gallery changes.
149  ObserverMap observers_;
150
151  // Helper that does the watches on the FILE thread.
152  scoped_ptr<FileWatchManager> watch_manager_;
153
154  base::WeakPtrFactory<GalleryWatchManager> weak_factory_;
155
156  DISALLOW_COPY_AND_ASSIGN(GalleryWatchManager);
157};
158
159#endif  // CHROME_BROWSER_MEDIA_GALLERIES_GALLERY_WATCH_MANAGER_H_
160