// 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/seat.h"

#include <memory>

#include "ash/wm/window_util.h"
#include "base/auto_reset.h"
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/memory/weak_ptr.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "build/chromeos_buildflags.h"
#include "components/exo/data_exchange_delegate.h"
#include "components/exo/data_source.h"
#include "components/exo/drag_drop_operation.h"
#include "components/exo/mime_utils.h"
#include "components/exo/seat_observer.h"
#include "components/exo/shell_surface_base.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/surface.h"
#include "components/exo/wm_helper.h"
#include "components/exo/xkb_tracker.h"
#include "services/data_decoder/public/cpp/decode_image.h"
#include "ui/aura/client/focus_client.h"
#include "ui/base/clipboard/clipboard_monitor.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint_serializer.h"
#include "ui/display/screen.h"
#include "ui/events/event_utils.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/gfx/geometry/point_f.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/shell.h"
#include "ui/aura/env.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

namespace exo {

Seat::Seat(std::unique_ptr<DataExchangeDelegate> delegate)
    : changing_clipboard_data_to_selection_source_(false),
      data_exchange_delegate_(std::move(delegate)) {
  WMHelper::GetInstance()->AddFocusObserver(this);
  // Prepend handler as it's critical that we see all events.
  WMHelper::GetInstance()->PrependPreTargetHandler(this);
  ui::ClipboardMonitor::GetInstance()->AddObserver(this);
  // TODO(reveman): Need to handle the mus case where PlatformEventSource is
  // null. https://crbug.com/856230
  if (ui::PlatformEventSource::GetInstance())
    ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
#if BUILDFLAG(IS_CHROMEOS_ASH)
  ui_lock_controller_ = std::make_unique<UILockController>(this);

  // Seat needs to be registered as observers before any Keyboard,
  // because Keyboard expects that the XkbTracker is up-to-date when its
  // observer method is called.
  xkb_tracker_ = std::make_unique<XkbTracker>();
  ash::ImeControllerImpl* ime_controller = ash::Shell::Get()->ime_controller();
  xkb_tracker_->UpdateKeyboardLayout(ime_controller->keyboard_layout_name());
  ime_controller->AddObserver(this);
#endif
}

Seat::Seat() : Seat(nullptr) {}

Seat::~Seat() {
  Shutdown();
}

void Seat::Shutdown() {
  if (was_shutdown_)
    return;
  was_shutdown_ = true;
  DCHECK(!selection_source_) << "DataSource must be released before Seat";
#if BUILDFLAG(IS_CHROMEOS_ASH)
  ash::Shell::Get()->ime_controller()->RemoveObserver(this);
#endif
  WMHelper::GetInstance()->RemoveFocusObserver(this);
  WMHelper::GetInstance()->RemovePreTargetHandler(this);
  ui::ClipboardMonitor::GetInstance()->RemoveObserver(this);
  if (ui::PlatformEventSource::GetInstance())
    ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
}

void Seat::AddObserver(SeatObserver* observer, int priority) {
  for (const auto& observer_list : priority_observer_list_)
    if (observer_list.HasObserver(observer))
      return;

  DCHECK(IsValidObserverPriority(priority));
  priority_observer_list_[priority].AddObserver(observer);
}

void Seat::RemoveObserver(SeatObserver* observer) {
  // We assume that the number of priority variations is small enough.
  for (auto& observer_list : priority_observer_list_)
    observer_list.RemoveObserver(observer);
}

void Seat::NotifyPointerCaptureEnabled(Pointer* pointer,
                                       aura::Window* capture_window) {
  for (auto& observer_list : priority_observer_list_) {
    for (auto& observer : observer_list)
      observer.OnPointerCaptureEnabled(pointer, capture_window);
  }
}

void Seat::NotifyPointerCaptureDisabled(Pointer* pointer,
                                        aura::Window* capture_window) {
  for (auto& observer_list : priority_observer_list_) {
    for (auto& observer : observer_list)
      observer.OnPointerCaptureDisabled(pointer, capture_window);
  }
}

Surface* Seat::GetFocusedSurface() {
  return GetTargetSurfaceForKeyboardFocus(
      WMHelper::GetInstance()->GetFocusedWindow());
}

void Seat::StartDrag(DataSource* source,
                     Surface* origin,
                     Surface* icon,
                     ui::mojom::DragEventSource event_source) {
  gfx::Point cursor_location = aura::Env::GetInstance()->GetLastPointerPoint(
      event_source, origin->window(), /*fallback=*/absl::nullopt);
  // DragDropOperation manages its own lifetime.
  drag_drop_operation_ = DragDropOperation::Create(
      data_exchange_delegate_.get(), source, origin, icon,
      gfx::PointF(cursor_location), event_source);
}

void Seat::AbortPendingDragOperation() {
  if (drag_drop_operation_)
    drag_drop_operation_->AbortIfPending();
}

void Seat::SetSelection(DataSource* source) {
  Surface* focused_surface = GetFocusedSurface();
  if (!source || !focused_surface ||
      !source->CanBeDataSourceForCopy(focused_surface)) {
    if (source)
      source->Cancelled();
    return;
  }

  if (selection_source_) {
    if (selection_source_->get() == source)
      return;
    selection_source_->get()->Cancelled();
  }
  selection_source_ = std::make_unique<ScopedDataSource>(source, this);
  ui::EndpointType endpoint_type =
      data_exchange_delegate_->GetDataTransferEndpointType(
          focused_surface->window());
  scoped_refptr<RefCountedScopedClipboardWriter> writer =
      base::MakeRefCounted<RefCountedScopedClipboardWriter>(endpoint_type);

  size_t num_data_read_callbacks = DataSource::kMaxDataTypes;

#if BUILDFLAG(IS_CHROMEOS_ASH)
  // Lacros sends additional metadata, in a custom MIME type, to sync clipboard
  // source metadata,
  if (endpoint_type == ui::EndpointType::kLacros)
    ++num_data_read_callbacks;
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

  base::RepeatingClosure data_read_callback = base::BarrierClosure(
      num_data_read_callbacks,
      base::BindOnce(&Seat::OnAllReadsFinished, weak_ptr_factory_.GetWeakPtr(),
                     writer));

#if BUILDFLAG(IS_CHROMEOS_ASH)
  if (endpoint_type == ui::EndpointType::kLacros) {
    source->ReadDataTransferEndpoint(
        base::BindOnce(&Seat::OnDataTransferEndpointRead,
                       weak_ptr_factory_.GetWeakPtr(), writer,
                       data_read_callback),
        data_read_callback);
  }
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

  source->GetDataForPreferredMimeTypes(
      base::BindOnce(&Seat::OnTextRead, weak_ptr_factory_.GetWeakPtr(), writer,
                     data_read_callback),
      base::BindOnce(&Seat::OnRTFRead, weak_ptr_factory_.GetWeakPtr(), writer,
                     data_read_callback),
      base::BindOnce(&Seat::OnHTMLRead, weak_ptr_factory_.GetWeakPtr(), writer,
                     data_read_callback),
      base::BindOnce(&Seat::OnImageRead, weak_ptr_factory_.GetWeakPtr(), writer,
                     data_read_callback),
      base::BindOnce(&Seat::OnFilenamesRead, weak_ptr_factory_.GetWeakPtr(),
                     endpoint_type, writer, data_read_callback),
      DataSource::ReadFileContentsDataCallback(),
      base::BindOnce(&Seat::OnWebCustomDataRead, weak_ptr_factory_.GetWeakPtr(),
                     writer, data_read_callback),
      data_read_callback);
}

class Seat::RefCountedScopedClipboardWriter
    : public ui::ScopedClipboardWriter,
      public base::RefCounted<RefCountedScopedClipboardWriter> {
 public:
  explicit RefCountedScopedClipboardWriter(ui::EndpointType type)
      : ScopedClipboardWriter(
            ui::ClipboardBuffer::kCopyPaste,
            std::make_unique<ui::DataTransferEndpoint>(type)) {}

 private:
  friend class base::RefCounted<RefCountedScopedClipboardWriter>;
  virtual ~RefCountedScopedClipboardWriter() = default;
};

#if BUILDFLAG(IS_CHROMEOS_ASH)
void Seat::OnDataTransferEndpointRead(
    scoped_refptr<RefCountedScopedClipboardWriter> writer,
    base::OnceClosure callback,
    const std::string& mime_type,
    std::u16string data) {
  std::string utf8_json = base::UTF16ToUTF8(data);
  auto clipboard_source = ui::ConvertJsonToDataTransferEndpoint(utf8_json);

  writer->SetDataSource(std::move(clipboard_source));
  std::move(callback).Run();
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

void Seat::OnTextRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
                      base::OnceClosure callback,
                      const std::string& mime_type,
                      std::u16string data) {
  writer->WriteText(std::move(data));
  std::move(callback).Run();
}

void Seat::OnRTFRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
                     base::OnceClosure callback,
                     const std::string& mime_type,
                     const std::vector<uint8_t>& data) {
  writer->WriteRTF(
      std::string(reinterpret_cast<const char*>(data.data()), data.size()));
  std::move(callback).Run();
}

void Seat::OnHTMLRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
                      base::OnceClosure callback,
                      const std::string& mime_type,
                      std::u16string data) {
  writer->WriteHTML(std::move(data), std::string());
  std::move(callback).Run();
}

void Seat::OnImageRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
                       base::OnceClosure callback,
                       const std::string& mime_type,
                       const std::vector<uint8_t>& data) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
  data_decoder::DecodeImageIsolated(
      data, data_decoder::mojom::ImageCodec::kDefault, false,
      std::numeric_limits<int64_t>::max(), gfx::Size(),
      base::BindOnce(&Seat::OnImageDecoded, weak_ptr_factory_.GetWeakPtr(),
                     std::move(callback), writer));
#else
  std::move(callback).Run();
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
void Seat::OnImageDecoded(base::OnceClosure callback,
                          scoped_refptr<RefCountedScopedClipboardWriter> writer,
                          const SkBitmap& bitmap) {
  if (!bitmap.isNull() && !bitmap.empty())
    writer->WriteImage(bitmap);
  std::move(callback).Run();
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

void Seat::OnFilenamesRead(
    ui::EndpointType source,
    scoped_refptr<RefCountedScopedClipboardWriter> writer,
    base::OnceClosure callback,
    const std::string& mime_type,
    const std::vector<uint8_t>& data) {
  std::vector<ui::FileInfo> filenames =
      data_exchange_delegate_->GetFilenames(source, data);
  writer->WriteFilenames(ui::FileInfosToURIList(filenames));
  std::move(callback).Run();
}

void Seat::OnWebCustomDataRead(
    scoped_refptr<RefCountedScopedClipboardWriter> writer,
    base::OnceClosure callback,
    const std::string& mime_type,
    const std::vector<uint8_t>& data) {
  base::Pickle pickle(reinterpret_cast<const char*>(data.data()), data.size());
  writer->WritePickledData(pickle,
                           ui::ClipboardFormatType::WebCustomDataType());
  std::move(callback).Run();
}

void Seat::OnAllReadsFinished(
    scoped_refptr<RefCountedScopedClipboardWriter> writer) {
  // We need to destroy the ScopedClipboardWriter in this call, before
  // |auto_reset| is destroyed, so if there are outstanding references that
  // would prevent that, reschedule this task.
  if (!writer->HasOneRef()) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(&Seat::OnAllReadsFinished,
                       weak_ptr_factory_.GetWeakPtr(), std::move(writer)));
    return;
  }
  base::AutoReset<bool> auto_reset(
      &changing_clipboard_data_to_selection_source_, true);
  writer.reset();
}

////////////////////////////////////////////////////////////////////////////////
// aura::client::FocusChangeObserver overrides:

void Seat::OnWindowFocused(aura::Window* gained_focus,
                           aura::Window* lost_focus) {
  Surface* const gaining_focus_surface =
      GetTargetSurfaceForKeyboardFocus(gained_focus);
  Surface* const lost_focus_surface =
      GetTargetSurfaceForKeyboardFocus(lost_focus);

  for (auto& observer_list : priority_observer_list_) {
    for (auto& observer : observer_list)
      observer.OnSurfaceFocused(gaining_focus_surface, lost_focus_surface,
                                !!gained_focus);
  }
}

////////////////////////////////////////////////////////////////////////////////
// ui::PlatformEventObserver overrides:

void Seat::WillProcessEvent(const ui::PlatformEvent& event) {
  switch (ui::EventTypeFromNative(event)) {
    case ui::ET_KEY_PRESSED:
    case ui::ET_KEY_RELEASED:
      physical_code_for_currently_processing_event_ = ui::CodeFromNative(event);
      break;
    default:
      break;
  }
}

void Seat::DidProcessEvent(const ui::PlatformEvent& event) {
  switch (ui::EventTypeFromNative(event)) {
    case ui::ET_KEY_PRESSED:
      physical_code_for_currently_processing_event_ = ui::DomCode::NONE;
      break;
    case ui::ET_KEY_RELEASED:
      // Remove this from the pressed key map because when IME is active we can
      // end up getting the DidProcessEvent call before we get the OnKeyEvent
      // callback and then the key will end up being stuck pressed.
      if (physical_code_for_currently_processing_event_ != ui::DomCode::NONE) {
        pressed_keys_.erase(physical_code_for_currently_processing_event_);
        physical_code_for_currently_processing_event_ = ui::DomCode::NONE;
      }
      break;
    default:
      break;
  }
}

////////////////////////////////////////////////////////////////////////////////
// ui::EventHandler overrides:

void Seat::OnKeyEvent(ui::KeyEvent* event) {
  // Ignore synthetic key repeat events.
  if (event->is_repeat())
    return;
  if (physical_code_for_currently_processing_event_ != ui::DomCode::NONE) {
    switch (event->type()) {
      case ui::ET_KEY_PRESSED:
        pressed_keys_.emplace(
            physical_code_for_currently_processing_event_,
            KeyState{event->code(), /*consumed_by_ime=*/false});
        break;
      case ui::ET_KEY_RELEASED:
        pressed_keys_.erase(physical_code_for_currently_processing_event_);
        break;
      default:
        NOTREACHED();
        break;
    }
  }
#if BUILDFLAG(IS_CHROMEOS_ASH)
  xkb_tracker_->UpdateKeyboardModifiers(event->flags());
  for (auto& observer_list : priority_observer_list_) {
    for (auto& observer : observer_list)
      observer.OnKeyboardModifierUpdated();
  }
#endif
}

////////////////////////////////////////////////////////////////////////////////
// ui::ClipboardObserver overrides:

void Seat::OnClipboardDataChanged() {
  if (!selection_source_ || changing_clipboard_data_to_selection_source_)
    return;
  selection_source_->get()->Cancelled();
  selection_source_.reset();
}

#if BUILDFLAG(IS_CHROMEOS_ASH)

UILockController* Seat::GetUILockControllerForTesting() {
  return ui_lock_controller_.get();
}

////////////////////////////////////////////////////////////////////////////////
// ash::ImeControllerImpl::Observer overrides:

void Seat::OnCapsLockChanged(bool enabled) {}

void Seat::OnKeyboardLayoutNameChanged(const std::string& layout_name) {
  xkb_tracker_->UpdateKeyboardLayout(layout_name);
}
#endif

////////////////////////////////////////////////////////////////////////////////
// DataSourceObserver overrides:

void Seat::OnDataSourceDestroying(DataSource* source) {
  if (selection_source_ && selection_source_->get() == source)
    selection_source_.reset();
}

}  // namespace exo
