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_MEDIA_GALLERIES_PERMISSION_CONTROLLER_H_
6#define CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_GALLERIES_PERMISSION_CONTROLLER_H_
7
8#include <map>
9#include <string>
10#include <vector>
11
12#include "base/callback.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/strings/string16.h"
15#include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
16#include "chrome/browser/media_galleries/media_galleries_preferences.h"
17#include "components/storage_monitor/removable_storage_observer.h"
18#include "ui/gfx/native_widget_types.h"
19#include "ui/shell_dialogs/select_file_dialog.h"
20
21namespace content {
22class WebContents;
23}
24
25namespace extensions {
26class Extension;
27}
28
29namespace ui {
30class MenuModel;
31}
32
33class MediaGalleriesDialogController;
34class MediaGalleryContextMenu;
35class Profile;
36
37// Newly added galleries are not added to preferences until the dialog commits,
38// so they do not have a pref id while the dialog is open; leading to
39// complicated code in the dialogs. To solve this complication, the controller
40// maps pref ids into a new space where it can also assign ids to new galleries.
41// The new number space is only valid for the lifetime of the controller. To
42// make it more clear where real pref ids are used and where the fake ids are
43// used, the GalleryDialogId type is used where fake ids are needed.
44typedef MediaGalleryPrefId GalleryDialogId;
45
46class MediaGalleriesPermissionController
47    : public MediaGalleriesDialogController,
48      public ui::SelectFileDialog::Listener,
49      public storage_monitor::RemovableStorageObserver,
50      public MediaGalleriesPreferences::GalleryChangeObserver {
51 public:
52  // The constructor creates a dialog controller which owns itself.
53  MediaGalleriesPermissionController(content::WebContents* web_contents,
54                                     const extensions::Extension& extension,
55                                     const base::Closure& on_finish);
56
57  // MediaGalleriesDialogController implementation.
58  virtual base::string16 GetHeader() const OVERRIDE;
59  virtual base::string16 GetSubtext() const OVERRIDE;
60  virtual bool IsAcceptAllowed() const OVERRIDE;
61  virtual bool ShouldShowFolderViewer(const Entry& entry) const OVERRIDE;
62  virtual std::vector<base::string16> GetSectionHeaders() const OVERRIDE;
63  virtual Entries GetSectionEntries(size_t index) const OVERRIDE;
64  // Auxiliary button for this dialog is the 'Add Folder' button.
65  virtual base::string16 GetAuxiliaryButtonText() const OVERRIDE;
66  virtual void DidClickAuxiliaryButton() OVERRIDE;
67  virtual void DidToggleEntry(GalleryDialogId gallery_id,
68                              bool selected) OVERRIDE;
69  virtual void DidClickOpenFolderViewer(GalleryDialogId gallery_id) OVERRIDE;
70  virtual void DidForgetEntry(GalleryDialogId gallery_id) OVERRIDE;
71  virtual base::string16 GetAcceptButtonText() const OVERRIDE;
72  virtual void DialogFinished(bool accepted) OVERRIDE;
73  virtual ui::MenuModel* GetContextMenu(GalleryDialogId gallery_id) OVERRIDE;
74  virtual content::WebContents* WebContents() OVERRIDE;
75
76 protected:
77  friend class MediaGalleriesPermissionControllerTest;
78
79  typedef base::Callback<MediaGalleriesDialog* (
80      MediaGalleriesDialogController*)> CreateDialogCallback;
81
82  // For use with tests.
83  MediaGalleriesPermissionController(
84      const extensions::Extension& extension,
85      MediaGalleriesPreferences* preferences,
86      const CreateDialogCallback& create_dialog_callback,
87      const base::Closure& on_finish);
88
89  virtual ~MediaGalleriesPermissionController();
90
91 private:
92  // This type keeps track of media galleries already known to the prefs system.
93  typedef std::map<GalleryDialogId, Entry> GalleryPermissionsMap;
94  typedef std::map<GalleryDialogId, bool /*permitted*/> ToggledGalleryMap;
95
96  class DialogIdMap {
97   public:
98    DialogIdMap();
99    ~DialogIdMap();
100    GalleryDialogId GetDialogId(MediaGalleryPrefId pref_id);
101    MediaGalleryPrefId GetPrefId(GalleryDialogId id) const;
102
103   private:
104    GalleryDialogId next_dialog_id_;
105    std::map<MediaGalleryPrefId, GalleryDialogId> back_map_;
106    std::vector<MediaGalleryPrefId> forward_mapping_;
107    DISALLOW_COPY_AND_ASSIGN(DialogIdMap);
108  };
109
110
111  // Bottom half of constructor -- called when |preferences_| is initialized.
112  void OnPreferencesInitialized();
113
114  // SelectFileDialog::Listener implementation:
115  virtual void FileSelected(const base::FilePath& path,
116                            int index,
117                            void* params) OVERRIDE;
118
119  // RemovableStorageObserver implementation.
120  // Used to keep dialog in sync with removable device status.
121  virtual void OnRemovableStorageAttached(
122      const storage_monitor::StorageInfo& info) OVERRIDE;
123  virtual void OnRemovableStorageDetached(
124      const storage_monitor::StorageInfo& info) OVERRIDE;
125
126  // MediaGalleriesPreferences::GalleryChangeObserver implementations.
127  // Used to keep the dialog in sync when the preferences change.
128  virtual void OnPermissionAdded(MediaGalleriesPreferences* pref,
129                                 const std::string& extension_id,
130                                 MediaGalleryPrefId pref_id) OVERRIDE;
131  virtual void OnPermissionRemoved(MediaGalleriesPreferences* pref,
132                                   const std::string& extension_id,
133                                   MediaGalleryPrefId pref_id) OVERRIDE;
134  virtual void OnGalleryAdded(MediaGalleriesPreferences* pref,
135                              MediaGalleryPrefId pref_id) OVERRIDE;
136  virtual void OnGalleryRemoved(MediaGalleriesPreferences* pref,
137                                MediaGalleryPrefId pref_id) OVERRIDE;
138  virtual void OnGalleryInfoUpdated(MediaGalleriesPreferences* pref,
139                                    MediaGalleryPrefId pref_id) OVERRIDE;
140
141  // Populates |known_galleries_| from |preferences_|. Subsequent calls merge
142  // into |known_galleries_| and do not change permissions for user toggled
143  // galleries.
144  void InitializePermissions();
145
146  // Saves state of |known_galleries_|, |new_galleries_| and
147  // |forgotten_galleries_| to model.
148  //
149  // NOTE: possible states for a gallery:
150  //   K   N   F   (K = Known, N = New, F = Forgotten)
151  // +---+---+---+
152  // | Y | N | N |
153  // +---+---+---+
154  // | N | Y | N |
155  // +---+---+---+
156  // | Y | N | Y |
157  // +---+---+---+
158  void SavePermissions();
159
160  // Updates the model and view when |preferences_| changes. Some of the
161  // possible changes includes a gallery getting blacklisted, or a new
162  // auto detected gallery becoming available.
163  void UpdateGalleriesOnPreferencesEvent();
164
165  // Updates the model and view when a device is attached or detached.
166  void UpdateGalleriesOnDeviceEvent(const std::string& device_id);
167
168  GalleryDialogId GetDialogId(MediaGalleryPrefId pref_id);
169  MediaGalleryPrefId GetPrefId(GalleryDialogId id) const;
170
171  Profile* GetProfile();
172
173  // The web contents from which the request originated.
174  content::WebContents* web_contents_;
175
176  // This is just a reference, but it's assumed that it won't become invalid
177  // while the dialog is showing.
178  const extensions::Extension* extension_;
179
180  // Mapping between pref ids and dialog ids.
181  DialogIdMap id_map_;
182
183  // This map excludes those galleries which have been blacklisted; it only
184  // counts active known galleries.
185  GalleryPermissionsMap known_galleries_;
186
187  // Galleries in |known_galleries_| that the user have toggled.
188  ToggledGalleryMap toggled_galleries_;
189
190  // The current set of permitted galleries (according to prefs).
191  MediaGalleryPrefIdSet pref_permitted_galleries_;
192
193  // Map of new galleries the user added, but have not saved. This list should
194  // never overlap with |known_galleries_|.
195  GalleryPermissionsMap new_galleries_;
196
197  // Galleries in |known_galleries_| that the user has forgotten.
198  std::set<GalleryDialogId> forgotten_galleries_;
199
200  // Callback to run when the dialog closes.
201  base::Closure on_finish_;
202
203  // The model that tracks galleries and extensions' permissions.
204  // This is the authoritative source for gallery information.
205  MediaGalleriesPreferences* preferences_;
206
207  // The view that's showing.
208  scoped_ptr<MediaGalleriesDialog> dialog_;
209
210  scoped_refptr<ui::SelectFileDialog> select_folder_dialog_;
211
212  scoped_ptr<MediaGalleryContextMenu> context_menu_;
213
214  // Creates the dialog. Only changed for unit tests.
215  CreateDialogCallback create_dialog_callback_;
216
217  DISALLOW_COPY_AND_ASSIGN(MediaGalleriesPermissionController);
218};
219
220#endif  // CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_GALLERIES_PERMISSION_CONTROLLER_H_
221