// 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.

// MediaFileSystemRegistry unit tests.

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

#include <stddef.h>

#include <algorithm>
#include <memory>
#include <set>
#include <vector>

#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/media_galleries/media_file_system_context.h"
#include "chrome/browser/media_galleries/media_galleries_preferences_factory.h"
#include "chrome/browser/media_galleries/media_galleries_test_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/storage_monitor/removable_device_constants.h"
#include "components/storage_monitor/storage_info.h"
#include "components/storage_monitor/storage_monitor.h"
#include "components/storage_monitor/test_storage_monitor.h"
#include "components/sync/model/string_ordinal.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_factory.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/web_contents_tester.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "testing/gtest/include/gtest/gtest.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
#endif

namespace content {
class SiteInstance;
}

using content::BrowserThread;
using storage_monitor::StorageInfo;
using storage_monitor::StorageMonitor;
using storage_monitor::TestStorageMonitor;

// Not anonymous so it can be friends with MediaFileSystemRegistry.
class TestMediaFileSystemContext : public MediaFileSystemContext {
 public:
  struct FSInfo {
    FSInfo() {}
    FSInfo(const std::string& device_id, const base::FilePath& path,
           const std::string& fs_name);

    bool operator<(const FSInfo& other) const;

    std::string device_id;
    base::FilePath path;
    std::string fs_name;
  };

  explicit TestMediaFileSystemContext(MediaFileSystemRegistry* registry);
  ~TestMediaFileSystemContext() override {}

  // MediaFileSystemContext implementation.
  bool RegisterFileSystem(const std::string& device_id,
                          const std::string& fs_name,
                          const base::FilePath& path) override;

  void RevokeFileSystem(const std::string& fs_name) override;

  base::FilePath GetRegisteredPath(const std::string& fs_name) const override;

  MediaFileSystemRegistry* registry() { return registry_; }

 private:
  void AddFSEntry(const std::string& device_id,
                  const base::FilePath& path,
                  const std::string& fs_name);

  MediaFileSystemRegistry* registry_;

  // The currently allocated mock file systems.
  std::map<std::string /*fs_name*/, FSInfo> file_systems_by_name_;
};

TestMediaFileSystemContext::FSInfo::FSInfo(const std::string& device_id,
                                           const base::FilePath& path,
                                           const std::string& fs_name)
    : device_id(device_id),
      path(path),
      fs_name(fs_name) {
}

bool TestMediaFileSystemContext::FSInfo::operator<(const FSInfo& other) const {
  if (device_id != other.device_id)
    return device_id < other.device_id;
  if (path.value() != other.path.value())
    return path.value() < other.path.value();
  return fs_name < other.fs_name;
}

TestMediaFileSystemContext::TestMediaFileSystemContext(
    MediaFileSystemRegistry* registry)
    : registry_(registry) {
  registry_->file_system_context_.reset(this);
}

bool TestMediaFileSystemContext::RegisterFileSystem(
    const std::string& device_id,
    const std::string& fs_name,
    const base::FilePath& path) {
  AddFSEntry(device_id, path, fs_name);
  return true;
}

void TestMediaFileSystemContext::RevokeFileSystem(const std::string& fs_name) {
  if (!base::ContainsKey(file_systems_by_name_, fs_name))
    return;
  EXPECT_EQ(1U, file_systems_by_name_.erase(fs_name));
}

base::FilePath TestMediaFileSystemContext::GetRegisteredPath(
    const std::string& fs_name) const {
  std::map<std::string /*fs_name*/, FSInfo>::const_iterator it =
      file_systems_by_name_.find(fs_name);
  if (it == file_systems_by_name_.end())
    return base::FilePath();
  return it->second.path;
}

void TestMediaFileSystemContext::AddFSEntry(const std::string& device_id,
                                            const base::FilePath& path,
                                            const std::string& fs_name) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(path.IsAbsolute());
  DCHECK(!path.ReferencesParent());

  FSInfo info(device_id, path, fs_name);
  file_systems_by_name_[fs_name] = info;
}

namespace {

typedef std::map<MediaGalleryPrefId, MediaFileSystemInfo> FSInfoMap;

void GetGalleryInfoCallback(
    FSInfoMap* results,
    const std::vector<MediaFileSystemInfo>& file_systems) {
  for (size_t i = 0; i < file_systems.size(); ++i) {
    ASSERT_FALSE(base::ContainsKey(*results, file_systems[i].pref_id));
    (*results)[file_systems[i].pref_id] = file_systems[i];
  }
}

void CheckGalleryInfo(const MediaFileSystemInfo& info,
                      TestMediaFileSystemContext* fs_context,
                      const base::FilePath& path,
                      bool removable,
                      bool media_device) {
  EXPECT_EQ(path, info.path);
  EXPECT_EQ(removable, info.removable);
  EXPECT_EQ(media_device, info.media_device);
  EXPECT_NE(0UL, info.pref_id);

  if (removable)
    EXPECT_NE(0UL, info.transient_device_id.size());
  else
    EXPECT_EQ(0UL, info.transient_device_id.size());

  base::FilePath fsid_path = fs_context->GetRegisteredPath(info.fsid);
  EXPECT_EQ(path, fsid_path);
}

class MockProfileSharedRenderProcessHostFactory
    : public content::RenderProcessHostFactory {
 public:
  MockProfileSharedRenderProcessHostFactory() {}
  ~MockProfileSharedRenderProcessHostFactory() override;

  // RPH created with this factory are owned by it.  If the RPH is destroyed
  // for testing purposes, it must be removed from the factory first.
  content::MockRenderProcessHost* ReleaseRPH(
      content::BrowserContext* browser_context);

  content::RenderProcessHost* CreateRenderProcessHost(
      content::BrowserContext* browser_context,
      content::SiteInstance* site_instance) const override;

 private:
  class SharedMockRenderProcessHost : public content::MockRenderProcessHost {
   public:
    explicit SharedMockRenderProcessHost(
        content::BrowserContext* browser_context)
        : content::MockRenderProcessHost(browser_context) {}

    // This test class lies that the process has not been used to allow
    // testing of process sharing/reuse inherent in the unit tests that depend
    // on the MockProfileSharedRenderProcessHostFactory.
    bool HostHasNotBeenUsed() override { return true; }

   private:
    DISALLOW_COPY_AND_ASSIGN(SharedMockRenderProcessHost);
  };

  mutable std::map<content::BrowserContext*,
                   std::unique_ptr<content::MockRenderProcessHost>>
      rph_map_;

  DISALLOW_COPY_AND_ASSIGN(MockProfileSharedRenderProcessHostFactory);
};

class ProfileState {
 public:
  explicit ProfileState(MockProfileSharedRenderProcessHostFactory* rph_factory);
  ~ProfileState();

  MediaGalleriesPreferences* GetMediaGalleriesPrefs();

  void CheckGalleries(
      const std::string& test,
      const std::vector<MediaFileSystemInfo>& regular_extension_galleries,
      const std::vector<MediaFileSystemInfo>& all_extension_galleries);

  FSInfoMap GetGalleriesInfo(extensions::Extension* extension);

  extensions::Extension* all_permission_extension();
  extensions::Extension* regular_permission_extension();
  Profile* profile();

  void AddNameForReadCompare(const base::string16& name);
  void AddNameForAllCompare(const base::string16& name);

 private:
  void CompareResults(const std::string& test,
                      const std::vector<base::string16>& names,
                      const std::vector<MediaFileSystemInfo>& expected,
                      const std::vector<MediaFileSystemInfo>& actual);
  bool ContainsEntry(const MediaFileSystemInfo& info,
                     const std::vector<MediaFileSystemInfo>& container);

  int GetAndClearComparisonCount();

  int num_comparisons_;

  std::unique_ptr<TestingProfile> profile_;

  scoped_refptr<extensions::Extension> all_permission_extension_;
  scoped_refptr<extensions::Extension> regular_permission_extension_;
  scoped_refptr<extensions::Extension> no_permissions_extension_;

  std::unique_ptr<content::WebContents> single_web_contents_;
  std::unique_ptr<content::WebContents> shared_web_contents1_;
  std::unique_ptr<content::WebContents> shared_web_contents2_;

  // The RenderProcessHosts are freed when their respective WebContents /
  // RenderViewHosts go away.
  content::MockRenderProcessHost* single_rph_;
  content::MockRenderProcessHost* shared_rph_;

  std::vector<base::string16> compare_names_read_;
  std::vector<base::string16> compare_names_all_;

  DISALLOW_COPY_AND_ASSIGN(ProfileState);
};

base::string16 GetExpectedFolderName(const base::FilePath& path) {
#if defined(OS_CHROMEOS)
  return path.BaseName().LossyDisplayName();
#else
  return path.LossyDisplayName();
#endif
}

}  // namespace

class MediaFileSystemRegistryTest : public ChromeRenderViewHostTestHarness {
 public:
  MediaFileSystemRegistryTest() = default;

  ~MediaFileSystemRegistryTest() override = default;

  void CreateProfileState(size_t profile_count);

  ProfileState* GetProfileState(size_t i);

  MediaGalleriesPreferences* GetPreferences(Profile* profile);

  base::FilePath empty_dir() {
    return empty_dir_;
  }

  base::FilePath dcim_dir() {
    return dcim_dir_;
  }

  TestMediaFileSystemContext* test_file_system_context() {
    return test_file_system_context_;
  }

  // Create a user added gallery based on the information passed and add it to
  // |profiles|. Returns the device id.
  std::string AddUserGallery(StorageInfo::Type type,
                             const std::string& unique_id,
                             const base::FilePath& path);

  // Returns the device id.
  std::string AttachDevice(StorageInfo::Type type,
                           const std::string& unique_id,
                           const base::FilePath& location);

  void DetachDevice(const std::string& device_id);

  void SetGalleryPermission(ProfileState* profile_state,
                            extensions::Extension* extension,
                            const std::string& device_id,
                            bool has_access);

  void AssertAllAutoAddedGalleries();

  void InitForGalleriesInfoTest(FSInfoMap* galleries_info);

  void CheckNewGalleryInfo(ProfileState* profile_state,
                           const FSInfoMap& galleries_info,
                           const base::FilePath& location,
                           bool removable,
                           bool media_device);

  std::vector<MediaFileSystemInfo> GetAutoAddedGalleries(
      ProfileState* profile_state);

  void ProcessAttach(const std::string& id,
                     const base::string16& name,
                     const base::FilePath::StringType& location) {
    StorageInfo info(id, location, name, base::string16(), base::string16(), 0);
    StorageMonitor::GetInstance()->receiver()->ProcessAttach(info);
  }

  void ProcessDetach(const std::string& id) {
    StorageMonitor::GetInstance()->receiver()->ProcessDetach(id);
  }

  MediaFileSystemRegistry* registry() {
    return test_file_system_context_->registry();
  }

  size_t GetExtensionGalleriesHostCount(
      const MediaFileSystemRegistry* registry) const;

  int num_auto_galleries() {
    return media_directories_.num_galleries();
  }

 protected:
  void SetUp() override;
  void TearDown() override;

 private:
  // This makes sure that at least one default gallery exists on the file
  // system.
  EnsureMediaDirectoriesExists media_directories_;

  // Some test gallery directories.
  base::ScopedTempDir galleries_dir_;
  // An empty directory in |galleries_dir_|
  base::FilePath empty_dir_;
  // A directory in |galleries_dir_| with a DCIM directory in it.
  base::FilePath dcim_dir_;

  // MediaFileSystemRegistry owns this.
  TestMediaFileSystemContext* test_file_system_context_;

  // Needed for extension service & friends to work.

#if defined(OS_CHROMEOS)
  chromeos::ScopedCrosSettingsTestHelper cros_settings_test_helper_;
#endif

  MockProfileSharedRenderProcessHostFactory rph_factory_;

  std::vector<std::unique_ptr<ProfileState>> profile_states_;

  DISALLOW_COPY_AND_ASSIGN(MediaFileSystemRegistryTest);
};

namespace {

bool MediaFileSystemInfoComparator(const MediaFileSystemInfo& a,
                                   const MediaFileSystemInfo& b) {
  CHECK_NE(a.name, b.name);  // Name must be unique.
  return a.name < b.name;
}

///////////////////////////////////////////////
// MockProfileSharedRenderProcessHostFactory //
///////////////////////////////////////////////

MockProfileSharedRenderProcessHostFactory::
    ~MockProfileSharedRenderProcessHostFactory() {
}

content::MockRenderProcessHost*
MockProfileSharedRenderProcessHostFactory::ReleaseRPH(
    content::BrowserContext* browser_context) {
  auto existing = rph_map_.find(browser_context);
  if (existing == rph_map_.end())
    return NULL;
  std::unique_ptr<content::MockRenderProcessHost> result =
      std::move(existing->second);
  rph_map_.erase(existing);
  return result.release();
}

content::RenderProcessHost*
MockProfileSharedRenderProcessHostFactory::CreateRenderProcessHost(
    content::BrowserContext* browser_context,
    content::SiteInstance* site_instance) const {
  auto existing = rph_map_.find(browser_context);
  if (existing != rph_map_.end())
    return existing->second.get();
  rph_map_[browser_context] =
      std::make_unique<SharedMockRenderProcessHost>(browser_context);
  return rph_map_[browser_context].get();
}

//////////////////
// ProfileState //
//////////////////

ProfileState::ProfileState(
    MockProfileSharedRenderProcessHostFactory* rph_factory)
    : num_comparisons_(0), profile_(new TestingProfile()) {
  extensions::TestExtensionSystem* extension_system(
      static_cast<extensions::TestExtensionSystem*>(
          extensions::ExtensionSystem::Get(profile_.get())));
  extension_system->CreateExtensionService(
      base::CommandLine::ForCurrentProcess(), base::FilePath(), false);

  std::vector<std::string> all_permissions;
  all_permissions.push_back("allAutoDetected");
  all_permissions.push_back("read");
  std::vector<std::string> read_permissions;
  read_permissions.push_back("read");

  all_permission_extension_ =
      AddMediaGalleriesApp("all", all_permissions, profile_.get());
  regular_permission_extension_ =
      AddMediaGalleriesApp("regular", read_permissions, profile_.get());
  no_permissions_extension_ =
      AddMediaGalleriesApp("no", read_permissions, profile_.get());

  single_web_contents_ =
      content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL);
  single_rph_ = rph_factory->ReleaseRPH(profile_.get());

  shared_web_contents1_ =
      content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL);
  shared_web_contents2_ =
      content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL);
  shared_rph_ = rph_factory->ReleaseRPH(profile_.get());
}

ProfileState::~ProfileState() {
  // TestExtensionSystem uses DeleteSoon, so we need to delete the profiles
  // and then run the message queue to clean up.  But first we have to
  // delete everything that references the profile.
  single_web_contents_.reset();
  shared_web_contents1_.reset();
  shared_web_contents2_.reset();
  profile_.reset();

  content::RunAllTasksUntilIdle();
}

MediaGalleriesPreferences* ProfileState::GetMediaGalleriesPrefs() {
  MediaGalleriesPreferences* prefs =
      MediaGalleriesPreferencesFactory::GetForProfile(profile_.get());
  base::RunLoop loop;
  prefs->EnsureInitialized(loop.QuitClosure());
  loop.Run();
  return prefs;
}

void ProfileState::CheckGalleries(
    const std::string& test,
    const std::vector<MediaFileSystemInfo>& regular_extension_galleries,
    const std::vector<MediaFileSystemInfo>& all_extension_galleries) {
  MediaFileSystemRegistry* registry =
      g_browser_process->media_file_system_registry();

  // No Media Galleries permissions.
  std::vector<MediaFileSystemInfo> empty_expectation;
  std::vector<base::string16> empty_names;
  registry->GetMediaFileSystemsForExtension(
      single_web_contents_.get(), no_permissions_extension_.get(),
      base::Bind(&ProfileState::CompareResults, base::Unretained(this),
                 base::StringPrintf("%s (no permission)", test.c_str()),
                 base::ConstRef(empty_names),
                 base::ConstRef(empty_expectation)));
  content::RunAllTasksUntilIdle();
  EXPECT_EQ(1, GetAndClearComparisonCount());

  // Read permission only.
  registry->GetMediaFileSystemsForExtension(
      single_web_contents_.get(), regular_permission_extension_.get(),
      base::Bind(&ProfileState::CompareResults, base::Unretained(this),
                 base::StringPrintf("%s (regular permission)", test.c_str()),
                 base::ConstRef(compare_names_read_),
                 base::ConstRef(regular_extension_galleries)));
  content::RunAllTasksUntilIdle();
  EXPECT_EQ(1, GetAndClearComparisonCount());

  // All galleries permission.
  registry->GetMediaFileSystemsForExtension(
      single_web_contents_.get(), all_permission_extension_.get(),
      base::Bind(&ProfileState::CompareResults, base::Unretained(this),
                 base::StringPrintf("%s (all permission)", test.c_str()),
                 base::ConstRef(compare_names_all_),
                 base::ConstRef(all_extension_galleries)));
  content::RunAllTasksUntilIdle();
  EXPECT_EQ(1, GetAndClearComparisonCount());
}

FSInfoMap ProfileState::GetGalleriesInfo(extensions::Extension* extension) {
  FSInfoMap results;
  MediaFileSystemRegistry* registry =
      g_browser_process->media_file_system_registry();
  registry->GetMediaFileSystemsForExtension(
      single_web_contents_.get(), extension,
      base::Bind(&GetGalleryInfoCallback, base::Unretained(&results)));
  content::RunAllTasksUntilIdle();
  return results;
}

extensions::Extension* ProfileState::all_permission_extension() {
  return all_permission_extension_.get();
}

extensions::Extension* ProfileState::regular_permission_extension() {
  return regular_permission_extension_.get();
}

Profile* ProfileState::profile() {
  return profile_.get();
}

void ProfileState::AddNameForReadCompare(const base::string16& name) {
  compare_names_read_.push_back(name);
}

void ProfileState::AddNameForAllCompare(const base::string16& name) {
  compare_names_all_.push_back(name);
}

bool ProfileState::ContainsEntry(
    const MediaFileSystemInfo& info,
    const std::vector<MediaFileSystemInfo>& container) {
  for (size_t i = 0; i < container.size(); ++i) {
    if (info.path.value() == container[i].path.value()) {
      EXPECT_FALSE(container[i].fsid.empty());
      if (!info.fsid.empty())
        EXPECT_EQ(info.fsid, container[i].fsid);
      return true;
    }
  }
  return false;
}

void ProfileState::CompareResults(
    const std::string& test,
    const std::vector<base::string16>& names,
    const std::vector<MediaFileSystemInfo>& expected,
    const std::vector<MediaFileSystemInfo>& actual) {
  num_comparisons_++;
  EXPECT_EQ(expected.size(), actual.size()) << test;

  // Order isn't important, so sort the results.
  std::vector<MediaFileSystemInfo> sorted(actual);
  std::sort(sorted.begin(), sorted.end(), MediaFileSystemInfoComparator);
  std::vector<MediaFileSystemInfo> expect(expected);
  std::sort(expect.begin(), expect.end(), MediaFileSystemInfoComparator);
  std::vector<base::string16> expect_names(names);
  std::sort(expect_names.begin(), expect_names.end());

  for (size_t i = 0; i < expect.size() && i < sorted.size(); ++i) {
    if (expect_names.size() > i)
      EXPECT_EQ(expect_names[i], sorted[i].name) << test;
    EXPECT_TRUE(ContainsEntry(expect[i], sorted)) << test;
  }
}

int ProfileState::GetAndClearComparisonCount() {
  int result = num_comparisons_;
  num_comparisons_ = 0;
  return result;
}

}  // namespace

/////////////////////////////////
// MediaFileSystemRegistryTest //
/////////////////////////////////

void MediaFileSystemRegistryTest::CreateProfileState(size_t profile_count) {
  for (size_t i = 0; i < profile_count; ++i) {
    profile_states_.push_back(std::make_unique<ProfileState>(&rph_factory_));
  }
}

ProfileState* MediaFileSystemRegistryTest::GetProfileState(size_t i) {
  return profile_states_[i].get();
}

MediaGalleriesPreferences* MediaFileSystemRegistryTest::GetPreferences(
    Profile* profile) {
  MediaGalleriesPreferences* prefs = registry()->GetPreferences(profile);
  base::RunLoop loop;
  prefs->EnsureInitialized(loop.QuitClosure());
  loop.Run();
  return prefs;
}

std::string MediaFileSystemRegistryTest::AddUserGallery(
    StorageInfo::Type type,
    const std::string& unique_id,
    const base::FilePath& path) {
  std::string device_id = StorageInfo::MakeDeviceId(type, unique_id);
  DCHECK(!StorageInfo::IsMediaDevice(device_id));

  for (size_t i = 0; i < profile_states_.size(); ++i) {
    profile_states_[i]->GetMediaGalleriesPrefs()->AddGallery(
        device_id, base::FilePath(), MediaGalleryPrefInfo::kUserAdded,
        base::string16(), base::string16(), base::string16(), 0,
        base::Time::Now(), 0, 0, 0);
  }
  return device_id;
}

std::string MediaFileSystemRegistryTest::AttachDevice(
    StorageInfo::Type type,
    const std::string& unique_id,
    const base::FilePath& location) {
  std::string device_id = StorageInfo::MakeDeviceId(type, unique_id);
  DCHECK(StorageInfo::IsRemovableDevice(device_id));
  base::string16 label = location.BaseName().LossyDisplayName();
  ProcessAttach(device_id, label, location.value());
  content::RunAllTasksUntilIdle();
  return device_id;
}

void MediaFileSystemRegistryTest::DetachDevice(const std::string& device_id) {
  DCHECK(StorageInfo::IsRemovableDevice(device_id));
  ProcessDetach(device_id);
  content::RunAllTasksUntilIdle();
}

void MediaFileSystemRegistryTest::SetGalleryPermission(
    ProfileState* profile_state, extensions::Extension* extension,
    const std::string& device_id, bool has_access) {
  MediaGalleriesPreferences* preferences =
      profile_state->GetMediaGalleriesPrefs();
  MediaGalleryPrefIdSet pref_id =
      preferences->LookUpGalleriesByDeviceId(device_id);
  ASSERT_EQ(1U, pref_id.size());
  preferences->SetGalleryPermissionForExtension(*extension, *pref_id.begin(),
                                                has_access);
}

void MediaFileSystemRegistryTest::AssertAllAutoAddedGalleries() {
  for (size_t i = 0; i < profile_states_.size(); ++i) {
    MediaGalleriesPreferences* prefs =
        profile_states_[0]->GetMediaGalleriesPrefs();

    // Make sure that we have at least one gallery and that they are all
    // auto added galleries.
    const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
    ASSERT_GT(galleries.size(), 0U);
#endif
    for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
         it != galleries.end();
         ++it) {
      ASSERT_EQ(MediaGalleryPrefInfo::kAutoDetected, it->second.type);
    }
  }
}

void MediaFileSystemRegistryTest::InitForGalleriesInfoTest(
    FSInfoMap* galleries_info) {
  CreateProfileState(1);
  AssertAllAutoAddedGalleries();

  // Get all existing gallery names.
  ProfileState* profile_state = GetProfileState(0U);
  *galleries_info = profile_state->GetGalleriesInfo(
      profile_state->all_permission_extension());
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
  ASSERT_EQ(3U, galleries_info->size());
#else
  ASSERT_EQ(0U, galleries_info->size());
#endif
}

void MediaFileSystemRegistryTest::CheckNewGalleryInfo(
    ProfileState* profile_state,
    const FSInfoMap& galleries_info,
    const base::FilePath& location,
    bool removable,
    bool media_device) {
  // Get new galleries.
  FSInfoMap new_galleries_info = profile_state->GetGalleriesInfo(
      profile_state->all_permission_extension());
  ASSERT_EQ(galleries_info.size() + 1U, new_galleries_info.size());

  bool found_new = false;
  for (FSInfoMap::const_iterator it = new_galleries_info.begin();
       it != new_galleries_info.end();
       ++it) {
    if (base::ContainsKey(galleries_info, it->first))
      continue;

    ASSERT_FALSE(found_new);
    CheckGalleryInfo(it->second, test_file_system_context_, location,
                     removable, media_device);
    found_new = true;
  }
  ASSERT_TRUE(found_new);
}

std::vector<MediaFileSystemInfo>
MediaFileSystemRegistryTest::GetAutoAddedGalleries(
    ProfileState* profile_state) {
  const MediaGalleriesPrefInfoMap& galleries =
      profile_state->GetMediaGalleriesPrefs()->known_galleries();
  std::vector<MediaFileSystemInfo> result;
  for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
       it != galleries.end();
       ++it) {
    if (it->second.type == MediaGalleryPrefInfo::kAutoDetected) {
      base::FilePath path = it->second.AbsolutePath();
      MediaFileSystemInfo info(path.BaseName().LossyDisplayName(), path,
                               std::string(), 0, std::string(), false, false);
      result.push_back(info);
    }
  }
  std::sort(result.begin(), result.end(), MediaFileSystemInfoComparator);
  return result;
}

size_t MediaFileSystemRegistryTest::GetExtensionGalleriesHostCount(
    const MediaFileSystemRegistry* registry) const {
  size_t extension_galleries_host_count = 0;
  for (MediaFileSystemRegistry::ExtensionGalleriesHostMap::const_iterator it =
           registry->extension_hosts_map_.begin();
       it != registry->extension_hosts_map_.end();
       ++it) {
    extension_galleries_host_count += it->second.size();
  }
  return extension_galleries_host_count;
}


void MediaFileSystemRegistryTest::SetUp() {
  ChromeRenderViewHostTestHarness::SetUp();
  ASSERT_TRUE(TestStorageMonitor::CreateAndInstall());

  DeleteContents();
  SetRenderProcessHostFactory(&rph_factory_);

  test_file_system_context_ = new TestMediaFileSystemContext(
      g_browser_process->media_file_system_registry());

  ASSERT_TRUE(galleries_dir_.CreateUniqueTempDir());
  empty_dir_ = galleries_dir_.GetPath().AppendASCII("empty");
  ASSERT_TRUE(base::CreateDirectory(empty_dir_));
  dcim_dir_ = galleries_dir_.GetPath().AppendASCII("with_dcim");
  ASSERT_TRUE(base::CreateDirectory(dcim_dir_));
  ASSERT_TRUE(base::CreateDirectory(
      dcim_dir_.Append(storage_monitor::kDCIMDirectoryName)));
}

void MediaFileSystemRegistryTest::TearDown() {
  profile_states_.clear();
  MediaFileSystemRegistry* registry =
      g_browser_process->media_file_system_registry();
  EXPECT_EQ(0U, GetExtensionGalleriesHostCount(registry));

  // The TestingProfile must be destroyed before the TestingBrowserProcess
  // because it uses it in its destructor.
  ChromeRenderViewHostTestHarness::TearDown();

  // The MediaFileSystemRegistry owned by the TestingBrowserProcess must be
  // destroyed before the StorageMonitor because it calls
  // StorageMonitor::RemoveObserver() in its destructor.
  TestingBrowserProcess::DeleteInstance();

  TestStorageMonitor::Destroy();
}

///////////
// Tests //
///////////

TEST_F(MediaFileSystemRegistryTest, Basic) {
  CreateProfileState(1);
  AssertAllAutoAddedGalleries();

  ProfileState* profile_state = GetProfileState(0);
  std::vector<MediaFileSystemInfo> auto_galleries =
      GetAutoAddedGalleries(profile_state);
  std::vector<MediaFileSystemInfo> empty_expectation;
  profile_state->CheckGalleries("basic", empty_expectation, auto_galleries);
}

TEST_F(MediaFileSystemRegistryTest, UserAddedGallery) {
  CreateProfileState(1);
  AssertAllAutoAddedGalleries();
  ProfileState* profile_state = GetProfileState(0);
  std::vector<MediaFileSystemInfo> auto_galleries =
      GetAutoAddedGalleries(profile_state);
  std::vector<MediaFileSystemInfo> added_galleries;
  profile_state->CheckGalleries("user added init", added_galleries,
                                auto_galleries);

  // Add a user gallery to the regular permission extension.
  std::string device_id = AddUserGallery(StorageInfo::FIXED_MASS_STORAGE,
                                         empty_dir().AsUTF8Unsafe(),
                                         empty_dir());
  SetGalleryPermission(profile_state,
                       profile_state->regular_permission_extension(),
                       device_id,
                       true /*has access*/);
  MediaFileSystemInfo added_info(empty_dir().LossyDisplayName(), empty_dir(),
                                 std::string(), 0, std::string(), false, false);
  added_galleries.push_back(added_info);
  profile_state->CheckGalleries("user added regular", added_galleries,
                                auto_galleries);

  // Add it to the all galleries extension.
  SetGalleryPermission(profile_state,
                       profile_state->all_permission_extension(),
                       device_id,
                       true /*has access*/);
  auto_galleries.push_back(added_info);
  profile_state->CheckGalleries("user added all", added_galleries,
                                auto_galleries);
}

// Regression test to make sure erasing galleries does not result a crash.
TEST_F(MediaFileSystemRegistryTest, EraseGalleries) {
  CreateProfileState(1);
  AssertAllAutoAddedGalleries();

  ProfileState* profile_state = GetProfileState(0);
  std::vector<MediaFileSystemInfo> auto_galleries =
      GetAutoAddedGalleries(profile_state);
  std::vector<MediaFileSystemInfo> empty_expectation;
  profile_state->CheckGalleries("erase", empty_expectation, auto_galleries);

  MediaGalleriesPreferences* prefs = profile_state->GetMediaGalleriesPrefs();
  MediaGalleriesPrefInfoMap galleries = prefs->known_galleries();
  for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
       it != galleries.end(); ++it) {
    prefs->ForgetGalleryById(it->first);
  }
}

// Regression test to make sure calling GetPreferences() does not re-insert
// galleries on auto-detected removable devices that were blacklisted.
TEST_F(MediaFileSystemRegistryTest,
       GetPreferencesDoesNotReinsertBlacklistedGalleries) {
  CreateProfileState(1);
  AssertAllAutoAddedGalleries();

  ProfileState* profile_state = GetProfileState(0);
  const size_t gallery_count = GetAutoAddedGalleries(profile_state).size();

  // Attach a device.
  const std::string device_id = AttachDevice(
      StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM,
      "removable_dcim_fake_id",
      dcim_dir());
  EXPECT_EQ(gallery_count + 1, GetAutoAddedGalleries(profile_state).size());

  // Forget the device.
  bool forget_gallery = false;
  MediaGalleriesPreferences* prefs = GetPreferences(profile_state->profile());
  const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
  for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
       it != galleries.end(); ++it) {
    if (it->second.device_id == device_id) {
      prefs->ForgetGalleryById(it->first);
      forget_gallery = true;
      break;
    }
  }
  content::RunAllTasksUntilIdle();
  EXPECT_TRUE(forget_gallery);
  EXPECT_EQ(gallery_count, GetAutoAddedGalleries(profile_state).size());

  // Call GetPreferences() and the gallery count should not change.
  prefs = GetPreferences(profile_state->profile());
  EXPECT_EQ(gallery_count, GetAutoAddedGalleries(profile_state).size());
}

TEST_F(MediaFileSystemRegistryTest, GalleryNameDefault) {
  FSInfoMap galleries_info;
  InitForGalleriesInfoTest(&galleries_info);

  for (FSInfoMap::const_iterator it = galleries_info.begin();
       it != galleries_info.end();
       ++it) {
    CheckGalleryInfo(it->second, test_file_system_context(),
                     it->second.path, false, false);
  }
}

// TODO(gbillock): Move the remaining test into the linux directory.
#if !defined(OS_MACOSX) && !defined(OS_WIN)
TEST_F(MediaFileSystemRegistryTest, GalleryMTP) {
  FSInfoMap galleries_info;
  InitForGalleriesInfoTest(&galleries_info);

  base::FilePath location(FILE_PATH_LITERAL("/mtp_bogus"));
  AttachDevice(StorageInfo::MTP_OR_PTP, "mtp_fake_id", location);
  CheckNewGalleryInfo(GetProfileState(0U), galleries_info, location,
                      true /*removable*/, true /* media device */);
}
#endif

TEST_F(MediaFileSystemRegistryTest, GalleryDCIM) {
  FSInfoMap galleries_info;
  InitForGalleriesInfoTest(&galleries_info);

  AttachDevice(StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM,
               "removable_dcim_fake_id",
               dcim_dir());
  CheckNewGalleryInfo(GetProfileState(0U), galleries_info, dcim_dir(),
                      true /*removable*/, true /* media device */);
}

TEST_F(MediaFileSystemRegistryTest, GalleryNoDCIM) {
  FSInfoMap galleries_info;
  InitForGalleriesInfoTest(&galleries_info);

  std::string device_id =
      AttachDevice(StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM,
                   empty_dir().AsUTF8Unsafe(),
                   empty_dir());
  std::string device_id2 =
      AddUserGallery(StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM,
                     empty_dir().AsUTF8Unsafe(),
                     empty_dir());
  ASSERT_EQ(device_id, device_id2);
  // Add permission for new non-default gallery.
  ProfileState* profile_state = GetProfileState(0U);
  SetGalleryPermission(profile_state,
                       profile_state->all_permission_extension(),
                       device_id,
                       true /*has access*/);
  CheckNewGalleryInfo(profile_state, galleries_info, empty_dir(),
                      true /*removable*/, false /* media device */);
}

TEST_F(MediaFileSystemRegistryTest, GalleryUserAddedPath) {
  FSInfoMap galleries_info;
  InitForGalleriesInfoTest(&galleries_info);

  std::string device_id = AddUserGallery(StorageInfo::FIXED_MASS_STORAGE,
                                         empty_dir().AsUTF8Unsafe(),
                                         empty_dir());
  // Add permission for new non-default gallery.
  ProfileState* profile_state = GetProfileState(0U);
  SetGalleryPermission(profile_state,
                       profile_state->all_permission_extension(),
                       device_id,
                       true /*has access*/);
  CheckNewGalleryInfo(profile_state, galleries_info, empty_dir(),
                      false /*removable*/, false /* media device */);
}

TEST_F(MediaFileSystemRegistryTest, DetachedDeviceGalleryPath) {
  const std::string device_id = AttachDevice(
      StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM,
      "removable_dcim_fake_id",
      dcim_dir());

  MediaGalleryPrefInfo pref_info;
  pref_info.device_id = device_id;
  EXPECT_EQ(dcim_dir().value(), pref_info.AbsolutePath().value());

  MediaGalleryPrefInfo pref_info_with_relpath;
  pref_info_with_relpath.path =
      base::FilePath(FILE_PATH_LITERAL("test_relpath"));
  pref_info_with_relpath.device_id = device_id;
  EXPECT_EQ(dcim_dir().Append(pref_info_with_relpath.path).value(),
            pref_info_with_relpath.AbsolutePath().value());

  DetachDevice(device_id);
  EXPECT_TRUE(pref_info.AbsolutePath().empty());
  EXPECT_TRUE(pref_info_with_relpath.AbsolutePath().empty());
}

TEST_F(MediaFileSystemRegistryTest, TestNameConstruction) {
  CreateProfileState(1);
  AssertAllAutoAddedGalleries();

  ProfileState* profile_state = GetProfileState(0);

  std::string user_gallery = AddUserGallery(StorageInfo::FIXED_MASS_STORAGE,
                                            empty_dir().AsUTF8Unsafe(),
                                            empty_dir());
  SetGalleryPermission(profile_state,
                       profile_state->regular_permission_extension(),
                       user_gallery,
                       true /*has access*/);
  SetGalleryPermission(profile_state,
                       profile_state->all_permission_extension(),
                       user_gallery,
                       true /*has access*/);

  std::vector<MediaFileSystemInfo> auto_galleries =
      GetAutoAddedGalleries(profile_state);
  MediaFileSystemInfo added_info(empty_dir().BaseName().LossyDisplayName(),
                                 empty_dir(), std::string(), 0, std::string(),
                                 false, false);
  auto_galleries.push_back(added_info);
  std::vector<MediaFileSystemInfo> one_expectation;
  one_expectation.push_back(added_info);

  base::string16 empty_dir_name = GetExpectedFolderName(empty_dir());
  profile_state->AddNameForReadCompare(empty_dir_name);
  profile_state->AddNameForAllCompare(empty_dir_name);

  // This part of the test is conditional on default directories existing
  // on the test platform. In ChromeOS, these directories do not exist.
  base::FilePath path;
  if (num_auto_galleries() > 0) {
    ASSERT_TRUE(base::PathService::Get(chrome::DIR_USER_MUSIC, &path));
    profile_state->AddNameForAllCompare(GetExpectedFolderName(path));
    ASSERT_TRUE(base::PathService::Get(chrome::DIR_USER_PICTURES, &path));
    profile_state->AddNameForAllCompare(GetExpectedFolderName(path));
    ASSERT_TRUE(base::PathService::Get(chrome::DIR_USER_VIDEOS, &path));
    profile_state->AddNameForAllCompare(GetExpectedFolderName(path));

    profile_state->CheckGalleries("names-dir", one_expectation, auto_galleries);
  } else {
    profile_state->CheckGalleries("names", one_expectation, one_expectation);
  }
}

TEST_F(MediaFileSystemRegistryTest, PreferenceListener) {
  CreateProfileState(1);
  AssertAllAutoAddedGalleries();

  // Add a user gallery to the regular permission extension.
  std::string device_id = AddUserGallery(StorageInfo::FIXED_MASS_STORAGE,
                                         empty_dir().AsUTF8Unsafe(),
                                         empty_dir());
  ProfileState* profile_state = GetProfileState(0);
  SetGalleryPermission(profile_state,
                       profile_state->regular_permission_extension(),
                       device_id,
                       true /*has access*/);

  FSInfoMap fs_info = profile_state->GetGalleriesInfo(
      profile_state->regular_permission_extension());
  ASSERT_EQ(1U, fs_info.size());
  EXPECT_FALSE(test_file_system_context()->GetRegisteredPath(
      fs_info.begin()->second.fsid).empty());

  // Revoke permission and ensure that the file system is revoked.
  SetGalleryPermission(profile_state,
                       profile_state->regular_permission_extension(),
                       device_id,
                       false /*has access*/);
  EXPECT_TRUE(test_file_system_context()->GetRegisteredPath(
      fs_info.begin()->second.fsid).empty());
}
