// Copyright 2014 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 "components/storage_monitor/storage_monitor_chromeos.h"

#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task_runner_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "chromeos/disks/disk.h"
#include "components/storage_monitor/media_storage_util.h"
#include "components/storage_monitor/mtp_manager_client_chromeos.h"
#include "components/storage_monitor/removable_device_constants.h"
#include "content/public/browser/browser_thread.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"

using chromeos::disks::Disk;
using chromeos::disks::DiskMountManager;

namespace storage_monitor {

namespace {

// Constructs a device id using uuid or manufacturer (vendor and product) id
// details.
std::string MakeDeviceUniqueId(const Disk& disk) {
  std::string uuid = disk.fs_uuid();
  if (!uuid.empty())
    return kFSUniqueIdPrefix + uuid;

  // If one of the vendor or product information is missing, its value in the
  // string is empty.
  // Format: VendorModelSerial:VendorInfo:ModelInfo:SerialInfo
  // TODO(kmadhusu) Extract serial information for the disks and append it to
  // the device unique id.
  const std::string& vendor = disk.vendor_id();
  const std::string& product = disk.product_id();
  if (vendor.empty() && product.empty())
    return std::string();
  return kVendorModelSerialPrefix + vendor + ":" + product + ":";
}

// Returns whether the requested device is valid. On success |info| will contain
// device information.
bool GetDeviceInfo(const DiskMountManager::MountPointInfo& mount_info,
                   bool has_dcim,
                   StorageInfo* info) {
  DCHECK(info);
  std::string source_path = mount_info.source_path;

  const Disk* disk =
      DiskMountManager::GetInstance()->FindDiskBySourcePath(source_path);
  if (!disk || disk->device_type() == chromeos::DEVICE_TYPE_UNKNOWN)
    return false;

  std::string unique_id = MakeDeviceUniqueId(*disk);
  if (unique_id.empty())
    return false;

  StorageInfo::Type type = has_dcim ?
      StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM :
      StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM;

  *info = StorageInfo(
      StorageInfo::MakeDeviceId(type, unique_id), mount_info.mount_path,
      base::UTF8ToUTF16(disk->device_label()),
      base::UTF8ToUTF16(disk->vendor_name()),
      base::UTF8ToUTF16(disk->product_name()), disk->total_size_in_bytes());
  return true;
}

// Returns whether the requested device is valid. On success |info| will contain
// fixed storage device information.
bool GetFixedStorageInfo(const Disk& disk, StorageInfo* info) {
  DCHECK(info);

  std::string unique_id = MakeDeviceUniqueId(disk);
  if (unique_id.empty())
    return false;

  *info = StorageInfo(
      StorageInfo::MakeDeviceId(StorageInfo::FIXED_MASS_STORAGE, unique_id),
      disk.mount_path(), base::UTF8ToUTF16(disk.device_label()),
      base::UTF8ToUTF16(disk.vendor_name()),
      base::UTF8ToUTF16(disk.product_name()), disk.total_size_in_bytes());
  return true;
}

}  // namespace

StorageMonitorCros::StorageMonitorCros() : weak_ptr_factory_(this) {}

StorageMonitorCros::~StorageMonitorCros() {
  DiskMountManager* manager = DiskMountManager::GetInstance();
  if (manager) {
    manager->RemoveObserver(this);
  }
}

void StorageMonitorCros::Init() {
  DCHECK(DiskMountManager::GetInstance());
  DiskMountManager::GetInstance()->AddObserver(this);
  CheckExistingMountPoints();

  // Tests may have already set a MTP manager.
  if (!mtp_device_manager_) {
    // Set up the connection with mojofied MtpManager.
    DCHECK(GetConnector());
    GetConnector()->BindInterface(device::mojom::kServiceName,
                                  mojo::MakeRequest(&mtp_device_manager_));
  }
  // |mtp_manager_client_| needs to be initialized for both tests and
  // production code, so keep it out of the if condition.
  mtp_manager_client_ = std::make_unique<MtpManagerClientChromeOS>(
      receiver(), mtp_device_manager_.get());
}

void StorageMonitorCros::CheckExistingMountPoints() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  for (const auto& it : DiskMountManager::GetInstance()->disks()) {
    if (it.second->IsStatefulPartition()) {
      AddFixedStorageDisk(*it.second);
      break;
    }
  }

  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner =
      base::CreateSequencedTaskRunnerWithTraits(
          {base::MayBlock(), base::TaskPriority::BEST_EFFORT});

  for (const auto& it : DiskMountManager::GetInstance()->mount_points()) {
    base::PostTaskAndReplyWithResult(
        blocking_task_runner.get(), FROM_HERE,
        base::Bind(&MediaStorageUtil::HasDcim,
                   base::FilePath(it.second.mount_path)),
        base::Bind(&StorageMonitorCros::AddMountedPath,
                   weak_ptr_factory_.GetWeakPtr(), it.second));
  }

  // Note: Relies on scheduled tasks on the |blocking_task_runner| being
  // sequential. This block needs to follow the for loop, so that the DoNothing
  // call on the |blocking_task_runner| happens after the scheduled metadata
  // retrievals, meaning that the reply callback will then happen after all the
  // AddMountedPath calls.

  blocking_task_runner->PostTaskAndReply(
      FROM_HERE, base::DoNothing(),
      base::BindOnce(&StorageMonitorCros::MarkInitialized,
                     weak_ptr_factory_.GetWeakPtr()));
}

void StorageMonitorCros::OnBootDeviceDiskEvent(
    DiskMountManager::DiskEvent event,
    const Disk& disk) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (!disk.IsStatefulPartition())
    return;

  switch (event) {
    case DiskMountManager::DiskEvent::DISK_ADDED: {
      AddFixedStorageDisk(disk);
      break;
    }
    case DiskMountManager::DiskEvent::DISK_REMOVED: {
      RemoveFixedStorageDisk(disk);
      break;
    }
    case DiskMountManager::DiskEvent::DISK_CHANGED: {
      // Although boot disks never change, this event is fired when the device
      // is woken from suspend and re-enumerates the set of disks. The event
      // could be changed to only fire when an actual change occurs, but that's
      // not currently possible because the "re-enumerate on wake" behaviour is
      // relied on to re-mount external media that was unmounted when the system
      // was suspended.
      break;
    }
  }
}

void StorageMonitorCros::OnMountEvent(
    DiskMountManager::MountEvent event,
    chromeos::MountError error_code,
    const DiskMountManager::MountPointInfo& mount_info) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // Ignore mount points that are not devices.
  if (mount_info.mount_type != chromeos::MOUNT_TYPE_DEVICE)
    return;
  // Ignore errors.
  if (error_code != chromeos::MOUNT_ERROR_NONE)
    return;
  if (mount_info.mount_condition != chromeos::disks::MOUNT_CONDITION_NONE)
    return;

  switch (event) {
    case DiskMountManager::MOUNTING: {
      if (base::ContainsKey(mount_map_, mount_info.mount_path)) {
        return;
      }

      base::PostTaskWithTraitsAndReplyWithResult(
          FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
          base::Bind(&MediaStorageUtil::HasDcim,
                     base::FilePath(mount_info.mount_path)),
          base::Bind(&StorageMonitorCros::AddMountedPath,
                     weak_ptr_factory_.GetWeakPtr(), mount_info));
      break;
    }
    case DiskMountManager::UNMOUNTING: {
      MountMap::iterator it = mount_map_.find(mount_info.mount_path);
      if (it == mount_map_.end())
        return;
      receiver()->ProcessDetach(it->second.device_id());
      mount_map_.erase(it);
      break;
    }
  }
}

void StorageMonitorCros::SetMediaTransferProtocolManagerForTest(
    device::mojom::MtpManagerPtr test_manager) {
  DCHECK(!mtp_device_manager_);
  mtp_device_manager_ = std::move(test_manager);
}

bool StorageMonitorCros::GetStorageInfoForPath(
    const base::FilePath& path,
    StorageInfo* device_info) const {
  DCHECK(device_info);

  if (mtp_manager_client_->GetStorageInfoForPath(path, device_info)) {
    return true;
  }

  if (!path.IsAbsolute())
    return false;

  base::FilePath current = path;
  while (!base::ContainsKey(mount_map_, current.value()) &&
         current != current.DirName()) {
    current = current.DirName();
  }

  MountMap::const_iterator info_it = mount_map_.find(current.value());
  if (info_it == mount_map_.end())
    return false;

  *device_info = info_it->second;
  return true;
}

// Callback executed when the unmount call is run by DiskMountManager.
// Forwards result to |EjectDevice| caller.
void NotifyUnmountResult(
    base::Callback<void(StorageMonitor::EjectStatus)> callback,
    chromeos::MountError error_code) {
  if (error_code == chromeos::MOUNT_ERROR_NONE)
    callback.Run(StorageMonitor::EJECT_OK);
  else
    callback.Run(StorageMonitor::EJECT_FAILURE);
}

void StorageMonitorCros::EjectDevice(
    const std::string& device_id,
    base::Callback<void(EjectStatus)> callback) {
  StorageInfo::Type type;
  if (!StorageInfo::CrackDeviceId(device_id, &type, NULL)) {
    callback.Run(EJECT_FAILURE);
    return;
  }

  if (type == StorageInfo::MTP_OR_PTP) {
    mtp_manager_client_->EjectDevice(device_id, callback);
    return;
  }

  std::string mount_path;
  for (MountMap::const_iterator info_it = mount_map_.begin();
       info_it != mount_map_.end(); ++info_it) {
    if (info_it->second.device_id() == device_id)
      mount_path = info_it->first;
  }

  if (mount_path.empty()) {
    callback.Run(EJECT_NO_SUCH_DEVICE);
    return;
  }

  DiskMountManager* manager = DiskMountManager::GetInstance();
  if (!manager) {
    callback.Run(EJECT_FAILURE);
    return;
  }

  manager->UnmountPath(mount_path, chromeos::UNMOUNT_OPTIONS_NONE,
                       base::BindOnce(NotifyUnmountResult, callback));
}

device::mojom::MtpManager*
StorageMonitorCros::media_transfer_protocol_manager() {
  return mtp_device_manager_.get();
}

void StorageMonitorCros::AddMountedPath(
    const DiskMountManager::MountPointInfo& mount_info,
    bool has_dcim) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (base::ContainsKey(mount_map_, mount_info.mount_path)) {
    // CheckExistingMountPoints() added the mount point information in the map
    // before the device attached handler is called. Therefore, an entry for
    // the device already exists in the map.
    return;
  }

  // Get the media device uuid and label if exists.
  StorageInfo info;
  if (!GetDeviceInfo(mount_info, has_dcim, &info))
    return;

  if (info.device_id().empty())
    return;

  mount_map_.insert(std::make_pair(mount_info.mount_path, info));

  receiver()->ProcessAttach(info);
}

void StorageMonitorCros::AddFixedStorageDisk(const Disk& disk) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(disk.IsStatefulPartition());

  StorageInfo info;
  if (!GetFixedStorageInfo(disk, &info))
    return;

  if (base::ContainsKey(mount_map_, disk.mount_path()))
    return;

  mount_map_.insert(std::make_pair(disk.mount_path(), info));
  receiver()->ProcessAttach(info);
}

void StorageMonitorCros::RemoveFixedStorageDisk(const Disk& disk) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(disk.IsStatefulPartition());

  StorageInfo info;
  if (!GetFixedStorageInfo(disk, &info))
    return;

  size_t erased_count = mount_map_.erase(disk.mount_path());
  if (!erased_count)
    return;

  receiver()->ProcessDetach((info.device_id()));
}

StorageMonitor* StorageMonitor::CreateInternal() {
  return new StorageMonitorCros();
}

}  // namespace storage_monitor
