// Copyright 2015 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/chromeos/file_manager/file_manager_browsertest_base.h"

#include <stddef.h>

#include <memory>
#include <utility>

#include "ash/public/interfaces/constants.mojom.h"
#include "ash/public/interfaces/shell_test_api.mojom.h"
#include "base/containers/circular_deque.h"
#include "base/json/json_reader.h"
#include "base/json/json_value_converter.h"
#include "base/json/json_writer.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/file_manager/file_manager_test_util.h"
#include "chrome/browser/chromeos/file_manager/mount_test_util.h"
#include "chrome/browser/chromeos/file_manager/path_util.h"
#include "chrome/browser/chromeos/file_manager/volume_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/sync_file_system/mock_remote_file_sync_service.h"
#include "chrome/browser/sync_file_system/sync_file_system_service_factory.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/file_manager_private.h"
#include "chromeos/chromeos_features.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/components/drivefs/drivefs_host.h"
#include "chromeos/components/drivefs/fake_drivefs.h"
#include "chromeos/dbus/concierge/service.pb.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_cros_disks_client.h"
#include "components/drive/chromeos/file_system_interface.h"
#include "components/drive/drive_pref_names.h"
#include "components/drive/service/fake_drive_service.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/api/test/test_api.h"
#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/notification_types.h"
#include "google_apis/drive/drive_api_parser.h"
#include "google_apis/drive/test_util.h"
#include "media/base/media_switches.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/service_manager/public/cpp/connector.h"
#include "storage/browser/fileapi/external_mount_points.h"
#include "ui/message_center/public/cpp/notification.h"

namespace file_manager {
namespace {

// During test, the test extensions can send a list of entries (directories
// or files) to add to a target volume using an AddEntriesMessage command.
//
// During a files app browser test, the "addEntries" message (see onCommand()
// below when name is "addEntries"). This adds them to the fake file system that
// is being used for testing.
//
// Here, we define some useful types to help parse the JSON from the addEntries
// format. The RegisterJSONConverter() method defines the expected types of each
// field from the message and which member variables to save them in.
//
// The "addEntries" message contains a vector of TestEntryInfo, which contains
// various nested subtypes:
//
//   * EntryType, which represents the type of entry (defined as an enum and
//     converted from the JSON string representation in MapStringToEntryType)
//
//   * SharedOption, representing whether the file is shared and appears in the
//     Shared with Me section of the app (similarly converted from the JSON
//     string representation to an enum for storing in MapStringToSharedOption)
//
//   * EntryCapabilities, which represents the capabilities (permissions) for
//     the new entry
//
//   * TestEntryInfo, which stores all of the above information, plus more
//     metadata about the entry.
//
// AddEntriesMessage contains an array of TestEntryInfo (one for each entry to
// add), plus the volume to add the entries to. It is constructed from JSON-
// parseable format as described in RegisterJSONConverter.
struct AddEntriesMessage {
  // Utility types.
  struct EntryCapabilities;
  struct TestEntryInfo;

  // Represents the various volumes available for adding entries.
  enum TargetVolume {
    LOCAL_VOLUME,
    DRIVE_VOLUME,
    CROSTINI_VOLUME,
    USB_VOLUME,
    ANDROID_FILES_VOLUME
  };

  // Represents the different types of entries (e.g. file, folder).
  enum EntryType { FILE, DIRECTORY, TEAM_DRIVE };

  // Represents whether an entry appears in 'Share with Me' or not.
  enum SharedOption { NONE, SHARED };

  // The actual AddEntriesMessage contents.

  // The volume to add |entries| to.
  TargetVolume volume;

  // The |entries| to be added.
  std::vector<std::unique_ptr<struct TestEntryInfo>> entries;

  // Converts |value| to an AddEntriesMessage: true on success.
  static bool ConvertJSONValue(const base::DictionaryValue& value,
                               AddEntriesMessage* message) {
    base::JSONValueConverter<AddEntriesMessage> converter;
    return converter.Convert(value, message);
  }

  // Registers AddEntriesMessage member info to the |converter|.
  static void RegisterJSONConverter(
      base::JSONValueConverter<AddEntriesMessage>* converter) {
    converter->RegisterCustomField("volume", &AddEntriesMessage::volume,
                                   &MapStringToTargetVolume);
    converter->RegisterRepeatedMessage<struct TestEntryInfo>(
        "entries", &AddEntriesMessage::entries);
  }

  // Maps |value| to TargetVolume. Returns true on success.
  static bool MapStringToTargetVolume(base::StringPiece value,
                                      TargetVolume* volume) {
    if (value == "local")
      *volume = LOCAL_VOLUME;
    else if (value == "drive")
      *volume = DRIVE_VOLUME;
    else if (value == "crostini")
      *volume = CROSTINI_VOLUME;
    else if (value == "usb")
      *volume = USB_VOLUME;
    else if (value == "android_files")
      *volume = ANDROID_FILES_VOLUME;
    else
      return false;
    return true;
  }

  // A message that specifies the capabilities (permissions) for the entry, in
  // a dictionary in JSON-parseable format.
  struct EntryCapabilities {
    EntryCapabilities()
        : can_copy(true),
          can_delete(true),
          can_rename(true),
          can_add_children(true),
          can_share(true) {}

    EntryCapabilities(bool can_copy,
                      bool can_delete,
                      bool can_rename,
                      bool can_add_children,
                      bool can_share)
        : can_copy(can_copy),
          can_delete(can_delete),
          can_rename(can_rename),
          can_add_children(can_add_children),
          can_share(can_share) {}

    bool can_copy;    // Whether the user can copy this file or directory.
    bool can_delete;  // Whether the user can delete this file or directory.
    bool can_rename;  // Whether the user can rename this file or directory.
    bool can_add_children;  // For directories, whether the user can add
                            // children to this directory.
    bool can_share;  // Whether the user can share this file or directory.

    static void RegisterJSONConverter(
        base::JSONValueConverter<EntryCapabilities>* converter) {
      converter->RegisterBoolField("canCopy", &EntryCapabilities::can_copy);
      converter->RegisterBoolField("canDelete", &EntryCapabilities::can_delete);
      converter->RegisterBoolField("canRename", &EntryCapabilities::can_rename);
      converter->RegisterBoolField("canAddChildren",
                                   &EntryCapabilities::can_add_children);
      converter->RegisterBoolField("canShare", &EntryCapabilities::can_share);
    }
  };

  // A message that specifies the metadata (name, shared options, capabilities
  // etc) for an entry, in a dictionary in JSON-parseable format.
  // This object must match TestEntryInfo in
  // ui/file_manager/integration_tests/test_util.js, which generates the message
  // that contains this object.
  struct TestEntryInfo {
    TestEntryInfo() : type(FILE), shared_option(NONE) {}

    TestEntryInfo(EntryType type,
                  const std::string& source_file_name,
                  const std::string& target_path,
                  const std::string& mime_type,
                  const std::string& team_drive_name,
                  SharedOption shared_option,
                  const base::Time& last_modified_time,
                  const EntryCapabilities& capabilities,
                  bool pinned)
        : type(type),
          shared_option(shared_option),
          source_file_name(source_file_name),
          target_path(target_path),
          team_drive_name(team_drive_name),
          mime_type(mime_type),
          last_modified_time(last_modified_time),
          capabilities(capabilities),
          pinned(pinned) {}

    EntryType type;                  // Entry type: file or directory.
    SharedOption shared_option;      // File entry sharing option.
    std::string source_file_name;    // Source file name prototype.
    std::string target_path;         // Target file or directory path.
    std::string name_text;           // Display file name.
    std::string team_drive_name;     // Name of team drive this entry is in.
    std::string mime_type;           // File entry content mime type.
    base::Time last_modified_time;   // Entry last modified time.
    EntryCapabilities capabilities;  // Entry permissions.
    bool pinned = false;             // Whether the file should be pinned.

    // Registers the member information to the given converter.
    static void RegisterJSONConverter(
        base::JSONValueConverter<TestEntryInfo>* converter) {
      converter->RegisterCustomField("type", &TestEntryInfo::type,
                                     &MapStringToEntryType);
      converter->RegisterStringField("sourceFileName",
                                     &TestEntryInfo::source_file_name);
      converter->RegisterStringField("targetPath", &TestEntryInfo::target_path);
      converter->RegisterStringField("nameText", &TestEntryInfo::name_text);
      converter->RegisterStringField("teamDriveName",
                                     &TestEntryInfo::team_drive_name);
      converter->RegisterStringField("mimeType", &TestEntryInfo::mime_type);
      converter->RegisterCustomField("sharedOption",
                                     &TestEntryInfo::shared_option,
                                     &MapStringToSharedOption);
      converter->RegisterCustomField("lastModifiedTime",
                                     &TestEntryInfo::last_modified_time,
                                     &MapStringToTime);
      converter->RegisterNestedField("capabilities",
                                     &TestEntryInfo::capabilities);
      converter->RegisterBoolField("pinned", &TestEntryInfo::pinned);
    }

    // Maps |value| to an EntryType. Returns true on success.
    static bool MapStringToEntryType(base::StringPiece value, EntryType* type) {
      if (value == "file")
        *type = FILE;
      else if (value == "directory")
        *type = DIRECTORY;
      else if (value == "team_drive")
        *type = TEAM_DRIVE;
      else
        return false;
      return true;
    }

    // Maps |value| to SharedOption. Returns true on success.
    static bool MapStringToSharedOption(base::StringPiece value,
                                        SharedOption* option) {
      if (value == "shared")
        *option = SHARED;
      else if (value == "none")
        *option = NONE;
      else
        return false;
      return true;
    }

    // Maps |value| to base::Time. Returns true on success.
    static bool MapStringToTime(base::StringPiece value, base::Time* time) {
      return base::Time::FromString(value.as_string().c_str(), time);
    }
  };
};

// Listens for chrome.test messages: PASS, FAIL, and SendMessage.
class FileManagerTestMessageListener : public content::NotificationObserver {
 public:
  struct Message {
    int type;
    std::string message;
    scoped_refptr<extensions::TestSendMessageFunction> function;
  };

  FileManagerTestMessageListener() {
    registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_TEST_PASSED,
                   content::NotificationService::AllSources());
    registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_TEST_FAILED,
                   content::NotificationService::AllSources());
    registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_TEST_MESSAGE,
                   content::NotificationService::AllSources());
  }

  Message GetNextMessage() {
    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

    if (messages_.empty()) {
      base::RunLoop run_loop;
      quit_closure_ = run_loop.QuitClosure();
      run_loop.Run();
    }

    DCHECK(!messages_.empty());
    const Message next = messages_.front();
    messages_.pop_front();
    return next;
  }

  void Observe(int type,
               const content::NotificationSource& source,
               const content::NotificationDetails& details) override {
    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

    Message message{type, std::string(), nullptr};
    if (type == extensions::NOTIFICATION_EXTENSION_TEST_PASSED) {
      test_complete_ = true;
    } else if (type == extensions::NOTIFICATION_EXTENSION_TEST_FAILED) {
      message.message = *content::Details<std::string>(details).ptr();
      test_complete_ = true;
    } else if (type == extensions::NOTIFICATION_EXTENSION_TEST_MESSAGE) {
      message.message = *content::Details<std::string>(details).ptr();
      using SendMessage = content::Source<extensions::TestSendMessageFunction>;
      message.function = SendMessage(source).ptr();
      using WillReply = content::Details<std::pair<std::string, bool*>>;
      *WillReply(details).ptr()->second = true;  // crbug.com/668680
      CHECK(!test_complete_) << "LATE MESSAGE: " << message.message;
    }

    messages_.push_back(message);
    if (quit_closure_) {
      std::move(quit_closure_).Run();
    }
  }

 private:
  bool test_complete_ = false;
  base::OnceClosure quit_closure_;
  base::circular_deque<Message> messages_;
  content::NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(FileManagerTestMessageListener);
};

// Test volume.
class TestVolume {
 protected:
  explicit TestVolume(const std::string& name) : name_(name) {}
  virtual ~TestVolume() = default;

  bool CreateRootDirectory(const Profile* profile) {
    if (root_initialized_)
      return true;
    root_ = profile->GetPath().Append(name_);
    root_initialized_ = base::CreateDirectory(root_);
    return root_initialized_;
  }

  const std::string& name() const { return name_; }
  const base::FilePath& root_path() const { return root_; }

  static base::FilePath GetTestDataFilePath(const std::string& file_name) {
    // Get the path to file manager's test data directory.
    base::FilePath source_dir;
    CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &source_dir));
    auto test_data_dir = source_dir.AppendASCII("chrome")
                             .AppendASCII("test")
                             .AppendASCII("data")
                             .AppendASCII("chromeos")
                             .AppendASCII("file_manager");
    // Return full test data path to the given |file_name|.
    return test_data_dir.Append(base::FilePath::FromUTF8Unsafe(file_name));
  }

 private:
  base::FilePath root_;
  bool root_initialized_ = false;
  std::string name_;

  DISALLOW_COPY_AND_ASSIGN(TestVolume);
};

class OfflineGetDriveConnectionState : public UIThreadExtensionFunction {
 public:
  OfflineGetDriveConnectionState() = default;

  ResponseAction Run() override {
    extensions::api::file_manager_private::DriveConnectionState result;
    result.type = "offline";
    return RespondNow(
        ArgumentList(extensions::api::file_manager_private::
                         GetDriveConnectionState::Results::Create(result)));
  }

 private:
  ~OfflineGetDriveConnectionState() override = default;

  DISALLOW_COPY_AND_ASSIGN(OfflineGetDriveConnectionState);
};

constexpr char kPredefinedProfileSalt[] = "salt";

}  // anonymous namespace

// LocalTestVolume: test volume for a local drive.
class LocalTestVolume : public TestVolume {
 public:
  explicit LocalTestVolume(const std::string& name) : TestVolume(name) {}
  ~LocalTestVolume() override = default;

  // Adds this local volume. Returns true on success.
  virtual bool Mount(Profile* profile) = 0;

  void CreateEntry(const AddEntriesMessage::TestEntryInfo& entry) {
    const base::FilePath target_path =
        root_path().AppendASCII(entry.target_path);

    entries_.insert(std::make_pair(target_path, entry));
    switch (entry.type) {
      case AddEntriesMessage::FILE: {
        const base::FilePath source_path =
            TestVolume::GetTestDataFilePath(entry.source_file_name);
        ASSERT_TRUE(base::CopyFile(source_path, target_path))
            << "Copy from " << source_path.value() << " to "
            << target_path.value() << " failed.";
        break;
      }
      case AddEntriesMessage::DIRECTORY:
        ASSERT_TRUE(base::CreateDirectory(target_path))
            << "Failed to create a directory: " << target_path.value();
        break;
      case AddEntriesMessage::TEAM_DRIVE:
        NOTREACHED() << "Can't create a team drive in a local volume: "
                     << target_path.value();
        break;
    }

    ASSERT_TRUE(UpdateModifiedTime(entry));
  }

 private:
  // Updates the ModifiedTime of the entry, and its parent directories if
  // needed. Returns true on success.
  bool UpdateModifiedTime(const AddEntriesMessage::TestEntryInfo& entry) {
    const base::FilePath path = root_path().AppendASCII(entry.target_path);
    if (!base::TouchFile(path, entry.last_modified_time,
                         entry.last_modified_time)) {
      return false;
    }

    // Update the modified time of parent directories because they may be
    // also affected by the update of child items.
    if (path.DirName() != root_path()) {
      const auto& it = entries_.find(path.DirName());
      if (it == entries_.end())
        return false;
      return UpdateModifiedTime(it->second);
    }

    return true;
  }

  std::map<base::FilePath, const AddEntriesMessage::TestEntryInfo> entries_;

  DISALLOW_COPY_AND_ASSIGN(LocalTestVolume);
};

// DownloadsTestVolume: local test volume for the "Downloads" directory.
class DownloadsTestVolume : public LocalTestVolume {
 public:
  DownloadsTestVolume() : LocalTestVolume("Downloads") {}
  ~DownloadsTestVolume() override = default;

  bool Mount(Profile* profile) override {
    if (!CreateRootDirectory(profile))
      return false;
    auto* volume = VolumeManager::Get(profile);
    return volume->RegisterDownloadsDirectoryForTesting(root_path());
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(DownloadsTestVolume);
};

class AndroidFilesTestVolume : public LocalTestVolume {
 public:
  AndroidFilesTestVolume() : LocalTestVolume("AndroidFiles") {}
  ~AndroidFilesTestVolume() override = default;

  bool Mount(Profile* profile) override {
    return CreateRootDirectory(profile) &&
           VolumeManager::Get(profile)->RegisterAndroidFilesDirectoryForTesting(
               root_path());
  }

  const base::FilePath& mount_path() const { return root_path(); }

  void Unmount(Profile* profile) {
    VolumeManager::Get(profile)->RemoveAndroidFilesDirectoryForTesting(
        root_path());
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(AndroidFilesTestVolume);
};

// CrostiniTestVolume: local test volume for the "Linux files" directory.
class CrostiniTestVolume : public LocalTestVolume {
 public:
  CrostiniTestVolume() : LocalTestVolume("Crostini") {}
  ~CrostiniTestVolume() override = default;

  // Create root dir so entries can be created, but volume is not mounted.
  bool Initialize(Profile* profile) { return CreateRootDirectory(profile); }

  bool Mount(Profile* profile) override {
    return CreateRootDirectory(profile) &&
           VolumeManager::Get(profile)->RegisterCrostiniDirectoryForTesting(
               root_path());
  }

  const base::FilePath& mount_path() const { return root_path(); }

 private:
  DISALLOW_COPY_AND_ASSIGN(CrostiniTestVolume);
};

// FakeTestVolume: local test volume with a given volume and device type.
class FakeTestVolume : public LocalTestVolume {
 public:
  FakeTestVolume(const std::string& name,
                 VolumeType volume_type,
                 chromeos::DeviceType device_type)
      : LocalTestVolume(name),
        volume_type_(volume_type),
        device_type_(device_type) {}
  ~FakeTestVolume() override = default;

  // Add the fake test volume entries.
  bool PrepareTestEntries(Profile* profile) {
    if (!CreateRootDirectory(profile))
      return false;

    // Note: must be kept in sync with BASIC_FAKE_ENTRY_SET defined in the
    // integration_tests/file_manager JS code.
    CreateEntry(AddEntriesMessage::TestEntryInfo(
        AddEntriesMessage::FILE, "text.txt", "hello.txt", std::string(),
        "text/plain", AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
        AddEntriesMessage::EntryCapabilities(), false));
    CreateEntry(AddEntriesMessage::TestEntryInfo(
        AddEntriesMessage::DIRECTORY, std::string(), "A", std::string(),
        std::string(), AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
        AddEntriesMessage::EntryCapabilities(), false));
    base::RunLoop().RunUntilIdle();
    return true;
  }

  bool PrepareDcimTestEntries(Profile* profile) {
    if (!CreateRootDirectory(profile))
      return false;

    CreateEntry(AddEntriesMessage::TestEntryInfo(
        AddEntriesMessage::DIRECTORY, "", "DCIM", std::string(), "",
        AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
        AddEntriesMessage::EntryCapabilities(), false));
    CreateEntry(AddEntriesMessage::TestEntryInfo(
        AddEntriesMessage::FILE, "image2.png", "image2.png", std::string(),
        "image/png", AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
        AddEntriesMessage::EntryCapabilities(), false));
    CreateEntry(AddEntriesMessage::TestEntryInfo(
        AddEntriesMessage::FILE, "image3.jpg", "DCIM/image3.jpg", std::string(),
        "image/jpeg", AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
        AddEntriesMessage::EntryCapabilities(), false));
    CreateEntry(AddEntriesMessage::TestEntryInfo(
        AddEntriesMessage::FILE, "text.txt", "DCIM/hello.txt", std::string(),
        "text/plain", AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
        AddEntriesMessage::EntryCapabilities(), false));
    base::RunLoop().RunUntilIdle();
    return true;
  }

  bool Mount(Profile* profile) override {
    if (!CreateRootDirectory(profile))
      return false;

    // Revoke name() mount point first, then re-add its mount point.
    GetMountPoints()->RevokeFileSystem(name());
    const bool added = GetMountPoints()->RegisterFileSystem(
        name(), storage::kFileSystemTypeNativeLocal,
        storage::FileSystemMountOption(), root_path());
    if (!added)
      return false;

    // Expose the mount point with the given volume and device type.
    VolumeManager::Get(profile)->AddVolumeForTesting(root_path(), volume_type_,
                                                     device_type_, read_only_);
    base::RunLoop().RunUntilIdle();
    return true;
  }

 private:
  storage::ExternalMountPoints* GetMountPoints() {
    return storage::ExternalMountPoints::GetSystemInstance();
  }

  const VolumeType volume_type_;
  const chromeos::DeviceType device_type_;
  const bool read_only_ = false;

  DISALLOW_COPY_AND_ASSIGN(FakeTestVolume);
};

// DriveTestVolume: test volume for Google Drive.
class DriveTestVolume : public TestVolume {
 public:
  DriveTestVolume() : TestVolume("drive") {}
  ~DriveTestVolume() override = default;

  virtual void CreateEntry(const AddEntriesMessage::TestEntryInfo& entry) {
    const base::FilePath path =
        base::FilePath::FromUTF8Unsafe(entry.target_path);
    const std::string target_name = path.BaseName().AsUTF8Unsafe();

    // Obtain the parent entry.
    drive::FileError error = drive::FILE_ERROR_OK;
    std::unique_ptr<drive::ResourceEntry> parent_entry(
        new drive::ResourceEntry);

    if (!entry.team_drive_name.empty()) {
      integration_service_->file_system()->GetResourceEntry(
          drive::util::GetDriveTeamDrivesRootPath()
              .Append(entry.team_drive_name)
              .Append(path)
              .DirName(),
          google_apis::test_util::CreateCopyResultCallback(&error,
                                                           &parent_entry));
    } else {
      integration_service_->file_system()->GetResourceEntry(
          drive::util::GetDriveMyDriveRootPath().Append(path).DirName(),
          google_apis::test_util::CreateCopyResultCallback(&error,
                                                           &parent_entry));
    }
    content::RunAllTasksUntilIdle();
    ASSERT_EQ(drive::FILE_ERROR_OK, error);
    ASSERT_TRUE(parent_entry);

    // Create the capabilities object.
    google_apis::FileResourceCapabilities file_capabilities;
    file_capabilities.set_can_copy(entry.capabilities.can_copy);
    file_capabilities.set_can_delete(entry.capabilities.can_delete);
    file_capabilities.set_can_rename(entry.capabilities.can_rename);
    file_capabilities.set_can_add_children(entry.capabilities.can_add_children);
    file_capabilities.set_can_share(entry.capabilities.can_share);

    google_apis::TeamDriveCapabilities team_drive_capabilities;
    team_drive_capabilities.set_can_copy(entry.capabilities.can_copy);
    team_drive_capabilities.set_can_delete_team_drive(
        entry.capabilities.can_delete);
    team_drive_capabilities.set_can_rename_team_drive(
        entry.capabilities.can_rename);
    team_drive_capabilities.set_can_add_children(
        entry.capabilities.can_add_children);
    team_drive_capabilities.set_can_share(entry.capabilities.can_share);

    // Add the file or directory entry.
    switch (entry.type) {
      case AddEntriesMessage::FILE:
        CreateFile(entry.source_file_name, parent_entry->resource_id(),
                   target_name, entry.mime_type,
                   entry.shared_option == AddEntriesMessage::SHARED,
                   entry.last_modified_time, file_capabilities);
        break;
      case AddEntriesMessage::DIRECTORY:
        CreateDirectory(parent_entry->resource_id(), target_name,
                        entry.last_modified_time, file_capabilities);
        break;
      case AddEntriesMessage::TEAM_DRIVE:
        CreateTeamDrive(entry.team_drive_name, team_drive_capabilities);
        break;
    }

    // Any file or directory created above, will only appear in Drive after
    // CheckForUpdates() has completed.
    CheckForUpdates();
    content::RunAllTasksUntilIdle();
  }

  // Creates a new Team Drive with ID |name| and name |name|, and sets the
  // capabilities to |capabilities|.
  void CreateTeamDrive(const std::string& name,
                       google_apis::TeamDriveCapabilities capabilities) {
    fake_drive_service_->AddTeamDrive(name, name);
    fake_drive_service_->SetTeamDriveCapabilities(name, capabilities);
  }

  // Creates an empty directory with the given |name| and |modification_time|.
  void CreateDirectory(
      const std::string& parent_id,
      const std::string& target_name,
      const base::Time& modification_time,
      const google_apis::FileResourceCapabilities& capabilities) {
    google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;

    std::unique_ptr<google_apis::FileResource> entry;
    fake_drive_service_->AddNewDirectory(
        parent_id, target_name, drive::AddNewDirectoryOptions(),
        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    base::RunLoop().RunUntilIdle();
    ASSERT_EQ(google_apis::HTTP_CREATED, error);
    ASSERT_TRUE(entry);

    fake_drive_service_->SetLastModifiedTime(
        entry->file_id(), modification_time,
        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    base::RunLoop().RunUntilIdle();
    ASSERT_TRUE(error == google_apis::HTTP_SUCCESS);
    ASSERT_TRUE(entry);

    fake_drive_service_->SetFileCapabilities(
        entry->file_id(), capabilities,
        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    base::RunLoop().RunUntilIdle();
    ASSERT_TRUE(error == google_apis::HTTP_SUCCESS);
    ASSERT_TRUE(entry);
  }

  // Creates a test file with the given spec.
  // Serves |test_file_name| file. Pass an empty string for an empty file.
  void CreateFile(const std::string& source_file_name,
                  const std::string& parent_id,
                  const std::string& target_name,
                  const std::string& mime_type,
                  bool shared_with_me,
                  const base::Time& modification_time,
                  const google_apis::FileResourceCapabilities& capabilities) {
    google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;

    std::string content_data;
    if (!source_file_name.empty()) {
      base::FilePath source_path =
          TestVolume::GetTestDataFilePath(source_file_name);
      ASSERT_TRUE(base::ReadFileToString(source_path, &content_data));
    }

    std::unique_ptr<google_apis::FileResource> entry;
    fake_drive_service_->AddNewFile(
        mime_type, content_data, parent_id, target_name, shared_with_me,
        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    base::RunLoop().RunUntilIdle();
    ASSERT_EQ(google_apis::HTTP_CREATED, error);
    ASSERT_TRUE(entry);

    fake_drive_service_->SetLastModifiedTime(
        entry->file_id(), modification_time,
        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    base::RunLoop().RunUntilIdle();
    ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
    ASSERT_TRUE(entry);

    fake_drive_service_->SetFileCapabilities(
        entry->file_id(), capabilities,
        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    base::RunLoop().RunUntilIdle();
    ASSERT_TRUE(error == google_apis::HTTP_SUCCESS);
    ASSERT_TRUE(entry);
  }

  // Notifies FileSystem that the contents in FakeDriveService have changed,
  // hence the new contents should be fetched.
  void CheckForUpdates() {
    if (integration_service_ && integration_service_->file_system()) {
      integration_service_->file_system()->CheckForUpdates();
    }
  }

  drive::DriveIntegrationService* CreateDriveIntegrationService(
      Profile* profile) {
    if (!CreateRootDirectory(profile))
      return nullptr;

    EXPECT_FALSE(profile_);
    profile_ = profile;

    EXPECT_FALSE(fake_drive_service_);
    fake_drive_service_ = new drive::FakeDriveService;

    EXPECT_FALSE(integration_service_);
    integration_service_ = new drive::DriveIntegrationService(
        profile, nullptr, fake_drive_service_, std::string(),
        root_path().Append("v1"), nullptr, CreateDriveFsConnectionDelegate());

    return integration_service_;
  }

 private:
  virtual base::RepeatingCallback<
      std::unique_ptr<drivefs::DriveFsHost::MojoConnectionDelegate>()>
  CreateDriveFsConnectionDelegate() {
    return {};
  }

  // Profile associated with this volume: not owned.
  Profile* profile_ = nullptr;
  // Fake drive service used for testing: not owned.
  drive::FakeDriveService* fake_drive_service_ = nullptr;
  // Integration service used for testing: not owned.
  drive::DriveIntegrationService* integration_service_ = nullptr;

  DISALLOW_COPY_AND_ASSIGN(DriveTestVolume);
};

// DriveFsTestVolume: test volume for Google Drive using DriveFS.
class DriveFsTestVolume : public DriveTestVolume {
 public:
  explicit DriveFsTestVolume(Profile* profile) : profile_(profile) {}
  ~DriveFsTestVolume() override = default;

  void CreateEntry(const AddEntriesMessage::TestEntryInfo& entry) override {
    const base::FilePath target_path = GetTargetPathForTestEntry(entry);

    entries_.insert(std::make_pair(target_path, entry));
    switch (entry.type) {
      case AddEntriesMessage::FILE: {
        fake_drivefs_->SetMetadata(
            GetRelativeDrivePathForTestEntry(entry), entry.mime_type,
            base::FilePath(entry.target_path).BaseName().value(), entry.pinned,
            entry.shared_option == AddEntriesMessage::SharedOption::SHARED);

        if (entry.source_file_name.empty()) {
          ASSERT_EQ(0, base::WriteFile(target_path, "", 0));
          break;
        }
        const base::FilePath source_path =
            TestVolume::GetTestDataFilePath(entry.source_file_name);
        ASSERT_TRUE(base::CopyFile(source_path, target_path))
            << "Copy from " << source_path.value() << " to "
            << target_path.value() << " failed.";
        break;
      }
      case AddEntriesMessage::DIRECTORY:
        ASSERT_TRUE(base::CreateDirectory(target_path))
            << "Failed to create a directory: " << target_path.value();
        break;
      case AddEntriesMessage::TEAM_DRIVE:
        ASSERT_TRUE(base::CreateDirectory(target_path))
            << "Failed to create a team drive: " << target_path.value();
        break;
    }

    ASSERT_TRUE(UpdateModifiedTime(entry));
  }

 private:
  base::RepeatingCallback<
      std::unique_ptr<drivefs::DriveFsHost::MojoConnectionDelegate>()>
  CreateDriveFsConnectionDelegate() override {
    CHECK(base::CreateDirectory(GetMyDrivePath()));
    CHECK(base::CreateDirectory(GetTeamDriveGrandRoot()));

    InitializeFakeDriveFs();
    return base::BindRepeating(&drivefs::FakeDriveFs::CreateConnectionDelegate,
                               base::Unretained(fake_drivefs_.get()));
  }

  void InitializeFakeDriveFs() {
    fake_drivefs_ = std::make_unique<drivefs::FakeDriveFs>(mount_path());
    fake_drivefs_->RegisterMountingForAccountId(base::BindRepeating(
        [](Profile* profile) {
          auto* user =
              chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
          if (!user)
            return std::string();

          return base::MD5String(
              kPredefinedProfileSalt +
              ("-" + user->GetAccountId().GetAccountIdKey()));
        },
        profile_));
  }

  // Updates the ModifiedTime of the entry, and its parent directories if
  // needed. Returns true on success.
  bool UpdateModifiedTime(const AddEntriesMessage::TestEntryInfo& entry) {
    const auto path = GetTargetPathForTestEntry(entry);
    if (!base::TouchFile(path, entry.last_modified_time,
                         entry.last_modified_time)) {
      return false;
    }

    // Update the modified time of parent directories because they may be
    // also affected by the update of child items.
    if (path.DirName() != GetTeamDriveGrandRoot() &&
        path.DirName() != GetMyDrivePath()) {
      const auto it = entries_.find(path.DirName());
      if (it == entries_.end())
        return false;
      return UpdateModifiedTime(it->second);
    }

    return true;
  }

  base::FilePath GetTargetPathForTestEntry(
      const AddEntriesMessage::TestEntryInfo& entry) {
    const base::FilePath target_path =
        entry.team_drive_name.empty()
            ? GetMyDrivePath().Append(entry.target_path)
            : GetTeamDrivePath(entry.team_drive_name).Append(entry.target_path);
    if (entry.name_text != entry.target_path)
      return target_path.DirName().Append(entry.name_text);
    return target_path;
  }

  base::FilePath GetRelativeDrivePathForTestEntry(
      const AddEntriesMessage::TestEntryInfo& entry) {
    const base::FilePath target_path = GetTargetPathForTestEntry(entry);
    base::FilePath drive_path("/");
    CHECK(mount_path().AppendRelativePath(target_path, &drive_path));
    return drive_path;
  }

  base::FilePath mount_path() { return root_path().Append("v2"); }

  base::FilePath GetMyDrivePath() { return mount_path().Append("root"); }

  base::FilePath GetTeamDriveGrandRoot() {
    return mount_path().Append("team_drives");
  }

  base::FilePath GetTeamDrivePath(const std::string& team_drive_name) {
    return GetTeamDriveGrandRoot().Append(team_drive_name);
  }

  Profile* const profile_;
  std::map<base::FilePath, const AddEntriesMessage::TestEntryInfo> entries_;
  std::unique_ptr<drivefs::FakeDriveFs> fake_drivefs_;

  DISALLOW_COPY_AND_ASSIGN(DriveFsTestVolume);
};

FileManagerBrowserTestBase::FileManagerBrowserTestBase() = default;

FileManagerBrowserTestBase::~FileManagerBrowserTestBase() = default;

void FileManagerBrowserTestBase::SetUp() {
  net::NetworkChangeNotifier::SetTestNotificationsOnly(true);
  extensions::ExtensionApiTest::SetUp();
}

void FileManagerBrowserTestBase::SetUpCommandLine(
    base::CommandLine* command_line) {
  // Use a fake audio stream crbug.com/835626
  command_line->AppendSwitch(switches::kDisableAudioOutput);

  if (!GetRequiresStartupBrowser()) {
    // Don't sink time into showing an unused browser window.
    // InProcessBrowserTest::browser() will be null.
    command_line->AppendSwitch(switches::kNoStartupWindow);

    // Without a browser window, opening an app window, then closing it will
    // trigger browser shutdown. Usually this is fine, except it also prevents
    // any _new_ app window being created, should a test want to do that.
    // (At the time of writing, exactly one does).
    // Although in this path no browser is created (and so one can never
    // close..), setting this to false prevents InProcessBrowserTest from adding
    // the kDisableZeroBrowsersOpenForTests flag, which would prevent
    // chrome_browser_main_chromeos from adding the keepalive that normally
    // stops chromeos from shutting down unexpectedly.
    set_exit_when_last_browser_closes(false);
  }

  if (IsGuestModeTest()) {
    command_line->AppendSwitch(chromeos::switches::kGuestSession);
    command_line->AppendSwitchNative(chromeos::switches::kLoginUser, "$guest");
    command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
    command_line->AppendSwitch(switches::kIncognito);
    set_chromeos_user_ = false;
  }

  if (IsIncognitoModeTest()) {
    command_line->AppendSwitch(switches::kIncognito);
  }

  std::vector<base::Feature> enabled_features;
  if (!IsGuestModeTest()) {
    enabled_features.emplace_back(features::kCrostini);
    enabled_features.emplace_back(features::kExperimentalCrostiniUI);
    command_line->AppendSwitch(chromeos::switches::kCrostiniFiles);
  }
  if (IsDriveFsTest()) {
    enabled_features.emplace_back(chromeos::features::kDriveFs);
  }
  feature_list_.InitWithFeatures(enabled_features, {});

  extensions::ExtensionApiTest::SetUpCommandLine(command_line);
}

bool FileManagerBrowserTestBase::SetUpUserDataDirectory() {
  if (IsGuestModeTest())
    return true;

  auto known_users_list = std::make_unique<base::ListValue>();
  auto user_dict = std::make_unique<base::DictionaryValue>();
  user_dict->SetString("account_type", "google");
  user_dict->SetString("email", "testuser@gmail.com");
  user_dict->SetString("gaia_id", "123456");
  known_users_list->Append(std::move(user_dict));

  base::DictionaryValue local_state;
  local_state.SetList("KnownUsers", std::move(known_users_list));

  std::string local_state_json;
  if (!base::JSONWriter::Write(local_state, &local_state_json))
    return false;

  base::FilePath local_state_file;
  if (!base::PathService::Get(chrome::DIR_USER_DATA, &local_state_file))
    return false;
  local_state_file = local_state_file.Append(chrome::kLocalStateFilename);
  return base::WriteFile(local_state_file, local_state_json.data(),
                         local_state_json.size()) != -1;
}

void FileManagerBrowserTestBase::SetUpInProcessBrowserTestFixture() {
  extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();

  local_volume_ = std::make_unique<DownloadsTestVolume>();

  if (!IsGuestModeTest()) {
    create_drive_integration_service_ =
        base::Bind(&FileManagerBrowserTestBase::CreateDriveIntegrationService,
                   base::Unretained(this));
    service_factory_for_test_ = std::make_unique<
        drive::DriveIntegrationServiceFactory::ScopedFactoryForTest>(
        &create_drive_integration_service_);
  }
}

void FileManagerBrowserTestBase::SetUpOnMainThread() {
  // Must happen after the browser process is created because instantiating
  // the factory will instantiate ExtensionSystemFactory which depends on
  // ExtensionsBrowserClient setup in BrowserProcessImpl.
  sync_file_system::SyncFileSystemServiceFactory::GetInstance()
      ->set_mock_remote_file_service(
          std::make_unique<::testing::NiceMock<
              sync_file_system::MockRemoteFileSyncService>>());

  extensions::ExtensionApiTest::SetUpOnMainThread();
  CHECK(profile());
  CHECK_EQ(!!browser(), GetRequiresStartupBrowser());

  CHECK(local_volume_->Mount(profile()));

  if (!IsGuestModeTest()) {
    // Start the embedded test server to serve the mocked CWS widget container.
    CHECK(embedded_test_server()->Start());
    drive_volume_ = drive_volumes_[profile()->GetOriginalProfile()].get();
    test_util::WaitUntilDriveMountPointIsAdded(profile());

    // Init crostini.  Set prefs to enable crostini and register
    // CustomMountPointCallback. TODO(joelhockey): It would be better if the
    // crostini interface allowed for testing without such tight coupling.
    crostini_volume_ = std::make_unique<CrostiniTestVolume>();
    profile()->GetPrefs()->SetBoolean(crostini::prefs::kCrostiniEnabled, true);
    crostini::CrostiniManager::GetForProfile(profile()->GetOriginalProfile())
        ->set_skip_restart_for_testing();
    chromeos::DBusThreadManager* dbus_thread_manager =
        chromeos::DBusThreadManager::Get();
    static_cast<chromeos::FakeCrosDisksClient*>(
        dbus_thread_manager->GetCrosDisksClient())
        ->AddCustomMountPointCallback(
            base::BindRepeating(&FileManagerBrowserTestBase::MaybeMountCrostini,
                                base::Unretained(this)));

    android_files_volume_ = std::make_unique<AndroidFilesTestVolume>();
    android_files_volume_->Mount(profile());
  }

  display_service_ =
      std::make_unique<NotificationDisplayServiceTester>(profile());

  if (IsOfflineTest()) {
    ExtensionFunctionRegistry::GetInstance().OverrideFunctionForTesting(
        "fileManagerPrivate.getDriveConnectionState",
        &NewExtensionFunction<OfflineGetDriveConnectionState>);
  }

  // The test resources are setup: enable and add default ChromeOS component
  // extensions now and not before: crbug.com/831074, crbug.com/804413
  test::AddDefaultComponentExtensionsOnMainThread(profile());

  // For tablet mode tests, enable the Ash virtual keyboard.
  if (IsTabletModeTest()) {
    EnableVirtualKeyboard();
  }
}

bool FileManagerBrowserTestBase::GetTabletMode() const {
  return false;
}

bool FileManagerBrowserTestBase::GetEnableDriveFs() const {
  return false;
}

bool FileManagerBrowserTestBase::GetRequiresStartupBrowser() const {
  return false;
}

bool FileManagerBrowserTestBase::GetNeedsZipSupport() const {
  return false;
}

bool FileManagerBrowserTestBase::GetIsOffline() const {
  return false;
}

void FileManagerBrowserTestBase::StartTest() {
  LOG(INFO) << "FileManagerBrowserTest::StartTest " << GetFullTestCaseName();
  static const base::FilePath test_extension_dir =
      base::FilePath(FILE_PATH_LITERAL("ui/file_manager/integration_tests"));
  LaunchExtension(test_extension_dir, GetTestExtensionManifestName());
  RunTestMessageLoop();
}

void FileManagerBrowserTestBase::LaunchExtension(const base::FilePath& path,
                                                 const char* manifest_name) {
  base::FilePath source_dir;
  CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &source_dir));

  const base::FilePath source_path = source_dir.Append(path);
  const extensions::Extension* const extension_launched =
      LoadExtensionAsComponentWithManifest(source_path, manifest_name);
  CHECK(extension_launched) << "Launching: " << manifest_name;
}

void FileManagerBrowserTestBase::RunTestMessageLoop() {
  FileManagerTestMessageListener listener;

  while (true) {
    auto message = listener.GetNextMessage();

    if (message.type == extensions::NOTIFICATION_EXTENSION_TEST_PASSED)
      return;  // Test PASSED.
    if (message.type == extensions::NOTIFICATION_EXTENSION_TEST_FAILED) {
      ADD_FAILURE() << message.message;
      return;  // Test FAILED.
    }

    // If the message in JSON format has no command, ignore it
    // but note a reply is required: use std::string().
    const auto json = base::JSONReader::Read(message.message);
    const base::DictionaryValue* dictionary = nullptr;
    std::string command;
    if (!json || !json->GetAsDictionary(&dictionary) ||
        !dictionary->GetString("name", &command)) {
      message.function->Reply(std::string());
      continue;
    }

    // Process the command, reply with the result.
    std::string result;
    OnCommand(command, *dictionary, &result);
    if (!HasFatalFailure()) {
      message.function->Reply(result);
      continue;
    }

    // Test FAILED: while processing the command.
    LOG(INFO) << "[FAILED] " << GetTestCaseName();
    return;
  }
}

void FileManagerBrowserTestBase::OnCommand(const std::string& name,
                                           const base::DictionaryValue& value,
                                           std::string* output) {
  base::ScopedAllowBlockingForTesting allow_blocking;

  if (name == "isInGuestMode") {
    // Obtain if the test runs in guest or incognito mode, or not.
    if (IsGuestModeTest() || IsIncognitoModeTest()) {
      LOG(INFO) << GetTestCaseName() << " isInGuestMode: true";
      *output = "true";
    } else {
      ASSERT_EQ(NOT_IN_GUEST_MODE, GetGuestMode());
      *output = "false";
    }

    return;
  }

  if (name == "getRootPaths") {
    // Obtain the root paths.
    const auto downloads_root = util::GetDownloadsMountPointName(profile());

    base::DictionaryValue dictionary;
    dictionary.SetString("downloads", "/" + downloads_root);

    if (!profile()->IsGuestSession()) {
      auto* drive_integration_service =
          drive::DriveIntegrationServiceFactory::GetForProfile(profile());
      if (drive_integration_service->IsMounted()) {
        const auto drive_mount_name =
            base::FilePath(drive_integration_service->GetMountPointPath())
                .BaseName();
        dictionary.SetString(
            "drive", base::StrCat({"/", drive_mount_name.value(), "/root"}));
      }
      if (android_files_volume_) {
        dictionary.SetString("android_files",
                             "/" + util::GetAndroidFilesMountPointName());
      }
    }
    base::JSONWriter::Write(dictionary, output);
    return;
  }

  if (name == "getTestName") {
    // Obtain the test case name.
    *output = GetTestCaseName();
    return;
  }

  if (name == "getCwsWidgetContainerMockUrl") {
    // Obtain the mock CWS widget container URL and URL.origin.
    const GURL url = embedded_test_server()->GetURL(
        "/chromeos/file_manager/cws_container_mock/index.html");
    std::string origin = url.GetOrigin().spec();
    if (*origin.rbegin() == '/')  // Strip origin trailing '/'.
      origin.resize(origin.length() - 1);

    base::DictionaryValue dictionary;
    dictionary.SetString("url", url.spec());
    dictionary.SetString("origin", origin);

    base::JSONWriter::Write(dictionary, output);
    return;
  }

  if (name == "addEntries") {
    // Add the message.entries to the message.volume.
    AddEntriesMessage message;
    ASSERT_TRUE(AddEntriesMessage::ConvertJSONValue(value, &message));

    for (size_t i = 0; i < message.entries.size(); ++i) {
      switch (message.volume) {
        case AddEntriesMessage::LOCAL_VOLUME:
          local_volume_->CreateEntry(*message.entries[i]);
          break;
        case AddEntriesMessage::CROSTINI_VOLUME:
          CHECK(crostini_volume_);
          ASSERT_TRUE(crostini_volume_->Initialize(profile()));
          crostini_volume_->CreateEntry(*message.entries[i]);
          break;
        case AddEntriesMessage::DRIVE_VOLUME:
          if (drive_volume_) {
            drive_volume_->CreateEntry(*message.entries[i]);
          } else if (!IsGuestModeTest()) {
            LOG(FATAL) << "Add entry: but no Drive volume.";
          }
          break;
        case AddEntriesMessage::USB_VOLUME:
          if (usb_volume_) {
            usb_volume_->CreateEntry(*message.entries[i]);
          } else {
            LOG(FATAL) << "Add entry: but no USB volume.";
          }
          break;
        case AddEntriesMessage::ANDROID_FILES_VOLUME:
          if (android_files_volume_) {
            android_files_volume_->CreateEntry(*message.entries[i]);
          } else {
            LOG(FATAL) << "Add entry: but no Android files volume.";
          }
          break;
      }
    }

    return;
  }

  if (name == "mountFakeUsb" || name == "mountFakeUsbEmpty" ||
      name == "mountFakeUsbDcim") {
    usb_volume_ = std::make_unique<FakeTestVolume>(
        "fake-usb", VOLUME_TYPE_REMOVABLE_DISK_PARTITION,
        chromeos::DEVICE_TYPE_USB);

    if (name == "mountFakeUsb")
      ASSERT_TRUE(usb_volume_->PrepareTestEntries(profile()));
    else if (name == "mountFakeUsbDcim")
      ASSERT_TRUE(usb_volume_->PrepareDcimTestEntries(profile()));

    ASSERT_TRUE(usb_volume_->Mount(profile()));
    return;
  }

  if (name == "mountFakeMtp" || name == "mountFakeMtpEmpty") {
    mtp_volume_ = std::make_unique<FakeTestVolume>(
        "fake-mtp", VOLUME_TYPE_MTP, chromeos::DEVICE_TYPE_UNKNOWN);

    if (name == "mountFakeMtp")
      ASSERT_TRUE(mtp_volume_->PrepareTestEntries(profile()));

    ASSERT_TRUE(mtp_volume_->Mount(profile()));
    return;
  }

  if (name == "useCellularNetwork") {
    net::NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChangeForTests(
        net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
            net::NetworkChangeNotifier::SUBTYPE_HSPA),
        net::NetworkChangeNotifier::CONNECTION_3G);
    return;
  }

  if (name == "clickNotificationButton") {
    std::string extension_id;
    std::string notification_id;
    ASSERT_TRUE(value.GetString("extensionId", &extension_id));
    ASSERT_TRUE(value.GetString("notificationId", &notification_id));

    const std::string delegate_id = extension_id + "-" + notification_id;
    base::Optional<message_center::Notification> notification =
        display_service_->GetNotification(delegate_id);
    EXPECT_TRUE(notification);

    int index;
    ASSERT_TRUE(value.GetInteger("index", &index));
    display_service_->SimulateClick(NotificationHandler::Type::EXTENSION,
                                    delegate_id, index, base::nullopt);
    return;
  }

  if (name == "launchProviderExtension") {
    std::string manifest;
    ASSERT_TRUE(value.GetString("manifest", &manifest));
    LaunchExtension(base::FilePath(FILE_PATH_LITERAL(
                        "ui/file_manager/integration_tests/testing_provider")),
                    manifest.c_str());
    return;
  }

  FAIL() << "Unknown test message: " << name;
}

drive::DriveIntegrationService*
FileManagerBrowserTestBase::CreateDriveIntegrationService(Profile* profile) {
  if (base::FeatureList::IsEnabled(chromeos::features::kDriveFs)) {
    profile->GetPrefs()->SetString(drive::prefs::kDriveFsProfileSalt,
                                   kPredefinedProfileSalt);
    drive_volumes_[profile->GetOriginalProfile()] =
        std::make_unique<DriveFsTestVolume>(profile->GetOriginalProfile());
    if (!IsIncognitoModeTest()) {
      base::ThreadTaskRunnerHandle::Get()->PostTask(
          FROM_HERE,
          base::BindOnce(base::IgnoreResult(&LocalTestVolume::Mount),
                         base::Unretained(local_volume_.get()), profile));
    }
  } else {
    drive_volumes_[profile->GetOriginalProfile()] =
        std::make_unique<DriveTestVolume>();
  }
  return drive_volumes_[profile->GetOriginalProfile()]
      ->CreateDriveIntegrationService(profile);
}

base::FilePath FileManagerBrowserTestBase::MaybeMountCrostini(
    const std::string& source_path,
    const std::vector<std::string>& mount_options) {
  GURL source_url(source_path);
  DCHECK(source_url.is_valid());
  if (source_url.scheme() != "sshfs") {
    return {};
  }
  // Mount crostini volume, and set VM now running for CrostiniManager.
  CHECK(crostini_volume_->Mount(profile()));
  crostini::CrostiniManager* crostini_manager =
      crostini::CrostiniManager::GetForProfile(profile()->GetOriginalProfile());
  vm_tools::concierge::VmInfo vm_info;
  crostini_manager->AddRunningVmForTesting(kCrostiniDefaultVmName,
                                           std::move(vm_info));
  return crostini_volume_->mount_path();
}

void FileManagerBrowserTestBase::EnableVirtualKeyboard() {
  CHECK(IsTabletModeTest());

  ash::mojom::ShellTestApiPtr shell_test_api;
  content::ServiceManagerConnection::GetForProcess()
      ->GetConnector()
      ->BindInterface(ash::mojom::kServiceName, &shell_test_api);
  ash::mojom::ShellTestApiAsyncWaiter waiter(shell_test_api.get());
  waiter.EnableVirtualKeyboard();
}

}  // namespace file_manager
