media_galleries_preferences.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/media_galleries_preferences.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/base_paths_posix.h"
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/callback.h"
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/i18n/time_formatting.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/browser_process.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/iapps_finder.h"
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/picasa_finder.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/media_file_system_registry.h"
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/media_galleries/media_galleries_histograms.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/storage_monitor/media_storage_util.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/storage_monitor/storage_monitor.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_paths.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/extension.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/permissions/media_galleries_permission.h"
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/extensions/permissions/permissions_data.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.h"
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "extensions/common/permissions/api_permission.h"
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "grit/generated_resources.h"
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/l10n/l10n_util.h"
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/text/bytes_formatting.h"
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::DictionaryValue;
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::ListValue;
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using extensions::ExtensionPrefs;
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Pref key for the list of media gallery permissions.
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kMediaGalleriesPermissions[] = "media_galleries_permissions";
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Pref key for Media Gallery ID.
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kMediaGalleryIdKey[] = "id";
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Pref key for Media Gallery Permission Value.
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kMediaGalleryHasPermissionKey[] = "has_permission";
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesDeviceIdKey[] = "deviceId";
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesDisplayNameKey[] = "displayName";
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesPathKey[] = "path";
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesPrefIdKey[] = "prefId";
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesTypeKey[] = "type";
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesVolumeLabelKey[] = "volumeLabel";
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesVendorNameKey[] = "vendorName";
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesModelNameKey[] = "modelName";
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesSizeKey[] = "totalSize";
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesLastAttachTimeKey[] = "lastAttachTime";
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesPrefsVersionKey[] = "preferencesVersion";
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesTypeAutoDetectedValue[] = "autoDetected";
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesTypeUserAddedValue[] = "userAdded";
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMediaGalleriesTypeBlackListedValue[] = "blackListed";
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kIPhotoGalleryName[] = "iPhoto";
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kITunesGalleryName[] = "iTunes";
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kPicasaGalleryName[] = "Picasa";
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int NumberExtensionsUsingMediaGalleries(Profile* profile) {
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int count = 0;
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!profile)
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return count;
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ExtensionService* extension_service =
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile)->extension_service();
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!extension_service)
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return count;
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const ExtensionSet* extensions = extension_service->extensions();
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (ExtensionSet::const_iterator i = extensions->begin();
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       i != extensions->end(); ++i) {
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (extensions::PermissionsData::HasAPIPermission(
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            *i, extensions::APIPermission::kMediaGalleries) ||
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        extensions::PermissionsData::HasAPIPermission(
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            *i, extensions::APIPermission::kMediaGalleriesPrivate)) {
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      count++;
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return count;
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetPrefId(const DictionaryValue& dict, MediaGalleryPrefId* value) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string string_id;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict.GetString(kMediaGalleriesPrefIdKey, &string_id) ||
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !base::StringToUint64(string_id, value)) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetType(const DictionaryValue& dict, MediaGalleryPrefInfo::Type* type) {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string string_type;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict.GetString(kMediaGalleriesTypeKey, &string_type))
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (string_type == kMediaGalleriesTypeAutoDetectedValue) {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *type = MediaGalleryPrefInfo::kAutoDetected;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (string_type == kMediaGalleriesTypeUserAddedValue) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *type = MediaGalleryPrefInfo::kUserAdded;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (string_type == kMediaGalleriesTypeBlackListedValue) {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *type = MediaGalleryPrefInfo::kBlackListed;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool PopulateGalleryPrefInfoFromDictionary(
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DictionaryValue& dict, MediaGalleryPrefInfo* out_gallery_info) {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaGalleryPrefId pref_id;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  string16 display_name;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string device_id;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType path;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaGalleryPrefInfo::Type type = MediaGalleryPrefInfo::kAutoDetected;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  string16 volume_label;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  string16 vendor_name;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  string16 model_name;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double total_size_in_bytes = 0.0;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double last_attach_time = 0.0;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool volume_metadata_valid = false;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int prefs_version = 0;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!GetPrefId(dict, &pref_id) ||
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !dict.GetString(kMediaGalleriesDeviceIdKey, &device_id) ||
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !dict.GetString(kMediaGalleriesPathKey, &path) ||
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !GetType(dict, &type)) {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict.GetString(kMediaGalleriesDisplayNameKey, &display_name);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict.GetInteger(kMediaGalleriesPrefsVersionKey, &prefs_version);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dict.GetString(kMediaGalleriesVolumeLabelKey, &volume_label) &&
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dict.GetString(kMediaGalleriesVendorNameKey, &vendor_name) &&
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dict.GetString(kMediaGalleriesModelNameKey, &model_name) &&
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dict.GetDouble(kMediaGalleriesSizeKey, &total_size_in_bytes) &&
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dict.GetDouble(kMediaGalleriesLastAttachTimeKey, &last_attach_time)) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    volume_metadata_valid = true;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->pref_id = pref_id;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->display_name = display_name;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->device_id = device_id;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->path = base::FilePath(path);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->type = type;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->volume_label = volume_label;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->vendor_name = vendor_name;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->model_name = model_name;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->total_size_in_bytes = total_size_in_bytes;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->last_attach_time =
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::FromInternalValue(last_attach_time);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->volume_metadata_valid = volume_metadata_valid;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_gallery_info->prefs_version = prefs_version;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DictionaryValue* CreateGalleryPrefInfoDictionary(
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const MediaGalleryPrefInfo& gallery) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryValue* dict = new DictionaryValue();
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString(kMediaGalleriesPrefIdKey,
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  base::Uint64ToString(gallery.pref_id));
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!gallery.volume_metadata_valid)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->SetString(kMediaGalleriesDisplayNameKey, gallery.display_name);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString(kMediaGalleriesDeviceIdKey, gallery.device_id);
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString(kMediaGalleriesPathKey, gallery.path.value());
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* type = NULL;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (gallery.type) {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case MediaGalleryPrefInfo::kAutoDetected:
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type = kMediaGalleriesTypeAutoDetectedValue;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case MediaGalleryPrefInfo::kUserAdded:
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type = kMediaGalleriesTypeUserAddedValue;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case MediaGalleryPrefInfo::kBlackListed:
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type = kMediaGalleriesTypeBlackListedValue;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString(kMediaGalleriesTypeKey, type);
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (gallery.volume_metadata_valid) {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->SetString(kMediaGalleriesVolumeLabelKey, gallery.volume_label);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->SetString(kMediaGalleriesVendorNameKey, gallery.vendor_name);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->SetString(kMediaGalleriesModelNameKey, gallery.model_name);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->SetDouble(kMediaGalleriesSizeKey, gallery.total_size_in_bytes);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->SetDouble(kMediaGalleriesLastAttachTimeKey,
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    gallery.last_attach_time.ToInternalValue());
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Version 0 of the prefs format was that the display_name was always
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // used to show the user-visible name of the gallery. Version 1 means
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // that there is an optional display_name, and when it is present, it
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // overrides the name that would be built from the volume metadata, path,
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // or whatever other data. So if we see a display_name with version 0, it
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // means it may be overwritten simply by getting new volume metadata.
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A display_name with version 1 should not be overwritten.
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetInteger(kMediaGalleriesPrefsVersionKey, gallery.prefs_version);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dict;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HasAutoDetectedGalleryPermission(const extensions::Extension& extension) {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extensions::MediaGalleriesPermission::CheckParam param(
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::MediaGalleriesPermission::kAllAutoDetectedPermission);
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return extensions::PermissionsData::CheckAPIPermissionWithParam(
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      &extension, extensions::APIPermission::kMediaGalleries, &param);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Retrieves the MediaGalleryPermission from the given dictionary; DCHECKs on
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// failure.
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool GetMediaGalleryPermissionFromDictionary(
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const DictionaryValue* dict,
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    MediaGalleryPermission* out_permission) {
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string string_id;
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (dict->GetString(kMediaGalleryIdKey, &string_id) &&
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::StringToUint64(string_id, &out_permission->pref_id) &&
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      dict->GetBoolean(kMediaGalleryHasPermissionKey,
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       &out_permission->has_permission)) {
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NOTREACHED();
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return false;
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstring16 GetDisplayNameForDevice(uint64 storage_size_in_bytes,
249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                 const string16& name) {
250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!name.empty());
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return (storage_size_in_bytes == 0) ?
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      name : ui::FormatBytes(storage_size_in_bytes) + ASCIIToUTF16(" ") + name;
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// For a device with |device_name| and a relative path |sub_folder|, construct
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// a display name. If |sub_folder| is empty, then just return |device_name|.
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstring16 GetDisplayNameForSubFolder(const string16& device_name,
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    const base::FilePath& sub_folder) {
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (sub_folder.empty())
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return device_name;
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return (sub_folder.BaseName().LossyDisplayName() +
262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          ASCIIToUTF16(" - ") +
263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          device_name);
264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstring16 GetFullProductName(const string16& vendor_name,
267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            const string16& model_name) {
268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (vendor_name.empty() && model_name.empty())
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return string16();
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  string16 product_name;
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (vendor_name.empty())
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    product_name = model_name;
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  else if (model_name.empty())
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    product_name = vendor_name;
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  else if (!vendor_name.empty() && !model_name.empty())
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    product_name = vendor_name + UTF8ToUTF16(", ") + model_name;
278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return product_name;
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaGalleryPrefInfo::MediaGalleryPrefInfo()
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : pref_id(kInvalidMediaGalleryPrefId),
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type(kInvalidType),
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      total_size_in_bytes(0),
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      volume_metadata_valid(false),
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      prefs_version(0) {
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaGalleryPrefInfo::~MediaGalleryPrefInfo() {}
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath MediaGalleryPrefInfo::AbsolutePath() const {
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath base_path = MediaStorageUtil::FindDevicePathById(device_id);
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!path.IsAbsolute());
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base_path.empty() ? base_path : base_path.Append(path);
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstring16 MediaGalleryPrefInfo::GetGalleryDisplayName() const {
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!StorageInfo::IsRemovableDevice(device_id)) {
30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // For fixed storage, the default name is the fully qualified directory
30368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // name, or in the case of a root directory, the root directory name.
30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Exception: ChromeOS -- the full pathname isn't visible there, so only
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // the directory name is used.
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::FilePath path = AbsolutePath();
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!display_name.empty())
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return display_name;
30968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_CHROMEOS)
31168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // See chrome/browser/chromeos/fileapi/file_system_backend.cc
31268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    base::FilePath home_path;
31368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (PathService::Get(base::DIR_HOME, &home_path)) {
31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      home_path = home_path.AppendASCII("Downloads");
31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      base::FilePath relative;
31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (home_path.AppendRelativePath(path, &relative))
31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return relative.LossyDisplayName();
31868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return path.BaseName().LossyDisplayName();
32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#else
32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return path.LossyDisplayName();
32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  string16 name = display_name;
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (name.empty())
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    name = volume_label;
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (name.empty())
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    name = GetFullProductName(vendor_name, model_name);
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (name.empty())
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    name = l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_UNLABELED_DEVICE);
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  name = GetDisplayNameForDevice(total_size_in_bytes, name);
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!path.empty())
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    name = GetDisplayNameForSubFolder(name, path);
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return name;
339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstring16 MediaGalleryPrefInfo::GetGalleryTooltip() const {
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return AbsolutePath().LossyDisplayName();
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstring16 MediaGalleryPrefInfo::GetGalleryAdditionalDetails() const {
346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  string16 attached;
347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (StorageInfo::IsRemovableDevice(device_id)) {
348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (MediaStorageUtil::IsRemovableStorageAttached(device_id)) {
349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      attached = l10n_util::GetStringUTF16(
350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          IDS_MEDIA_GALLERIES_DIALOG_DEVICE_ATTACHED);
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else if (!last_attach_time.is_null()) {
352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      attached = l10n_util::GetStringFUTF16(
353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          IDS_MEDIA_GALLERIES_LAST_ATTACHED,
354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::TimeFormatShortDateNumeric(last_attach_time));
355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else {
356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      attached = l10n_util::GetStringUTF16(
357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          IDS_MEDIA_GALLERIES_DIALOG_DEVICE_NOT_ATTACHED);
358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return attached;
362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool MediaGalleryPrefInfo::IsGalleryAvailable() const {
365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return !StorageInfo::IsRemovableDevice(device_id) ||
366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         MediaStorageUtil::IsRemovableStorageAttached(device_id);
367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaGalleriesPreferences::GalleryChangeObserver::~GalleryChangeObserver() {}
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaGalleriesPreferences::MediaGalleriesPreferences(Profile* profile)
3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : initialized_(false),
3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      pre_initialization_callbacks_waiting_(0),
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile_(profile),
3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      extension_prefs_for_testing_(NULL),
3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_factory_(this) {
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)MediaGalleriesPreferences::~MediaGalleriesPreferences() {
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (StorageMonitor::GetInstance())
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    StorageMonitor::GetInstance()->RemoveObserver(this);
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MediaGalleriesPreferences::EnsureInitialized(base::Closure callback) {
3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (IsInitialized()) {
3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!callback.is_null())
3894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      callback.Run();
3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  on_initialize_callbacks_.push_back(callback);
3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (on_initialize_callbacks_.size() > 1)
3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // This counter must match the number of async methods dispatched below.
3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // It cannot be incremented inline with each callback, as some may return
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // synchronously, decrement the counter to 0, and prematurely trigger
4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // FinishInitialization.
4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  pre_initialization_callbacks_waiting_ = 3;
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Check whether we should be initializing -- are there any extensions that
4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // are using media galleries?
4054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  media_galleries::UsageCount(media_galleries::PREFS_INITIALIZED);
4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (NumberExtensionsUsingMediaGalleries(profile_) == 0) {
4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    media_galleries::UsageCount(media_galleries::PREFS_INITIALIZED_ERROR);
4084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // We determine the freshness of the profile here, before any of the finders
4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // return and add media galleries to it.
4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  StorageMonitor::GetInstance()->EnsureInitialized(
4134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&MediaGalleriesPreferences::OnStorageMonitorInit,
4144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 weak_factory_.GetWeakPtr(),
4154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 !APIHasBeenUsed(profile_) /* add_default_galleries */));
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Look for optional default galleries every time.
4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  iapps::FindITunesLibrary(
4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&MediaGalleriesPreferences::OnFinderDeviceID,
4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 weak_factory_.GetWeakPtr()));
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  picasa::FindPicasaDatabase(
4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&MediaGalleriesPreferences::OnFinderDeviceID,
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 weak_factory_.GetWeakPtr()));
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if 0
4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  iapps::FindIPhotoLibrary(
4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&MediaGalleriesPreferences::OnFinderDeviceID,
42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 weak_factory_.GetWeakPtr()));
43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool MediaGalleriesPreferences::IsInitialized() const { return initialized_; }
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Profile* MediaGalleriesPreferences::profile() { return profile_; }
4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MediaGalleriesPreferences::OnInitializationCallbackReturned() {
4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!IsInitialized());
4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(pre_initialization_callbacks_waiting_ > 0);
4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (--pre_initialization_callbacks_waiting_ == 0)
4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FinishInitialization();
4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MediaGalleriesPreferences::FinishInitialization() {
4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!IsInitialized());
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  initialized_ = true;
4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  StorageMonitor* monitor = StorageMonitor::GetInstance();
4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(monitor->IsInitialized());
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
452d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  InitFromPrefs();
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StorageMonitor::GetInstance()->AddObserver(this);
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::vector<StorageInfo> existing_devices =
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      monitor->GetAllAvailableStorages();
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (size_t i = 0; i < existing_devices.size(); i++) {
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!(StorageInfo::IsMediaDevice(existing_devices[i].device_id()) &&
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          StorageInfo::IsRemovableDevice(existing_devices[i].device_id())))
4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      continue;
4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AddGallery(existing_devices[i].device_id(),
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               base::FilePath(),
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               false,
4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               existing_devices[i].storage_label(),
4664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               existing_devices[i].vendor_name(),
4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               existing_devices[i].model_name(),
4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               existing_devices[i].total_size_in_bytes(),
4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               base::Time::Now());
4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (std::vector<base::Closure>::iterator iter =
4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           on_initialize_callbacks_.begin();
4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       iter != on_initialize_callbacks_.end();
4754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       ++iter) {
4764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    iter->Run();
4774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  on_initialize_callbacks_.clear();
479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MediaGalleriesPreferences::AddDefaultGalleries() {
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kDirectoryKeys[] = {
483d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    chrome::DIR_USER_MUSIC,
484d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    chrome::DIR_USER_PICTURES,
485d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    chrome::DIR_USER_VIDEOS,
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(kDirectoryKeys); ++i) {
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath path;
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!PathService::Get(kDirectoryKeys[i], &path))
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath relative_path;
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StorageInfo info;
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (MediaStorageUtil::GetDeviceInfoFromPath(path, &info, &relative_path)) {
4967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      AddGalleryInternal(info.device_id(), info.name(), relative_path, false,
4977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                         info.storage_label(), info.vendor_name(),
4987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                         info.model_name(), info.total_size_in_bytes(),
4997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                         base::Time(), true, 2);
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool MediaGalleriesPreferences::UpdateDeviceIDForSingletonType(
5057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const std::string& device_id) {
5067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  StorageInfo::Type singleton_type;
5077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!StorageInfo::CrackDeviceId(device_id, &singleton_type, NULL))
5087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return false;
5097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PrefService* prefs = profile_->GetPrefs();
5117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<ListPrefUpdate> update(new ListPrefUpdate(
5127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      prefs, prefs::kMediaGalleriesRememberedGalleries));
5137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ListValue* list = update->Get();
5147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (ListValue::iterator iter = list->begin(); iter != list->end(); ++iter) {
5157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // All of these calls should succeed, but preferences file can be corrupt.
5167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DictionaryValue* dict;
5177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!(*iter)->GetAsDictionary(&dict))
5187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      continue;
5197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    std::string this_device_id;
5207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!dict->GetString(kMediaGalleriesDeviceIdKey, &this_device_id))
5217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      continue;
5227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (this_device_id == device_id)
5237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return true;  // No update is necessary.
5247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    StorageInfo::Type device_type;
5257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!StorageInfo::CrackDeviceId(this_device_id, &device_type, NULL))
5267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      continue;
5277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (device_type == singleton_type) {
5297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      dict->SetString(kMediaGalleriesDeviceIdKey, device_id);
5307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      update.reset();  // commits the update.
531d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      InitFromPrefs();
532d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      MediaGalleryPrefId pref_id;
533d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (GetPrefId(*dict, &pref_id)) {
534d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        FOR_EACH_OBSERVER(GalleryChangeObserver,
535d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                          gallery_change_observers_,
536d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                          OnGalleryInfoUpdated(this, pref_id));
537d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
5387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return true;
5397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
5407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
5417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return false;
5427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
5437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MediaGalleriesPreferences::OnStorageMonitorInit(
5454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    bool add_default_galleries) {
5464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (add_default_galleries)
5474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AddDefaultGalleries();
5484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  OnInitializationCallbackReturned();
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MediaGalleriesPreferences::OnFinderDeviceID(const std::string& device_id) {
5524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!device_id.empty() && !UpdateDeviceIDForSingletonType(device_id)) {
5534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    std::string gallery_name;
5544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (StorageInfo::IsIPhotoDevice(device_id))
5554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      gallery_name = kIPhotoGalleryName;
5564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    else if (StorageInfo::IsITunesDevice(device_id))
5574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      gallery_name = kITunesGalleryName;
5584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    else if (StorageInfo::IsPicasaDevice(device_id))
5594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      gallery_name = kPicasaGalleryName;
5604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    else
5614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      NOTREACHED();
5624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AddGalleryInternal(device_id, ASCIIToUTF16(gallery_name),
5647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       base::FilePath(), false /*not user added*/,
5657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       string16(), string16(), string16(), 0,
5667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       base::Time(), false, 2);
5677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
5684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  OnInitializationCallbackReturned();
57090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
57190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
572d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void MediaGalleriesPreferences::InitFromPrefs() {
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  known_galleries_.clear();
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_map_.clear();
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrefService* prefs = profile_->GetPrefs();
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ListValue* list = prefs->GetList(
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      prefs::kMediaGalleriesRememberedGalleries);
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (list) {
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (ListValue::const_iterator it = list->begin();
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         it != list->end(); ++it) {
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const DictionaryValue* dict = NULL;
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!(*it)->GetAsDictionary(&dict))
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MediaGalleryPrefInfo gallery_info;
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!PopulateGalleryPrefInfoFromDictionary(*dict, &gallery_info))
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      known_galleries_[gallery_info.pref_id] = gallery_info;
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      device_map_[gallery_info.device_id].insert(gallery_info.pref_id);
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaGalleriesPreferences::AddGalleryChangeObserver(
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GalleryChangeObserver* observer) {
5984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gallery_change_observers_.AddObserver(observer);
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaGalleriesPreferences::RemoveGalleryChangeObserver(
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GalleryChangeObserver* observer) {
6044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gallery_change_observers_.RemoveObserver(observer);
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaGalleriesPreferences::OnRemovableStorageAttached(
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StorageInfo& info) {
6104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
61190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!StorageInfo::IsMediaDevice(info.device_id()))
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AddGallery(info.device_id(), base::FilePath(),
6157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)             false /*not user added*/,
6167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)             info.storage_label(),
6177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)             info.vendor_name(),
6187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)             info.model_name(),
6197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)             info.total_size_in_bytes(),
6207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)             base::Time::Now());
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MediaGalleriesPreferences::LookUpGalleryByPath(
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path,
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaGalleryPrefInfo* gallery_info) const {
6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StorageInfo info;
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath relative_path;
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!MediaStorageUtil::GetDeviceInfoFromPath(path, &info, &relative_path)) {
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (gallery_info)
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *gallery_info = MediaGalleryPrefInfo();
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  relative_path = relative_path.NormalizePathSeparators();
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaGalleryPrefIdSet galleries_on_device =
63790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      LookUpGalleriesByDeviceId(info.device_id());
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (MediaGalleryPrefIdSet::const_iterator it = galleries_on_device.begin();
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != galleries_on_device.end();
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const MediaGalleryPrefInfo& gallery = known_galleries_.find(*it)->second;
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (gallery.path != relative_path)
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (gallery_info)
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *gallery_info = gallery;
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This method is called by controller::FilesSelected when the user
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // adds a new gallery. Control reaches here when the selected gallery is
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // on a volume we know about, but have no gallery already for. Returns
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // hypothetical data to the caller about what the prefs will look like
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if the gallery is added.
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(gbillock): split this out into another function so it doesn't
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // conflate LookUp.
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (gallery_info) {
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gallery_info->pref_id = kInvalidMediaGalleryPrefId;
65990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    gallery_info->device_id = info.device_id();
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gallery_info->path = relative_path;
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gallery_info->type = MediaGalleryPrefInfo::kUserAdded;
6627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    gallery_info->volume_label = info.storage_label();
6637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    gallery_info->vendor_name = info.vendor_name();
6647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    gallery_info->model_name = info.model_name();
6657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    gallery_info->total_size_in_bytes = info.total_size_in_bytes();
6667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    gallery_info->last_attach_time = base::Time::Now();
6677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    gallery_info->volume_metadata_valid = true;
6687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    gallery_info->prefs_version = 2;
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaGalleryPrefIdSet MediaGalleriesPreferences::LookUpGalleriesByDeviceId(
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& device_id) const {
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeviceIdPrefIdsMap::const_iterator found = device_map_.find(device_id);
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (found == device_map_.end())
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MediaGalleryPrefIdSet();
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return found->second;
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath MediaGalleriesPreferences::LookUpGalleryPathForExtension(
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaGalleryPrefId gallery_id,
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const extensions::Extension* extension,
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool include_unpermitted_galleries) {
6854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(extension);
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!include_unpermitted_galleries &&
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !ContainsKey(GalleriesForExtension(*extension), gallery_id))
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::FilePath();
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaGalleriesPrefInfoMap::const_iterator it =
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      known_galleries_.find(gallery_id);
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it == known_galleries_.end())
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::FilePath();
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return MediaStorageUtil::FindDevicePathById(it->second.device_id);
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaGalleryPrefId MediaGalleriesPreferences::AddGallery(
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& device_id,
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& relative_path, bool user_added,
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const string16& volume_label, const string16& vendor_name,
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const string16& model_name, uint64 total_size_in_bytes,
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Time last_attach_time) {
7044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return AddGalleryInternal(device_id, string16(), relative_path, user_added,
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            volume_label, vendor_name, model_name,
7077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                            total_size_in_bytes, last_attach_time, true, 2);
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaGalleryPrefId MediaGalleriesPreferences::AddGalleryInternal(
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& device_id, const string16& display_name,
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& relative_path, bool user_added,
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const string16& volume_label, const string16& vendor_name,
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const string16& model_name, uint64 total_size_in_bytes,
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Time last_attach_time,
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool volume_metadata_valid,
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int prefs_version) {
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath normalized_relative_path =
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      relative_path.NormalizePathSeparators();
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaGalleryPrefIdSet galleries_on_device =
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LookUpGalleriesByDeviceId(device_id);
722d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (MediaGalleryPrefIdSet::const_iterator pref_id_it =
723d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)           galleries_on_device.begin();
724d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)       pref_id_it != galleries_on_device.end();
725d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)       ++pref_id_it) {
726d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const MediaGalleryPrefInfo& existing =
727d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        known_galleries_.find(*pref_id_it)->second;
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (existing.path != normalized_relative_path)
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool update_gallery_type =
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        user_added && (existing.type == MediaGalleryPrefInfo::kBlackListed);
73390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Status quo: In M27 and M28, galleries added manually use version 0,
73490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // and galleries added automatically (including default galleries) use
73590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // version 1. The name override is used by default galleries as well
73690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // as all device attach events.
7377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // We want to upgrade the name if the existing version is < 2. Leave it
7387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // alone if the existing display name is set with version == 2 and the
7397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // proposed new name is empty.
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool update_gallery_name = existing.display_name != display_name;
7417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (existing.prefs_version == 2 && !existing.display_name.empty() &&
7427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        display_name.empty()) {
7437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      update_gallery_name = false;
7447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool update_gallery_metadata = volume_metadata_valid &&
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ((existing.volume_label != volume_label) ||
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         (existing.vendor_name != vendor_name) ||
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         (existing.model_name != model_name) ||
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         (existing.total_size_in_bytes != total_size_in_bytes) ||
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         (existing.last_attach_time != last_attach_time));
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!update_gallery_name && !update_gallery_type &&
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        !update_gallery_metadata)
754d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return *pref_id_it;
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PrefService* prefs = profile_->GetPrefs();
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<ListPrefUpdate> update(
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new ListPrefUpdate(prefs, prefs::kMediaGalleriesRememberedGalleries));
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ListValue* list = update->Get();
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (ListValue::const_iterator list_iter = list->begin();
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         list_iter != list->end();
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++list_iter) {
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DictionaryValue* dict;
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MediaGalleryPrefId iter_id;
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if ((*list_iter)->GetAsDictionary(&dict) &&
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GetPrefId(*dict, &iter_id) &&
768d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          *pref_id_it == iter_id) {
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (update_gallery_type) {
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          dict->SetString(kMediaGalleriesTypeKey,
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          kMediaGalleriesTypeAutoDetectedValue);
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (update_gallery_name)
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          dict->SetString(kMediaGalleriesDisplayNameKey, display_name);
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (update_gallery_metadata) {
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          dict->SetString(kMediaGalleriesVolumeLabelKey, volume_label);
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          dict->SetString(kMediaGalleriesVendorNameKey, vendor_name);
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          dict->SetString(kMediaGalleriesModelNameKey, model_name);
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          dict->SetDouble(kMediaGalleriesSizeKey, total_size_in_bytes);
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          dict->SetDouble(kMediaGalleriesLastAttachTimeKey,
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          last_attach_time.ToInternalValue());
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dict->SetInteger(kMediaGalleriesPrefsVersionKey, prefs_version);
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Commits the prefs update.
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    update.reset();
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
791d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (update_gallery_name || update_gallery_metadata ||
792d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        update_gallery_type) {
793d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      InitFromPrefs();
794d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      FOR_EACH_OBSERVER(GalleryChangeObserver,
795d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                        gallery_change_observers_,
796d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                        OnGalleryInfoUpdated(this, *pref_id_it));
797d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
798d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return *pref_id_it;
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrefService* prefs = profile_->GetPrefs();
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaGalleryPrefInfo gallery_info;
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gallery_info.pref_id = prefs->GetUint64(prefs::kMediaGalleriesUniqueId);
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prefs->SetUint64(prefs::kMediaGalleriesUniqueId, gallery_info.pref_id + 1);
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gallery_info.display_name = display_name;
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gallery_info.device_id = device_id;
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gallery_info.path = normalized_relative_path;
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gallery_info.type = MediaGalleryPrefInfo::kAutoDetected;
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (user_added)
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gallery_info.type = MediaGalleryPrefInfo::kUserAdded;
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (volume_metadata_valid) {
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gallery_info.volume_label = volume_label;
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gallery_info.vendor_name = vendor_name;
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gallery_info.model_name = model_name;
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gallery_info.total_size_in_bytes = total_size_in_bytes;
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gallery_info.last_attach_time = last_attach_time;
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gallery_info.volume_metadata_valid = volume_metadata_valid;
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gallery_info.prefs_version = prefs_version;
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ListPrefUpdate update(prefs, prefs::kMediaGalleriesRememberedGalleries);
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ListValue* list = update.Get();
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    list->Append(CreateGalleryPrefInfoDictionary(gallery_info));
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
827d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  InitFromPrefs();
828d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FOR_EACH_OBSERVER(GalleryChangeObserver,
829d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    gallery_change_observers_,
830d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    OnGalleryAdded(this, gallery_info.pref_id));
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gallery_info.pref_id;
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaGalleryPrefId MediaGalleriesPreferences::AddGalleryByPath(
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path) {
8374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaGalleryPrefInfo gallery_info;
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (LookUpGalleryByPath(path, &gallery_info) &&
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gallery_info.type != MediaGalleryPrefInfo::kBlackListed) {
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gallery_info.pref_id;
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return AddGalleryInternal(gallery_info.device_id,
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            gallery_info.display_name,
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            gallery_info.path,
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            true /*user added*/,
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            gallery_info.volume_label,
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            gallery_info.vendor_name,
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            gallery_info.model_name,
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            gallery_info.total_size_in_bytes,
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            gallery_info.last_attach_time,
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            gallery_info.volume_metadata_valid,
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            gallery_info.prefs_version);
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaGalleriesPreferences::ForgetGalleryById(MediaGalleryPrefId pref_id) {
8574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrefService* prefs = profile_->GetPrefs();
859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ListPrefUpdate> update(new ListPrefUpdate(
860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs, prefs::kMediaGalleriesRememberedGalleries));
861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ListValue* list = update->Get();
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ContainsKey(known_galleries_, pref_id))
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ListValue::iterator iter = list->begin(); iter != list->end(); ++iter) {
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DictionaryValue* dict;
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaGalleryPrefId iter_id;
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->GetAsDictionary(&dict) && GetPrefId(*dict, &iter_id) &&
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pref_id == iter_id) {
871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      RemoveGalleryPermissionsFromPrefs(pref_id);
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MediaGalleryPrefInfo::Type type;
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (GetType(*dict, &type) &&
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          type == MediaGalleryPrefInfo::kAutoDetected) {
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dict->SetString(kMediaGalleriesTypeKey,
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        kMediaGalleriesTypeBlackListedValue);
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        list->Erase(iter, NULL);
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      update.reset(NULL);  // commits the update.
881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
882d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      InitFromPrefs();
883d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      FOR_EACH_OBSERVER(GalleryChangeObserver,
884d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                        gallery_change_observers_,
885d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                        OnGalleryRemoved(this, pref_id));
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MediaGalleryPrefIdSet MediaGalleriesPreferences::GalleriesForExtension(
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const extensions::Extension& extension) const {
8934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaGalleryPrefIdSet result;
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (HasAutoDetectedGalleryPermission(extension)) {
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (MediaGalleriesPrefInfoMap::const_iterator it =
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             known_galleries_.begin(); it != known_galleries_.end(); ++it) {
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (it->second.type == MediaGalleryPrefInfo::kAutoDetected)
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        result.insert(it->second.pref_id);
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<MediaGalleryPermission> stored_permissions =
905868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      GetGalleryPermissionsFromPrefs(extension.id());
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<MediaGalleryPermission>::const_iterator it =
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           stored_permissions.begin(); it != stored_permissions.end(); ++it) {
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!it->has_permission) {
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result.erase(it->pref_id);
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MediaGalleriesPrefInfoMap::const_iterator gallery =
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          known_galleries_.find(it->pref_id);
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(gallery != known_galleries_.end());
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (gallery->second.type != MediaGalleryPrefInfo::kBlackListed) {
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        result.insert(it->pref_id);
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        NOTREACHED() << gallery->second.device_id;
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result;
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool MediaGalleriesPreferences::SetGalleryPermissionForExtension(
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const extensions::Extension& extension,
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaGalleryPrefId pref_id,
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool has_permission) {
9284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The gallery may not exist anymore if the user opened a second config
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // surface concurrently and removed it. Drop the permission update if so.
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaGalleriesPrefInfoMap::const_iterator gallery_info =
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      known_galleries_.find(pref_id);
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (gallery_info == known_galleries_.end())
93468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
936d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool default_permission = false;
937d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (gallery_info->second.type == MediaGalleryPrefInfo::kAutoDetected)
938d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    default_permission = HasAutoDetectedGalleryPermission(extension);
939d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // When the permission matches the default, we don't need to remember it.
940d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (has_permission == default_permission) {
941d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!UnsetGalleryPermissionInPrefs(extension.id(), pref_id))
942d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // If permission wasn't set, assume nothing has changed.
94368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return false;
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
945d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!SetGalleryPermissionInPrefs(extension.id(), pref_id, has_permission))
94668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return false;
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
948d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (has_permission)
949d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    FOR_EACH_OBSERVER(GalleryChangeObserver,
950d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                      gallery_change_observers_,
951d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                      OnPermissionAdded(this, extension.id(), pref_id));
952d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  else
953d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    FOR_EACH_OBSERVER(GalleryChangeObserver,
954d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                      gallery_change_observers_,
955d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                      OnPermissionRemoved(this, extension.id(), pref_id));
95668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return true;
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const MediaGalleriesPrefInfoMap& MediaGalleriesPreferences::known_galleries()
9604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const {
9614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
9624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return known_galleries_;
9634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
9644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaGalleriesPreferences::Shutdown() {
966c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_ = NULL;
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MediaGalleriesPreferences::APIHasBeenUsed(Profile* profile) {
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaGalleryPrefId current_id =
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile->GetPrefs()->GetUint64(prefs::kMediaGalleriesUniqueId);
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return current_id != kInvalidMediaGalleryPrefId + 1;
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
9787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MediaGalleriesPreferences::RegisterProfilePrefs(
979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registry->RegisterListPref(prefs::kMediaGalleriesRememberedGalleries,
981c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
982c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterUint64Pref(
983c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kMediaGalleriesUniqueId,
984c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kInvalidMediaGalleryPrefId + 1,
985c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
9862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
988d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool MediaGalleriesPreferences::SetGalleryPermissionInPrefs(
989868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& extension_id,
990868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    MediaGalleryPrefId gallery_id,
991868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool has_access) {
9924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
993868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionPrefs::ScopedListUpdate update(GetExtensionPrefs(),
994868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          extension_id,
995868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          kMediaGalleriesPermissions);
996868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ListValue* permissions = update.Get();
997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!permissions) {
998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    permissions = update.Create();
999868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1000868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // If the gallery is already in the list, update the permission...
1001868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (ListValue::iterator iter = permissions->begin();
1002868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         iter != permissions->end(); ++iter) {
1003868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DictionaryValue* dict = NULL;
1004868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!(*iter)->GetAsDictionary(&dict))
1005868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        continue;
1006868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      MediaGalleryPermission perm;
1007868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!GetMediaGalleryPermissionFromDictionary(dict, &perm))
1008868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        continue;
1009868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (perm.pref_id == gallery_id) {
1010d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (has_access != perm.has_permission) {
1011d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          dict->SetBoolean(kMediaGalleryHasPermissionKey, has_access);
1012d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          return true;
1013d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        } else {
1014d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          return false;
1015d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
1016868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
1017868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1018868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1019868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // ...Otherwise, add a new entry for the gallery.
1020868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DictionaryValue* dict = new DictionaryValue;
1021868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  dict->SetString(kMediaGalleryIdKey, base::Uint64ToString(gallery_id));
1022868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  dict->SetBoolean(kMediaGalleryHasPermissionKey, has_access);
1023868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  permissions->Append(dict);
1024d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return true;
1025868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1026868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1027d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool MediaGalleriesPreferences::UnsetGalleryPermissionInPrefs(
1028868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& extension_id,
1029868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    MediaGalleryPrefId gallery_id) {
10304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
1031868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionPrefs::ScopedListUpdate update(GetExtensionPrefs(),
1032868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          extension_id,
1033868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          kMediaGalleriesPermissions);
1034868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ListValue* permissions = update.Get();
1035868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!permissions)
1036d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return false;
1037868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1038868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (ListValue::iterator iter = permissions->begin();
1039868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       iter != permissions->end(); ++iter) {
1040868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const DictionaryValue* dict = NULL;
1041868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!(*iter)->GetAsDictionary(&dict))
1042868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
1043868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    MediaGalleryPermission perm;
1044868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!GetMediaGalleryPermissionFromDictionary(dict, &perm))
1045868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
1046868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (perm.pref_id == gallery_id) {
1047868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      permissions->Erase(iter, NULL);
1048d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return true;
1049868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1050868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1051d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return false;
1052868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1053868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1054868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::vector<MediaGalleryPermission>
1055868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)MediaGalleriesPreferences::GetGalleryPermissionsFromPrefs(
1056868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& extension_id) const {
10574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
1058868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<MediaGalleryPermission> result;
1059868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const ListValue* permissions;
1060868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!GetExtensionPrefs()->ReadPrefAsList(extension_id,
1061868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           kMediaGalleriesPermissions,
1062868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           &permissions)) {
1063868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return result;
1064868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1065868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1066868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (ListValue::const_iterator iter = permissions->begin();
1067868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       iter != permissions->end(); ++iter) {
1068868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DictionaryValue* dict = NULL;
1069868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!(*iter)->GetAsDictionary(&dict))
1070868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
1071868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    MediaGalleryPermission perm;
1072868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!GetMediaGalleryPermissionFromDictionary(dict, &perm))
1073868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
1074868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    result.push_back(perm);
1075868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1076868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1077868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
1078868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1079868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1080868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MediaGalleriesPreferences::RemoveGalleryPermissionsFromPrefs(
1081868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    MediaGalleryPrefId gallery_id) {
10824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
1083868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionPrefs* prefs = GetExtensionPrefs();
1084868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const DictionaryValue* extensions =
10853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      prefs->pref_service()->GetDictionary(prefs::kExtensionsPref);
1086868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!extensions)
1087868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1088868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1089868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (DictionaryValue::Iterator iter(*extensions); !iter.IsAtEnd();
1090868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       iter.Advance()) {
1091868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!extensions::Extension::IdIsValid(iter.key())) {
1092868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      NOTREACHED();
1093868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
1094868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1095868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    UnsetGalleryPermissionInPrefs(iter.key(), gallery_id);
1096868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1097868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1098868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1099868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ExtensionPrefs* MediaGalleriesPreferences::GetExtensionPrefs() const {
11004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
1101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (extension_prefs_for_testing_)
1102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return extension_prefs_for_testing_;
1103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return extensions::ExtensionPrefs::Get(profile_);
1104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MediaGalleriesPreferences::SetExtensionPrefsForTesting(
1107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    extensions::ExtensionPrefs* extension_prefs) {
11084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(IsInitialized());
1109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  extension_prefs_for_testing_ = extension_prefs;
11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1111