// Copyright 2017 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/exo/data_offer.h"

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/no_destructor.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "components/exo/data_offer_delegate.h"
#include "components/exo/data_offer_observer.h"
#include "components/exo/file_helper.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/clipboard_types.h"
#include "ui/base/dragdrop/file_info.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "url/gurl.h"

namespace exo {
namespace {

constexpr char kTextMimeTypeUtf8[] = "text/plain;charset=utf-8";
constexpr char kUtf8String[] = "UTF8_STRING";
constexpr char kUriListSeparator[] = "\r\n";

class RefCountedString16 : public base::RefCountedMemory {
 public:
  static scoped_refptr<RefCountedString16> TakeString(
      base::string16&& to_destroy) {
    scoped_refptr<RefCountedString16> self(new RefCountedString16);
    to_destroy.swap(self->data_);
    return self;
  }

  // Overridden from base::RefCountedMemory:
  const unsigned char* front() const override {
    return reinterpret_cast<const unsigned char*>(data_.data());
  }
  size_t size() const override { return data_.size() * sizeof(base::char16); }

 protected:
  ~RefCountedString16() override {}

 private:
  base::string16 data_;
};

void WriteFileDescriptor(base::ScopedFD fd,
                         scoped_refptr<base::RefCountedMemory> memory) {
  if (!base::WriteFileDescriptor(fd.get(),
                                 reinterpret_cast<const char*>(memory->front()),
                                 memory->size()))
    DLOG(ERROR) << "Failed to write drop data";
}

// Gets a comma-separated list of urls extracted from |data|->file.
bool GetUrlListFromDataFile(FileHelper* file_helper,
                            const ui::OSExchangeData& data,
                            base::string16* url_list_string) {
  if (!data.HasFile())
    return false;
  std::vector<ui::FileInfo> files;
  if (data.GetFilenames(&files)) {
    for (const auto& info : files) {
      GURL url;
      // TODO(niwa): Need to fill the correct app_id.
      if (file_helper->GetUrlFromPath(/* app_id */ "", info.path, &url)) {
        if (!url_list_string->empty())
          *url_list_string += base::UTF8ToUTF16(kUriListSeparator);
        *url_list_string += base::UTF8ToUTF16(url.spec());
      }
    }
  }
  return !url_list_string->empty();
}

ui::ClipboardFormatType GetClipboardFormatType() {
  static const char kFormatString[] = "chromium/x-file-system-files";
  static base::NoDestructor<ui::ClipboardFormatType> format_type(
      ui::ClipboardFormatType::GetType(kFormatString));
  return *format_type;
}

}  // namespace

DataOffer::DataOffer(DataOfferDelegate* delegate)
    : delegate_(delegate), weak_ptr_factory_(this) {}

DataOffer::~DataOffer() {
  delegate_->OnDataOfferDestroying(this);
  for (DataOfferObserver& observer : observers_) {
    observer.OnDataOfferDestroying(this);
  }
}

void DataOffer::AddObserver(DataOfferObserver* observer) {
  observers_.AddObserver(observer);
}

void DataOffer::RemoveObserver(DataOfferObserver* observer) {
  observers_.RemoveObserver(observer);
}

void DataOffer::Accept(const std::string* mime_type) {}

void DataOffer::Receive(const std::string& mime_type, base::ScopedFD fd) {
  const auto data_it = data_.find(mime_type);
  if (data_it == data_.end()) {
    DLOG(ERROR) << "Unexpected mime type is requested";
    return;
  }
  if (data_it->second) {
    base::PostTaskWithTraits(
        FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
        base::BindOnce(&WriteFileDescriptor, std::move(fd), data_it->second));
  } else {
    // Data bytes for this mime type are being processed currently.
    pending_receive_requests_.push_back(
        std::make_pair(mime_type, std::move(fd)));
  }
}

void DataOffer::Finish() {}

void DataOffer::SetActions(const base::flat_set<DndAction>& dnd_actions,
                           DndAction preferred_action) {
  dnd_action_ = preferred_action;
  delegate_->OnAction(preferred_action);
}

void DataOffer::SetSourceActions(
    const base::flat_set<DndAction>& source_actions) {
  source_actions_ = source_actions;
  delegate_->OnSourceActions(source_actions);
}

void DataOffer::SetDropData(FileHelper* file_helper,
                            const ui::OSExchangeData& data) {
  DCHECK_EQ(0u, data_.size());

  const std::string uri_list_mime_type = file_helper->GetMimeTypeForUriList();
  base::string16 url_list_string;
  if (GetUrlListFromDataFile(file_helper, data, &url_list_string)) {
    data_.emplace(uri_list_mime_type,
                  RefCountedString16::TakeString(std::move(url_list_string)));
    delegate_->OnOffer(uri_list_mime_type);
    return;
  }

  base::Pickle pickle;
  if (data.GetPickledData(GetClipboardFormatType(), &pickle) &&
      file_helper->HasUrlsInPickle(pickle)) {
    // Set nullptr as a temporary value for the mime type.
    // The value will be overriden in the callback below.
    data_.emplace(uri_list_mime_type, nullptr);
    // TODO(niwa): Need to fill the correct app_id.
    file_helper->GetUrlsFromPickle(
        /* app_id */ "", pickle,
        base::BindOnce(&DataOffer::OnPickledUrlsResolved,
                       weak_ptr_factory_.GetWeakPtr(), uri_list_mime_type));
    delegate_->OnOffer(uri_list_mime_type);
    return;
  }

  base::string16 string_content;
  if (data.HasString() && data.GetString(&string_content)) {
    const std::string text_mime_type = std::string(ui::kMimeTypeText);
    data_.emplace(text_mime_type,
                  RefCountedString16::TakeString(std::move(string_content)));
    delegate_->OnOffer(text_mime_type);
    return;
  }
}

void DataOffer::SetClipboardData(FileHelper* file_helper,
                                 const ui::Clipboard& data) {
  DCHECK_EQ(0u, data_.size());
  if (data.IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextWType(),
                             ui::CLIPBOARD_TYPE_COPY_PASTE)) {
    base::string16 content;
    data.ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &content);
    std::string utf8_content = base::UTF16ToUTF8(content);
    scoped_refptr<base::RefCountedString> utf8_ref =
        base::RefCountedString::TakeString(&utf8_content);
    data_.emplace(std::string(kTextMimeTypeUtf8), utf8_ref);
    data_.emplace(std::string(kUtf8String), utf8_ref);
    delegate_->OnOffer(std::string(kTextMimeTypeUtf8));
    delegate_->OnOffer(std::string(kUtf8String));
  }
}

void DataOffer::OnPickledUrlsResolved(const std::string& mime_type,
                                      const std::vector<GURL>& urls) {
  const auto data_it = data_.find(mime_type);
  DCHECK(data_it != data_.end());
  DCHECK(!data_it->second);  // nullptr should be set as a temporary value.
  data_.erase(data_it);

  base::string16 url_list_string;
  for (const GURL& url : urls) {
    if (!url.is_valid())
      continue;
    if (!url_list_string.empty())
      url_list_string += base::UTF8ToUTF16(kUriListSeparator);
    url_list_string += base::UTF8ToUTF16(url.spec());
  }
  const auto ref_counted_memory =
      RefCountedString16::TakeString(std::move(url_list_string));
  data_.emplace(mime_type, ref_counted_memory);

  // Process pending receive requests for this mime type, if there are any.
  auto it = pending_receive_requests_.begin();
  while (it != pending_receive_requests_.end()) {
    if (it->first == mime_type) {
      base::PostTaskWithTraits(
          FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
          base::BindOnce(&WriteFileDescriptor, std::move(it->second),
                         ref_counted_memory));
      it = pending_receive_requests_.erase(it);
    } else {
      ++it;
    }
  }
}

}  // namespace exo
