Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / media_galleries / media_galleries_dialog_controller.cc
blob8ad59e86e47a4fc8431729789c557964e5cc576b
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 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
7 #include "base/base_paths.h"
8 #include "base/path_service.h"
9 #include "base/stl_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
13 #include "chrome/browser/media_galleries/media_file_system_registry.h"
14 #include "chrome/browser/media_galleries/media_galleries_histograms.h"
15 #include "chrome/browser/media_galleries/media_gallery_context_menu.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/chrome_select_file_policy.h"
18 #include "components/storage_monitor/storage_info.h"
19 #include "components/storage_monitor/storage_monitor.h"
20 #include "content/public/browser/web_contents.h"
21 #include "extensions/browser/extension_prefs.h"
22 #include "extensions/common/extension.h"
23 #include "extensions/common/permissions/media_galleries_permission.h"
24 #include "extensions/common/permissions/permissions_data.h"
25 #include "grit/generated_resources.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/models/simple_menu_model.h"
28 #include "ui/base/text/bytes_formatting.h"
30 using extensions::APIPermission;
31 using extensions::Extension;
32 using storage_monitor::StorageInfo;
33 using storage_monitor::StorageMonitor;
35 namespace {
37 // Comparator for sorting GalleryPermissionsVector -- sorts
38 // allowed galleries low, and then sorts by absolute path.
39 bool GalleriesVectorComparator(
40 const MediaGalleriesDialogController::GalleryPermission& a,
41 const MediaGalleriesDialogController::GalleryPermission& b) {
42 if (a.allowed && !b.allowed)
43 return true;
44 if (!a.allowed && b.allowed)
45 return false;
47 return a.pref_info.AbsolutePath() < b.pref_info.AbsolutePath();
50 } // namespace
52 MediaGalleriesDialogController::MediaGalleriesDialogController(
53 content::WebContents* web_contents,
54 const Extension& extension,
55 const base::Closure& on_finish)
56 : web_contents_(web_contents),
57 extension_(&extension),
58 on_finish_(on_finish),
59 preferences_(
60 g_browser_process->media_file_system_registry()->GetPreferences(
61 GetProfile())),
62 create_dialog_callback_(base::Bind(&MediaGalleriesDialog::Create)) {
63 // Passing unretained pointer is safe, since the dialog controller
64 // is self-deleting, and so won't be deleted until it can be shown
65 // and then closed.
66 preferences_->EnsureInitialized(
67 base::Bind(&MediaGalleriesDialogController::OnPreferencesInitialized,
68 base::Unretained(this)));
70 // Unretained is safe because |this| owns |context_menu_|.
71 context_menu_.reset(
72 new MediaGalleryContextMenu(
73 base::Bind(&MediaGalleriesDialogController::DidForgetGallery,
74 base::Unretained(this))));
77 void MediaGalleriesDialogController::OnPreferencesInitialized() {
78 if (StorageMonitor::GetInstance())
79 StorageMonitor::GetInstance()->AddObserver(this);
81 // |preferences_| may be NULL in tests.
82 if (preferences_) {
83 preferences_->AddGalleryChangeObserver(this);
84 InitializePermissions();
87 dialog_.reset(create_dialog_callback_.Run(this));
90 MediaGalleriesDialogController::MediaGalleriesDialogController(
91 const extensions::Extension& extension,
92 MediaGalleriesPreferences* preferences,
93 const CreateDialogCallback& create_dialog_callback,
94 const base::Closure& on_finish)
95 : web_contents_(NULL),
96 extension_(&extension),
97 on_finish_(on_finish),
98 preferences_(preferences),
99 create_dialog_callback_(create_dialog_callback) {
100 OnPreferencesInitialized();
103 MediaGalleriesDialogController::~MediaGalleriesDialogController() {
104 if (StorageMonitor::GetInstance())
105 StorageMonitor::GetInstance()->RemoveObserver(this);
107 // |preferences_| may be NULL in tests.
108 if (preferences_)
109 preferences_->RemoveGalleryChangeObserver(this);
111 if (select_folder_dialog_.get())
112 select_folder_dialog_->ListenerDestroyed();
115 base::string16 MediaGalleriesDialogController::GetHeader() const {
116 return l10n_util::GetStringFUTF16(IDS_MEDIA_GALLERIES_DIALOG_HEADER,
117 base::UTF8ToUTF16(extension_->name()));
120 base::string16 MediaGalleriesDialogController::GetSubtext() const {
121 extensions::MediaGalleriesPermission::CheckParam copy_to_param(
122 extensions::MediaGalleriesPermission::kCopyToPermission);
123 extensions::MediaGalleriesPermission::CheckParam delete_param(
124 extensions::MediaGalleriesPermission::kDeletePermission);
125 bool has_copy_to_permission =
126 extensions::PermissionsData::CheckAPIPermissionWithParam(
127 extension_, APIPermission::kMediaGalleries, &copy_to_param);
128 bool has_delete_permission =
129 extensions::PermissionsData::CheckAPIPermissionWithParam(
130 extension_, APIPermission::kMediaGalleries, &delete_param);
132 int id;
133 if (has_copy_to_permission)
134 id = IDS_MEDIA_GALLERIES_DIALOG_SUBTEXT_READ_WRITE;
135 else if (has_delete_permission)
136 id = IDS_MEDIA_GALLERIES_DIALOG_SUBTEXT_READ_DELETE;
137 else
138 id = IDS_MEDIA_GALLERIES_DIALOG_SUBTEXT_READ_ONLY;
140 return l10n_util::GetStringFUTF16(id, base::UTF8ToUTF16(extension_->name()));
143 base::string16 MediaGalleriesDialogController::GetUnattachedLocationsHeader()
144 const {
145 return l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_UNATTACHED_LOCATIONS);
148 bool MediaGalleriesDialogController::IsAcceptAllowed() const {
149 if (!toggled_galleries_.empty() || !forgotten_galleries_.empty())
150 return true;
152 for (GalleryPermissionsMap::const_iterator iter = new_galleries_.begin();
153 iter != new_galleries_.end();
154 ++iter) {
155 if (iter->second.allowed)
156 return true;
159 return false;
162 // Note: sorts by display criterion: GalleriesVectorComparator.
163 MediaGalleriesDialogController::GalleryPermissionsVector
164 MediaGalleriesDialogController::FillPermissions(bool attached) const {
165 GalleryPermissionsVector result;
166 for (GalleryPermissionsMap::const_iterator iter = known_galleries_.begin();
167 iter != known_galleries_.end(); ++iter) {
168 if (!ContainsKey(forgotten_galleries_, iter->first) &&
169 attached == iter->second.pref_info.IsGalleryAvailable()) {
170 result.push_back(iter->second);
173 for (GalleryPermissionsMap::const_iterator iter = new_galleries_.begin();
174 iter != new_galleries_.end(); ++iter) {
175 if (attached == iter->second.pref_info.IsGalleryAvailable()) {
176 result.push_back(iter->second);
180 std::sort(result.begin(), result.end(), GalleriesVectorComparator);
181 return result;
184 MediaGalleriesDialogController::GalleryPermissionsVector
185 MediaGalleriesDialogController::AttachedPermissions() const {
186 return FillPermissions(true);
189 MediaGalleriesDialogController::GalleryPermissionsVector
190 MediaGalleriesDialogController::UnattachedPermissions() const {
191 return FillPermissions(false);
194 void MediaGalleriesDialogController::OnAddFolderClicked() {
195 base::FilePath default_path =
196 extensions::file_system_api::GetLastChooseEntryDirectory(
197 extensions::ExtensionPrefs::Get(GetProfile()), extension_->id());
198 if (default_path.empty())
199 PathService::Get(base::DIR_USER_DESKTOP, &default_path);
200 select_folder_dialog_ =
201 ui::SelectFileDialog::Create(this, new ChromeSelectFilePolicy(NULL));
202 select_folder_dialog_->SelectFile(
203 ui::SelectFileDialog::SELECT_FOLDER,
204 l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY_TITLE),
205 default_path,
206 NULL,
208 base::FilePath::StringType(),
209 web_contents_->GetTopLevelNativeWindow(),
210 NULL);
213 void MediaGalleriesDialogController::DidToggleGallery(
214 GalleryDialogId gallery_id, bool enabled) {
215 // Check known galleries.
216 GalleryPermissionsMap::iterator iter = known_galleries_.find(gallery_id);
217 if (iter != known_galleries_.end()) {
218 if (iter->second.allowed == enabled)
219 return;
221 iter->second.allowed = enabled;
222 if (ContainsKey(toggled_galleries_, gallery_id))
223 toggled_galleries_.erase(gallery_id);
224 else
225 toggled_galleries_.insert(gallery_id);
226 return;
229 iter = new_galleries_.find(gallery_id);
230 if (iter != new_galleries_.end())
231 iter->second.allowed = enabled;
233 // Don't sort -- the dialog is open, and we don't want to adjust any
234 // positions for future updates to the dialog contents until they are
235 // redrawn.
238 void MediaGalleriesDialogController::DidForgetGallery(
239 GalleryDialogId gallery_id) {
240 media_galleries::UsageCount(media_galleries::DIALOG_FORGET_GALLERY);
241 if (!new_galleries_.erase(gallery_id)) {
242 DCHECK(ContainsKey(known_galleries_, gallery_id));
243 forgotten_galleries_.insert(gallery_id);
245 dialog_->UpdateGalleries();
248 void MediaGalleriesDialogController::DialogFinished(bool accepted) {
249 // The dialog has finished, so there is no need to watch for more updates
250 // from |preferences_|.
251 // |preferences_| may be NULL in tests.
252 if (preferences_)
253 preferences_->RemoveGalleryChangeObserver(this);
255 if (accepted)
256 SavePermissions();
258 on_finish_.Run();
260 delete this;
263 content::WebContents* MediaGalleriesDialogController::web_contents() {
264 return web_contents_;
267 void MediaGalleriesDialogController::FileSelected(const base::FilePath& path,
268 int /*index*/,
269 void* /*params*/) {
270 extensions::file_system_api::SetLastChooseEntryDirectory(
271 extensions::ExtensionPrefs::Get(GetProfile()),
272 extension_->id(),
273 path);
275 // Try to find it in the prefs.
276 MediaGalleryPrefInfo gallery;
277 DCHECK(preferences_);
278 bool gallery_exists = preferences_->LookUpGalleryByPath(path, &gallery);
279 if (gallery_exists && !gallery.IsBlackListedType()) {
280 // The prefs are in sync with |known_galleries_|, so it should exist in
281 // |known_galleries_| as well. User selecting a known gallery effectively
282 // just sets the gallery to permitted.
283 GalleryDialogId gallery_id = GetDialogId(gallery.pref_id);
284 GalleryPermissionsMap::iterator iter = known_galleries_.find(gallery_id);
285 DCHECK(iter != known_galleries_.end());
286 iter->second.allowed = true;
287 forgotten_galleries_.erase(gallery_id);
288 dialog_->UpdateGalleries();
289 return;
292 // Try to find it in |new_galleries_| (user added same folder twice).
293 for (GalleryPermissionsMap::iterator iter = new_galleries_.begin();
294 iter != new_galleries_.end(); ++iter) {
295 if (iter->second.pref_info.path == gallery.path &&
296 iter->second.pref_info.device_id == gallery.device_id) {
297 iter->second.allowed = true;
298 dialog_->UpdateGalleries();
299 return;
303 // Lastly, if not found, add a new gallery to |new_galleries_|.
304 // Note that it will have prefId = kInvalidMediaGalleryPrefId.
305 GalleryDialogId gallery_id = GetDialogId(gallery.pref_id);
306 new_galleries_[gallery_id] = GalleryPermission(gallery_id, gallery, true);
307 dialog_->UpdateGalleries();
310 void MediaGalleriesDialogController::OnRemovableStorageAttached(
311 const StorageInfo& info) {
312 UpdateGalleriesOnDeviceEvent(info.device_id());
315 void MediaGalleriesDialogController::OnRemovableStorageDetached(
316 const StorageInfo& info) {
317 UpdateGalleriesOnDeviceEvent(info.device_id());
320 void MediaGalleriesDialogController::OnPermissionAdded(
321 MediaGalleriesPreferences* /* prefs */,
322 const std::string& extension_id,
323 MediaGalleryPrefId /* pref_id */) {
324 if (extension_id != extension_->id())
325 return;
326 UpdateGalleriesOnPreferencesEvent();
329 void MediaGalleriesDialogController::OnPermissionRemoved(
330 MediaGalleriesPreferences* /* prefs */,
331 const std::string& extension_id,
332 MediaGalleryPrefId /* pref_id */) {
333 if (extension_id != extension_->id())
334 return;
335 UpdateGalleriesOnPreferencesEvent();
338 void MediaGalleriesDialogController::OnGalleryAdded(
339 MediaGalleriesPreferences* /* prefs */,
340 MediaGalleryPrefId /* pref_id */) {
341 UpdateGalleriesOnPreferencesEvent();
344 void MediaGalleriesDialogController::OnGalleryRemoved(
345 MediaGalleriesPreferences* /* prefs */,
346 MediaGalleryPrefId /* pref_id */) {
347 UpdateGalleriesOnPreferencesEvent();
350 void MediaGalleriesDialogController::OnGalleryInfoUpdated(
351 MediaGalleriesPreferences* prefs,
352 MediaGalleryPrefId pref_id) {
353 DCHECK(preferences_);
354 const MediaGalleriesPrefInfoMap& pref_galleries =
355 preferences_->known_galleries();
356 MediaGalleriesPrefInfoMap::const_iterator pref_it =
357 pref_galleries.find(pref_id);
358 if (pref_it == pref_galleries.end())
359 return;
360 const MediaGalleryPrefInfo& gallery_info = pref_it->second;
361 UpdateGalleriesOnDeviceEvent(gallery_info.device_id);
364 void MediaGalleriesDialogController::InitializePermissions() {
365 known_galleries_.clear();
366 DCHECK(preferences_);
367 const MediaGalleriesPrefInfoMap& galleries = preferences_->known_galleries();
368 for (MediaGalleriesPrefInfoMap::const_iterator iter = galleries.begin();
369 iter != galleries.end();
370 ++iter) {
371 const MediaGalleryPrefInfo& gallery = iter->second;
372 if (gallery.IsBlackListedType())
373 continue;
375 GalleryDialogId gallery_id = GetDialogId(gallery.pref_id);
376 known_galleries_[gallery_id] =
377 GalleryPermission(gallery_id, gallery, false);
380 MediaGalleryPrefIdSet permitted =
381 preferences_->GalleriesForExtension(*extension_);
383 for (MediaGalleryPrefIdSet::iterator iter = permitted.begin();
384 iter != permitted.end(); ++iter) {
385 GalleryDialogId gallery_id = GetDialogId(*iter);
386 if (ContainsKey(toggled_galleries_, gallery_id))
387 continue;
388 DCHECK(ContainsKey(known_galleries_, gallery_id));
389 known_galleries_[gallery_id].allowed = true;
393 void MediaGalleriesDialogController::SavePermissions() {
394 DCHECK(preferences_);
395 media_galleries::UsageCount(media_galleries::SAVE_DIALOG);
396 for (GalleryPermissionsMap::const_iterator iter = known_galleries_.begin();
397 iter != known_galleries_.end(); ++iter) {
398 MediaGalleryPrefId pref_id = iter->second.pref_info.pref_id;
399 if (ContainsKey(forgotten_galleries_, iter->first)) {
400 preferences_->ForgetGalleryById(pref_id);
401 } else {
402 bool changed = preferences_->SetGalleryPermissionForExtension(
403 *extension_, pref_id, iter->second.allowed);
404 if (changed) {
405 if (iter->second.allowed) {
406 media_galleries::UsageCount(
407 media_galleries::DIALOG_PERMISSION_ADDED);
408 } else {
409 media_galleries::UsageCount(
410 media_galleries::DIALOG_PERMISSION_REMOVED);
416 for (GalleryPermissionsMap::const_iterator iter = new_galleries_.begin();
417 iter != new_galleries_.end(); ++iter) {
418 media_galleries::UsageCount(media_galleries::DIALOG_GALLERY_ADDED);
419 // If the user added a gallery then unchecked it, forget about it.
420 if (!iter->second.allowed)
421 continue;
423 const MediaGalleryPrefInfo& gallery = iter->second.pref_info;
424 MediaGalleryPrefId id = preferences_->AddGallery(
425 gallery.device_id, gallery.path, MediaGalleryPrefInfo::kUserAdded,
426 gallery.volume_label, gallery.vendor_name, gallery.model_name,
427 gallery.total_size_in_bytes, gallery.last_attach_time, 0, 0, 0);
428 preferences_->SetGalleryPermissionForExtension(*extension_, id, true);
432 void MediaGalleriesDialogController::UpdateGalleriesOnPreferencesEvent() {
433 // Merge in the permissions from |preferences_|. Afterwards,
434 // |known_galleries_| may contain galleries that no longer belong there,
435 // but the code below will put |known_galleries_| back in a consistent state.
436 InitializePermissions();
438 std::set<GalleryDialogId> new_galleries_to_remove;
439 // Look for duplicate entries in |new_galleries_| in case one was added
440 // in another dialog.
441 for (GalleryPermissionsMap::iterator it = known_galleries_.begin();
442 it != known_galleries_.end();
443 ++it) {
444 GalleryPermission& gallery = it->second;
445 for (GalleryPermissionsMap::iterator new_it = new_galleries_.begin();
446 new_it != new_galleries_.end();
447 ++new_it) {
448 if (new_it->second.pref_info.path == gallery.pref_info.path &&
449 new_it->second.pref_info.device_id == gallery.pref_info.device_id) {
450 // Found duplicate entry. Get the existing permission from it and then
451 // remove it.
452 gallery.allowed = new_it->second.allowed;
453 new_galleries_to_remove.insert(new_it->first);
454 break;
458 for (std::set<GalleryDialogId>::const_iterator it =
459 new_galleries_to_remove.begin();
460 it != new_galleries_to_remove.end();
461 ++it) {
462 new_galleries_.erase(*it);
465 dialog_->UpdateGalleries();
468 void MediaGalleriesDialogController::UpdateGalleriesOnDeviceEvent(
469 const std::string& device_id) {
470 dialog_->UpdateGalleries();
473 ui::MenuModel* MediaGalleriesDialogController::GetContextMenu(
474 GalleryDialogId gallery_id) {
475 context_menu_->set_pref_id(gallery_id);
476 return context_menu_.get();
479 GalleryDialogId MediaGalleriesDialogController::GetDialogId(
480 MediaGalleryPrefId pref_id) {
481 return id_map_.GetDialogId(pref_id);
484 Profile* MediaGalleriesDialogController::GetProfile() {
485 return Profile::FromBrowserContext(web_contents_->GetBrowserContext());
488 MediaGalleriesDialogController::DialogIdMap::DialogIdMap()
489 : next_dialog_id_(1) {
492 MediaGalleriesDialogController::DialogIdMap::~DialogIdMap() {
495 GalleryDialogId
496 MediaGalleriesDialogController::DialogIdMap::GetDialogId(
497 MediaGalleryPrefId pref_id) {
498 std::map<GalleryDialogId, MediaGalleryPrefId>::const_iterator it =
499 mapping_.find(pref_id);
500 if (it != mapping_.end())
501 return it->second;
503 GalleryDialogId result = next_dialog_id_++;
504 if (pref_id != kInvalidMediaGalleryPrefId)
505 mapping_[pref_id] = result;
506 return result;
509 // MediaGalleries dialog -------------------------------------------------------
511 MediaGalleriesDialog::~MediaGalleriesDialog() {}