media_galleries_preferences.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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. 4 5#include "chrome/browser/media_galleries/media_galleries_preferences.h" 6 7#include "base/path_service.h" 8#include "base/prefs/pref_service.h" 9#include "base/stl_util.h" 10#include "base/string16.h" 11#include "base/strings/string_number_conversions.h" 12#include "base/utf_string_conversions.h" 13#include "base/values.h" 14#include "chrome/browser/browser_process.h" 15#include "chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.h" 16#include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.h" 17#include "chrome/browser/extensions/extension_prefs.h" 18#include "chrome/browser/extensions/extension_service.h" 19#include "chrome/browser/extensions/extension_system.h" 20#include "chrome/browser/media_galleries/fileapi/itunes_finder.h" 21#include "chrome/browser/media_galleries/media_file_system_registry.h" 22#include "chrome/browser/prefs/scoped_user_pref_update.h" 23#include "chrome/browser/profiles/profile.h" 24#include "chrome/browser/storage_monitor/media_storage_util.h" 25#include "chrome/browser/storage_monitor/storage_monitor.h" 26#include "chrome/common/chrome_paths.h" 27#include "chrome/common/extensions/extension.h" 28#include "chrome/common/extensions/permissions/api_permission.h" 29#include "chrome/common/extensions/permissions/media_galleries_permission.h" 30#include "chrome/common/pref_names.h" 31#include "components/user_prefs/pref_registry_syncable.h" 32 33namespace chrome { 34 35namespace { 36 37const char kMediaGalleriesDeviceIdKey[] = "deviceId"; 38const char kMediaGalleriesDisplayNameKey[] = "displayName"; 39const char kMediaGalleriesPathKey[] = "path"; 40const char kMediaGalleriesPrefIdKey[] = "prefId"; 41const char kMediaGalleriesTypeKey[] = "type"; 42const char kMediaGalleriesVolumeLabelKey[] = "volumeLabel"; 43const char kMediaGalleriesVendorNameKey[] = "vendorName"; 44const char kMediaGalleriesModelNameKey[] = "modelName"; 45const char kMediaGalleriesSizeKey[] = "totalSize"; 46const char kMediaGalleriesLastAttachTimeKey[] = "lastAttachTime"; 47const char kMediaGalleriesPrefsVersionKey[] = "preferencesVersion"; 48 49const char kMediaGalleriesTypeAutoDetectedValue[] = "autoDetected"; 50const char kMediaGalleriesTypeUserAddedValue[] = "userAdded"; 51const char kMediaGalleriesTypeBlackListedValue[] = "blackListed"; 52 53const char kITunesGalleryName[] = "iTunes"; 54 55bool GetPrefId(const DictionaryValue& dict, MediaGalleryPrefId* value) { 56 std::string string_id; 57 if (!dict.GetString(kMediaGalleriesPrefIdKey, &string_id) || 58 !base::StringToUint64(string_id, value)) { 59 return false; 60 } 61 62 return true; 63} 64 65bool GetType(const DictionaryValue& dict, MediaGalleryPrefInfo::Type* type) { 66 std::string string_type; 67 if (!dict.GetString(kMediaGalleriesTypeKey, &string_type)) 68 return false; 69 70 if (string_type == kMediaGalleriesTypeAutoDetectedValue) { 71 *type = MediaGalleryPrefInfo::kAutoDetected; 72 return true; 73 } 74 if (string_type == kMediaGalleriesTypeUserAddedValue) { 75 *type = MediaGalleryPrefInfo::kUserAdded; 76 return true; 77 } 78 if (string_type == kMediaGalleriesTypeBlackListedValue) { 79 *type = MediaGalleryPrefInfo::kBlackListed; 80 return true; 81 } 82 83 return false; 84} 85 86bool PopulateGalleryPrefInfoFromDictionary( 87 const DictionaryValue& dict, MediaGalleryPrefInfo* out_gallery_info) { 88 MediaGalleryPrefId pref_id; 89 string16 display_name; 90 std::string device_id; 91 base::FilePath::StringType path; 92 MediaGalleryPrefInfo::Type type = MediaGalleryPrefInfo::kAutoDetected; 93 string16 volume_label; 94 string16 vendor_name; 95 string16 model_name; 96 double total_size_in_bytes = 0.0; 97 double last_attach_time = 0.0; 98 bool volume_metadata_valid = false; 99 int prefs_version = 0; 100 101 if (!GetPrefId(dict, &pref_id) || 102 !dict.GetString(kMediaGalleriesDeviceIdKey, &device_id) || 103 !dict.GetString(kMediaGalleriesPathKey, &path) || 104 !GetType(dict, &type)) { 105 return false; 106 } 107 108 dict.GetString(kMediaGalleriesDisplayNameKey, &display_name); 109 dict.GetInteger(kMediaGalleriesPrefsVersionKey, &prefs_version); 110 111 if (dict.GetString(kMediaGalleriesVolumeLabelKey, &volume_label) && 112 dict.GetString(kMediaGalleriesVendorNameKey, &vendor_name) && 113 dict.GetString(kMediaGalleriesModelNameKey, &model_name) && 114 dict.GetDouble(kMediaGalleriesSizeKey, &total_size_in_bytes) && 115 dict.GetDouble(kMediaGalleriesLastAttachTimeKey, &last_attach_time)) { 116 volume_metadata_valid = true; 117 } 118 119 out_gallery_info->pref_id = pref_id; 120 out_gallery_info->display_name = display_name; 121 out_gallery_info->device_id = device_id; 122 out_gallery_info->path = base::FilePath(path); 123 out_gallery_info->type = type; 124 out_gallery_info->volume_label = volume_label; 125 out_gallery_info->vendor_name = vendor_name; 126 out_gallery_info->model_name = model_name; 127 out_gallery_info->total_size_in_bytes = total_size_in_bytes; 128 out_gallery_info->last_attach_time = 129 base::Time::FromInternalValue(last_attach_time); 130 out_gallery_info->volume_metadata_valid = volume_metadata_valid; 131 out_gallery_info->prefs_version = prefs_version; 132 133 return true; 134} 135 136DictionaryValue* CreateGalleryPrefInfoDictionary( 137 const MediaGalleryPrefInfo& gallery) { 138 DictionaryValue* dict = new DictionaryValue(); 139 dict->SetString(kMediaGalleriesPrefIdKey, 140 base::Uint64ToString(gallery.pref_id)); 141 if (!gallery.volume_metadata_valid) 142 dict->SetString(kMediaGalleriesDisplayNameKey, gallery.display_name); 143 dict->SetString(kMediaGalleriesDeviceIdKey, gallery.device_id); 144 dict->SetString(kMediaGalleriesPathKey, gallery.path.value()); 145 146 const char* type = NULL; 147 switch (gallery.type) { 148 case MediaGalleryPrefInfo::kAutoDetected: 149 type = kMediaGalleriesTypeAutoDetectedValue; 150 break; 151 case MediaGalleryPrefInfo::kUserAdded: 152 type = kMediaGalleriesTypeUserAddedValue; 153 break; 154 case MediaGalleryPrefInfo::kBlackListed: 155 type = kMediaGalleriesTypeBlackListedValue; 156 break; 157 default: 158 NOTREACHED(); 159 break; 160 } 161 dict->SetString(kMediaGalleriesTypeKey, type); 162 163 if (gallery.volume_metadata_valid) { 164 dict->SetString(kMediaGalleriesVolumeLabelKey, gallery.volume_label); 165 dict->SetString(kMediaGalleriesVendorNameKey, gallery.vendor_name); 166 dict->SetString(kMediaGalleriesModelNameKey, gallery.model_name); 167 dict->SetDouble(kMediaGalleriesSizeKey, gallery.total_size_in_bytes); 168 dict->SetDouble(kMediaGalleriesLastAttachTimeKey, 169 gallery.last_attach_time.ToInternalValue()); 170 } 171 172 // Version 0 of the prefs format was that the display_name was always 173 // used to show the user-visible name of the gallery. Version 1 means 174 // that there is an optional display_name, and when it is present, it 175 // overrides the name that would be built from the volume metadata, path, 176 // or whatever other data. So if we see a display_name with version 0, it 177 // means it may be overwritten simply by getting new volume metadata. 178 // A display_name with version 1 should not be overwritten. 179 dict->SetInteger(kMediaGalleriesPrefsVersionKey, gallery.prefs_version); 180 181 return dict; 182} 183 184bool HasAutoDetectedGalleryPermission(const extensions::Extension& extension) { 185 extensions::MediaGalleriesPermission::CheckParam param( 186 extensions::MediaGalleriesPermission::kAllAutoDetectedPermission); 187 return extension.CheckAPIPermissionWithParam( 188 extensions::APIPermission::kMediaGalleries, ¶m); 189} 190 191} // namespace 192 193MediaGalleryPrefInfo::MediaGalleryPrefInfo() 194 : pref_id(kInvalidMediaGalleryPrefId), 195 type(kInvalidType), 196 total_size_in_bytes(0), 197 volume_metadata_valid(false), 198 prefs_version(0) { 199} 200 201MediaGalleryPrefInfo::~MediaGalleryPrefInfo() {} 202 203base::FilePath MediaGalleryPrefInfo::AbsolutePath() const { 204 base::FilePath base_path = MediaStorageUtil::FindDevicePathById(device_id); 205 DCHECK(!path.IsAbsolute()); 206 return base_path.empty() ? base_path : base_path.Append(path); 207} 208 209MediaGalleriesPreferences::GalleryChangeObserver::~GalleryChangeObserver() {} 210 211MediaGalleriesPreferences::MediaGalleriesPreferences(Profile* profile) 212 : weak_factory_(this), 213 profile_(profile) { 214 AddDefaultGalleriesIfFreshProfile(); 215 216 // Look for optional default galleries every time. 217 itunes::ITunesFinder::FindITunesLibrary( 218 base::Bind(&MediaGalleriesPreferences::OnITunesDeviceID, 219 weak_factory_.GetWeakPtr())); 220 221 InitFromPrefs(false /*no notification*/); 222 223 StorageMonitor* monitor = StorageMonitor::GetInstance(); 224 if (monitor) 225 monitor->AddObserver(this); 226} 227 228MediaGalleriesPreferences::~MediaGalleriesPreferences() { 229 StorageMonitor* monitor = StorageMonitor::GetInstance(); 230 if (monitor) 231 monitor->RemoveObserver(this); 232} 233 234void MediaGalleriesPreferences::AddDefaultGalleriesIfFreshProfile() { 235 // Only add defaults the first time. 236 if (APIHasBeenUsed(profile_)) 237 return; 238 239 // Fresh profile case. 240 const int kDirectoryKeys[] = { 241 DIR_USER_MUSIC, 242 DIR_USER_PICTURES, 243 DIR_USER_VIDEOS, 244 }; 245 246 for (size_t i = 0; i < arraysize(kDirectoryKeys); ++i) { 247 base::FilePath path; 248 if (!PathService::Get(kDirectoryKeys[i], &path)) 249 continue; 250 251 base::FilePath relative_path; 252 StorageInfo info; 253 if (MediaStorageUtil::GetDeviceInfoFromPath(path, &info, &relative_path)) { 254 // TODO(gbillock): Add in the volume metadata here when available. 255 AddGalleryWithName(info.device_id, info.name, relative_path, 256 false /*user added*/); 257 } 258 } 259} 260 261void MediaGalleriesPreferences::OnITunesDeviceID(const std::string& device_id) { 262 DCHECK(!device_id.empty()); 263 AddGalleryWithName(device_id, ASCIIToUTF16(kITunesGalleryName), 264 base::FilePath(), false /*not user added*/); 265} 266 267void MediaGalleriesPreferences::InitFromPrefs(bool notify_observers) { 268 known_galleries_.clear(); 269 device_map_.clear(); 270 271 PrefService* prefs = profile_->GetPrefs(); 272 const ListValue* list = prefs->GetList( 273 prefs::kMediaGalleriesRememberedGalleries); 274 if (list) { 275 for (ListValue::const_iterator it = list->begin(); 276 it != list->end(); ++it) { 277 const DictionaryValue* dict = NULL; 278 if (!(*it)->GetAsDictionary(&dict)) 279 continue; 280 281 MediaGalleryPrefInfo gallery_info; 282 if (!PopulateGalleryPrefInfoFromDictionary(*dict, &gallery_info)) 283 continue; 284 285 known_galleries_[gallery_info.pref_id] = gallery_info; 286 device_map_[gallery_info.device_id].insert(gallery_info.pref_id); 287 } 288 } 289 if (notify_observers) 290 NotifyChangeObservers(std::string()); 291} 292 293void MediaGalleriesPreferences::NotifyChangeObservers( 294 const std::string& extension_id) { 295 FOR_EACH_OBSERVER(GalleryChangeObserver, 296 gallery_change_observers_, 297 OnGalleryChanged(this, extension_id)); 298} 299 300void MediaGalleriesPreferences::AddGalleryChangeObserver( 301 GalleryChangeObserver* observer) { 302 gallery_change_observers_.AddObserver(observer); 303} 304 305void MediaGalleriesPreferences::RemoveGalleryChangeObserver( 306 GalleryChangeObserver* observer) { 307 gallery_change_observers_.RemoveObserver(observer); 308} 309 310void MediaGalleriesPreferences::OnRemovableStorageAttached( 311 const StorageInfo& info) { 312 if (!MediaStorageUtil::IsMediaDevice(info.device_id)) 313 return; 314 315 if (info.name.empty()) { 316 AddGallery(info.device_id, base::FilePath(), 317 false /*not user added*/, 318 info.storage_label, 319 info.vendor_name, 320 info.model_name, 321 info.total_size_in_bytes, 322 base::Time::Now()); 323 } else { 324 // TODO(gbillock): get rid of this code path. 325 AddGalleryWithName(info.device_id, info.name, base::FilePath(), false); 326 } 327} 328 329bool MediaGalleriesPreferences::LookUpGalleryByPath( 330 const base::FilePath& path, 331 MediaGalleryPrefInfo* gallery_info) const { 332 StorageInfo info; 333 base::FilePath relative_path; 334 if (!MediaStorageUtil::GetDeviceInfoFromPath(path, &info, &relative_path)) { 335 if (gallery_info) 336 *gallery_info = MediaGalleryPrefInfo(); 337 return false; 338 } 339 340 relative_path = relative_path.NormalizePathSeparators(); 341 MediaGalleryPrefIdSet galleries_on_device = 342 LookUpGalleriesByDeviceId(info.device_id); 343 for (MediaGalleryPrefIdSet::const_iterator it = galleries_on_device.begin(); 344 it != galleries_on_device.end(); 345 ++it) { 346 const MediaGalleryPrefInfo& gallery = known_galleries_.find(*it)->second; 347 if (gallery.path != relative_path) 348 continue; 349 350 if (gallery_info) 351 *gallery_info = gallery; 352 return true; 353 } 354 355 // This method is called by controller::FilesSelected when the user 356 // adds a new gallery. Control reaches here when the selected gallery is 357 // on a volume we know about, but have no gallery already for. Returns 358 // hypothetical data to the caller about what the prefs will look like 359 // if the gallery is added. 360 // TODO(gbillock): split this out into another function so it doesn't 361 // conflate LookUp. 362 if (gallery_info) { 363 gallery_info->pref_id = kInvalidMediaGalleryPrefId; 364 gallery_info->display_name = info.name; 365 gallery_info->device_id = info.device_id; 366 gallery_info->path = relative_path; 367 gallery_info->type = MediaGalleryPrefInfo::kUserAdded; 368 // TODO(gbillock): Need to add volume metadata here from |info|. 369 } 370 return false; 371} 372 373MediaGalleryPrefIdSet MediaGalleriesPreferences::LookUpGalleriesByDeviceId( 374 const std::string& device_id) const { 375 DeviceIdPrefIdsMap::const_iterator found = device_map_.find(device_id); 376 if (found == device_map_.end()) 377 return MediaGalleryPrefIdSet(); 378 return found->second; 379} 380 381base::FilePath MediaGalleriesPreferences::LookUpGalleryPathForExtension( 382 MediaGalleryPrefId gallery_id, 383 const extensions::Extension* extension, 384 bool include_unpermitted_galleries) { 385 DCHECK(extension); 386 if (!include_unpermitted_galleries && 387 !ContainsKey(GalleriesForExtension(*extension), gallery_id)) 388 return base::FilePath(); 389 390 MediaGalleriesPrefInfoMap::const_iterator it = 391 known_galleries_.find(gallery_id); 392 if (it == known_galleries_.end()) 393 return base::FilePath(); 394 return MediaStorageUtil::FindDevicePathById(it->second.device_id); 395} 396 397MediaGalleryPrefId MediaGalleriesPreferences::AddGallery( 398 const std::string& device_id, 399 const base::FilePath& relative_path, bool user_added, 400 const string16& volume_label, const string16& vendor_name, 401 const string16& model_name, uint64 total_size_in_bytes, 402 base::Time last_attach_time) { 403 return AddGalleryInternal(device_id, string16(), relative_path, user_added, 404 volume_label, vendor_name, model_name, 405 total_size_in_bytes, last_attach_time, true, 1); 406} 407 408MediaGalleryPrefId MediaGalleriesPreferences::AddGalleryWithName( 409 const std::string& device_id, const string16& display_name, 410 const base::FilePath& relative_path, bool user_added) { 411 return AddGalleryInternal(device_id, display_name, relative_path, user_added, 412 string16(), string16(), string16(), 413 0, base::Time(), false, 1); 414} 415 416MediaGalleryPrefId MediaGalleriesPreferences::AddGalleryInternal( 417 const std::string& device_id, const string16& display_name, 418 const base::FilePath& relative_path, bool user_added, 419 const string16& volume_label, const string16& vendor_name, 420 const string16& model_name, uint64 total_size_in_bytes, 421 base::Time last_attach_time, 422 bool volume_metadata_valid, 423 int prefs_version) { 424 base::FilePath normalized_relative_path = 425 relative_path.NormalizePathSeparators(); 426 MediaGalleryPrefIdSet galleries_on_device = 427 LookUpGalleriesByDeviceId(device_id); 428 for (MediaGalleryPrefIdSet::const_iterator it = galleries_on_device.begin(); 429 it != galleries_on_device.end(); 430 ++it) { 431 const MediaGalleryPrefInfo& existing = known_galleries_.find(*it)->second; 432 if (existing.path != normalized_relative_path) 433 continue; 434 435 bool update_gallery_type = 436 user_added && (existing.type == MediaGalleryPrefInfo::kBlackListed); 437 bool update_gallery_name = existing.display_name != display_name; 438 bool update_gallery_metadata = volume_metadata_valid && 439 ((existing.volume_label != volume_label) || 440 (existing.vendor_name != vendor_name) || 441 (existing.model_name != model_name) || 442 (existing.total_size_in_bytes != total_size_in_bytes) || 443 (existing.last_attach_time != last_attach_time)); 444 445 if (!update_gallery_name && !update_gallery_type && 446 !update_gallery_metadata) 447 return *it; 448 449 PrefService* prefs = profile_->GetPrefs(); 450 scoped_ptr<ListPrefUpdate> update( 451 new ListPrefUpdate(prefs, prefs::kMediaGalleriesRememberedGalleries)); 452 ListValue* list = update->Get(); 453 454 for (ListValue::const_iterator list_iter = list->begin(); 455 list_iter != list->end(); 456 ++list_iter) { 457 DictionaryValue* dict; 458 MediaGalleryPrefId iter_id; 459 if ((*list_iter)->GetAsDictionary(&dict) && 460 GetPrefId(*dict, &iter_id) && 461 *it == iter_id) { 462 if (update_gallery_type) { 463 dict->SetString(kMediaGalleriesTypeKey, 464 kMediaGalleriesTypeAutoDetectedValue); 465 } 466 if (update_gallery_name) 467 dict->SetString(kMediaGalleriesDisplayNameKey, display_name); 468 if (update_gallery_metadata) { 469 dict->SetString(kMediaGalleriesVolumeLabelKey, volume_label); 470 dict->SetString(kMediaGalleriesVendorNameKey, vendor_name); 471 dict->SetString(kMediaGalleriesModelNameKey, model_name); 472 dict->SetDouble(kMediaGalleriesSizeKey, total_size_in_bytes); 473 dict->SetDouble(kMediaGalleriesLastAttachTimeKey, 474 last_attach_time.ToInternalValue()); 475 } 476 dict->SetInteger(kMediaGalleriesPrefsVersionKey, prefs_version); 477 break; 478 } 479 } 480 481 // Commits the prefs update. 482 update.reset(); 483 484 if (update_gallery_name || update_gallery_metadata || update_gallery_type) 485 InitFromPrefs(true /* notify observers */); 486 return *it; 487 } 488 489 PrefService* prefs = profile_->GetPrefs(); 490 491 MediaGalleryPrefInfo gallery_info; 492 gallery_info.pref_id = prefs->GetUint64(prefs::kMediaGalleriesUniqueId); 493 prefs->SetUint64(prefs::kMediaGalleriesUniqueId, gallery_info.pref_id + 1); 494 gallery_info.display_name = display_name; 495 gallery_info.device_id = device_id; 496 gallery_info.path = normalized_relative_path; 497 gallery_info.type = MediaGalleryPrefInfo::kAutoDetected; 498 if (user_added) 499 gallery_info.type = MediaGalleryPrefInfo::kUserAdded; 500 if (volume_metadata_valid) { 501 gallery_info.volume_label = volume_label; 502 gallery_info.vendor_name = vendor_name; 503 gallery_info.model_name = model_name; 504 gallery_info.total_size_in_bytes = total_size_in_bytes; 505 gallery_info.last_attach_time = last_attach_time; 506 } 507 gallery_info.volume_metadata_valid = volume_metadata_valid; 508 gallery_info.prefs_version = prefs_version; 509 510 { 511 ListPrefUpdate update(prefs, prefs::kMediaGalleriesRememberedGalleries); 512 ListValue* list = update.Get(); 513 list->Append(CreateGalleryPrefInfoDictionary(gallery_info)); 514 } 515 InitFromPrefs(true /* notify observers */); 516 517 return gallery_info.pref_id; 518} 519 520MediaGalleryPrefId MediaGalleriesPreferences::AddGalleryByPath( 521 const base::FilePath& path) { 522 MediaGalleryPrefInfo gallery_info; 523 if (LookUpGalleryByPath(path, &gallery_info) && 524 gallery_info.type != MediaGalleryPrefInfo::kBlackListed) { 525 return gallery_info.pref_id; 526 } 527 return AddGalleryInternal(gallery_info.device_id, 528 gallery_info.display_name, 529 gallery_info.path, 530 true /*user added*/, 531 gallery_info.volume_label, 532 gallery_info.vendor_name, 533 gallery_info.model_name, 534 gallery_info.total_size_in_bytes, 535 gallery_info.last_attach_time, 536 gallery_info.volume_metadata_valid, 537 gallery_info.prefs_version); 538} 539 540void MediaGalleriesPreferences::ForgetGalleryById(MediaGalleryPrefId pref_id) { 541 PrefService* prefs = profile_->GetPrefs(); 542 scoped_ptr<ListPrefUpdate> update(new ListPrefUpdate( 543 prefs, prefs::kMediaGalleriesRememberedGalleries)); 544 ListValue* list = update->Get(); 545 546 if (!ContainsKey(known_galleries_, pref_id)) 547 return; 548 549 for (ListValue::iterator iter = list->begin(); iter != list->end(); ++iter) { 550 DictionaryValue* dict; 551 MediaGalleryPrefId iter_id; 552 if ((*iter)->GetAsDictionary(&dict) && GetPrefId(*dict, &iter_id) && 553 pref_id == iter_id) { 554 extensions::MediaGalleriesPrivateAPI::RemoveMediaGalleryPermissions( 555 GetExtensionPrefs(), pref_id); 556 MediaGalleryPrefInfo::Type type; 557 if (GetType(*dict, &type) && 558 type == MediaGalleryPrefInfo::kAutoDetected) { 559 dict->SetString(kMediaGalleriesTypeKey, 560 kMediaGalleriesTypeBlackListedValue); 561 } else { 562 list->Erase(iter, NULL); 563 } 564 update.reset(NULL); // commits the update. 565 566 InitFromPrefs(true /* notify observers */); 567 return; 568 } 569 } 570} 571 572MediaGalleryPrefIdSet MediaGalleriesPreferences::GalleriesForExtension( 573 const extensions::Extension& extension) const { 574 MediaGalleryPrefIdSet result; 575 576 if (HasAutoDetectedGalleryPermission(extension)) { 577 for (MediaGalleriesPrefInfoMap::const_iterator it = 578 known_galleries_.begin(); it != known_galleries_.end(); ++it) { 579 if (it->second.type == MediaGalleryPrefInfo::kAutoDetected) 580 result.insert(it->second.pref_id); 581 } 582 } 583 584 std::vector<MediaGalleryPermission> stored_permissions = 585 extensions::MediaGalleriesPrivateAPI::GetMediaGalleryPermissions( 586 GetExtensionPrefs(), extension.id()); 587 for (std::vector<MediaGalleryPermission>::const_iterator it = 588 stored_permissions.begin(); it != stored_permissions.end(); ++it) { 589 if (!it->has_permission) { 590 result.erase(it->pref_id); 591 } else { 592 MediaGalleriesPrefInfoMap::const_iterator gallery = 593 known_galleries_.find(it->pref_id); 594 DCHECK(gallery != known_galleries_.end()); 595 if (gallery->second.type != MediaGalleryPrefInfo::kBlackListed) { 596 result.insert(it->pref_id); 597 } else { 598 NOTREACHED() << gallery->second.device_id; 599 } 600 } 601 } 602 return result; 603} 604 605void MediaGalleriesPreferences::SetGalleryPermissionForExtension( 606 const extensions::Extension& extension, 607 MediaGalleryPrefId pref_id, 608 bool has_permission) { 609 // The gallery may not exist anymore if the user opened a second config 610 // surface concurrently and removed it. Drop the permission update if so. 611 MediaGalleriesPrefInfoMap::const_iterator gallery_info = 612 known_galleries_.find(pref_id); 613 if (gallery_info == known_galleries_.end()) 614 return; 615 616#if defined(ENABLE_EXTENSIONS) 617 extensions::GalleryWatchStateTracker* state_tracker = 618 extensions::GalleryWatchStateTracker::GetForProfile(profile_); 619#endif 620 bool all_permission = HasAutoDetectedGalleryPermission(extension); 621 if (has_permission && all_permission) { 622 if (gallery_info->second.type == MediaGalleryPrefInfo::kAutoDetected) { 623 extensions::MediaGalleriesPrivateAPI::UnsetMediaGalleryPermission( 624 GetExtensionPrefs(), extension.id(), pref_id); 625 NotifyChangeObservers(extension.id()); 626#if defined(ENABLE_EXTENSIONS) 627 if (state_tracker) { 628 state_tracker->OnGalleryPermissionChanged(extension.id(), pref_id, 629 true); 630 } 631#endif 632 return; 633 } 634 } 635 636 if (!has_permission && !all_permission) { 637 extensions::MediaGalleriesPrivateAPI::UnsetMediaGalleryPermission( 638 GetExtensionPrefs(), extension.id(), pref_id); 639 } else { 640 extensions::MediaGalleriesPrivateAPI::SetMediaGalleryPermission( 641 GetExtensionPrefs(), extension.id(), pref_id, has_permission); 642 } 643 NotifyChangeObservers(extension.id()); 644#if defined(ENABLE_EXTENSIONS) 645 if (state_tracker) { 646 state_tracker->OnGalleryPermissionChanged(extension.id(), pref_id, 647 has_permission); 648 } 649#endif 650} 651 652void MediaGalleriesPreferences::Shutdown() { 653 weak_factory_.InvalidateWeakPtrs(); 654 profile_ = NULL; 655} 656 657// static 658bool MediaGalleriesPreferences::APIHasBeenUsed(Profile* profile) { 659 MediaGalleryPrefId current_id = 660 profile->GetPrefs()->GetUint64(prefs::kMediaGalleriesUniqueId); 661 return current_id != kInvalidMediaGalleryPrefId + 1; 662} 663 664// static 665void MediaGalleriesPreferences::RegisterUserPrefs( 666 user_prefs::PrefRegistrySyncable* registry) { 667 registry->RegisterListPref(prefs::kMediaGalleriesRememberedGalleries, 668 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 669 registry->RegisterUint64Pref( 670 prefs::kMediaGalleriesUniqueId, 671 kInvalidMediaGalleryPrefId + 1, 672 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 673} 674 675extensions::ExtensionPrefs* 676MediaGalleriesPreferences::GetExtensionPrefs() const { 677 ExtensionService* extension_service = 678 extensions::ExtensionSystem::Get(profile_)->extension_service(); 679 return extension_service->extension_prefs(); 680} 681 682} // namespace chrome 683