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_preferences.h"
7 #include "base/base_paths_posix.h"
8 #include "base/callback.h"
9 #include "base/i18n/time_formatting.h"
10 #include "base/path_service.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/prefs/scoped_user_pref_update.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string16.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/values.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/media_galleries/fileapi/iapps_finder.h"
22 #include "chrome/browser/media_galleries/fileapi/picasa_finder.h"
23 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
24 #include "chrome/browser/media_galleries/media_file_system_registry.h"
25 #include "chrome/browser/media_galleries/media_galleries_histograms.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/common/chrome_paths.h"
28 #include "chrome/common/pref_names.h"
29 #include "components/pref_registry/pref_registry_syncable.h"
30 #include "components/storage_monitor/media_storage_util.h"
31 #include "components/storage_monitor/storage_monitor.h"
32 #include "content/public/browser/browser_thread.h"
33 #include "extensions/browser/extension_prefs.h"
34 #include "extensions/browser/extension_system.h"
35 #include "extensions/browser/pref_names.h"
36 #include "extensions/common/extension.h"
37 #include "extensions/common/extension_set.h"
38 #include "extensions/common/permissions/api_permission.h"
39 #include "extensions/common/permissions/media_galleries_permission.h"
40 #include "extensions/common/permissions/permissions_data.h"
41 #include "grit/generated_resources.h"
42 #include "ui/base/l10n/l10n_util.h"
44 using base::DictionaryValue
;
45 using base::ListValue
;
46 using extensions::ExtensionPrefs
;
47 using storage_monitor::MediaStorageUtil
;
48 using storage_monitor::StorageInfo
;
49 using storage_monitor::StorageMonitor
;
53 // Pref key for the list of media gallery permissions.
54 const char kMediaGalleriesPermissions
[] = "media_galleries_permissions";
55 // Pref key for Media Gallery ID.
56 const char kMediaGalleryIdKey
[] = "id";
57 // Pref key for Media Gallery Permission Value.
58 const char kMediaGalleryHasPermissionKey
[] = "has_permission";
60 const char kMediaGalleriesDeviceIdKey
[] = "deviceId";
61 const char kMediaGalleriesDisplayNameKey
[] = "displayName";
62 const char kMediaGalleriesPathKey
[] = "path";
63 const char kMediaGalleriesPrefIdKey
[] = "prefId";
64 const char kMediaGalleriesTypeKey
[] = "type";
65 const char kMediaGalleriesVolumeLabelKey
[] = "volumeLabel";
66 const char kMediaGalleriesVendorNameKey
[] = "vendorName";
67 const char kMediaGalleriesModelNameKey
[] = "modelName";
68 const char kMediaGalleriesSizeKey
[] = "totalSize";
69 const char kMediaGalleriesLastAttachTimeKey
[] = "lastAttachTime";
70 const char kMediaGalleriesScanAudioCountKey
[] = "audioCount";
71 const char kMediaGalleriesScanImageCountKey
[] = "imageCount";
72 const char kMediaGalleriesScanVideoCountKey
[] = "videoCount";
73 const char kMediaGalleriesPrefsVersionKey
[] = "preferencesVersion";
75 const char kMediaGalleriesTypeAutoDetectedValue
[] = "autoDetected";
76 const char kMediaGalleriesTypeBlackListedValue
[] = "blackListed";
77 const char kMediaGalleriesTypeRemovedScanValue
[] = "removedScan";
78 const char kMediaGalleriesTypeScanResultValue
[] = "scanResult";
79 const char kMediaGalleriesTypeUserAddedValue
[] = "userAdded";
81 const char kIPhotoGalleryName
[] = "iPhoto";
82 const char kITunesGalleryName
[] = "iTunes";
83 const char kPicasaGalleryName
[] = "Picasa";
85 const int kCurrentPrefsVersion
= 2;
87 int NumberExtensionsUsingMediaGalleries(Profile
* profile
) {
91 ExtensionService
* extension_service
=
92 extensions::ExtensionSystem::Get(profile
)->extension_service();
93 if (!extension_service
)
96 const extensions::ExtensionSet
* extensions
= extension_service
->extensions();
97 for (extensions::ExtensionSet::const_iterator i
= extensions
->begin();
98 i
!= extensions
->end(); ++i
) {
99 const extensions::PermissionsData
* permissions_data
=
100 (*i
)->permissions_data();
101 if (permissions_data
->HasAPIPermission(
102 extensions::APIPermission::kMediaGalleries
) ||
103 permissions_data
->HasAPIPermission(
104 extensions::APIPermission::kMediaGalleriesPrivate
)) {
111 bool GetPrefId(const base::DictionaryValue
& dict
, MediaGalleryPrefId
* value
) {
112 std::string string_id
;
113 if (!dict
.GetString(kMediaGalleriesPrefIdKey
, &string_id
) ||
114 !base::StringToUint64(string_id
, value
)) {
121 bool GetType(const base::DictionaryValue
& dict
,
122 MediaGalleryPrefInfo::Type
* type
) {
123 std::string string_type
;
124 if (!dict
.GetString(kMediaGalleriesTypeKey
, &string_type
))
127 if (string_type
== kMediaGalleriesTypeUserAddedValue
) {
128 *type
= MediaGalleryPrefInfo::kUserAdded
;
131 if (string_type
== kMediaGalleriesTypeAutoDetectedValue
) {
132 *type
= MediaGalleryPrefInfo::kAutoDetected
;
135 if (string_type
== kMediaGalleriesTypeBlackListedValue
) {
136 *type
= MediaGalleryPrefInfo::kBlackListed
;
139 if (string_type
== kMediaGalleriesTypeScanResultValue
) {
140 *type
= MediaGalleryPrefInfo::kScanResult
;
143 if (string_type
== kMediaGalleriesTypeRemovedScanValue
) {
144 *type
= MediaGalleryPrefInfo::kRemovedScan
;
151 const char* TypeToStringValue(MediaGalleryPrefInfo::Type type
) {
152 const char* result
= NULL
;
154 case MediaGalleryPrefInfo::kUserAdded
:
155 result
= kMediaGalleriesTypeUserAddedValue
;
157 case MediaGalleryPrefInfo::kAutoDetected
:
158 result
= kMediaGalleriesTypeAutoDetectedValue
;
160 case MediaGalleryPrefInfo::kBlackListed
:
161 result
= kMediaGalleriesTypeBlackListedValue
;
163 case MediaGalleryPrefInfo::kScanResult
:
164 result
= kMediaGalleriesTypeScanResultValue
;
166 case MediaGalleryPrefInfo::kRemovedScan
:
167 result
= kMediaGalleriesTypeRemovedScanValue
;
176 bool PopulateGalleryPrefInfoFromDictionary(
177 const base::DictionaryValue
& dict
, MediaGalleryPrefInfo
* out_gallery_info
) {
178 MediaGalleryPrefId pref_id
;
179 base::string16 display_name
;
180 std::string device_id
;
181 base::FilePath::StringType path
;
182 MediaGalleryPrefInfo::Type type
= MediaGalleryPrefInfo::kInvalidType
;
183 base::string16 volume_label
;
184 base::string16 vendor_name
;
185 base::string16 model_name
;
186 double total_size_in_bytes
= 0.0;
187 double last_attach_time
= 0.0;
188 bool volume_metadata_valid
= false;
192 int prefs_version
= 0;
194 if (!GetPrefId(dict
, &pref_id
) ||
195 !dict
.GetString(kMediaGalleriesDeviceIdKey
, &device_id
) ||
196 !dict
.GetString(kMediaGalleriesPathKey
, &path
) ||
197 !GetType(dict
, &type
)) {
201 dict
.GetString(kMediaGalleriesDisplayNameKey
, &display_name
);
202 dict
.GetInteger(kMediaGalleriesPrefsVersionKey
, &prefs_version
);
204 if (dict
.GetString(kMediaGalleriesVolumeLabelKey
, &volume_label
) &&
205 dict
.GetString(kMediaGalleriesVendorNameKey
, &vendor_name
) &&
206 dict
.GetString(kMediaGalleriesModelNameKey
, &model_name
) &&
207 dict
.GetDouble(kMediaGalleriesSizeKey
, &total_size_in_bytes
) &&
208 dict
.GetDouble(kMediaGalleriesLastAttachTimeKey
, &last_attach_time
)) {
209 volume_metadata_valid
= true;
212 if (dict
.GetInteger(kMediaGalleriesScanAudioCountKey
, &audio_count
) &&
213 dict
.GetInteger(kMediaGalleriesScanImageCountKey
, &image_count
) &&
214 dict
.GetInteger(kMediaGalleriesScanVideoCountKey
, &video_count
)) {
215 out_gallery_info
->audio_count
= audio_count
;
216 out_gallery_info
->image_count
= image_count
;
217 out_gallery_info
->video_count
= video_count
;
219 out_gallery_info
->audio_count
= 0;
220 out_gallery_info
->image_count
= 0;
221 out_gallery_info
->video_count
= 0;
224 out_gallery_info
->pref_id
= pref_id
;
225 out_gallery_info
->display_name
= display_name
;
226 out_gallery_info
->device_id
= device_id
;
227 out_gallery_info
->path
= base::FilePath(path
);
228 out_gallery_info
->type
= type
;
229 out_gallery_info
->volume_label
= volume_label
;
230 out_gallery_info
->vendor_name
= vendor_name
;
231 out_gallery_info
->model_name
= model_name
;
232 out_gallery_info
->total_size_in_bytes
= total_size_in_bytes
;
233 out_gallery_info
->last_attach_time
=
234 base::Time::FromInternalValue(last_attach_time
);
235 out_gallery_info
->volume_metadata_valid
= volume_metadata_valid
;
236 out_gallery_info
->prefs_version
= prefs_version
;
241 base::DictionaryValue
* CreateGalleryPrefInfoDictionary(
242 const MediaGalleryPrefInfo
& gallery
) {
243 base::DictionaryValue
* dict
= new base::DictionaryValue();
244 dict
->SetString(kMediaGalleriesPrefIdKey
,
245 base::Uint64ToString(gallery
.pref_id
));
246 dict
->SetString(kMediaGalleriesDeviceIdKey
, gallery
.device_id
);
247 dict
->SetString(kMediaGalleriesPathKey
, gallery
.path
.value());
248 dict
->SetString(kMediaGalleriesTypeKey
, TypeToStringValue(gallery
.type
));
250 if (gallery
.volume_metadata_valid
) {
251 dict
->SetString(kMediaGalleriesVolumeLabelKey
, gallery
.volume_label
);
252 dict
->SetString(kMediaGalleriesVendorNameKey
, gallery
.vendor_name
);
253 dict
->SetString(kMediaGalleriesModelNameKey
, gallery
.model_name
);
254 dict
->SetDouble(kMediaGalleriesSizeKey
, gallery
.total_size_in_bytes
);
255 dict
->SetDouble(kMediaGalleriesLastAttachTimeKey
,
256 gallery
.last_attach_time
.ToInternalValue());
258 dict
->SetString(kMediaGalleriesDisplayNameKey
, gallery
.display_name
);
261 if (gallery
.audio_count
|| gallery
.image_count
|| gallery
.video_count
) {
262 dict
->SetInteger(kMediaGalleriesScanAudioCountKey
, gallery
.audio_count
);
263 dict
->SetInteger(kMediaGalleriesScanImageCountKey
, gallery
.image_count
);
264 dict
->SetInteger(kMediaGalleriesScanVideoCountKey
, gallery
.video_count
);
267 // Version 0 of the prefs format was that the display_name was always
268 // used to show the user-visible name of the gallery. Version 1 means
269 // that there is an optional display_name, and when it is present, it
270 // overrides the name that would be built from the volume metadata, path,
271 // or whatever other data. So if we see a display_name with version 0, it
272 // means it may be overwritten simply by getting new volume metadata.
273 // A display_name with version 1 should not be overwritten.
274 dict
->SetInteger(kMediaGalleriesPrefsVersionKey
, gallery
.prefs_version
);
279 bool HasAutoDetectedGalleryPermission(const extensions::Extension
& extension
) {
280 extensions::MediaGalleriesPermission::CheckParam
param(
281 extensions::MediaGalleriesPermission::kAllAutoDetectedPermission
);
282 return extension
.permissions_data()->CheckAPIPermissionWithParam(
283 extensions::APIPermission::kMediaGalleries
, ¶m
);
286 // Retrieves the MediaGalleryPermission from the given dictionary; DCHECKs on
288 bool GetMediaGalleryPermissionFromDictionary(
289 const base::DictionaryValue
* dict
,
290 MediaGalleryPermission
* out_permission
) {
291 std::string string_id
;
292 if (dict
->GetString(kMediaGalleryIdKey
, &string_id
) &&
293 base::StringToUint64(string_id
, &out_permission
->pref_id
) &&
294 dict
->GetBoolean(kMediaGalleryHasPermissionKey
,
295 &out_permission
->has_permission
)) {
302 // For a device with |device_name| and a relative path |sub_folder|, construct
303 // a display name. If |sub_folder| is empty, then just return |device_name|.
304 base::string16
GetDisplayNameForSubFolder(const base::string16
& device_name
,
305 const base::FilePath
& sub_folder
) {
306 if (sub_folder
.empty())
308 return (sub_folder
.BaseName().LossyDisplayName() +
309 base::ASCIIToUTF16(" - ") +
313 void InitializeImportedMediaGalleryRegistryOnFileThread() {
314 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
315 ImportedMediaGalleryRegistry::GetInstance()->Initialize();
320 MediaGalleryPrefInfo::MediaGalleryPrefInfo()
321 : pref_id(kInvalidMediaGalleryPrefId
),
323 total_size_in_bytes(0),
324 volume_metadata_valid(false),
331 MediaGalleryPrefInfo::~MediaGalleryPrefInfo() {}
333 base::FilePath
MediaGalleryPrefInfo::AbsolutePath() const {
334 base::FilePath base_path
= MediaStorageUtil::FindDevicePathById(device_id
);
335 DCHECK(!path
.IsAbsolute());
336 return base_path
.empty() ? base_path
: base_path
.Append(path
);
339 bool MediaGalleryPrefInfo::IsBlackListedType() const {
340 return type
== kBlackListed
|| type
== kRemovedScan
;
343 base::string16
MediaGalleryPrefInfo::GetGalleryDisplayName() const {
344 if (!StorageInfo::IsRemovableDevice(device_id
)) {
345 // For fixed storage, the default name is the fully qualified directory
346 // name, or in the case of a root directory, the root directory name.
347 // Exception: ChromeOS -- the full pathname isn't visible there, so only
348 // the directory name is used.
349 base::FilePath path
= AbsolutePath();
350 if (!display_name
.empty())
353 #if defined(OS_CHROMEOS)
354 // See chrome/browser/chromeos/fileapi/file_system_backend.cc
355 base::FilePath download_path
;
356 if (PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS_SAFE
, &download_path
)) {
357 base::FilePath relative
;
358 if (download_path
.AppendRelativePath(path
, &relative
))
359 return relative
.LossyDisplayName();
361 return path
.BaseName().LossyDisplayName();
363 return path
.LossyDisplayName();
367 StorageInfo
info(device_id
,
368 MediaStorageUtil::FindDevicePathById(device_id
).value(),
369 volume_label
, vendor_name
, model_name
, total_size_in_bytes
);
370 base::string16 name
= info
.GetDisplayNameWithOverride(display_name
, true);
372 name
= GetDisplayNameForSubFolder(name
, path
);
376 base::string16
MediaGalleryPrefInfo::GetGalleryTooltip() const {
377 return AbsolutePath().LossyDisplayName();
380 base::string16
MediaGalleryPrefInfo::GetGalleryAdditionalDetails() const {
381 base::string16 attached
;
382 if (StorageInfo::IsRemovableDevice(device_id
)) {
383 if (MediaStorageUtil::IsRemovableStorageAttached(device_id
)) {
384 attached
= l10n_util::GetStringUTF16(
385 IDS_MEDIA_GALLERIES_DIALOG_DEVICE_ATTACHED
);
386 } else if (!last_attach_time
.is_null()) {
387 attached
= l10n_util::GetStringFUTF16(
388 IDS_MEDIA_GALLERIES_LAST_ATTACHED
,
389 base::TimeFormatShortDateNumeric(last_attach_time
));
391 attached
= l10n_util::GetStringUTF16(
392 IDS_MEDIA_GALLERIES_DIALOG_DEVICE_NOT_ATTACHED
);
399 bool MediaGalleryPrefInfo::IsGalleryAvailable() const {
400 return !StorageInfo::IsRemovableDevice(device_id
) ||
401 MediaStorageUtil::IsRemovableStorageAttached(device_id
);
404 MediaGalleriesPreferences::GalleryChangeObserver::~GalleryChangeObserver() {}
406 MediaGalleriesPreferences::MediaGalleriesPreferences(Profile
* profile
)
407 : initialized_(false),
408 pre_initialization_callbacks_waiting_(0),
410 extension_prefs_for_testing_(NULL
),
411 weak_factory_(this) {
414 MediaGalleriesPreferences::~MediaGalleriesPreferences() {
415 if (StorageMonitor::GetInstance())
416 StorageMonitor::GetInstance()->RemoveObserver(this);
419 void MediaGalleriesPreferences::EnsureInitialized(base::Closure callback
) {
420 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
422 if (IsInitialized()) {
423 if (!callback
.is_null())
428 on_initialize_callbacks_
.push_back(callback
);
429 if (on_initialize_callbacks_
.size() > 1)
432 // This counter must match the number of async methods dispatched below.
433 // It cannot be incremented inline with each callback, as some may return
434 // synchronously, decrement the counter to 0, and prematurely trigger
435 // FinishInitialization.
436 pre_initialization_callbacks_waiting_
= 4;
438 // Check whether we should be initializing -- are there any extensions that
439 // are using media galleries?
440 media_galleries::UsageCount(media_galleries::PREFS_INITIALIZED
);
441 if (NumberExtensionsUsingMediaGalleries(profile_
) == 0) {
442 media_galleries::UsageCount(media_galleries::PREFS_INITIALIZED_ERROR
);
445 // We determine the freshness of the profile here, before any of the finders
446 // return and add media galleries to it.
447 StorageMonitor::GetInstance()->EnsureInitialized(
448 base::Bind(&MediaGalleriesPreferences::OnStorageMonitorInit
,
449 weak_factory_
.GetWeakPtr(),
450 !APIHasBeenUsed(profile_
) /* add_default_galleries */));
452 // Look for optional default galleries every time.
453 iapps::FindITunesLibrary(
454 base::Bind(&MediaGalleriesPreferences::OnFinderDeviceID
,
455 weak_factory_
.GetWeakPtr()));
457 picasa::FindPicasaDatabase(
458 base::Bind(&MediaGalleriesPreferences::OnFinderDeviceID
,
459 weak_factory_
.GetWeakPtr()));
461 iapps::FindIPhotoLibrary(
462 base::Bind(&MediaGalleriesPreferences::OnFinderDeviceID
,
463 weak_factory_
.GetWeakPtr()));
466 bool MediaGalleriesPreferences::IsInitialized() const { return initialized_
; }
468 Profile
* MediaGalleriesPreferences::profile() { return profile_
; }
470 void MediaGalleriesPreferences::OnInitializationCallbackReturned() {
471 DCHECK(!IsInitialized());
472 DCHECK_GT(pre_initialization_callbacks_waiting_
, 0);
473 if (--pre_initialization_callbacks_waiting_
== 0)
474 FinishInitialization();
477 void MediaGalleriesPreferences::FinishInitialization() {
478 DCHECK(!IsInitialized());
482 StorageMonitor
* monitor
= StorageMonitor::GetInstance();
483 DCHECK(monitor
->IsInitialized());
487 StorageMonitor::GetInstance()->AddObserver(this);
489 std::vector
<StorageInfo
> existing_devices
=
490 monitor
->GetAllAvailableStorages();
491 for (size_t i
= 0; i
< existing_devices
.size(); i
++) {
492 if (!(StorageInfo::IsMediaDevice(existing_devices
[i
].device_id()) &&
493 StorageInfo::IsRemovableDevice(existing_devices
[i
].device_id())))
495 AddGallery(existing_devices
[i
].device_id(),
497 MediaGalleryPrefInfo::kAutoDetected
,
498 existing_devices
[i
].storage_label(),
499 existing_devices
[i
].vendor_name(),
500 existing_devices
[i
].model_name(),
501 existing_devices
[i
].total_size_in_bytes(),
502 base::Time::Now(), 0, 0, 0);
505 for (std::vector
<base::Closure
>::iterator iter
=
506 on_initialize_callbacks_
.begin();
507 iter
!= on_initialize_callbacks_
.end();
511 on_initialize_callbacks_
.clear();
514 void MediaGalleriesPreferences::AddDefaultGalleries() {
515 const int kDirectoryKeys
[] = {
516 chrome::DIR_USER_MUSIC
,
517 chrome::DIR_USER_PICTURES
,
518 chrome::DIR_USER_VIDEOS
,
521 for (size_t i
= 0; i
< arraysize(kDirectoryKeys
); ++i
) {
523 if (!PathService::Get(kDirectoryKeys
[i
], &path
))
526 base::FilePath relative_path
;
528 if (MediaStorageUtil::GetDeviceInfoFromPath(path
, &info
, &relative_path
)) {
529 AddGalleryInternal(info
.device_id(), base::string16(), relative_path
,
530 MediaGalleryPrefInfo::kAutoDetected
,
531 info
.storage_label(), info
.vendor_name(),
532 info
.model_name(), info
.total_size_in_bytes(),
533 base::Time(), true, 0, 0, 0, kCurrentPrefsVersion
);
538 bool MediaGalleriesPreferences::UpdateDeviceIDForSingletonType(
539 const std::string
& device_id
) {
540 StorageInfo::Type singleton_type
;
541 if (!StorageInfo::CrackDeviceId(device_id
, &singleton_type
, NULL
))
544 PrefService
* prefs
= profile_
->GetPrefs();
545 scoped_ptr
<ListPrefUpdate
> update(new ListPrefUpdate(
546 prefs
, prefs::kMediaGalleriesRememberedGalleries
));
547 base::ListValue
* list
= update
->Get();
548 for (base::ListValue::iterator iter
= list
->begin();
549 iter
!= list
->end(); ++iter
) {
550 // All of these calls should succeed, but preferences file can be corrupt.
551 base::DictionaryValue
* dict
;
552 if (!(*iter
)->GetAsDictionary(&dict
))
554 std::string this_device_id
;
555 if (!dict
->GetString(kMediaGalleriesDeviceIdKey
, &this_device_id
))
557 if (this_device_id
== device_id
)
558 return true; // No update is necessary.
559 StorageInfo::Type device_type
;
560 if (!StorageInfo::CrackDeviceId(this_device_id
, &device_type
, NULL
))
563 if (device_type
== singleton_type
) {
564 dict
->SetString(kMediaGalleriesDeviceIdKey
, device_id
);
565 update
.reset(); // commits the update.
567 MediaGalleryPrefId pref_id
;
568 if (GetPrefId(*dict
, &pref_id
)) {
569 FOR_EACH_OBSERVER(GalleryChangeObserver
,
570 gallery_change_observers_
,
571 OnGalleryInfoUpdated(this, pref_id
));
579 void MediaGalleriesPreferences::OnStorageMonitorInit(
580 bool add_default_galleries
) {
581 if (add_default_galleries
)
582 AddDefaultGalleries();
583 OnInitializationCallbackReturned();
586 void MediaGalleriesPreferences::OnFinderDeviceID(const std::string
& device_id
) {
587 if (!device_id
.empty()) {
588 std::string gallery_name
;
589 if (StorageInfo::IsIPhotoDevice(device_id
))
590 gallery_name
= kIPhotoGalleryName
;
591 else if (StorageInfo::IsITunesDevice(device_id
))
592 gallery_name
= kITunesGalleryName
;
593 else if (StorageInfo::IsPicasaDevice(device_id
))
594 gallery_name
= kPicasaGalleryName
;
596 if (!gallery_name
.empty()) {
597 pre_initialization_callbacks_waiting_
++;
598 content::BrowserThread::PostTaskAndReply(
599 content::BrowserThread::FILE,
601 base::Bind(&InitializeImportedMediaGalleryRegistryOnFileThread
),
603 &MediaGalleriesPreferences::OnInitializationCallbackReturned
,
604 weak_factory_
.GetWeakPtr()));
607 if (!UpdateDeviceIDForSingletonType(device_id
)) {
608 DCHECK(!gallery_name
.empty());
609 AddGalleryInternal(device_id
, base::ASCIIToUTF16(gallery_name
),
610 base::FilePath(), MediaGalleryPrefInfo::kAutoDetected
,
611 base::string16(), base::string16(), base::string16(),
612 0, base::Time(), false, 0, 0, 0, kCurrentPrefsVersion
);
616 OnInitializationCallbackReturned();
619 void MediaGalleriesPreferences::InitFromPrefs() {
620 known_galleries_
.clear();
623 PrefService
* prefs
= profile_
->GetPrefs();
624 const base::ListValue
* list
= prefs
->GetList(
625 prefs::kMediaGalleriesRememberedGalleries
);
627 for (base::ListValue::const_iterator it
= list
->begin();
628 it
!= list
->end(); ++it
) {
629 const base::DictionaryValue
* dict
= NULL
;
630 if (!(*it
)->GetAsDictionary(&dict
))
633 MediaGalleryPrefInfo gallery_info
;
634 if (!PopulateGalleryPrefInfoFromDictionary(*dict
, &gallery_info
))
637 known_galleries_
[gallery_info
.pref_id
] = gallery_info
;
638 device_map_
[gallery_info
.device_id
].insert(gallery_info
.pref_id
);
643 void MediaGalleriesPreferences::AddGalleryChangeObserver(
644 GalleryChangeObserver
* observer
) {
645 DCHECK(IsInitialized());
646 gallery_change_observers_
.AddObserver(observer
);
649 void MediaGalleriesPreferences::RemoveGalleryChangeObserver(
650 GalleryChangeObserver
* observer
) {
651 DCHECK(IsInitialized());
652 gallery_change_observers_
.RemoveObserver(observer
);
655 void MediaGalleriesPreferences::OnRemovableStorageAttached(
656 const StorageInfo
& info
) {
657 DCHECK(IsInitialized());
658 if (!StorageInfo::IsMediaDevice(info
.device_id()))
661 AddGallery(info
.device_id(), base::FilePath(),
662 MediaGalleryPrefInfo::kAutoDetected
, info
.storage_label(),
663 info
.vendor_name(), info
.model_name(), info
.total_size_in_bytes(),
664 base::Time::Now(), 0, 0, 0);
667 bool MediaGalleriesPreferences::LookUpGalleryByPath(
668 const base::FilePath
& path
,
669 MediaGalleryPrefInfo
* gallery_info
) const {
670 DCHECK(IsInitialized());
672 // First check if the path matches an imported gallery.
673 for (MediaGalleriesPrefInfoMap::const_iterator it
=
674 known_galleries_
.begin(); it
!= known_galleries_
.end(); ++it
) {
675 const std::string
& device_id
= it
->second
.device_id
;
676 if (iapps::PathIndicatesIPhotoLibrary(device_id
, path
) ||
677 iapps::PathIndicatesITunesLibrary(device_id
, path
)) {
678 *gallery_info
= it
->second
;
684 base::FilePath relative_path
;
685 if (!MediaStorageUtil::GetDeviceInfoFromPath(path
, &info
, &relative_path
)) {
687 *gallery_info
= MediaGalleryPrefInfo();
691 relative_path
= relative_path
.NormalizePathSeparators();
692 MediaGalleryPrefIdSet galleries_on_device
=
693 LookUpGalleriesByDeviceId(info
.device_id());
694 for (MediaGalleryPrefIdSet::const_iterator it
= galleries_on_device
.begin();
695 it
!= galleries_on_device
.end();
697 const MediaGalleryPrefInfo
& gallery
= known_galleries_
.find(*it
)->second
;
698 if (gallery
.path
!= relative_path
)
702 *gallery_info
= gallery
;
706 // This method is called by controller::FilesSelected when the user
707 // adds a new gallery. Control reaches here when the selected gallery is
708 // on a volume we know about, but have no gallery already for. Returns
709 // hypothetical data to the caller about what the prefs will look like
710 // if the gallery is added.
711 // TODO(gbillock): split this out into another function so it doesn't
714 gallery_info
->pref_id
= kInvalidMediaGalleryPrefId
;
715 gallery_info
->device_id
= info
.device_id();
716 gallery_info
->path
= relative_path
;
717 gallery_info
->type
= MediaGalleryPrefInfo::kInvalidType
;
718 gallery_info
->volume_label
= info
.storage_label();
719 gallery_info
->vendor_name
= info
.vendor_name();
720 gallery_info
->model_name
= info
.model_name();
721 gallery_info
->total_size_in_bytes
= info
.total_size_in_bytes();
722 gallery_info
->last_attach_time
= base::Time::Now();
723 gallery_info
->volume_metadata_valid
= true;
724 gallery_info
->prefs_version
= kCurrentPrefsVersion
;
729 MediaGalleryPrefIdSet
MediaGalleriesPreferences::LookUpGalleriesByDeviceId(
730 const std::string
& device_id
) const {
731 DeviceIdPrefIdsMap::const_iterator found
= device_map_
.find(device_id
);
732 if (found
== device_map_
.end())
733 return MediaGalleryPrefIdSet();
734 return found
->second
;
737 base::FilePath
MediaGalleriesPreferences::LookUpGalleryPathForExtension(
738 MediaGalleryPrefId gallery_id
,
739 const extensions::Extension
* extension
,
740 bool include_unpermitted_galleries
) {
741 DCHECK(IsInitialized());
743 if (!include_unpermitted_galleries
&&
744 !ContainsKey(GalleriesForExtension(*extension
), gallery_id
))
745 return base::FilePath();
747 MediaGalleriesPrefInfoMap::const_iterator it
=
748 known_galleries_
.find(gallery_id
);
749 if (it
== known_galleries_
.end())
750 return base::FilePath();
751 return MediaStorageUtil::FindDevicePathById(it
->second
.device_id
);
754 MediaGalleryPrefId
MediaGalleriesPreferences::AddGallery(
755 const std::string
& device_id
,
756 const base::FilePath
& relative_path
,
757 MediaGalleryPrefInfo::Type type
,
758 const base::string16
& volume_label
,
759 const base::string16
& vendor_name
,
760 const base::string16
& model_name
,
761 uint64 total_size_in_bytes
,
762 base::Time last_attach_time
,
766 DCHECK(IsInitialized());
767 return AddGalleryInternal(device_id
, base::string16(), relative_path
,
768 type
, volume_label
, vendor_name
, model_name
,
769 total_size_in_bytes
, last_attach_time
, true,
770 audio_count
, image_count
, video_count
,
771 kCurrentPrefsVersion
);
774 MediaGalleryPrefId
MediaGalleriesPreferences::AddGalleryInternal(
775 const std::string
& device_id
, const base::string16
& display_name
,
776 const base::FilePath
& relative_path
, MediaGalleryPrefInfo::Type type
,
777 const base::string16
& volume_label
, const base::string16
& vendor_name
,
778 const base::string16
& model_name
, uint64 total_size_in_bytes
,
779 base::Time last_attach_time
, bool volume_metadata_valid
,
780 int audio_count
, int image_count
, int video_count
, int prefs_version
) {
781 DCHECK(type
== MediaGalleryPrefInfo::kUserAdded
||
782 type
== MediaGalleryPrefInfo::kAutoDetected
||
783 type
== MediaGalleryPrefInfo::kScanResult
);
784 base::FilePath normalized_relative_path
=
785 relative_path
.NormalizePathSeparators();
786 MediaGalleryPrefIdSet galleries_on_device
=
787 LookUpGalleriesByDeviceId(device_id
);
788 for (MediaGalleryPrefIdSet::const_iterator pref_id_it
=
789 galleries_on_device
.begin();
790 pref_id_it
!= galleries_on_device
.end();
792 const MediaGalleryPrefInfo
& existing
=
793 known_galleries_
.find(*pref_id_it
)->second
;
794 if (existing
.path
!= normalized_relative_path
)
797 bool update_gallery_type
= false;
798 MediaGalleryPrefInfo::Type new_type
= existing
.type
;
799 if (type
== MediaGalleryPrefInfo::kUserAdded
) {
800 if (existing
.type
== MediaGalleryPrefInfo::kBlackListed
) {
801 new_type
= MediaGalleryPrefInfo::kAutoDetected
;
802 update_gallery_type
= true;
804 if (existing
.type
== MediaGalleryPrefInfo::kRemovedScan
) {
805 new_type
= MediaGalleryPrefInfo::kUserAdded
;
806 update_gallery_type
= true;
810 // Status quo: In M27 and M28, galleries added manually use version 0,
811 // and galleries added automatically (including default galleries) use
812 // version 1. The name override is used by default galleries as well
813 // as all device attach events.
814 // We want to upgrade the name if the existing version is < 2. Leave it
815 // alone if the existing display name is set with version == 2 and the
816 // proposed new name is empty.
817 bool update_gallery_name
= existing
.display_name
!= display_name
;
818 if (existing
.prefs_version
== 2 && !existing
.display_name
.empty() &&
819 display_name
.empty()) {
820 update_gallery_name
= false;
822 bool update_gallery_metadata
= volume_metadata_valid
&&
823 ((existing
.volume_label
!= volume_label
) ||
824 (existing
.vendor_name
!= vendor_name
) ||
825 (existing
.model_name
!= model_name
) ||
826 (existing
.total_size_in_bytes
!= total_size_in_bytes
) ||
827 (existing
.last_attach_time
!= last_attach_time
));
829 bool update_scan_counts
=
830 new_type
!= MediaGalleryPrefInfo::kRemovedScan
&&
831 new_type
!= MediaGalleryPrefInfo::kBlackListed
&&
832 (audio_count
> 0 || image_count
> 0 || video_count
> 0 ||
833 existing
.audio_count
|| existing
.image_count
|| existing
.video_count
);
835 if (!update_gallery_name
&& !update_gallery_type
&&
836 !update_gallery_metadata
&& !update_scan_counts
)
839 PrefService
* prefs
= profile_
->GetPrefs();
840 scoped_ptr
<ListPrefUpdate
> update(
841 new ListPrefUpdate(prefs
, prefs::kMediaGalleriesRememberedGalleries
));
842 base::ListValue
* list
= update
->Get();
844 for (base::ListValue::const_iterator list_iter
= list
->begin();
845 list_iter
!= list
->end();
847 base::DictionaryValue
* dict
;
848 MediaGalleryPrefId iter_id
;
849 if ((*list_iter
)->GetAsDictionary(&dict
) &&
850 GetPrefId(*dict
, &iter_id
) &&
851 *pref_id_it
== iter_id
) {
852 if (update_gallery_type
)
853 dict
->SetString(kMediaGalleriesTypeKey
, TypeToStringValue(new_type
));
854 if (update_gallery_name
)
855 dict
->SetString(kMediaGalleriesDisplayNameKey
, display_name
);
856 if (update_gallery_metadata
) {
857 dict
->SetString(kMediaGalleriesVolumeLabelKey
, volume_label
);
858 dict
->SetString(kMediaGalleriesVendorNameKey
, vendor_name
);
859 dict
->SetString(kMediaGalleriesModelNameKey
, model_name
);
860 dict
->SetDouble(kMediaGalleriesSizeKey
, total_size_in_bytes
);
861 dict
->SetDouble(kMediaGalleriesLastAttachTimeKey
,
862 last_attach_time
.ToInternalValue());
864 if (update_scan_counts
) {
865 dict
->SetInteger(kMediaGalleriesScanAudioCountKey
, audio_count
);
866 dict
->SetInteger(kMediaGalleriesScanImageCountKey
, image_count
);
867 dict
->SetInteger(kMediaGalleriesScanVideoCountKey
, video_count
);
869 dict
->SetInteger(kMediaGalleriesPrefsVersionKey
, prefs_version
);
874 // Commits the prefs update.
878 FOR_EACH_OBSERVER(GalleryChangeObserver
, gallery_change_observers_
,
879 OnGalleryInfoUpdated(this, *pref_id_it
));
883 PrefService
* prefs
= profile_
->GetPrefs();
885 MediaGalleryPrefInfo gallery_info
;
886 gallery_info
.pref_id
= prefs
->GetUint64(prefs::kMediaGalleriesUniqueId
);
887 prefs
->SetUint64(prefs::kMediaGalleriesUniqueId
, gallery_info
.pref_id
+ 1);
888 gallery_info
.display_name
= display_name
;
889 gallery_info
.device_id
= device_id
;
890 gallery_info
.path
= normalized_relative_path
;
891 gallery_info
.type
= type
;
892 gallery_info
.volume_label
= volume_label
;
893 gallery_info
.vendor_name
= vendor_name
;
894 gallery_info
.model_name
= model_name
;
895 gallery_info
.total_size_in_bytes
= total_size_in_bytes
;
896 gallery_info
.last_attach_time
= last_attach_time
;
897 gallery_info
.volume_metadata_valid
= volume_metadata_valid
;
898 gallery_info
.audio_count
= audio_count
;
899 gallery_info
.image_count
= image_count
;
900 gallery_info
.video_count
= video_count
;
901 gallery_info
.prefs_version
= prefs_version
;
904 ListPrefUpdate
update(prefs
, prefs::kMediaGalleriesRememberedGalleries
);
905 base::ListValue
* list
= update
.Get();
906 list
->Append(CreateGalleryPrefInfoDictionary(gallery_info
));
909 FOR_EACH_OBSERVER(GalleryChangeObserver
,
910 gallery_change_observers_
,
911 OnGalleryAdded(this, gallery_info
.pref_id
));
913 return gallery_info
.pref_id
;
916 MediaGalleryPrefId
MediaGalleriesPreferences::AddGalleryByPath(
917 const base::FilePath
& path
, MediaGalleryPrefInfo::Type type
) {
918 DCHECK(IsInitialized());
919 MediaGalleryPrefInfo gallery_info
;
920 if (LookUpGalleryByPath(path
, &gallery_info
) &&
921 !gallery_info
.IsBlackListedType()) {
922 return gallery_info
.pref_id
;
924 return AddGalleryInternal(gallery_info
.device_id
,
925 gallery_info
.display_name
,
928 gallery_info
.volume_label
,
929 gallery_info
.vendor_name
,
930 gallery_info
.model_name
,
931 gallery_info
.total_size_in_bytes
,
932 gallery_info
.last_attach_time
,
933 gallery_info
.volume_metadata_valid
,
935 kCurrentPrefsVersion
);
938 void MediaGalleriesPreferences::ForgetGalleryById(MediaGalleryPrefId id
) {
939 EraseOrBlacklistGalleryById(id
, false);
942 void MediaGalleriesPreferences::EraseGalleryById(MediaGalleryPrefId id
) {
943 EraseOrBlacklistGalleryById(id
, true);
946 void MediaGalleriesPreferences::EraseOrBlacklistGalleryById(
947 MediaGalleryPrefId id
, bool erase
) {
948 DCHECK(IsInitialized());
949 PrefService
* prefs
= profile_
->GetPrefs();
950 scoped_ptr
<ListPrefUpdate
> update(new ListPrefUpdate(
951 prefs
, prefs::kMediaGalleriesRememberedGalleries
));
952 base::ListValue
* list
= update
->Get();
954 if (!ContainsKey(known_galleries_
, id
))
957 for (base::ListValue::iterator iter
= list
->begin();
958 iter
!= list
->end(); ++iter
) {
959 base::DictionaryValue
* dict
;
960 MediaGalleryPrefId iter_id
;
961 if ((*iter
)->GetAsDictionary(&dict
) && GetPrefId(*dict
, &iter_id
) &&
963 RemoveGalleryPermissionsFromPrefs(id
);
964 MediaGalleryPrefInfo::Type type
;
965 if (!erase
&& GetType(*dict
, &type
) &&
966 (type
== MediaGalleryPrefInfo::kAutoDetected
||
967 type
== MediaGalleryPrefInfo::kScanResult
)) {
968 if (type
== MediaGalleryPrefInfo::kAutoDetected
) {
969 dict
->SetString(kMediaGalleriesTypeKey
,
970 kMediaGalleriesTypeBlackListedValue
);
972 dict
->SetString(kMediaGalleriesTypeKey
,
973 kMediaGalleriesTypeRemovedScanValue
);
974 dict
->SetInteger(kMediaGalleriesScanAudioCountKey
, 0);
975 dict
->SetInteger(kMediaGalleriesScanImageCountKey
, 0);
976 dict
->SetInteger(kMediaGalleriesScanVideoCountKey
, 0);
979 list
->Erase(iter
, NULL
);
981 update
.reset(NULL
); // commits the update.
984 FOR_EACH_OBSERVER(GalleryChangeObserver
,
985 gallery_change_observers_
,
986 OnGalleryRemoved(this, id
));
992 bool MediaGalleriesPreferences::NonAutoGalleryHasPermission(
993 MediaGalleryPrefId id
) const {
994 DCHECK(IsInitialized());
995 DCHECK(!ContainsKey(known_galleries_
, id
) ||
996 known_galleries_
.find(id
)->second
.type
!=
997 MediaGalleryPrefInfo::kAutoDetected
);
998 ExtensionPrefs
* prefs
= GetExtensionPrefs();
999 const base::DictionaryValue
* extensions
=
1000 prefs
->pref_service()->GetDictionary(extensions::pref_names::kExtensions
);
1004 for (base::DictionaryValue::Iterator
iter(*extensions
); !iter
.IsAtEnd();
1006 if (!extensions::Extension::IdIsValid(iter
.key())) {
1010 std::vector
<MediaGalleryPermission
> permissions
=
1011 GetGalleryPermissionsFromPrefs(iter
.key());
1012 for (std::vector
<MediaGalleryPermission
>::const_iterator it
=
1013 permissions
.begin(); it
!= permissions
.end(); ++it
) {
1014 if (it
->pref_id
== id
) {
1015 if (it
->has_permission
)
1024 MediaGalleryPrefIdSet
MediaGalleriesPreferences::GalleriesForExtension(
1025 const extensions::Extension
& extension
) {
1026 DCHECK(IsInitialized());
1027 MediaGalleryPrefIdSet result
;
1029 if (HasAutoDetectedGalleryPermission(extension
)) {
1030 for (MediaGalleriesPrefInfoMap::const_iterator it
=
1031 known_galleries_
.begin(); it
!= known_galleries_
.end(); ++it
) {
1032 if (it
->second
.type
== MediaGalleryPrefInfo::kAutoDetected
)
1033 result
.insert(it
->second
.pref_id
);
1037 std::vector
<MediaGalleryPermission
> stored_permissions
=
1038 GetGalleryPermissionsFromPrefs(extension
.id());
1039 for (std::vector
<MediaGalleryPermission
>::const_iterator it
=
1040 stored_permissions
.begin(); it
!= stored_permissions
.end(); ++it
) {
1041 if (!it
->has_permission
) {
1042 result
.erase(it
->pref_id
);
1044 MediaGalleriesPrefInfoMap::const_iterator gallery
=
1045 known_galleries_
.find(it
->pref_id
);
1047 // Handle a stored permission for an erased gallery. This should never
1048 // happen but, has caused crashes in the wild. http://crbug.com/374330.
1049 if (gallery
== known_galleries_
.end()) {
1050 RemoveGalleryPermissionsFromPrefs(it
->pref_id
);
1054 if (!gallery
->second
.IsBlackListedType()) {
1055 result
.insert(it
->pref_id
);
1057 NOTREACHED() << gallery
->second
.device_id
;
1064 bool MediaGalleriesPreferences::SetGalleryPermissionForExtension(
1065 const extensions::Extension
& extension
,
1066 MediaGalleryPrefId pref_id
,
1067 bool has_permission
) {
1068 DCHECK(IsInitialized());
1069 // The gallery may not exist anymore if the user opened a second config
1070 // surface concurrently and removed it. Drop the permission update if so.
1071 MediaGalleriesPrefInfoMap::const_iterator gallery_info
=
1072 known_galleries_
.find(pref_id
);
1073 if (gallery_info
== known_galleries_
.end())
1076 bool default_permission
= false;
1077 if (gallery_info
->second
.type
== MediaGalleryPrefInfo::kAutoDetected
)
1078 default_permission
= HasAutoDetectedGalleryPermission(extension
);
1079 // When the permission matches the default, we don't need to remember it.
1080 if (has_permission
== default_permission
) {
1081 if (!UnsetGalleryPermissionInPrefs(extension
.id(), pref_id
))
1082 // If permission wasn't set, assume nothing has changed.
1085 if (!SetGalleryPermissionInPrefs(extension
.id(), pref_id
, has_permission
))
1089 FOR_EACH_OBSERVER(GalleryChangeObserver
,
1090 gallery_change_observers_
,
1091 OnPermissionAdded(this, extension
.id(), pref_id
));
1093 FOR_EACH_OBSERVER(GalleryChangeObserver
,
1094 gallery_change_observers_
,
1095 OnPermissionRemoved(this, extension
.id(), pref_id
));
1099 const MediaGalleriesPrefInfoMap
& MediaGalleriesPreferences::known_galleries()
1101 DCHECK(IsInitialized());
1102 return known_galleries_
;
1105 base::Time
MediaGalleriesPreferences::GetLastScanCompletionTime() const {
1106 int64 last_scan_time_internal
=
1107 profile_
->GetPrefs()->GetInt64(prefs::kMediaGalleriesLastScanTime
);
1108 return base::Time::FromInternalValue(last_scan_time_internal
);
1111 void MediaGalleriesPreferences::SetLastScanCompletionTime(
1112 const base::Time
& time
) {
1113 profile_
->GetPrefs()->SetInt64(prefs::kMediaGalleriesLastScanTime
,
1114 time
.ToInternalValue());
1117 void MediaGalleriesPreferences::Shutdown() {
1118 weak_factory_
.InvalidateWeakPtrs();
1123 bool MediaGalleriesPreferences::APIHasBeenUsed(Profile
* profile
) {
1124 MediaGalleryPrefId current_id
=
1125 profile
->GetPrefs()->GetUint64(prefs::kMediaGalleriesUniqueId
);
1126 return current_id
!= kInvalidMediaGalleryPrefId
+ 1;
1130 void MediaGalleriesPreferences::RegisterProfilePrefs(
1131 user_prefs::PrefRegistrySyncable
* registry
) {
1132 registry
->RegisterListPref(prefs::kMediaGalleriesRememberedGalleries
,
1133 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
1134 registry
->RegisterUint64Pref(
1135 prefs::kMediaGalleriesUniqueId
,
1136 kInvalidMediaGalleryPrefId
+ 1,
1137 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
1138 registry
->RegisterInt64Pref(
1139 prefs::kMediaGalleriesLastScanTime
,
1140 base::Time().ToInternalValue(),
1141 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
1144 bool MediaGalleriesPreferences::SetGalleryPermissionInPrefs(
1145 const std::string
& extension_id
,
1146 MediaGalleryPrefId gallery_id
,
1148 DCHECK(IsInitialized());
1149 ExtensionPrefs::ScopedListUpdate
update(GetExtensionPrefs(),
1151 kMediaGalleriesPermissions
);
1152 base::ListValue
* permissions
= update
.Get();
1154 permissions
= update
.Create();
1156 // If the gallery is already in the list, update the permission...
1157 for (base::ListValue::iterator iter
= permissions
->begin();
1158 iter
!= permissions
->end(); ++iter
) {
1159 base::DictionaryValue
* dict
= NULL
;
1160 if (!(*iter
)->GetAsDictionary(&dict
))
1162 MediaGalleryPermission perm
;
1163 if (!GetMediaGalleryPermissionFromDictionary(dict
, &perm
))
1165 if (perm
.pref_id
== gallery_id
) {
1166 if (has_access
!= perm
.has_permission
) {
1167 dict
->SetBoolean(kMediaGalleryHasPermissionKey
, has_access
);
1175 // ...Otherwise, add a new entry for the gallery.
1176 base::DictionaryValue
* dict
= new base::DictionaryValue
;
1177 dict
->SetString(kMediaGalleryIdKey
, base::Uint64ToString(gallery_id
));
1178 dict
->SetBoolean(kMediaGalleryHasPermissionKey
, has_access
);
1179 permissions
->Append(dict
);
1183 bool MediaGalleriesPreferences::UnsetGalleryPermissionInPrefs(
1184 const std::string
& extension_id
,
1185 MediaGalleryPrefId gallery_id
) {
1186 DCHECK(IsInitialized());
1187 ExtensionPrefs::ScopedListUpdate
update(GetExtensionPrefs(),
1189 kMediaGalleriesPermissions
);
1190 base::ListValue
* permissions
= update
.Get();
1194 for (base::ListValue::iterator iter
= permissions
->begin();
1195 iter
!= permissions
->end(); ++iter
) {
1196 const base::DictionaryValue
* dict
= NULL
;
1197 if (!(*iter
)->GetAsDictionary(&dict
))
1199 MediaGalleryPermission perm
;
1200 if (!GetMediaGalleryPermissionFromDictionary(dict
, &perm
))
1202 if (perm
.pref_id
== gallery_id
) {
1203 permissions
->Erase(iter
, NULL
);
1210 std::vector
<MediaGalleryPermission
>
1211 MediaGalleriesPreferences::GetGalleryPermissionsFromPrefs(
1212 const std::string
& extension_id
) const {
1213 DCHECK(IsInitialized());
1214 std::vector
<MediaGalleryPermission
> result
;
1215 const base::ListValue
* permissions
;
1216 if (!GetExtensionPrefs()->ReadPrefAsList(extension_id
,
1217 kMediaGalleriesPermissions
,
1222 for (base::ListValue::const_iterator iter
= permissions
->begin();
1223 iter
!= permissions
->end(); ++iter
) {
1224 base::DictionaryValue
* dict
= NULL
;
1225 if (!(*iter
)->GetAsDictionary(&dict
))
1227 MediaGalleryPermission perm
;
1228 if (!GetMediaGalleryPermissionFromDictionary(dict
, &perm
))
1230 result
.push_back(perm
);
1236 void MediaGalleriesPreferences::RemoveGalleryPermissionsFromPrefs(
1237 MediaGalleryPrefId gallery_id
) {
1238 DCHECK(IsInitialized());
1239 ExtensionPrefs
* prefs
= GetExtensionPrefs();
1240 const base::DictionaryValue
* extensions
=
1241 prefs
->pref_service()->GetDictionary(extensions::pref_names::kExtensions
);
1245 for (base::DictionaryValue::Iterator
iter(*extensions
); !iter
.IsAtEnd();
1247 if (!extensions::Extension::IdIsValid(iter
.key())) {
1251 UnsetGalleryPermissionInPrefs(iter
.key(), gallery_id
);
1255 ExtensionPrefs
* MediaGalleriesPreferences::GetExtensionPrefs() const {
1256 DCHECK(IsInitialized());
1257 if (extension_prefs_for_testing_
)
1258 return extension_prefs_for_testing_
;
1259 return extensions::ExtensionPrefs::Get(profile_
);
1262 void MediaGalleriesPreferences::SetExtensionPrefsForTesting(
1263 extensions::ExtensionPrefs
* extension_prefs
) {
1264 DCHECK(IsInitialized());
1265 extension_prefs_for_testing_
= extension_prefs
;