// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/media_galleries/media_galleries_preferences.h"

#include "base/base_paths_posix.h"
#include "base/callback.h"
#include "base/i18n/time_formatting.h"
#include "base/path_service.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/media_galleries/fileapi/iapps_finder.h"
#include "chrome/browser/media_galleries/fileapi/picasa_finder.h"
#include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
#include "chrome/browser/media_galleries/media_file_system_registry.h"
#include "chrome/browser/media_galleries/media_galleries_histograms.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/storage_monitor/media_storage_util.h"
#include "components/storage_monitor/storage_monitor.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/permissions/api_permission.h"
#include "extensions/common/permissions/media_galleries_permission.h"
#include "extensions/common/permissions/permissions_data.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

using base::DictionaryValue;
using base::ListValue;
using extensions::ExtensionPrefs;
using storage_monitor::MediaStorageUtil;
using storage_monitor::StorageInfo;
using storage_monitor::StorageMonitor;

namespace {

// Pref key for the list of media gallery permissions.
const char kMediaGalleriesPermissions[] = "media_galleries_permissions";
// Pref key for Media Gallery ID.
const char kMediaGalleryIdKey[] = "id";
// Pref key for Media Gallery Permission Value.
const char kMediaGalleryHasPermissionKey[] = "has_permission";

const char kMediaGalleriesDeviceIdKey[] = "deviceId";
const char kMediaGalleriesDisplayNameKey[] = "displayName";
const char kMediaGalleriesPathKey[] = "path";
const char kMediaGalleriesPrefIdKey[] = "prefId";
const char kMediaGalleriesTypeKey[] = "type";
const char kMediaGalleriesVolumeLabelKey[] = "volumeLabel";
const char kMediaGalleriesVendorNameKey[] = "vendorName";
const char kMediaGalleriesModelNameKey[] = "modelName";
const char kMediaGalleriesSizeKey[] = "totalSize";
const char kMediaGalleriesLastAttachTimeKey[] = "lastAttachTime";
const char kMediaGalleriesScanAudioCountKey[] = "audioCount";
const char kMediaGalleriesScanImageCountKey[] = "imageCount";
const char kMediaGalleriesScanVideoCountKey[] = "videoCount";
const char kMediaGalleriesPrefsVersionKey[] = "preferencesVersion";

const char kMediaGalleriesTypeAutoDetectedValue[] = "autoDetected";
const char kMediaGalleriesTypeBlackListedValue[] = "blackListed";
const char kMediaGalleriesTypeRemovedScanValue[] = "removedScan";
const char kMediaGalleriesTypeScanResultValue[] = "scanResult";
const char kMediaGalleriesTypeUserAddedValue[] = "userAdded";

const char kIPhotoGalleryName[] = "iPhoto";
const char kITunesGalleryName[] = "iTunes";
const char kPicasaGalleryName[] = "Picasa";

const int kCurrentPrefsVersion = 2;

int NumberExtensionsUsingMediaGalleries(Profile* profile) {
  int count = 0;
  if (!profile)
    return count;
  ExtensionService* extension_service =
      extensions::ExtensionSystem::Get(profile)->extension_service();
  if (!extension_service)
    return count;

  const extensions::ExtensionSet* extensions = extension_service->extensions();
  for (extensions::ExtensionSet::const_iterator i = extensions->begin();
       i != extensions->end(); ++i) {
    const extensions::PermissionsData* permissions_data =
        (*i)->permissions_data();
    if (permissions_data->HasAPIPermission(
            extensions::APIPermission::kMediaGalleries) ||
        permissions_data->HasAPIPermission(
            extensions::APIPermission::kMediaGalleriesPrivate)) {
      count++;
    }
  }
  return count;
}

bool GetPrefId(const base::DictionaryValue& dict, MediaGalleryPrefId* value) {
  std::string string_id;
  if (!dict.GetString(kMediaGalleriesPrefIdKey, &string_id) ||
      !base::StringToUint64(string_id, value)) {
    return false;
  }

  return true;
}

bool GetType(const base::DictionaryValue& dict,
             MediaGalleryPrefInfo::Type* type) {
  std::string string_type;
  if (!dict.GetString(kMediaGalleriesTypeKey, &string_type))
    return false;

  if (string_type == kMediaGalleriesTypeUserAddedValue) {
    *type = MediaGalleryPrefInfo::kUserAdded;
    return true;
  }
  if (string_type == kMediaGalleriesTypeAutoDetectedValue) {
    *type = MediaGalleryPrefInfo::kAutoDetected;
    return true;
  }
  if (string_type == kMediaGalleriesTypeBlackListedValue) {
    *type = MediaGalleryPrefInfo::kBlackListed;
    return true;
  }
  if (string_type == kMediaGalleriesTypeScanResultValue) {
    *type = MediaGalleryPrefInfo::kScanResult;
    return true;
  }
  if (string_type == kMediaGalleriesTypeRemovedScanValue) {
    *type = MediaGalleryPrefInfo::kRemovedScan;
    return true;
  }

  return false;
}

const char* TypeToStringValue(MediaGalleryPrefInfo::Type type) {
  const char* result = NULL;
  switch (type) {
    case MediaGalleryPrefInfo::kUserAdded:
      result = kMediaGalleriesTypeUserAddedValue;
      break;
    case MediaGalleryPrefInfo::kAutoDetected:
      result = kMediaGalleriesTypeAutoDetectedValue;
      break;
    case MediaGalleryPrefInfo::kBlackListed:
      result = kMediaGalleriesTypeBlackListedValue;
      break;
    case MediaGalleryPrefInfo::kScanResult:
      result = kMediaGalleriesTypeScanResultValue;
      break;
    case MediaGalleryPrefInfo::kRemovedScan:
      result = kMediaGalleriesTypeRemovedScanValue;
      break;
    default:
      NOTREACHED();
      break;
  }
  return result;
}

bool PopulateGalleryPrefInfoFromDictionary(
    const base::DictionaryValue& dict, MediaGalleryPrefInfo* out_gallery_info) {
  MediaGalleryPrefId pref_id;
  base::string16 display_name;
  std::string device_id;
  base::FilePath::StringType path;
  MediaGalleryPrefInfo::Type type = MediaGalleryPrefInfo::kInvalidType;
  base::string16 volume_label;
  base::string16 vendor_name;
  base::string16 model_name;
  double total_size_in_bytes = 0.0;
  double last_attach_time = 0.0;
  bool volume_metadata_valid = false;
  int audio_count = 0;
  int image_count = 0;
  int video_count = 0;
  int prefs_version = 0;

  if (!GetPrefId(dict, &pref_id) ||
      !dict.GetString(kMediaGalleriesDeviceIdKey, &device_id) ||
      !dict.GetString(kMediaGalleriesPathKey, &path) ||
      !GetType(dict, &type)) {
    return false;
  }

  dict.GetString(kMediaGalleriesDisplayNameKey, &display_name);
  dict.GetInteger(kMediaGalleriesPrefsVersionKey, &prefs_version);

  if (dict.GetString(kMediaGalleriesVolumeLabelKey, &volume_label) &&
      dict.GetString(kMediaGalleriesVendorNameKey, &vendor_name) &&
      dict.GetString(kMediaGalleriesModelNameKey, &model_name) &&
      dict.GetDouble(kMediaGalleriesSizeKey, &total_size_in_bytes) &&
      dict.GetDouble(kMediaGalleriesLastAttachTimeKey, &last_attach_time)) {
    volume_metadata_valid = true;
  }

  if (dict.GetInteger(kMediaGalleriesScanAudioCountKey, &audio_count) &&
      dict.GetInteger(kMediaGalleriesScanImageCountKey, &image_count) &&
      dict.GetInteger(kMediaGalleriesScanVideoCountKey, &video_count)) {
    out_gallery_info->audio_count = audio_count;
    out_gallery_info->image_count = image_count;
    out_gallery_info->video_count = video_count;
  } else {
    out_gallery_info->audio_count = 0;
    out_gallery_info->image_count = 0;
    out_gallery_info->video_count = 0;
  }

  out_gallery_info->pref_id = pref_id;
  out_gallery_info->display_name = display_name;
  out_gallery_info->device_id = device_id;
  out_gallery_info->path = base::FilePath(path);
  out_gallery_info->type = type;
  out_gallery_info->volume_label = volume_label;
  out_gallery_info->vendor_name = vendor_name;
  out_gallery_info->model_name = model_name;
  out_gallery_info->total_size_in_bytes = total_size_in_bytes;
  out_gallery_info->last_attach_time =
      base::Time::FromInternalValue(last_attach_time);
  out_gallery_info->volume_metadata_valid = volume_metadata_valid;
  out_gallery_info->prefs_version = prefs_version;

  return true;
}

base::DictionaryValue* CreateGalleryPrefInfoDictionary(
    const MediaGalleryPrefInfo& gallery) {
  base::DictionaryValue* dict = new base::DictionaryValue();
  dict->SetString(kMediaGalleriesPrefIdKey,
                  base::Uint64ToString(gallery.pref_id));
  dict->SetString(kMediaGalleriesDeviceIdKey, gallery.device_id);
  dict->SetString(kMediaGalleriesPathKey, gallery.path.value());
  dict->SetString(kMediaGalleriesTypeKey, TypeToStringValue(gallery.type));

  if (gallery.volume_metadata_valid) {
    dict->SetString(kMediaGalleriesVolumeLabelKey, gallery.volume_label);
    dict->SetString(kMediaGalleriesVendorNameKey, gallery.vendor_name);
    dict->SetString(kMediaGalleriesModelNameKey, gallery.model_name);
    dict->SetDouble(kMediaGalleriesSizeKey, gallery.total_size_in_bytes);
    dict->SetDouble(kMediaGalleriesLastAttachTimeKey,
                    gallery.last_attach_time.ToInternalValue());
  } else {
    dict->SetString(kMediaGalleriesDisplayNameKey, gallery.display_name);
  }

  if (gallery.audio_count || gallery.image_count || gallery.video_count) {
    dict->SetInteger(kMediaGalleriesScanAudioCountKey, gallery.audio_count);
    dict->SetInteger(kMediaGalleriesScanImageCountKey, gallery.image_count);
    dict->SetInteger(kMediaGalleriesScanVideoCountKey, gallery.video_count);
  }

  // Version 0 of the prefs format was that the display_name was always
  // used to show the user-visible name of the gallery. Version 1 means
  // that there is an optional display_name, and when it is present, it
  // overrides the name that would be built from the volume metadata, path,
  // or whatever other data. So if we see a display_name with version 0, it
  // means it may be overwritten simply by getting new volume metadata.
  // A display_name with version 1 should not be overwritten.
  dict->SetInteger(kMediaGalleriesPrefsVersionKey, gallery.prefs_version);

  return dict;
}

bool HasAutoDetectedGalleryPermission(const extensions::Extension& extension) {
  extensions::MediaGalleriesPermission::CheckParam param(
      extensions::MediaGalleriesPermission::kAllAutoDetectedPermission);
  return extension.permissions_data()->CheckAPIPermissionWithParam(
      extensions::APIPermission::kMediaGalleries, &param);
}

// Retrieves the MediaGalleryPermission from the given dictionary; DCHECKs on
// failure.
bool GetMediaGalleryPermissionFromDictionary(
    const base::DictionaryValue* dict,
    MediaGalleryPermission* out_permission) {
  std::string string_id;
  if (dict->GetString(kMediaGalleryIdKey, &string_id) &&
      base::StringToUint64(string_id, &out_permission->pref_id) &&
      dict->GetBoolean(kMediaGalleryHasPermissionKey,
                       &out_permission->has_permission)) {
    return true;
  }
  NOTREACHED();
  return false;
}

// For a device with |device_name| and a relative path |sub_folder|, construct
// a display name. If |sub_folder| is empty, then just return |device_name|.
base::string16 GetDisplayNameForSubFolder(const base::string16& device_name,
                                          const base::FilePath& sub_folder) {
  if (sub_folder.empty())
    return device_name;
  return (sub_folder.BaseName().LossyDisplayName() +
          base::ASCIIToUTF16(" - ") +
          device_name);
}

void InitializeImportedMediaGalleryRegistryOnFileThread() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
  ImportedMediaGalleryRegistry::GetInstance()->Initialize();
}

}  // namespace

MediaGalleryPrefInfo::MediaGalleryPrefInfo()
    : pref_id(kInvalidMediaGalleryPrefId),
      type(kInvalidType),
      total_size_in_bytes(0),
      volume_metadata_valid(false),
      audio_count(0),
      image_count(0),
      video_count(0),
      prefs_version(0) {
}

MediaGalleryPrefInfo::~MediaGalleryPrefInfo() {}

base::FilePath MediaGalleryPrefInfo::AbsolutePath() const {
  base::FilePath base_path = MediaStorageUtil::FindDevicePathById(device_id);
  DCHECK(!path.IsAbsolute());
  return base_path.empty() ? base_path : base_path.Append(path);
}

bool MediaGalleryPrefInfo::IsBlackListedType() const {
  return type == kBlackListed || type == kRemovedScan;
}

base::string16 MediaGalleryPrefInfo::GetGalleryDisplayName() const {
  if (!StorageInfo::IsRemovableDevice(device_id)) {
    // For fixed storage, the default name is the fully qualified directory
    // name, or in the case of a root directory, the root directory name.
    // Exception: ChromeOS -- the full pathname isn't visible there, so only
    // the directory name is used.
    base::FilePath path = AbsolutePath();
    if (!display_name.empty())
      return display_name;

#if defined(OS_CHROMEOS)
    // See chrome/browser/chromeos/fileapi/file_system_backend.cc
    base::FilePath download_path;
    if (PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS_SAFE, &download_path)) {
      base::FilePath relative;
      if (download_path.AppendRelativePath(path, &relative))
        return relative.LossyDisplayName();
    }
    return path.BaseName().LossyDisplayName();
#else
    return path.LossyDisplayName();
#endif
  }

  StorageInfo info(device_id,
                   MediaStorageUtil::FindDevicePathById(device_id).value(),
                   volume_label, vendor_name, model_name, total_size_in_bytes);
  base::string16 name = info.GetDisplayNameWithOverride(display_name, true);
  if (!path.empty())
    name = GetDisplayNameForSubFolder(name, path);
  return name;
}

base::string16 MediaGalleryPrefInfo::GetGalleryTooltip() const {
  return AbsolutePath().LossyDisplayName();
}

base::string16 MediaGalleryPrefInfo::GetGalleryAdditionalDetails() const {
  base::string16 attached;
  if (StorageInfo::IsRemovableDevice(device_id)) {
    if (MediaStorageUtil::IsRemovableStorageAttached(device_id)) {
      attached = l10n_util::GetStringUTF16(
          IDS_MEDIA_GALLERIES_DIALOG_DEVICE_ATTACHED);
    } else if (!last_attach_time.is_null()) {
      attached = l10n_util::GetStringFUTF16(
          IDS_MEDIA_GALLERIES_LAST_ATTACHED,
          base::TimeFormatShortDateNumeric(last_attach_time));
    } else {
      attached = l10n_util::GetStringUTF16(
          IDS_MEDIA_GALLERIES_DIALOG_DEVICE_NOT_ATTACHED);
    }
  }

  return attached;
}

bool MediaGalleryPrefInfo::IsGalleryAvailable() const {
  return !StorageInfo::IsRemovableDevice(device_id) ||
         MediaStorageUtil::IsRemovableStorageAttached(device_id);
}

MediaGalleriesPreferences::GalleryChangeObserver::~GalleryChangeObserver() {}

MediaGalleriesPreferences::MediaGalleriesPreferences(Profile* profile)
    : initialized_(false),
      pre_initialization_callbacks_waiting_(0),
      profile_(profile),
      extension_prefs_for_testing_(NULL),
      weak_factory_(this) {
}

MediaGalleriesPreferences::~MediaGalleriesPreferences() {
  if (StorageMonitor::GetInstance())
    StorageMonitor::GetInstance()->RemoveObserver(this);
}

void MediaGalleriesPreferences::EnsureInitialized(base::Closure callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (IsInitialized()) {
    if (!callback.is_null())
      callback.Run();
    return;
  }

  on_initialize_callbacks_.push_back(callback);
  if (on_initialize_callbacks_.size() > 1)
    return;

  // This counter must match the number of async methods dispatched below.
  // It cannot be incremented inline with each callback, as some may return
  // synchronously, decrement the counter to 0, and prematurely trigger
  // FinishInitialization.
  pre_initialization_callbacks_waiting_ = 4;

  // Check whether we should be initializing -- are there any extensions that
  // are using media galleries?
  media_galleries::UsageCount(media_galleries::PREFS_INITIALIZED);
  if (NumberExtensionsUsingMediaGalleries(profile_) == 0) {
    media_galleries::UsageCount(media_galleries::PREFS_INITIALIZED_ERROR);
  }

  // We determine the freshness of the profile here, before any of the finders
  // return and add media galleries to it.
  StorageMonitor::GetInstance()->EnsureInitialized(
      base::Bind(&MediaGalleriesPreferences::OnStorageMonitorInit,
                 weak_factory_.GetWeakPtr(),
                 !APIHasBeenUsed(profile_) /* add_default_galleries */));

  // Look for optional default galleries every time.
  iapps::FindITunesLibrary(
      base::Bind(&MediaGalleriesPreferences::OnFinderDeviceID,
                 weak_factory_.GetWeakPtr()));

  picasa::FindPicasaDatabase(
      base::Bind(&MediaGalleriesPreferences::OnFinderDeviceID,
                 weak_factory_.GetWeakPtr()));

  iapps::FindIPhotoLibrary(
      base::Bind(&MediaGalleriesPreferences::OnFinderDeviceID,
                 weak_factory_.GetWeakPtr()));
}

bool MediaGalleriesPreferences::IsInitialized() const { return initialized_; }

Profile* MediaGalleriesPreferences::profile() { return profile_; }

void MediaGalleriesPreferences::OnInitializationCallbackReturned() {
  DCHECK(!IsInitialized());
  DCHECK_GT(pre_initialization_callbacks_waiting_, 0);
  if (--pre_initialization_callbacks_waiting_ == 0)
    FinishInitialization();
}

void MediaGalleriesPreferences::FinishInitialization() {
  DCHECK(!IsInitialized());

  initialized_ = true;

  StorageMonitor* monitor = StorageMonitor::GetInstance();
  DCHECK(monitor->IsInitialized());

  InitFromPrefs();

  StorageMonitor::GetInstance()->AddObserver(this);

  std::vector<StorageInfo> existing_devices =
      monitor->GetAllAvailableStorages();
  for (size_t i = 0; i < existing_devices.size(); i++) {
    if (!(StorageInfo::IsMediaDevice(existing_devices[i].device_id()) &&
          StorageInfo::IsRemovableDevice(existing_devices[i].device_id())))
      continue;
    AddGallery(existing_devices[i].device_id(),
               base::FilePath(),
               MediaGalleryPrefInfo::kAutoDetected,
               existing_devices[i].storage_label(),
               existing_devices[i].vendor_name(),
               existing_devices[i].model_name(),
               existing_devices[i].total_size_in_bytes(),
               base::Time::Now(), 0, 0, 0);
  }

  for (std::vector<base::Closure>::iterator iter =
           on_initialize_callbacks_.begin();
       iter != on_initialize_callbacks_.end();
       ++iter) {
    iter->Run();
  }
  on_initialize_callbacks_.clear();
}

void MediaGalleriesPreferences::AddDefaultGalleries() {
  const int kDirectoryKeys[] = {
    chrome::DIR_USER_MUSIC,
    chrome::DIR_USER_PICTURES,
    chrome::DIR_USER_VIDEOS,
  };

  for (size_t i = 0; i < arraysize(kDirectoryKeys); ++i) {
    base::FilePath path;
    if (!PathService::Get(kDirectoryKeys[i], &path))
      continue;

    base::FilePath relative_path;
    StorageInfo info;
    if (MediaStorageUtil::GetDeviceInfoFromPath(path, &info, &relative_path)) {
      AddGalleryInternal(info.device_id(), base::string16(), relative_path,
                         MediaGalleryPrefInfo::kAutoDetected,
                         info.storage_label(), info.vendor_name(),
                         info.model_name(), info.total_size_in_bytes(),
                         base::Time(), true, 0, 0, 0, kCurrentPrefsVersion);
    }
  }
}

bool MediaGalleriesPreferences::UpdateDeviceIDForSingletonType(
    const std::string& device_id) {
  StorageInfo::Type singleton_type;
  if (!StorageInfo::CrackDeviceId(device_id, &singleton_type, NULL))
    return false;

  PrefService* prefs = profile_->GetPrefs();
  scoped_ptr<ListPrefUpdate> update(new ListPrefUpdate(
      prefs, prefs::kMediaGalleriesRememberedGalleries));
  base::ListValue* list = update->Get();
  for (base::ListValue::iterator iter = list->begin();
       iter != list->end(); ++iter) {
    // All of these calls should succeed, but preferences file can be corrupt.
    base::DictionaryValue* dict;
    if (!(*iter)->GetAsDictionary(&dict))
      continue;
    std::string this_device_id;
    if (!dict->GetString(kMediaGalleriesDeviceIdKey, &this_device_id))
      continue;
    if (this_device_id == device_id)
      return true;  // No update is necessary.
    StorageInfo::Type device_type;
    if (!StorageInfo::CrackDeviceId(this_device_id, &device_type, NULL))
      continue;

    if (device_type == singleton_type) {
      dict->SetString(kMediaGalleriesDeviceIdKey, device_id);
      update.reset();  // commits the update.
      InitFromPrefs();
      MediaGalleryPrefId pref_id;
      if (GetPrefId(*dict, &pref_id)) {
        FOR_EACH_OBSERVER(GalleryChangeObserver,
                          gallery_change_observers_,
                          OnGalleryInfoUpdated(this, pref_id));
      }
      return true;
    }
  }
  return false;
}

void MediaGalleriesPreferences::OnStorageMonitorInit(
    bool add_default_galleries) {
  if (add_default_galleries)
    AddDefaultGalleries();
  OnInitializationCallbackReturned();
}

void MediaGalleriesPreferences::OnFinderDeviceID(const std::string& device_id) {
  if (!device_id.empty()) {
    std::string gallery_name;
    if (StorageInfo::IsIPhotoDevice(device_id))
      gallery_name = kIPhotoGalleryName;
    else if (StorageInfo::IsITunesDevice(device_id))
      gallery_name = kITunesGalleryName;
    else if (StorageInfo::IsPicasaDevice(device_id))
      gallery_name = kPicasaGalleryName;

    if (!gallery_name.empty()) {
      pre_initialization_callbacks_waiting_++;
      content::BrowserThread::PostTaskAndReply(
          content::BrowserThread::FILE,
          FROM_HERE,
          base::Bind(&InitializeImportedMediaGalleryRegistryOnFileThread),
          base::Bind(
              &MediaGalleriesPreferences::OnInitializationCallbackReturned,
              weak_factory_.GetWeakPtr()));
    }

    if (!UpdateDeviceIDForSingletonType(device_id)) {
      DCHECK(!gallery_name.empty());
      AddGalleryInternal(device_id, base::ASCIIToUTF16(gallery_name),
                         base::FilePath(), MediaGalleryPrefInfo::kAutoDetected,
                         base::string16(), base::string16(), base::string16(),
                         0, base::Time(), false, 0, 0, 0, kCurrentPrefsVersion);
    }
  }

  OnInitializationCallbackReturned();
}

void MediaGalleriesPreferences::InitFromPrefs() {
  known_galleries_.clear();
  device_map_.clear();

  PrefService* prefs = profile_->GetPrefs();
  const base::ListValue* list = prefs->GetList(
      prefs::kMediaGalleriesRememberedGalleries);
  if (list) {
    for (base::ListValue::const_iterator it = list->begin();
         it != list->end(); ++it) {
      const base::DictionaryValue* dict = NULL;
      if (!(*it)->GetAsDictionary(&dict))
        continue;

      MediaGalleryPrefInfo gallery_info;
      if (!PopulateGalleryPrefInfoFromDictionary(*dict, &gallery_info))
        continue;

      known_galleries_[gallery_info.pref_id] = gallery_info;
      device_map_[gallery_info.device_id].insert(gallery_info.pref_id);
    }
  }
}

void MediaGalleriesPreferences::AddGalleryChangeObserver(
    GalleryChangeObserver* observer) {
  DCHECK(IsInitialized());
  gallery_change_observers_.AddObserver(observer);
}

void MediaGalleriesPreferences::RemoveGalleryChangeObserver(
    GalleryChangeObserver* observer) {
  DCHECK(IsInitialized());
  gallery_change_observers_.RemoveObserver(observer);
}

void MediaGalleriesPreferences::OnRemovableStorageAttached(
    const StorageInfo& info) {
  DCHECK(IsInitialized());
  if (!StorageInfo::IsMediaDevice(info.device_id()))
    return;

  AddGallery(info.device_id(), base::FilePath(),
             MediaGalleryPrefInfo::kAutoDetected, info.storage_label(),
             info.vendor_name(), info.model_name(), info.total_size_in_bytes(),
             base::Time::Now(), 0, 0, 0);
}

bool MediaGalleriesPreferences::LookUpGalleryByPath(
    const base::FilePath& path,
    MediaGalleryPrefInfo* gallery_info) const {
  DCHECK(IsInitialized());

  // First check if the path matches an imported gallery.
  for (MediaGalleriesPrefInfoMap::const_iterator it =
           known_galleries_.begin(); it != known_galleries_.end(); ++it) {
    const std::string& device_id = it->second.device_id;
    if (iapps::PathIndicatesIPhotoLibrary(device_id, path) ||
        iapps::PathIndicatesITunesLibrary(device_id, path)) {
      *gallery_info = it->second;
      return true;
    }
  }

  StorageInfo info;
  base::FilePath relative_path;
  if (!MediaStorageUtil::GetDeviceInfoFromPath(path, &info, &relative_path)) {
    if (gallery_info)
      *gallery_info = MediaGalleryPrefInfo();
    return false;
  }

  relative_path = relative_path.NormalizePathSeparators();
  MediaGalleryPrefIdSet galleries_on_device =
      LookUpGalleriesByDeviceId(info.device_id());
  for (MediaGalleryPrefIdSet::const_iterator it = galleries_on_device.begin();
       it != galleries_on_device.end();
       ++it) {
    const MediaGalleryPrefInfo& gallery = known_galleries_.find(*it)->second;
    if (gallery.path != relative_path)
      continue;

    if (gallery_info)
      *gallery_info = gallery;
    return true;
  }

  // This method is called by controller::FilesSelected when the user
  // adds a new gallery. Control reaches here when the selected gallery is
  // on a volume we know about, but have no gallery already for. Returns
  // hypothetical data to the caller about what the prefs will look like
  // if the gallery is added.
  // TODO(gbillock): split this out into another function so it doesn't
  // conflate LookUp.
  if (gallery_info) {
    gallery_info->pref_id = kInvalidMediaGalleryPrefId;
    gallery_info->device_id = info.device_id();
    gallery_info->path = relative_path;
    gallery_info->type = MediaGalleryPrefInfo::kInvalidType;
    gallery_info->volume_label = info.storage_label();
    gallery_info->vendor_name = info.vendor_name();
    gallery_info->model_name = info.model_name();
    gallery_info->total_size_in_bytes = info.total_size_in_bytes();
    gallery_info->last_attach_time = base::Time::Now();
    gallery_info->volume_metadata_valid = true;
    gallery_info->prefs_version = kCurrentPrefsVersion;
  }
  return false;
}

MediaGalleryPrefIdSet MediaGalleriesPreferences::LookUpGalleriesByDeviceId(
    const std::string& device_id) const {
  DeviceIdPrefIdsMap::const_iterator found = device_map_.find(device_id);
  if (found == device_map_.end())
    return MediaGalleryPrefIdSet();
  return found->second;
}

base::FilePath MediaGalleriesPreferences::LookUpGalleryPathForExtension(
    MediaGalleryPrefId gallery_id,
    const extensions::Extension* extension,
    bool include_unpermitted_galleries) {
  DCHECK(IsInitialized());
  DCHECK(extension);
  if (!include_unpermitted_galleries &&
      !ContainsKey(GalleriesForExtension(*extension), gallery_id))
    return base::FilePath();

  MediaGalleriesPrefInfoMap::const_iterator it =
      known_galleries_.find(gallery_id);
  if (it == known_galleries_.end())
    return base::FilePath();
  return MediaStorageUtil::FindDevicePathById(it->second.device_id);
}

MediaGalleryPrefId MediaGalleriesPreferences::AddGallery(
    const std::string& device_id,
    const base::FilePath& relative_path,
    MediaGalleryPrefInfo::Type type,
    const base::string16& volume_label,
    const base::string16& vendor_name,
    const base::string16& model_name,
    uint64 total_size_in_bytes,
    base::Time last_attach_time,
    int audio_count,
    int image_count,
    int video_count) {
  DCHECK(IsInitialized());
  return AddGalleryInternal(device_id, base::string16(), relative_path,
                            type, volume_label, vendor_name, model_name,
                            total_size_in_bytes, last_attach_time, true,
                            audio_count, image_count, video_count,
                            kCurrentPrefsVersion);
}

MediaGalleryPrefId MediaGalleriesPreferences::AddGalleryInternal(
    const std::string& device_id, const base::string16& display_name,
    const base::FilePath& relative_path, MediaGalleryPrefInfo::Type type,
    const base::string16& volume_label, const base::string16& vendor_name,
    const base::string16& model_name, uint64 total_size_in_bytes,
    base::Time last_attach_time, bool volume_metadata_valid,
    int audio_count, int image_count, int video_count, int prefs_version) {
  DCHECK(type == MediaGalleryPrefInfo::kUserAdded ||
         type == MediaGalleryPrefInfo::kAutoDetected ||
         type == MediaGalleryPrefInfo::kScanResult);
  base::FilePath normalized_relative_path =
      relative_path.NormalizePathSeparators();
  MediaGalleryPrefIdSet galleries_on_device =
    LookUpGalleriesByDeviceId(device_id);
  for (MediaGalleryPrefIdSet::const_iterator pref_id_it =
           galleries_on_device.begin();
       pref_id_it != galleries_on_device.end();
       ++pref_id_it) {
    const MediaGalleryPrefInfo& existing =
        known_galleries_.find(*pref_id_it)->second;
    if (existing.path != normalized_relative_path)
      continue;

    bool update_gallery_type = false;
    MediaGalleryPrefInfo::Type new_type = existing.type;
    if (type == MediaGalleryPrefInfo::kUserAdded) {
      if (existing.type == MediaGalleryPrefInfo::kBlackListed) {
        new_type = MediaGalleryPrefInfo::kAutoDetected;
        update_gallery_type = true;
      }
      if (existing.type == MediaGalleryPrefInfo::kRemovedScan) {
        new_type = MediaGalleryPrefInfo::kUserAdded;
        update_gallery_type = true;
      }
    }

    // Status quo: In M27 and M28, galleries added manually use version 0,
    // and galleries added automatically (including default galleries) use
    // version 1. The name override is used by default galleries as well
    // as all device attach events.
    // We want to upgrade the name if the existing version is < 2. Leave it
    // alone if the existing display name is set with version == 2 and the
    // proposed new name is empty.
    bool update_gallery_name = existing.display_name != display_name;
    if (existing.prefs_version == 2 && !existing.display_name.empty() &&
        display_name.empty()) {
      update_gallery_name = false;
    }
    bool update_gallery_metadata = volume_metadata_valid &&
        ((existing.volume_label != volume_label) ||
         (existing.vendor_name != vendor_name) ||
         (existing.model_name != model_name) ||
         (existing.total_size_in_bytes != total_size_in_bytes) ||
         (existing.last_attach_time != last_attach_time));

    bool update_scan_counts =
      new_type != MediaGalleryPrefInfo::kRemovedScan &&
      new_type != MediaGalleryPrefInfo::kBlackListed &&
      (audio_count > 0 || image_count > 0 || video_count > 0 ||
       existing.audio_count || existing.image_count || existing.video_count);

    if (!update_gallery_name && !update_gallery_type &&
        !update_gallery_metadata && !update_scan_counts)
      return *pref_id_it;

    PrefService* prefs = profile_->GetPrefs();
    scoped_ptr<ListPrefUpdate> update(
        new ListPrefUpdate(prefs, prefs::kMediaGalleriesRememberedGalleries));
    base::ListValue* list = update->Get();

    for (base::ListValue::const_iterator list_iter = list->begin();
         list_iter != list->end();
         ++list_iter) {
      base::DictionaryValue* dict;
      MediaGalleryPrefId iter_id;
      if ((*list_iter)->GetAsDictionary(&dict) &&
          GetPrefId(*dict, &iter_id) &&
          *pref_id_it == iter_id) {
        if (update_gallery_type)
          dict->SetString(kMediaGalleriesTypeKey, TypeToStringValue(new_type));
        if (update_gallery_name)
          dict->SetString(kMediaGalleriesDisplayNameKey, display_name);
        if (update_gallery_metadata) {
          dict->SetString(kMediaGalleriesVolumeLabelKey, volume_label);
          dict->SetString(kMediaGalleriesVendorNameKey, vendor_name);
          dict->SetString(kMediaGalleriesModelNameKey, model_name);
          dict->SetDouble(kMediaGalleriesSizeKey, total_size_in_bytes);
          dict->SetDouble(kMediaGalleriesLastAttachTimeKey,
                          last_attach_time.ToInternalValue());
        }
        if (update_scan_counts) {
          dict->SetInteger(kMediaGalleriesScanAudioCountKey, audio_count);
          dict->SetInteger(kMediaGalleriesScanImageCountKey, image_count);
          dict->SetInteger(kMediaGalleriesScanVideoCountKey, video_count);
        }
        dict->SetInteger(kMediaGalleriesPrefsVersionKey, prefs_version);
        break;
      }
    }

    // Commits the prefs update.
    update.reset();

    InitFromPrefs();
    FOR_EACH_OBSERVER(GalleryChangeObserver, gallery_change_observers_,
                      OnGalleryInfoUpdated(this, *pref_id_it));
    return *pref_id_it;
  }

  PrefService* prefs = profile_->GetPrefs();

  MediaGalleryPrefInfo gallery_info;
  gallery_info.pref_id = prefs->GetUint64(prefs::kMediaGalleriesUniqueId);
  prefs->SetUint64(prefs::kMediaGalleriesUniqueId, gallery_info.pref_id + 1);
  gallery_info.display_name = display_name;
  gallery_info.device_id = device_id;
  gallery_info.path = normalized_relative_path;
  gallery_info.type = type;
  gallery_info.volume_label = volume_label;
  gallery_info.vendor_name = vendor_name;
  gallery_info.model_name = model_name;
  gallery_info.total_size_in_bytes = total_size_in_bytes;
  gallery_info.last_attach_time = last_attach_time;
  gallery_info.volume_metadata_valid = volume_metadata_valid;
  gallery_info.audio_count = audio_count;
  gallery_info.image_count = image_count;
  gallery_info.video_count = video_count;
  gallery_info.prefs_version = prefs_version;

  {
    ListPrefUpdate update(prefs, prefs::kMediaGalleriesRememberedGalleries);
    base::ListValue* list = update.Get();
    list->Append(CreateGalleryPrefInfoDictionary(gallery_info));
  }
  InitFromPrefs();
  FOR_EACH_OBSERVER(GalleryChangeObserver,
                    gallery_change_observers_,
                    OnGalleryAdded(this, gallery_info.pref_id));

  return gallery_info.pref_id;
}

MediaGalleryPrefId MediaGalleriesPreferences::AddGalleryByPath(
    const base::FilePath& path, MediaGalleryPrefInfo::Type type) {
  DCHECK(IsInitialized());
  MediaGalleryPrefInfo gallery_info;
  if (LookUpGalleryByPath(path, &gallery_info) &&
      !gallery_info.IsBlackListedType()) {
    return gallery_info.pref_id;
  }
  return AddGalleryInternal(gallery_info.device_id,
                            gallery_info.display_name,
                            gallery_info.path,
                            type,
                            gallery_info.volume_label,
                            gallery_info.vendor_name,
                            gallery_info.model_name,
                            gallery_info.total_size_in_bytes,
                            gallery_info.last_attach_time,
                            gallery_info.volume_metadata_valid,
                            0, 0, 0,
                            kCurrentPrefsVersion);
}

void MediaGalleriesPreferences::ForgetGalleryById(MediaGalleryPrefId id) {
  EraseOrBlacklistGalleryById(id, false);
}

void MediaGalleriesPreferences::EraseGalleryById(MediaGalleryPrefId id) {
  EraseOrBlacklistGalleryById(id, true);
}

void MediaGalleriesPreferences::EraseOrBlacklistGalleryById(
    MediaGalleryPrefId id, bool erase) {
  DCHECK(IsInitialized());
  PrefService* prefs = profile_->GetPrefs();
  scoped_ptr<ListPrefUpdate> update(new ListPrefUpdate(
      prefs, prefs::kMediaGalleriesRememberedGalleries));
  base::ListValue* list = update->Get();

  if (!ContainsKey(known_galleries_, id))
    return;

  for (base::ListValue::iterator iter = list->begin();
       iter != list->end(); ++iter) {
    base::DictionaryValue* dict;
    MediaGalleryPrefId iter_id;
    if ((*iter)->GetAsDictionary(&dict) && GetPrefId(*dict, &iter_id) &&
        id == iter_id) {
      RemoveGalleryPermissionsFromPrefs(id);
      MediaGalleryPrefInfo::Type type;
      if (!erase && GetType(*dict, &type) &&
          (type == MediaGalleryPrefInfo::kAutoDetected ||
           type == MediaGalleryPrefInfo::kScanResult)) {
        if (type == MediaGalleryPrefInfo::kAutoDetected) {
          dict->SetString(kMediaGalleriesTypeKey,
                          kMediaGalleriesTypeBlackListedValue);
        } else {
          dict->SetString(kMediaGalleriesTypeKey,
                          kMediaGalleriesTypeRemovedScanValue);
          dict->SetInteger(kMediaGalleriesScanAudioCountKey, 0);
          dict->SetInteger(kMediaGalleriesScanImageCountKey, 0);
          dict->SetInteger(kMediaGalleriesScanVideoCountKey, 0);
        }
      } else {
        list->Erase(iter, NULL);
      }
      update.reset(NULL);  // commits the update.

      InitFromPrefs();
      FOR_EACH_OBSERVER(GalleryChangeObserver,
                        gallery_change_observers_,
                        OnGalleryRemoved(this, id));
      return;
    }
  }
}

bool MediaGalleriesPreferences::NonAutoGalleryHasPermission(
    MediaGalleryPrefId id) const {
  DCHECK(IsInitialized());
  DCHECK(!ContainsKey(known_galleries_, id) ||
         known_galleries_.find(id)->second.type !=
             MediaGalleryPrefInfo::kAutoDetected);
  ExtensionPrefs* prefs = GetExtensionPrefs();
  const base::DictionaryValue* extensions =
      prefs->pref_service()->GetDictionary(extensions::pref_names::kExtensions);
  if (!extensions)
    return true;

  for (base::DictionaryValue::Iterator iter(*extensions); !iter.IsAtEnd();
       iter.Advance()) {
    if (!extensions::Extension::IdIsValid(iter.key())) {
      NOTREACHED();
      continue;
    }
    std::vector<MediaGalleryPermission> permissions =
        GetGalleryPermissionsFromPrefs(iter.key());
    for (std::vector<MediaGalleryPermission>::const_iterator it =
             permissions.begin(); it != permissions.end(); ++it) {
      if (it->pref_id == id) {
        if (it->has_permission)
          return true;
        break;
      }
    }
  }
  return false;
}

MediaGalleryPrefIdSet MediaGalleriesPreferences::GalleriesForExtension(
    const extensions::Extension& extension) const {
  DCHECK(IsInitialized());
  MediaGalleryPrefIdSet result;

  if (HasAutoDetectedGalleryPermission(extension)) {
    for (MediaGalleriesPrefInfoMap::const_iterator it =
             known_galleries_.begin(); it != known_galleries_.end(); ++it) {
      if (it->second.type == MediaGalleryPrefInfo::kAutoDetected)
        result.insert(it->second.pref_id);
    }
  }

  std::vector<MediaGalleryPermission> stored_permissions =
      GetGalleryPermissionsFromPrefs(extension.id());
  for (std::vector<MediaGalleryPermission>::const_iterator it =
           stored_permissions.begin(); it != stored_permissions.end(); ++it) {
    if (!it->has_permission) {
      result.erase(it->pref_id);
    } else {
      MediaGalleriesPrefInfoMap::const_iterator gallery =
          known_galleries_.find(it->pref_id);
      DCHECK(gallery != known_galleries_.end());
      if (!gallery->second.IsBlackListedType()) {
        result.insert(it->pref_id);
      } else {
        NOTREACHED() << gallery->second.device_id;
      }
    }
  }
  return result;
}

bool MediaGalleriesPreferences::SetGalleryPermissionForExtension(
    const extensions::Extension& extension,
    MediaGalleryPrefId pref_id,
    bool has_permission) {
  DCHECK(IsInitialized());
  // The gallery may not exist anymore if the user opened a second config
  // surface concurrently and removed it. Drop the permission update if so.
  MediaGalleriesPrefInfoMap::const_iterator gallery_info =
      known_galleries_.find(pref_id);
  if (gallery_info == known_galleries_.end())
    return false;

  bool default_permission = false;
  if (gallery_info->second.type == MediaGalleryPrefInfo::kAutoDetected)
    default_permission = HasAutoDetectedGalleryPermission(extension);
  // When the permission matches the default, we don't need to remember it.
  if (has_permission == default_permission) {
    if (!UnsetGalleryPermissionInPrefs(extension.id(), pref_id))
      // If permission wasn't set, assume nothing has changed.
      return false;
  } else {
    if (!SetGalleryPermissionInPrefs(extension.id(), pref_id, has_permission))
      return false;
  }
  if (has_permission)
    FOR_EACH_OBSERVER(GalleryChangeObserver,
                      gallery_change_observers_,
                      OnPermissionAdded(this, extension.id(), pref_id));
  else
    FOR_EACH_OBSERVER(GalleryChangeObserver,
                      gallery_change_observers_,
                      OnPermissionRemoved(this, extension.id(), pref_id));
  return true;
}

const MediaGalleriesPrefInfoMap& MediaGalleriesPreferences::known_galleries()
    const {
  DCHECK(IsInitialized());
  return known_galleries_;
}

base::Time MediaGalleriesPreferences::GetLastScanCompletionTime() const {
  int64 last_scan_time_internal =
      profile_->GetPrefs()->GetInt64(prefs::kMediaGalleriesLastScanTime);
  return base::Time::FromInternalValue(last_scan_time_internal);
}

void MediaGalleriesPreferences::SetLastScanCompletionTime(
    const base::Time& time) {
  profile_->GetPrefs()->SetInt64(prefs::kMediaGalleriesLastScanTime,
                                 time.ToInternalValue());
}

void MediaGalleriesPreferences::Shutdown() {
  weak_factory_.InvalidateWeakPtrs();
  profile_ = NULL;
}

// static
bool MediaGalleriesPreferences::APIHasBeenUsed(Profile* profile) {
  MediaGalleryPrefId current_id =
      profile->GetPrefs()->GetUint64(prefs::kMediaGalleriesUniqueId);
  return current_id != kInvalidMediaGalleryPrefId + 1;
}

// static
void MediaGalleriesPreferences::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterListPref(prefs::kMediaGalleriesRememberedGalleries,
                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  registry->RegisterUint64Pref(
      prefs::kMediaGalleriesUniqueId,
      kInvalidMediaGalleryPrefId + 1,
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  registry->RegisterInt64Pref(
      prefs::kMediaGalleriesLastScanTime,
      base::Time().ToInternalValue(),
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}

bool MediaGalleriesPreferences::SetGalleryPermissionInPrefs(
    const std::string& extension_id,
    MediaGalleryPrefId gallery_id,
    bool has_access) {
  DCHECK(IsInitialized());
  ExtensionPrefs::ScopedListUpdate update(GetExtensionPrefs(),
                                          extension_id,
                                          kMediaGalleriesPermissions);
  base::ListValue* permissions = update.Get();
  if (!permissions) {
    permissions = update.Create();
  } else {
    // If the gallery is already in the list, update the permission...
    for (base::ListValue::iterator iter = permissions->begin();
         iter != permissions->end(); ++iter) {
      base::DictionaryValue* dict = NULL;
      if (!(*iter)->GetAsDictionary(&dict))
        continue;
      MediaGalleryPermission perm;
      if (!GetMediaGalleryPermissionFromDictionary(dict, &perm))
        continue;
      if (perm.pref_id == gallery_id) {
        if (has_access != perm.has_permission) {
          dict->SetBoolean(kMediaGalleryHasPermissionKey, has_access);
          return true;
        } else {
          return false;
        }
      }
    }
  }
  // ...Otherwise, add a new entry for the gallery.
  base::DictionaryValue* dict = new base::DictionaryValue;
  dict->SetString(kMediaGalleryIdKey, base::Uint64ToString(gallery_id));
  dict->SetBoolean(kMediaGalleryHasPermissionKey, has_access);
  permissions->Append(dict);
  return true;
}

bool MediaGalleriesPreferences::UnsetGalleryPermissionInPrefs(
    const std::string& extension_id,
    MediaGalleryPrefId gallery_id) {
  DCHECK(IsInitialized());
  ExtensionPrefs::ScopedListUpdate update(GetExtensionPrefs(),
                                          extension_id,
                                          kMediaGalleriesPermissions);
  base::ListValue* permissions = update.Get();
  if (!permissions)
    return false;

  for (base::ListValue::iterator iter = permissions->begin();
       iter != permissions->end(); ++iter) {
    const base::DictionaryValue* dict = NULL;
    if (!(*iter)->GetAsDictionary(&dict))
      continue;
    MediaGalleryPermission perm;
    if (!GetMediaGalleryPermissionFromDictionary(dict, &perm))
      continue;
    if (perm.pref_id == gallery_id) {
      permissions->Erase(iter, NULL);
      return true;
    }
  }
  return false;
}

std::vector<MediaGalleryPermission>
MediaGalleriesPreferences::GetGalleryPermissionsFromPrefs(
    const std::string& extension_id) const {
  DCHECK(IsInitialized());
  std::vector<MediaGalleryPermission> result;
  const base::ListValue* permissions;
  if (!GetExtensionPrefs()->ReadPrefAsList(extension_id,
                                           kMediaGalleriesPermissions,
                                           &permissions)) {
    return result;
  }

  for (base::ListValue::const_iterator iter = permissions->begin();
       iter != permissions->end(); ++iter) {
    base::DictionaryValue* dict = NULL;
    if (!(*iter)->GetAsDictionary(&dict))
      continue;
    MediaGalleryPermission perm;
    if (!GetMediaGalleryPermissionFromDictionary(dict, &perm))
      continue;
    result.push_back(perm);
  }

  return result;
}

void MediaGalleriesPreferences::RemoveGalleryPermissionsFromPrefs(
    MediaGalleryPrefId gallery_id) {
  DCHECK(IsInitialized());
  ExtensionPrefs* prefs = GetExtensionPrefs();
  const base::DictionaryValue* extensions =
      prefs->pref_service()->GetDictionary(extensions::pref_names::kExtensions);
  if (!extensions)
    return;

  for (base::DictionaryValue::Iterator iter(*extensions); !iter.IsAtEnd();
       iter.Advance()) {
    if (!extensions::Extension::IdIsValid(iter.key())) {
      NOTREACHED();
      continue;
    }
    UnsetGalleryPermissionInPrefs(iter.key(), gallery_id);
  }
}

ExtensionPrefs* MediaGalleriesPreferences::GetExtensionPrefs() const {
  DCHECK(IsInitialized());
  if (extension_prefs_for_testing_)
    return extension_prefs_for_testing_;
  return extensions::ExtensionPrefs::Get(profile_);
}

void MediaGalleriesPreferences::SetExtensionPrefsForTesting(
    extensions::ExtensionPrefs* extension_prefs) {
  DCHECK(IsInitialized());
  extension_prefs_for_testing_ = extension_prefs;
}
