/*
 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/clipboard/data_transfer.h"

#include <memory>

#include "base/optional.h"
#include "build/build_config.h"
#include "third_party/blink/public/common/widget/screen_info.h"
#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer_access_policy.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer_item.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer_item_list.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/editing/visible_selection.h"
#include "third_party/blink/renderer/core/fileapi/file_list.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/drag_image.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-blink.h"

namespace blink {

namespace {

class DraggedNodeImageBuilder {
  STACK_ALLOCATED();

 public:
  DraggedNodeImageBuilder(LocalFrame& local_frame, Node& node)
      : local_frame_(&local_frame),
        node_(&node)
#if DCHECK_IS_ON()
        ,
        dom_tree_version_(node.GetDocument().DomTreeVersion())
#endif
  {
    for (Node& descendant : NodeTraversal::InclusiveDescendantsOf(*node_))
      descendant.SetDragged(true);
  }

  ~DraggedNodeImageBuilder() {
#if DCHECK_IS_ON()
    DCHECK_EQ(dom_tree_version_, node_->GetDocument().DomTreeVersion());
#endif
    for (Node& descendant : NodeTraversal::InclusiveDescendantsOf(*node_))
      descendant.SetDragged(false);
  }

  std::unique_ptr<DragImage> CreateImage() {
#if DCHECK_IS_ON()
    DCHECK_EQ(dom_tree_version_, node_->GetDocument().DomTreeVersion());
#endif
    // Construct layout object for |node_| with pseudo class "-webkit-drag"
    local_frame_->View()->UpdateAllLifecyclePhasesExceptPaint(
        DocumentUpdateReason::kDragImage);
    LayoutObject* const dragged_layout_object = node_->GetLayoutObject();
    if (!dragged_layout_object)
      return nullptr;
    // Paint starting at the nearest stacking context, clipped to the object
    // itself. This will also paint the contents behind the object if the
    // object contains transparency and there are other elements in the same
    // stacking context which stacked below.
    PaintLayer* layer = dragged_layout_object->EnclosingLayer();
    if (!layer->GetLayoutObject().IsStackingContext())
      layer = layer->AncestorStackingContext();

    IntRect absolute_bounding_box =
        dragged_layout_object->AbsoluteBoundingBoxRectIncludingDescendants();
    // TODO(chrishtr): consider using the root frame's visible rect instead
    // of the local frame, to avoid over-clipping.
    IntRect visible_rect(IntPoint(),
                         layer->GetLayoutObject().GetFrameView()->Size());
    // If the absolute bounding box is large enough to be possibly a memory
    // or IPC payload issue, clip it to the visible content rect.
    if (absolute_bounding_box.Size().Area() > visible_rect.Size().Area()) {
      absolute_bounding_box.Intersect(visible_rect);
    }

    FloatRect bounding_box =
        layer->GetLayoutObject()
            .AbsoluteToLocalQuad(FloatQuad(absolute_bounding_box))
            .BoundingBox();
    PaintLayerPaintingInfo painting_info(
        layer, CullRect(EnclosingIntRect(bounding_box)),
        kGlobalPaintFlattenCompositingLayers, PhysicalOffset());
    PaintLayerFlags flags = kPaintLayerHaveTransparency;
    PaintRecordBuilder builder;

    dragged_layout_object->GetDocument().Lifecycle().AdvanceTo(
        DocumentLifecycle::kInPaint);
    PaintLayerPainter(*layer).Paint(builder.Context(), painting_info, flags);
    dragged_layout_object->GetDocument().Lifecycle().AdvanceTo(
        DocumentLifecycle::kPaintClean);

    FloatPoint paint_offset = bounding_box.Location();
    PropertyTreeState border_box_properties = layer->GetLayoutObject()
                                                  .FirstFragment()
                                                  .LocalBorderBoxProperties()
                                                  .Unalias();
    // We paint in the containing transform node's space. Add the offset from
    // the layer to this transform space.
    paint_offset +=
        FloatPoint(layer->GetLayoutObject().FirstFragment().PaintOffset());

    return DataTransfer::CreateDragImageForFrame(
        *local_frame_, 1.0f,
        bounding_box.Size(), paint_offset, builder, border_box_properties);
  }

 private:
  LocalFrame* const local_frame_;
  Node* const node_;
#if DCHECK_IS_ON()
  const uint64_t dom_tree_version_;
#endif
};

base::Optional<DragOperationsMask> ConvertEffectAllowedToDragOperationsMask(
    const AtomicString& op) {
  // Values specified in
  // https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransfer-effectallowed
  if (op == "uninitialized")
    return kDragOperationEvery;
  if (op == "none")
    return kDragOperationNone;
  if (op == "copy")
    return kDragOperationCopy;
  if (op == "link")
    return kDragOperationLink;
  if (op == "move")
    return kDragOperationMove;
  if (op == "copyLink") {
    return static_cast<DragOperationsMask>(kDragOperationCopy |
                                           kDragOperationLink);
  }
  if (op == "copyMove") {
    return static_cast<DragOperationsMask>(kDragOperationCopy |
                                           kDragOperationMove);
  }
  if (op == "linkMove") {
    return static_cast<DragOperationsMask>(kDragOperationLink |
                                           kDragOperationMove);
  }
  if (op == "all")
    return kDragOperationEvery;
  return base::nullopt;
}

AtomicString ConvertDragOperationsMaskToEffectAllowed(DragOperationsMask op) {
  if (((op & kDragOperationMove) && (op & kDragOperationCopy) &&
       (op & kDragOperationLink)) ||
      (op == kDragOperationEvery))
    return "all";
  if ((op & kDragOperationMove) && (op & kDragOperationCopy))
    return "copyMove";
  if ((op & kDragOperationMove) && (op & kDragOperationLink))
    return "linkMove";
  if ((op & kDragOperationCopy) && (op & kDragOperationLink))
    return "copyLink";
  if (op & kDragOperationMove)
    return "move";
  if (op & kDragOperationCopy)
    return "copy";
  if (op & kDragOperationLink)
    return "link";
  return "none";
}

// We provide the IE clipboard types (URL and Text), and the clipboard types
// specified in the HTML spec. See
// https://html.spec.whatwg.org/multipage/dnd.html#the-datatransfer-interface
String NormalizeType(const String& type, bool* convert_to_url = nullptr) {
  String clean_type = type.StripWhiteSpace().LowerASCII();
  if (clean_type == kMimeTypeText ||
      clean_type.StartsWith(kMimeTypeTextPlainEtc))
    return kMimeTypeTextPlain;
  if (clean_type == kMimeTypeURL) {
    if (convert_to_url)
      *convert_to_url = true;
    return kMimeTypeTextURIList;
  }
  return clean_type;
}

}  // namespace

// static
DataTransfer* DataTransfer::Create() {
  DataTransfer* data = Create(
      kCopyAndPaste, DataTransferAccessPolicy::kWritable, DataObject::Create());
  data->drop_effect_ = "none";
  data->effect_allowed_ = "none";
  return data;
}

// static
DataTransfer* DataTransfer::Create(DataTransferType type,
                                   DataTransferAccessPolicy policy,
                                   DataObject* data_object) {
  return MakeGarbageCollected<DataTransfer>(type, policy, data_object);
}

DataTransfer::~DataTransfer() = default;

void DataTransfer::setDropEffect(const AtomicString& effect) {
  if (!IsForDragAndDrop())
    return;

  // The attribute must ignore any attempts to set it to a value other than
  // none, copy, link, and move.
  if (effect != "none" && effect != "copy" && effect != "link" &&
      effect != "move")
    return;

  // The specification states that dropEffect can be changed at all times, even
  // if the DataTransfer instance is protected or neutered.
  drop_effect_ = effect;
}

void DataTransfer::setEffectAllowed(const AtomicString& effect) {
  if (!IsForDragAndDrop())
    return;

  if (!ConvertEffectAllowedToDragOperationsMask(effect)) {
    // This means that there was no conversion, and the effectAllowed that
    // we are passed isn't a valid effectAllowed, so we should ignore it,
    // and not set |effect_allowed_|.

    // The attribute must ignore any attempts to set it to a value other than
    // none, copy, copyLink, copyMove, link, linkMove, move, all, and
    // uninitialized.
    return;
  }

  if (CanWriteData())
    effect_allowed_ = effect;
}

void DataTransfer::clearData(const String& type) {
  if (!CanWriteData())
    return;

  if (type.IsNull())
    data_object_->ClearAll();
  else
    data_object_->ClearData(NormalizeType(type));
}

String DataTransfer::getData(const String& type) const {
  if (!CanReadData())
    return String();

  bool convert_to_url = false;
  String data = data_object_->GetData(NormalizeType(type, &convert_to_url));
  if (!convert_to_url)
    return data;
  return ConvertURIListToURL(data);
}

void DataTransfer::setData(const String& type, const String& data) {
  if (!CanWriteData())
    return;

  data_object_->SetData(NormalizeType(type), data);
}

bool DataTransfer::hasDataStoreItemListChanged() const {
  return data_store_item_list_changed_ || !CanReadTypes();
}

void DataTransfer::OnItemListChanged() {
  data_store_item_list_changed_ = true;
}

Vector<String> DataTransfer::types() {
  if (!CanReadTypes())
    return Vector<String>();

  data_store_item_list_changed_ = false;
  return data_object_->Types();
}

FileList* DataTransfer::files() const {
  auto* files = MakeGarbageCollected<FileList>();
  if (!CanReadData())
    return files;

  for (uint32_t i = 0; i < data_object_->length(); ++i) {
    if (data_object_->Item(i)->Kind() == DataObjectItem::kFileKind) {
      Blob* blob = data_object_->Item(i)->GetAsFile();
      if (auto* file = DynamicTo<File>(blob))
        files->Append(file);
    }
  }

  return files;
}

void DataTransfer::setDragImage(Element* image, int x, int y) {
  DCHECK(image);

  if (!IsForDragAndDrop())
    return;

  IntPoint location(x, y);
  auto* html_image_element = DynamicTo<HTMLImageElement>(image);
  if (html_image_element && !image->isConnected())
    SetDragImageResource(html_image_element->CachedImage(), location);
  else
    SetDragImageElement(image, location);
}

void DataTransfer::ClearDragImage() {
  setDragImage(nullptr, nullptr, IntPoint());
}

void DataTransfer::SetDragImageResource(ImageResourceContent* img,
                                        const IntPoint& loc) {
  setDragImage(img, nullptr, loc);
}

void DataTransfer::SetDragImageElement(Node* node, const IntPoint& loc) {
  setDragImage(nullptr, node, loc);
}

FloatRect DataTransfer::ClipByVisualViewport(const FloatRect& absolute_rect,
                                             const LocalFrame& frame) {
  IntRect viewport_in_root_frame =
      EnclosingIntRect(frame.GetPage()->GetVisualViewport().VisibleRect());
  FloatRect absolute_viewport =
      FloatRect(frame.View()->ConvertFromRootFrame(viewport_in_root_frame));
  return Intersection(absolute_viewport, absolute_rect);
}

// static
// Converts from size in CSS space to device space based on the given frame.
FloatSize DataTransfer::DeviceSpaceSize(const FloatSize& css_size,
                                        const LocalFrame& frame) {
  float device_scale_factor = frame.GetPage()->DeviceScaleFactorDeprecated();
  float page_scale_factor = frame.GetPage()->GetVisualViewport().Scale();
  FloatSize device_size(css_size);
  device_size.Scale(device_scale_factor * page_scale_factor);
  return device_size;
}

// static
// Returns a DragImage whose bitmap contains |contents|, positioned and scaled
// in device space.
std::unique_ptr<DragImage> DataTransfer::CreateDragImageForFrame(
    LocalFrame& frame,
    float opacity,
    const FloatSize& css_size,
    const FloatPoint& paint_offset,
    PaintRecordBuilder& builder,
    const PropertyTreeState& property_tree_state) {
  float device_scale_factor = frame.GetPage()->DeviceScaleFactorDeprecated();
  float page_scale_factor = frame.GetPage()->GetVisualViewport().Scale();

  FloatSize device_size = DeviceSpaceSize(css_size, frame);
  AffineTransform transform;
  FloatSize paint_offset_size =
      DeviceSpaceSize(FloatSize(paint_offset.X(), paint_offset.Y()), frame);
  transform.Translate(-paint_offset_size.Width(), -paint_offset_size.Height());
  transform.Scale(device_scale_factor * page_scale_factor);

  // Rasterize upfront, since DragImage::create() is going to do it anyway
  // (SkImage::asLegacyBitmap).
  SkSurfaceProps surface_props(0, kUnknown_SkPixelGeometry);
  sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(
      device_size.Width(), device_size.Height(), &surface_props);
  if (!surface)
    return nullptr;

  SkiaPaintCanvas skia_paint_canvas(surface->getCanvas());
  skia_paint_canvas.concat(AffineTransformToSkMatrix(transform));
  builder.EndRecording(skia_paint_canvas, property_tree_state);

  scoped_refptr<Image> image =
      UnacceleratedStaticBitmapImage::Create(surface->makeImageSnapshot());
  ChromeClient& chrome_client = frame.GetPage()->GetChromeClient();
  float screen_device_scale_factor =
      chrome_client.GetScreenInfo(frame).device_scale_factor;

  // There is no orientation information in the image, so pass
  // kDoNotRespectImageOrientation in order to avoid wasted work looking
  // at orientation.
  return DragImage::Create(image.get(), kDoNotRespectImageOrientation,
                           screen_device_scale_factor, kInterpolationDefault,
                           opacity);
}

// static
std::unique_ptr<DragImage> DataTransfer::NodeImage(LocalFrame& frame,
                                                   Node& node) {
  DraggedNodeImageBuilder image_node(frame, node);
  return image_node.CreateImage();
}

std::unique_ptr<DragImage> DataTransfer::CreateDragImage(
    IntPoint& loc,
    LocalFrame* frame) const {
  if (drag_image_element_) {
    loc = drag_loc_;

    return NodeImage(*frame, *drag_image_element_);
  }
  if (drag_image_) {
    loc = drag_loc_;
    return DragImage::Create(drag_image_->GetImage());
  }
  return nullptr;
}

static ImageResourceContent* GetImageResourceContent(Element* element) {
  // Attempt to pull ImageResourceContent from element
  DCHECK(element);
  if (auto* image = DynamicTo<LayoutImage>(element->GetLayoutObject())) {
    if (image->CachedImage() && !image->CachedImage()->ErrorOccurred())
      return image->CachedImage();
  }
  return nullptr;
}

static void WriteImageToDataObject(DataObject* data_object,
                                   Element* element,
                                   const KURL& image_url) {
  // Shove image data into a DataObject for use as a file
  ImageResourceContent* cached_image = GetImageResourceContent(element);
  if (!cached_image || !cached_image->GetImage() || !cached_image->IsLoaded())
    return;

  Image* image = cached_image->GetImage();
  scoped_refptr<SharedBuffer> image_buffer = image->Data();
  if (!image_buffer || !image_buffer->size())
    return;

  data_object->AddSharedBuffer(
      image_buffer, image_url, image->FilenameExtension(),
      cached_image->GetResponse().HttpHeaderFields().Get(
          http_names::kContentDisposition));
}

void DataTransfer::DeclareAndWriteDragImage(Element* element,
                                            const KURL& link_url,
                                            const KURL& image_url,
                                            const String& title) {
  if (!data_object_)
    return;

  data_object_->SetURLAndTitle(link_url.IsValid() ? link_url : image_url,
                               title);

  // Write the bytes in the image to the file format.
  WriteImageToDataObject(data_object_.Get(), element, image_url);

  // Put img tag on the clipboard referencing the image
  data_object_->SetData(kMimeTypeTextHTML,
                        CreateMarkup(element, kIncludeNode, kResolveAllURLs));
}

void DataTransfer::WriteURL(Node* node, const KURL& url, const String& title) {
  if (!data_object_)
    return;
  DCHECK(!url.IsEmpty());

  data_object_->SetURLAndTitle(url, title);

  // The URL can also be used as plain text.
  data_object_->SetData(kMimeTypeTextPlain, url.GetString());

  // The URL can also be used as an HTML fragment.
  data_object_->SetHTMLAndBaseURL(
      CreateMarkup(node, kIncludeNode, kResolveAllURLs), url);
}

void DataTransfer::WriteSelection(const FrameSelection& selection) {
  if (!data_object_)
    return;

  if (!EnclosingTextControl(
          selection.ComputeVisibleSelectionInDOMTreeDeprecated().Start())) {
    data_object_->SetHTMLAndBaseURL(selection.SelectedHTMLForClipboard(),
                                    selection.GetFrame()->GetDocument()->Url());
  }

  String str = selection.SelectedTextForClipboard();
#if defined(OS_WIN)
  ReplaceNewlinesWithWindowsStyleNewlines(str);
#endif
  ReplaceNBSPWithSpace(str);
  data_object_->SetData(kMimeTypeTextPlain, str);
}

void DataTransfer::SetAccessPolicy(DataTransferAccessPolicy policy) {
  // once you go numb, can never go back
  DCHECK(policy_ != DataTransferAccessPolicy::kNumb ||
         policy == DataTransferAccessPolicy::kNumb);
  policy_ = policy;
}

bool DataTransfer::CanReadTypes() const {
  return policy_ == DataTransferAccessPolicy::kReadable ||
         policy_ == DataTransferAccessPolicy::kTypesReadable ||
         policy_ == DataTransferAccessPolicy::kWritable;
}

bool DataTransfer::CanReadData() const {
  return policy_ == DataTransferAccessPolicy::kReadable ||
         policy_ == DataTransferAccessPolicy::kWritable;
}

bool DataTransfer::CanWriteData() const {
  return policy_ == DataTransferAccessPolicy::kWritable;
}

bool DataTransfer::CanSetDragImage() const {
  return policy_ == DataTransferAccessPolicy::kImageWritable ||
         policy_ == DataTransferAccessPolicy::kWritable;
}

DragOperationsMask DataTransfer::SourceOperation() const {
  base::Optional<DragOperationsMask> op =
      ConvertEffectAllowedToDragOperationsMask(effect_allowed_);
  DCHECK(op);
  return *op;
}

ui::mojom::blink::DragOperation DataTransfer::DestinationOperation() const {
  DCHECK(DropEffectIsInitialized());
  base::Optional<DragOperationsMask> op =
      ConvertEffectAllowedToDragOperationsMask(drop_effect_);
  return static_cast<ui::mojom::blink::DragOperation>(*op);
}

void DataTransfer::SetSourceOperation(DragOperationsMask op) {
  effect_allowed_ = ConvertDragOperationsMaskToEffectAllowed(op);
}

void DataTransfer::SetDestinationOperation(ui::mojom::blink::DragOperation op) {
  drop_effect_ = ConvertDragOperationsMaskToEffectAllowed(
      static_cast<DragOperationsMask>(op));
}

DataTransferItemList* DataTransfer::items() {
  // TODO: According to the spec, we are supposed to return the same collection
  // of items each time. We now return a wrapper that always wraps the *same*
  // set of items, so JS shouldn't be able to tell, but we probably still want
  // to fix this.
  return MakeGarbageCollected<DataTransferItemList>(this, data_object_);
}

DataObject* DataTransfer::GetDataObject() const {
  return data_object_;
}

DataTransfer::DataTransfer(DataTransferType type,
                           DataTransferAccessPolicy policy,
                           DataObject* data_object)
    : policy_(policy),
      effect_allowed_("uninitialized"),
      transfer_type_(type),
      data_object_(data_object),
      data_store_item_list_changed_(true) {
  data_object_->AddObserver(this);
}

void DataTransfer::setDragImage(ImageResourceContent* image,
                                Node* node,
                                const IntPoint& loc) {
  if (!CanSetDragImage())
    return;

  drag_image_ = image;
  drag_loc_ = loc;
  drag_image_element_ = node;
}

bool DataTransfer::HasFileOfType(const String& type) const {
  if (!CanReadTypes())
    return false;

  for (uint32_t i = 0; i < data_object_->length(); ++i) {
    if (data_object_->Item(i)->Kind() == DataObjectItem::kFileKind) {
      Blob* blob = data_object_->Item(i)->GetAsFile();
      if (blob && blob->IsFile() &&
          DeprecatedEqualIgnoringCase(blob->type(), type))
        return true;
    }
  }
  return false;
}

bool DataTransfer::HasStringOfType(const String& type) const {
  if (!CanReadTypes())
    return false;

  return data_object_->Types().Contains(type);
}

void DataTransfer::Trace(Visitor* visitor) const {
  visitor->Trace(data_object_);
  visitor->Trace(drag_image_);
  visitor->Trace(drag_image_element_);
  ScriptWrappable::Trace(visitor);
}

}  // namespace blink
