// Copyright (c) 2013 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 "ui/base/x/selection_owner.h"

#include <algorithm>
#include <X11/Xlib.h>
#include <X11/Xatom.h>

#include "base/logging.h"
#include "ui/base/x/selection_utils.h"
#include "ui/base/x/x11_foreign_window_manager.h"
#include "ui/base/x/x11_util.h"

namespace ui {

namespace {

const char kAtomPair[] = "ATOM_PAIR";
const char kIncr[] = "INCR";
const char kMultiple[] = "MULTIPLE";
const char kSaveTargets[] = "SAVE_TARGETS";
const char kTargets[] = "TARGETS";

const char* kAtomsToCache[] = {
  kAtomPair,
  kIncr,
  kMultiple,
  kSaveTargets,
  kTargets,
  NULL
};

// The period of |incremental_transfer_abort_timer_|. Arbitrary but must be <=
// than kIncrementalTransferTimeoutMs.
const int kTimerPeriodMs = 1000;

// The amount of time to wait for the selection requestor to process the data
// sent by the selection owner before aborting an incremental data transfer.
const int kIncrementalTransferTimeoutMs = 10000;

COMPILE_ASSERT(kTimerPeriodMs <= kIncrementalTransferTimeoutMs,
               timer_period_must_be_less_or_equal_to_transfer_timeout);

// Returns a conservative max size of the data we can pass into
// XChangeProperty(). Copied from GTK.
size_t GetMaxRequestSize(XDisplay* display) {
  long extended_max_size = XExtendedMaxRequestSize(display);
  long max_size =
      (extended_max_size ? extended_max_size : XMaxRequestSize(display)) - 100;
  return std::min(static_cast<long>(0x40000),
                  std::max(static_cast<long>(0), max_size));
}

// Gets the value of an atom pair array property. On success, true is returned
// and the value is stored in |value|.
bool GetAtomPairArrayProperty(XID window,
                              XAtom property,
                              std::vector<std::pair<XAtom,XAtom> >* value) {
  XAtom type = None;
  int format = 0;  // size in bits of each item in 'property'
  unsigned long num_items = 0;
  unsigned char* properties = NULL;
  unsigned long remaining_bytes = 0;

  int result = XGetWindowProperty(gfx::GetXDisplay(),
                                  window,
                                  property,
                                  0,          // offset into property data to
                                              // read
                                  (~0L),      // entire array
                                  False,      // deleted
                                  AnyPropertyType,
                                  &type,
                                  &format,
                                  &num_items,
                                  &remaining_bytes,
                                  &properties);

  if (result != Success)
    return false;

  // GTK does not require |type| to be kAtomPair.
  if (format != 32 || num_items % 2 != 0) {
    XFree(properties);
    return false;
  }

  XAtom* atom_properties = reinterpret_cast<XAtom*>(properties);
  value->clear();
  for (size_t i = 0; i < num_items; i+=2)
    value->push_back(std::make_pair(atom_properties[i], atom_properties[i+1]));
  XFree(properties);
  return true;
}

}  // namespace

SelectionOwner::SelectionOwner(XDisplay* x_display,
                               XID x_window,
                               XAtom selection_name)
    : x_display_(x_display),
      x_window_(x_window),
      selection_name_(selection_name),
      max_request_size_(GetMaxRequestSize(x_display)),
      atom_cache_(x_display_, kAtomsToCache) {
}

SelectionOwner::~SelectionOwner() {
  // If we are the selection owner, we need to release the selection so we
  // don't receive further events. However, we don't call ClearSelectionOwner()
  // because we don't want to do this indiscriminately.
  if (XGetSelectionOwner(x_display_, selection_name_) == x_window_)
    XSetSelectionOwner(x_display_, selection_name_, None, CurrentTime);
}

void SelectionOwner::RetrieveTargets(std::vector<XAtom>* targets) {
  for (SelectionFormatMap::const_iterator it = format_map_.begin();
       it != format_map_.end(); ++it) {
    targets->push_back(it->first);
  }
}

void SelectionOwner::TakeOwnershipOfSelection(
    const SelectionFormatMap& data) {
  XSetSelectionOwner(x_display_, selection_name_, x_window_, CurrentTime);

  if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) {
    // The X server agrees that we are the selection owner. Commit our data.
    format_map_ = data;
  }
}

void SelectionOwner::ClearSelectionOwner() {
  XSetSelectionOwner(x_display_, selection_name_, None, CurrentTime);
  format_map_ = SelectionFormatMap();
}

void SelectionOwner::OnSelectionRequest(const XEvent& event) {
  XID requestor = event.xselectionrequest.requestor;
  XAtom requested_target = event.xselectionrequest.target;
  XAtom requested_property = event.xselectionrequest.property;

  // Incrementally build our selection. By default this is a refusal, and we'll
  // override the parts indicating success in the different cases.
  XEvent reply;
  reply.xselection.type = SelectionNotify;
  reply.xselection.requestor = requestor;
  reply.xselection.selection = event.xselectionrequest.selection;
  reply.xselection.target = requested_target;
  reply.xselection.property = None;  // Indicates failure
  reply.xselection.time = event.xselectionrequest.time;

  if (requested_target == atom_cache_.GetAtom(kMultiple)) {
    // The contents of |requested_property| should be a list of
    // <target,property> pairs.
    std::vector<std::pair<XAtom,XAtom> > conversions;
    if (GetAtomPairArrayProperty(requestor,
                                 requested_property,
                                 &conversions)) {
      std::vector<XAtom> conversion_results;
      for (size_t i = 0; i < conversions.size(); ++i) {
        bool conversion_successful = ProcessTarget(conversions[i].first,
                                                   requestor,
                                                   conversions[i].second);
        conversion_results.push_back(conversions[i].first);
        conversion_results.push_back(
            conversion_successful ? conversions[i].second : None);
      }

      // Set the property to indicate which conversions succeeded. This matches
      // what GTK does.
      XChangeProperty(
          x_display_,
          requestor,
          requested_property,
          atom_cache_.GetAtom(kAtomPair),
          32,
          PropModeReplace,
          reinterpret_cast<const unsigned char*>(&conversion_results.front()),
          conversion_results.size());

      reply.xselection.property = requested_property;
    }
  } else {
    if (ProcessTarget(requested_target, requestor, requested_property))
      reply.xselection.property = requested_property;
  }

  // Send off the reply.
  XSendEvent(x_display_, requestor, False, 0, &reply);
}

void SelectionOwner::OnSelectionClear(const XEvent& event) {
  DLOG(ERROR) << "SelectionClear";

  // TODO(erg): If we receive a SelectionClear event while we're handling data,
  // we need to delay clearing.
}

bool SelectionOwner::CanDispatchPropertyEvent(const XEvent& event) {
  return event.xproperty.state == PropertyDelete &&
         FindIncrementalTransferForEvent(event) != incremental_transfers_.end();
}

void SelectionOwner::OnPropertyEvent(const XEvent& event) {
  std::vector<IncrementalTransfer>::iterator it =
      FindIncrementalTransferForEvent(event);
  if (it == incremental_transfers_.end())
    return;

  ProcessIncrementalTransfer(&(*it));
  if (!it->data.get())
    CompleteIncrementalTransfer(it);
}

bool SelectionOwner::ProcessTarget(XAtom target,
                                   XID requestor,
                                   XAtom property) {
  XAtom multiple_atom = atom_cache_.GetAtom(kMultiple);
  XAtom save_targets_atom = atom_cache_.GetAtom(kSaveTargets);
  XAtom targets_atom = atom_cache_.GetAtom(kTargets);

  if (target == multiple_atom || target == save_targets_atom)
    return false;

  if (target == targets_atom) {
    // We have been asked for TARGETS. Send an atom array back with the data
    // types we support.
    std::vector<XAtom> targets;
    targets.push_back(targets_atom);
    targets.push_back(save_targets_atom);
    targets.push_back(multiple_atom);
    RetrieveTargets(&targets);

    XChangeProperty(x_display_, requestor, property, XA_ATOM, 32,
                    PropModeReplace,
                    reinterpret_cast<unsigned char*>(&targets.front()),
                    targets.size());
    return true;
  } else {
    // Try to find the data type in map.
    SelectionFormatMap::const_iterator it = format_map_.find(target);
    if (it != format_map_.end()) {
      if (it->second->size() > max_request_size_) {
        // We must send the data back in several chunks due to a limitation in
        // the size of X requests. Notify the selection requestor that the data
        // will be sent incrementally by returning data of type "INCR".
        int length = it->second->size();
        XChangeProperty(x_display_,
                        requestor,
                        property,
                        atom_cache_.GetAtom(kIncr),
                        32,
                        PropModeReplace,
                        reinterpret_cast<unsigned char*>(&length),
                        1);

        // Wait for the selection requestor to indicate that it has processed
        // the selection result before sending the first chunk of data. The
        // selection requestor indicates this by deleting |property|.
        base::TimeTicks timeout =
            base::TimeTicks::Now() +
            base::TimeDelta::FromMilliseconds(kIncrementalTransferTimeoutMs);
        int foreign_window_manager_id =
            ui::XForeignWindowManager::GetInstance()->RequestEvents(
                requestor, PropertyChangeMask);
        incremental_transfers_.push_back(
            IncrementalTransfer(requestor,
                                target,
                                property,
                                it->second,
                                0,
                                timeout,
                                foreign_window_manager_id));

        // Start a timer to abort the data transfer in case that the selection
        // requestor does not support the INCR property or gets destroyed during
        // the data transfer.
        if (!incremental_transfer_abort_timer_.IsRunning()) {
          incremental_transfer_abort_timer_.Start(
              FROM_HERE,
              base::TimeDelta::FromMilliseconds(kTimerPeriodMs),
              this,
              &SelectionOwner::AbortStaleIncrementalTransfers);
        }
      } else {
        XChangeProperty(
            x_display_,
            requestor,
            property,
            target,
            8,
            PropModeReplace,
            const_cast<unsigned char*>(it->second->front()),
            it->second->size());
      }
      return true;
    }
    // I would put error logging here, but GTK ignores TARGETS and spams us
    // looking for its own internal types.
  }
  return false;
}

void SelectionOwner::ProcessIncrementalTransfer(IncrementalTransfer* transfer) {
  size_t remaining = transfer->data->size() - transfer->offset;
  size_t chunk_length = std::min(remaining, max_request_size_);
  XChangeProperty(
      x_display_,
      transfer->window,
      transfer->property,
      transfer->target,
      8,
      PropModeReplace,
      const_cast<unsigned char*>(transfer->data->front() + transfer->offset),
      chunk_length);
  transfer->offset += chunk_length;
  transfer->timeout = base::TimeTicks::Now() +
      base::TimeDelta::FromMilliseconds(kIncrementalTransferTimeoutMs);

  // When offset == data->size(), we still need to transfer a zero-sized chunk
  // to notify the selection requestor that the transfer is complete. Clear
  // transfer->data once the zero-sized chunk is sent to indicate that state
  // related to this data transfer can be cleared.
  if (chunk_length == 0)
    transfer->data = NULL;
}

void SelectionOwner::AbortStaleIncrementalTransfers() {
  base::TimeTicks now = base::TimeTicks::Now();
  for (int i = static_cast<int>(incremental_transfers_.size()) - 1;
       i >= 0; --i) {
    if (incremental_transfers_[i].timeout <= now)
      CompleteIncrementalTransfer(incremental_transfers_.begin() + i);
  }
}

void SelectionOwner::CompleteIncrementalTransfer(
    std::vector<IncrementalTransfer>::iterator it) {
  ui::XForeignWindowManager::GetInstance()->CancelRequest(
      it->foreign_window_manager_id);
  incremental_transfers_.erase(it);

  if (incremental_transfers_.empty())
    incremental_transfer_abort_timer_.Stop();
}

std::vector<SelectionOwner::IncrementalTransfer>::iterator
    SelectionOwner::FindIncrementalTransferForEvent(const XEvent& event) {
  for (std::vector<IncrementalTransfer>::iterator it =
           incremental_transfers_.begin();
       it != incremental_transfers_.end();
       ++it) {
    if (it->window == event.xproperty.window &&
        it->property == event.xproperty.atom) {
      return it;
    }
  }
  return incremental_transfers_.end();
}

SelectionOwner::IncrementalTransfer::IncrementalTransfer(
    XID window,
    XAtom target,
    XAtom property,
    const scoped_refptr<base::RefCountedMemory>& data,
    int offset,
    base::TimeTicks timeout,
    int foreign_window_manager_id)
    : window(window),
      target(target),
      property(property),
      data(data),
      offset(offset),
      timeout(timeout),
      foreign_window_manager_id(foreign_window_manager_id) {
}

SelectionOwner::IncrementalTransfer::~IncrementalTransfer() {
}

}  // namespace ui
