/*
 * 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 "core/clipboard/DataTransfer.h"

#include <memory>

#include "build/build_config.h"
#include "core/clipboard/DataObject.h"
#include "core/clipboard/DataTransferItem.h"
#include "core/clipboard/DataTransferItemList.h"
#include "core/editing/EphemeralRange.h"
#include "core/editing/FrameSelection.h"
#include "core/editing/VisibleSelection.h"
#include "core/editing/serializers/Serialization.h"
#include "core/fileapi/FileList.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/forms/TextControlElement.h"
#include "core/layout/LayoutImage.h"
#include "core/layout/LayoutObject.h"
#include "core/loader/resource/ImageResourceContent.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "core/paint/PaintInfo.h"
#include "core/paint/PaintLayer.h"
#include "core/paint/PaintLayerPainter.h"
#include "platform/DragImage.h"
#include "platform/clipboard/ClipboardMimeTypes.h"
#include "platform/clipboard/ClipboardUtilities.h"
#include "platform/graphics/StaticBitmapImage.h"
#include "platform/graphics/paint/PaintRecordBuilder.h"
#include "platform/network/mime/MIMETypeRegistry.h"
#include "public/platform/WebScreenInfo.h"
#include "third_party/skia/include/core/SkSurface.h"

namespace blink {

namespace {

class DraggedNodeImageBuilder {
  STACK_ALLOCATED();

 public:
  DraggedNodeImageBuilder(const 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 |m_node| with pseudo class "-webkit-drag"
    local_frame_->View()->UpdateAllLifecyclePhasesExceptPaint();
    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->StackingNode()->IsStackingContext())
      layer = layer->StackingNode()->AncestorStackingContextNode()->Layer();
    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.
    FloatRect visible_rect =
        layer->GetLayoutObject().GetFrameView()->VisibleContentRect();
    // 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(IntRect(visible_rect));
    }

    FloatRect bounding_box =
        layer->GetLayoutObject()
            .AbsoluteToLocalQuad(FloatQuad(absolute_bounding_box),
                                 kUseTransforms)
            .BoundingBox();
    PaintLayerPaintingInfo painting_info(layer, LayoutRect(bounding_box),
                                         kGlobalPaintFlattenCompositingLayers,
                                         LayoutSize());
    PaintLayerFlags flags = kPaintLayerHaveTransparency |
                            kPaintLayerAppliedTransform |
                            kPaintLayerUncachedClipRects;
    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);

    PropertyTreeState border_box_properties = PropertyTreeState::Root();
    if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
      border_box_properties =
          *layer->GetLayoutObject().FirstFragment().LocalBorderBoxProperties();
    }
    FloatPoint paint_offset = dragged_layout_object->LocalToAncestorPoint(
        FloatPoint(), &layer->GetLayoutObject(), kUseTransforms);
    return DataTransfer::CreateDragImageForFrame(
        *local_frame_, 1.0f,
        LayoutObject::ShouldRespectImageOrientation(dragged_layout_object),
        bounding_box.Size(), paint_offset, builder, border_box_properties);
  }

 private:
  const Member<const LocalFrame> local_frame_;
  const Member<Node> node_;
#if DCHECK_IS_ON()
  const uint64_t dom_tree_version_;
#endif
};
}  // namespace
static DragOperation ConvertEffectAllowedToDragOperation(const String& op) {
  // Values specified in
  // http://www.whatwg.org/specs/web-apps/current-work/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 (DragOperation)(kDragOperationGeneric | kDragOperationMove);
  if (op == "copyLink")
    return (DragOperation)(kDragOperationCopy | kDragOperationLink);
  if (op == "copyMove")
    return (DragOperation)(kDragOperationCopy | kDragOperationGeneric |
                           kDragOperationMove);
  if (op == "linkMove")
    return (DragOperation)(kDragOperationLink | kDragOperationGeneric |
                           kDragOperationMove);
  if (op == "all")
    return kDragOperationEvery;
  return kDragOperationPrivate;  // really a marker for "no conversion"
}

static String ConvertDragOperationToEffectAllowed(DragOperation op) {
  bool move_set = !!((kDragOperationGeneric | kDragOperationMove) & op);

  if ((move_set && (op & kDragOperationCopy) && (op & kDragOperationLink)) ||
      (op == kDragOperationEvery))
    return "all";
  if (move_set && (op & kDragOperationCopy))
    return "copyMove";
  if (move_set && (op & kDragOperationLink))
    return "linkMove";
  if ((op & kDragOperationCopy) && (op & kDragOperationLink))
    return "copyLink";
  if (move_set)
    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 WHATWG Web Applications 1.0 draft see
// http://www.whatwg.org/specs/web-apps/current-work/ Section 6.3.5.3
static String NormalizeType(const String& type,
                            bool* convert_to_url = nullptr) {
  String clean_type = type.StripWhiteSpace().DeprecatedLower();
  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;
}

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

DataTransfer* DataTransfer::Create(DataTransferType type,
                                   DataTransferAccessPolicy policy,
                                   DataObject* data_object) {
  return new DataTransfer(type, policy, data_object);
}

DataTransfer::~DataTransfer() = default;

void DataTransfer::setDropEffect(const String& 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.
  //
  // Allowing these changes seems inconsequential, but findDropZone() in
  // EventHandler.cpp relies on being able to call setDropEffect during
  // dragenter, when the DataTransfer policy is DataTransferTypesReadable.
  drop_effect_ = effect;
}

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

  if (ConvertEffectAllowedToDragOperation(effect) == kDragOperationPrivate) {
    // 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 m_effectAllowed.

    // 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 {
  FileList* files = FileList::Create();
  if (!CanReadData())
    return files;

  for (size_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())
        files->Append(ToFile(blob));
    }
  }

  return files;
}

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

  if (!IsForDragAndDrop())
    return;

  IntPoint location(x, y);
  if (IsHTMLImageElement(*image) && !image->isConnected())
    SetDragImageResource(ToHTMLImageElement(*image).CachedImage(), location);
  else
    SetDragImageElement(image, location);
}

void DataTransfer::ClearDragImage() {
  if (!CanSetDragImage())
    return;

  drag_image_ = nullptr;
  drag_loc_ = IntPoint();
  drag_image_element_ = nullptr;
}

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& rect_in_document,
                                             const LocalFrame& frame) {
  IntRect viewport_in_root_frame =
      IntRect(frame.GetPage()->GetVisualViewport().VisibleRect());
  FloatRect viewport_in_document =
      frame.View()->RootFrameToDocument(viewport_in_root_frame);
  return Intersection(viewport_in_document, rect_in_document);
}

// 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(
    const LocalFrame& frame,
    float opacity,
    RespectImageOrientationEnum image_orientation,
    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 =
      StaticBitmapImage::Create(surface->makeImageSnapshot());
  float screen_device_scale_factor =
      frame.GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;

  return DragImage::Create(image.get(), image_orientation,
                           screen_device_scale_factor, kInterpolationDefault,
                           opacity);
}

// static
std::unique_ptr<DragImage> DataTransfer::NodeImage(const 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);
  LayoutObject* layout_object = element->GetLayoutObject();
  if (!layout_object || !layout_object->IsImage())
    return nullptr;

  LayoutImage* image = ToLayoutImage(layout_object);
  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(
          HTTPNames::Content_Disposition));
}

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_ != kDataTransferNumb || policy == kDataTransferNumb);
  policy_ = policy;
}

bool DataTransfer::CanReadTypes() const {
  return policy_ == kDataTransferReadable ||
         policy_ == kDataTransferTypesReadable ||
         policy_ == kDataTransferWritable;
}

bool DataTransfer::CanReadData() const {
  return policy_ == kDataTransferReadable || policy_ == kDataTransferWritable;
}

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

bool DataTransfer::CanSetDragImage() const {
  return policy_ == kDataTransferImageWritable ||
         policy_ == kDataTransferWritable;
}

DragOperation DataTransfer::SourceOperation() const {
  DragOperation op = ConvertEffectAllowedToDragOperation(effect_allowed_);
  DCHECK_NE(op, kDragOperationPrivate);
  return op;
}

DragOperation DataTransfer::DestinationOperation() const {
  DragOperation op = ConvertEffectAllowedToDragOperation(drop_effect_);
  DCHECK(op == kDragOperationCopy || op == kDragOperationNone ||
         op == kDragOperationLink ||
         op == (DragOperation)(kDragOperationGeneric | kDragOperationMove) ||
         op == kDragOperationEvery);
  return op;
}

void DataTransfer::SetSourceOperation(DragOperation op) {
  DCHECK_NE(op, kDragOperationPrivate);
  effect_allowed_ = ConvertDragOperationToEffectAllowed(op);
}

void DataTransfer::SetDestinationOperation(DragOperation op) {
  DCHECK(op == kDragOperationCopy || op == kDragOperationNone ||
         op == kDragOperationLink || op == kDragOperationGeneric ||
         op == kDragOperationMove ||
         op == static_cast<DragOperation>(kDragOperationGeneric |
                                          kDragOperationMove));
  drop_effect_ = ConvertDragOperationToEffectAllowed(op);
}

bool DataTransfer::HasDropZoneType(const String& keyword) {
  if (keyword.StartsWith("file:"))
    return HasFileOfType(keyword.Substring(5));

  if (keyword.StartsWith("string:"))
    return HasStringOfType(keyword.Substring(7));

  return false;
}

DataTransferItemList* DataTransfer::items() {
  // FIXME: 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 DataTransferItemList::Create(this, data_object_);
}

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

DataTransfer::DataTransfer(DataTransferType type,
                           DataTransferAccessPolicy policy,
                           DataObject* data_object)
    : policy_(policy),
      drop_effect_("uninitialized"),
      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 (size_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);
}

DragOperation ConvertDropZoneOperationToDragOperation(
    const String& drag_operation) {
  if (drag_operation == "copy")
    return kDragOperationCopy;
  if (drag_operation == "move")
    return kDragOperationMove;
  if (drag_operation == "link")
    return kDragOperationLink;
  return kDragOperationNone;
}

String ConvertDragOperationToDropZoneOperation(DragOperation operation) {
  switch (operation) {
    case kDragOperationCopy:
      return String("copy");
    case kDragOperationMove:
      return String("move");
    case kDragOperationLink:
      return String("link");
    default:
      return String("copy");
  }
}

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

}  // namespace blink
